/* ============================================================
   notes.allisterk.com — notes.css · v1.1 (self-contained)
   ------------------------------------------------------------
   The complete stylesheet for the Notes engine. No shared/common
   assets: the foundation that used to come from the hub's
   tokens.css is inlined below with Notes' own values resolved —
   yellow-green pigment on warm paper.

   Reading-focused: the ladder (post index), the post page, figures,
   halfsies, callouts, footnotes.
   ============================================================ */

:root {
  /* type */
  --type-serif: "Crimson Pro", "Iowan Old Style", Georgia, serif;
  --type-mono:  "JetBrains Mono", ui-monospace, "SF Mono", Menlo, monospace;

  /* ink */
  --ink:       #14110E;
  --ink-soft:  #6B6357;
  --ink-faint: rgba(20, 17, 14, 0.13);
  --ink-rule:  rgba(20, 17, 14, 0.18);

  /* paper (warm) */
  --paper: #F7F3EA;

  /* yellow-green pigment family. Four steps, each with one job, so
     the green is actually visible instead of hiding at either end:

       --pigment      #8AC926  1.81 on paper — DECORATIVE ONLY. Fails
                              both the 4.5 text floor and the 3.0
                              non-text floor. Fills and washes only:
                              never a text color, never a lone
                              affordance carrying meaning.
       --pigment-mid  #4A7318  5.05 on paper (AA) — the LINK green.
                              This is the step the palette was missing:
                              deep reads as near-black, so links looked
                              like plain ink. Mid reads unmistakably
                              green and still passes.
       --pigment-deep #324A12  8.93 on paper (AAA) — structural marks
                              and hover/active states.
       --pigment-soft #C5E58F  1.27 on paper — rest-state underlines,
                              callout grounds, selection.

     hl-1 / hl-2 are the split-complementary pair for yellow-green
     (85° → 235° / 295°). hl-1 is 5.98 (AA) and carries tags and
     footnote anchors; hl-2 is 3.90 — large text or non-text only. */
  --pigment:      #8AC926;
  --pigment-mid:  #4A7318;
  --pigment-deep: #324A12;
  --pigment-soft: #C5E58F;
  --pigment-link: var(--pigment-mid);
  --hl-1:         #3A50C9;
  --hl-2:         #C93AC1;

  /* One focus ring for the whole site (WCAG 2.4.7). */
  --focus: #14110E;
}

/* ── Base ───────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }

/* The reel breaks out of the reading column to 100vw. On a platform
   with classic (space-taking) scrollbars, 100vw counts the scrollbar
   and would push a horizontal one onto the page. `clip` on the root
   swallows that overhang. Deliberately not `hidden`, which would make
   the root a scroll container and break position: sticky. */
html { overflow-x: clip; }

/* 21px base — reading site, default scale. */
html { font-size: 21px; }

body {
  background: var(--paper);
  color: var(--ink);
  font-family: var(--type-serif);
  font-weight: 400;
  font-size: 1rem;
  line-height: 1.6;
  /* Old-style figures in the serif: dates and quantities sit inside
     the line instead of shouting above it. The mono faces opt back
     out to lining tabular numerals where columns need to align. */
  font-variant-numeric: oldstyle-nums;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img, video { max-width: 100%; }

/* Body links: green at rest with a soft underline, deepening to the
   bright pigment on hover. The underline is offset off the baseline
   and skips descenders — the link is legible as a link before you
   ever touch it, which the old ink-colored version was not. */
a {
  color: var(--pigment-link);
  text-decoration: underline;
  text-decoration-color: var(--pigment-soft);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.16em;
  text-decoration-skip-ink: auto;
  transition: color 140ms ease, text-decoration-color 140ms ease;
}
a:hover {
  color: var(--pigment-deep);
  text-decoration-color: var(--pigment);
}

/* Focus ring — every focusable thing, one shape. WCAG 2.4.7. */
:where(a, button, summary, [tabindex]):focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 3px;
  border-radius: 1px;
}

