/*
 * GENERATED FILE — DO NOT EDIT.
 *
 * Source:    tokens.json  (@dentate/tokens v0.1.0, theme "dentate")
 * Emitter:   build.mjs
 * Regenerate: node build.mjs
 *
 * Edit tokens.json and rebuild. An edit made here is erased on the next
 * build, and — worse — it is erased silently in ONE repo while the other
 * two keep the old value. That divergence is the entire reason this
 * package exists. ARX ufobitcl9hsesf30vkmf.
 *
 * Dentate — Shared Design System v3.0 "Phosphor"
 *
 * Brand story: the dentate gyrus — memory made and remade, patterns kept
 * distinct, a record that is never overwritten.
 *
 *   Ground   #070809  — near-black substrate
 *   Ink      #EEF0F2  — text on ground
 *   Signal   #8FE3D0  — phosphor cyan-green (live, distinct, "signal")
 *   Remade   #F2C078  — warm amber (renewal, the record re-lit)
 *
 * Typography (roles, not faces — §5):
 *   Brand    'Bitcount Grid Double' — variable weight axis used as "neuron
 *            weight" at the locked 400; dots read as discrete cells.
 *            Legacy mark: Sixtyfour Convergence (D6, retired).
 *   Body     'Newsreader', 'Spectral' — serif, the document/record
 *            register. Schibsted Grotesk and Fraunces are RETIRED (§5).
 *   Labels   'Spline Sans Mono' — apparatus: eyebrows, keys, hashes, dates.
 *
 * Includes:
 *   - Token system (--cd-* structural, --brand-* palette)
 *   - Light/dark theme variants via [data-theme]
 *   - Liquid glass card primitive (.glass-card) with raytrace mouse vars
 *   - Hero utilities (.hero-eyebrow, .accent)
 *   - Dentate wordmark (.dentate-wordmark) in Bitcount Grid Double
 *   - Semantic hue table (--cd-hue-*) for charts, dots, avatars (§4b)
 *
 * The mouse-reactive raytrace JS lives in cortex-glass.ts. The root
 * +layout.svelte imports and initializes it on mount.
 */

/* ─── Dentate Brand Palette ─── */
:root {
  --brand-signal:       #8FE3D0;  /* phosphor cyan-green — primary accent */
  --brand-signal-soft:  #B5F0E2;  /* signal highlight */
  --brand-signal-deep:  #4FBFA4;  /* signal pressed / deep */
  --brand-amber:        #F2C078;  /* warm amber — "remade" accent */
  --brand-amber-soft:   #F8D9A8;  /* amber highlight */
  --brand-amber-deep:   #D99A45;  /* amber pressed */
  --brand-ground:       #070809;  /* near-black ground */
  --brand-ground-rich:  #030404;  /* deepest shadow */
  --brand-ink:          #EEF0F2;  /* ink on ground */
  --brand-steel:        #9FB4C7;  /* cool steel — tertiary (enterprise) */
  --brand-steel-soft:   #BCCBD9;  /* steel highlight */

  /* ─── Channel tokens ───
     The same colours as CHANNELS, for the one thing a hex token cannot do:
     carry an alpha at the call site. Written as
         rgb(var(--brand-signal-rgb) / 0.18)
     A tinted border, a glow, a wash and a scrim are all "the accent at an
     alpha", and without these they can only be spelled as a raw literal —
     which is how a repo ends up with ~200 rgba() brand literals that a
     palette change cannot reach, and how a find-replace over comments
     leaves the numbers behind. These ARE the accent: they re-grade with it.

     --brand-danger-rgb is here because a tinted FAILURE state could not be
     spelled at all. Destructive UI is not one colour, it is a colour at
     four alphas — a 0.02 wash behind a danger zone, a 0.08 banner fill, a
     0.25 border, a 0.30 rim — and --cd-danger is a finished hex, so none of
     those had a token to reach for. Two repos hit that wall in the same
     week and each invented its own way past it: synap-portal spelled 27 of
     them as color-mix(… var(--cd-danger) N%, transparent), synap-marketing's
     verify page typed rgba(229, 100, 92, …) with a comment saying the
     channel did not exist. Both are now this token. Note what the second
     workaround cost: a literal cannot re-grade, so the light block had to
     re-spell the same rule at rgba(179, 38, 30, …) and the two copies could
     drift apart. */
  --brand-signal-rgb:  143 227 208;
  --brand-amber-rgb:   242 192 120;
  --brand-steel-rgb:   159 180 199;
  --brand-danger-rgb:  229 100 92;
  --brand-ink-rgb:     238 240 242;
  --brand-ground-rgb:  7 8 9;
}

