/* ============================================================================
   docs.css — the documentation shell: layout, type, prose, cards, search, pager
   ----------------------------------------------------------------------------
   The section's stylesheet is deliberately in two halves, and the line between
   them is "does this rule reach inside a demonstration?":

     docs.css   (this file)  the document. Sidebar and brand row, the flat nav,
                the search button and its dialog, the reading column and every
                prose component in it, the index cards' chrome, the hero action
                row, the pager, the footer, and all three responsive steps.
     demos.css  the drawing. The 940×587.5 stage and its container-query scale,
                every demo-internal rule, the entrance/park vocabulary, the
                rail, the travel wrapper, the sweep, and the phone frames.

   One consequence worth knowing: the index CARD is split across both. Its box,
   border, copy block and title row are here; the miniature inside it is
   demos.css's, and the two rules that trim the frame where the card wraps it
   (`.section-card .demo-frame`) are here, with the card they belong to.

   TOKENS ONLY. Not one literal colour, shadow, blur or radius value in this
   file resolves anywhere but src/shared/tokens.css — tokens-dark.css re-points
   those same names, so dark mode costs this file nothing.

   MOTION. Three durations and one ease, from docs/design/v3-docs.md's table:
   380ms (opacity / small translate), 420ms (scaleY, scaleX), 460ms (the
   payment chip's translateX) — the last two are demos.css's. Everything here
   that is not one of those is instant on purpose: colour changes on controls
   cut rather than fade, because a hover that fades in reads as lag.

   WHAT THIS FILE DOES NOT RESTATE. shell.css already ships `*{box-sizing}`,
   the body ground and column, `.sr-only`, the `:focus-visible` orange outline,
   the `.shell-tile` metrics, the `html[data-theme-switching]` transition kill,
   and a global reduced-motion duration clamp. This file only overrides where
   the section genuinely differs.

   Load order: tokens.css, tokens-dark.css, shell.css, this file, demos.css.
   ========================================================================== */

/* ==========================================================================
   1 · SECTION VARIABLES AND BASE
   ========================================================================== */

/* The section's motion constants and its hairline, named once. `--progress`
   and `--travel` are the demos' two animated custom properties; they are
   declared here so a frame that has not been painted yet still resolves them
   to a finished state rather than to `unset`. */
:root{
  --docs-ease:cubic-bezier(.23,1,.32,1);
  --docs-duration:380ms;
  --docs-line:var(--brand-20);
  --progress:1;
  --travel:200%;
}

/* 13px/1.65 is the section's reading body. shell.css owns the ground colour,
   the font family and the page column. */
body{ font-size:13px; line-height:1.65; }

a{ color:inherit; text-decoration:none; }
button{ border:0; }
button:disabled{ cursor:default; }
button,a{ -webkit-tap-highlight-color:transparent; }
p,h1,h2,h3,figure{ margin:0; }

/* the 24-box set's default size; every caller that needs another one sets it */
svg.icon{ width:24px; height:24px; flex:none; vertical-align:middle; }

/* The skip link is `.sr-only` (shell.css) until focused, then it is a real
   control in the top-left corner. Fixed, so it is visible wherever the reader
   had scrolled to when they started tabbing. */
.skip-link:focus{
  position:fixed; z-index:100; top:8px; left:8px;
  width:auto; height:auto; clip:auto; overflow:visible;
  padding:10px 15px;
  background:var(--paper); border:1px solid var(--brand);
}

/* -- type roles ------------------------------------------------------------
   `.micro` and `.eyebrow` are the site's two mono label roles. The eyebrow's
   0.4em tracking is the established value; `.micro` is the tighter one used
   inside components. `.ordinal` numbers a tool card or a verification tier. */
.micro,.eyebrow,.ordinal,.mono{ font-family:var(--font-mono); }
.micro{ font-size:10px; letter-spacing:.08em; }
.eyebrow{ font-size:10px; letter-spacing:.4em; line-height:1.8; color:var(--graphite); }

/* ==========================================================================
   2 · LAYOUT — the 1180px frame and its two columns
   ========================================================================== */

/* 1180px including 18px side padding — the v2 document frame, so a reader
   moving between Developers and this section sees the same measure. 248px of
   sidebar is 48px narrower than the marketplace's 296px filtering column:
   five links need less width than filters do, and the recovered space goes to
   the demonstrations. `flex:1 0 auto` because shell.css makes the body a
   column; without it the auto margins would centre a short page vertically. */
.docs-layout{
  width:min(1180px,100%);
  padding:40px 18px 0;
  margin:auto;
  flex:1 0 auto;
  display:grid;
  grid-template-columns:248px minmax(0,1fr);
  gap:40px;
  align-items:start;
}