::selection { background: var(--pigment-soft); color: var(--ink); }

code {
  font-family: var(--type-mono);
  font-size: 0.85em;
  background: color-mix(in srgb, var(--ink) 6%, var(--paper));
  padding: 0.1em 0.35em;
}

/* ── Header motion (notes-header.js · "Flyers") ──────────
   Document-anchored, not fixed: the band belongs to the top of the
   page and scrolls away with the masthead, so it can never sit
   behind the writing. The script measures the real height from
   `.top-bar`; the value here is only what shows before it runs.
   z-index 0 with the page at 1 — a negative z-index would put the
   canvas behind body's own paper background and make it invisible. */
.notes-header {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 118px;
  z-index: 0;
  pointer-events: none;
}

/* ── Page scaffold ──────────────────────────────────────── */

.page {
  position: relative;
  z-index: 1;
  max-width: 60rem;
  margin: 0 auto;
  padding: 2rem 1.5rem 2rem;
}
@media (min-width: 900px) { .page { padding: 2.5rem 4rem 3rem; } }

/* Top bar — masthead + nav. No rule beneath it: the whitespace is
   the separation. */
.top-bar {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  padding-bottom: 0;
  margin-bottom: 3.5rem;
}
.top-bar .masthead-id {
  font-family: var(--type-mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink);
  text-decoration: none;
}
.top-bar .masthead-id:hover { color: var(--pigment-link); }
/* flex+gap rather than margin-left: on a phone the nav wraps, and a
   left margin indented the wrapped line away from the masthead. */
.top-bar nav {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 1.4rem;
}
.top-bar nav a {
  color: var(--ink-soft);
  text-decoration: none;
  font-family: var(--type-mono);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.top-bar nav a:hover { color: var(--pigment-link); }

/* Preamble — landing hero */
.preamble {
  margin-bottom: 4rem;
  max-width: 62ch;
}
.preamble h1 {
  font-family: var(--type-serif);
  /* 200 is a hairline at display size and the first thing on the
     page; 260 keeps the airiness but stops it dissolving. */
  font-weight: 260;
  font-size: clamp(2.8rem, 5.5vw, 4.6rem);
  line-height: 0.98;
  letter-spacing: -0.025em;
  margin: 0 0 1.4rem;
  text-wrap: balance;
}
.preamble p {
  font-size: 1.22rem;
  line-height: 1.5;
  color: var(--ink);
  margin: 0;
  /* Keeps "— against the current." from stranding two words on a
     line of its own. */
  text-wrap: pretty;
}
.preamble em { color: var(--ink-soft); }

/* ── The ladder (post index) ────────────────────────────── */

ol.ladder {
  list-style: none;
  padding: 0;
  margin: 0;
}
/* The whole row is the target.
   Rather than wrapping the <li> in an anchor — which cannot legally
   contain the tag links, and which would make every screen reader
   announce the dek and the date as part of the link text — the
   title's own anchor is stretched over the row with a ::after
   overlay. One real link, correctly labelled, with a row-sized hit
   area. The tags sit above the overlay so they stay independently
   clickable. */
ol.ladder > li {
  position: relative;
  border-top: 1px solid var(--ink-rule);
  /* Bleed the hover wash past the text without moving the text. */
  padding: 1.9rem 0.85rem;
  margin: 0 -0.85rem;
  cursor: pointer;
  transition: background-color 180ms ease;
}
ol.ladder > li:first-child { border-top-color: var(--ink-rule); }
ol.ladder > li:hover,
ol.ladder > li:focus-within {
  background: color-mix(in srgb, var(--pigment-soft) 26%, var(--paper));
}
ol.ladder h2 a::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
}
/* Above the overlay, so a tag is still its own link. */
ol.ladder .tags { position: relative; z-index: 2; }
/* Hovering anywhere on the row lights the title, because the title
   is what the click will follow. */