/* ─── Structural Tokens ─── */
:root {
  /* Depth Stack (4 levels) */
  --cd-void:     #070809;
  --cd-surface:  #0C0E10;
  --cd-raised:   #121517;
  --cd-float:    #181C1F;

  /* Signal Colors (semantic) */
  --cd-axon:      var(--brand-steel);   /* selections, tertiary — Enterprise tier */
  --cd-signal:    var(--brand-signal);  /* UI accent — the "signal" */
  --cd-dendrite:  var(--brand-signal);  /* active, live, success */
  --cd-membrane:  var(--brand-amber);   /* warmth, renewal, caution */
  --cd-danger:    #E5645C;              /* error, destructive */

  /* FILL-grade accents (§4c) — DARK VALUES, and the reason they are here.
     On the void a fill IS the accent: the split exists because phosphor and
     amber invert on paper, so in this grade these three are byte-identical
     to the tokens above and look pointless.

     They are not. They were emitted in the LIGHT BLOCK ONLY, which meant an
     unscoped rule reaching for one — the normal way to write a rule, and the
     way `background: var(--cd-signal-fill)` reads to anyone — resolved to
     NOTHING in dark, and an undefined custom property does not fall back to
     anything sensible: it makes the whole declaration invalid-at-computed-
     value-time, so the element inherits or goes transparent and no tool
     reports it. That is the exact failure --cd-danger already had (undefined
     in light, inherited the dark #E5645C at 2.73:1 on paper) reproduced
     in the other direction, and §14 documents it. A grade-split token has to
     be DEFINED in both grades even when one grade's value is a duplicate;
     only then does the light block override rather than introduce. */
  --cd-signal-fill:    #8FE3D0;  /* = the accent on the void */
  --cd-membrane-fill:  #F2C078;  /* = the accent on the void */
  --brand-amber-fill:  #F2C078;

  /* Text Stack. Gated: --cd-soma and --cd-dim are measured against BOTH
     grounds in this grade and refuse to emit below 4.5:1. --cd-ghost is
     1.99:1 and is NOT reading ink — placeholder and disabled only,
     never a word the user has to read. NOT READING INK. */
  --cd-soma:   #EEF0F2;
  --cd-dim:    #8A939B;
  --cd-ghost:  #3B434A;

  /* Structural */
  --cd-separator:         rgba(238, 240, 242, 0.07);
  --cd-separator-strong:  rgba(238, 240, 242, 0.13);

  /* The scrim — the one role here that does NOT invert. It is emitted
     only once, in this dark block, and the light block deliberately does
     not override it. See shared.scrim in tokens.json for why: a scrim
     dims the page behind a dialog, and a scrim that turns into paper on
     the light grade dims nothing. ground-rich (#030404) at 0.55. Identical in both grades, on purpose. */
  --cd-scrim:  rgba(3, 4, 4, 0.55);

  /* ─── The spacing scale (PORTAL-SPEC §3.3) ───
     The single highest-leverage token in this file. synap-portal was
     measured carrying 30+ distinct padding values and 20+ distinct gap
     values, and not one of them was a decision — they accumulated
     because there was nothing correct to reach for. Verbatim from
     SynapSpace, role names included, because the role name IS the
     token: ask for `card`, not for 16. PX and not rem — pt is px 1:1 at
     1x, so 16pt card padding lands as 16px, where 1rem is 16px only
     until something changes the root size and the scale silently stops
     matching itself.

     You cannot break a grid you never had. Pick the ROLE, not the number. */
  --cd-space-hair:     2px;   /* between a mark and its label */
  --cd-space-tight:    4px;   /* inside a chip; stacked metadata lines */
  --cd-space-snug:     8px;   /* related elements in a row; chip padding */
  --cd-space-element:  12px;  /* default gap between siblings in a group */
  --cd-space-card:     16px;  /* card interior padding; between cards in a list */
  --cd-space-group:    24px;  /* between groups within a section; panel interior */
  --cd-space-section:  40px;  /* between sections */
  --cd-space-hero:     64px;  /* around a hero moment, sparingly */

  /* Radii — the locked scale (§4). Four surface values plus one sub-surface
     step for MARKS. A heatmap cell, a legend swatch, a status dot or a 3px
     quote rule is not a container: its corner is a function of its own
     thickness. Ask --cd-radius-chip for an 8px square and you get a dot, and
     a year of activity reads as confetti instead of a grid. Anything wide
     enough to hold text is a surface — use chip and up. */
  --cd-radius-mark:   2px;
  --cd-radius-chip:   8px;
  --cd-radius-card:   12px;
  --cd-radius-panel:  16px;
  --cd-radius-sheet:  20px;

  /* Measure — how wide a column of text is allowed to get (§4).
     A window is not a measure: unconstrained, prose runs ~175 characters a
     line and the return sweep gets long enough that the eye loses its place.
     Percentages are of the PANE, not the viewport. */
  --cd-measure:         clamp(560px, 82%, 980px);  /* prose: ≈95–165 chars */
  --cd-measure-notice:  480px;                     /* glanced, not read */

  /* Typography — the three ROLES (§3.5). Three faces, no fourth stack, no
     system-ui. mono is apparatus (every label, value, key, chip, timestamp,
     column head, nav row); body is the serif and is for anything read as
     LANGUAGE; brand is the wordmark and the one hero numeral, nothing else. */
  --cd-font-body:   'Newsreader', 'Spectral', Georgia, 'Times New Roman', serif;
  --cd-font-mono:   'Spline Sans Mono', 'SF Mono', ui-monospace, monospace;
  --cd-font-brand:  'Bitcount Grid Double', 'Spline Sans Mono', monospace;

  /* ─── The type ramp (PORTAL-SPEC §3.4) ───
     RENDERED sizes — every rung is already through the Mac's scaled() =
     max(size x 1.32, 12), which is why there is no rung below 12px and
     why the nominal SynapFont numbers in the comments are NOT these
     numbers. mono(9), the 252-call-site workhorse, renders at 11.88 and
     clamps to 12. A port that copies the call-site numbers rebuilds the
     exact defect this ramp exists to kill: 303 sub-12px declarations
     inside a 0.5px band, which is not a scale, it is one
     undifferentiated grey field.

     Span 12 -> 84 = 7.0x. The portal's was 2.8x. The ramp is
     deliberately NARROW at the bottom — the Mac's hierarchy comes from
     weight, tracking, case and ink rather than size — so every rung
     must differ from its neighbour in at least TWO of those four, and
     the one hero numeral is what buys the span. Exactly one
     --cd-text-hero per data surface, and it is the record's own number,
     never a heading.
     Face is the role, not a family: mono x10, body x3, brand x1. */
  --cd-text-apparatus:  12px;    /* mono · mono(7/8/9) floored */
  --cd-text-detail:     13px;    /* mono · mono(10) */
  --cd-text-meta:       14.5px;  /* mono · mono(11) */
  --cd-text-control:    16px;    /* mono · mono(12) */
  --cd-text-row:        17px;    /* mono · mono(13) */
  --cd-text-body:       18.5px;  /* mono · mono(14) */
  --cd-text-headline:   21px;    /* mono · mono(16) */
  --cd-text-title:      24px;    /* mono · mono(18) */
  --cd-text-stat:       28px;    /* mono · mono(21) */
  --cd-text-glance:     33px;    /* mono · mono(25) */
  --cd-text-hero:       84px;    /* brand · display(64) */
  --cd-text-prose-sm:   13px;    /* body · sans(13) */
  --cd-text-prose:      15px;    /* body · sans(15) */
  --cd-text-prose-lg:   17px;    /* body · sans(17) */

  /* THE FLOOR. Nothing renders below this. Ever. Any reason. Emitted as
     a token so a call site and a lint rule ask the same source rather
     than both remembering the number. scaled(n) = max(n * factor, px).
     Nothing renders below `px`. Ever. Any reason. */
  --cd-text-floor:  12px;

  /* Tier Aliases */
  --cd-tier-enterprise:  var(--cd-axon);
  --cd-tier-personal:    var(--cd-signal);
  --cd-tier-business:    var(--cd-membrane);

  /* ─── Ink on a solid accent (§2.1) ───
     The Mac gets this for free: SynapTheme.onAccent runs a contrast
     pick at paint time. CSS has no contrast-color(), so the web cannot
     compute it — and without these two tokens there is no correct solid
     primary button, which is why the portal shipped none at all and its
     `primary` is really the Mac's SECONDARY register. These flip
     AGAINST the normal ink direction, and that is the whole reason they
     cannot be --cd-soma: in dark the accent fill is a light mint so the
     ink is the ground; in light the fill is a deep green so the ink is
     paper. Measured on the fill they sit on, not on the page.
     --cd-on-danger has exactly one consumer: the T3 confirm key (§4.2).
     Danger is ink and hairline everywhere else, never a filled slab. */
  --cd-on-signal:  #070809;  /* 13.43:1 on #8FE3D0 */
  --cd-on-danger:  #070809;  /* 6.02:1 on #E5645C */

  /* ─── Row hover (§2.1) ───
     ACHROMATIC, at an alpha. DataTable open-coded this as the signal
     accent at 0.05, and a TINTED row hover makes every row under the
     cursor look SELECTED. Selection is a state the user chose; hover is
     where the mouse happens to be. They must not share a colour. The
     Mac's light rowHover is an opaque paperFill because its rows sit on
     the ground — portal rows sit inside a card that is ALREADY
     --cd-paper-fill, so neutral ink at an alpha is the portable form of
     the same intent, and it is still achromatic. */
  --cd-row-hover:  rgba(238, 240, 242, 0.055);

  /* Transitions. `fast` is the Mac's easeOut(0.14) spelled explicitly: the
     difference from `ease` is not the 10ms, it is that `ease` has an ease-IN
     head, so a hover tint starts slow and reads as lag on exactly the
     interaction that has to feel instant. `press` is faster still — a control
     that takes as long to depress as it does to tint feels mushy. */
  --cd-transition-fast:    140ms cubic-bezier(0, 0, 0.58, 1);
  --cd-transition-press:   100ms cubic-bezier(0, 0, 0.58, 1);
  --cd-transition-normal:  0.3s ease;

  /* ─── Liquid Glass Tokens — Dark Theme defaults ───
     Signal at top-right, amber at bottom-left: 'signal in, memory
     remade'. 225deg points toward bottom-left. */
  --glass-bg: linear-gradient(
    225deg,
    rgba(143, 227, 208, 0.07) 0%,
    rgba(10, 13, 14, 0.55) 50%,
    rgba(242, 192, 120, 0.06) 100%
  );
  --glass-border:      rgba(143, 227, 208, 0.16);
  --glass-border-top:  rgba(238, 240, 242, 0.22);
  --glass-shadow-soft:   0 1px 0 rgba(238, 240, 242, 0.08) inset,
                         0 -1px 0 rgba(0, 0, 0, 0.45) inset,
                         0 18px 50px rgba(3, 4, 4, 0.55),
                         0 4px 12px rgba(0, 0, 0, 0.30);
  --glass-shadow-glossy: 0 1px 0 rgba(238, 240, 242, 0.20) inset,
                         0 -1px 0 rgba(0, 0, 0, 0.60) inset,
                         0 24px 64px rgba(3, 4, 4, 0.70),
                         0 6px 16px rgba(143, 227, 208, 0.10);
}