/* Sticky at 30px: orientation stays put while the document scrolls past it.
   `align-self:start` keeps it from stretching to the document's height, which
   is what would break the sticky. */
.docs-sidebar{
  position:sticky; top:30px;
  min-width:0; align-self:start;
  padding-right:24px;
  border-right:1px solid var(--docs-line);
}

/* -- the brand row ---------------------------------------------------------
   src/shared/nav.js mounts the site's real wordmark accordion into
   `.shell-brand`; the tile beside it is the shell's `[data-theme-tile]`. Two
   things are re-sized for a 248px column — the tile, and the row's own gap —
   the trigger is given the column's width, and the panel's own layout
   transition is replaced below. Nothing else about the row is this section's:
   the mark, the wordmark, the gap between them and the chevron are the site's,
   which is the point of mounting the site's nav here. */
.brand-row{
  display:flex; align-items:center; justify-content:space-between;
  gap:6px; margin-bottom:45px;
}
.brand-row .shell-brand{ min-width:0; flex:1; }
/* 34px here against the bar's 38px, and no shadow: the tile sits on paper in
   a column, not on a glass bar over content. */
.brand-row .shell-tile{ width:34px; height:34px; box-shadow:none; }

/* The brand row is the marketplace sidebar's row, one step down for a 248px
   column — and NOTHING else. v3 round 2 removed three overrides that were
   quietly wrong:

     · `.nav-wordmark` / `.nav-logo` at `!important` — nav.js has never emitted
       those class names (it emits `.nav-word` and `.nav-mark`), so the two
       rules styled nothing at all. The wordmark is 17px on .28em because
       shell.css's `.shell-wordmark` says so, which is the bar's own step down
       from the marketplace's 19px, beside a 26px mark rather than a 30px one.
     · `.nav-trigger{gap:5px}` — the site's brand row is 9px, and 5px is what
       made the row read cramped next to the marketplace's.

   The one thing this row DOES need is the column's width. The "bar" variant
   makes `.nav` a flex box, so its accordion item shrink-wraps to the wordmark
   and the trigger's `width:100%` resolves against that — which leaves
   `.acc-chev`'s `margin-left:auto` nothing to push against, and the chevron
   lands 4px after the word. That is right for a sticky bar, where the brand is
   content-width; it is wrong in a 248px column. Stretching the nav and its
   item hands the trigger the row, and the chevron rides to the right edge
   exactly as it does in the marketplace's 296px sidebar. Same glyph, same
   13px, same 9px gap, same −90° → 0° rotation, on the site's own 150ms. */
.brand-row .nav{ flex:1 1 auto; min-width:0; }
.brand-row .nav > [data-acc-item]{ flex:1 1 auto; min-width:0; }

/* The accordion's own open/close animates grid-template-rows — a layout
   property. This section animates opacity and transform only, so the panel is
   re-pointed at the section's pair on the section's curve. State and keyboard
   model stay the imported implementation's; only the paint changes. */
.docs-sidebar .acc-panel{
  transition:opacity 380ms var(--docs-ease), transform 380ms var(--docs-ease);
}
/* The chevron is NOT re-pointed. `.nav-chevron` was another name nav.js never
   emits (it is `.acc-chev`), so the line below it did nothing — and it should
   do nothing: a rotation is not a layout property, so the site's own
   `transform var(--dur-150) var(--ease)` is exactly the rest/open rotation the
   marketplace's row plays, and this row now plays it too. */

/* 9px, and indented to the nav rows' text — the eyebrow labels the column
   below it, so it lines up with it. */
.docs-sidebar .eyebrow{ margin:0 0 18px 10px; font-size:9px; }

/* ==========================================================================
   3 · SIDEBAR CONTROLS — search button, flat nav, closing block
   ========================================================================== */

/* One control, two ways in: this button and Ctrl/Cmd+K open the same dialog.
   The keycap is a real <kbd>, and it is the first thing to go at phone width
   where the button becomes an icon. */
.search-button{
  width:100%; min-height:42px;
  display:flex; align-items:center; gap:9px;
  padding:0 11px;
  border:1px solid var(--docs-line); border-radius:11px;
  background:var(--paper-66); color:var(--graphite);
  font-size:12px; text-align:left;
}
.search-button .icon{ width:16px; height:16px; }
.search-button kbd{
  margin-left:auto;
  font:9px var(--font-mono);
  border:1px solid var(--border); border-radius:4px;
  padding:3px 4px;
}

