/*§RUN§[70,"\n",3505,"\n",53345,"\n",1095]§*/html,body{height:100%;margin:0}#dc-root,#dc-root>.sc-host{height:100%}/**
 * faces.css — the two type families `tokens.css` names, actually delivered.
 * `CONTRACT-Webfont-16AUG.md`. Self-hosted, `public/fonts/PROVENANCE.md` records the source.
 *
 * ⛔ §0's defect, measured three ways before this file existed: zero `@font-face` anywhere in
 * `src/`, zero font integration in `astro.config`/`package.json`, zero `.woff2` hits in `dist/`
 * — the built output, which is the check that would have caught it. `tokens.css` has named
 * `"Geist"` and `"Geist Mono"` since it was written; every page has rendered in the `system-ui` /
 * `ui-monospace` fallback the whole time.
 *
 * ⛔⛔ SCOPE, deliberately narrow — §1. Three Geist weights, two Geist Mono weights: exactly
 * what `--type-*-weight` publishes today. NOT Geist 700 (loaded by the drawing, used by no rule
 * this project has). Shipping a weight nothing uses is the font-file version of the 51 inert
 * `60ch` declarations design struck the same day this contract was written.
 *
 * ⛔ `font-display: swap`, never `optional` — `optional` can drop the face entirely on a slow
 * connection, which reintroduces the exact fallback this file exists to remove.
 *
 * ⭐ `CONTRACT-Serif-16AUG.md` adds "Newsreader" below, ROMAN and ITALIC, both the `opsz` variable
 * file (NOT the smaller `wght`-only file — the optical axis is the entire reason this face is
 * variable at all) clamped to `font-weight: 400`, the one weight design's corpus draws.
 *
 * ⭐⭐ `CONTRACT-Optimize-14SEP.md` addendum 2 criterion 3, 17 Sep 2026: the two files at
 * `/fonts/Newsreader-{Roman,Italic}.woff2` are now `fontTools.varLib.instancer wght=400` output
 * — the `wght` axis (200-800, never set by any rule) is pinned OUT of the font itself rather than
 * only clamped by this `@font-face` block, and `opsz` (6-72, the axis this face exists for) is
 * kept, at the same served address (no manifest tracks `public/fonts`, so no new address is
 * owed) and the same 224-character set. Roman 132,000 → 57,608 B, Italic 146,872 → 63,544 B. A
 * computed-style scan of the built site (FINDING-Speed-16SEP.md, confirmed again by this round)
 * found 0 elements setting Newsreader to a weight or `font-variation-settings` other than what
 * this file already declares, so pinning the axis in the file changes no rendered page.
 */