/* ─── Semantic Hues (§4b) — for charts, status dots, avatars, terminals ───
   Dentate has three HUES (phosphor, amber, steel), but a chart needs more
   separated marks than three, and when this table is absent every surface
   invents its own. That already happened: an audit separated phosphor from
   cyan by inventing #7FC8DE, a saturated blue that reads as another brand's
   accent, and the Mac had to reject it in code. The resolution is to
   separate by VALUE within a hue rather than by inventing one.

   Transcribed from TerminalTheme.dentateDark / .dentateLight. Do not
   re-derive by eye. --cd-hue-*-bright is the value step, not a second hue. */
:root {
  --cd-hue-cursor:     #F2C078;  /* amber ember — a FILL (§4c) */
  --cd-hue-selection:  #16231F;

  --cd-hue-black:           #05070A;
  --cd-hue-black-bright:    #8A939B;
  --cd-hue-red:             #E06552;
  --cd-hue-red-bright:      #F0796A;
  --cd-hue-green:           #6FD3A6;
  --cd-hue-green-bright:    #8AE7BC;
  --cd-hue-yellow:          #DFCB6E;
  --cd-hue-yellow-bright:   #F8D9A8;
  --cd-hue-blue:            #9FB4C7;
  --cd-hue-blue-bright:     #BCCBD9;
  --cd-hue-magenta:         #8FE3D0;
  --cd-hue-magenta-bright:  #F2C078;
  --cd-hue-cyan:            #4FBFA4;
  --cd-hue-cyan-bright:     #4FBFA4;
  --cd-hue-white:           #E4E9E5;
  --cd-hue-white-bright:    #F4F8F5;
}