/* Five rows, flat. No nested section tree: the deep links live in the search
   and in each page's "in this guide" row, so the sidebar stays one glance. */
.docs-nav{ display:grid; gap:5px; margin-top:23px; }
.docs-nav a{
  display:flex; align-items:center; gap:11px;
  min-height:42px; padding:9px 11px;
  color:var(--graphite); border-radius:9px; font-size:12px;
}
.docs-nav .icon{ width:18px; height:18px; }
/* the current row: a brand wash, the ink colour, and a 2px inset marker —
   `box-shadow` rather than a border so the row does not shift by 2px */
.docs-nav a[aria-current]{
  background:var(--brand-08); color:var(--ink);
  font-weight:600; box-shadow:inset 2px 0 var(--brand);
}
.docs-nav a[aria-current] .icon{ color:var(--brand); }
.docs-nav a:hover,.search-button:hover{ background:var(--brand-08); }

.sidebar-bottom{
  margin:43px 10px 0;
  color:var(--graphite); font-size:11px; line-height:1.7;
}
.sidebar-bottom a{ display:inline-flex; gap:5px; align-items:center; margin-top:13px; }
.sidebar-bottom .icon{ width:15px; height:15px; }
.sidebar-bottom .micro{ font-size:8px; }

/* ==========================================================================
   4 · THE DOCUMENT COLUMN — page heading and the introduction's opening
   ========================================================================== */

.doc-main{ min-width:0; padding-bottom:25px; }

/* 43px/1.15 at weight 500 with −.045em tracking: the v2 display scale. */
.page-heading{ padding:43px 0 28px; }
.page-heading h1{
  font-size:43px; line-height:1.15; font-weight:500;
  letter-spacing:-.045em; margin:17px 0 18px;
}
.page-heading .eyebrow{ color:var(--graphite); }

/* 550px is a short reading task before the demonstration that answers it. */
.lede{ font-size:14px; color:var(--graphite); line-height:1.8; max-width:550px; }

/* -- the introduction's mark ----------------------------------------------
   The landing loader's settled 3D logo, turning, as a link back to the landing
   page — src/shared/logo3d.js, styled by src/shared/logo3d.css, which docs.html
   loads after this file. It replaced a 24-box glyph over a cropped contour
   field and the `COGNIA / DOCUMENTATION` eyebrow beneath it.

   It is IN THE FLOW, not absolutely positioned over a padded header: the square
   is the first thing in the column, its left edge is the title's left edge, and
   the header's own 43px padding is the space above it. The h1's shared 17px top
   margin is overridden to the 24px this mark wants, because a margin between
   two siblings collapses and a gap that is stated twice is a gap that drifts.

   The square itself is one number, `--logo3d-size`, read by the module off the
   laid-out box. The phone step is the same number in the 520px block below. */
.intro-heading{ --logo3d-size:220px; }
.intro-mark{ width:var(--logo3d-size); height:var(--logo3d-size); }
.intro-heading h1{ font-size:46px; margin-top:24px; }

/* the one emphasis line, anchored by an orange point */
.intro-emphasis{ display:flex; align-items:center; gap:10px; font-size:12px; padding:7px 0 27px; }
.intro-emphasis > span{ width:5px; height:5px; border-radius:50%; background:var(--brand); }

/* -- the contour field's paint --------------------------------------------
   Shared material. It was declared here rather than in demos.css because the
   introduction's old mark drew it outside any demo; the mark above is now the
   3D logo, so the chain hero (`demos.js`) is its only caller and this block
   could move — it stays because docs.css loads on every route either way and
   moving a rule to say the same thing is not a change. Fine lines, brand
   colour at low opacity; the threads are graphite dashes and the seeds are
   solid. Decorative — the SVG is aria-hidden at the source. */
.terrain{ color:var(--brand); stroke:currentColor; stroke-width:.65; opacity:.7; }
.terrain .thread{ stroke:var(--graphite); stroke-width:.6; opacity:.5; stroke-dasharray:2 5; }
.terrain .seed{ fill:var(--brand); stroke:none; }
.terrain .faint{ opacity:.4; }

/* ==========================================================================
   5 · THE INDEX CARDS — the card's chrome around demos.css's miniature
   ========================================================================== */

/* Two by two at the full frame: 419px cards, 18px apart. */
.section-grid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:18px; }

.section-card{
  display:block; min-width:0;
  border:1px solid var(--docs-line); border-radius:16px;
  background:var(--paper-66); box-shadow:var(--sh-4-panel);
  overflow:hidden;
}
/* The miniature is the demo frame, wrapped: the card already carries the
   border, the radius and the shadow, so the frame gives all three up and keeps
   only the hairline that separates the drawing from the copy. */
