/* Agent Engineering Handbook — shared stylesheet.
   One file for every generated page: the map (index.html), the reader
   template, the frame gallery and the not-found page.  Tokens are in the
   first block; the rationale lives in DESIGN.md at the repository root and
   the behaviour decisions in INTERACTIONS.md (both source-only).  Copied
   verbatim to public/assets/ by build/render.py.  Nothing is loaded from the
   network: system faces only. */

/* ------------------------------------------------------------------ tokens */
:root {
  /* Ground: near-black, with two lifted surfaces and a single hairline value.
     Premium tech design language: the structure is drawn with hairlines, not
     with shadows, and nothing on the page glows. */
  --bg: #0b0b0c;
  --surface: #141416;
  --surface-2: #1b1b1f;
  --border: rgba(247, 243, 239, 0.11);
  --border-strong: rgba(247, 243, 239, 0.26);
  --fill: rgba(247, 243, 239, 0.03);

  /* Text: warm off-white stepped by opacity.  Contrast against --bg:
       --fg          17.6   --muted-fg  9.4   --dim-fg  6.9
       --link         8.9   --accent-text 7.3  --primary 5.6 (non-text ≥ 3:1) */
  --fg: #f7f3ef;
  --muted-fg: #b4afa8;
  --dim-fg: #948f89;
  --link: #f29764;
  --accent-text: #f37a3b;
  --primary: #ea580c;
  --on-primary: #0b0b0c;

  /* Type: one sans voice for headings and body, one mono voice for every
     secondary line — labels, metadata, numbering, timestamps and paths. */
  --font-sans: system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, "Liberation Mono", monospace;
  --text-xs: 0.8rem;
  --text-sm: 0.9rem;
  --text-base: 1rem;
  --text-read: 1.0625rem;   /* reader body at 760px and above */
  --text-lg: 1.15rem;
  --text-xl: 1.85rem;       /* section headings: 44 > 29.6 > 22.4 > 17 is ~1.3-1.5x per step */
  --text-2xl: 2rem;
  --title-home: clamp(2.4rem, 1.3rem + 3.6vw, 4.05rem);
  --title-page: clamp(1.8rem, 1.1rem + 2.6vw, 2.75rem);
  --leading: 1.6;
  --measure: 39rem;         /* reader column: ~75 characters at 17px */

  /* The mono label: 11px, uppercase, wide tracking, at the muted step. */
  --label-size: 0.6875rem;
  --label-track: 0.14em;

  /* Spacing (4px base) */
  --s-1: 4px; --s-2: 8px; --s-3: 12px; --s-4: 16px; --s-5: 24px;
  --s-6: 32px; --s-7: 40px; --s-8: 64px; --s-9: 96px;
  --gutter: 24px;
  --page-max: 1200px;

  /* Shape and motion: square, with 4px on tiles and 14px on large panels. */
  --radius-sm: 2px;
  --radius: 4px;
  --radius-lg: 14px;
  --hover-ms: 140ms;
}

/* ------------------------------------------------------------------- base */
* { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--text-base);
  line-height: var(--leading);
  -webkit-font-smoothing: antialiased;
  min-width: 300px;
}
h1, h2, h3, h4 { margin: 0; overflow-wrap: break-word; line-height: 1.2; }
/* Weight descends with level. It used to invert - h3 and h4 at 650 under an
   h2 at 500 - so a subsection read as more emphatic than the section holding
   it. Size does the work now; weight only confirms it. */
h1, h2 { font-weight: 500; letter-spacing: -0.028em; }
h3, h4 { font-weight: 500; letter-spacing: -0.018em; }
p { margin: 0 0 0.95em; }
a { color: var(--link); text-decoration: underline; text-decoration-thickness: 1px; text-decoration-color: color-mix(in oklab, var(--link) 40%, transparent); text-underline-offset: 0.2em; }
a:hover { text-decoration-color: currentColor; }
code, kbd, samp, .mono { font-family: var(--font-mono); font-size: 0.92em; }
img { max-width: 100%; height: auto; display: block; }
ul, ol { margin: 0; padding: 0; }
:focus-visible { outline: 2px solid var(--primary); outline-offset: 3px; border-radius: 3px; }
.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.skip {
  position: absolute; left: 12px; top: -60px; z-index: 50;
  background: var(--primary); color: var(--on-primary); padding: 8px 12px; border-radius: var(--radius-sm);
  text-decoration: none; font-weight: 600;
}
.skip:focus { top: 12px; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  :root { --hover-ms: 0ms; }
}

/* Page gutters.  Vertical padding on blocks uses padding-block so nothing can
   override the horizontal gutter by accident. */
.wrap { max-width: var(--page-max); margin: 0 auto; padding: 0 var(--gutter); }
@media (max-width: 400px) { :root { --gutter: 16px; } }

/* Grid and flex children default to min-width:auto; one unbreakable token (a
   40-character hash) could then widen a track.  Every layout child gets a
   zero minimum and long references may wrap anywhere. */
.opening > *, .shelf > .wrap > *, .closing > *, .tile, .tile > *, .pick li > *, .site-head .wrap > *,
.ideas li > *, .frame > *, .reader > *, .rail > *, .page-head > *, .guide-seq > * { min-width: 0; }
code, .shelf-head p, .tile .dir, .pick .a, .frame figcaption, .rail, .edition { overflow-wrap: anywhere; }

/* Small shared pieces */
.chip {
  display: inline-flex; align-items: center; gap: 6px; max-width: 100%;
  padding: 4px 10px 4px 8px; border: 1px solid var(--border); border-radius: var(--radius);
  background: var(--fill); color: var(--fg); text-decoration: none;
  font-size: var(--text-xs); line-height: 1.35;
  transition: border-color var(--hover-ms) ease-out, background-color var(--hover-ms) ease-out;
}
.chip .n { font-family: var(--font-mono); font-size: 0.86em; color: var(--accent-text); white-space: nowrap; }
.chip:hover { border-color: var(--border-strong); background: var(--surface-2); }
.num { font-family: var(--font-mono); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- header */
.site-head { border-bottom: 1px solid var(--border); background: var(--bg); position: relative; z-index: 20; }
.site-head .wrap { display: flex; align-items: center; gap: 4px 20px; min-height: 60px; }
.brand { font-weight: 500; font-size: 1.05rem; letter-spacing: -0.02em; color: var(--fg); text-decoration: none; margin-right: auto; padding: 8px 0; white-space: nowrap; }
.brand:hover { color: var(--link); }
.brand .mark { display: inline-block; width: 8px; height: 8px; background: var(--primary); margin-right: 10px; vertical-align: 0.05em; }
.primary { display: none; gap: 2px; }
.primary a, .repo, .menu summary {
  display: inline-block; padding: 8px 10px; border-radius: var(--radius);
  color: var(--muted-fg); text-decoration: none; line-height: 1.3;
  font-family: var(--font-mono); font-size: var(--label-size);
  text-transform: uppercase; letter-spacing: var(--label-track);
}
.primary a:hover, .repo:hover, .menu summary:hover { color: var(--fg); background: var(--surface-2); }
.primary a[aria-current="page"] { color: var(--fg); box-shadow: inset 0 -2px 0 var(--primary); border-radius: var(--radius) var(--radius) 0 0; }
.repo { white-space: nowrap; }
.menu { position: relative; }
.menu summary { list-style: none; cursor: pointer; user-select: none; }
.menu summary::-webkit-details-marker { display: none; }
.menu summary::after { content: ""; display: inline-block; width: 6px; height: 6px; margin-left: 8px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: translateY(-2px) rotate(45deg); }
.menu[open] summary { color: var(--fg); background: var(--surface-2); }
.menu[open] summary::after { transform: translateY(1px) rotate(-135deg); }
.menu .l-narrow { display: inline; }
.menu .l-wide { display: none; }
.menu nav {
  position: absolute; right: 0; top: calc(100% + 6px); z-index: 30; min-width: 224px;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius);
  padding: 6px;
}
.menu ul { list-style: none; }
.menu li a { display: block; padding: 8px 10px; border-radius: var(--radius-sm); color: var(--fg); text-decoration: none; font-size: 0.95rem; white-space: nowrap; }
.menu li a:hover { background: var(--surface-2); }
.menu li a[aria-current="page"] { color: var(--accent-text); }
.menu li.sep { border-top: 1px solid var(--border); margin: 6px 4px; }
@media (max-width: 480px) {
  .site-head .wrap { gap: 8px; }
  .brand { font-size: 1rem; white-space: normal; line-height: 1.2; }   /* may take two lines at 320px */
  .repo { display: none; }   /* the menu's last item reaches the repository */
}
@media (min-width: 760px) {
  .primary { display: flex; }
  .menu .l-narrow { display: none; }
  .menu .l-wide { display: inline; }
  .menu li.in-primary { display: none; }
}

/* ---------------------------------------------------- map: the landing page
   Text-led opening on a faint hairline grid, then bands separated by rules.
   Every secondary line is monospace; one accent; no shadow, glass or glow. */