/* ─── Light Theme Overrides (Daylight register) ───
   Warm paper ground; signal + amber darken for contrast but hold the
   same two-accent story.

   THE LIGHT GRADE IS NOT A VERBATIM PORT OF THE DARK ONE (§4c).
   Phosphor and amber INVERT on paper. On the void ground they are
   excellent — #8FE3D0 is 13.43:1 and #F2C078 is 12.01:1. On #E6E8E1 they
   collapse: #0E7C66 is only 4.15:1 (FAILS body text), #B3701D is 3.24:1
   (large/UI only), and the softs #2BA98E (2.37:1) and #D08A30 (2.31:1)
   fail everything. --cd-danger was undefined here entirely, so it
   inherited the dark #E5645C at 2.73:1 on paper.

   So the accents split into TEXT tokens and FILL tokens below, and the
   split is load-bearing: a *-fill token painted onto type ships failing
   text. build.mjs asserts it for every gradient it emits. Measurement
   trail: ARX htj1dhn3ca1l9fovyrni. */
:root[data-theme="light"] {
  --cd-void:     #E6E8E1;  /* soft phosphor-tinted paper, not white, easy on the eyes */
  --cd-surface:  #EEF1EA;  /* off-white card with a faint green undertone (no pure white) */
  --cd-raised:   #F1F3ED;
  --cd-float:    #EFF2EB;

  --cd-soma:   #171B18;
  --cd-dim:    #545E56;
  --cd-ghost:  #98A199;

  --cd-separator:         rgba(20, 30, 25, 0.07);
  --cd-separator-strong:  rgba(20, 30, 25, 0.12);

  /* TEXT-SAFE accents — the only ones that may paint type on paper, and
     every one of them measured here against the page ground AND the card
     before it is written. The page ground is the worst case in this grade:
     paper steps AWAY from dark ink, so a card flatters and a token checked
     only on --cd-paper-fill can be failing on --cd-void and read as green. */
  --cd-signal:     #0B6C59;  /* 5.14:1 on void, 5.57:1 on surface */
  --cd-dendrite:   #0B6C59;
  --cd-membrane:   #8F5613;  /* light amber TEXT token */
  --cd-danger:     #B3261E;  /* 5.29:1 — was undefined in light */
  --cd-axon:       #47657D;
  --brand-signal:  #0B6C59;
  --brand-amber:   #8F5613;
  --brand-steel:   #47657D;
  /* Phosphor deep, a value step below the accent — NOT a teal-blue.
     Dentate has three hues and cyan is not one of them (§4b). */
  --brand-signal-deep:  #084C40;  /* 8.82:1 on paper, 8.02:1 on void */
  --brand-amber-deep:   #8F5613;

  /* FILL-ONLY accents (§4c). NEVER type, NEVER an icon carrying meaning
     at small size — backgrounds, borders, rules, bars, swatches.
     The first three OVERRIDE the dark declarations above; they used to be
     declared here and nowhere else, which left them undefined in dark. */
  --cd-signal-fill:     #0E7C66;  /* 4.15:1 — demoted from text */
  --cd-membrane-fill:   #B3701D;  /* 3.24:1 — large/UI only */
  --brand-amber-fill:   #B3701D;
  --brand-signal-soft:  #2BA98E;  /* 2.37:1 — BANNED from paper text */
  --brand-amber-soft:   #D08A30;  /* 2.31:1 — BANNED from paper text */

  /* Channel tokens, light grade. These re-grade with the accent, which is
     the entire point: rgb(var(--brand-signal-rgb) / 0.18) written once
     paints phosphor on the void and deep green on paper.

     They carry the TEXT-safe base, not the fill. Channels are consumed at
     an alpha, so the fill's extra saturation would buy almost nothing at
     0.1 — but a channel token is the one place a value can escape to alpha
     1 (rgb(var(--x) / 1), or a call site that just drops the slash), and if
     it did, the fill grade would be failing text. Safe at every alpha. */
  --brand-signal-rgb:  11 108 89;
  --brand-amber-rgb:   143 86 19;
  --brand-steel-rgb:   71 101 125;
  --brand-danger-rgb:  179 38 30;
  --brand-ink-rgb:     23 27 24;
  --brand-ground-rgb:  230 232 225;

  /* Semantic hues, light grade (§4b). Both --cd-hue-magenta values are the
     FILL grade on paper (4.15:1 and 3.24:1) — they carry the accent ROLE,
     not permission to paint type. */
  --cd-hue-cursor:     #B3701D;
  --cd-hue-selection:  #DCE0D7;

  --cd-hue-black:           #171B18;
  --cd-hue-black-bright:    #545E56;
  --cd-hue-red:             #B8422F;
  --cd-hue-red-bright:      #C9503C;
  --cd-hue-green:           #1E6B4E;
  --cd-hue-green-bright:    #1E6B4E;
  --cd-hue-yellow:          #7A5B12;
  --cd-hue-yellow-bright:   #7A5B12;
  --cd-hue-blue:            #47657D;
  --cd-hue-blue-bright:     #47657D;
  --cd-hue-magenta:         #0E7C66;
  --cd-hue-magenta-bright:  #B3701D;
  --cd-hue-cyan:            #0B6659;
  --cd-hue-cyan-bright:     #0B6659;
  --cd-hue-white:           #98A199;
  --cd-hue-white-bright:    #171B18;
  /* ─── Paper (D3) ───
     Light is PAPER, not frosted glass. A frosted material over a warm
     ground resolves to grey, and grey slabs are what makes a light UI
     read as unstyled. These are the exact values from the Mac's
     SynapSurface: the ground lifted 0.44 toward white (which lands on
     --cd-raised #F1F3ED almost exactly — a card is BARELY off the
     ground, and the hairline plus the contact shadow do the separating),
     a 0.30 lift for panels nested inside a card, ink at 0.13 for the
     edge so it belongs to the paper rather than being drawn on top of
     it, and two shadows: a tight contact edge that sells "sheet resting
     on desk" plus a wide faint ambient for the lift. */
  --cd-paper-fill:         #F1F2EE;  /* ground + 0.44 → white */
  --cd-paper-fill-subtle:  #EEEFEA;  /* nested, 0.30 */
  --cd-paper-hairline:     rgba(23, 27, 24, 0.13);
  --cd-paper-shadow:      0 1px 1.5px rgba(23, 27, 24, 0.072),
                          0 5px 12px rgba(23, 27, 24, 0.039);
  --cd-paper-shadow-lift: 0 1px 1.5px rgba(23, 27, 24, 0.10),
                          0 10px 22px rgba(23, 27, 24, 0.055);

  /* Ink on a solid accent, light grade — and it INVERTS. The accent fill on
     paper is a deep green (#0E7C66), so the ink that sits on it is the
     lightest thing on hand that is not pure white (§11.4): the paper fill
     itself. This is the tight one in the whole file and the gate measures it
     on every build. Row hover flips the same way — neutral ink DARKENING the
     paper, still achromatic, still not the accent. */
  --cd-on-signal:  #F1F2EE;  /* 4.56:1 on #0E7C66 */
  --cd-on-danger:  #F1F2EE;  /* 5.81:1 on #B3261E */
  --cd-row-hover:  rgba(23, 27, 24, 0.05);

  /* The --glass-* tokens are DARK-ONLY from here. Light does not use
     them; .glass-card is overridden wholesale below. */
}