.section-card .demo-frame{
  border:0; border-bottom:1px solid var(--docs-line);
  border-radius:0; box-shadow:none;
}

.card-copy{ padding:18px; }
.card-title{ display:flex; align-items:center; gap:9px; }
.card-title h2{ font-size:15px; line-height:1.3; letter-spacing:-.02em; font-weight:500; }
.card-title > .icon:first-child{ width:19px; height:19px; color:var(--brand); }
/* the arrow is the card's whole hover: 3px of travel on the section's curve.
   The LINK owns hover and focus — the drawing inside is pointer-events:none —
   so this fires for the keyboard exactly as it does for the pointer. */
.card-title > .icon:last-child{
  width:17px; height:17px; margin-left:auto; color:var(--graphite);
  transition:transform 380ms var(--docs-ease);
}
.section-card:is(:hover,:focus-visible) .card-title > .icon:last-child{ transform:translateX(3px); }

.card-copy p{ margin:9px 0 21px; font-size:11px; color:var(--graphite); }
.card-foot{
  display:flex; justify-content:space-between;
  font:9px var(--font-mono); letter-spacing:.08em; color:var(--graphite);
}
.card-foot > span{ letter-spacing:0; }

.intro-note{ padding:30px 0 10px; }
.intro-note .micro{ color:var(--brand); font-size:9px; letter-spacing:.18em; }
.intro-note p{ margin-top:10px; font-size:12px; color:var(--graphite); }

/* ==========================================================================
   6 · THE HERO'S ROW — actions, caption, on-page links
   ========================================================================== */

.hero-figure{ margin:0; }

/* Centred and wrapping, so the third control drops to its own line on a phone
   rather than shrinking the two that do something. */
.hero-actions{
  display:flex; justify-content:center; align-items:center;
  gap:10px; flex-wrap:wrap; margin:16px 0 12px;
}
.action{
  min-height:40px; border-radius:11px; padding:8px 14px;
  display:inline-flex; align-items:center; justify-content:center; gap:8px;
  border:1px solid var(--docs-line); background:var(--paper-66);
  font-size:11px;
}
.action .icon{ width:15px; height:15px; }
.action.primary{
  background:var(--brand); border-color:var(--brand);
  color:var(--on-brand,var(--ink)); font-weight:600;
}
/* A destination that does not exist yet is a real disabled button with a
   dashed edge — never an anchor to a page that would 404. */
.action.soon{ border-style:dashed; color:var(--graphite); background:none; }
.soon-tag{
  font:8px var(--font-mono);
  border:1px dashed var(--docs-line); border-radius:4px;
  padding:1px 4px;
}

/* the caption states the record / proposal boundary under every figure */
.figure-caption{
  font-size:10px; line-height:1.6; text-align:center;
  color:var(--graphite); margin:0 auto 32px; max-width:560px;
}

/* Two hairlines around the guide's own links. Anchors only — no scroll-spy,
   so nothing here observes scroll or schedules a timer. */
.on-page{
  display:flex; flex-wrap:wrap; gap:7px 18px;
  padding:16px 0;
  border-top:1px solid var(--docs-line); border-bottom:1px solid var(--docs-line);
  font-size:11px; color:var(--graphite);
}
.on-page > .micro{ margin-right:8px; font-size:9px; }
.on-page a:hover{ color:var(--ink); }

/* ==========================================================================
   7 · PROSE — one reading column and the components inside it
   ========================================================================== */

/* `scroll-margin-top` is what makes a deep link land under the heading rather
   than with it flush against the viewport edge. */
.prose-section{ padding-top:39px; scroll-margin-top:28px; }
.prose-section h2{
  font-size:23px; font-weight:500; letter-spacing:-.03em;
  line-height:1.3; margin-bottom:17px;
}
/* the anchor mark appears on hover or keyboard focus of the heading's link */
.prose-section h2 a{ display:inline-flex; align-items:center; gap:10px; }
.anchor-mark{ color:var(--graphite); opacity:0; font:15px var(--font-mono); }
.prose-section h2 a:is(:hover,:focus-visible) .anchor-mark{ opacity:1; }

.prose-section > p{
  font-size:13px; line-height:1.85; color:var(--graphite);
  margin:13px 0; max-width:680px;
}
.prose-section strong{ font-weight:600; color:var(--ink); }
.prose-section .note,.note{ font-size:11px; line-height:1.75; color:var(--graphite); }
code{ font:11px var(--font-mono); overflow-wrap:anywhere; color:var(--ink); }

