/* generated from crates/choir-node/src/ui.css -- do not edit.
   Regenerate: cargo run -p choir-cli --example gen-surface
 
   The token block of that sheet, cut at its reset marker, with
   each theme selector widened to answer to mdBook's `<html>`
   class as well as this workspace's `data-theme`. Edit the
   tokens there and the node's pages and the book move together.
   Component styles are deliberately NOT shared: that sheet
   styles `h2` as an uppercase eyebrow and centres `body`,
   which is right for a node page and wrong for a book. */

/* choir node browser surface — design tokens + choir components.
   =========================================================================
   TWO HALVES, ONE SHEET, BOTH OURS. Above the CHOIR COMPONENTS marker is
   the token block: every colour, size, radius, shadow, gradient and
   duration this surface is allowed to use, named once. Below it is the
   component block, which styles this node's pages out of those tokens.

   This file is self-contained on purpose. No font files ship, so the
   stacks name system faces only — including the display serif, which is
   already on every machine this surface is read on.

   THE RULE: no colour, size, radius, shadow or duration is authored below
   the marker. The component block references `var(--…)` and nothing else.
   A value that does not exist yet gets a token in the block above first.
   Four tests enforce it — a raw value below the marker, a `var()` naming
   a token nobody defined, a translucent wash painted as text, and a box
   pinned to a fixed width.

   TWO REGISTERS, ONE SYSTEM. The reading pages (the front door, signing
   in, redeeming an invite, a refusal) are set as a page of a book: a
   display serif, a measure, air. The tool pages (browsing, reviewing,
   the console) are set as an instrument: all sans, dense, precise. Same
   palette, same spacing, same motion; two voices.
   ========================================================================= */