/* ─── Liquid Glass Card — raytrace-style mouse-reactive ───
   Cursor = moving point light source.
   --mx/--my drive the surface specular position (% inside card).
   --light-angle rotates a conic-gradient rim so the lit edge faces the cursor.
   --light-intensity attenuates rim brightness with cursor distance.
   All four vars are written by cortex-glass.ts on every pointermove. */
.glass-card {
  --mx: 50%;
  --my: 50%;
  --light-angle: 135deg;
  --light-intensity: 0.35;
  position: relative;
  background: var(--glass-bg);
  -webkit-backdrop-filter: blur(28px) saturate(140%);
          backdrop-filter: blur(28px) saturate(140%);
  border-radius: var(--cd-radius-panel);
  border: 1px solid transparent;
  box-shadow: var(--glass-shadow-soft);
  padding: 1.75rem;
  transition:
    box-shadow var(--cd-transition-normal),
    transform var(--cd-transition-normal);
  overflow: hidden;
  isolation: isolate;
}
/* SURFACE SPECULAR — Phosphor lensing, not a spotlight: the cursor area
   wakes the glass into a faint pool, screen-blended so it reads as light
   emitted from within the substrate. */
.glass-card::before {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background:
    radial-gradient(
      circle 420px at var(--mx) var(--my),
      rgba(143, 227, 208, 0.10) 0%,
      rgba(143, 227, 208, 0.06) 18%,
      rgba(143, 227, 208, 0.03) 38%,
      rgba(143, 227, 208, 0.012) 58%,
      transparent 78%
    ),
    radial-gradient(
      circle 680px at var(--mx) var(--my),
      rgba(242, 192, 120, 0.05) 0%,
      rgba(242, 192, 120, 0.015) 35%,
      transparent 75%
    );
  pointer-events: none;
  z-index: 0;
  opacity: 0.90;
  mix-blend-mode: screen;
  transition: opacity var(--cd-transition-normal);
}
/* RIM LIGHT — Conic gradient drawn only on the 1px border ring via the
   mask trick. */