/* -- the record callout — a real capsule, linked to its marketplace row ---- */
.record-callout{
  border:1px solid var(--docs-line); border-radius:16px;
  background:var(--paper-66);
  padding:20px; margin:22px 0; max-width:650px;
}
.record-callout .micro{ color:var(--brand); }
.record-callout strong{ display:block; font-size:17px; font-weight:500; margin:9px 0; }
.record-callout p{ font-size:12px; color:var(--graphite); }
.record-callout a,.text-link{ display:inline-flex; align-items:center; gap:8px; font-size:11px; margin-top:16px; }
.record-callout .icon,.text-link .icon{ width:16px; height:16px; }

/* -- definition rows — the verification tiers, the contract roles ---------- */
.definition-rows{ margin:20px 0; }
.definition-rows > div{
  padding:15px 0;
  display:grid; grid-template-columns:210px minmax(0,1fr); gap:15px;
  border-bottom:1px solid var(--docs-line);
}
dt{ font-size:12px; font-weight:500; }
dd{ margin:0; font-size:12px; color:var(--graphite); }
.ordinal{ font-size:10px; color:var(--brand); margin-right:11px; }

/* -- the split table and the lineage records ------------------------------ */
.split-table{ margin:20px 0; }
.split-table > div{
  display:grid; grid-template-columns:1fr 80px 80px; gap:12px;
  padding:14px 0; border-bottom:1px solid var(--docs-line);
  font-size:12px;
}
/* figures right-aligned in mono, so percentages and dollars line up by digit */
.split-table b,.split-table > div > span:last-child{ font-family:var(--font-mono); text-align:right; }

.lineage-records{
  border:1px solid var(--docs-line); border-radius:16px;
  overflow:hidden; margin:20px 0;
}
.lineage-records a{
  display:grid; grid-template-columns:85px 1fr 65px;
  align-items:center; gap:10px;
  padding:14px 16px; font-size:11px;
  background:var(--paper-66);
}
.lineage-records a + a{ border-top:1px solid var(--docs-line); }
.lineage-records a:hover{ background:var(--brand-08); }
.lineage-records b{ text-align:right; font-weight:500; }

/* -- code blocks ----------------------------------------------------------
   The <pre> is `tabindex="0"` at the source so a keyboard reader can scroll
   it; the text wraps rather than scrolling sideways, which is what keeps the
   page's own scrollWidth honest at 390px. */
.code-block{
  border:1px solid var(--docs-line); background:var(--paper-66);
  border-radius:16px; overflow:hidden; margin:16px 0;
}
.code-head{
  display:flex; align-items:center; justify-content:space-between;
  padding:10px 16px; border-bottom:1px solid var(--docs-line);
  font:9px var(--font-mono); letter-spacing:.08em; color:var(--graphite);
}
/* min-width holds the button's box across "Copy" → "Copied" → "Select to
   copy", so a denied clipboard does not reflow the header it sits in */
.copy{
  padding:6px 9px;
  border:1px solid var(--docs-line); border-radius:7px;
  background:var(--paper-72); font-size:10px; min-width:55px;
}
.code-block pre{
  padding:19px 20px; margin:0;
  white-space:pre-wrap; overflow-wrap:anywhere;
  font:11px/1.9 var(--font-mono);
}

/* -- the tool surface ----------------------------------------------------- */
.tool-index{
  display:flex; flex-wrap:wrap; gap:7px 13px; margin:20px 0;
  font:10px/1.8 var(--font-mono);
}
.tool-index a{ border-bottom:1px solid var(--docs-line); }

.tool-grid{ display:grid; grid-template-columns:repeat(2,minmax(0,1fr)); gap:14px; }
.tool-card{
  min-width:0;
  border:1px solid var(--docs-line); border-radius:16px;
  padding:17px; background:var(--paper-66);
  scroll-margin-top:24px;               /* developers.html#memory_fork lands here */
}
/* Fork spans the row: it is the seventh of a two-column set, and a half-width
   orphan reads as a mistake. */
.tool-card:last-child{ grid-column:1/-1; }
.tool-title{ display:flex; align-items:center; }
.tool-title h3{ font:11px var(--font-mono); overflow-wrap:anywhere; }
.tool-title .ordinal{ font-size:9px; }
.tool-card p{ font-size:11px; line-height:1.65; color:var(--graphite); margin:11px 0 16px; }
.tool-io{ display:grid; grid-template-columns:1fr 1fr; gap:15px; }
.tool-io > div + div{ border-left:1px solid var(--docs-line); padding-left:15px; }
.tool-io .micro{ font-size:8px; color:var(--graphite); }
.tool-io pre{ margin:8px 0 0; font:10px/1.8 var(--font-mono); white-space:pre-wrap; overflow-wrap:anywhere; }
.tool-card > a{
  display:block; margin-top:18px; padding-top:12px;
  border-top:1px solid var(--docs-line); font-size:10px;
}