ol.ladder > li:hover h2 a,
ol.ladder > li:focus-within h2 a {
  color: var(--pigment-deep);
  text-decoration-color: var(--pigment);
  text-decoration-thickness: 3px;
}
ol.ladder > li:hover .when,
ol.ladder > li:focus-within .when { color: var(--pigment-deep); }

/* Two columns, not three: the "no. 14" counter is gone, so the title
   starts at the page's left edge and the date holds the right. */
ol.ladder .post-head {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.35rem;
  align-items: baseline;
}
@media (min-width: 700px) {
  ol.ladder .post-head { grid-template-columns: 1fr 8rem; gap: 1.5rem; }
}

ol.ladder h2 {
  font-style: italic;
  font-weight: 400;
  font-size: clamp(1.6rem, 2.7vw, 2.05rem);
  line-height: 1.15;
  letter-spacing: -0.008em;
  margin: 0;
  text-wrap: balance;
}
/* A post title IS the link — so it has to look like one at rest.
   Ink text over a soft-green underline; hover pulls the whole title
   into the deep green and lights the underline bright. */
ol.ladder h2 a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--pigment-soft);
  text-decoration-thickness: 2px;
  text-underline-offset: 0.18em;
  transition: color 140ms ease, text-decoration-color 140ms ease,
              text-decoration-thickness 140ms ease;
}
ol.ladder h2 a:hover {
  color: var(--pigment-deep);
  text-decoration-color: var(--pigment);
  text-decoration-thickness: 3px;
}

ol.ladder .when {
  font-family: var(--type-mono);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: 0.74rem;
  color: var(--ink-soft);
  letter-spacing: 0.04em;
  text-align: right;
  display: none;
}
@media (min-width: 700px) { ol.ladder .when { display: block; } }

/* Dek and tags used to be indented 5.25rem to clear the counter
   column. With the counter gone they align to the title. */
ol.ladder .dek {
  margin: 0.7rem 0 0;
  font-size: 1.02rem;
  line-height: 1.55;
  color: var(--ink-soft);
  max-width: 62ch;
  text-wrap: pretty;
}
ol.ladder .dek:empty { display: none; }
ol.ladder .dek .when-inline {
  font-family: var(--type-mono);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: 0.72rem;
  color: var(--ink-soft);
  margin-right: 0.6em;
}
@media (min-width: 700px) {
  ol.ladder .dek .when-inline { display: none; }
  /* A dek that only carried the mobile date collapses on desktop. */
  ol.ladder .dek:not(:has(+ *)):has(> .when-inline:only-child) { display: none; }
}

ol.ladder .tags {
  margin: 0.7rem 0 0;
  font-family: var(--type-mono);
  font-size: 0.72rem;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}
/* Tags use hl-1 (split-complement blue-violet, 5.98 on paper) — the
   second color register, on a soft-green ground so they read as
   chips rather than as loose blue words in the margin. */
ol.ladder .tags a {
  color: var(--hl-1);
  text-decoration: none;
  display: inline-block;
  margin: 0 0.35em 0.35em 0;
  padding: 0.15em 0.5em;
  background: color-mix(in srgb, var(--pigment-soft) 45%, var(--paper));
  transition: background-color 140ms ease, color 140ms ease;
}
ol.ladder .tags a:hover {
  color: var(--pigment-deep);
  background: var(--pigment-soft);
}

/* ── The post page ──────────────────────────────────────── */

article.post {
  max-width: 36rem;
  margin: 0 auto;
}
/* The counter is gone here too — the date carries the meta line. */
article.post .post-meta {
  font-family: var(--type-mono);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: 0.74rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-soft);
  margin: 0 0 1rem;
}

article.post h1 {
  font-style: italic;
  font-weight: 400;
  font-size: clamp(2.4rem, 4.4vw, 3.4rem);
  line-height: 1.04;
  letter-spacing: -0.012em;
  margin: 0 0 2.25rem;
  text-wrap: balance;
}

/* Section heads sit at the body's weight, not above it — a reading
   site wants the hierarchy in the whitespace, not in bold. */