.glass-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: conic-gradient(
    from calc(var(--light-angle) - 35deg),
    rgba(238, 240, 242, calc(0.45 * var(--light-intensity))) 0deg,
    rgba(238, 240, 242, calc(0.55 * var(--light-intensity))) 35deg,
    rgba(143, 227, 208, calc(0.45 * var(--light-intensity))) 90deg,
    rgba(238, 240, 242, 0.10) 180deg,
    rgba(242, 192, 120, calc(0.40 * var(--light-intensity))) 270deg,
    rgba(238, 240, 242, calc(0.45 * var(--light-intensity))) 360deg
  );
  -webkit-mask:
    linear-gradient(#fff 0 0) content-box,
    linear-gradient(#fff 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
  z-index: 1;
}
.glass-card:hover {
  box-shadow: var(--glass-shadow-glossy);
  transform: translateY(-2px);
}
.glass-card:hover::before { opacity: 1; }
.glass-card > * { position: relative; z-index: 2; }

/* ─── PAPER CARD (D3) — light is not glass wearing a light coat ───
   Locked: light cards are OPAQUE PAPER. A frosted material over a warm
   ground resolves to grey, and grey slabs are what made this read as
   unstyled. So light gets no backdrop-filter, no mouse-reactive specular
   pool and no conic rim: an opaque sheet a shade whiter than the ground,
   a 0.75px hairline of ink at 0.13 that belongs to the paper rather than
   being drawn on top of it, a tight contact shadow that sells "sheet
   resting on desk", a faint wide ambient for the lift, and one 135deg
   breath of the accent at 0.055 — enough to carry an identity, far too
   little to read as a coloured (or worse, grey) fill. A tinted sheet is
   a grey sheet; the saturated colour belongs on the MARKS inside.

   These rules come AFTER the dark ones on purpose. Equal specificity
   means source order decides, and the light block used to sit above the
   base .glass-card:hover / ::after — so the glossy glass shadow and the
   conic rim won anyway. Do not move this block back up.

   Recipe ported verbatim from SynapSurface in
   ~/Developer/SynapMac/Sources/SynapMac/Views/GlassBento.swift. */
:root[data-theme="light"] .glass-card {
  background: var(--cd-paper-fill);
  -webkit-backdrop-filter: none;
          backdrop-filter: none;
  border: 0.75px solid var(--cd-paper-hairline);
  box-shadow: var(--cd-paper-shadow);
}
/* Nested sheets sit one step quieter so depth still reads when they stack. */
:root[data-theme="light"] .glass-card .glass-card {
  background: var(--cd-paper-fill-subtle);
}
:root[data-theme="light"] .glass-card::before {
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--cd-signal-fill) 5.5%, transparent) 0%,
    transparent 100%
  );
  mix-blend-mode: normal;
  opacity: 1;
}
/* No rim light on paper — the hairline IS the edge. */
:root[data-theme="light"] .glass-card::after { display: none; }
:root[data-theme="light"] .glass-card:hover {
  box-shadow: var(--cd-paper-shadow-lift);
}
:root[data-theme="light"] .glass-card:hover::before { opacity: 1; }