/* -- the recorded trace and its result panel ------------------------------
   The recorded run and the capsule's aggregate are two different things; they
   are two different components here for the same reason the prose says so. */
.recorded-trace{
  border:1px solid var(--docs-line); border-radius:16px;
  overflow:hidden; margin:20px 0; background:var(--paper-66);
}
.trace-head{ display:flex; justify-content:space-between; gap:10px; padding:15px 16px; background:var(--brand-06); }
.trace-head .micro{ font-size:8px; }
.trace-row{
  display:grid; grid-template-columns:45px 1fr 32px; gap:10px;
  align-items:baseline; padding:12px 16px;
  border-top:1px solid var(--docs-line); font-size:11px;
}
.trace-row time,.trace-row b{ font:10px var(--font-mono); font-weight:400; color:var(--graphite); }
.trace-row b{ text-align:right; }

.result-summary{ display:grid; grid-template-columns:repeat(3,1fr); gap:12px; }
.result-summary > div{ display:flex; flex-direction:column; padding:15px; border-left:1px solid var(--docs-line); }
.result-summary span{ font-size:10px; color:var(--graphite); }
.result-summary b{ font:17px var(--font-mono); margin-top:8px; }

/* -- failure patterns — native <details>, so no disclosure logic ---------- */
.failure-pattern{
  margin-top:12px;
  border:1px solid var(--docs-line); border-radius:11px;
  padding:14px 16px; background:var(--paper-66);
}
.failure-pattern summary{ cursor:pointer; font-size:12px; }
.failure-pattern summary .micro{ font-size:8px; display:block; margin-top:4px; color:var(--graphite); }
.failure-pattern p{ margin-top:15px; font-size:12px; color:var(--graphite); }
.failure-pattern dl{ display:grid; grid-template-columns:80px 1fr; gap:8px; }

/* -- the storage rule ----------------------------------------------------- */
.storage-rule{ display:grid; grid-template-columns:1fr 1fr; gap:30px; padding:20px 0; }
.storage-rule > div + div{ padding-left:25px; border-left:1px solid var(--docs-line); }
.storage-rule .micro{ color:var(--brand); }
.storage-rule h3{ font-size:20px; font-weight:500; letter-spacing:-.025em; margin:10px 0; }
.storage-rule p{ font-size:12px; line-height:1.9; color:var(--graphite); }

.prose-section .emphasis{
  color:var(--ink); font-size:15px;
  border-left:2px solid var(--brand);
  padding:6px 18px; margin-top:20px;
}

/* ==========================================================================
   8 · PAGER, FOOTER, AND THE TWO BOOT STATES
   ========================================================================== */

/* Two equal cells, 52px clear of the prose. The last page's second cell goes
   back to the Introduction rather than dead-ending the guide. */
.pager{
  display:grid; grid-template-columns:1fr 1fr; gap:18px;
  border-top:1px solid var(--docs-line);
  margin-top:52px; padding-top:24px;
}
.pager a{
  min-height:75px; padding:14px 16px;
  border:1px solid var(--docs-line); border-radius:11px;
  background:var(--paper-66);
}
.pager a:last-child{ text-align:right; }
.pager span{
  display:block; font:8px var(--font-mono); letter-spacing:.1em;
  color:var(--graphite); margin-bottom:6px;
}
.pager b{ font-size:12px; font-weight:500; }

.docs-footer{
  display:flex; justify-content:space-between; gap:15px;
  padding:35px 0 5px;
  font-size:10px; color:var(--graphite);
}
.docs-footer .micro{ font-size:8px; }
.docs-footer b{ color:var(--ink); font-weight:600; }

/* the one frame before the records land */
.loading{ min-height:300px; padding:80px 0; font-size:13px; color:var(--graphite); }

/* and the visible failure, when they do not */
.error-state{ padding:40px 20px; border:1px solid var(--docs-line); border-radius:16px; }
.error-state h2{ font-size:23px; font-weight:500; margin-bottom:10px; }
.error-state p{ color:var(--graphite); margin-bottom:20px; }

/* ==========================================================================
   9 · THE SEARCH DIALOG
   ========================================================================== */

/* A native <dialog>: the top layer, focus containment, Escape and the backdrop
   all come with it. It sits at 15dvh rather than centred, because the list
   grows downward and a centred panel would move as the reader types. */