article.post h2, article.post h3, article.post h4 {
  font-family: var(--type-serif);
  font-weight: 600;
  font-size: 1.28rem;
  line-height: 1.25;
  letter-spacing: -0.004em;
  margin: 2.75rem 0 0.7rem;
  color: var(--ink);
  text-wrap: balance;
}
article.post h3 em, article.post h2 em { font-weight: 400; }

article.post p {
  font-size: 1.08rem;
  line-height: 1.68;
  margin: 0 0 1.15rem;
  text-wrap: pretty;
}

/* Inline links inherit the base underline treatment; only the rest
   colour differs so a link inside prose is greener than one in the
   chrome. */
article.post a {
  color: var(--pigment-link);
  text-decoration-color: var(--pigment-soft);
}
article.post a:hover {
  color: var(--pigment-deep);
  text-decoration-color: var(--pigment);
}

article.post em { font-style: italic; }
article.post strong { font-weight: 700; }

article.post blockquote {
  font-family: var(--type-serif);
  font-style: italic;
  font-size: 1.2rem;
  line-height: 1.5;
  color: var(--ink-soft);
  border-left: 3px solid var(--pigment);
  padding: 0 0 0 1.25rem;
  margin: 1.75rem 0;
  max-width: 36rem;
}
article.post blockquote p { font-size: inherit; line-height: inherit; margin: 0 0 0.5rem; }

article.post ul, article.post ol {
  font-size: 1.1rem;
  line-height: 1.6;
  margin: 0 0 1.1rem;
  padding-left: 1.5rem;
}
article.post ul li::marker,
article.post ol li::marker { color: var(--pigment-deep); }

/* ── Footnotes ──────────────────────────────────────────────
   Two different things wear <sup> in this content, and they need
   opposite treatment:

   1. The REFERENCE in the body — [<sup>1</sup>](#footnote1). A true
      superscript. line-height: 0 keeps it from inflating its line.
   2. The ENTRY at the foot — <sup id="footnote1">1</sup>Text follows…
      This one is not a superscript at all, it is a list marker, and
      raising it left the digit floating half a line above its own
      sentence and jammed against the first word. That is the
      misalignment.

   The legacy .md carries style="vertical-align: super; font-size:
   smaller" inline on BOTH. FishLadder owns those files, so the
   stylesheet has to out-rank the inline style rather than the
   content being edited — hence the !important on exactly the two
   properties the inline style sets, and nothing else. */

article.post sup { line-height: 0; }
article.post sup a, article.post a sup {
  text-decoration: none;
  color: var(--hl-1);
}
article.post sup a:hover, article.post a:hover sup { color: var(--pigment-deep); }

/* The entry paragraph: hanging indent, marker in the gutter. */
article.post p:has(> sup[id^="footnote"]:first-child) {
  font-size: 0.94rem;
  line-height: 1.55;
  color: var(--ink-soft);
  margin: 0 0 0.7rem;
  padding-left: 2.2em;
  text-indent: -2.2em;
}
article.post p > sup[id^="footnote"]:first-child {
  vertical-align: baseline !important;   /* was: super  */
  font-size: 0.88em !important;          /* was: smaller */
  display: inline-block;
  width: 2.2em;
  text-indent: 0;
  line-height: inherit;
  font-family: var(--type-mono);
  font-variant-numeric: tabular-nums lining-nums;
  color: var(--hl-1);
}
/* Air above the first entry only — the run of notes then sets tight,
   so the apparatus reads as one block rather than as more paragraphs. */
article.post p:has(> sup[id^="footnote"]:first-child) { margin-top: 2rem; }
article.post p:has(> sup[id^="footnote"]:first-child)
          + p:has(> sup[id^="footnote"]:first-child) { margin-top: 0; }

/* ── Figures ────────────────────────────────────────────── */