:root{
  /* ---- type -------------------------------------------------------- */
  /* System faces only, and `system-ui` first: the node ships no font
     file, so the stack names what the reader's own machine already has.
     A webfont here would be an asset the operator did not ask to host
     and a request this surface makes to nobody. */
  --font-sans:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --font-mono:ui-monospace,"SF Mono","Cascadia Mono",Menlo,Consolas,monospace;
  /* The reading register. `ui-serif` resolves to New York on Apple
     platforms and to the reader's serif elsewhere; the named faces are
     the fallbacks that actually exist on Windows and on Linux desktops.
     It is used for one thing — the title of a page somebody reads rather
     than operates — and that restraint is what keeps it from reading as
     a theme. */
  --font-display:ui-serif,"New York","Iowan Old Style","Palatino Linotype",
    Palatino,"Book Antiqua",Georgia,serif;

  /* A 16px root, so a rem is a round number and the space scale below
     lands on a 4px grid without a decimal in sight. */
  --fs-100:0.6875rem; /* 11px — micro labels, table eyebrows */
  --fs-200:0.75rem;   /* 12px — captions, meta, counts */
  --fs-300:0.8125rem; /* 13px — code, oids, dense tables */
  --fs-400:0.875rem;  /* 14px — UI default */
  --fs-500:1rem;      /* 16px — body copy */
  --fs-600:1.125rem;  /* 18px — lede */
  --fs-700:1.3125rem; /* 21px — h3 */
  --fs-800:1.625rem;  /* 26px — h2 */
  --fs-900:2.125rem;  /* 34px — h1 */
  --fs-1000:2.75rem;  /* 44px — the top of the fixed scale */
  --fs-1100:3.5rem;   /* 56px — the ceiling the display step reaches */

  /* Fluid steps. A door read on a phone and a door read on a 27-inch
     display are the same page at two sizes, and picking one fixed size
     means picking which of the two is wrong. `clamp` interpolates
     between the steps above rather than beside them, so the scale is
     still the scale. These are the only viewport-relative lengths in the
     sheet, and they are here rather than in a media query because a
     breakpoint is a raw length by definition and the component block may
     not author one. */
  --fs-display:clamp(2.125rem,1.35rem + 3.4vw,3.5rem); /* the front door's title */
  --fs-title:clamp(1.75rem,1.35rem + 1.9vw,2.75rem);   /* every other task page */
  --fs-lede:clamp(1.0625rem,1rem + 0.4vw,1.3125rem);   /* the sentence under it */

  --lh-tight:1.08;
  --lh-snug:1.3;
  --lh-normal:1.5;
  --lh-copy:1.65; /* prose: the front door and a README */
  --lh-code:1.6;

  --fw-regular:400;
  --fw-medium:500;
  --fw-bold:600; /* 600, not 700: a system face at 700 shouts */

  /* Tracking is nearly zero on purpose. `system-ui` is drawn for screen
     text at these sizes and does not want the optical correction a
     display face does; only the largest steps and the small-caps
     eyebrows get one. The serif takes a touch more negative tracking
     than the sans, because it is set larger. */
  --tr-display:-0.026em;
  --tr-heading:-0.012em;
  --tr-body:0;
  --tr-mono:0;
  --tr-caps:0.085em; /* eyebrows, small-caps labels */

  /* ---- space (4px grid at a 16px root) ----------------------------- */
  --sp-0:0;
  --sp-1:0.25rem; /* 4  */
  --sp-2:0.5rem;  /* 8  */
  --sp-3:0.75rem; /* 12 */
  --sp-4:1rem;    /* 16 */
  --sp-5:1.25rem; /* 20 */
  --sp-6:1.5rem;  /* 24 */
  --sp-8:2rem;    /* 32 */
  --sp-10:2.5rem; /* 40 */
  --sp-12:3rem;   /* 48 */
  --sp-16:4rem;   /* 64 */
  --sp-20:5rem;   /* 80 */
  --sp-28:7rem;   /* 112 */
  --sp-40:10rem;  /* 160 */

  /* The page's own margins, as tokens rather than as a media query, so
     the narrow-viewport override below is the only place a breakpoint
     is written and the component block stays free of lengths. */
  --pad-x:var(--sp-8);
  --pad-y:var(--sp-10);
  --pad-card:var(--sp-6);
  --gap-pane:var(--sp-10);

  /* ---- radii ------------------------------------------------------
     A radius is a decoration, and this sheet still spends its hierarchy
     on type and whitespace. But nothing rounded at all reads as a
     terminal dump rather than as a made thing, so the scale is small,
     consistent, and used on the four shapes that are genuinely objects:
     a well, a card, a control, a badge.
     ------------------------------------------------------------------ */
  --r-xs:3px;
  --r-sm:5px;
  --r-md:9px;
  --r-lg:14px;
  --r-xl:20px;
  --r-pill:999px;

  /* ---- borders ----------------------------------------------------- */
  --bw-hair:1px;
  --bw-1:1px;
  --bw-0:0;
  --bw-2:2px;
  --bw-4:4px;    /* the outer radius of the focus ring */
  --bw-rule:2px; /* the accent tick */
  --border:var(--bw-1) solid var(--line);
  --border-hair:var(--bw-hair) solid var(--hairline);
  --border-accent:var(--bw-1) solid var(--accent-line);

  /* ---- motion -----------------------------------------------------
     Short, eased, and never more than one property in flight that the
     reader did not ask for. The entrance is 320ms because that is about
     where a rise stops reading as movement and starts reading as the
     page having arrived; the state flips are 60–120ms because a hover
     that takes longer than that feels loose.
     ------------------------------------------------------------------ */
  --dur-1:60ms; /* state flips: hover, focus */
  --dur-2:120ms;
  --dur-3:180ms;
  --dur-4:240ms;
  --dur-5:320ms; /* an element arriving */
  --dur-6:520ms; /* the one long one: the door's title */
  --ease-out:cubic-bezier(.22,.61,.36,1);
  --ease-in-out:cubic-bezier(.45,.05,.55,.95);
  --ease-emphatic:cubic-bezier(.16,.84,.24,1);
  --ease-linear:linear;
  /* A stagger, so a list arrives as a list rather than as a block. */
  --delay-1:40ms;
  --delay-2:90ms;
  --delay-3:140ms;
  --delay-4:190ms;
  --delay-5:240ms;
  --delay-6:290ms;
  /* How far something travels on the way in, and how far a control
     lifts under the cursor. Both deliberately small enough to read as
     weight rather than as animation. */
  --rise:0.375rem;
  --lift:-1px;

  /* ---- layout ------------------------------------------------------ */
  --measure:36rem; /* a book's measure: ~66 characters at 16px */
  --search:20rem;  /* a form field's cap, wherever one is set */
  --omni:24rem;    /* the bar's search box: a field, not a banner */
  --article:42rem; /* prose that carries code, slightly wider */
  --side:17rem;    /* a narrow pane */
  --palette:38rem; /* the command palette, a shade wider than a measure */
  --toc:14rem;
  --topbar-h:3rem;
  --page-max:76rem;
  --tool-header-h:2.75rem;
  --card-min:14rem; /* a claim on the front door, before it wraps */
  /* One column of a three-up conflict. A floor rather than a width, so
     the columns stack rather than overflow when the viewport cannot
     give three of them this much. */
  --col-min:15rem;
  /* The blur behind the chrome bar, so what scrolls under it is present
     without being legible. */
  --blur-1:4px;  /* the palette's backdrop: a hint of depth, no more */
  /* Whether a listing shows the commit subject at all. A column that has
     been truncated to two characters is not a column; it is noise where
     a column used to be. Carried as a token because the component block
     may not author a breakpoint, and the narrow override below is the
     one place that decides. */
  --col-subject:table-cell;
  --col-meta:inline; /* the commit strip's hash and age */

  /* ---- z ----------------------------------------------------------- */
  --z-under:-1;
  --z-base:0;
  --z-sticky:10;
  --z-header:20;
  --z-dropdown:30;
  --z-scrim:40;
  --z-palette:50;

  /* ---- icons ------------------------------------------------------ */
  /* Sixteen-unit glyphs, each an SVG the browser draws once from a
     data URI and uses as a mask over the text colour, so a glyph takes
     the colour of whatever it sits in, hover and theme included. In
     the stylesheet rather than the markup, so twenty-five rows of
     folders cost one glyph and not twenty-five. */
  --icon:1rem;
  --i-folder:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath fill='black' d='M1 3.5C1 2.67 1.67 2 2.5 2h3.38c.4 0 .78.16 1.06.44L8.06 3.5H13.5c.83 0 1.5.67 1.5 1.5v7.5c0 .83-.67 1.5-1.5 1.5h-11C1.67 14 1 13.33 1 12.5z'/%3E%3C/svg%3E");
  --i-file:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M3.5 1.75h5.5l3.5 3.5v8a1 1 0 0 1-1 1h-8a1 1 0 0 1-1-1v-10.5a1 1 0 0 1 1-1z'/%3E%3Cpath d='M9 1.75v3.5h3.5'/%3E%3C/svg%3E");
  --i-code:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5.5 4.5L2 8l3.5 3.5M10.5 4.5L14 8l-3.5 3.5'/%3E%3C/svg%3E");
  --i-history:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.25 8a5.75 5.75 0 1 0 1.7-4.1L2.25 5.6'/%3E%3Cpath d='M2.25 2.5v3.1h3.1'/%3E%3Cpath d='M8 4.75V8l2.25 1.25'/%3E%3C/svg%3E");
  --i-review:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.75 3.25h10.5a1 1 0 0 1 1 1v6.5a1 1 0 0 1-1 1h-6l-3 2.5v-2.5h-1.5a1 1 0 0 1-1-1v-6.5a1 1 0 0 1 1-1z'/%3E%3Cpath d='M5.75 7.5l1.5 1.5 3-3'/%3E%3C/svg%3E");
  --i-contribute:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='4' cy='3.5' r='1.75'/%3E%3Ccircle cx='4' cy='12.5' r='1.75'/%3E%3Ccircle cx='12' cy='12.5' r='1.75'/%3E%3Cpath d='M4 5.25v5.5M12 10.75V7a3 3 0 0 0-3-3H7.5M9 2.5L7.5 4 9 5.5'/%3E%3C/svg%3E");
  --i-branch:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='4.5' cy='3.5' r='1.75'/%3E%3Ccircle cx='4.5' cy='12.5' r='1.75'/%3E%3Ccircle cx='11.5' cy='5' r='1.75'/%3E%3Cpath d='M4.5 5.25v5.5M11.5 6.75c0 3-7 2.5-7 4'/%3E%3C/svg%3E");
  --i-tag:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M1.75 2.75v4.5l7 7 5.5-5.5-7-7h-4.5a1 1 0 0 0-1 1z'/%3E%3Ccircle cx='5' cy='5' r='.75' fill='black'/%3E%3C/svg%3E");
  --i-terminal:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M2.5 4l3.5 4-3.5 4M8 12h5.5'/%3E%3C/svg%3E");
  --i-law:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 2.25v11.5M5 13.75h6M3.5 4.5h9'/%3E%3Cpath d='M2 9.5a2 1.25 0 0 0 4 0L4 4.5zM10 9.5a2 1.25 0 0 0 4 0L12 4.5z'/%3E%3C/svg%3E");
  --i-shield:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 1.75l5.25 2v4c0 3.25-2.25 5.5-5.25 6.5-3-1-5.25-3.25-5.25-6.5v-4z'/%3E%3C/svg%3E");
  --i-book:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M8 4.25c-1.5-1-3.5-1.5-6.25-1.5v9.5c2.75 0 4.75.5 6.25 1.5 1.5-1 3.5-1.5 6.25-1.5v-9.5c-2.75 0-4.75.5-6.25 1.5zM8 4.25v9.5'/%3E%3C/svg%3E");
  --i-people:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='6' cy='5.5' r='2.25'/%3E%3Cpath d='M1.75 13.5c.4-2.25 2.1-3.5 4.25-3.5s3.85 1.25 4.25 3.5'/%3E%3Cpath d='M10.5 3.5a2.25 2.25 0 0 1 0 4.25M12 10.25c1.25.5 2 1.6 2.25 3.25'/%3E%3C/svg%3E");
  --i-caret:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='black' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4.5 6.25L8 9.75l3.5-3.5'/%3E%3C/svg%3E");

  /* ---- the chain --------------------------------------------------
     The one figure on this surface that is about what the product is
     rather than about the page. The rail's Activity list is this
     repository's own ordered log, so it is drawn as one: a node per
     entry, joined top to bottom, newest first. An ordinary entry is a
     ring; the head is filled, because it is the single entry an append
     can land after; a merge is a diamond, two lines of history
     rejoining at one committed value.

     Drawn as gradients over the glyph box the list already reserves,
     so a node costs no markup and stays on the same baseline the
     masked icons sit on. The stops are percentages rather than
     lengths: the figure is then a function of `--icon` and scales with
     it, and the component block below stays free of raw values. The
     theme tokens inside resolve on `:root`, the element all three
     palettes declare them on, which is what lets these be written once
     rather than once per theme. */
  --node:radial-gradient(circle at 50% 50%,
    transparent 0 24%,var(--line-strong) 25% 42%,transparent 43%);
  --node-head:radial-gradient(circle at 50% 50%,
    var(--accent) 0 42%,transparent 43%);
}