.search-dialog{
  padding:0;
  border:1px solid var(--docs-line); border-radius:16px;
  background:var(--paper); color:var(--ink);
  box-shadow:var(--sh-4-panel);
  width:min(600px,calc(100% - 32px));
  max-height:75dvh;
  margin:15dvh auto auto;
}
.search-dialog::backdrop{ background:var(--scrim-modal); backdrop-filter:blur(4px); }

.dialog-input{
  display:flex; gap:12px; align-items:center;
  padding:15px 18px; border-bottom:1px solid var(--docs-line);
}
.dialog-input > .icon{ width:19px; height:19px; color:var(--brand); }
/* The input's outline is REPLACED, not removed: a 2px ring around a borderless
   field inside its own header row reads as a box drawn twice, so the row's
   hairline turns brand instead. Focus is never unmarked — and every other
   control in this file keeps shell.css's `:focus-visible` outline. */
.dialog-input:focus-within{ border-bottom-color:var(--brand); }
.dialog-input input{
  min-width:0; flex:1;
  background:none; border:0; outline:none;
  font-size:14px; min-height:28px;
}
/* The placeholder is the one colour the browser would otherwise pick: Chromium
   paints it #757575, which is 4.35:1 on paper and 4.01:1 on the dark ground —
   below 4.5 at 14px, and a literal colour in a section that carries none.
   `--graphite` is the established secondary-text role and reads 6.66 / 8.89.
   `opacity:1` because Firefox dims placeholders on top of the colour. */
.dialog-input input::placeholder{ color:var(--graphite); opacity:1; }
.dialog-input button{
  font:9px var(--font-mono); padding:8px;
  border:1px solid var(--docs-line); border-radius:6px;
  background:var(--paper-66);
}

.search-results{ padding:9px; max-height:52dvh; overflow:auto; }
/* results are anchors; :focus is styled as well as :hover because the arrow
   keys move real focus through them */
.search-results a{ display:flex; align-items:center; gap:13px; border-radius:9px; padding:12px 13px; font-size:12px; }
.search-results a:hover,.search-results a:focus{ background:var(--brand-08); }
.search-results .icon{ width:19px; height:19px; color:var(--graphite); }
.search-results b{ font-weight:500; }
.search-results small{ display:block; color:var(--graphite); font-size:10px; margin-top:3px; }
.search-empty{ padding:35px 20px; color:var(--graphite); font-size:12px; }

.search-footer{
  padding:11px 20px; border-top:1px solid var(--docs-line);
  font:9px var(--font-mono); color:var(--graphite);
}

/* ==========================================================================
   10 · RESPONSIVE — 1000px, 760px, 520px
   ========================================================================== */

/* -- 1000px: the same shape, tightened -------------------------------------
   210px of sidebar and a 25px gap. The tool grid drops to one column here
   rather than at phone width, because an INPUT / OUTPUT pair in half of half
   a 1000px viewport is two words per line. */
@media (max-width:1000px){
  .docs-layout{ grid-template-columns:210px minmax(0,1fr); gap:25px; }
  .docs-sidebar{ padding-right:17px; }
  /* the brand row needs no step of its own here: 26px mark + 9px gap + the
     wordmark's 66px + the chevron is 126px inside a 193px column */
  .brand-row{ gap:2px; }
  .card-copy{ padding:15px; }
  .card-title h2{ font-size:13px; }
  .card-title > .icon:first-child{ width:16px; }
  .definition-rows > div{ grid-template-columns:180px 1fr; }
  .tool-grid{ grid-template-columns:1fr; }
  .tool-card:last-child{ grid-column:auto; }
}

/* -- 760px: the sidebar becomes a header ----------------------------------
   In flow, not fixed: an overlay would cover the prose it is navigating. The
   wordmark stays left, Search and the tile go right, and the same five links
   become a horizontally scrolling row — app.js brings the current one into
   view on the first frame. */