/* ─── Shared Hero / Typography Utilities ─── */
.hero-eyebrow {
  display: block;
  font-family: var(--cd-font-mono);
  font-size: 0.6875rem;
  font-weight: 500;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--cd-dim);
  margin-bottom: 1.25rem;
}
/* Gradient text — paints any inline span along the signal→amber axis. */
.accent {
  background: linear-gradient(105deg, #8FE3D0 0%, #B5F0E2 40%, #F2C078 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
/* Gradient-clipped type is still TYPE: every stop has to be text-safe on
   paper (§4c), and build.mjs fails the build if one is not. The old ramp
   ran through #2BA98E (2.37:1) and landed on #B3701D (3.24:1) — a
   headline that failed at both ends. */
:root[data-theme="light"] .accent {
  background: linear-gradient(105deg, #0B6C59 0%, #084C40 45%, #8F5613 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}

/* ─── Dentate Wordmark — Bitcount Grid Double at "neuron weight" 400.
   The dot-matrix cells read as discrete memory cells.
   The phosphor gradient axis follows the cursor via --light-angle
   (written by cortex-glass.ts), so the wordmark surface catches light
   like the glass cards do.
   Legacy mark: Sixtyfour Convergence (D6). Not emitted. */
.dentate-wordmark {
  --light-angle: 225deg;
  font-family: 'Bitcount Grid Double', 'Spline Sans Mono', monospace;
  /* 400 is the locked "neuron weight" (§5, and §12 locks it). At 300 the
     dot-matrix cells thin out and stop reading as discrete memory cells,
     which is the whole metaphor. */
  font-weight: 400;
  font-variation-settings: 'wght' 400;
  letter-spacing: 0.03em;
  text-transform: lowercase;
  background: linear-gradient(var(--light-angle), #B5F0E2 0%, #8FE3D0 55%, #F2C078 115%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
  filter:
    drop-shadow(0 0 1px rgba(143, 227, 208, 0.45))
    drop-shadow(0 0 14px rgba(143, 227, 208, 0.28));
  transition: background 0.4s ease;
}
:root[data-theme="light"] .dentate-wordmark {
  background: linear-gradient(var(--light-angle), #0B6C59 0%, #0B6C59 55%, #8F5613 115%);
  -webkit-background-clip: text;
          background-clip: text;
  filter:
    drop-shadow(0 0 1px rgba(11, 108, 89, 0.25))
    drop-shadow(0 0 8px rgba(11, 108, 89, 0.14));
}

/* ─── Glow Utility Classes ───
   Utility box-shadows. DARK-GRADE VALUES, no light override today —
   they are emissive marks, and an emissive mark on paper is a different
   problem that has not been measured. Flagged, not guessed. */
.glow-resting  { box-shadow: 0 0 6px  rgba(143, 227, 208, 0.18); }
.glow-active   { box-shadow: 0 0 8px  rgba(143, 227, 208, 0.32); }
.glow-selected { box-shadow: 0 0 14px rgba(143, 227, 208, 0.45); }
.glow-ai       { box-shadow: 0 0 10px rgba(242, 192, 120, 0.35); }
.glow-live     { box-shadow: 0 0 8px  rgba(143, 227, 208, 0.32); }

@keyframes cd-breathe {
  0%, 100% { box-shadow: 0 0 6px rgba(143, 227, 208, 0.18); }
  50%      { box-shadow: 0 0 16px rgba(143, 227, 208, 0.40); }
}
.glow-breathe { animation: cd-breathe 2.5s ease-in-out infinite; }

/* ─── Halftone Background Utilities — the "cell grid" of the substrate ─── */
.halftone-subtle {
  background-image: radial-gradient(circle, rgba(143, 227, 208, 0.03) 1px, transparent 1px);
  background-size: 24px 24px;
}
.halftone-medium {
  background-image: radial-gradient(circle, rgba(143, 227, 208, 0.045) 1px, transparent 1px);
  background-size: 20px 20px;
}
.halftone-dense {
  background-image: radial-gradient(circle, rgba(242, 192, 120, 0.05) 1.2px, transparent 1.2px);
  background-size: 16px 16px;
}

/* .cortex-wordmark / .cortex-wordmark-lg were REMOVED 2026-08-07.
   They set text-transform: uppercase, which §6 forbids outright — the
   wordmark is lowercase, always. They had zero call sites left, so they
   were a trap waiting for someone to reach for the "wordmark" class and
   ship an all-caps mark. Use .dentate-wordmark. */

/* ─── Selection + Scrollbar ─── */
::selection {
  background-color: rgba(143, 227, 208, 0.28);
  color: var(--cd-soma);
}
/* Fill direction inverts (§4c): dark = void-ink on accent, light =
   PAPER-ink on accent. White-on-accent is NEVER correct in either
   grade. Both grades are a tint of the accent carrying the normal ink. */
:root[data-theme="light"] ::selection {
  background-color: rgba(11, 108, 89, 0.22);
  color: var(--cd-soma);
}
::-webkit-scrollbar       { width: 5px; height: 5px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--cd-ghost); border-radius: 4px; }
::-webkit-scrollbar-thumb:hover { background: var(--cd-dim); }