article.post figure {
  margin: 2rem 0;
}
@media (min-width: 900px) {
  article.post figure { margin-left: -3rem; margin-right: -3rem; }
}
article.post figure img,
article.post figure video,
article.post video {
  display: block;
  width: 100%;
  height: auto;
}
article.post video { margin: 2rem 0; }
@media (min-width: 900px) {
  article.post video { width: calc(100% + 6rem); margin-left: -3rem; }
}

article.post figure figcaption,
article.post .caption {
  margin-top: 0.75rem;
  font-family: var(--type-serif);
  font-style: italic;
  font-size: 0.95rem !important;
  line-height: 1.5;
  color: var(--ink-soft);
}
/* Captions follow their figure/video tight. */
article.post figure + .caption,
article.post video + .caption { margin-top: -1.25rem; }
@media (min-width: 900px) {
  article.post .caption.half { max-width: 60%; }
}

/* Legacy inline-styled blocks (floats, tinted boxes) are honored as
   written, but always clear and never overflow the column. */
article.post div[style] { max-width: 100%; overflow: hidden; }

/* …with one exception. The sponsor callout in 009 carries a hard-coded
   background-color: rgb(179, 211, 234) — a baby blue from the old
   site's palette that fights this site's green on sight. The .md is
   FishLadder's, so the retint happens here instead: any legacy block
   that paints its own ground is pulled onto the pigment's soft cousin.
   Ink on #C5E58F is 12.7:1, so the text inside stays AAA either way. */
article.post div[style*="background"] {
  background-color: var(--pigment-soft) !important;
}

/* ── Reel (gallery) ─────────────────────────────────────────
   A folder of images as a run of full-width frames you swipe
   through. Authored as one line in the .md — see _lib/reel.php.

   The mechanism is CSS scroll-snap, not script: the swipe is the
   browser's own, with the browser's own momentum and rubber-band,
   which no amount of pointer-event JavaScript matches. reel.js
   adds the arrows, the counter and the full-screen view on top of
   something that already works without it.
   ============================================================ */

.reel {
  /* Frame box height. One image per frame, contained inside it, so
     portrait and landscape sit in the same rectangle. */
  --reel-h: clamp(300px, 62vh, 720px);

  /* Out of the 36rem reading column and across the whole screen.
     margin-left:50% puts the left edge at the column's centre;
     translate pulls it back by half its own width. Works at any
     parent width, unlike a fixed negative margin. */
  width: 100vw;
  margin-left: 50%;
  translate: -50% 0;

  margin-top: 3rem;
  margin-bottom: 3rem;
}
.reel--tall  { --reel-h: clamp(360px, 78vh, 900px); }
.reel--short { --reel-h: clamp(220px, 44vh, 480px); }

/* Past the point where .page stops growing, edge-to-edge would strand
   the frames far outside the text. Cap them on the page's own width
   instead — unless {full} asked for the full screen. */
@media (min-width: 1300px) {
  .reel:not(.reel--full) { width: 60rem; }
}

/* The track is an <ol>, so `article.post ol` (0,1,2) out-ranks a lone
   .reel-track (0,1,0) and was landing 1.5rem of list padding inside
   the scroller — which makes every frame narrower than the track and
   walks the "which frame am I on" arithmetic a whole frame off by the
   end of thirty. Two classes (0,2,0) take the reset back, and stay
   correct on pages that are not wrapped in article.post.

   Both ancestors are named because the full-screen view is a <dialog
   class="reel-lightbox"> appended to <body> — it is NOT inside a
   .reel, so a lone `.reel .reel-track` leaves the cloned track with
   no flex, no overflow and no snapping, which stacks all thirty
   images down the page while the counter cheerfully reports frames. */
.reel .reel-track,
.reel-lightbox .reel-track {
  display: flex;
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: 1rem;

  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  /* Swiping past the last frame must not hand the gesture to the
     browser's back-navigation. */
  overscroll-behavior-x: contain;

  /* Our own counter and rail are the position indicator; a native
     horizontal bar under the frames is noise on a reading page. */
  scrollbar-width: none;

  /* A faint stage, so a contained image reads as sitting in a frame
     rather than floating on the paper with odd gaps. */
  background: color-mix(in srgb, var(--ink) 4%, var(--paper));
}
.reel-track::-webkit-scrollbar { display: none; }
.reel-track:focus-visible { outline: 2px solid var(--focus); outline-offset: -2px; }