/* A phone is not a desktop with less room; it is a different page
   margin. This is the sheet's one breakpoint, and it moves tokens
   rather than layout — every component below reads the same names and
   none of them knows a viewport width exists. */
@media (max-width:52rem){
  :root{
    --pad-x:var(--sp-5);
    --pad-y:var(--sp-6);
    --pad-card:var(--sp-5);
    --gap-pane:var(--sp-8);
  }
}
@media (max-width:34rem){
  :root{
    --pad-x:var(--sp-4);
    --pad-card:var(--sp-4);
    --col-subject:none;
    --col-meta:none;
  }
}

/* =========================================================================
   LIGHT — the canonical palette, and the one the surface is designed in.

   Warm neutral greys: the ground is a paper white with a little yellow
   in it and the ink is a warm near-black, never `#000`. The accent is a
   deep indigo — one hue, used for links, for the current selection, and
   for the single decisive control on a page that has one.

   Every ratio below is measured against `--ground` unless it says
   otherwise, and every body and secondary text token clears 4.5:1. The
   test that proves it checks every ink against every ground in both
   palettes, so a nudge for taste cannot quietly drop one under the bar.
   ====================================================================== */
:root,
:root[data-theme="light"],:root.light:not([data-theme="dark"]),:root.rust:not([data-theme="dark"]){
  color-scheme:light;

  --ground:oklch(97.96% 0.0057 84.57); /* page */
  --surface:oklch(100% 0 0);           /* a card, a pane, the chrome bar */
  --card:oklch(100% 0 0);
  --raise:oklch(94.4% 0.0115 84.58);   /* hover fills, inputs */
  --sunken:oklch(95.85% 0.0098 87.47); /* code wells, diffs */

  --ink:oklch(25.8% 0.0086 75.21);     /* body copy      — 14.6:1 */
  --strong:oklch(17.47% 0.0052 67.47); /* headings       — 17.9:1 */
  --muted:oklch(44.08% 0.0144 79.71);  /* secondary      —  7.5:1 */
  --faint:oklch(50.6% 0.0159 78.18);   /* tertiary, meta —  5.7:1 */
  --inverse:oklch(100% 0 0);           /* text on an accent fill — 7.2:1 */

  --line:oklch(25.8% 0.0086 75.21 / .13);
  --hairline:oklch(25.8% 0.0086 75.21 / .07);
  --line-strong:oklch(25.8% 0.0086 75.21 / .26);

  --accent:oklch(43.69% 0.1221 271.84);    /* the one accent: a deep indigo */
  --accent-ink:oklch(40.53% 0.122 271.74); /* accent as text/links — 7.9:1 */
  --accent-hover:oklch(33.42% 0.1098 271.13);
  --accent-tint:oklch(43.69% 0.1221 271.84 / .08);
  --accent-line:oklch(43.69% 0.1221 271.84 / .32);

  /* Status colours are desaturated and live on text and thin rules. The
     `-tint` washes are backgrounds only; a foreground always takes the
     solid token beside it. */
  --ok:oklch(47.04% 0.0964 159.31);      --ok-tint:oklch(47.04% 0.0964 159.31 / .08);    --ok-line:oklch(47.04% 0.0964 159.31 / .32);
  --warn:oklch(47.56% 0.0932 76.04);    --warn-tint:oklch(47.56% 0.0932 76.04 / .08);  --warn-line:oklch(47.56% 0.0932 76.04 / .32);
  --danger:oklch(49.67% 0.1535 21.08);  --danger-tint:oklch(49.67% 0.1535 21.08 / .07);--danger-line:oklch(49.67% 0.1535 21.08 / .32);
  --info:var(--accent-ink); --info-tint:var(--accent-tint); --info-line:var(--accent-line);

  /* A plain ring, no blur and no colour bleed: two solid pixels offset
     from the control. Written as a `box-shadow` pair because several
     controls draw their own border and an `outline` on those sits
     outside it at an inconsistent distance. */
  --focus:oklch(40.53% 0.122 271.74);
  --focus-ring:0 0 0 var(--bw-2) var(--ground),0 0 0 var(--bw-4) var(--focus);
  --selection:oklch(43.69% 0.1221 271.84 / .16);
  /* What the page becomes while the palette is over it. Per theme, and
     it has to be: the first version mixed `--strong`, on the reasoning
     that it is the darkest ink in whichever palette is in force. It is
     the ink, and in the dark theme the ink is a warm bone -- so the
     overlay lightened the page it was meant to dim, and everything
     behind the dialog went to grey mush. A scrim is dark in both themes
     or it is not a scrim. */
  --scrim:color-mix(in oklab,var(--strong) 42%,transparent);

  /* Depth is still carried mostly by whitespace and hairlines. What
     these add is the small amount of separation a card needs to sit on
     the page rather than be drawn on it: one contact shadow and one
     wide, very light ambient one. Warm, never neutral black. */
  --shadow-1:0 1px 1px oklch(25.8% 0.0086 75.21 / .04);
  --shadow-2:0 1px 2px oklch(25.8% 0.0086 75.21 / .05),0 8px 20px -14px oklch(25.8% 0.0086 75.21 / .22);
  --shadow-3:0 1px 2px oklch(25.8% 0.0086 75.21 / .05),0 14px 32px -18px oklch(25.8% 0.0086 75.21 / .28),
             0 30px 60px -40px oklch(25.8% 0.0086 75.21 / .3);
  --shadow-inset:inset 0 1px 0 oklch(100% 0 0 / .7);

  /* The light behind the page. Two very wide, very weak radial washes
     at the top, so the first screen has a horizon and the rest of the
     page settles onto plain paper. Nothing here is legible as a colour;
     it is legible as depth. */
  --glow-1:radial-gradient(72% 46% at 50% -8%,oklch(43.69% 0.1221 271.84 / .18),transparent 68%);
  --glow-2:radial-gradient(46% 34% at 88% 2%,oklch(47.56% 0.0932 76.04 / .09),transparent 70%);
  --glow-3:radial-gradient(90% 36% at 50% 108%,oklch(43.69% 0.1221 271.84 / .07),transparent 70%);
  --head:oklch(96.51% 0.0074 80.72); /* the header strip of a box */
  /* Tooth. A tile of monochrome noise the browser draws once from the
     SVG in the dark theme's value and repeats; the last row of the
     colour matrix is its whole opacity. Off on paper, where a texture
     on white reads as dirt rather than depth. */
  --grain:none;
  /* A rule that fades out rather than stopping. Used under an eyebrow
     and above the footer, where a full-strength line across the page
     would be the loudest thing on it. */
  --rule-fade:linear-gradient(90deg,var(--line),oklch(25.8% 0.0086 75.21 / 0));
  /* The stave: the one ornament on this surface, and the only place the
     name of the product shows up as a shape. Four hairlines, a musical
     staff at rest. */
  --stave:repeating-linear-gradient(180deg,var(--hairline) 0 1px,transparent 1px 7px);
  /* The same figure at mark size: three rules in the accent, drawn into
     a box the size of a capital letter. */
  --stave-mark:repeating-linear-gradient(90deg,var(--accent) 0 2px,transparent 2px 5px);
  /* A card's fill. A hair lighter at the top than at the bottom, which
     is what makes a flat rectangle read as a surface catching light. */
  --card-wash:linear-gradient(180deg,oklch(100% 0 0),oklch(98.88% 0.0045 78.3));
  --sunken-wash:linear-gradient(180deg,oklch(95.85% 0.0098 87.47),oklch(96.78% 0.0086 84.57));

  /* Syntax: one hue family plus three signals, all ≥ 4.5:1 on
     `--sunken`, which is the surface code is set on. */
  --syn-plain:oklch(25.8% 0.0086 75.21);
  --syn-comment:oklch(50.6% 0.0159 78.18);
  --syn-keyword:oklch(40.53% 0.122 271.74);
  --syn-type:oklch(45.83% 0.0747 243.27);
  --syn-func:oklch(42.18% 0.0672 245.6);
  --syn-string:oklch(47.04% 0.0964 159.31);
  --syn-number:oklch(47.56% 0.0932 76.04);
  --syn-const:oklch(45.84% 0.1097 309.68);
  --syn-macro:oklch(47.8% 0.1119 44.99);
  --syn-punct:oklch(44.08% 0.0144 79.71);
  --syn-added:oklch(47.04% 0.0964 159.31 / .1);
  --syn-removed:oklch(49.67% 0.1535 21.08 / .09);
  --syn-gutter:oklch(52.35% 0.0157 78.18);
}