/* The mono label, used by markers, badges, counts and metadata. */
.marker .pill, .contents a span, .badge, .band-head .count, .shelf-head .count,
.tile .ix, .tiles.cards .dir, .grid-frames .t, .grid-frames .open, .tile.idea .meta .ts {
  font-family: var(--font-mono); font-size: var(--label-size);
  text-transform: uppercase; letter-spacing: var(--label-track);
}

/* A section marker: a bordered mono pill with a hairline rule running from it. */
.marker { display: flex; align-items: center; gap: 14px; margin-bottom: 18px; }
.marker .pill { display: inline-block; padding: 5px 10px; border: 1px solid var(--border-strong); border-radius: 999px; color: var(--muted-fg); white-space: nowrap; }
.marker::after { content: ""; flex: 1; height: 1px; background: var(--border); }

.opening { padding-block: 48px 56px; border-bottom: 1px solid var(--border); position: relative; overflow: hidden; }
/* Drawn hairline grid, faded out — never a photograph. */
.opening::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background-image: linear-gradient(var(--border) 1px, transparent 1px), linear-gradient(90deg, var(--border) 1px, transparent 1px);
  background-size: 64px 64px;
  -webkit-mask-image: radial-gradient(120% 80% at 30% 0%, #000 0%, transparent 72%);
  mask-image: radial-gradient(120% 80% at 30% 0%, #000 0%, transparent 72%);
}
.opening > .wrap { display: grid; gap: 40px; position: relative; }
@media (min-width: 980px) { .opening { padding-block: 84px 76px; } .opening > .wrap { grid-template-columns: minmax(0, 1fr) minmax(0, 0.92fr); gap: 72px; align-items: start; } }
.opening h1 { font-size: var(--title-home); line-height: 1.04; letter-spacing: -0.032em; max-width: 15ch; margin-bottom: 22px; text-wrap: balance; }
.opening h1 em { font-style: italic; color: var(--accent-text); }
.opening .lead { font-size: 1.15rem; line-height: 1.5; color: var(--muted-fg); max-width: 44ch; margin-bottom: 26px; }

.actions { display: flex; flex-wrap: wrap; gap: 10px; margin-bottom: 26px; }
.btn {
  display: inline-flex; align-items: center; min-height: 40px; padding: 9px 18px;
  border: 1px solid var(--border-strong); border-radius: 0; background: transparent;
  color: var(--fg); text-decoration: none; font-size: var(--text-sm); font-weight: 500;
  transition: border-color var(--hover-ms) ease-out, background-color var(--hover-ms) ease-out;
}
.btn:hover { border-color: var(--fg); background: var(--surface-2); }
.btn.primary { background: var(--primary); border-color: var(--primary); color: var(--on-primary); font-weight: 600; }
.btn.primary:hover { background: #f2691d; border-color: #f2691d; }

.contents { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; }
.contents a { display: inline-flex; align-items: center; gap: 7px; padding: 6px 11px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--fill); color: var(--muted-fg); text-decoration: none; font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); transition: border-color var(--hover-ms) ease-out; }
.contents a:hover { border-color: var(--border-strong); color: var(--fg); }
.contents a span { color: var(--accent-text); font-weight: 600; letter-spacing: 0; }
.edition { margin-top: 28px; padding-top: 18px; border-top: 1px solid var(--border); font-size: var(--text-sm); color: var(--dim-fg); max-width: 52ch; }
.edition .num { color: var(--muted-fg); }

/* The problem panel, as a drawn schedule.

   It was a bordered box of eight rows separated by rules, which read as a
   table of contents when it is the one place on the home page that answers
   "which guide do I need?". It is now the vocabulary's drafting-guide figure:
   a dashed spine down the left, a mono [01]-[08] marker on every row, and one
   accent trace that draws down the spine as the panel passes through view.
   The links are untouched - it is a graphic that routes, not a picture of one. */
.pick { background: var(--fill); border: 1px solid var(--border); border-radius: var(--radius); padding: 22px 20px 20px; }
@media (min-width: 980px) { .pick { padding: 26px 26px 24px; } }
.pick h2 { font-size: 1.25rem; margin-bottom: 4px; }
.pick > p { color: var(--muted-fg); font-size: var(--text-sm); margin-bottom: 16px; }

/* The problem panel's own drawing: three repeated fixes converging on one check.
   It is decorative and carries no information the rows do not, so it is aria-hidden
   and alt-empty. It draws itself left to right as the panel crosses the viewport,
   the same idea as the spine trace below and driven by the same timeline, so nothing
   animates on load and nothing runs off screen. Without scroll-driven animations the
   finished drawing is simply shown, which is the same picture at rest. */
.pick-figure { margin: 0 0 18px; }
.pick-figure img { display: block; width: 100%; height: auto; opacity: 0.9; }
@media (min-width: 980px) {
  .pick-figure { margin: 2px 0 22px; }
  .pick-figure img { max-width: 620px; }
}
@media (min-width: 1200px) {
  .pick-figure img { max-width: 760px; }
}

/* The spine: a dashed drafting guide, with the accent trace drawn over it. */
.pick ol { list-style: none; position: relative; padding-left: 46px; }
.pick ol::before, .pick ol::after { content: ""; position: absolute; left: 15px; top: 4px; bottom: 4px; width: 1px; }
.pick ol::before { background: repeating-linear-gradient(var(--border) 0 4px, transparent 4px 9px); }
.pick ol::after { background: var(--primary); transform-origin: top; opacity: 0.85; }

.pick li { display: grid; gap: 8px; padding: 13px 0; border-top: 1px solid var(--border); position: relative; }
.pick li:first-child { border-top: 0; padding-top: 4px; }
@media (min-width: 640px) { .pick li { grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr); gap: 16px; align-items: start; } }
.pick .q { font-weight: 600; line-height: 1.35; font-size: var(--text-sm); }
.pick .a { display: flex; flex-wrap: wrap; gap: 6px; }

/* The marker sits on the spine, in the gutter the list is padded for. */
.pick .ix {
  position: absolute; left: -46px; top: 15px; width: 32px;
  font-family: var(--font-mono); font-size: var(--label-size); letter-spacing: 0.02em;
  color: var(--dim-fg); background: var(--bg); padding: 2px 0; text-align: left;
}
.pick li:first-child .ix { top: 6px; }

/* One slow dash flow, and the trace drawing down the spine, both driven by the
   panel's own progress through the viewport - so nothing animates on load and
   nothing runs while the panel is off screen. Browsers without scroll-driven
   animations get the finished drawing, which is the same picture at rest. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* The trace's zero state lives here, with the animation that fills it,
       so a browser without scroll-driven animations shows the finished trace
       rather than none. */
    .pick ol::after { transform: scaleY(0); animation: pick-trace linear both; animation-timeline: view(); animation-range: entry 60% cover 55%; }
    .pick ol::before { animation: pick-dash 3.2s linear infinite; }
    .pick .ix { animation: pick-mark linear both; animation-timeline: view(); animation-range: entry 65% cover 60%; }
    /* The drawing is a raster, so it cannot stroke itself; a soft-edged mask sweeping
       left to right reads the same way and costs nothing. It finishes before the spine
       trace starts, so the panel resolves in one direction: drawing, then trace. */
    .pick-figure img {
      animation: pick-draw linear both;
      animation-timeline: view();
      animation-range: entry 45% cover 40%;
    }
  }
}