.reel-frame {
  flex: 0 0 100%;
  height: var(--reel-h);
  scroll-snap-align: center;
  /* One frame per swipe. Without this a flick skates past four of
     them, which is the wrong feel when each image is the subject. */
  scroll-snap-stop: always;
  padding: 1rem 1rem 0.75rem;
}

/* Out from under the article's figure rules — the breakout margins
   and the width:100% image both belong to inline figures, not here.
   ------------------------------------------------------------------
   Column flex with min-height: 0, NOT a 1fr grid row. A `1fr` row is
   sized by its content when the content is a raw image, so the image
   claims its own intrinsic height, overflows the fixed frame, and
   shoves the caption out of the box. Flex with min-height: 0 lets the
   image box shrink to the space that is actually left after the
   caption has taken its share, and object-fit does the letterboxing
   inside it. */
article.post .reel figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  min-height: 0;
}
article.post .reel img {
  display: block;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  cursor: zoom-in;
}
/* No <dialog> in this browser, so there is nothing to zoom into. */
article.post .reel--nozoom img { cursor: default; }

article.post .reel figcaption {
  flex: none;
  margin: 0.7rem 0 0;
  text-align: center;
  /* Two lines held open, so the page does not jump under your thumb
     when a one-line caption is followed by a two-line one. */
  min-height: 3em;
  text-wrap: pretty;
}
/* A frame whose file had nothing to say still reserves the space, so
   captioned and uncaptioned images are the same size. */
article.post .reel figure:not(:has(figcaption))::after {
  content: "";
  flex: none;
  display: block;
  min-height: 3em;
  margin-top: 0.7rem;
}

/* Chrome — arrows, rail, counter. Ships `hidden`; reel.js reveals it,
   so a page without script shows a working scroller instead of dead
   buttons. Inset to the reading column so it lines up with the prose
   above it, even while the frames run wider. */
.reel-chrome {
  width: min(36rem, 100% - 3rem);
  margin: 0.9rem auto 0;
  display: flex;
  align-items: center;
  gap: 0.9rem;
}

.reel-nav {
  flex: none;
  appearance: none;
  border: 0;
  background: none;
  padding: 0.1em 0.35em;
  font-family: var(--type-serif);
  font-size: 1.5rem;
  line-height: 1;
  color: var(--ink-soft);
  cursor: pointer;
  transition: color 140ms ease;
}
.reel-nav:hover { color: var(--pigment-deep); }
/* aria-disabled rather than the disabled attribute: at the first and
   last frame the button stops doing anything, but a keyboard user
   does not have focus yanked out from under them. */
.reel-nav[aria-disabled="true"] { color: var(--ink-faint); cursor: default; }

.reel-rail {
  flex: 1;
  height: 2px;
  background: var(--ink-faint);
  overflow: hidden;
}
.reel-rail span {
  display: block;
  height: 100%;
  width: 0;
  background: var(--pigment-deep);
  transition: width 200ms ease;
}

.reel-count {
  flex: none;
  margin: 0;
  font-family: var(--type-mono);
  font-variant-numeric: tabular-nums lining-nums;
  font-size: 0.74rem;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}

/* ── Reel, full screen ──────────────────────────────────────
   Same track, same snapping, the whole viewport. The ground is
   --ink rather than paper: a near-black surround is what keeps a
   photograph's own colour from being read against a warm tint. */

.reel-lightbox {
  border: 0;
  padding: 0;
  margin: 0;
  width: 100vw;
  max-width: 100vw;
  height: 100dvh;
  max-height: 100dvh;
  background: var(--ink);
  color: var(--paper);
  overflow: hidden;
}
.reel-lightbox::backdrop { background: var(--ink); }