/* =========================================================================
   DARK — a palette, not an inversion.

   Warm charcoal rather than blue-black, and an ink that is a warm bone
   rather than white. The accent lightens to hold its ratio; it does not
   change hue, so the two themes are the same design at two exposures.
   ====================================================================== */
@media (prefers-color-scheme:dark){
  :root:not([data-theme="light"]){
    color-scheme:dark;

    --ground:oklch(18.3% 0.0026 67.66);
    --surface:oklch(21.38% 0.0042 84.59);
    --card:oklch(21.38% 0.0042 84.59);
    --raise:oklch(24.96% 0.0036 48.58);
    --sunken:oklch(16.45% 0.0027 67.64);

    --ink:oklch(87.14% 0.0134 82.4);     /* 12.4:1 */
    --strong:oklch(96.48% 0.0086 84.57); /* 16.9:1 */
    --muted:oklch(72% 0.0166 77.02);     /*  7.5:1 */
    --faint:oklch(68.5% 0.0168 77.01);   /*  6.6:1 */
    --inverse:oklch(18.3% 0.0026 67.66);

    --line:oklch(87.14% 0.0134 82.4 / .14);
    --hairline:oklch(87.14% 0.0134 82.4 / .07);
    --line-strong:oklch(87.14% 0.0134 82.4 / .28);

    --accent:oklch(66.74% 0.1101 273.65);
    --accent-ink:oklch(76.73% 0.0817 274.2); /*  8.7:1 */
    --accent-hover:oklch(85.14% 0.0566 275.18);
    --accent-tint:oklch(76.73% 0.0817 274.2 / .12);
    --accent-line:oklch(76.73% 0.0817 274.2 / .36);

    --ok:oklch(75.1% 0.1043 162.01);      --ok-tint:oklch(75.1% 0.1043 162.01 / .1);   --ok-line:oklch(75.1% 0.1043 162.01 / .34);
    --warn:oklch(75.72% 0.1074 81.11);    --warn-tint:oklch(75.72% 0.1074 81.11 / .1);  --warn-line:oklch(75.72% 0.1074 81.11 / .34);
    --danger:oklch(73.41% 0.1149 16.17);  --danger-tint:oklch(73.41% 0.1149 16.17 / .1);--danger-line:oklch(73.41% 0.1149 16.17 / .34);
    --info:var(--accent-ink); --info-tint:var(--accent-tint); --info-line:var(--accent-line);

    --focus:oklch(76.73% 0.0817 274.2);
    --focus-ring:0 0 0 var(--bw-2) var(--ground),0 0 0 var(--bw-4) var(--focus);
    --selection:oklch(76.73% 0.0817 274.2 / .26);
    --scrim:color-mix(in oklab,var(--sunken) 68%,transparent);

    --shadow-1:0 1px 1px oklch(0% 0 0 / .4);
    --shadow-2:0 1px 2px oklch(0% 0 0 / .5),0 8px 20px -14px oklch(0% 0 0 / .8);
    --shadow-3:0 1px 2px oklch(0% 0 0 / .5),0 14px 32px -18px oklch(0% 0 0 / .75),
               0 30px 60px -40px oklch(0% 0 0 / .9);
    --shadow-inset:inset 0 1px 0 oklch(100% 0 0 / .04);

    --glow-1:radial-gradient(72% 46% at 50% -8%,oklch(66.74% 0.1101 273.65 / .16),transparent 68%);
    --glow-2:radial-gradient(46% 34% at 88% 2%,oklch(75.72% 0.1074 81.11 / .07),transparent 70%);
    --glow-3:radial-gradient(90% 36% at 50% 108%,oklch(66.74% 0.1101 273.65 / .08),transparent 70%);
    --head:oklch(23.93% 0.0058 91.6);
    --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .04 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
    --rule-fade:linear-gradient(90deg,var(--line),oklch(87.14% 0.0134 82.4 / 0));
    --stave:repeating-linear-gradient(180deg,var(--hairline) 0 1px,transparent 1px 7px);
  /* The same figure at mark size: three rules in the accent, drawn into
     a box the size of a capital letter. */
  --stave-mark:repeating-linear-gradient(90deg,var(--accent) 0 2px,transparent 2px 5px);
    --card-wash:linear-gradient(180deg,oklch(22.68% 0.0041 84.59),oklch(20.94% 0.0042 84.59));
    --sunken-wash:linear-gradient(180deg,oklch(16.45% 0.0027 67.64),oklch(17.84% 0.0026 67.66));

    --syn-plain:oklch(87.14% 0.0134 82.4);
    --syn-comment:oklch(64.65% 0.0168 77.01);
    --syn-keyword:oklch(76.73% 0.0817 274.2);
    --syn-type:oklch(82% 0.054 247.62);
    --syn-func:oklch(84.61% 0.0423 251.67);
    --syn-string:oklch(79.99% 0.0865 157.44);
    --syn-number:oklch(79% 0.0959 82.46);
    --syn-const:oklch(77.41% 0.0835 306.47);
    --syn-macro:oklch(76.11% 0.0892 50.01);
    --syn-punct:oklch(67.62% 0.0166 77.02);
    --syn-added:oklch(75.1% 0.1043 162.01 / .12);
    --syn-removed:oklch(73.41% 0.1149 16.17 / .12);
    --syn-gutter:oklch(65.31% 0.0168 77.01);
  }
}