@keyframes pick-draw {
  from { -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 0%, transparent 8%, transparent 100%);
                 mask-image: linear-gradient(90deg, #000 0%, #000 0%, transparent 8%, transparent 100%); }
  to   { -webkit-mask-image: linear-gradient(90deg, #000 0%, #000 100%, transparent 108%, transparent 100%);
                 mask-image: linear-gradient(90deg, #000 0%, #000 100%, transparent 108%, transparent 100%); }
}
@keyframes pick-trace { from { transform: scaleY(0); } to { transform: scaleY(1); } }
@keyframes pick-dash { to { background-position-y: 9px; } }
@keyframes pick-mark { 0%, 55% { color: var(--dim-fg); } 100% { color: var(--accent-text); } }

/* Bands: a dithered seam between sections rather than a hard rule - the one
   transition idiom Augment and Sourcegraph share. Two layers of dots, 4px and
   7px pitch, each masked to fade downward at a different rate, so the density
   thins the way an ordered dither does rather than merely dimming. Drawn, not
   a photograph: a generated raster was tried and did not earn its place. */
.band { padding-block: 56px; position: relative; }
.band::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 26px; pointer-events: none;
  background-image: radial-gradient(circle, rgba(247, 243, 239, 0.34) 0.75px, transparent 0.85px), radial-gradient(circle, rgba(247, 243, 239, 0.22) 0.75px, transparent 0.85px);
  background-size: 4px 4px, 7px 7px; background-position: 0 0, 2px 3px;
  -webkit-mask-image: linear-gradient(#000 0, rgba(0, 0, 0, 0.55) 30%, transparent 100%); mask-image: linear-gradient(#000 0, rgba(0, 0, 0, 0.55) 30%, transparent 100%); }
.band:last-of-type::after { display: none; }
.band-seam-top { border-top: 1px solid var(--border); }
.band-head { margin-bottom: 28px; }
.band-head h2 { font-size: clamp(1.5rem, 1.15rem + 1.2vw, 2.05rem); letter-spacing: -0.028em; text-wrap: balance; }
.band-head > p { color: var(--muted-fg); max-width: 66ch; margin-top: 10px; font-size: var(--text-sm); }
/* Two other reading axes for a band head. Split: the heading starts at the
   left and its premise starts past the centre on the same line, so the band
   opens as one composition rather than a stacked title. Centred: heading and
   premise centred, the axis change that separates the guides' left-aligned
   lane from the investigations below it. */
@media (min-width: 900px) {
  .band-head.split { display: grid; grid-template-columns: minmax(0, 46%) minmax(0, 40%); justify-content: space-between; align-items: start; margin-bottom: 34px; }
  .band-head.split > p { margin-top: 0.55em; }
}
.band-head.centered { text-align: center; }
.band-head.centered > p { margin-inline: auto; }
.route.centered { text-align: center; }

/* The ideas row bleeds to the right edge of the screen. Its left edge stays on
   the page's reading edge (the wrap's content edge, computed from the band's
   own width so a scrollbar cannot push the page wider); the right edge is the
   viewport, so the nineteenth card is out along the row rather than boxed in
   the wrap, and the last card crops at the screen edge under the fade. The
   script-added controls sit inside the same block and inherit the left edge. */
.bleed { padding-left: max(var(--gutter), calc((100% - var(--page-max)) / 2 + var(--gutter))); }
/* The fade at the screen edge is wider here than a rail's 28px: it has to
   dissolve body text, not a hairline, so the cut card reads as further along
   rather than clipped mid-word. The shared fade rule reads this value. */
.bleed .ideas-row { padding-right: var(--gutter); scroll-padding-right: var(--gutter); --fade: clamp(64px, 10vw, 144px); }

/* Four skills as fixed lanes: explanation in the left lane, the drawing in a
   fixed right lane, rows adjoining on hairlines with no box around any row.
   Repetition here is the point: four comparable things read as one
   comparison because the division between the lanes never moves. */
.lanes { list-style: none; border-top: 1px solid var(--border); }
.lanes .tile.skill { position: relative; display: grid; gap: 10px 56px; padding: 24px 0 22px; border-bottom: 1px solid var(--border); }
.lanes .tile.skill > .art { position: relative; display: grid; place-items: center; height: 192px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--fill); color: var(--accent-text); transition: border-color var(--hover-ms) ease-out; }
.lanes .tile.skill > .art svg { width: 136px; height: 136px; }
.lanes .tile.skill > .art .cap { position: absolute; left: 14px; bottom: 12px; font-family: var(--font-mono); font-size: var(--label-size); letter-spacing: var(--label-track); color: var(--dim-fg); }
.lanes .tile.skill:hover > .art, .lanes .tile.skill:focus-within > .art { border-color: var(--border-strong); }
.lanes .tile.skill a.t { font-size: 1.45rem; font-weight: 500; line-height: 1.2; letter-spacing: -0.025em; color: var(--fg); text-decoration: none; }
.lanes .tile.skill a.t::after { content: ""; position: absolute; inset: 0; }
.lanes .tile.skill a.t:hover { color: var(--link); }
.lanes .tile.skill .when { color: var(--muted-fg); font-size: var(--text-base); line-height: 1.5; max-width: 46ch; margin: 0; }
.lanes .tile.skill .fed { color: var(--dim-fg); font-size: var(--text-xs); margin: 0; }
.lanes .tile.skill .fed .n { font-family: var(--font-mono); color: var(--accent-text); font-weight: 600; }
.lanes .tile.skill .routes { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 18px; padding-top: 6px; }
.lanes .tile.skill .routes .dir { font-family: var(--font-mono); font-size: var(--label-size); color: var(--dim-fg); word-break: break-all; }
.lanes .tile.skill .routes .dir a { position: relative; z-index: 1; color: var(--dim-fg); }
@media (min-width: 760px) {
  /* The text lane is centred against the drawing: the empty first and last
     rows share whatever height the drawing's box has beyond the text, so a
     row is as tall as its drawing with no hollow under its text. If the text
     is the taller of the two the drawing centres against it instead. */
  .lanes .tile.skill { grid-template-columns: minmax(0, 1fr) 320px; grid-template-rows: 1fr auto auto auto auto 1fr; align-items: start; }
  .lanes .tile.skill > :not(.art) { grid-column: 1; }
  .lanes .tile.skill > a.t { grid-row: 2; }
  .lanes .tile.skill > .when { grid-row: 3; }
  .lanes .tile.skill > .fed { grid-row: 4; }
  .lanes .tile.skill > .routes { grid-row: 5; }
  .lanes .tile.skill > .art { grid-column: 2; grid-row: 1 / -1; align-self: center; }
}
@media (max-width: 759px) { .lanes .tile.skill > .art { height: 180px; } .lanes .tile.skill > .art svg { width: 120px; height: 120px; } }

/* Thirteen guides in a contracted reading lane: the band narrows to 0.82 of
   the page and reads left-aligned inside that, so the directory does not
   inherit the wide bands' container. Each source is one row; the accent
   stage marks are one per guide, so 8 / 2 / 2 / 1 is read as length. */
.lane { max-width: calc(var(--page-max) * 0.82); margin-inline: auto; }
.directory { list-style: none; border-top: 1px solid var(--border); }
.directory li { border-bottom: 1px solid var(--border); }
.directory a { display: grid; gap: 6px 28px; padding: 18px 0; color: var(--fg); text-decoration: none; transition: background-color var(--hover-ms) ease-out; }
.directory a:hover .t { color: var(--link); }
.directory .range { font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); color: var(--accent-text); white-space: nowrap; padding-top: 3px; }
.directory .body { display: grid; gap: 4px; min-width: 0; }
.directory .t { font-weight: 600; font-size: 1.05rem; letter-spacing: -0.015em; line-height: 1.3; }
.directory .k { font-family: var(--font-mono); font-size: var(--label-size); letter-spacing: 0.01em; color: var(--dim-fg); line-height: 1.5; }
.directory .marks { display: flex; gap: 4px; align-self: center; justify-self: start; transform-origin: left center; }
.directory .marks i { display: block; width: 14px; height: 3px; background: var(--primary); }
@media (min-width: 720px) { .directory a { grid-template-columns: 124px minmax(0, 1fr) 140px; align-items: start; } .directory .marks { align-self: start; margin-top: 8px; } }

/* Three investigations as wired file cards. The card most of the guides came
   from is the primary. On wide screens it takes the whole top row as a
   landscape card and the two companions share the row beneath, so 10 / 2 / 1
   is visible as space (2 : 1 : 1 by width) while all three diagrams are drawn
   at one size, one that reads: the drawings are 160 units wide with labels of
   about 3 units, so a label is 9px only from 480px of width, which a third of
   the page cannot give. The wire is one hairline bus between the rows with a
   stem into each card: the primary hangs above it, the companions below.
   Stacked, under 900px, the wire is the rail above the stack and each card
   hangs from the one before it. The metadata line is mono and computed; it
   sits under the title, not over it. The modifier is report-specific
   (file-primary): `.primary` is the header's section navigation, hidden on
   narrow screens and set as mono labels, and sharing its name once hid the
   leading report on phones and set its title as navigation on desktop. */
.files { list-style: none; display: grid; gap: 22px; position: relative; padding-top: 22px; margin-top: 6px; }
.files::before { content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px; background: var(--border-strong); transform-origin: left center; }
.file { position: relative; min-width: 0; }
.file::before { content: ""; position: absolute; left: 28px; top: -22px; height: 22px; border-left: 1px solid var(--border-strong); }
.file > a { display: grid; gap: 10px; align-content: start; height: 100%; padding: 22px 24px 20px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--fill); color: var(--fg); text-decoration: none; transition: border-color var(--hover-ms) ease-out, background-color var(--hover-ms) ease-out; }
.file > a:hover { border-color: var(--border-strong); background: var(--surface); }
.file .art { display: block; width: 100%; max-width: 480px; color: var(--accent-text); margin-bottom: 6px; }
.file .art svg { display: block; width: 100%; height: auto; }
.file .t { font-weight: 600; font-size: 1.1rem; line-height: 1.28; letter-spacing: -0.02em; }
.file-primary .t { font-size: 1.4rem; font-weight: 500; letter-spacing: -0.025em; }
.file .k { color: var(--muted-fg); font-size: var(--text-sm); line-height: 1.5; }
.file .meta { margin-top: auto; padding-top: 10px; font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); color: var(--dim-fg); }
@media (min-width: 900px) {
  /* 45px between the rows: the bus sits 22px under the primary and the
     companions' 22px stems rise to meet it. */
  .files { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 45px 24px; padding-top: 0; margin-top: 10px; }
  .files::before { display: none; }
  .file .art { max-width: none; margin-bottom: 8px; }
  .file-primary { grid-column: 1 / -1; }
  .file-primary::before { top: auto; bottom: -22px; }
  .file-primary::after { content: ""; position: absolute; left: 0; right: 0; bottom: -23px; height: 1px; background: var(--border-strong); transform-origin: left center; }
  /* Landscape: the diagram in the left lane, the title, line and metadata as
     one block centred against it on the right. */
  .file-primary > a { grid-template-columns: minmax(0, 1.15fr) minmax(0, 1fr); grid-template-rows: 1fr auto auto auto 1fr; gap: 0 40px; align-items: center; padding: 22px 28px 22px 24px; }
  .file-primary .art { grid-column: 1; grid-row: 1 / -1; margin-bottom: 0; }
  .file-primary .t { grid-column: 2; grid-row: 2; font-size: 1.55rem; }
  .file-primary .k { grid-column: 2; grid-row: 3; margin-top: 10px; }
  .file-primary .meta { grid-column: 2; grid-row: 4; margin-top: 0; padding-top: 16px; }
}

/* Scroll-drawn quantities and wiring, driven by each element's own passage
   through the viewport, guarded like the panel trace: only where the
   browser has scroll-driven animations and the reader has not asked for
   reduced motion. Everywhere else the finished drawing is simply there. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .directory .marks { transform: scaleX(0); animation: grow-x linear both; animation-timeline: view(); animation-range: entry 45% cover 40%; }
    .files::before, .file-primary::after { transform: scaleX(0); animation: grow-x linear both; animation-timeline: view(); animation-range: entry 30% cover 45%; }
  }
}
@keyframes grow-x { from { transform: scaleX(0); } to { transform: scaleX(1); } }

/* The nineteen ideas: icon tiles on dashed guides, each with its [nn] marker. */
/* No container border: each tile paints its own hairline, so a tier of seven
   shows ground after its last tile instead of two outlined empties - the same
   rule the guide shelves already follow. */
.ideas { list-style: none; display: grid; gap: 1px; background: var(--bg); }
@media (min-width: 700px) { .ideas:not(.track) { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .ideas:not(.track) { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* The nineteen ideas on the home page: one horizontal track the reader swipes.
   The home page used to show three of them and route out for the rest; the row
   carries the whole set, in order, and still routes out to the grid. The
   wrapper scrolls and takes the focus; the track is the list. Snapping is
   proximity rather than mandatory so a flick can cross several cards and a
   half-shown card at the end still signals there is more. */
.ideas-row { overflow-x: auto; scroll-snap-type: x proximity; scroll-padding-left: 1px; }
.ideas-row:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 3px; }
.ideas.track { grid-auto-flow: column; grid-auto-columns: 78vw; width: max-content; max-width: none; }
@media (min-width: 560px) { .ideas.track { grid-auto-columns: 300px; } }
@media (min-width: 1080px) { .ideas.track { grid-auto-columns: 336px; } }
.ideas.track > li { scroll-snap-align: start; }

/* Previous/next and the counter, added by handbook.js and absent without it. */
.row-controls { display: flex; align-items: center; gap: 10px; margin-top: 16px; }
.row-controls button {
  display: inline-flex; align-items: center; justify-content: center; width: 34px; height: 34px;
  border: 1px solid var(--border-strong); border-radius: 0; background: transparent;
  color: var(--fg); cursor: pointer; font-size: 15px; line-height: 1;
  transition: border-color var(--hover-ms) ease-out, background-color var(--hover-ms) ease-out;
}
.row-controls button:hover:not(:disabled) { border-color: var(--fg); background: var(--surface-2); }
.row-controls button:disabled { opacity: 0.34; cursor: default; }
.row-controls .count { font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); color: var(--dim-fg); }
.row-controls .count b { color: var(--accent-text); font-weight: 500; }
.tile.idea { box-shadow: 0 0 0 1px var(--border); position: relative; display: flex; flex-direction: column; gap: 9px; height: 100%; padding: 20px 20px 18px; background: var(--bg); transition: background-color var(--hover-ms) ease-out; }
.tile.idea:hover, .tile.idea:focus-within { background: var(--surface); }
.tile.idea .ix { position: absolute; top: 18px; right: 18px; color: var(--dim-fg); letter-spacing: 0.08em; }
.tile.idea .art { display: block; width: 40px; height: 40px; color: var(--accent-text); }
.tile.idea .art svg { width: 100%; height: 100%; }
.tile.idea h3 { font-size: 1.02rem; font-weight: 600; line-height: 1.32; letter-spacing: -0.015em; padding-right: 44px; }
.tile.idea .who { color: var(--dim-fg); font-size: var(--text-xs); }
.tile.idea .when { color: var(--muted-fg); font-size: var(--text-sm); line-height: 1.5; }
.tile.idea .meta { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: auto; padding-top: 4px; }
.tile.idea .meta .ts { color: var(--accent-text); text-decoration: none; }
.tile.idea .meta .ts:hover { text-decoration: underline; }
.badge { display: inline-block; padding: 3px 8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--fill); color: var(--dim-fg); }
.tile.idea .to { display: flex; flex-wrap: wrap; gap: 6px; }

/* Four skills: a hairline grid led by each drawing. */
.tiles.cards { list-style: none; display: grid; gap: 1px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
@media (min-width: 640px) { .tiles.cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .tiles.cards:not(.skills) { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.tiles.cards .tile { box-shadow: 0 0 0 1px var(--border); position: relative; display: flex; flex-direction: column; gap: 10px; padding: 22px 22px 20px; background: var(--bg); transition: background-color var(--hover-ms) ease-out; }
.tiles.cards .tile:hover, .tiles.cards .tile:focus-within { background: var(--surface); }
.tiles.cards .art { display: block; color: var(--accent-text); }
/* The skills figure: Augment's loops. A 2x2 of tall hairline cells, each
   carrying its drawing at a size that does visual work, with a mono caption
   inside the drawing's box naming the loop it closes. It was four small cards
   in a row with 52px glyphs; the same four skills now read as four figures. */
.tiles.cards.skills { grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 639px) { .tiles.cards.skills { grid-template-columns: minmax(0, 1fr); } }
.tiles.cards .tile.skill { padding: 28px 28px 24px; gap: 12px; }
.tiles.cards .tile.skill .art { position: relative; width: 100%; height: 190px; display: grid; place-items: center; border: 1px solid var(--border); border-radius: var(--radius); background: var(--fill); margin-bottom: 8px; }
.tiles.cards .tile.skill .art svg { width: 128px; height: 128px; }
.tiles.cards .tile.skill .art .cap { position: absolute; left: 14px; bottom: 12px; font-family: var(--font-mono); font-size: var(--label-size); letter-spacing: var(--label-track); color: var(--dim-fg); }
.tiles.cards .tile.skill a.t { font-size: 1.35rem; font-weight: 500; letter-spacing: -0.025em; }
.tiles.cards .tile.skill .when { font-size: var(--text-base); max-width: 40ch; }
.tiles.cards .tile.skill .routes { display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 18px; margin-top: auto; padding-top: 10px; }
.tiles.cards .tile.skill .routes .dir { margin-top: 0; padding-top: 0; }
.tiles.cards .tile.report .art { width: 100%; max-width: 190px; color: var(--muted-fg); }
.tiles.cards .tile.report .art svg { width: 100%; height: auto; }
.tiles.cards a.t { font-size: 1.1rem; font-weight: 600; line-height: 1.28; letter-spacing: -0.02em; color: var(--fg); text-decoration: none; }
.tiles.cards a.t::after { content: ""; position: absolute; inset: 0; }
.tiles.cards a.t:hover { color: var(--link); }
.tiles.cards .when { color: var(--muted-fg); font-size: var(--text-sm); line-height: 1.5; }
.tiles.cards .fed { color: var(--dim-fg); font-size: var(--text-xs); }
.tiles.cards .fed .n { font-family: var(--font-mono); color: var(--accent-text); font-weight: 600; }
.tiles.cards .dir { margin-top: auto; padding-top: 4px; color: var(--dim-fg); text-transform: none; letter-spacing: 0; word-break: break-all; }
.tiles.cards .dir a { position: relative; z-index: 1; color: var(--dim-fg); }

/* Thirteen guides: icon tiles under a mono shelf label. */
.shelf { padding-top: 34px; }
.shelf + .shelf { border-top: 1px solid var(--border); }
.shelf-head { display: grid; gap: 6px; margin-bottom: 16px; }
@media (min-width: 900px) { .shelf-head { grid-template-columns: minmax(0, 1fr) minmax(0, 1.6fr) auto; gap: 8px 40px; align-items: baseline; } }
.shelf-head h3 { font-size: 1.05rem; font-weight: 600; letter-spacing: -0.02em; }
.shelf-head p { color: var(--dim-fg); font-size: var(--text-sm); }
.shelf-head .count { color: var(--dim-fg); white-space: nowrap; }
/* No outer border: each cell paints its own hairline, so a two- or one-guide
   shelf shows ground beside its cells instead of an outlined blank. */
.tiles.guides { list-style: none; display: grid; gap: 1px; background: var(--bg); }
@media (min-width: 620px) { .tiles.guides { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .tiles.guides { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.tile.guide { box-shadow: 0 0 0 1px var(--border); position: relative; display: grid; grid-template-columns: 34px minmax(0, 1fr); gap: 12px; align-items: start; padding: 15px 16px; background: var(--bg); transition: background-color var(--hover-ms) ease-out; }
.tile.guide:hover, .tile.guide:focus-within { background: var(--surface); }
.tile.guide .glyph-box { display: grid; place-items: center; width: 34px; height: 34px; border: 1px solid var(--border); border-radius: var(--radius); color: var(--accent-text); }
.tile.guide .glyph-box svg { width: 20px; height: 20px; }
.tile.guide a.t { display: block; font-size: 0.95rem; font-weight: 600; line-height: 1.3; color: var(--fg); text-decoration: none; letter-spacing: -0.012em; }
.tile.guide a.t::after { content: ""; position: absolute; inset: 0; }
.tile.guide a.t:hover { color: var(--link); }
.tile.guide a.t .n { font-family: var(--font-mono); font-size: var(--label-size); color: var(--dim-fg); margin-right: 7px; letter-spacing: var(--label-track); }
.tile.guide .when { color: var(--dim-fg); font-size: var(--text-xs); line-height: 1.45; margin-top: 4px; }

/* Twelve frames as file cards: the images themselves live in the gallery. */
.grid-frames { display: grid; gap: 1px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
@media (min-width: 560px) { .grid-frames { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .grid-frames { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1180px) { .grid-frames { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.grid-frames figure { margin: 0; background: var(--bg); box-shadow: 0 0 0 1px var(--border); }
.grid-frames a { display: grid; gap: 6px; padding: 15px 16px 14px; height: 100%; color: var(--fg); text-decoration: none; transition: background-color var(--hover-ms) ease-out; }
.grid-frames a:hover { background: var(--surface); }
.grid-frames .t { color: var(--accent-text); letter-spacing: 0.06em; }
.grid-frames figcaption { font-size: var(--text-sm); line-height: 1.4; color: var(--muted-fg); }
.grid-frames .open { color: var(--dim-fg); }

.closing { padding-block: 56px 72px; display: grid; gap: 40px; }
/* The ledger: the foot of the page as a record, not prose. Each row is a
   mono status the page can defend - RUN, LIMIT, NOT RUN, UNVERIFIED - and one
   sentence. Only RUN takes the accent; the others stay quiet, which is the
   honest hierarchy. The credits are a definition list for the same reason. */
.ledger { list-style: none; display: grid; gap: 1px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; margin-top: 4px; }
.ledger li { display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 14px; align-items: start; padding: 13px 16px; background: var(--bg); box-shadow: 0 0 0 1px var(--border); }
.ledger .st { justify-self: start; font-family: var(--font-mono); font-size: var(--label-size); letter-spacing: var(--label-track); text-transform: uppercase; line-height: 1; padding: 5px 7px; border: 1px solid var(--border-strong); border-radius: var(--radius); color: var(--dim-fg); white-space: nowrap; }
.ledger .st-run { color: var(--accent-text); border-color: color-mix(in oklab, var(--accent-text) 45%, transparent); background: color-mix(in oklab, var(--accent-text) 12%, transparent); }
.ledger .what { color: var(--muted-fg); font-size: var(--text-sm); line-height: 1.5; margin: 0; }
.closing .ledger-col .route { margin-top: 16px; }
.credits { display: grid; gap: 0; margin: 4px 0 18px; border-top: 1px solid var(--border); }
.credits > div { display: grid; grid-template-columns: 104px minmax(0, 1fr); gap: 14px; padding: 10px 0; border-bottom: 1px solid var(--border); }
.credits dt { font-family: var(--font-mono); font-size: var(--label-size); letter-spacing: var(--label-track); text-transform: uppercase; color: var(--dim-fg); padding-top: 3px; }
.credits dd { margin: 0; color: var(--fg); font-size: var(--text-sm); }
.credits dd .h { display: block; font-family: var(--font-mono); font-size: var(--text-xs); color: var(--dim-fg); margin-top: 2px; }
.closing .attr { font-size: var(--text-xs); color: var(--dim-fg); }
@media (min-width: 900px) { .closing { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 64px; } }
.closing h2 { font-size: var(--text-xl); letter-spacing: -0.025em; margin-bottom: 12px; }
.closing p { color: var(--muted-fg); font-size: var(--text-sm); margin-bottom: 10px; }
.closing ul { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; margin-top: 14px; }
/* --------------------------------------------------------------- reader */
.reader { padding-block: 32px 64px; display: grid; grid-template-columns: minmax(0, var(--measure)); justify-content: center; }
@media (min-width: 1100px) {
  /* The rail leads on the left; the article follows. Both columns sit at the
     page's edges so they line up with the header and the footer. */
  /* The rail keeps the page's left edge, in line with the header's brand; the
     reading column follows it at a fixed gap rather than being pushed to the
     far edge, which at 1440 left the two sides 250px apart. */
  .reader { grid-template-columns: 248px minmax(0, var(--measure)); column-gap: 56px;
    justify-content: start; align-items: start; padding-block: 48px 80px; }
  .reader > .col { grid-column: 2; grid-row: 1; }
  .reader > .rail { grid-column: 1; grid-row: 1; }
}
@media (min-width: 760px) { .reader { font-size: var(--text-read); } }
.reader .col { min-width: 0; }

.page-head { margin-bottom: 28px; }
.page-head .context { display: flex; flex-wrap: wrap; gap: 4px 10px; align-items: baseline; font-size: var(--text-sm); color: var(--muted-fg); margin-bottom: 14px; }
.page-head .context .n { font-family: var(--font-mono); color: var(--accent-text); font-weight: 600; }
.page-head .context a { color: var(--muted-fg); text-decoration-color: color-mix(in oklab, var(--muted-fg) 40%, transparent); }
.page-head .context a:hover { color: var(--fg); }
.page-head h1 { font-size: var(--title-page); line-height: 1.12; letter-spacing: -0.018em; }

/* Narrow screens: a native disclosure with the page's sections. */
.toc-mobile { margin-bottom: 28px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.toc-mobile summary { list-style: none; cursor: pointer; padding: 12px 16px; font-weight: 600; font-size: var(--text-sm); display: flex; align-items: center; justify-content: space-between; }
.toc-mobile summary::-webkit-details-marker { display: none; }
.toc-mobile summary::after { content: ""; width: 7px; height: 7px; border-right: 1.5px solid currentColor; border-bottom: 1.5px solid currentColor; transform: rotate(45deg); margin-right: 3px; }
.toc-mobile[open] summary { border-bottom: 1px solid var(--border); }
.toc-mobile[open] summary::after { transform: rotate(-135deg); }
.toc-mobile .toc { padding: 8px 16px 12px; }
@media (min-width: 1100px) { .toc-mobile { display: none; } }

/* The section list shared by the disclosure and the rail. */
.toc ol { list-style: none; }
.toc li a { display: block; padding: 5px 0 5px 12px; border-left: 2px solid transparent; color: var(--muted-fg); text-decoration: none; font-size: var(--text-sm); line-height: 1.4; }
.toc li a:hover { color: var(--fg); }
.toc li a[aria-current="true"] { color: var(--fg); border-left-color: var(--primary); }
.toc li li a { padding-left: 24px; font-size: var(--text-xs); }

/* The rail: sections, place on the map, evidence and neighbours (wide screens). */
.rail { display: none; }
@media (min-width: 1100px) {
  /* The rail holds beside the article and takes its own scroll when it is taller
     than the screen — the ordinary table-of-contents pattern. Its scrollbar and
     its containment come from the shared scroll-region rule below. */
  .rail {
    display: block; position: sticky; top: 24px;
    max-height: calc(100vh - 48px); overflow-y: auto;
    padding-right: 10px; font-size: var(--text-base);
  }
}
/* Rail headings act as labels: the mono label treatment. */
.rail h2, .evidence-mobile h2 {
  font-family: var(--font-mono); font-size: var(--label-size); font-weight: 600;
  text-transform: uppercase; letter-spacing: var(--label-track); color: var(--dim-fg); margin: 0 0 8px;
}
.rail > div { padding: 18px 0; border-top: 1px solid var(--border); }
.rail > div:first-child { padding-top: 4px; border-top: 0; }
.rail .place p { margin: 0; font-size: var(--text-sm); color: var(--muted-fg); line-height: 1.45; }
.rail .place .use { margin-top: 6px; color: var(--fg); }
.rail .place .n { font-family: var(--font-mono); color: var(--accent-text); font-weight: 600; }
.rail .place a { color: var(--muted-fg); text-decoration-color: color-mix(in oklab, var(--muted-fg) 40%, transparent); }
.rail .place a:hover { color: var(--fg); }
.rail .neighbours a { display: block; padding: 6px 0; font-size: var(--text-sm); color: var(--fg); text-decoration: none; line-height: 1.35; }
.rail .neighbours a:hover { color: var(--link); }
.rail .neighbours .k { display: block; font-size: var(--text-xs); color: var(--dim-fg); }
.rail .neighbours .n { font-family: var(--font-mono); color: var(--accent-text); margin-right: 4px; }
.rail .evidence figure { margin: 0 0 12px; }
.rail .evidence a.shot { display: block; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; background: #000; }
.rail .evidence a.shot:hover { border-color: var(--border-strong); }
.rail .evidence img { aspect-ratio: 16 / 9; width: 100%; object-fit: cover; }
.rail .evidence figcaption { font-size: var(--text-xs); color: var(--muted-fg); margin-top: 6px; line-height: 1.4; }
.rail .evidence figcaption .t { font-family: var(--font-mono); color: var(--accent-text); margin-right: 2px; }
.rail .rail-note { margin: 0; font-size: var(--text-xs); }
.rail .source a { font-size: var(--text-sm); }

/* Narrow screens: the applied frames follow the article instead of the rail. */
.evidence-mobile { margin-top: 40px; padding-top: 22px; border-top: 1px solid var(--border); }
.evidence-mobile h2 { margin: 0 0 12px; }
.evidence-mobile .figs { display: grid; gap: 14px; grid-template-columns: repeat(auto-fill, minmax(min(220px, 100%), 1fr)); }
.evidence-mobile figure { margin: 0; }
.evidence-mobile a.shot { display: block; border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden; background: #000; }
.evidence-mobile img { aspect-ratio: 16 / 9; width: 100%; object-fit: cover; }
.evidence-mobile figcaption { font-size: var(--text-xs); color: var(--muted-fg); margin-top: 6px; line-height: 1.4; }
.evidence-mobile figcaption .t { font-family: var(--font-mono); color: var(--accent-text); margin-right: 2px; }
.evidence-mobile .rail-note { margin: 10px 0 0; font-size: var(--text-xs); }
@media (min-width: 1100px) { .evidence-mobile { display: none; } }

/* The article itself. */
.reader article { min-width: 0; }
.reader article > p:first-child { color: var(--muted-fg); font-size: 1.08em; line-height: 1.55; margin-bottom: 1.4em; }
.reader article h2 { font-size: var(--text-xl); line-height: 1.15; margin: 2.4em 0 0.55em; padding-top: 1em; border-top: 1px solid var(--border); scroll-margin-top: 24px; }
.reader article > h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; }
.reader article h3 { font-size: 1.32em; line-height: 1.22; margin: 1.9em 0 0.45em; scroll-margin-top: 24px; }
.reader article h4 { font-size: 1.1em; margin: 1.6em 0 0.4em; }

/* On a skill page the appended reference files are whole documents, not the
   next section of the same argument. Their heading keeps the h2 level but
   wears a mono badge and sits under a heavier gap, so "a different document
   starts here" and "the next part" no longer look identical. */
.skill-ref > h2 { margin-top: 3.2em; padding-top: 1.4em; border-top-color: var(--border-strong); display: flex; flex-wrap: wrap; align-items: center; gap: 10px 14px; }
.skill-ref > h2 .kind { font-family: var(--font-mono); font-size: var(--label-size); font-weight: 500; text-transform: uppercase; letter-spacing: var(--label-track); color: var(--accent-text); border: 1px solid color-mix(in oklab, var(--accent-text) 45%, transparent); background: color-mix(in oklab, var(--accent-text) 12%, transparent); border-radius: var(--radius); padding: 4px 8px; line-height: 1; }
.reader p, .reader li, .reader td, .reader th { overflow-wrap: anywhere; }
.reader ul, .reader ol { padding-left: 1.5em; margin: 0 0 1.1em; }
.reader li { margin: 0.4em 0; }
.reader li::marker { color: var(--dim-fg); }
.reader li > ul, .reader li > ol { margin-top: 0.4em; margin-bottom: 0; }
.reader blockquote { margin: 1.4em 0; padding: 14px 20px; border-left: 3px solid var(--primary); border-radius: 0 var(--radius-sm) var(--radius-sm) 0; background: var(--surface); color: var(--muted-fg); }
.reader blockquote p:last-child { margin-bottom: 0; }
.reader code { font-size: 0.86em; background: var(--surface-2); padding: 2px 6px; border-radius: 5px; }
.reader pre { padding: 16px 18px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); overflow-x: auto; max-width: 100%; line-height: 1.55; margin: 1.2em 0 1.4em; }
.reader pre code { background: none; padding: 0; overflow-wrap: normal; font-size: 0.84em; }
.reader hr { border: 0; border-top: 1px solid var(--border); margin: 2em 0; }
.reader strong { font-weight: 650; }
/* ------------------------------------------------------- scroll regions
   Every region on the site that scrolls inside the page gets one treatment: a
   scroll that never chains into the page behind it, and a thin quiet scrollbar
   rather than the browser's default slab. The rail scrolls vertically, code
   blocks and wide tables horizontally; the behaviour should not differ between
   them just because the axis does. */
/* Containment is per axis. The rail scrolls vertically, so it contains both
   axes. A region that only scrolls sideways contains only the x axis: with
   both axes contained it sits at its vertical boundary already, swallows the
   wheel, and the page stops scrolling whenever the cursor is over it - the
   owner's QA finding of 2026-09-10, measured as 0px of page scroll over the
   ideas row, the track, a wide table and a code block. */
.rail { overscroll-behavior: contain; }
.table-scroll, .reader pre, .ideas-row, .track-row { overscroll-behavior-x: contain; overscroll-behavior-y: auto; }
.rail, .table-scroll, .reader pre, .ideas-row {
  scrollbar-width: none;          /* Firefox */
  -ms-overflow-style: none;       /* old Edge */
}
.rail::-webkit-scrollbar,
.table-scroll::-webkit-scrollbar,
.ideas-row::-webkit-scrollbar,
.reader pre::-webkit-scrollbar { width: 0; height: 0; display: none; }

/* A scrollbar is a poor way to say "there is more": it is browser chrome
   dropped into a composition that draws everything else itself. The regions
   fade out at the edge they overflow instead, which says the same thing in the
   page's own voice and disappears the moment there is nothing more to show.
   A fade is decoration, not an affordance, so the two regions a reader might
   not know to scroll keep a real control: the rows have previous/next, and
   tables and code blocks stay focusable scroll regions reachable by keyboard. */
.rail { --fade: 28px; }
.rail.is-overflowing { -webkit-mask-image: linear-gradient(#000 calc(100% - var(--fade)), transparent); mask-image: linear-gradient(#000 calc(100% - var(--fade)), transparent); }
.rail.is-at-end { -webkit-mask-image: none; mask-image: none; }
.ideas-row.is-overflowing { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - var(--fade, 40px)), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - var(--fade, 40px)), transparent); }
.ideas-row.is-at-end { -webkit-mask-image: none; mask-image: none; }
.rail::-webkit-scrollbar-track,
.table-scroll::-webkit-scrollbar-track,
.reader pre::-webkit-scrollbar-track { background: transparent; }
.rail::-webkit-scrollbar-thumb,
.table-scroll::-webkit-scrollbar-thumb,
.reader pre::-webkit-scrollbar-thumb { background: var(--border-strong); border-radius: 3px; }
.rail:hover::-webkit-scrollbar-thumb,
.table-scroll:hover::-webkit-scrollbar-thumb,
.reader pre:hover::-webkit-scrollbar-thumb { background: var(--dim-fg); }

.table-scroll { max-width: 100%; overflow-x: auto; margin: 1.2em 0 1.6em; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); }
.table-scroll:focus-visible { outline-offset: 2px; }
table { width: 100%; border-collapse: collapse; font-size: 0.9em; min-width: 560px; }
th, td { padding: 10px 14px; border-top: 1px solid var(--border); text-align: left; vertical-align: top; line-height: 1.5; }
th { background: var(--surface-2); border-top: 0; font-weight: 600; color: var(--muted-fg); font-size: 0.92em; }
td:not(:first-child), th:not(:first-child) { border-left: 1px solid var(--border); }
.reader figure { margin: 1.5em 0 2.2em; }
.reader figure img { border: 1px solid var(--border); border-radius: var(--radius); }
.reader figcaption { margin-top: 12px; color: var(--muted-fg); font-size: 0.92em; }

/* Previous / next, then the source line. */
.guide-seq { display: grid; gap: 12px; margin-top: 40px; padding-top: 24px; border-top: 1px solid var(--border); font-size: var(--text-base); }
@media (min-width: 640px) { .guide-seq { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); } }
.guide-seq a { display: block; color: var(--fg); text-decoration: none; padding: 14px 16px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--surface); transition: border-color var(--hover-ms) ease-out; line-height: 1.35; }
.guide-seq a:hover { border-color: var(--border-strong); }
.guide-seq a .k { display: block; color: var(--dim-fg); font-size: var(--text-xs); margin-bottom: 4px; }
.guide-seq a .n { font-family: var(--font-mono); color: var(--accent-text); margin-right: 4px; }
.guide-seq .next { text-align: right; }
.guide-seq .next .k::after { content: " →"; }
.guide-seq .prev .k::before { content: "← "; }
.source-note { margin-top: 20px; margin-bottom: 0; color: var(--dim-fg); font-size: var(--text-sm); }
.source-note a { color: var(--muted-fg); }

.site-foot { padding-block: 28px 56px; border-top: 1px solid var(--border); color: var(--dim-fg); font-size: var(--text-sm); }
.site-foot .wrap { display: grid; gap: 14px; }
@media (min-width: 900px) { .site-foot .wrap { grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 40px; } }
.site-foot p { max-width: 64ch; margin: 0; }
.site-foot ul { list-style: none; display: flex; flex-wrap: wrap; gap: 6px 18px; }
.site-foot a { color: var(--muted-fg); text-decoration: none; }
.site-foot a:hover { color: var(--fg); text-decoration: underline; }

/* --------------------------------------------------------------- gallery */
.gallery-head { padding-block: 40px 28px; border-bottom: 1px solid var(--border); }
.gallery-head h1 { font-size: var(--title-page); line-height: 1.12; letter-spacing: -0.018em; margin-bottom: 14px; max-width: 22ch; text-wrap: balance; }
.gallery-head .lead { color: var(--muted-fg); font-size: var(--text-lg); max-width: 58ch; }
.gallery-head .links { color: var(--muted-fg); font-size: var(--text-sm); }
.strip { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin-top: 20px; }
.strip a { display: inline-block; font-family: var(--font-mono); font-size: var(--text-sm); color: var(--fg); text-decoration: none; padding: 5px 10px; border: 1px solid var(--border); border-radius: 999px; background: var(--surface); }
.strip a:hover { border-color: var(--border-strong); }
.gallery { display: grid; gap: 44px 32px; padding-block: 36px 72px; }
@media (min-width: 760px) { .gallery { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.frame { scroll-margin-top: 20px; }
.frame h2 { font-size: 1.28rem; margin: 0 0 12px; line-height: 1.3; }
.frame h2 .t { font-family: var(--font-mono); font-size: 0.85em; font-weight: 600; color: var(--accent-text); margin-right: 6px; }
.frame figure { margin: 0; }
.frame a.shot { display: block; border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; background: #000; }
.frame a.shot img { aspect-ratio: 16 / 9; width: 100%; object-fit: cover; }
.frame figcaption { margin-top: 12px; color: var(--muted-fg); font-size: var(--text-sm); line-height: 1.5; }
.frame figcaption .links { display: block; margin-top: 6px; }

/* ------------------------------------------------------------- not found */
.notfound { padding-block: 56px 96px; max-width: var(--measure); }
.notfound h1 { font-size: var(--title-page); margin-bottom: 14px; }
.notfound p { color: var(--muted-fg); max-width: 56ch; }
.notfound ul { list-style: none; display: grid; gap: 8px; margin-top: 20px; }

/* ------------------------------------------------------------------ print */
@media print {
  :root { --bg: #fff; --surface: #fff; --surface-2: #f2f0ec; --border: #ccc; --fg: #111; --muted-fg: #444; --dim-fg: #555; --link: #1a4a8a; --accent-text: #b3410a; --primary: #b3410a; }
  .skip, .site-head, .guide-seq, .rail, .toc-mobile, .site-foot ul { display: none; }
  .reader { display: block; max-width: none; }
  .reader pre { white-space: pre-wrap; }
  table { min-width: 0; }
  .tile a.t::after { display: none; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.85em; color: var(--muted-fg); }
}

/* ------------------------------------------------ progressive disclosure
   The home page shows one taste of each section and routes out; the full
   sets live on ideas.html, guides.html and the gallery. */
.route { margin-top: 18px; }
.more { display: inline-flex; align-items: center; gap: 8px; color: var(--accent-text); text-decoration: none; font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); }
.more:hover { text-decoration: underline; }
.tile.idea h3 a { color: inherit; text-decoration: none; }
.tile.idea h3 a::after { content: ""; position: absolute; inset: 0; }
.tile.idea h3 a:hover { color: var(--link); }
.tile.idea .meta .ts { color: var(--accent-text); }

/* Shelves on the home page: four rows, each a route into guides.html. */
.shelves { list-style: none; display: grid; gap: 1px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
@media (min-width: 720px) { .shelves { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
/* Three reports fill three columns; in two they left a blank fourth cell. */
@media (min-width: 900px) { .shelves.reports { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.shelves a { display: grid; gap: 4px; padding: 16px 18px; background: var(--bg); color: var(--fg); text-decoration: none; box-shadow: 0 0 0 1px var(--border); transition: background-color var(--hover-ms) ease-out; }
.shelves a:hover { background: var(--surface); }
.shelves .range, .shelves .k { font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); color: var(--dim-fg); }
.shelves .range { color: var(--accent-text); }
.shelves .t { font-weight: 600; font-size: 1rem; letter-spacing: -0.015em; }

/* Frames on the home page: the twelve timestamps as a mono strip. */
.timestamps { list-style: none; display: flex; flex-wrap: wrap; gap: 6px; }
.timestamps a { display: inline-block; padding: 6px 10px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--fill); color: var(--accent-text); text-decoration: none; font-family: var(--font-mono); font-size: var(--text-xs); letter-spacing: 0.06em; transition: border-color var(--hover-ms) ease-out; }
.timestamps a:hover { border-color: var(--border-strong); }

/* Section pages: a head, then the full set. */
.section-head { padding-block: 44px 8px; }
@media (min-width: 980px) { .section-head { padding-block: 64px 8px; } }
.section-head h1 { font-size: clamp(2rem, 1.2rem + 2.6vw, 3.1rem); letter-spacing: -0.03em; max-width: 24ch; margin-bottom: 14px; text-wrap: balance; }
.section-head .lead { color: var(--muted-fg); max-width: 62ch; font-size: 1.05rem; }
/* Source files a section page offers but does not lead with. */
.section-head .head-links { margin-top: 14px; color: var(--dim-fg); font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); }

/* The closing route of a section page. A reader who reaches the bottom of a
   set has finished something; each row names the next set and why. Same
   routing-row form as the home page's shelves, so arriving anywhere in the
   site teaches the one pattern. */
.hub-next { border-top: 1px solid var(--border); padding-block: 40px 64px; }
.hub-next h2 { font-size: 1.15rem; font-weight: 600; letter-spacing: -0.02em; margin-bottom: 16px; max-width: 30ch; }
.hub-next ul { list-style: none; display: grid; gap: 1px; background: var(--bg); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; }
@media (min-width: 720px) { .hub-next ul { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); } }
.hub-next a { display: grid; gap: 4px; align-content: start; height: 100%; padding: 16px 18px; background: var(--bg); color: var(--fg); text-decoration: none; box-shadow: 0 0 0 1px var(--border); transition: background-color var(--hover-ms) ease-out; }
.hub-next a:hover { background: var(--surface); }
.hub-next .t { font-weight: 500; }
/* Mono, but not uppercase: these lines are sentences rather than labels, and
   the label's 0.14em tracking makes a sentence shout and read slowly. */
.hub-next .k { font-family: var(--font-mono); font-size: var(--label-size); letter-spacing: 0.01em; line-height: 1.5; color: var(--dim-fg); }
.shelves-band { padding-block: 8px 56px; }
.shelves-band .shelf-head h2 { font-size: 1.15rem; font-weight: 600; letter-spacing: -0.02em; }

/* Reader pages: the drawing above the title (ideas, guides, investigations,
   skills) and the skill's deck line. */
.page-head .art { display: block; width: 56px; height: 56px; color: var(--accent-text); margin: 10px 0 14px; }
.page-head .art svg { width: 100%; height: 100%; }
.page-head .art.wide { width: 190px; height: 95px; }
.page-head .deck { color: var(--muted-fg); max-width: 58ch; margin: 12px 0 0; }
.skill-ref { margin-top: 2em; padding-top: 1em; border-top: 1px solid var(--border); }
.skill-ref > h2:first-child { margin-top: 0; padding-top: 0; border-top: 0; font-size: var(--text-xl); }
.rail .place .use p { margin: 0 0 6px; font-size: var(--text-sm); line-height: 1.45; }
.idea-page .rail .watch .ts { color: var(--accent-text); text-decoration: none; font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); }
.idea-page .rail .watch .ts:hover { text-decoration: underline; }
.idea-page .rail .leads p { margin: 0 0 6px; }
.idea-page .rail .badge { display: inline-block; }

/* ------------------------------------------------------------------ */
/* Investigations page: three full-viewport studies (T3).              */
/* One study per report: the authored diagram at full column width,    */
/* mono meta, the claim, findings as a hairline-divided list, and the  */
/* CTA row. min-height, never a fixed height, so a phone can grow past */
/* one viewport. Nothing animates; motion is added later.              */
/* ------------------------------------------------------------------ */
.study { min-height: 100svh; display: grid; align-content: center; padding-block: 64px; border-top: 1px solid var(--border); }
.study-figure { margin: 0; }
.study-figure svg { display: block; width: 100%; height: auto; color: var(--accent-text); }
/* B5. The diagram is revealed by a left-to-right sweep scrubbed by the
   figure's own passage through the viewport, following the order the drawing
   is read in (repositories, fork, verifier; glossary, transport, artifact;
   schema, five layers, types). No pin and no library: pinning would add
   scroll length without adding information, and this is 0 KB. The drawing
   itself is untouched, so the check that the exact figure appears still
   holds. Without scroll-driven animations, or under reduced motion, the
   diagram is simply complete. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .study-figure svg {
      -webkit-mask-image: linear-gradient(90deg, #000 84%, transparent 100%); mask-image: linear-gradient(90deg, #000 84%, transparent 100%);
      -webkit-mask-size: 200% 100%; mask-size: 200% 100%; -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
      -webkit-mask-position: 200% 0; mask-position: 200% 0;
      animation: study-sweep linear both; animation-timeline: view(); animation-range: entry 20% cover 55%;
    }
  }
}
@keyframes study-sweep { from { -webkit-mask-position: 200% 0; mask-position: 200% 0; } to { -webkit-mask-position: 0% 0; mask-position: 0% 0; } }
.study-meta { margin: 0 0 14px; font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); color: var(--dim-fg); }
.study h2 { margin: 0 0 18px; }
.study .claim { margin: 0 0 24px; font-size: var(--text-lg); line-height: 1.5; color: var(--fg); max-width: 32ch; }
.study .findings { list-style: none; margin: 0 0 32px; padding: 0; display: grid; gap: 1px; background: var(--bg); }
.study .findings li { background: var(--bg); box-shadow: 0 0 0 1px var(--border); padding: 14px 16px; line-height: 1.5; color: var(--muted-fg); }
.study .findings .ix { font-family: var(--font-mono); font-size: var(--label-size); letter-spacing: var(--label-track); color: var(--dim-fg); margin-right: 10px; }
.study .study-cta { margin: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 12px 22px; }
.study .study-body { max-width: 60ch; }
/* Wide viewports: the figure takes the left column, the text the right. */
@media (min-width: 980px) {
  .study > .wrap { display: grid; grid-template-columns: minmax(0, 640px) minmax(0, 1fr); gap: 72px; align-items: center; }
  .study-figure svg { width: 100%; max-width: 640px; }
}

/* T5: the ideas hub sorted into three evidential tiers (DESIGN-NOTES note 8).
   Each tier is a hairline-ruled band with its own marker pill; the .ideas grid
   rule already handles 1/2/3 columns, so only the tier's own chrome is here. */
.tier { padding-block: 40px 56px; border-top: 1px solid var(--border); }
.tier h2 { font-size: var(--text-xl); margin: 14px 0 6px; }
.tier-lead { color: var(--muted-fg); max-width: 60ch; margin-bottom: 22px; }


/* ------------------------------------------------------------ the track
   The thirteen guides as a pipeline: one hairline rail, an accent stage bar
   per guide, the guide's drawing hung from the bar by a dotted vertical, and
   a mono group label above the rail where a new source begins. It scrolls
   sideways as a native region with the same controls as the ideas row. */
.track-band { padding-block: 40px 8px; border-bottom: 0; }
.track-band .tier-lead { color: var(--muted-fg); max-width: 60ch; margin: 6px 0 22px; }
.track-row { overflow-x: auto; scroll-snap-type: x proximity; padding-top: 30px; }
.track-row:focus-visible { outline: 2px solid var(--accent-text); outline-offset: 3px; }
.track { list-style: none; display: grid; grid-auto-flow: column; grid-auto-columns: 78vw; width: max-content; position: relative; padding-top: 22px; border-top: 1px solid var(--border-strong); }
@media (min-width: 560px) { .track { grid-auto-columns: 262px; } }
.stage { position: relative; scroll-snap-align: start; padding: 22px 20px 18px 0; margin-right: 24px; }
.stage .bar { position: absolute; left: 0; top: -23px; width: calc(100% - 8px); height: 3px; background: var(--primary); }
.stage::before { content: ""; position: absolute; left: 20px; top: -20px; height: 34px; border-left: 1px dotted var(--border-strong); }
.stage .seg { position: absolute; left: 0; top: -54px; white-space: nowrap; font-family: var(--font-mono); font-size: var(--label-size); text-transform: uppercase; letter-spacing: var(--label-track); color: var(--accent-text); }
.stage .art { display: grid; place-items: center; width: 56px; height: 56px; margin-left: -8px; border: 1px solid var(--border); border-radius: var(--radius); background: var(--bg); color: var(--accent-text); position: relative; z-index: 1; }
.stage .art svg { width: 30px; height: 30px; }
.stage a.t { display: block; margin-top: 14px; font-size: 1.05rem; font-weight: 500; line-height: 1.28; letter-spacing: -0.015em; color: var(--fg); text-decoration: none; }
.stage a.t::after { content: ""; position: absolute; inset: 0; }
.stage a.t:hover { color: var(--link); }
.stage a.t .n { display: block; font-family: var(--font-mono); font-size: var(--label-size); letter-spacing: var(--label-track); color: var(--dim-fg); margin-bottom: 6px; }
.stage .when { color: var(--dim-fg); font-size: var(--text-sm); line-height: 1.45; margin-top: 8px; }
.track-row { scrollbar-width: none; }
.track-row::-webkit-scrollbar { width: 0; height: 0; display: none; }
.track-row.is-overflowing { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 40px), transparent); mask-image: linear-gradient(90deg, #000 calc(100% - 40px), transparent); }
.track-row.is-at-end { -webkit-mask-image: none; mask-image: none; }


/* ---------------------------------------------------------------- motion
   Things enter the page by fading in and rising 14px, once, as they scroll
   into view; siblings arrive 60ms apart. The `js` class is set in the head
   before first paint, so without the script nothing is ever hidden, and the
   script shows anything already on screen at once, so nothing above the fold
   flashes. Under reduced motion the page is simply there. */
.js .reveal-pending { opacity: 0; transform: translateY(14px); }
.js .reveal-in { opacity: 1; transform: none; transition: opacity 560ms cubic-bezier(.2,.7,.2,1), transform 560ms cubic-bezier(.2,.7,.2,1); }
.tiles > li, .shelves > li > a, .hub-next li > a, .stage, .ledger li, .file > a { transition: transform var(--hover-ms) ease-out, background-color var(--hover-ms) ease-out, border-color var(--hover-ms) ease-out; }
.tiles > li:hover, .shelves > li > a:hover, .hub-next li > a:hover, .stage:hover, .file > a:hover { transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) {
  .js .reveal-pending, .js .reveal-in { opacity: 1; transform: none; transition: none; }
  .tiles > li:hover, .shelves > li > a:hover, .hub-next li > a:hover, .stage:hover, .file > a:hover { transform: none; }
}


/* ------------------------------------------------------------ the prompt
   Codecademy's typed cursor in an accent box, as the one small coding
   animation on the page: a shell prompt that types each of the four skills
   as the slash command that invokes it, holds, deletes, and moves on. The
   whole line is a link to the skills. Under reduced motion it is a static
   prompt with no blink. */
.prompt { display: inline-flex; align-items: center; margin-top: 18px; padding: 9px 13px; border: 1px solid color-mix(in oklab, var(--accent-text) 45%, transparent); background: color-mix(in oklab, var(--accent-text) 9%, transparent); border-radius: var(--radius); font-family: var(--font-mono); font-size: var(--text-sm); color: var(--fg); text-decoration: none; min-width: 27ch; transition: border-color var(--hover-ms) ease-out, background-color var(--hover-ms) ease-out; }
.prompt:hover { border-color: var(--accent-text); background: color-mix(in oklab, var(--accent-text) 14%, transparent); }
.prompt .ps { color: var(--accent-text); margin-right: 6px; }
.prompt .cursor { color: var(--accent-text); margin-left: 1px; animation: prompt-blink 1.1s steps(1) infinite; }
@keyframes prompt-blink { 50% { opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .prompt .cursor { animation: none; } }