.reel-lightbox .reel-track {
  background: none;
  height: 100dvh;
}
.reel-lightbox .reel-frame {
  height: 100dvh;
  padding: 2.5rem 1rem 3.5rem;
}
.reel-lightbox figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  height: 100%;
  width: 100%;
  min-height: 0;
}
.reel-lightbox img {
  display: block;
  flex: 1 1 auto;
  min-height: 0;
  width: 100%;
  height: 100%;
  object-fit: contain;
  cursor: zoom-out;
}
.reel-lightbox figcaption {
  flex: none;
  margin: 0.9rem 0 0;
  text-align: center;
  font-family: var(--type-serif);
  font-style: italic;
  font-size: 0.95rem;
  line-height: 1.5;
  color: color-mix(in srgb, var(--paper) 72%, var(--ink));
  min-height: 3em;
  text-wrap: pretty;
}

.reel-lightbox .reel-chrome {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0.9rem;
  margin: 0 auto;
}
.reel-lightbox .reel-nav { color: color-mix(in srgb, var(--paper) 70%, var(--ink)); }
.reel-lightbox .reel-nav:hover { color: var(--pigment); }
.reel-lightbox .reel-nav[aria-disabled="true"] { color: color-mix(in srgb, var(--paper) 26%, var(--ink)); }
.reel-lightbox .reel-rail { background: color-mix(in srgb, var(--paper) 22%, var(--ink)); }
.reel-lightbox .reel-rail span { background: var(--pigment); }
.reel-lightbox .reel-count { color: color-mix(in srgb, var(--paper) 70%, var(--ink)); }

.reel-close {
  position: absolute;
  top: 0.6rem;
  right: 0.9rem;
  appearance: none;
  border: 0;
  background: none;
  padding: 0.2em 0.4em;
  font-family: var(--type-mono);
  font-size: 1.1rem;
  line-height: 1;
  color: color-mix(in srgb, var(--paper) 70%, var(--ink));
  cursor: pointer;
}
.reel-close:hover { color: var(--pigment); }
.reel-lightbox :where(button, [tabindex]):focus-visible,
.reel-lightbox .reel-track:focus-visible {
  outline: 2px solid var(--paper);
  outline-offset: 2px;
}

/* ── Tags + post foot ───────────────────────────────────── */

article.post .tags {
  margin: 2.5rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--ink-rule);
  font-family: var(--type-mono);
  font-size: 0.72rem;
  letter-spacing: 0.02em;
}
/* Same chip as the ladder's — one tag treatment site-wide. */
article.post .tags a {
  color: var(--hl-1);
  text-decoration: none;
  display: inline-block;
  margin: 0 0.35em 0.35em 0;
  padding: 0.15em 0.5em;
  background: color-mix(in srgb, var(--pigment-soft) 45%, var(--paper));
  transition: background-color 140ms ease, color 140ms ease;
}
article.post .tags a:hover {
  color: var(--pigment-deep);
  background: var(--pigment-soft);
}

.post-foot {
  max-width: 36rem;
  margin: 4rem auto 0;
  padding-top: 1.25rem;
  border-top: 1px solid var(--ink-rule);
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 1rem;
  font-family: var(--type-mono);
  font-size: 0.76rem;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}
.post-foot a { color: var(--ink-soft); text-decoration: none; }
.post-foot a:hover { color: var(--pigment-deep); }

/* ── Site footer ────────────────────────────────────────── */

/* No rule above the footer either — 5rem of paper does that job. */
.notes-foot {
  margin-top: 5rem;
  padding-top: 0;
  display: grid;
  gap: 0.4rem;
  font-family: var(--type-mono);
  font-size: 0.7rem;
  letter-spacing: 0.06em;
  color: var(--ink-soft);
}
.notes-foot em { font-style: italic; }
.notes-foot a { color: var(--ink-soft); text-decoration: none; }
.notes-foot a:hover { color: var(--pigment-deep); }

/* ── Reduced motion ─────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0s !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0s !important;
    scroll-behavior: auto !important;
  }
}