/* Manual override — duplicated rather than `@extend`'d because plain CSS
   has no mixins and the attribute must beat the media query above. The
   generator that cuts this block for the book widens both theme
   selectors by name, so neither may be reworded, and a test compares the
   two spellings declaration by declaration. */
:root[data-theme="dark"],:root.coal:not([data-theme="light"]),:root.navy:not([data-theme="light"]),:root.ayu:not([data-theme="light"]){
  color-scheme:dark;

  --ground:oklch(18.3% 0.0026 67.66);
  --surface:oklch(21.38% 0.0042 84.59);
  --card:oklch(21.38% 0.0042 84.59);
  --raise:oklch(24.96% 0.0036 48.58);
  --sunken:oklch(16.45% 0.0027 67.64);

  --ink:oklch(87.14% 0.0134 82.4);
  --strong:oklch(96.48% 0.0086 84.57);
  --muted:oklch(72% 0.0166 77.02);
  --faint:oklch(68.5% 0.0168 77.01);
  --inverse:oklch(18.3% 0.0026 67.66);

  --line:oklch(87.14% 0.0134 82.4 / .14);
  --hairline:oklch(87.14% 0.0134 82.4 / .07);
  --line-strong:oklch(87.14% 0.0134 82.4 / .28);

  --accent:oklch(66.74% 0.1101 273.65);
  --accent-ink:oklch(76.73% 0.0817 274.2);
  --accent-hover:oklch(85.14% 0.0566 275.18);
  --accent-tint:oklch(76.73% 0.0817 274.2 / .12);
  --accent-line:oklch(76.73% 0.0817 274.2 / .36);

  --ok:oklch(75.1% 0.1043 162.01);      --ok-tint:oklch(75.1% 0.1043 162.01 / .1);   --ok-line:oklch(75.1% 0.1043 162.01 / .34);
  --warn:oklch(75.72% 0.1074 81.11);    --warn-tint:oklch(75.72% 0.1074 81.11 / .1);  --warn-line:oklch(75.72% 0.1074 81.11 / .34);
  --danger:oklch(73.41% 0.1149 16.17);  --danger-tint:oklch(73.41% 0.1149 16.17 / .1);--danger-line:oklch(73.41% 0.1149 16.17 / .34);
  --info:var(--accent-ink); --info-tint:var(--accent-tint); --info-line:var(--accent-line);

  --focus:oklch(76.73% 0.0817 274.2);
  --focus-ring:0 0 0 var(--bw-2) var(--ground),0 0 0 var(--bw-4) var(--focus);
  --selection:oklch(76.73% 0.0817 274.2 / .26);
  --scrim:color-mix(in oklab,var(--sunken) 68%,transparent);

  --shadow-1:0 1px 1px oklch(0% 0 0 / .4);
  --shadow-2:0 1px 2px oklch(0% 0 0 / .5),0 8px 20px -14px oklch(0% 0 0 / .8);
  --shadow-3:0 1px 2px oklch(0% 0 0 / .5),0 14px 32px -18px oklch(0% 0 0 / .75),
             0 30px 60px -40px oklch(0% 0 0 / .9);
  --shadow-inset:inset 0 1px 0 oklch(100% 0 0 / .04);

  --glow-1:radial-gradient(72% 46% at 50% -8%,oklch(66.74% 0.1101 273.65 / .16),transparent 68%);
  --glow-2:radial-gradient(46% 34% at 88% 2%,oklch(75.72% 0.1074 81.11 / .07),transparent 70%);
  --glow-3:radial-gradient(90% 36% at 50% 108%,oklch(66.74% 0.1101 273.65 / .08),transparent 70%);
  --head:oklch(23.93% 0.0058 91.6);
  --grain:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix values='0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 .04 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23g)'/%3E%3C/svg%3E");
  --rule-fade:linear-gradient(90deg,var(--line),oklch(87.14% 0.0134 82.4 / 0));
  --stave:repeating-linear-gradient(180deg,var(--hairline) 0 1px,transparent 1px 7px);
  /* The same figure at mark size: three rules in the accent, drawn into
     a box the size of a capital letter. */
  --stave-mark:repeating-linear-gradient(90deg,var(--accent) 0 2px,transparent 2px 5px);
  --card-wash:linear-gradient(180deg,oklch(22.68% 0.0041 84.59),oklch(20.94% 0.0042 84.59));
  --sunken-wash:linear-gradient(180deg,oklch(16.45% 0.0027 67.64),oklch(17.84% 0.0026 67.66));

  --syn-plain:oklch(87.14% 0.0134 82.4);
  --syn-comment:oklch(64.65% 0.0168 77.01);
  --syn-keyword:oklch(76.73% 0.0817 274.2);
  --syn-type:oklch(82% 0.054 247.62);
  --syn-func:oklch(84.61% 0.0423 251.67);
  --syn-string:oklch(79.99% 0.0865 157.44);
  --syn-number:oklch(79% 0.0959 82.46);
  --syn-const:oklch(77.41% 0.0835 306.47);
  --syn-macro:oklch(76.11% 0.0892 50.01);
  --syn-punct:oklch(67.62% 0.0166 77.02);
  --syn-added:oklch(75.1% 0.1043 162.01 / .12);
  --syn-removed:oklch(73.41% 0.1149 16.17 / .12);
  --syn-gutter:oklch(65.31% 0.0168 77.01);
}

/* --- legacy aliases -----------------------------------------------------
   Names the book's hand-written sheet and older generated markup still
   reference. Keep them; author nothing new against them.
   ----------------------------------------------------------------------- */
:root{
  --sans:var(--font-sans);
  --mono:var(--font-mono);
  --serif:var(--font-display);
  --tint:var(--accent-tint);
  --tint-line:var(--accent-line);
  --shadow:var(--shadow-2);
  --shadow-lg:var(--shadow-3);
  --icons:var(--faint);
}