@media (max-width:760px){
  .docs-layout{ display:block; padding:0 18px; }
  .docs-sidebar{
    position:relative; top:0;
    padding:18px 0;
    border:0; border-bottom:1px solid var(--docs-line);
  }
  .brand-row{ margin-bottom:18px; justify-content:space-between; }
  /* the header's brand keeps the shell's phone step — 15px on .22em beside a
     22px mark, shell.css's own — and the chevron still ends the row */
  .brand-row .shell-brand{ max-width:220px; }
  .brand-row .shell-tile{ width:38px; height:38px; }
  .docs-sidebar > .eyebrow,.sidebar-bottom{ display:none; }

  /* the search button becomes a 38px icon control beside the tile */
  .search-button{
    position:absolute; right:48px; top:18px;
    width:38px; height:38px; min-height:38px;
    justify-content:center; padding:0;
  }
  .search-button .search-label,.search-button kbd{ display:none; }

  .docs-nav{ display:flex; overflow:auto; gap:7px; margin:0; padding:3px 0; scrollbar-width:none; }
  .docs-nav a{ flex:none; padding:8px 10px; min-height:36px; font-size:10px; gap:6px; }
  .docs-nav .icon{ width:15px; height:15px; }
  /* the marker moves to the underside, where a horizontal row reads it */
  .docs-nav a[aria-current]{ box-shadow:inset 0 -2px var(--brand); }

  .page-heading{ padding:32px 0 24px; }
  .page-heading h1{ font-size:36px; }
  .intro-heading h1{ font-size:39px; }
  .section-grid{ gap:14px; }
  .docs-footer{ padding-bottom:20px; }
  .prose-section{ scroll-margin-top:18px; }
}

/* -- 520px: the phone pass -------------------------------------------------
   Type steps down, the two-column components stack, and long code wraps. The
   pager stays two columns — it is two short labels, and stacking it would put
   "next" below the fold on every page. Nothing is hidden to make the page fit:
   overflow is solved by wrapping and by the nav's own scroll. */
@media (max-width:520px){
  .page-heading h1{ font-size:31px; line-height:1.17; margin:15px 0; }
  /* the mark steps to 160px, and the 24px above the title is restated because
     the shared rule above it resets the whole margin at this width */
  .intro-heading{ --logo3d-size:160px; }
  .intro-heading h1{ font-size:38px; margin-top:24px; }
  .lede{ font-size:13px; line-height:1.8; }
  .eyebrow{ font-size:8px; letter-spacing:.32em; }
  .intro-emphasis{ font-size:10px; gap:7px; padding-bottom:23px; }

  .section-grid{ grid-template-columns:1fr; gap:18px; }
  .card-copy{ padding:18px; }
  .card-title h2{ font-size:16px; }
  .card-copy p{ font-size:12px; }
  .card-foot{ font-size:9px; }
  .intro-note{ padding-top:27px; }
  /* the lede's hand-placed line break is a desktop measure decision */
  .desktop-break{ display:none; }

  .hero-actions{ gap:8px; }
  .action{ font-size:10px; padding:8px 11px; min-height:40px; }
  .figure-caption{ font-size:9px; line-height:1.7; margin-bottom:23px; }
  .on-page{ gap:6px 15px; font-size:10px; }
  .on-page > .micro{ width:100%; font-size:8px; }

  .prose-section{ padding-top:31px; }
  .prose-section h2{ font-size:21px; }
  .prose-section > p{ font-size:12px; }
  .definition-rows > div{ grid-template-columns:1fr; gap:7px; padding:14px 0; }
  .definition-rows dd{ padding-left:0; font-size:11px; }
  .lineage-records a{ grid-template-columns:70px 1fr; gap:6px 9px; padding:12px; font-size:10px; }
  .lineage-records b{ grid-column:2; text-align:left; }

  .tool-card{ padding:16px; }
  .tool-io pre{ font-size:9px; }
  .tool-title h3{ font-size:11px; }
  .result-summary{ gap:5px; }
  .result-summary > div{ padding:11px; }
  .result-summary span{ font-size:8px; }
  .result-summary b{ font-size:15px; }
  .trace-row{ font-size:10px; padding:12px; }
  .trace-head .micro:last-child{ display:none; }
  .storage-rule{ grid-template-columns:1fr; gap:20px; }
  .storage-rule > div + div{ padding:20px 0 0; border-left:0; border-top:1px solid var(--docs-line); }

  .pager{ gap:10px; margin-top:37px; }
  .pager a{ padding:12px; }
  .pager b{ font-size:10px; }
  .docs-footer{ font-size:9px; }
}

/* ==========================================================================
   11 · REDUCED MOTION
   ==========================================================================
   shell.css already clamps every transition and animation on the page to
   .01ms under this query, which is what pins the demonstrations to their
   finished frames. Two things it cannot do are here: `scroll-behavior`, and
   the card arrow's resting position — a 3px offset held with the transition
   removed would leave the arrow displaced for as long as the pointer sits on
   the card, which is a state, not a movement. */
@media (prefers-reduced-motion: reduce){
  *,*::before,*::after{ animation:none !important; transition:none !important; scroll-behavior:auto !important; }
  .section-card:is(:hover,:focus-visible) .card-title > .icon:last-child{ transform:none; }
}