@font-face {
  font-family: "Geist";
  src: url("/fonts/Geist-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("/fonts/Geist-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist";
  src: url("/fonts/Geist-SemiBold.woff2") format("woff2");
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/fonts/GeistMono-Regular.woff2") format("woff2");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Geist Mono";
  src: url("/fonts/GeistMono-Medium.woff2") format("woff2");
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src: url("/fonts/Newsreader-Roman.woff2") format("woff2-variations");
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: "Newsreader";
  src: url("/fonts/Newsreader-Italic.woff2") format("woff2-variations");
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

    .sc-placeholder{background:color-mix(in srgb,currentColor 8%,transparent);
      border:1px solid color-mix(in srgb,currentColor 50%,transparent);
      border-radius:2px;box-sizing:border-box;overflow:hidden}
    @keyframes sc-shine{0%{background-position:100% 50%}100%{background-position:0% 50%}}
    html.sc-dc-streaming .sc-placeholder,
    html.sc-dc-streaming .sc-interp.sc-missing{position:relative;
      background:color-mix(in srgb,currentColor 5%,transparent);
      border-color:transparent}
    html.sc-dc-streaming .sc-placeholder::before,
    html.sc-dc-streaming .sc-interp.sc-missing::before{content:'';
      position:absolute;inset:0;pointer-events:none;
      background:linear-gradient(90deg,rgba(217,119,87,0) 25%,rgba(247,225,211,.95) 37%,rgba(217,119,87,0) 63%);
      background-size:400% 100%;animation:sc-shine 1.4s ease infinite}
    html.sc-dc-streaming .sc-placeholder:nth-child(n+9 of .sc-placeholder)::before,
    html.sc-dc-streaming .sc-interp.sc-missing:nth-child(n+9 of .sc-interp.sc-missing)::before{animation:none;
      background:color-mix(in srgb,currentColor 8%,transparent)}
    .sc-placeholder-error{padding:4px 8px;font:11px/1.4 ui-monospace,monospace;
      color:color-mix(in srgb,currentColor 70%,transparent);word-break:break-word}
    .sc-interp.sc-missing{display:inline-block;width:2em;height:1em;overflow:hidden;
      vertical-align:text-bottom;background:rgba(255,255,255,.3);border:1px solid rgba(0,0,0,.5);
      border-radius:2px;box-sizing:border-box;color:transparent;
      user-select:none}
    .sc-interp.sc-unresolved{font-family:ui-monospace,monospace;font-size:.85em;
      color:color-mix(in srgb,currentColor 50%,transparent);
      background:color-mix(in srgb,currentColor 10%,transparent);border-radius:3px;
      padding:0 3px}
    .sc-host.sc-has-error{position:relative}
    .sc-logic-error{position:absolute;top:8px;left:8px;z-index:2147483647;max-width:60ch;
      padding:6px 10px;background:#b00020;color:#fff;font:12px/1.4 ui-monospace,monospace;
      border-radius:4px;white-space:pre-wrap;pointer-events:none}
    /* Mirrors PRINT_BASELINE_CSS in apps/web deck-stage-export.ts — keep both
       in sync until dc-runtime regains a build step. */
    @media print {
      @page { margin: 0.5cm; }
      figure, table { break-inside: avoid; }
      #dc-root, #dc-root > .sc-host { height: auto; }
      *, *::before, *::after {
        print-color-adjust: exact; -webkit-print-color-adjust: exact;
        backdrop-filter: none !important; -webkit-backdrop-filter: none !important;
        animation-delay: -99s !important; animation-duration: .001s !important;
        animation-iteration-count: 1 !important; animation-fill-mode: both !important;
        animation-play-state: running !important; transition-duration: 0s !important;
      }
    }
  
x-dc{display:none!important}

/**
 * cc-tokens.css — the shared token layer, one copy for every drawing (brief 119, drafted by Claude Code, 15 Sep 2026).
 *
 * Step 1 of Ryan's trial (D1 A, then his "A" on 15 Sep): these are CC Shell Header's own token lines, moved here
 * verbatim, byte for byte, and the header now links this file instead of declaring them. Nothing else links it yet.
 * Once Ryan has reviewed the header in the editor, the other drawings link it too and their own copies go.
 * ⚠️ 16 names carry two or three values across the drawings today (--ground, --surface, --rule, --edge, --stroke,
 * --caption, --quiet, --meta, --lede, --ink, --loud, --gutter and four --accent-* steps); those are settled with
 * design before a second drawing links this file, never picked silently here.
 */

:root { --gutter-window:clamp(16px, 3.5443cqw + 2.18px, 44px); --gutter:var(--gutter-window); --space-apart:24px; --space-inset:16px; --space-bound:8px; --space-block:44px; --space-tight:4px; } /* ⭐ DECLARED brief 84 §2 — this drawing's own line, no longer an injection (was brief 48 A1). Transcribed from FOUNDATION: spacing and measure. ⭐ brief 86 §1 — --gutter's published value now lives in --gutter-window and --gutter reads it; same computed value, no second copy of the clamp, and the measure override on the chrome root has a name to reference. */
:root { --type-close-esc:10.5px; } /* ⭐ brief 62 §2 — published: off both --type-label (9.504px/400/.14em) and --type-micro (9.5px/400/.06em), a real third mono-caps size, not a rounding of either. */
:root { --ground:#0C0F12; --surface:#14171B; --panel:#1C2028; --rule:#272A2F; --caption:#7B8187; --quiet:#8E949C; --ink:#D6D9DE; --loud:#F5F7F9; } /* ⭐ DECLARED brief 84 §1 — this drawing's own line, no longer an injection (was brief 47 A1). Transcribed from FOUNDATION's neutral ramp. */
:root { --edge:#3F4348; } /* ⭐ brief 120 Part 3 (row 1977; Claude Code, 15 Sep, Ryan's A): CC Shell Header's search-overlay close button paints var(--edge) and nothing declared it. #3F4348 is the value the site has shipped since 11 Sep, and CC: Loadout's own ramp carries it. One of the 16 two-valued names brief 119 settles before a second drawing links this file. */
:root { --meta:#A4AAB1; } /* Declared once here (Ryan's yes, 17 Sep 2026). Every other drawing that paints var(--meta) declares this same #A4AAB1, so none of them changes. CC: Gathering declared none after linking this file, so its meta text lost its colour; this restores the value the site ships. */


/* ⛔ REALM IS INHERITED, NEVER A PROP — tokens.css §48.11, ruled 15 Aug. What follows is a
   TRANSCRIPT of the token layer so this component draws standalone, keyed to `data-realm` on
   an ANCESTOR, which is the only thing that may set a realm. ⭐ SiteHeader declares no accent
   value of its own and takes no realm: the second ladder, and REALMS[].hue with it, is gone. */
:root, [data-realm] {
  --accent-hue-oklch: 90;
  --accent-wash:  oklch(0.222 0.028 var(--accent-hue-oklch));
  --accent-ring:  oklch(0.300 0.060 var(--accent-hue-oklch));
  --accent-rule:  oklch(0.450 0.090 var(--accent-hue-oklch));
  --accent-base:  oklch(0.750 0.125 var(--accent-hue-oklch));
  --accent-press: oklch(0.660 0.125 var(--accent-hue-oklch));
  --accent-lift:  oklch(0.860 0.055 var(--accent-hue-oklch));
  --chrome-gold:  oklch(0.750 0.125 90);
  /* Facts ABOUT a realm, never the page's cast — the class matrix and the result chip.
     ⭐ brief 88 §1 — and, from today, the realm SELECTOR's matched set: it names the realm the
     reader chose, which need not be the realm the page is cast in. */
  --realm-arthurian: oklch(0.750 0.125  25);
  --realm-tuatha:    oklch(0.750 0.125 160);
  --realm-viking:    oklch(0.750 0.125 250);
  /* ⚠️ brief 88 §1, MY ONE DEVIATION FROM THE WORDING, declared. The amendment says the divider
     hairline takes --realm-*, but that is the ladder's BASE step (L 0.750 / C 0.125) and the
     seam was drawn at its RING step (--accent-ring, L 0.300 / C 0.060) — a 1px full-chroma line
     across the whole window is not a hairline, it is a rule. These three are the ring step at
     each realm's hue, transcribed off the same ladder --accent-ring comes from, so the seam
     takes the CHOSEN realm as ruled and keeps the weight it was drawn at. ⏳ To take the
     wording literally instead, point the seam at --realm-* and delete these three. */
  --realm-ring-arthurian: oklch(0.300 0.060  25);
  --realm-ring-tuatha:    oklch(0.300 0.060 160);
  --realm-ring-viking:    oklch(0.300 0.060 250);
}
[data-realm="arthurian"]        { --accent-hue-oklch:  25; }
[data-realm="tuatha-de-danann"] { --accent-hue-oklch: 160; }
[data-realm="viking"]           { --accent-hue-oklch: 250; }

/* Failure: the failed-link underline and the notice edge. Every drawing already paints
   var(--danger, oklch(0.660 0.170 22)); declared once here (Ryan, 15 Sep 2026). */
:root { --danger: oklch(0.660 0.170 22); }


  /* ══ brief 100 §2 · THIS PAGE'S TWO CONTROLS, IN CSS ══════════════════════════════════════
     The view toggle is a radio pair and the recipe tree is nested <details>. Everything below
     is a pseudo-state or a state read off another element with :has() — the only two things
     that cannot be an inline style. ⛔ And neither pane may carry an inline display: an inline
     value outranks these rules, which is the whole reason they are here. */
  [data-cc-joint] input[data-cc-native] { position:absolute; width:1px; height:1px; opacity:0; margin:0; pointer-events:none; }
  [data-cc-joint] [data-cc-view] { background:#12161a; color:var(--quiet); }
  /* brief 95 §2 · hover goes to the SELECTED ground, so the hover shows the press's outcome. */
  [data-cc-joint] [data-cc-view]:hover { background:#2b3138; color:var(--loud); }
  /* The selected half takes no pointer: it is already the view you are looking at, and hover is
     a promise that a press changes something. */
  [data-cc-joint] [data-cc-view]:has(input:checked) { background:#2b3138; color:var(--loud); pointer-events:none; }
  [data-cc-joint] [data-cc-view]:has(input:focus-visible) { outline:2px solid var(--stroke, #696E74); outline-offset:2px; }

  [data-cc-joint] [data-cc-pane] { display:none; }
  [data-cc-joint]:has([data-cc-view="recipe"] input:checked) [data-cc-pane="recipe"] { display:block; }
  [data-cc-joint]:has([data-cc-view="places"] input:checked) [data-cc-pane="places"] { display:block; }

  /* The tree. The marker goes; the caret the page already drew is the disclosure, and it turns. */
  [data-cc-joint] details[data-cc-branch] > summary { list-style:none; }
  [data-cc-joint] details[data-cc-branch] > summary::-webkit-details-marker { display:none; }
  [data-cc-joint] details[data-cc-branch][open] > summary [data-cc-twist] { transform:rotate(180deg); }


  :root { --gutter:clamp(16px, 3.5443cqw + 2.18px, 44px); --section:clamp(44px, 5.5696cqw + 22.28px, 88px); } /* ⭐ DECLARED brief 84 §2 — this drawing's own line, no longer an injection (was brief 48 A1). Transcribed from FOUNDATION: spacing and measure. */
  /* The published accent ladder, declared ONCE so the file references the TOKEN rather than
     re-typing its expression. L and C live here and nowhere else; --accent-hue-oklch is the
     only number a realm sets. ⛔ No literal fallback anywhere — an undeclared hue must fail
     loudly, because silently drawing 160 renders an Arthurian page Tuatha green and nothing
     objects. Declared on :root AND [data-realm] together: a ladder declared only upstream
     resolves against the upstream hue and inherits the RESULT, so a descendant realm flip
     would not move it. */

  body { margin:0; background:var(--ground); color:var(--ink); font-family:'Geist', system-ui, sans-serif; -webkit-font-smoothing:antialiased; }
  * { box-sizing:border-box; }
  a { color:var(--accent-base); text-decoration:none; }
  a:hover { color:var(--accent-lift); }

  /* ⭐ 22 Sep · MOBILE PAIR 18 — PHONE ONLY, below 640 of container, the width at which this
     band's Source, Where and Used in tracks already clamp to nought. This is the band the whole
     item page exists for, and on a phone every rung of it was a 19–23px target stacked a few
     pixels from the next — on 1,063 pages.
     ⛔ The OVERFLOW claimed here on the first pass is withdrawn (22 Sep): it was our probe
     reading past a clipped parent, not the page. What the band does lose at 390 is its second
     column — the rung becomes Qty plus Item, so where an input comes from is carried by indent
     alone. So below 640 the rung stops being a grid: Qty, plate and name on line 1, Source and
     Where on line 2 under the name, which buys that back. The row's own inset goes to 0 so the
     nesting indent has the width to say what it means; the caret stays the platform's
     disclosure, and at 60px the ingredient link and the twist are separate targets. */
  @container (max-width: 640px) {
    [data-cc-chainhead] { display:none !important; }
    [data-cc-joint] summary {
      grid-template-columns:44px auto minmax(0,1fr) !important;
      row-gap:var(--space-tight);
      min-height:60px;
      padding-left:0 !important; padding-right:0 !important;
    }
    [data-cc-joint] summary > span:nth-child(1) { grid-column:1; grid-row:1; }
    [data-cc-joint] summary > span:nth-child(2) { grid-column:2 / -1; grid-row:1; }
    [data-cc-joint] summary > span:nth-child(3) { grid-column:2; grid-row:2; }
    [data-cc-joint] summary > span:nth-child(4) { grid-column:3; grid-row:2; padding-left:var(--space-bound) !important; }
    /* Used in is the one cell that does not come back: it is a count about somewhere else, and
       the rung's own two facts are what the reader lost. */
    [data-cc-joint] summary > span:nth-child(5) { display:none; }
    [data-cc-joint] summary a { display:flex; align-items:center; min-height:44px; white-space:normal !important; }
    /* ⛔ 23 Sep · criterion 24 — "Coal" (31.2) and "Salt", CLASSIFIED rather than assumed: measured
       on the built page, each is the name link of a recipe-tree row whose parent is a flex span and
       whose only siblings are the 44px plate and the node-info block. No running text surrounds it,
       so it is a standalone row link, and a standalone link is 44 × 44. */
    [data-cc-joint] summary a { min-width:44px; }
  }

  /* ⛔ 23 Sep · CONTRACT-MobileApply-22SEP.md criterion 14 — THE TWO GROUPS PAIR 18 DID NOT REACH.
     Pair 18 is scoped to `[data-cc-joint] summary a`, and its own comment says "Used in is the one
     cell that does not come back" — so "What it goes into" and the view tabs kept the sizes the
     first pass measured. Both were re-measured on the built page at 390, not read off the drawing:
     · the reverse index's 10 name links at 166 × 19. Severity was tested rather than assumed: the
       row is 358 × 57, but a tap 31px below the link's top, inside the row and outside the link,
       does nothing, while a tap on the 19px link navigates. The 19px link really was the only
       target. It becomes a 44-tall flex line, which carries its wrapper — and therefore the
       ItemCard overlay mounted at `inset:0` on that wrapper, the round's other named 10 (214 × 40)
       — up with it. One rule, both groups.
     · the two view tabs. The radios themselves are the 1 × 1 `opacity:0` inputs Pair 18 leaves
       alone; what a thumb actually lands on is the label that styles them, and that was 38 tall.
       Class Index's realm radios already reach 44 this way. */
  @container (max-width: 640px) {
    [data-screen-label="Used in"] [data-cc-cell="usedname"] {
      display:flex; align-items:center; min-height:44px; white-space:normal !important;
    }
    [data-cc-joint] [data-cc-view] { min-height:44px; }
  }


  /* ⭐ brief 119, 15 Sep 2026 — the token lines that stood here (spacing, --type-close-esc, the neutral ramp, and the realm-keyed accent ladder with its three realm selectors) moved verbatim to ./cc-tokens.css, linked above. Values unchanged. */
  /* ⛔ NOT a bare `a` selector. A helmet stylesheet is global and this component is
     IMPORTED, so a bare rule here outranks the host page's own by mount order and decides
     link colour for every link on the page. Scoped to this component's own root instead. */
  [data-cc-chrome="header"] a { color:var(--ink); text-decoration:none; }
  [data-cc-chrome="header"] a:hover { color:var(--loud); }

  /* ⛔ caret-color was --chrome, which is the focus ring and only the focus ring. Removed:
     the field's caret is currentColor, which is --loud, the ink already in the box. */
  input.cc-q { all:unset; flex:1 1 auto; min-width:0; font-family:'Geist', system-ui, sans-serif; color:var(--loud); }
  input.cc-q::placeholder { color:#A4AAB1; }
  /* ⛔ The search field carries NO ring and NO border in any state — ground and ink only.
     ⭐ AND THE SEARCH BAR IS THE WHOLE ROW: everything above the divider is one object, so
     the ground change belongs to the row, not to a box inside it. A 564-wide well sitting in
     a wider row drew exactly the edge the no-border rule exists to avoid — it just drew it
     in ground instead of in stroke. The measure governs the RESULTS below the divider; the
     bar itself is full-bleed, and its close affordance is part of it.
     `all:unset` does not remove the UA focus outline, so focus was also drawing a bright box
     around the flex area. Now: focus deepens the row and lifts the placeholder to --lede. */
  input.cc-q:focus, input.cc-q:focus-visible { outline:none; box-shadow:none; }
  /* ⭐ brief 61 §5 — was raw #080A0D. Now the published --state-recess relation: a flat
     30% black veil over whatever ground sits beneath, same shape as the hover lift. */
  [data-searchrow]:focus-within { background:color-mix(in srgb, black 30%, var(--ground)) !important; }
  [data-searchrow]:focus-within input.cc-q::placeholder { color:#C7CCD1; }

  /* ── the chrome's own four rules · sweep, 16 Aug ─────────────────────────────────
     ⭐ ONE rule each for the button reset, the tint, the ring and the guard. Written
     here rather than inline because the alternative is 16 decisions in this file and 161
     across the corpus, and because a per-element hover is 16 places for the next one to
     drift. ⛔ This is the only thing in the file that could not be an inline style. */
  [data-cc-chrome="header"] {
    --chrome:#CFD6DE; --focus-ring-width:2px; --focus-ring-offset:2px;
    --motion-tint:160ms; --motion-settle:260ms; --motion-drift:420ms;
  }
  /* ⛔⛔ The two layout groups are collapsed to 0 by a clamp and clipped, which hides them
     from the EYE and not from the TAB ORDER — harmless while they were spans, a defect the
     moment they became real controls. A phone reader would tab seven invisible desktop
     controls, Sign in and the search trigger among them, before reaching anything drawn.
     ⭐ visibility:hidden takes them out of the tab order and the a11y tree; the clamp still
     owns the layout, so no dimension moves. Two queries, not fourteen attributes. */
  @container (max-width: 899.98px) { [data-cc-chrome="header"] [data-cc-group="desktop"] { visibility:hidden; } }
  @container (min-width: 900px)    { [data-cc-chrome="header"] [data-cc-group="mobile"]  { visibility:hidden; } }

  /* ⛔ 23 Sep · CONTRACT-MobileApply-22SEP.md criterion 21 — ONE SHAPE, SWEPT, NOT ONE INSTANCE.
     Pair 01 made the mark's anchor a 44-tall flex box below 900 with every size term clamped to 0
     above it — and left `display:flex; align-items:center` unconditional. Above 900 the box stays
     39.08 × 24 either way, which is why pass 2 could only declare it an exception rather than call it
     a defect; but it is the same shape as criterion 16's back link and criterion 20's name links,
     and the sweep scopes every instance of the shape rather than excusing the ones that happen to
     paint nothing. The anchor keeps main's `display:block`, and flex moves in here — both
     declared in this sheet and neither inline, because an inline `display` would outrank the query. */
  [data-cc-chrome="header"] [data-cc-logolink] { display:block; }
  @container (max-width: 899.98px) { [data-cc-chrome="header"] [data-cc-logolink] { display:flex; align-items:center; } }

  [data-cc-chrome="header"] button {
    appearance:none; -webkit-appearance:none; background:none; border:0; margin:0;
    padding:0; font:inherit; color:inherit; text-align:left;
  }
  /* tint · 160ms ease. ⛔ Colour only — the chrome draws no settle, drift or ambient. */
  [data-cc-chrome="header"] a,
  [data-cc-chrome="header"] button {
    transition: color var(--motion-tint) ease, background-color var(--motion-tint) ease;
  }
  /* ⭐ Focus DRAWN as a state rather than left to the standard.
     ⛔ `input:focus-visible` WAS in this list, on the reasoning that `all:unset` had removed
     the field's ring and the ring had to come back. Removed 15 Aug: the search bar's states
     are ground and ink only, so the ring is not missing from it — it is refused by it. Links
     and buttons keep the ring; they have no ground of their own to deepen. */
  [data-cc-chrome="header"] a:focus-visible,
  [data-cc-chrome="header"] button:focus-visible {
    outline: var(--focus-ring-width) solid var(--chrome);
    outline-offset: var(--focus-ring-offset);
  }
  /* ⛔ The guard, keyed to the same three names. tint KEEPS — a colour change is not
     motion, and dropping it takes feedback away and gives nothing back. settle and drift
     lose their geometry, ambient stops. Declared although the chrome draws none of those
     three, so the next thing added here inherits the contract instead of inventing one. */
  @media (prefers-reduced-motion: reduce) {
    [data-cc-chrome="header"] [data-motion="settle"],
    [data-cc-chrome="header"] [data-motion="drift"] { transform:none; transition-property:color, background-color; }
    [data-cc-chrome="header"] [data-motion="ambient"] { animation:none; }
  }

  /* ══ brief 100 §2 · THE BROWSER RUNS THIS CHROME NOW ═══════════════════════════════════
     Five controls used to be five pieces of component state (menu, drawer, search, scope) and
     a document keydown listener. They are now the platform's: `popover` for the four menus,
     the drawer and the search overlay; `<details>` for the drawer's two expanding sections;
     a radio group for the search scope; `:placeholder-shown` for typed-vs-resting. Escape,
     outside-click dismiss, one-open-at-a-time and the invoker's aria-expanded all arrive from
     the standard. ⛔ This block is the only thing in the file that could not be inline: every
     rule here is either a pseudo-state or a state read off a DIFFERENT element with :has().

     ⚠️ ONE DECLARED DIFFERENCE. A popover is painted in the TOP LAYER, so its containing block
     is the window and not this component's query container. Its edge is therefore drawn off
     --cc-edge (the same clamp in vw) rather than --gutter (cqw). In the build the bar spans the
     window and the two are the same number; in a narrow preview harness the panels take the
     window's edge while the bar takes the harness's. Named rather than hidden. */
  [data-cc-chrome="header"] {
    --cc-edge: max(clamp(16px, 3.5443vw + 2.18px, 44px), (100vw - 1180px) / 2);
    --cc-bar-bottom: 60px;               /* ribbon 3 + bar 56 + seam 1 */
  }
  /* The ribbon is a prop, so the drop is read off the ribbon's PRESENCE, not off a hole. */
  [data-cc-chrome="header"]:not(:has([data-cc-ribbon])) { --cc-bar-bottom: 57px; }

  [data-cc-chrome="header"] [popover] { margin:0; border:0; padding:0; color:var(--ink); }
  /* ⛔ No scrim. The chrome never drew one, and a popover brings a default backdrop. */
  [data-cc-chrome="header"] [popover]::backdrop { background:transparent; }
  [data-cc-chrome="header"] [data-cc-pop] {
    /* inset:auto first — the UA sheet sets inset:0 on every popover, and an over-constrained
       left+right+width resolves to the left edge whatever `right` says. */
    position:fixed; inset:auto; top:var(--cc-bar-bottom); z-index:50;
    background:var(--surface); max-height:calc(100dvh - var(--cc-bar-bottom)); overflow-y:auto;
  }
  /* ⚠️ Each side names BOTH horizontal offsets. A popover with left AND right set is
     over-constrained and the browser keeps the start edge, which is how a right-hung menu
     first drew itself against the left gutter — the UA sheet's inset:0 is on the element too
     and one `inset:auto` earlier in the block was not enough to clear it. */
  [data-cc-chrome="header"] [data-cc-pop="left"]  { left:calc(var(--cc-edge) - 16px); right:auto; }
  [data-cc-chrome="header"] [data-cc-pop="right"] { right:calc(var(--cc-edge) - 16px); left:auto; }
  [data-cc-chrome="header"] [data-cc-pop="wide"]  { left:0; right:auto; width:100vw; }
  /* One declaration rather than fifty edits: inside a top-layer panel --gutter IS --cc-edge, so
     every edge the panels already drew off --gutter keeps its name and changes its measure. */
  [data-cc-chrome="header"] [popover] { --gutter: var(--cc-edge); }

  /* ══ 11 Sep, Ryan · THE TWO BAR MENUS OPEN ON HOVER, AND CLASSES IS A LINK ════════════════
     Classes and the realm chooser are not press-to-open menus: the pointer arrives and they
     come down. That rules out `popover`, which only opens on invocation — so these two panels
     are plain fixed panels shown by :hover and :focus-within, read off the chrome root with
     :has(). The panel stays open while the pointer is inside it because it is a DESCENDANT of
     nothing it needs to be: the rule tests the panel's own hover as a second condition.
     ⭐ A press on Classes now GOES TO /classes — it is an <a>, and the menu is what hover adds.
     ⚠️ position:fixed, not absolute: the desktop nav group clips (overflow:hidden), and the
     chrome root's container-type makes it the containing block for fixed children, so the panel
     hangs off the root and the group cannot cut it. Its top edge is the bar's bottom edge with
     no gap, which is what lets the pointer travel from the opener into the panel.
     ⛔ The search overlay, the account menu and the mobile drawer stay popovers: those are
     press-to-open, and Escape plus light dismiss is exactly what they want. */
  /* ⚠️ 11 Sep, Ryan · THE BRIDGE, and it is the whole reason the panel is two elements. The
     opener is a 44px box centred in a 56px bar, so its bottom edge sits ~7px above the bar's —
     and the panel began at the bar's bottom. Between the two was a dead band where neither was
     hovered, so the menu closed on the way down to it. The PANEL is now a transparent box that
     starts 10px higher and pads that 10px back; its inner box is the surface the reader sees.
     The hover regions therefore overlap and the drawn edge does not move. ⛔ The bridge cannot
     be a ::before or a negative-top child: the scrolling box would clip it, which is why the
     scroll and the ground moved to the inner element. */
  [data-cc-chrome="header"] [data-cc-panel] {
    display:none; position:fixed; inset:auto; z-index:50;
    top:calc(var(--cc-bar-bottom) - 10px); padding-top:10px;
    background:transparent; --gutter: var(--cc-edge);
  }
  [data-cc-chrome="header"] [data-cc-panel-inner] {
    background:var(--surface); max-height:calc(100dvh - var(--cc-bar-bottom)); overflow-y:auto;
  }
  [data-cc-chrome="header"] [data-cc-panel="classes"] { left:calc(var(--cc-edge) - 16px); right:auto; }
  [data-cc-chrome="header"] [data-cc-panel="realm"]   { right:calc(var(--cc-edge) - 16px); left:auto; }
  /* ⭐ brief 101 §1.8 · the account menu joins them, right-aligned to the same edge. */
  [data-cc-chrome="header"] [data-cc-panel="account"] { right:calc(var(--cc-edge) - 16px); left:auto; }
  [data-cc-chrome="header"]:has([data-cc-opener="account"]:hover)        [data-cc-panel="account"],
  [data-cc-chrome="header"]:has([data-cc-opener="account"]:focus-visible) [data-cc-panel="account"],
  [data-cc-chrome="header"]:has([data-cc-panel="account"]:hover)         [data-cc-panel="account"],
  [data-cc-chrome="header"]:has([data-cc-panel="account"]:focus-within)  [data-cc-panel="account"],
  [data-cc-chrome="header"]:has([data-cc-opener="classes"]:hover)        [data-cc-panel="classes"],
  [data-cc-chrome="header"]:has([data-cc-opener="classes"]:focus-visible) [data-cc-panel="classes"],
  [data-cc-chrome="header"]:has([data-cc-panel="classes"]:hover)         [data-cc-panel="classes"],
  [data-cc-chrome="header"]:has([data-cc-panel="classes"]:focus-within)  [data-cc-panel="classes"],
  [data-cc-chrome="header"]:has([data-cc-opener="realm"]:hover)          [data-cc-panel="realm"],
  [data-cc-chrome="header"]:has([data-cc-opener="realm"]:focus-visible)  [data-cc-panel="realm"],
  [data-cc-chrome="header"]:has([data-cc-panel="realm"]:hover)           [data-cc-panel="realm"],
  [data-cc-chrome="header"]:has([data-cc-panel="realm"]:focus-within)    [data-cc-panel="realm"] { display:block; }

  /* The two caret states of the Classes opener, and the drawer opener's two words. Both used to
     be a pair of sc-ifs on component state; both are drawn once now and chosen by CSS.
     ⛔ AND NEITHER CARET MAY CARRY AN INLINE `display`. One did, and an inline display outranks
     the rule that hides it — which is why the open menu drew both arrows at once. */
  [data-cc-chrome="header"] [data-cc-caret="down"] { display:block; }
  [data-cc-chrome="header"] [data-cc-caret="up"]   { display:none; }
  [data-cc-chrome="header"]:has([data-cc-opener="classes"]:hover)       [data-cc-opener="classes"] [data-cc-caret="down"],
  [data-cc-chrome="header"]:has([data-cc-panel="classes"]:hover)        [data-cc-opener="classes"] [data-cc-caret="down"],
  [data-cc-chrome="header"]:has([data-cc-panel="classes"]:focus-within) [data-cc-opener="classes"] [data-cc-caret="down"] { display:none; }
  [data-cc-chrome="header"]:has([data-cc-opener="classes"]:hover)       [data-cc-opener="classes"] [data-cc-caret="up"],
  [data-cc-chrome="header"]:has([data-cc-panel="classes"]:hover)        [data-cc-opener="classes"] [data-cc-caret="up"],
  [data-cc-chrome="header"]:has([data-cc-panel="classes"]:focus-within) [data-cc-opener="classes"] [data-cc-caret="up"]   { display:block; }
  [data-cc-chrome="header"] [data-cc-drawer-word="close"] { display:none; }
  [data-cc-chrome="header"]:has(#cc-drawer:popover-open) [data-cc-drawer-word="menu"]  { display:none; }
  [data-cc-chrome="header"]:has(#cc-drawer:popover-open) [data-cc-drawer-word="close"] { display:inline; color:var(--loud); }

  /* THE SEARCH OVERLAY'S TWO HALVES. Resting is an empty field, which the browser already
     knows: :placeholder-shown. So both halves are in the drawn page and CSS picks, with no
     render pass and no state — and a reader who types with no engine running still crosses
     from one to the other. ⛔ The RESULTS inside the typed half are a fetch, so they stay the
     build's (§7); this rule only decides which half is on screen.

     ⛔ AND NOT ONE OF THESE DISPLAY VALUES MAY BE INLINE. An inline `display` outranks the UA
     stylesheet's `[popover]:not(:popover-open) { display:none }`, so a popover carrying its own
     inline display is a panel that is permanently open — which is exactly how the first cut of
     this pass drew the search overlay. Every display that participates in an open/closed or
     either/or state therefore lives in this block, and the inline styles keep the rest. */
  #cc-search:popover-open { display:flex; flex-direction:column; }
  #cc-search [data-cc-when="typed"]   { display:contents; }
  #cc-search [data-cc-when="resting"] { display:block; }
  #cc-search:has(input.cc-q:placeholder-shown)      [data-cc-when="typed"]   { display:none; }
  #cc-search:not(:has(input.cc-q:placeholder-shown)) [data-cc-when="resting"] { display:none; }

  /* THE SCOPE CHIPS ARE A RADIO GROUP. The pressed chip is :checked, so the ground and the ink
     are a rule rather than two holes, and the "Search All Realms Instead" escape is a <label>
     pointing at the first radio — a control that changes state with no handler at all. */
  [data-cc-chrome="header"] input[data-cc-native] {
    position:absolute; width:1px; height:1px; opacity:0; margin:0; pointer-events:none;
  }
  #cc-search [data-cc-scope] { background:transparent; color:var(--quiet); }
  #cc-search [data-cc-scope]:hover { color:var(--loud); }
  #cc-search [data-cc-scope]:has(input:checked) { background:var(--ground); color:var(--loud); }
  #cc-search [data-cc-scope="realm"]:has(input:checked) { color:var(--accent-base); }
  #cc-search [data-cc-scope]:has(input:focus-visible) {
    outline: var(--focus-ring-width) solid var(--chrome); outline-offset: var(--focus-ring-offset);
  }
  /* The widen escape is pointless once the scope is already all realms — it was a `display`
     hole read off state, and it is now the same fact read off the radio. */
  #cc-search:has(#cc-scope-all:checked) [data-cc-widen] { display:none; }

  /* ⭐ brief 115 §2 · THE RESULT CHIP TAKES ITS OWN REALM'S HUE. The pattern used to pin every
     chip to var(--chrome-gold) and let the BUILD print only the word — so a Viking result's
     chip read the right word in the wrong colour. data-cc-result-realm is the marked part the
     build sets per row ("arthurian" | "tuatha" | "viking" | "" for no realm), and this is the
     only place the colour is decided. */
  #cc-search [data-cc-result-chip] { color:var(--chrome-gold); }
  #cc-search [data-cc-result-chip][data-cc-result-realm="arthurian"] { color:var(--realm-arthurian); }
  #cc-search [data-cc-result-chip][data-cc-result-realm="tuatha"] { color:var(--realm-tuatha); }
  #cc-search [data-cc-result-chip][data-cc-result-realm="viking"] { color:var(--realm-viking); }

  /* THE DRAWER'S TWO EXPANDING SECTIONS are <details>. The marker goes; the caret the drawing
     already drew stays, and turns on [open]. */
  #cc-drawer details > summary { list-style:none; cursor:pointer; }
  #cc-drawer details > summary::-webkit-details-marker { display:none; }
  #cc-drawer details > summary:hover { background:var(--ground); }
  #cc-drawer details[open] > summary [data-cc-caret="down"] { transform:rotate(180deg); }

  /* ══ brief 102 · SIGNED IN/OUT AND THE READER'S REALM ARE ROOT ATTRIBUTES, NOT PROPS ═══════
     Both are decided when the page is READ, so both versions of everything they touch are drawn
     and one attribute on :root (the document, not this component) picks. Other reading pages —
     the class ladder's offer, the crafting index CTA, Home — read the SAME two attributes, which
     is why they live above this component rather than on its own root.
     ⛔ data-cc-reader-realm is never data-realm: that attribute is the page's own cast (brief 87)
     and a page never reads its own cast as the reader's choice.
     ⭐ Every element that carries an inline `display` already (the sign-in control and the
     avatar are inline-flex by default) needs !important to win here — that is the one place
     this stylesheet uses it outside the published --state-recess exception, and for the same
     reason: an inline value always outranks an external rule otherwise. */
  :root[data-cc-account="in"] [data-cc-chrome="header"] [data-cc-signed="out"] { display:none !important; }
  :root:not([data-cc-account="in"]) [data-cc-chrome="header"] [data-cc-signed="in"] { display:none !important; }
  :root:not([data-cc-account="in"]) [data-cc-chrome="header"] [data-cc-panel="account"] { display:none !important; }

  /* THE REALM WORD, EVERYWHERE IT APPEARS. `data-cc-rw` marks a run of text that depends on the
     reader's realm — the bar's opener, the drawer's Realm summary, the drawer's Classes hint —
     so one rule serves every site the word is drawn, and none of them computes a string. */
  [data-cc-chrome="header"] [data-cc-rw] { display:none; }
  :root:not([data-cc-reader-realm]) [data-cc-chrome="header"] [data-cc-rw=""] { display:inline; }
  :root[data-cc-reader-realm="arthurian"] [data-cc-chrome="header"] [data-cc-rw="arthurian"],
  :root[data-cc-reader-realm="tuatha-de-danann"] [data-cc-chrome="header"] [data-cc-rw="tuatha-de-danann"],
  :root[data-cc-reader-realm="viking"] [data-cc-chrome="header"] [data-cc-rw="viking"] { display:inline; }
  /* The opener's ink and the seam under the bar take the SAME attribute as a colour rather than
     a second copy of a word — there is no text to duplicate, so this is the one site the switch
     stays a value instead of a set of spans. */
  [data-cc-chrome="header"] [data-cc-realm-ink] { color:var(--quiet); }
  [data-cc-chrome="header"] [data-cc-seam] { height:1px; background:var(--rule); }
  :root[data-cc-reader-realm="arthurian"] [data-cc-chrome="header"] [data-cc-realm-ink] { color:var(--realm-arthurian); }
  :root[data-cc-reader-realm="tuatha-de-danann"] [data-cc-chrome="header"] [data-cc-realm-ink] { color:var(--realm-tuatha); }
  :root[data-cc-reader-realm="viking"] [data-cc-chrome="header"] [data-cc-realm-ink] { color:var(--realm-viking); }
  :root[data-cc-reader-realm="arthurian"] [data-cc-chrome="header"] [data-cc-seam] { background:var(--realm-ring-arthurian); }
  :root[data-cc-reader-realm="tuatha-de-danann"] [data-cc-chrome="header"] [data-cc-seam] { background:var(--realm-ring-tuatha); }
  :root[data-cc-reader-realm="viking"] [data-cc-chrome="header"] [data-cc-seam] { background:var(--realm-ring-viking); }

  /* THE CLASS MENU IS ONE MATRIX, ALWAYS — three columns, all 21 names, never a second copy of
     the data keyed to a realm. A chosen realm narrows it to one column and adds the way back to
     /classes; nothing here is content, only which cells and which width. */
  [data-cc-chrome="header"] [data-cc-panel-inner="classes"] { width:560px; }
  :root[data-cc-reader-realm] [data-cc-chrome="header"] [data-cc-panel-inner="classes"] { width:360px; }
  :root[data-cc-reader-realm] [data-cc-chrome="header"] [data-cc-mrow] { grid-template-columns:96px minmax(0,1fr) !important; }
  :root[data-cc-reader-realm="arthurian"] [data-cc-chrome="header"] [data-cc-mcol="tuatha-de-danann"],
  :root[data-cc-reader-realm="arthurian"] [data-cc-chrome="header"] [data-cc-mcol="viking"],
  :root[data-cc-reader-realm="tuatha-de-danann"] [data-cc-chrome="header"] [data-cc-mcol="arthurian"],
  :root[data-cc-reader-realm="tuatha-de-danann"] [data-cc-chrome="header"] [data-cc-mcol="viking"],
  :root[data-cc-reader-realm="viking"] [data-cc-chrome="header"] [data-cc-mcol="arthurian"],
  :root[data-cc-reader-realm="viking"] [data-cc-chrome="header"] [data-cc-mcol="tuatha-de-danann"] { display:none; }
  [data-cc-chrome="header"] [data-cc-classes-exit] { display:none; }
  :root[data-cc-reader-realm] [data-cc-chrome="header"] [data-cc-classes-exit] { display:block; }

  /* THE DRAWER'S CLASS LIST IS THE SAME TRIO, ALWAYS, narrowed to one link the same way, so
     /classes' full 21 and a realm's 7 are one piece of markup rather than two. */
  :root[data-cc-reader-realm="arthurian"] [data-cc-chrome="header"] [data-cc-drawer-cell]:not([data-cc-drawer-cell="arthurian"]),
  :root[data-cc-reader-realm="tuatha-de-danann"] [data-cc-chrome="header"] [data-cc-drawer-cell]:not([data-cc-drawer-cell="tuatha-de-danann"]),
  :root[data-cc-reader-realm="viking"] [data-cc-chrome="header"] [data-cc-drawer-cell]:not([data-cc-drawer-cell="viking"]) { display:none; }

  /* THE REALM PICKER'S OWN CURRENT MARK reads the live attribute, not the value baked at save,
     so picking a realm from this exact menu moves the mark with no reload. "" is All Realms. */
  [data-cc-chrome="header"] [data-cc-realm-row] { background:transparent; }
  :root:not([data-cc-reader-realm]) [data-cc-chrome="header"] [data-cc-realm-row=""],
  :root[data-cc-reader-realm="arthurian"] [data-cc-chrome="header"] [data-cc-realm-row="arthurian"],
  :root[data-cc-reader-realm="tuatha-de-danann"] [data-cc-chrome="header"] [data-cc-realm-row="tuatha-de-danann"],
  :root[data-cc-reader-realm="viking"] [data-cc-chrome="header"] [data-cc-realm-row="viking"] { background:var(--ground); }

  /* PENDING AND FAILED, AS ATTRIBUTES ON THE CONTROL ITSELF. Pending dims the control, takes it
     out of the tab order's effect (pointer-events, not tabindex) and swaps its word to the -ing
     form drawn beside it — no JS style hole, so the look survives a save. Failed leaves the
     control alone and tints its lower edge, the same edge the header's own failure line uses. */
  [data-cc-chrome="header"] [data-cc-pending] { opacity:0.45; pointer-events:none; }
  [data-cc-chrome="header"] [data-cc-word="pending"] { display:none; }
  [data-cc-chrome="header"] [data-cc-pending] [data-cc-word="rest"] { display:none; }
  [data-cc-chrome="header"] [data-cc-pending] [data-cc-word="pending"] { display:inline; }
  [data-cc-chrome="header"] [data-cc-failed] { box-shadow:inset 0 -2px 0 0 var(--danger, oklch(0.660 0.170 22)); }


  :root { --meta:#A4AAB1; --gold:oklch(0.750 0.125 90); --gold-lift:oklch(0.860 0.055 90); }
  body { margin:0; background:#0C0F12; color:#D6D9DE; font-family:'Geist', system-ui, sans-serif; -webkit-font-smoothing:antialiased; }
  * { box-sizing:border-box; }
  a { color:oklch(0.750 0.125 90); text-decoration:none; }
  a:hover { color:oklch(0.860 0.055 90); }
  /* ⛔ 23 Sep · criterion 24 — a STANDALONE link is a control, and a control is 44 × 44 at 390 (Plan's rule, now in spec/RULINGS.md; inline links inside running prose are exempt). "Items" measured 40.2 wide, CLASSIFIED on the built item page: its parent is
     this <nav>, and its only siblings are the "/" separator and the current page's name — a
     breadcrumb row, not prose, so the parent link is a standalone control. This drawing declares
     no container of its own, so the query resolves against the page that mounts it, which is the
     measure the rest of that page's phone rules read. */
  @container (max-width: 899.98px) { [data-cc-crumbparent] { min-width:44px; } }


  :root { --hollow:#101317; --seam:#4b5259; --stroke:#696E74;
    --meta:#A4AAB1; --lede:#C7CCD1;
    --gold:oklch(0.750 0.125 90); --gold-lift:oklch(0.860 0.055 90);
    --realm-arthurian:oklch(0.750 0.125 25); --realm-tuatha:oklch(0.750 0.125 160); --realm-viking:oklch(0.750 0.125 250);
    --absent-ink:var(--quiet); --absent-line:var(--edge);
    --absent-hatch:repeating-linear-gradient(135deg, transparent 0 3px, color-mix(in oklab, var(--absent-line) 40%, transparent) 3px 4px);
    --shadow-modal:0 24px 60px rgba(0,0,0,0.6);
  }
  body { margin:0; background:var(--ground); color:var(--ink); font-family:'Geist', system-ui, sans-serif; -webkit-font-smoothing:antialiased; }
  * { box-sizing:border-box; }
  a { color:var(--gold); text-decoration:none; }
  a:hover { color:var(--gold-lift); }

  /* ══ brief 100 §2.4 / §2.6 · THE CARD OPENS IN CSS ═══════════════════════════════════════
     What this block replaces: a matchMedia listener, a resize listener, a capture-phase scroll
     listener, a document keydown listener, a getBoundingClientRect per open, and six state keys
     (open, pinned, rect, box, canHover, vw, vh). The card is a child of its own trigger now, so
     :hover and :focus-within are the whole mechanism.

     ⭐ TWO PRESENTATIONS, PICKED BY THE POINTER, in a media query rather than in JS. A fine
     pointer gets the flyout under the name; a coarse pointer gets the bottom sheet. That was
     `canHover` read from matchMedia and pushed into state on every change.
     ⭐ THE FLYOUT NO LONGER CLOSES ON SCROLL, because it no longer has to: it is positioned
     against its trigger instead of against the window, so it travels with the page.
     ⛔ NO DISPLAY, WIDTH OR POSITION MAY BE INLINE ON THE CARD. Every one of those takes part in
     an open/closed or either/or state, and an inline value outranks this block. */
  [data-cc-scrim] { display:none; position:fixed; inset:0; background:rgba(0,0,0,0.5); z-index:60; pointer-events:none; }
  [data-cc-sheet-hint] { display:none; }
  @media (hover: none) { [data-cc-card] [data-cc-sheet-hint] { display:block; } }
  /* ⭐ 22 Sep · MOBILE PAIR 07 · THE CARD READS ITS CONTAINER, NOT THE WINDOW. max-width was
     min(380px, calc(100vw − 24px)) — the right sum for a card floating over the whole window and
     the wrong one for a card in flow inside a panel, which is how /crafting, /gathering and
     /items all mount it. 100% makes it fit wherever it is mounted; width:380px still decides the
     size everywhere the container is wider than that, so no pointer-width card moves. */
  [data-cc-card]  { display:none; flex-direction:column; width:380px; max-width:100%; }
  /* A specimen mount has no trigger: the hit is display:contents and the card is just in flow. */
  [data-cc-hit="static"] > [data-cc-card] { display:flex; }

  /* ⭐ brief 105 §1 · THE MOUNT'S OWN WRAPPER TAKES NO POINTER EVENTS EITHER. dc-import wraps
     every mount in its own div (.sc-host), and an overlay mount's `style="position:absolute;
     inset:0"` lands on THAT div — so the wrapper, not the hit span the 11 Sep note fixed, was
     the thing sitting on top of the row and swallowing the press. Scoped to a wrapper that
     holds an overlay hit (never a blanket rule on .sc-host, which belongs to every import on
     the site, not just this card), so the click reaches the link or label the wrapper covers,
     on every page that mounts this card this way — including any the build mounts itself. */
  .sc-host:has(> [data-cc-hit="overlay"]) { pointer-events:none; }

  @media (hover: hover) and (pointer: fine) {
  /* ⭐ 11 Sep · AN OVERLAY MOUNT'S TRIGGER IS THE CELL IT COVERS, NOT THE COVER. The hit is a
     transparent box over a row or a table cell, and while it took pointer events it also
     swallowed the press that belongs to the thing underneath — which used to be fine only
     because the card forwarded that press in script. It takes no pointer events now, so the
     row's own label or link gets the click, and the card opens on the PARENT's hover and
     focus-within instead. One selector change, and the hit stays a box so anchor positioning
     still has something to measure against. */
    :hover > * > [data-cc-hit="overlay"] > [data-cc-card],
    :focus-within > [data-cc-hit="overlay"] > [data-cc-card],
    [data-cc-hit="inline"]:hover  > [data-cc-card],
    [data-cc-hit="inline"]:focus-within  > [data-cc-card] {
      display:flex; position:absolute; top:100%; left:0; margin-top:10px; z-index:70;
      max-height:min(560px, 68dvh); overflow-y:auto; overflow-x:hidden;
      box-shadow:var(--shadow-modal); pointer-events:none;
    }
    /* ⭐ WHERE THE BROWSER CAN FLIP A PANEL ITSELF, IT DOES. This is the exact computation the
       deleted script ran — below if it fits, else above, else pinned to the window — expressed
       as anchor positioning with try-fallbacks. It also restores fixed positioning, so a host
       cell that clips cannot clip the card. Behind @supports, because the fallback above is the
       honest floor: start-aligned under the trigger, clamped by max-width. */
    @supports (anchor-name: --cc-card) and (position-try-fallbacks: flip-block) {
      [data-cc-hit="overlay"], [data-cc-hit="inline"] { anchor-name:--cc-card; anchor-scope:--cc-card; }
      :hover > * > [data-cc-hit="overlay"] > [data-cc-card],
      :focus-within > [data-cc-hit="overlay"] > [data-cc-card],
      [data-cc-hit="inline"]:hover  > [data-cc-card],
      [data-cc-hit="inline"]:focus-within  > [data-cc-card] {
        position:fixed; position-anchor:--cc-card; position-area:block-end span-inline-end;
        top:auto; left:auto; margin:10px 0 0;
        position-try-fallbacks: flip-block, flip-inline, flip-block flip-inline;
      }
    }
  }

  /* ⚠️ COARSE POINTER · a tap focuses the trigger and the sheet comes up; a tap anywhere off it
     takes the focus away and the sheet goes. That is the whole interaction, and it is why the
     sheet's "Close" button is retired: a control inside the card's own focus subtree cannot
     take focus out of that subtree, so a Close there could only ever be script. The scrim takes
     no pointer events for the same reason — the tap has to reach the page to land the dismiss. */
  @media (hover: none) {
    :focus-within > [data-cc-hit="overlay"] > [data-cc-card],
    [data-cc-hit="inline"]:focus-within  > [data-cc-card] {
      display:flex; position:fixed; left:0; right:0; bottom:0; width:auto; max-width:none;
      z-index:70; max-height:82dvh; overflow-y:auto;
      border-left:0; border-right:0; border-bottom:0; box-shadow:var(--shadow-modal);
    }
    :focus-within > [data-cc-hit="overlay"] > [data-cc-scrim],
    [data-cc-hit="inline"]:focus-within  > [data-cc-scrim] { display:block; }

    /* ⛔ 23 Sep · CONTRACT-MobileApply-22SEP.md Addendum 5, the carried item — THE CARD'S OWN
       NAME LINK. Measured 236 × 21 on the built /crafting at 390: the card is a fixed bottom sheet
       on a coarse pointer, and this link is the ONLY way out of it to the item's own page, so it
       is a standalone row link and owes the full 44 of height. Found by share 3 and left out of
       criterion 14's named list; it rides here under Ryan's "i want THE ENTIRE site examined".
       ⭐ Inside this (hover: none) block by construction, so no pointer width can see it. */
    [data-cc-cardname] { display:flex; align-items:center; min-height:44px; }

    /* ⛔ 23 Sep · CONTRACT-MobileApply-22SEP.md criterion 25 — THE SAME OPT-IN CC AbilityCard GOT
       FOR CRITERION 12. `.sc-host:has(> [data-cc-hit="overlay"])` is pointer-events:none so the row's
       own link gets a fine-pointer click, and the overlay states pointerEvents:'none' inline; on a
       coarse pointer there is no hover, so a tap reached nothing and no card ever opened (camp
       types: 119 of 119 silent). A host that has nothing under its overlay declares
       `data-cc-tapcard`, and only there does the overlay take the tap — `!important` because the
       overlay's own none is inline. Hosts that DO sit on a link (the Items rows, the item page's
       "Used in") do not declare it, so their tap still navigates. Pure CSS: it works on a reading
       page, which ships no engine, with JavaScript on or off. */
    [data-cc-tapcard] > .sc-host:has(> [data-cc-hit="overlay"]) { pointer-events:auto; }
    [data-cc-tapcard] > .sc-host > [data-cc-hit="overlay"] { pointer-events:auto !important; }
  }


  :root { --gutter:clamp(16px, 3.5443cqw + 2.18px, 44px); --section:clamp(44px, 5.5696cqw + 22.28px, 88px); } /* ⭐ DECLARED brief 84 §2 — this drawing's own line, no longer an injection (was brief 48 A1). Transcribed from FOUNDATION: spacing and measure. */
  /* ⛔ Scoped for the same reason as the header — see that file. A bare `a` rule in an
     imported component's helmet decides link colour for the whole host page. */
  [data-cc-chrome="footer"] a { color:var(--ink); text-decoration:none; }
  [data-cc-chrome="footer"] a:hover { color:var(--loud); }

  /* ── the same four chrome rules as the header · sweep, 16 Aug ────────────────────
     ⭐ The footer has no controls, so it needs three of them: the tint, the ring, and
     the guard that says the tint keeps. ⛔ There is no button reset because there is
     no button — every interactive thing in this file is a destination and is an <a>. */
  [data-cc-chrome="footer"] {
    --chrome:#CFD6DE; --focus-ring-width:2px; --focus-ring-offset:2px;
    --motion-tint:160ms; --motion-settle:260ms; --motion-drift:420ms;
  }
  [data-cc-chrome="footer"] a { transition: color var(--motion-tint) ease; }
  [data-cc-chrome="footer"] a:focus-visible {
    outline: var(--focus-ring-width) solid var(--chrome);
    outline-offset: var(--focus-ring-offset);
  }
  @media (prefers-reduced-motion: reduce) {
    /* tint KEEPS — nothing here moves, and the colour change is the whole of the state. */
  }

  /* ⭐ ink → lede on the SIZE axis, not the importance one. The column links are 14px on
     the desktop layout and 16px below 900, which is the size class where ink glares — so
     the fold happens in the same query that changes the size, and nowhere else. */
  [data-cc-chrome="footer"] a.cc-col { color:var(--ink); }
  @container (max-width: 900px) {
    [data-cc-chrome="footer"] a.cc-col { color:#C7CCD1; }
  }

  /* ⭐ 22 Sep · MOBILE PAIR 02 — the last three links on every page of the site were 13px
     tall at 9.5px mono, baseline-aligned on one wrapping line. Below 900 they take the same
     treatment the Columns band one hairline above already takes: a column of 44-tall rows at
     gap 0 (three padded controls that touch, per the spacing round), and 12.5px — this band's
     own copyright size, not a new ramp step (Q3, 22 Sep). The copyright takes the full measure
     above them. Nothing here applies at pointer widths. */
  @container (max-width: 900px) {
    [data-cc-chrome="footer"] [data-cc-legal] {
      flex-basis:100%; flex-direction:column; align-items:stretch; gap:0; font-size:12.5px;
    }
    [data-cc-chrome="footer"] [data-cc-legal] > a,
    [data-cc-chrome="footer"] [data-cc-legal] > span {
      display:flex; align-items:center; min-height:44px;
    }
    /* ⛔ 23 Sep · criterion 24 — a STANDALONE link is a control, and a control is 44 × 44 at 390 (Plan's rule, now in spec/RULINGS.md; inline links inside running prose are exempt). Pair 02 gave these three 44 of height and nothing about width, so Terms
       stood at 31.4 and Privacy at 43.9. They are the legal row's own links, one per row below 900
       — standalone, not words in a sentence. Width only; the height is Pair 02's. */
    [data-cc-chrome="footer"] [data-cc-legal] > a { min-width:44px; }
  }
[data-cc-hover-css="color:var(--loud);"]:hover{color:var(--loud) !important}
[data-cc-hover-css="background:var(--surface);"]:hover{background:var(--surface) !important}
[data-cc-hover-css="color:var(--ink);"]:hover{color:var(--ink) !important}
[data-cc-hover-css="background:var(--ground); color:var(--loud);"]:hover{background:var(--ground) !important; color:var(--loud) !important}
[data-cc-hover-css="background:var(--ground);"]:hover{background:var(--ground) !important}
[data-cc-hover-css="background:var(--panel);"]:hover{background:var(--panel) !important}
[data-cc-hover-css="color:oklch(0.860 0.055 90);"]:hover{color:oklch(0.860 0.055 90) !important}
[data-cc-hover-css="background:#232b34;"]:hover{background:#232b34 !important}
[data-cc-hover-css="background:#12161a;"]:hover{background:#12161a !important}
[data-cc-hover-css="color:var(--accent-lift);"]:hover{color:var(--accent-lift) !important}
[data-cc-hover-css="border-bottom-color:var(--gold);"]:hover{border-bottom-color:var(--gold) !important}
[data-cc-hover-css="color:var(--quiet);"]:hover{color:var(--quiet) !important}
