/* chelseabrady.com — SoulSystems tokens, flattened.
   Generated from the design system's tokens/ layer, concatenated in @import order.
   Asset paths rewritten to be relative to THIS file (project root).
   Edit here freely; this is a standalone copy, not linked back to the system. */


/* ==== tokens/fonts.css ===================================================== */
/* =========================================================
   Nocturne — webfonts
   ---------------------------------------------------------
   Fraunces        display serif (variable: opsz, wght, SOFT, WONK)
   Figtree         body sans (replaced Manrope — closed, flat-terminalled
                   grotesque that agreed with neither Fraunces nor Kilimanjaro)
   JetBrains Mono  eyebrows, labels, meta, buttons

   SUBSTITUTION FLAGGED: the reference app screens use a flared,
   high-contrast serif for display (spurred terminals, teardrop
   dots) and a geometric-humanist sans for body. Neither is
   Fraunces or Manrope. Fraunces at WONK 1 / SOFT 100 is the
   closest available approximation. If licensed files exist,
   drop them in assets/fonts/ and replace this @import with
   @font-face rules.
   ========================================================= */
@import url('https://fonts.googleapis.com/css2?family=Fraunces:ital,opsz,wght,SOFT,WONK@0,9..144,100..900,0..100,0..1;1,9..144,100..900,0..100,0..1&family=Figtree:ital,wght@0,300..900;1,300..900&display=swap');

/* ---------------------------------------------------------
   KILIMANJARO SANS ROUND5 — the bold voice.
   Supplied by Chelsea as an .otf. One weight (Regular), a
   rounded geometric sans. It is not a body face and not a
   replacement for Fraunces: it is the word inside a heading
   that has to land hard, and it carries every label now that
   monospace is out of the system.
   --------------------------------------------------------- */
@font-face {
  font-family: 'Kilimanjaro Sans';
  src: url('./fonts/Kilimanjaro%20Sans%20Round5.otf') format('opentype');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}

/* ---------------------------------------------------------
   BLUSHY CHARM — the script accent.
   Supplied by Chelsea as a .ttf. One weight, real kerning.
   The SOFT counterpart to Kilimanjaro's hard emphasis: one
   lowercase word per screen, at display scale, never a label.
   Deep descender (-886/2048) so it needs vertical room.
   --------------------------------------------------------- */
/* Blushy Charm and Black Editorial Script were reviewed and set aside. Their
   @font-face blocks are removed so neither is fetched; both files remain in
   uploads/ if we want them back. CHOSEN: Fruitypops 400, below. */

/* ---------------------------------------------------------
   SCRIPT CANDIDATES — supplied .otf files, one weight each.
   Metrics differ enough that they are NOT drop-in swaps:

     Blushy Charm           asc 1671 desc -886 /2048 → line box 1.249em
     Black Editorial Script asc 1174 desc  -500/1000 → line box 1.674em
     NL_Tequila Sunrise     asc 1107 desc  -426/1000 → line box 1.533em

   The two new faces carry tall swashes, so they need a SMALLER font-size
   multiple and MORE leading than Blushy Charm. Sizes are set per face on the
   board rather than shared.
   --------------------------------------------------------- */
/* Tequila Sunrise Inky was reviewed and set aside — its @font-face is removed
   so it is not fetched. The file stays in uploads/ if we want it back. */
/* FRUITYPOPS — the first supplied face with a genuine second weight.
   The two files are a matched pair (410 glyphs each, asc 975/978, desc -400,
   upem 1000), but the Bold declares its own family name "Fruitypops Bold" with
   subfamily Regular and usWeightClass 400 — no bold bit anywhere. Registering
   both under ONE family with explicit weights is what turns them into a real
   axis, so `font-weight: 700` works instead of the browser faking it.
   Line box 1.375em of its own size → at 1.0em a line carrying it needs lh 1.38. */
@font-face {
  font-family: 'Fruitypops';
  src: url('./fonts/Fruitypops.ttf') format('truetype');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Fruitypops';
  src: url('./fonts/Fruitypops%20Bold.ttf') format('truetype');
  font-weight: 700; font-style: normal; font-display: swap;
}

/* NO MONOSPACE. JetBrains Mono is removed from the system, and no Courier of
   any kind is a substitute. Labels, eyebrows, meta and buttons are set in
   Kilimanjaro Sans uppercase with wide tracking, or Figtree 700 uppercase. */


/* ==== tokens/colors.css ==================================================== */
/* =========================================================
   COSMIC DESERT — COLOR

   THIS IS COSMIC DESERT. There is no separate predecessor.
   "Nocturne" was the working name while the night surfaces were
   being built; that work is merged and the name is retired except
   as the label on the dark mode. Everything the old Cosmic Desert
   documented — rust, ochre, sage, parchment, taupe, the signal
   spectrum, monospace labels — is superseded here, and survives
   ONLY as aliases so old markup keeps resolving. Do not author
   with any of those names.

   TWO modes, defined authoritatively in tokens/modes.css, which
   loads last and wins:
     [data-mode="dark"]  — Nocturne. Ink ground, cream type.  (default)
     [data-mode="light"] — Dawn. Cream ground, ink type.
   "warm" and "desert" are aliases of light, kept so older markup
   resolves. They are not separate modes and must not be treated
   as any.

   The palette is four hues assigned by ROLE — clay, rose, magenta,
   indigo — plus one cream and the ink ramp. See the block at the
   bottom of this file; everything above it is history.
   ========================================================= */

:root {
  /* ---------------------------------------------------------
     NIGHT SPINE — sampled from the reference screens
     --------------------------------------------------------- */
  --night-deep:    #05080f;   /* below the base: gradient tops, true void */
  --night:         #0a0e16;   /* THE page base. Cool blue-black — matches
                                 chelseabrady.com's theme colour exactly, so the
                                 marketing site and the products share one dark. */
  /* THE RAMP BENDS TOWARD VIOLET AS IT RISES.
     The old ramp (#121826 → #1a2234 → #232d42) was pure blue-grey, so a purple
     control had nothing beneath it to belong to — it was the only purple object
     in the room. Each step up now gains violet, which means the room itself
     travels navy → violet and the purple CTA is simply the brightest point on
     the surface ramp rather than an import. The base is untouched: it still
     matches chelseabrady.com exactly. */
  --night-raised:  #121026;   /* sheets, sub-surfaces */
  --night-lift:    #1b1633;   /* cards on night */
  --nebula:        #271f47;   /* tab bar, translucent chrome, chips */
  --nebula-soft:   #372c62;   /* raised chip / inactive segment */
  --night-blue:    #1a2234;   /* the previous blue-grey lift, preserved */
  --nebula-blue:   #232d42;   /* the previous blue-grey nebula, preserved */

  /* The violet-black the reference screens used, kept for reference and for
     anything that wants the old spine. Not the default any more. */
  --night-violet:  #12052d;

  /* MOONLIGHT IS BONE. The old value, #ECEED6, carried a green tint (G above R)
     and is out of the system — as is the green-grey dim, #C3C4B2. The light on
     night is now the same warm cream as the light ground, so the palette has
     exactly ONE cream and it cannot drift green again. The name is kept because
     it is referenced everywhere and it still describes the job. */
  --moonlight:     #f4ecde;   /* THE light on night: primary fg, FAB, active pill */
  --moonlight-dim: #d3cfc8;   /* warm neutral grey — no green, no brown */
  --moonlight-mute:#949cb0;   /* meta on night — 6.9:1 on the ground, 4.9:1 on nebula */
  --moonlight-low: #4a5566;   /* ornament / disabled */

  /* CONTROL CHROME — electric indigo.
     The old #492C9B was a red-leaning violet. Against a blue-black ground that
     is the worst possible distance: near enough to look like the same colour
     failing, far enough to argue with it. Rotating the hue toward blue puts it
     in the ground's own family, so it reads as the navy lit up rather than as
     a second, disagreeing colour — and it is MORE saturated, not less.
     Old values kept as --violet-royal if a page still wants them. */
  --dusk-violet:   #241f6e;   /* segmented-control track */
  /* BRIGHT PURPLE — the third brand colour. The old #4234d4 was blue-violet:
     it read as a generic SaaS button, not as purple. This is a true purple,
     pushed off the blue axis toward magenta. */
  /* PURPLE IS THE BRIDGE, NOT A THIRD PARTY.
     Terracotta is red-orange, the ground is blue: purple is the hue that sits
     between them, and its job is to close that gap. #7c31db failed at it by
     being too light and too clean — a UI colour dropped onto a photograph.
     Deepened and slightly greyed, it now lands at the top of the surface ramp
     and shares terracotta's red undertone, so it reads as a relative of both. */
  /* TWO COOLS, TWO JOBS — both taken from the iris ramp, so the controls and
     the glow are made of the same pigments instead of merely coexisting.
     #6b34c4 is gone: it was a mixed purple, neither magenta nor indigo, and a
     mixed hue on a violet ground reads as a mistake rather than a decision.

     ELECTRIC INDIGO drives controls. It belongs to the ground's own family, so
     a primary button reads as the navy brought up to voltage.
     MAGENTA-VIOLET is the accent. It carries the same red as the clay, which
     is what ties the warm and cool halves of the palette together. */
  --indigo-electric: #4f3fd6;   /* primary control */
  --indigo-el-soft:  #6a5ce8;   /* hover */
  --indigo-el-deep:  #3a2cab;   /* pressed */

  --violet:        #8e2c9c;   /* magenta-violet — the accent */
  --violet-soft:   #a83ab8;   /* hover lift */
  --violet-deep:   #6e1f7a;   /* pressed */
  --violet-mixed:  #6b34c4;   /* archived */
  --violet-neon:   #7c31db;   /* archived */
  --violet-blue:   #4234d4;   /* the previous blue-violet, preserved */

  /* ---------------------------------------------------------
     GLASS — THE INTEGRATOR
     A solid fill sits ON the ground; glass lets the ground through, so every
     accent ends up breathing the same air as the navy behind it. That shared
     air is what makes three colours read as one system instead of three
     designs. The saturate() is the load-bearing part: it enriches whatever is
     behind the panel, which is the difference between glass and fog.
     --------------------------------------------------------- */
  /* The CTA pane's own blur — lighter and less saturated than panel glass,
     because a pill is small and a heavy blur at that size reads as a smear.
     Both signature buttons point at this so tuning hits them together. */
  --pane-blur:         blur(14px) saturate(1.5);
  --glass-blur:        blur(16px) saturate(165%);
  --glass-blur-heavy:  blur(28px) saturate(180%);
  --glass-fill:        linear-gradient(150deg, rgba(244,236,222,0.070) 0%, rgba(244,236,222,0.028) 100%);
  --glass-fill-hi:     linear-gradient(150deg, rgba(244,236,222,0.115) 0%, rgba(244,236,222,0.050) 100%);
  --glass-fill-deep:   linear-gradient(150deg, rgba(30,24,58,0.72) 0%, rgba(16,14,34,0.62) 100%);
  /* NO BEVEL. A light catch along the top edge — hard line or soft gradient —
     is a dated treatment: it reads as a 2010s glass button, not as a modern
     panel. SoulSystems' own cards carry no highlight at all; the panel is
     defined by ONE warm hairline and the tonal step against the ground, and
     that is the whole material. Kept as a token so callers still resolve.
     A no-op SHADOW, not the keyword `none`: `none` inside a comma-separated
     box-shadow list makes the whole declaration invalid, which silently drops
     every other shadow on the element. */
  --glass-catch:       0 0 0 0 rgba(0,0,0,0);
  --glass-light:       linear-gradient(102deg, rgba(247,239,226,0.90) 0%, rgba(251,245,236,0.84) 46%, rgba(243,236,243,0.88) 100%);
  --glass-violet:      linear-gradient(140deg, rgba(79,63,214,0.54) 0%, rgba(58,44,171,0.40) 100%);
  --glass-violet-hi:   linear-gradient(140deg, rgba(106,92,232,0.64) 0%, rgba(79,63,214,0.46) 100%);
  --glass-magenta:     linear-gradient(140deg, rgba(142,44,156,0.52) 0%, rgba(110,31,122,0.38) 100%);
  --glass-terracotta:  linear-gradient(140deg, rgba(203,88,66,0.52) 0%, rgba(164,64,48,0.38) 100%);
  --glass-terracotta-hi: linear-gradient(140deg, rgba(220,110,89,0.64) 0%, rgba(203,88,66,0.46) 100%);

  /* The signature CTA fill. Reads as cream at a glance — the tint is a whisper,
     warm at the leading edge, barely cool at the trailing one, so the pill
     picks up the halo around it instead of competing with it. */
  /* Two layers. The radial keeps the middle of the pane pale so the label sits
     on cream, while the edges stay thin enough for the bloom to come through.
     A single flat alpha can only be one or the other. */
  --fill-signature: radial-gradient(125% 165% at 50% 44%,
      rgba(255,253,247,0.97) 0%,
      rgba(252,246,238,0.93) 42%,
      rgba(240,228,221,0.76) 78%,
      rgba(224,208,206,0.64) 100%);
  --violet-royal:  #492c9b;   /* the previous value, preserved */

  /* Terracotta is a STATEMENT colour — pullquotes, italic accents, editorial
     links. It is not a button colour. On this ground a terracotta fill reads
     dull and skin-toned; the control colour above is what carries life. */

  /* Wine wash — the "period" / high-intensity state tint */
  --wine:          #85113b;
  --wine-deep:     #4b0b34;
  --wine-soft:     #a8265a;

  /* ---------------------------------------------------------
     COSMIC DESERT — preserved, unchanged values
     --------------------------------------------------------- */
  --void:          #0d0b0a;
  --obsidian:      #141110;
  --basalt:        #1b1715;
  --stone:         #2a2320;
  --dust:          #3d342e;

  --parchment:     var(--bone);
  --parchment-dim: rgba(244, 236, 222, 0.82);
  --parchment-mute:rgba(244, 236, 222, 0.62);
  --parchment-low: rgba(244, 236, 222, 0.34);

  --bone:          #f4ecde;
  /* BROWNS, RETIRED. linen/sand/taupe were tan, khaki and brown; the warm
     #1d1814 ink is superseded by #0a0e16 below. Kept only as aliases so old
     references resolve. Never author with any of these names. */
  --linen:         var(--bone);
  --sand:          var(--bone);
  --taupe:         rgba(10, 14, 22, 0.66);

  /* TERRACOTTA — the statement accent.
     #C26B4A is the live SoulSystems terracotta. It measures 5.11:1 on the navy
     ground, so unlike the darker value it replaces it is AA at ANY text size —
     no size lock needed. The scale below is derived from it, not invented. */
  /* THE WARM ANCHOR.
     #c26b4a was a desaturated mid-orange: same value as everything around it,
     no conviction, and orange shares nothing with a violet ground. Rotated
     toward RED CLAY so it carries the same red undertone as the purple — that
     shared undertone is what makes them relatives — and pulled away from the
     mustard's yellow so the two warms stop colliding. 4.6:1 on the ground. */
  --terracotta:        #cb5842;   /* CHOSEN. Do not substitute. */
  --terracotta-deep:   #a44030;   /* light grounds — 4.83:1 on bone */
  --terracotta-deeper: #7a2c20;   /* warm-mode hover */
  /* Tints are mixed toward the GROUND, not toward white. Mixing a warm hue
     toward white lands on beige — the whole family goes pastel and skin-toned.
     Mixing toward the navy keeps the chroma and just lowers the light. */
  --terracotta-soft:   #dc6e59;
  --terracotta-pale:   color-mix(in srgb, var(--terracotta) 38%, var(--night));
  --terracotta-veil:   color-mix(in srgb, var(--terracotta) 14%, var(--night));
  --terracotta-link:   var(--terracotta);

  /* CLAY ROSE — GRADIENT ONLY.
     It sits between the clay and the magenta and does real work as a blend
     stop, but as a flat fill or as type it reads pink and drags the palette
     sweet. Never assign it to text, a button, an icon or a border: it is only
     ever one stop inside a ramp, next to something else. */
  --clay-rose:         #b8465a;

  /* THE SATURATION LIFT IS REVERSED.
     These were pushed to full chroma because they looked muddy on the navy.
     They looked muddy because the surface ramp had no violet in it — not
     because they were too dull. Lifting them fixed the symptom and produced
     three saturated hues shouting at each other. Now that the ramp bends
     navy → violet, the original dusty values read correctly: they are earth
     pigments, and earth pigments are supposed to be greyed. The lifted values
     are kept as --*-hot for anywhere that genuinely needs voltage. */
  --rust:          #b84a2c;
  --rust-deep:     #8e3418;
  --rust-soft:     #cc5733;
  --rust-hot:      #c8451f;
  --ember:         #c9531f;

  /* MUSTARD, AS A PIGMENT NOT A HIGHLIGHTER.
     #d6a61c was a hard chroma yellow — against a violet ground that reads as a
     warning label, not as brass. Returned to the greyed ochre this palette
     started with: enough yellow to separate from the clay, dirty enough to
     look like it was mixed rather than picked. 6.9:1 on the ground. */
  /* MUSTARD IS OUT OF THE PALETTE.
     Every version of it — chroma, greyed, brass — read as a third argument on
     a violet ground. The palette is now two accents and a light: purple as the
     bridge, red clay as the warm anchor, and PARCHMENT doing every job the
     mustard used to do (eyebrows, focus, prose links, defined channels).
     Parchment is warm enough to keep the desert in the room but has no chroma
     to fight with, so it never competes. --ochre is kept as an alias because
     it is referenced widely; the mustards below are archived, not in use. */
  --parchment:     var(--bone);
  --parchment-dim: var(--moonlight-dim);
  --parchment-hi:  var(--bone);
  --ochre:         var(--parchment);
  --ochre-deep:    var(--parchment-dim);
  --ochre-soft:    var(--parchment-hi);
  --ochre-mustard: #c4913a;   /* archived */
  --ochre-hot:     #d6a61c;   /* archived */
  --ochre-dusty:   #c78a3e;

  --indigo:        #3a4a7a;
  --indigo-deep:   #22336e;
  --indigo-soft:   #4f639e;
  --indigo-hot:    #3a55a8;   /* the lifted version, preserved */

  /* Wine and violet carry the cool end of the warm range so the palette does
     not run peach → beige → cream with nothing saturated in between. */
  --wine:          #a81e5c;
  --wine-deep:     #78103f;
  --violet-hot:    #6b3fa0;

  --coral:         #cf6247;
  --sage:          var(--indigo);
  --sage-dusty:    var(--indigo);
  --moss:          var(--indigo-deep);

  /* ---------------------------------------------------------
     SIGNAL SPECTRUM
     A continuous hue ramp used for DATA and STATE only —
     never for decoration, never for type. This is the one
     place Nocturne runs fully saturated. Read it as a wheel:
     red → pink → amber → green → azure → violet → back to red.
     --------------------------------------------------------- */
  --signal-red:     #f51a17;
  --signal-crimson: #dd1e1c;
  --signal-magenta: #da1580;
  --signal-pink:    #fe4c87;
  --signal-coral:   #fa6a4a;
  --signal-orange:  #f94f12;
  --signal-amber:   #f7a93b;
  --signal-lime:    #a6c058;
  --signal-green:   #32a652;
  --signal-teal:    #2e9ca8;
  --signal-azure:   #4e7baf;
  --signal-indigo:  #5063a1;
  --signal-violet:  #7c3bb8;
  --signal-purple:  #9a0aa1;

  /* Four named stops on the ramp — the arc. Any product that shows a
     long-arc progression (planner blocks, session energy, chart centres,
     capacity states) reads left to right through these. */
  --arc-1: var(--signal-red);      /* ignition / high intensity */
  --arc-2: var(--signal-amber);    /* build / rising */
  --arc-3: var(--signal-green);    /* peak / delivery */
  --arc-4: var(--signal-azure);    /* integrate / descending */

  /* ---------------------------------------------------------
     GRADIENTS
     Surfaces stay flat. Gradients belong to: sky washes,
     iridescent halos, spectrum rings, and pictorial art.
     --------------------------------------------------------- */
  --grad-night:      linear-gradient(180deg, var(--night-deep) 0%, var(--night) 45%, #131a2a 100%);
  --grad-wine:       linear-gradient(180deg, var(--night) 0%, #35101f 55%, var(--wine) 100%);
  --grad-dusk:       linear-gradient(180deg, var(--ochre-soft) 0%, var(--coral) 32%, var(--rust-deep) 68%, var(--indigo-deep) 100%);
  --grad-aurora:     linear-gradient(150deg, #2f1c75 0%, #7c3bb8 40%, #da1580 72%, #f94f12 100%);
  --grad-spectrum:   conic-gradient(from 220deg, #f51a17, #fe4c87, #f94f12, #f7a93b, #a6c058, #32a652, #2e9ca8, #4e7baf, #7c3bb8, #f51a17);
  /* Generic pearl iridescence — cool, unbranded. Kept for reference. */
  --grad-iridescent: linear-gradient(96deg, #f2c9c0 0%, #f6dcc0 18%, #eeeed8 40%, #cfe0d8 60%, #c6d3ea 80%, #d9c9e6 100%);

  /* THE DESERT IRIS — the brand's own rainbow. Every stop is a Cosmic Desert
     colour at full chroma: ochre → rust → wine → violet → indigo.
     It travels ONE direction around the wheel — warm into cool — and stops at
     indigo. Carrying on into teal and green closes the loop into a full
     spectrum, and a full spectrum reads as a Pride flag, not as a horizon.
     Nothing green or cyan is in the ramp for that reason. No stop is mixed
     toward white or grey — a desaturated stop makes the whole thing go dull. */
  --iris-1: var(--clay-soft);   /* apricot — was a hot ochre; gold in the glow read as
                          a sunrise stock gradient. Orange without yellow. */
  --iris-2: var(--clay);   /* rust */
  --iris-3: var(--rose);   /* clay rose — gradient-only pigment */
  --iris-3b: var(--rose-deep);  /* wine */
  --iris-4: var(--magenta);   /* magenta-violet */
  --iris-5: var(--indigo);   /* electric indigo */
  --iris-6: var(--indigo);   /* terminates on indigo — see note */
  --grad-iris: linear-gradient(96deg, var(--iris-1) 0%, var(--iris-2) 17%, var(--iris-3) 32%, var(--iris-3b) 45%, var(--iris-4) 62%, var(--iris-5) 85%, var(--iris-6) 100%);
  /* Pale version, for a fill that has dark type on it */
  --grad-iris-pale: linear-gradient(96deg,
    color-mix(in srgb, var(--iris-1) 58%, var(--bone)) 0%,
    color-mix(in srgb, var(--iris-2) 58%, var(--bone)) 19%,
    color-mix(in srgb, var(--iris-3) 58%, var(--bone)) 36%,
    color-mix(in srgb, var(--iris-4) 58%, var(--bone)) 55%,
    color-mix(in srgb, var(--iris-5) 58%, var(--bone)) 76%,
    color-mix(in srgb, var(--iris-6) 58%, var(--bone)) 100%);
  --grad-iris-ring: conic-gradient(from 210deg, var(--iris-1), var(--iris-2), var(--iris-3), var(--iris-3b), var(--iris-4), var(--iris-5), var(--iris-6), var(--iris-1));
  --grad-ember:      linear-gradient(160deg, #f94f12 0%, #f7a93b 45%, #12052d 100%);

  /* ---------------------------------------------------------
     SEMANTIC — Nocturne night is the default
     --------------------------------------------------------- */
  --bg:            var(--night);
  --bg-deep:       var(--night-deep);
  --bg-raised:     var(--night-raised);
  --bg-raised-2:   var(--night-lift);
  --bg-chrome:     rgba(18, 24, 38, 0.84);   /* tab bar / nav, expects blur */

  /* Scrims and overlays derive from the ground, so retuning the spine retunes
     every veil with it. */
  --scrim-modal:   color-mix(in srgb, var(--night-deep) 55%, transparent);
  --scrim-media:   color-mix(in srgb, var(--night-deep) 78%, transparent);
  --scrim-chip:    color-mix(in srgb, var(--night-deep) 60%, transparent);
  --surface-glass: color-mix(in srgb, var(--night-raised) 55%, transparent);

  /* ---------------------------------------------------------
     GLASS
     The SoulSystems surface. Not a tinted panel — four things
     at once: a low-opacity fill, a backdrop blur that SATURATES
     what is behind it (this is what makes it feel like glass and
     not fog), a bright hairline, and a light catch along the top
     edge. Any surface that floats over content uses it.
     --------------------------------------------------------- */
  --glass-fill:        rgba(255, 255, 255, .07);
  --glass-fill-raised: rgba(255, 255, 255, .11);
  --glass-fill-deep:   rgba(10, 14, 22, .62);
  --glass-blur:        blur(22px) saturate(155%);
  --glass-blur-heavy:  blur(40px) saturate(170%);
  --glass-border:      rgba(255, 255, 255, .13);
  --glass-border-lit:  rgba(255, 255, 255, .22);
  --glass-edge:        inset 0 1px 0 rgba(255, 255, 255, .17);
  --glass-shadow:      0 18px 48px -22px rgba(0, 0, 0, .8);

  --fg:            var(--moonlight);
  --fg-dim:        var(--moonlight-dim);
  --fg-mute:       var(--moonlight-mute);
  --fg-low:        var(--moonlight-low);
  --fg-on-light:   var(--night);             /* type on a moonlight/iridescent fill */

  --border:        rgba(244, 236, 222, 0.14);
  --border-soft:   rgba(244, 236, 222, 0.07);
  --border-strong: rgba(244, 236, 222, 0.30);

  --accent:        var(--violet);          /* control bodies only */
  --accent-statement: var(--terracotta);   /* pullquotes, italic accents, one CTA */
  --accent-alt:    var(--terracotta-soft);
  --accent-cool:   var(--indigo);
  --accent-hot:    var(--signal-red);

  /* Gold is DEMOTED. On a navy ground, gold-plus-navy reads collegiate, so ochre
     no longer owns eyebrows, focus or hover. It survives as a data colour (the
     bodygraph's defined channels), as a mid stop in the iris, and as an
     editorial accent in warm/desert mode where the ground is not navy. */
  --accent-data:   var(--ochre);

  --link:          var(--moonlight);
  --link-hover:    var(--terracotta-link);

  /* Semantic status — desert-tempered, not SaaS */
  --positive:      var(--indigo);
  --caution:       var(--clay-soft);
  --critical:      var(--rose);
  --info:          var(--magenta);
}




/* =========================================================
   THE PALETTE — ONE, NOT THREE
   ---------------------------------------------------------
   Everything above this line is history. This block is the
   whole palette: SIX hues and THREE neutrals. Nothing else
   is a colour — every other token in this file is now an
   alias pointing into these nine values.

   The six hues run warm to cool around a single arc:

     CLAY      the warm anchor. Statements, warm fills.
     ROSE      clay carried toward red. The bridge hue.
     MAGENTA   the accent. Carries clay's red into the cool half.
     INDIGO    controls. The ground brought up to voltage.
     SAGE      the one cool organic. Positive states, growth.
     PARCHMENT the warm light. Eyebrows, quiet type, warm ground.

   Why this fixes it: the old file had a desert set, a
   violet/wine chrome set, and a fourteen-stop saturated ramp
   that belonged to no brand at all. Three palettes reading as
   three designs. The ramp is gone — data now steps through
   the SAME six hues, which is why a chart and a button finally
   look like they come from one place.
   ========================================================= */
:root {
  --clay:      #cb5842;
  --rose:      #b8465a;
  --magenta:   #8e2c9c;
  --indigo:    #4f3fd6;

  /* SAGE AND PARCHMENT ARE OUT OF THE PALETTE.
     Sage was the one cool organic and parchment the warm light; both are gone.
     Sage read grey-green against four saturated hues, and every parchment step
     landed tan or brown (--parchment-deep var(--moonlight-dim) was a brown outright). They
     survive ONLY as aliases so the ~90 places that reference them keep
     resolving — sage now points at indigo, parchment at the cream. Do not
     reintroduce either as a colour. */
  --sage:      var(--indigo);
  --parchment: var(--bone);

  --ink:       #0a0e16;
  --bone:      #f4ecde;
  --moonlight: var(--bone);   /* same cream. #ECEED6 is gone — it read green. */

  /* Each hue gets exactly three steps: deep (pressed, light grounds),
     base, and soft (hover, lifted). No hue gets a fourth. */
  --clay-deep:      #a44030;  --clay-soft:      #dc6e59;
  --rose-deep:      #8e2f42;  --rose-soft:      #cc5c70;
  --magenta-deep:   #6e1f7a;  --magenta-soft:   #a83ab8;
  --indigo-deep:    #3a2cab;  --indigo-soft:    #6a5ce8;
  --sage-deep:      var(--indigo-deep);  --sage-soft:      var(--indigo-soft);
  --parchment-deep: var(--moonlight-dim); --parchment-soft: var(--bone);

  /* ---- Aliases. Old names, new palette. ---------------- */
  --terracotta: var(--clay);
  --terracotta-deep: var(--clay-deep);
  --terracotta-deeper: #7a2c20;
  --terracotta-soft: var(--clay-soft);
  --terracotta-link: var(--clay);
  --clay-rose: var(--rose);
  --rust: var(--clay); --rust-deep: var(--clay-deep);
  --rust-soft: var(--clay-soft); --rust-hot: var(--clay);
  --ember: var(--clay); --coral: var(--clay-soft);
  /* --ochre was parchment, so every eyebrow, focus ring, active tab and nav
     underline in the system rendered var(--bone). It now points at CLAY. */
  --ochre: var(--clay); --ochre-deep: var(--clay-deep);
  --ochre-soft: var(--clay-soft); --ochre-hot: var(--clay);
  --ochre-dusty: var(--clay-deep); --ochre-mustard: var(--clay-deep);
  --parchment-dim: var(--parchment-deep);
  --parchment-hi: var(--parchment-soft);
  --violet: var(--magenta); --violet-soft: var(--magenta-soft);
  --violet-deep: var(--magenta-deep); --violet-hot: var(--magenta);
  --indigo-electric: var(--indigo);
  --indigo-el-soft: var(--indigo-soft);
  --indigo-el-deep: var(--indigo-deep);
  --indigo-hot: var(--indigo);
  /* NOTE: --indigo-soft is NOT aliased here. It is defined above as #6a5ce8.
     This line previously read `--indigo-soft: var(--indigo-soft)`, a self
     reference — guaranteed-invalid at computed-value time, so the token
     resolved to nothing and silently took --indigo-el-soft, --signal-azure
     and --info down with it. Never alias a token to itself. */
  --dusk-violet: #241f6e;
  --wine: var(--rose); --wine-deep: var(--rose-deep); --wine-soft: var(--rose-soft);
  --sage-dusty: var(--indigo); --moss: var(--indigo-deep);

  /* ---- Data. Steps through the palette, warm to cool. ---
     Four stops, not fourteen. A long arc reads left to right
     as clay → rose → magenta → indigo — the same journey the
     signature gradient makes, so a progress ring and the CTA
     glow are visibly the same idea. */
  --arc-1: var(--clay);      /* ignition */
  --arc-2: var(--rose);      /* build */
  --arc-3: var(--magenta);   /* peak */
  --arc-4: var(--indigo);    /* integrate */

  /* ---- State. Four meanings, all inside the palette. ---- */
  --state-positive: var(--indigo);
  --state-caution:  var(--clay-soft);
  --state-critical: var(--rose);
  --state-info:     var(--magenta);

  /* Legacy signal-* names, folded onto the four stops so old
     markup keeps working without reintroducing a rainbow. */
  --signal-red: var(--clay);      --signal-crimson: var(--clay-deep);
  --signal-orange: var(--clay-soft); --signal-coral: var(--clay-soft);
  --signal-pink: var(--rose-soft); --signal-magenta: var(--rose);
  --signal-amber: var(--clay-soft); --signal-lime: var(--indigo-soft);
  --signal-green: var(--indigo);    --signal-teal: var(--indigo-deep);
  --signal-azure: var(--indigo-soft); --signal-indigo: var(--indigo);
  --signal-violet: var(--magenta); --signal-purple: var(--magenta-deep);
}


/* ==== tokens/typography.css ================================================ */
/* =========================================================
   NOCTURNE — TYPOGRAPHY TOKENS
   Three voices, unchanged from Cosmic Desert, retuned for
   small screens: Fraunces display / Manrope body / JetBrains
   Mono labels. What Nocturne adds is the WONK + SOFT axes on
   Fraunces (flared, slightly eccentric terminals) and a
   mobile-first end of the scale.
   ========================================================= */

:root {
  --font-display: 'Fraunces', 'Iowan Old Style', 'Cormorant Garamond', Georgia, serif;
  /* Warm humanist geometric — generous apertures, open counters. Round enough
     to sit with Kilimanjaro without going soft, steady enough for long copy.
     Replaced Manrope, which was flat-terminalled and belonged to neither face. */
  --font-body:    'Figtree', 'Helvetica Neue', -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  /* THE BOLD VOICE. Rounded geometric sans, one weight. Used for the word
     inside a heading that has to land, and for every label. */
  --font-accent:  'Kilimanjaro Sans', 'Figtree', system-ui, sans-serif;
  /* THE SCRIPT ACCENT. The soft counterpart to Kilimanjaro's hard emphasis.
     One lowercase word per screen, display scale only. Never a label. */
  --font-script:  'Fruitypops', 'Snell Roundhand', cursive;
  /* Monospace is OUT of the system. --font-mono is kept only so old markup
     resolves to something sane; it now points at the label face. Never
     Courier, never JetBrains, never any monospace. */
  --font-mono:    var(--font-accent);

  /* Fraunces variation presets — always set one, never leave default */
  --fv-display: "opsz" 144, "SOFT" 100, "WONK" 1;  /* hero words */
  --fv-heading: "opsz" 72,  "SOFT" 80,  "WONK" 1;  /* h1–h2 */
  --fv-title:   "opsz" 48,  "SOFT" 60,  "WONK" 1;  /* h3–h4, screen titles */
  --fv-text:    "opsz" 14,  "SOFT" 20,  "WONK" 0;  /* rare: serif at text size */

  /* Type scale — 1.25 around a 17px body; -xxs/-2xs added for mobile chrome */
  --fs-2xs:  0.625rem;   /* 10px  — dense mono ticks (day-of-week ruler) */
  --fs-xs:   0.72rem;    /* 11.5  — mono eyebrow */
  --fs-sm:   0.8125rem;  /* 13    — mono meta */
  --fs-base: 1.0625rem;  /* 17    — body */
  --fs-md:   1.1875rem;  /* 19    — lede, app body */
  --fs-lg:   1.5rem;     /* 24    — H4 */
  --fs-xl:   1.875rem;   /* 30    — H3 */
  --fs-2xl:  2.5rem;     /* 40    — H2, mobile hero */
  --fs-3xl:  3.5rem;     /* 56    — H1 */
  --fs-4xl:  5rem;       /* 80    — display */
  --fs-5xl:  7rem;       /* 112   — poster */

  --lh-tight:  1.04;
  --lh-snug:   1.18;
  --lh-normal: 1.55;
  --lh-loose:  1.7;

  --ls-tight:  -0.02em;
  --ls-snug:   -0.01em;
  --ls-normal: 0;
  --ls-wide:   0.08em;
  --ls-mono:   0.16em;   /* label tracking — was the mono eyebrow tracking */
  --ls-mono-x: 0.22em;   /* wide label, used on segmented controls / tab labels */

  /* BODY TRACKING. Manrope at 300 with no tracking sets thin and squished and
     is genuinely hard to read at length. Body copy is 400 minimum, with a
     little air between the letters and looser leading. */
  --ls-body:   0.014em;
  --lh-body:   1.72;

  --measure:    62ch;
  --measure-sm: 48ch;
  --measure-lg: 72ch;
  --measure-app: 34ch;   /* centered app prose — short lines, generous leading */
}


/* ==== tokens/spacing.css =================================================== */
/* =========================================================
   NOCTURNE — SPACING & LAYOUT
   4px grid. Editorial rhythm is generous; app rhythm is
   tighter and vertically centred.
   ========================================================= */

:root {
  --space-0:  0;
  --space-1:  0.25rem;   /*   4 */
  --space-2:  0.5rem;    /*   8 */
  --space-3:  0.75rem;   /*  12 */
  --space-4:  1rem;      /*  16 */
  --space-5:  1.5rem;    /*  24 */
  --space-6:  2rem;      /*  32 */
  --space-7:  3rem;      /*  48 */
  --space-8:  4rem;      /*  64 */
  --space-9:  6rem;      /*  96 */
  --space-10: 8rem;      /* 128 */
  --space-11: 12rem;     /* 192 — editorial section rhythm */

  --content-max: 1240px;
  --gutter: clamp(1.25rem, 4vw, 3rem);

  /* App frame — the reference screens are 1320×2868 @3x = 440×956 pt */
  --app-width:      440px;
  --app-height:     956px;
  --app-gutter:     20px;
  --app-safe-top:   56px;   /* below the status bar */
  --app-safe-bottom: 96px;  /* above the tab bar */
  --tabbar-height:  84px;
  --hit-min:        44px;   /* never smaller */
}


/* ==== tokens/effects.css =================================================== */
/* =========================================================
   NOCTURNE — EFFECTS: radii, borders, shadow, BLOOM, motion
   The bloom (radial glow) is the single biggest addition
   Nocturne makes to Cosmic Desert. Cosmic Desert says
   "prefer hairlines to shadow"; Nocturne says "prefer
   hairlines to shadow, and BLOOM instead of elevation."
   ========================================================= */

:root {
  /* ---------- RADII ----------
     Editorial stays restrained (0/2/4/6). App chrome is soft:
     controls are pills, cards are 20–28px. Documented divergence
     from Cosmic Desert's "pill for meta tags only" rule — on a
     touch surface the pill IS the control shape. */
  --radius-0: 0;
  --radius-1: 2px;    /* fields, tags (editorial) */
  --radius-2: 4px;    /* cards (editorial) */
  --radius-3: 6px;    /* larger cards (editorial) */
  --radius-4: 12px;   /* app: tiles, sheets' inner blocks */
  --radius-5: 20px;   /* app: standard card */
  --radius-6: 28px;   /* app: hero card, bottom sheet */
  --radius-pill: 999px;

  /* ---------- BORDERS ---------- */
  --hairline:        1px solid var(--border);
  --hairline-soft:   1px solid var(--border-soft);
  --hairline-strong: 1px solid var(--border-strong);
  --rule-2:          2px solid var(--border);

  /* ---------- SHADOW — warm, low, sparing ---------- */
  --shadow-0: none;
  --shadow-1: 0 1px 0 rgba(0,0,0,0.25);
  --shadow-2: 0 4px 16px rgba(0,0,0,0.30);
  --shadow-3: 0 20px 60px rgba(0,0,0,0.50);
  --shadow-sheet: 0 -12px 40px rgba(8, 1, 26, 0.65);

  /* ---------- BLOOM ----------
     A bloom is a soft radial light source BEHIND content, sized
     1.5–3× the element. Use as a background-image on a pseudo
     element, not as a box-shadow — box-shadow blooms clip.
     Opacity ceiling: 0.55. Above that it reads as a filter. */
  /* REPOINTED ONTO THE FOUR HUES. Every bloom here used to be mixed from the
     retired signal ramp — #F51A17 red, #7C3BB8 violet, #32A652 green, ochre,
     #4E7BAF azure. So the pigment was four hues while the LIGHT in the room was
     five other colours, which is much of why the glow read as generic: it
     belonged to no brand. Light and pigment are now the same four. */
  --bloom-clay:    radial-gradient(closest-side, rgba(203,88,66,0.68) 0%, rgba(203,88,66,0.30) 26%, rgba(203,88,66,0.08) 54%, transparent 78%);
  --bloom-rose:    radial-gradient(closest-side, rgba(184,70,90,0.68) 0%, rgba(184,70,90,0.30) 26%, rgba(184,70,90,0.08) 54%, transparent 78%);
  --bloom-magenta: radial-gradient(closest-side, rgba(142,44,156,0.68) 0%, rgba(142,44,156,0.30) 26%, rgba(142,44,156,0.08) 54%, transparent 78%);
  --bloom-indigo:  radial-gradient(closest-side, rgba(79,63,214,0.68) 0%, rgba(79,63,214,0.30) 26%, rgba(79,63,214,0.08) 54%, transparent 78%);
  --bloom-cream:   radial-gradient(closest-side, rgba(244,236,222,0.50) 0%, rgba(244,236,222,0.21) 26%, rgba(244,236,222,0.06) 54%, transparent 78%);
  /* Aliases — old names, four-hue light. */
  --bloom-red:    var(--bloom-clay);
  --bloom-rust:   var(--bloom-clay);
  --bloom-ochre:  var(--bloom-clay);
  --bloom-violet: var(--bloom-magenta);
  --bloom-green:  var(--bloom-indigo);
  --bloom-azure:  var(--bloom-indigo);
  /* The iris bloom: clay → rose → magenta → indigo, the same journey the arc
     makes. One per screen, behind the focal object only. */
  --bloom-iris:
    radial-gradient(closest-side, rgba(220,110,89,0.56) 0%, rgba(203,88,66,0.40) 22%, rgba(184,70,90,0.28) 40%, rgba(142,44,156,0.20) 56%, rgba(79,63,214,0.12) 70%, transparent 84%);

  /* ---------- HALO ----------
     A halo is a bloom tight around a control's own silhouette. TIGHT is the
     load-bearing word: a small radius with a hard falloff reads as light coming
     off an object. A wide, low-alpha spread reads as fog, which is what the
     earlier values did. Core alpha up, radius roughly halved, transparent by
     78% of the box instead of 100%.
     The iridescent halo under a moonlight pill is the signature
     primary-CTA treatment. */
  --halo-iridescent: 0 0 28px 6px rgba(242,201,192,0.45), 0 0 48px 18px rgba(198,211,234,0.28);
  /* The desert iris as a halo: warm inner ring, cool outer bleed. This is the
     primary-CTA glow on the cool blue-black spine. */
  --halo-iris:
    0 0 24px 5px rgba(201,96,74,0.44),
    0 0 44px 14px rgba(199,138,62,0.30),
    0 0 76px 30px rgba(90,107,154,0.24);
  /* THE SIGNATURE HALO.
     Directional, not concentric: warm hues sit low and left, cool hues high
     and right, so the pill reads as an object lit from two sides rather than
     a ring of colour. Offsets do the placing; large blurs keep it as light.
     This is the ONLY place the full spectrum appears on a control, and it is
     always OUTSIDE the silhouette — never in the fill. */
  --halo-signature:
    0 3px 8px -3px rgba(238,74,48,0.46),
    6px -3px 8px -4px rgba(78,124,232,0.42),
    0 5px 14px -5px rgba(150,72,220,0.34);
  --halo-signature-hover:
    0 4px 11px -2px rgba(238,74,48,0.60),
    7px -4px 11px -3px rgba(78,124,232,0.54),
    0 7px 18px -4px rgba(150,72,220,0.44);

  /* Single-hue halos. One colour blooming out from a solid pill reads as light;
     a rainbow blooming out reads as a sticker. */
  --halo-violet:
    0 0 13px 1px rgba(79,63,214,0.58),
    0 0 30px 6px rgba(79,63,214,0.26);
  --halo-terracotta:
    0 0 12px 1px rgba(194,107,74,0.62),
    0 0 28px 6px rgba(194,107,74,0.28);
  --halo-iris-soft:
    0 0 18px 4px rgba(227,164,138,0.30),
    0 0 40px 16px rgba(90,107,154,0.18);
  --halo-moonlight:  0 0 12px 1px rgba(244,236,222,0.44);
  --halo-red:        0 0 22px 3px rgba(245,26,23,0.45);
  --halo-green:      0 0 22px 4px rgba(50,166,82,0.50);
  --glow-ochre:      0 0 0 1px rgba(199,138,62,0.35), 0 0 24px rgba(199,138,62,0.18);

  /* ---------- TEXT GLOW ----------
     Display type on night gets a whisper of glow so it sits in
     the air rather than on a plate. Never on body copy. */
  --text-glow:        0 0 24px rgba(244,236,222,0.28);
  --text-glow-strong: 0 0 14px rgba(244,236,222,0.55), 0 0 40px rgba(244,236,222,0.22);

  /* ---------- THE SKY ----------
     Not a speckle. The old --starfield was seven cream dots at 0.35–0.75 alpha
     on one tile — evenly sized, evenly bright, evenly spread, which is exactly
     what a sky is not. Three things make it read as an actual sky:

     1. MAGNITUDE DISTRIBUTION. Real skies are mostly faint stars and a few
        bright ones. FAR is a dozen dots under 1px at 0.14–0.26; NEAR is five
        over 1.7px at 0.62–0.90. The old field had no faint population at all,
        so every star competed and the whole thing read as noise.
     2. COLOUR. Stars are not white. A few here are clay (warm giants) and a
        few indigo (hot blues), which also ties the sky to the palette instead
        of floating above it.
     3. UNEVEN DENSITY. --sky-band is a soft drift across the field, so it has
        a grain and a direction rather than a uniform sprinkle.

     The three tile sizes share no common factor, so the layers never align
     into a visible grid — that misalignment is what reads as depth. */
  --sky-far:
    radial-gradient(0.8px 0.8px at 11% 9%,   rgba(244,236,222,0.24), transparent 100%),
    radial-gradient(0.7px 0.7px at 29% 21%,  rgba(244,236,222,0.16), transparent 100%),
    radial-gradient(0.9px 0.9px at 44% 6%,   rgba(244,236,222,0.22), transparent 100%),
    radial-gradient(0.7px 0.7px at 58% 33%,  rgba(244,236,222,0.14), transparent 100%),
    radial-gradient(0.8px 0.8px at 71% 17%,  rgba(244,236,222,0.20), transparent 100%),
    radial-gradient(0.7px 0.7px at 88% 27%,  rgba(244,236,222,0.15), transparent 100%),
    radial-gradient(0.9px 0.9px at 7%  46%,  rgba(244,236,222,0.21), transparent 100%),
    radial-gradient(0.7px 0.7px at 23% 61%,  rgba(244,236,222,0.14), transparent 100%),
    radial-gradient(0.8px 0.8px at 39% 78%,  rgba(244,236,222,0.19), transparent 100%),
    radial-gradient(0.7px 0.7px at 54% 91%,  rgba(244,236,222,0.16), transparent 100%),
    radial-gradient(0.9px 0.9px at 77% 68%,  rgba(244,236,222,0.23), transparent 100%),
    radial-gradient(0.7px 0.7px at 93% 84%,  rgba(244,236,222,0.15), transparent 100%);
  /* One size per gradient. A short background-size list is CYCLED across the
     layers rather than stopping, so three sizes against 25 gradients assigns
     the wrong tile to most of them — which inverts the magnitude distribution
     the layers exist to create. Counts must match exactly: 12 / 8 / 5. */
  --sky-far-size:
    300px 380px, 300px 380px, 300px 380px, 300px 380px, 300px 380px, 300px 380px,
    300px 380px, 300px 380px, 300px 380px, 300px 380px, 300px 380px, 300px 380px;

  --sky-mid:
    radial-gradient(1.2px 1.2px at 16% 14%, rgba(244,236,222,0.44), transparent 100%),
    radial-gradient(1px   1px   at 41% 37%, rgba(244,236,222,0.32), transparent 100%),
    radial-gradient(1.3px 1.3px at 67% 11%, rgba(244,236,222,0.46), transparent 100%),
    radial-gradient(1px   1px   at 84% 43%, rgba(244,236,222,0.30), transparent 100%),
    radial-gradient(1.2px 1.2px at 12% 71%, rgba(203,88,66,0.34),   transparent 100%),
    radial-gradient(1px   1px   at 48% 63%, rgba(244,236,222,0.33), transparent 100%),
    radial-gradient(1.3px 1.3px at 73% 88%, rgba(244,236,222,0.40), transparent 100%),
    radial-gradient(1px   1px   at 92% 74%, rgba(79,63,214,0.36),   transparent 100%);
  --sky-mid-size:
    210px 250px, 210px 250px, 210px 250px, 210px 250px,
    210px 250px, 210px 250px, 210px 250px, 210px 250px;

  /* The few genuinely bright ones. Two carry a hue, and each has a faint bleed —
     a bright star in a real sky spills a little light around itself. */
  --sky-near:
    radial-gradient(2.2px 2.2px at 19% 23%, rgba(244,236,222,0.90), rgba(244,236,222,0.10) 60%, transparent 100%),
    radial-gradient(1.8px 1.8px at 62% 12%, rgba(220,110,89,0.78),  rgba(203,88,66,0.09)   62%, transparent 100%),
    radial-gradient(2px   2px   at 37% 69%, rgba(244,236,222,0.72), rgba(244,236,222,0.08) 60%, transparent 100%),
    radial-gradient(1.7px 1.7px at 81% 55%, rgba(106,92,232,0.74),  rgba(79,63,214,0.09)   62%, transparent 100%),
    radial-gradient(1.9px 1.9px at 55% 90%, rgba(244,236,222,0.62), rgba(244,236,222,0.07) 60%, transparent 100%);
  --sky-near-size:
    560px 640px, 560px 640px, 560px 640px, 560px 640px, 560px 640px;

  --sky-band:
    radial-gradient(128% 44% at 20% 6%,  rgba(244,236,222,0.045) 0%, transparent 64%),
    radial-gradient(96%  34% at 82% 94%, rgba(79,63,214,0.055)   0%, transparent 68%);

  /* ---------- THE SKY IN DAYLIGHT ----------
     THE POLARITY FLIPS. At night the sky is light on dark, so stars are light
     points. On cream nothing can be lighter than the page, so daylight form has
     to come from SHADE: clouds are warm masses laid over the cream, and the
     bright gaps between them are the cream itself. That is why dimming the
     starfield fails — wrong polarity, not wrong opacity.

     The cream ground is untouched. Everything here is whisper-alpha tint on top
     of it, 0.026–0.13, warm low-left and cool high-right — the same directional
     light the night bloom uses. Unrepeated, so they scale with the element and
     a hero and a phone each get one sky rather than a tiling pattern.

     NO ROSE. Rose on cream IS the pink — it was carrying two of the five cloud
     masses and dragged the whole sky candy. The day sky now leads with INDIGO,
     MAGENTA second, and clay only as a small ember at the horizon. That makes it
     a dawn before the sun is up rather than a sunrise postcard: less sweet, and
     more Cosmic Desert. */
  --day-clouds:
    radial-gradient(64% 38% at 16% 24%, rgba(79,63,214,0.072) 0%, transparent 70%),
    radial-gradient(50% 30% at 74% 10%, rgba(142,44,156,0.055) 0%, transparent 72%),
    radial-gradient(72% 34% at 86% 56%, rgba(79,63,214,0.058) 0%, transparent 68%),
    radial-gradient(56% 26% at 32% 72%, rgba(142,44,156,0.042) 0%, transparent 70%),
    radial-gradient(86% 30% at 48% 98%, rgba(79,63,214,0.050) 0%, transparent 66%),
    linear-gradient(179deg, transparent 22%, rgba(79,63,214,0.032) 31%, transparent 39%,
                            transparent 54%, rgba(142,44,156,0.026) 62%, transparent 70%);

  /* The horizon: a violet-blue pool low-left with one small clay ember at its
     core, and a magenta counter high-right. The ember is the ONLY warm thing in
     the daylight sky — enough to place a sun, not enough to go peach. */
  --day-sun:
    radial-gradient(58% 52% at 6% 98%,  rgba(106,92,232,0.115) 0%, rgba(79,63,214,0.055) 44%, transparent 74%),
    radial-gradient(26% 22% at 2% 100%, rgba(203,88,66,0.075) 0%, transparent 72%),
    radial-gradient(48% 42% at 94% 4%,  rgba(142,44,156,0.050) 0%, transparent 70%);

  /* THE ENGRAVED CHART — now an opt-in variant (.sky--chart), not the daylight
     default. Ink points on cream read as an antique celestial plate: right for a
     chart tool, wrong for a page that is meant to feel like a morning. */
  --sky-chart:
    radial-gradient(1.5px 1.5px at 19% 23%, rgba(10,14,22,0.30),  transparent 100%),
    radial-gradient(1.3px 1.3px at 62% 12%, rgba(164,64,48,0.34), transparent 100%),
    radial-gradient(1.4px 1.4px at 37% 69%, rgba(10,14,22,0.24),  transparent 100%),
    radial-gradient(1.2px 1.2px at 81% 55%, rgba(58,44,171,0.30), transparent 100%),
    radial-gradient(1.3px 1.3px at 55% 90%, rgba(10,14,22,0.20),  transparent 100%);
  --sky-chart-size:
    560px 640px, 560px 640px, 560px 640px, 560px 640px, 560px 640px;
  --sky-chart-fine:
    radial-gradient(1px 1px at 16% 14%, rgba(10,14,22,0.17), transparent 100%),
    radial-gradient(1px 1px at 41% 37%, rgba(10,14,22,0.12), transparent 100%),
    radial-gradient(1px 1px at 67% 11%, rgba(10,14,22,0.16), transparent 100%),
    radial-gradient(1px 1px at 84% 43%, rgba(10,14,22,0.11), transparent 100%),
    radial-gradient(1px 1px at 12% 71%, rgba(10,14,22,0.14), transparent 100%),
    radial-gradient(1px 1px at 48% 63%, rgba(10,14,22,0.12), transparent 100%),
    radial-gradient(1px 1px at 73% 88%, rgba(10,14,22,0.15), transparent 100%),
    radial-gradient(1px 1px at 92% 74%, rgba(10,14,22,0.11), transparent 100%);
  --sky-chart-fine-size:
    210px 250px, 210px 250px, 210px 250px, 210px 250px,
    210px 250px, 210px 250px, 210px 250px, 210px 250px;
  --sky-band-light:
    radial-gradient(128% 44% at 20% 6%,  rgba(10,14,22,0.030)  0%, transparent 64%),
    radial-gradient(96%  34% at 82% 94%, rgba(58,44,171,0.035) 0%, transparent 68%);

  /* Legacy. Points at the MID layer, so anything still calling --starfield gets
     the tuned population rather than the old uniform sprinkle. New work uses
     the .sky class, which stacks all three layers. */
  --starfield: var(--sky-mid);
  --starfield-size: var(--sky-mid-size);

  /* ---------- BLUR ---------- */
  --blur-chrome: blur(14px);   /* tab bar, nav */
  --blur-sheet:  blur(8px);    /* prose floating over collage / art */
  --blur-scrim:  blur(2px);

  /* ---------- MOTION ---------- */
  --ease-reveal: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-ui:     cubic-bezier(0.4, 0, 0.2, 1);
  --ease-slow:   cubic-bezier(0.83, 0, 0.17, 1);

  --dur-fast:   160ms;
  --dur-base:   240ms;
  --dur-mid:    400ms;
  --dur-reveal: 640ms;
  --dur-slow:   900ms;
  --dur-orbit:  60s;    /* motif rotation, 40–80s */
  --dur-breathe: 6s;    /* bloom pulse — slow, barely perceptible */
}


/* ==== tokens/base.css ====================================================== */
/* =========================================================
   NOCTURNE — BASELINE + SEMANTIC PATTERN CLASSES
   ========================================================= */

html {
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-body);
  font-size: 17px;
  line-height: var(--lh-normal);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
body { margin: 0; background: var(--bg); color: var(--fg); }

*, *::before, *::after { box-sizing: border-box; }

/* ---------------- Display / headings ---------------- */
.display, h1.display {
  font-family: var(--font-display);
  font-size: clamp(3rem, 7vw, var(--fs-4xl));
  font-weight: 350;
  font-variation-settings: var(--fv-display);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--fg);
  text-wrap: balance;
  margin: 0;
}
h1, .h1 {
  font-family: var(--font-display); font-size: var(--fs-3xl); font-weight: 350;
  font-variation-settings: var(--fv-heading);
  line-height: var(--lh-tight); letter-spacing: var(--ls-tight);
  color: var(--fg); text-wrap: balance; margin: 0;
}
h2, .h2 {
  font-family: var(--font-display); font-size: var(--fs-2xl); font-weight: 350;
  font-variation-settings: var(--fv-heading);
  line-height: var(--lh-snug); letter-spacing: var(--ls-snug);
  color: var(--fg); text-wrap: balance; margin: 0;
}
h3, .h3 {
  font-family: var(--font-display); font-size: var(--fs-xl); font-weight: 400;
  font-variation-settings: var(--fv-title);
  line-height: var(--lh-snug); letter-spacing: var(--ls-snug);
  color: var(--fg); margin: 0;
}
h4, .h4 {
  font-family: var(--font-display); font-size: var(--fs-lg); font-weight: 400;
  font-variation-settings: var(--fv-title);
  line-height: var(--lh-snug); color: var(--fg); margin: 0;
}

/* Cosmic Desert signature: italic phrase inside a heading, recolored.
   TERRACOTTA is the statement colour — on the cool blue-black spine it is the
   complement of the ground, so it carries. (It only went muddy on the old
   violet-black base.) Ochre stays the SYSTEM colour: eyebrows, focus, hover. */
h1 em, h2 em, h3 em, .display em, .accent-italic {
  font-style: italic; font-weight: 350; color: var(--terracotta);
  font-variation-settings: "opsz" 72, "SOFT" 100, "WONK" 1;
}
.accent-italic--gold { color: var(--clay-text); }
.accent-italic--rust { color: var(--clay); }
.accent-italic--rust { color: var(--terracotta); }
.accent-italic--pink { color: var(--signal-pink); }

/* Display type on night, floating in air */
.glow      { text-shadow: var(--text-glow); }
.glow--hi  { text-shadow: var(--text-glow-strong); }

/* ---------------- Body ---------------- */
p, .p {
  font-family: var(--font-body); font-size: var(--fs-base); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: var(--ls-body); color: var(--fg-dim);
  max-width: var(--measure); margin: 0; text-wrap: pretty;
}
.lede {
  font-family: var(--font-body); font-size: var(--fs-md); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: var(--ls-body);
  color: var(--fg); max-width: var(--measure);
}
/* App prose: centred, short measure, generous leading */
.prose-app {
  font-family: var(--font-body); font-size: var(--fs-md); font-weight: 400;
  line-height: var(--lh-body); letter-spacing: var(--ls-body);
  color: var(--fg); text-align: center;
  max-width: var(--measure-app); margin-inline: auto; text-wrap: pretty;
}

/* The bold voice inside a heading. Kilimanjaro is uppercase-only here and set
   slightly smaller than the serif around it so their cap heights agree. */
/* Element-qualified on purpose. A `:where()` theme reset contributes ZERO
   specificity, so a bare `.bold-word` / `.script-word` ties with it at (0,1,0)
   and loses on source order — the accent silently falls back to the surrounding
   family. Qualifying with the element lifts these to (0,1,1). */
span.bold-word, em.bold-word, b.bold-word, .bold-word {
  font-family: var(--font-accent); font-style: normal; font-weight: 400;
  font-size: 0.84em; text-transform: uppercase; letter-spacing: -0.005em;
  font-variation-settings: normal; color: inherit;
}

/* THE SCRIPT WORD — the other kind of emphasis.
   Kilimanjaro lands hard: uppercase, structural, stamped. This lands soft:
   lowercase, personal, handwritten. They are two answers to the same job, so
   they NEVER appear in the same heading — two emphasis faces in one line is a
   ransom note. Rules, all load-bearing:
     · ONE script word per screen. Not per section. Per screen.
     · Display scale only, 40px floor. Never a label, button, meta or datum.
     · Lowercase always. Never uppercase — scripts have no capitals worth the name.
     · Never tracked. Letter-spacing breaks the joins between letters, which is
       the entire reason to use a script.
     · Its descender is deep, so the line it sits on needs line-height ≥ 1.15
       and no tight bottom margin, or the tails collide with the next line. */
span.script-word, em.script-word, .script-word {
  font-family: var(--font-script); font-style: normal; font-weight: 400;
  /* FRUITYPOPS 400. A monoline script with a bouncing baseline. It ships a
     metrics-compatible 700 as well, but 400 is the chosen voice — the bold is
     available if a context genuinely needs it, without reflowing the line.
     LEADING IS ARITHMETIC: its own line box is (975+400)/1000 = 1.375em of its
     size, so at 1.0em a line carrying it needs 1.4em of leading. Either set
     that, or put the script on its own final line with padding-bottom on the
     block — then the serif above keeps tight display leading.
     THE LEFT MARGIN IS LOAD-BEARING: the entry stroke has almost no left
     sidebearing, so without it the first letter collides with the preceding
     word. A margin rather than a literal space, so it cannot break at a line end. */
  font-size: 1em;
  margin-left: .14em;
  white-space: nowrap;   /* a phrase broken mid-join defeats the point */
  -webkit-text-stroke: var(--script-stroke, 0) currentColor;
  paint-order: stroke fill;
  letter-spacing: 0; text-transform: none;
  font-variation-settings: normal; line-height: 1;
  color: var(--clay);
}
small, .small { font-size: var(--fs-sm); color: var(--fg-mute); }

/* ---------------- Labels (no monospace anywhere) ---------------- */
.mono {
  font-family: var(--font-accent); font-size: var(--fs-xs); font-weight: 400;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-dim);
}
.eyebrow {
  font-family: var(--font-accent); font-size: var(--fs-xs); font-weight: 400;
  letter-spacing: var(--ls-mono); text-transform: uppercase;
  color: var(--fg-dim); display: inline-block; margin: 0 0 var(--space-4);
}
/* On night, an eyebrow that labels a screen section goes moonlight,
   not ochre — ochre is reserved for editorial and hover states. */
.eyebrow--moonlight { color: var(--fg); }
.eyebrow--mute { color: var(--fg-mute); }
.meta {
  font-family: var(--font-accent); font-size: var(--fs-sm);
  letter-spacing: var(--ls-wide); color: var(--fg-mute);
}
.tick {
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 400;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute);
}

/* ---------------- Pullquote ---------------- */
/* Size-locked: terracotta is AA-large only on the ground. */
.pullquote {
  font-family: var(--font-display); font-style: italic; font-weight: 350;
  font-size: var(--fs-xl); font-variation-settings: var(--fv-title);
  line-height: var(--lh-snug); color: var(--terracotta); text-align: center;
  max-width: var(--measure-sm); margin: var(--space-7) auto; text-wrap: balance;
}
.pullquote--ochre-alt { color: var(--clay-text); }
.pullquote--rust { color: var(--terracotta); }
.pullquote--pink { color: var(--signal-pink); }

code, kbd, samp {
  font-family: var(--font-accent); font-size: 0.9em; color: var(--terracotta-link);
  background: var(--bg-raised); padding: 0.1em 0.35em; border-radius: var(--radius-1);
}

/* ---------------- Links ---------------- */
a { color: var(--link); text-decoration: none; transition: color var(--dur-base) var(--ease-ui); }
a:hover { color: var(--link-hover); }
.link-grow { position: relative; color: var(--fg); }
.link-grow::after {
  content: ""; position: absolute; left: 0; bottom: -2px;
  width: 0; height: 1px; background: currentColor;
  transition: width 320ms var(--ease-ui);
}
.link-grow:hover::after { width: 100%; }

/* =========================================================
   NOCTURNE UTILITIES
   ========================================================= */

/* Night ground: gradient + starfield in one element */
.nocturne-ground { position: relative; background: var(--grad-night); isolation: isolate; }
.nocturne-ground::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: var(--starfield);
  background-size: var(--starfield-size);
  background-repeat: repeat;
  opacity: 0.9;
}
.nocturne-ground > * { position: relative; z-index: 1; }

/* THE SKY.
   Three tiled layers of differing magnitude plus a density drift. Put it on a
   dark ground and it is a night sky; the SAME class on a light ground inverts
   to an engraved star chart, because pale dots cannot exist on cream. Depth
   comes from the three tile sizes sharing no factor, so the layers never align.
   Two pseudo elements: ::before carries the stars, ::after the density drift. */
.sky { position: relative; isolation: isolate; }
.sky::before, .sky::after {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
}
.sky::before {
  background-image: var(--sky-near), var(--sky-mid), var(--sky-far);
  background-size: var(--sky-near-size), var(--sky-mid-size), var(--sky-far-size);
  background-repeat: repeat;
}
.sky::after { background-image: var(--sky-band); }
.sky > * { position: relative; z-index: 1; }
/* Fixed variant — the sky stays put while content moves across it, so it reads
   as the room the page is in rather than a texture the page carries. */
.sky--fixed::before, .sky--fixed::after { position: fixed; }

/* DAYLIGHT. Not the starfield dimmed — the polarity inverted. Clouds are warm
   shade laid on the cream; the bright gaps are the cream itself. Unrepeated, so
   one sky scales to the element instead of tiling. */
[data-mode="light"] .sky::before, [data-mode="light"].sky::before,
[data-mode="warm"]  .sky::before, [data-mode="warm"].sky::before {
  background-image: var(--day-clouds);
  background-size: 100% 100%;
  background-repeat: no-repeat;
}
[data-mode="light"] .sky::after, [data-mode="light"].sky::after,
[data-mode="warm"]  .sky::after, [data-mode="warm"].sky::after {
  background-image: var(--day-sun);
  background-size: 100% 100%;
  background-repeat: no-repeat;
}

/* Opt-in: the engraved celestial plate, for chart tools rather than marketing.
   Ink points on cream — a document, not a time of day. */
[data-mode="light"] .sky--chart::before, [data-mode="light"].sky--chart::before,
[data-mode="warm"]  .sky--chart::before, [data-mode="warm"].sky--chart::before {
  background-image: var(--sky-chart), var(--sky-chart-fine);
  background-size: var(--sky-chart-size), var(--sky-chart-fine-size);
  background-repeat: repeat;
}
[data-mode="light"] .sky--chart::after, [data-mode="light"].sky--chart::after,
[data-mode="warm"]  .sky--chart::after, [data-mode="warm"].sky--chart::after {
  background-image: var(--sky-band-light);
  background-size: auto;
}

/* Starfield as a standalone layer */
.starfield {
  position: absolute; inset: 0; pointer-events: none;
  background-image: var(--starfield);
  background-size: var(--starfield-size);
  background-repeat: repeat;
}

/* Bloom: put on a positioned wrapper; sized by --bloom-size */
.bloom { position: relative; }
.bloom::before {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: var(--bloom-size, 220%); aspect-ratio: 1;
  transform: translate(-50%, -50%);
  background-image: var(--bloom, var(--bloom-violet));
  pointer-events: none; z-index: -1;
}
.bloom--red    { --bloom: var(--bloom-red); }
.bloom--green  { --bloom: var(--bloom-green); }
.bloom--azure  { --bloom: var(--bloom-azure); }
.bloom--cream  { --bloom: var(--bloom-cream); }
.bloom--ochre  { --bloom: var(--bloom-ochre); }

@keyframes nocturne-breathe {
  0%, 100% { opacity: 0.82; transform: translate(-50%, -50%) scale(1); }
  50%      { opacity: 1;    transform: translate(-50%, -50%) scale(1.06); }
}
.bloom--breathe::before {
  animation: nocturne-breathe var(--dur-breathe) var(--ease-slow) infinite;
}

/* Chrome bar: translucent nebula + blur */
.chrome {
  background: var(--glass-fill-deep);
  box-shadow: var(--glass-catch);
  -webkit-backdrop-filter: var(--glass-blur-heavy);
  backdrop-filter: var(--glass-blur-heavy);
  border-top: var(--hairline-soft);
}

/* Hairline card on night */
.card-night {
  background: var(--surface-glass);
  border: var(--hairline-soft);
  border-radius: var(--radius-5);
  transition: border-color var(--dur-base) var(--ease-ui), transform var(--dur-base) var(--ease-ui);
}
.card-night:hover { border-color: var(--border-strong); transform: translateY(-2px); }

@keyframes nocturne-orbit { to { transform: rotate(360deg); } }
.orbit    { animation: nocturne-orbit var(--dur-orbit) linear infinite; }
.orbit--ccw { animation-direction: reverse; }

/* Brand SVGs inherit currentColor */
.wordmark, .motif { color: var(--fg); fill: currentColor; }
.wordmark svg path, .motif svg path, img.wordmark, img.motif { fill: currentColor; }
.cls-1 { fill: currentColor; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
}


/* ---------------------------------------------------------
   AMBIENT FIELD
   Glass only reads if there is something behind it to blur and
   saturate. On a flat near-black ground it is invisible, and the
   page goes dull no matter how saturated the accents are. This
   lays three large, soft iris blooms into the ground itself —
   fixed, so they behave like light in the room rather than
   decoration that scrolls. Low alpha: felt, not seen.
   --------------------------------------------------------- */
.ambient { position: relative; }
.ambient::before {
  content: ""; position: fixed; inset: -20vh -10vw; z-index: 0; pointer-events: none;
  /* TWO temperatures only. A room is lit by a warm source and a cool one —
     running the whole iris through the ground turns the page into a spectrum,
     which reads as a rainbow rather than as light. Warm low, cool high. */
  background:
    radial-gradient(58vw 52vh at 88% 4%,  color-mix(in srgb, var(--iris-5) 46%, transparent) 0%, transparent 68%),
    radial-gradient(62vw 54vh at 6% 82%,  color-mix(in srgb, var(--iris-2) 38%, transparent) 0%, transparent 70%);
  filter: blur(24px); opacity: .8;
}
.ambient > * { position: relative; z-index: 1; }
[data-mode="warm"] .ambient::before,
[data-mode="warm"].ambient::before { opacity: .42; }
@media (prefers-reduced-motion: no-preference) {
  .ambient::before { animation: ambient-drift 48s var(--ease-soft, ease-in-out) infinite alternate; }
}
@keyframes ambient-drift {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(-2.5%, 1.5%, 0) scale(1.06); }
}

/* ==== tokens/elements.css ================================================== */
/* =========================================================
   NOCTURNE — ELEMENTS
   Real, shippable component CSS. The boards in `board/` demo
   these exact classes; consumers get them from styles.css.

   Everything is mode-agnostic: it reads semantic tokens only
   (--bg, --fg, --border, --accent…), so a single markup tree
   works in night, desert and warm mode.

   Naming: .n- prefix, block__element--modifier.
   ========================================================= */

/* ---------------------------------------------------------
   LAYOUT
--------------------------------------------------------- */
.n-shell { width: 100%; }
.n-wrap { width: 100%; max-width: var(--content-max); margin-inline: auto; padding-inline: var(--gutter); }
.n-wrap--narrow { max-width: 760px; }
.n-wrap--wide { max-width: 1440px; }
.n-section { padding-block: clamp(4rem, 9vh, 7.5rem); }
.n-section--tight { padding-block: clamp(2.5rem, 5vh, 4rem); }
.n-stack { display: grid; gap: var(--space-5); }
.n-stack--sm { display: grid; gap: var(--space-3); }
.n-stack--lg { display: grid; gap: var(--space-7); }
.n-row { display: flex; flex-wrap: wrap; gap: var(--space-4); align-items: center; }
.n-split { display: grid; gap: var(--space-8); grid-template-columns: 1fr 1fr; align-items: center; }
.n-split--asym { grid-template-columns: 5fr 6fr; }
.n-split--asym-r { grid-template-columns: 6fr 5fr; }
.n-grid-3 { display: grid; gap: var(--space-5); grid-template-columns: repeat(3, 1fr); }
.n-grid-2 { display: grid; gap: var(--space-5); grid-template-columns: repeat(2, 1fr); }
.n-grid-4 { display: grid; gap: var(--space-4); grid-template-columns: repeat(4, 1fr); }

@media (max-width: 1024px) {
  .n-split, .n-split--asym, .n-split--asym-r { grid-template-columns: 1fr; gap: var(--space-6); }
  .n-grid-3, .n-grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 640px) {
  .n-grid-2, .n-grid-3, .n-grid-4 { grid-template-columns: 1fr; }
  .n-section { padding-block: clamp(2.5rem, 8vh, 4rem); }
}

/* ---------------------------------------------------------
   BUTTONS — FOUR VARIANTS, AND THAT IS THE WHOLE SET.

   It was eight: iridescent, halo, terracotta, iris, moonlight, primary, ghost,
   editorial. Six of them were FILLED, several were the same idea at a different
   alpha, and when six variants can all be "the button" no screen can say which
   one is. Reduced to:

     .n-btn--primary    the signature. One per screen.
     .n-btn--magenta    the statement CTA. Magenta-deep. The loudest fill in the set.
     .n-btn--aura       the glowing CTA — solid fill, light pooling outside it.
                        One hue knob (clay / rose / magenta / indigo / iris).
     .n-btn--ghost      secondary, outlined.
     .n-btn--editorial  a link with a rule under it, not a pill.

   Sizes (--sm / --lg / --full) are not variants. The retired names are folded
   into the selector lists below, so existing markup keeps working and there is
   only one set of declarations to tune.

   HOVER IS A SMALL STEP, NEVER A NEW HUE. A button that changes colour family on
   hover reads as a second active state rather than a hovered one.
--------------------------------------------------------- */
.n-btn {
  --btn-pad: 15px 32px;
  appearance: none;
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  min-height: var(--hit-min);
  padding: var(--btn-pad);
  border: 1px solid transparent;
  /* --radius-3, NOT --radius-pill. Radii in this system are 0/2/4/6 and the pill
     belongs to meta tags only; a pill button is the SaaS default and it was
     quietly overriding the rule on every control. The aura's ::before inherits
     this, so the glow silhouette squares up with the button too. */
  border-radius: var(--radius-3);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: var(--fs-base);
  line-height: 1;
  text-decoration: none;
  cursor: pointer;
  transition:
    background var(--dur-base) var(--ease-ui),
    color var(--dur-base) var(--ease-ui),
    border-color var(--dur-base) var(--ease-ui),
    box-shadow var(--dur-base) var(--ease-ui);
}
.n-btn:focus-visible { outline: 2px solid var(--clay-soft); outline-offset: 3px; }
.n-btn[disabled], .n-btn--disabled { opacity: 0.4; pointer-events: none; }

.n-btn--sm { --btn-pad: 10px 20px; font-size: var(--fs-sm); }
.n-btn--lg { --btn-pad: 18px 40px; font-size: var(--fs-md); }
.n-btn--full { width: 100%; }

/* PRIMARY — THE SIGNATURE. A cream glass pane with the light UNDERNEATH it, not
   around it: a box-shadow only paints outside the silhouette, so glass over it
   has nothing to pick up. Two temperatures, warm low-left and cool high-right,
   in three offset pools of different size — an even ring reads as a rendered
   effect rather than as light. modes.css turns this solid indigo in daylight,
   because glass over cream goes pastel and nothing glows on cream. */
.n-btn--primary {
  position: relative;
  isolation: isolate;
  background: var(--fill-signature);
  -webkit-backdrop-filter: var(--pane-blur); backdrop-filter: var(--pane-blur);
  color: var(--ink);
  font-weight: 700;
  border: 1.5px solid #ffffff;
  box-shadow: var(--halo-signature), inset 0 0 0 0.5px rgba(255,255,255,0.9);
}
.n-btn--primary::before {
  content: ""; position: absolute; inset: -8px; z-index: -1;
  border-radius: inherit;
  background:
    /* WARM-LED. This was indigo at .78 against clay at .85, with magenta at .55
       underneath — three cool pools out of four, which is why the signature CTA
       read as a purple button rather than a cream one lit from below. Clay leads,
       rose answers, and indigo is now a cool edge on the high side instead of the
       loudest thing in the stack. */
    radial-gradient(66% 134% at 20% 96%, rgba(203,88,66,0.92) 0%, rgba(203,88,66,0) 68%),
    radial-gradient(52% 118% at 48% 6%,  rgba(184,70,90,0.58) 0%, rgba(184,70,90,0) 70%),
    radial-gradient(62% 130% at 90% 20%, rgba(79,63,214,0.30) 0%, rgba(79,63,214,0) 66%);
  filter: blur(9px) saturate(1.02);
  transition: filter var(--dur-base) var(--ease-ui), inset var(--dur-base) var(--ease-ui);
}
.n-btn--primary:hover { box-shadow: var(--halo-signature-hover); }
.n-btn--primary:hover::before { filter: blur(8px) saturate(1); inset: -8px; }
.n-btn--primary:active { filter: brightness(0.97); box-shadow: var(--halo-signature); }
/* Anchors styled as buttons must not inherit the global link-hover colour —
   that is what used to repaint the CTA label. */
a.n-btn--primary, a.n-btn--primary:hover { color: var(--ink); }

/* MAGENTA — the statement CTA, and the loudest fill in the set. SOLID in both
   modes: a translucent fill
   goes peach over cream, which is the pastel failure the glass buttons had.
   It fills with clay-DEEP, not clay. Cream type on --clay is only 3.57:1, which
   fails in BOTH modes — a button label is never large text. Deep measures ~5.4:1,
   so hover and active move by brightness rather than by stepping to a lighter
   fill that would drop back under the threshold. */
.n-btn--magenta {
  background: var(--magenta-deep); color: var(--moonlight); border-color: transparent;
}
.n-btn--magenta:hover { background: var(--magenta-deep); filter: brightness(1.16); }
.n-btn--magenta:active { background: var(--magenta-deep); filter: brightness(0.92); }
a.n-btn--magenta:hover { color: var(--moonlight); }


/* AURA — the glowing CTA. A solid pill in a role hue with its own light pooling
   out from behind it: a blurred radial in the same hue on ::before, plus a
   two-stop halo. The fill stays opaque (glass is for what floats, and a
   translucent pill cannot carry a label), so the glow lives ENTIRELY outside
   the silhouette. That is the difference between light and a sticker.

   ONE variant with a hue knob, not four variants — set --aura-hue/--aura-bloom/
   --aura-halo, or use the three shorthand modifiers below. Clay by default,
   because clay is the warm statement hue and the ground it glows against is cool.

   Hover pushes the pool wider and softer rather than brighter: light spreading
   reads as approach, light intensifying reads as a state change.
   NIGHT ONLY — modes.css swaps it for a warm-tinted drop shadow on cream,
   because nothing glows against daylight. */
.n-btn--aura {
  --aura-fill: var(--clay-deep);
  --aura-bloom: var(--bloom-clay);
  --aura-halo: 0 0 12px 1px rgba(203,88,66,0.58), 0 0 30px 6px rgba(203,88,66,0.26);
  --aura-halo-hover: 0 0 16px 2px rgba(203,88,66,0.70), 0 0 40px 10px rgba(203,88,66,0.32);
  position: relative;
  isolation: isolate;
  background: var(--aura-fill);
  color: var(--moonlight);
  border-color: transparent;
  box-shadow: var(--aura-halo);
}
.n-btn--aura::before {
  content: ""; position: absolute; inset: -9px; z-index: -1;
  border-radius: inherit;
  background: var(--aura-bloom);
  filter: blur(9px);
  transition: inset var(--dur-base) var(--ease-ui), filter var(--dur-base) var(--ease-ui);
}
.n-btn--aura:hover { box-shadow: var(--aura-halo-hover); }
.n-btn--aura:hover::before { inset: -14px; filter: blur(14px); }
.n-btn--aura:active { box-shadow: var(--aura-halo); filter: brightness(0.95); }
.n-btn--aura:active::before { inset: -6px; filter: blur(7px); }
a.n-btn--aura, a.n-btn--aura:hover { color: var(--moonlight); }

.n-btn--aura-rose {
  --aura-fill: var(--rose-deep);
  --aura-bloom: var(--bloom-rose);
  --aura-halo: 0 0 12px 1px rgba(184,70,90,0.58), 0 0 30px 6px rgba(184,70,90,0.26);
  --aura-halo-hover: 0 0 16px 2px rgba(184,70,90,0.70), 0 0 40px 10px rgba(184,70,90,0.32);
}
.n-btn--aura-magenta {
  --aura-fill: var(--magenta-deep);
  --aura-bloom: var(--bloom-magenta);
  --aura-halo: 0 0 12px 1px rgba(142,44,156,0.58), 0 0 30px 6px rgba(142,44,156,0.26);
  --aura-halo-hover: 0 0 16px 2px rgba(142,44,156,0.70), 0 0 40px 10px rgba(142,44,156,0.32);
}
.n-btn--aura-indigo {
  --aura-fill: var(--indigo-deep);
  --aura-bloom: var(--bloom-indigo);
  --aura-halo: 0 0 12px 1px rgba(79,63,214,0.58), 0 0 30px 6px rgba(79,63,214,0.26);
  --aura-halo-hover: 0 0 16px 2px rgba(79,63,214,0.70), 0 0 40px 10px rgba(79,63,214,0.32);
}
/* The one exception to single-hue: the iris aura steps clay -> rose -> magenta ->
   indigo behind an indigo pill, the same walk the progress arc makes. It is the
   loudest control in the system: ONE per screen, and only on the page's own
   signature action. */
.n-btn--aura-iris {
  --aura-fill: var(--indigo-deep);
  --aura-bloom: var(--bloom-iris);
  --aura-halo: var(--halo-signature);
  --aura-halo-hover: var(--halo-signature-hover);
}
.n-btn--aura-iris::before { inset: -11px; filter: blur(11px); }
.n-btn--aura-iris:hover::before { inset: -16px; filter: blur(16px); }

@media (prefers-reduced-motion: reduce) {
  .n-btn--aura::before { transition: none; }
}

.n-btn--ghost { background: transparent; color: var(--fg); border-color: var(--border); }
/* A step, not a hue: the hairline firms up and a faint wash appears. Recolouring
   the label on hover made ghost look like a different variant. */
.n-btn--ghost:hover { border-color: var(--border-strong); background: color-mix(in srgb, var(--fg) 7%, transparent); }
.n-btn--ghost:active { background: color-mix(in srgb, var(--fg) 12%, transparent); }
a.n-btn--ghost:hover { color: var(--fg); }

/* Editorial: mono uppercase, rule underneath, arrow character */
.n-btn--editorial {
  background: transparent;
  color: var(--fg);
  border: none;
  border-bottom: 1px solid var(--border);
  border-radius: var(--radius-0);
  padding: 0 0 5px;
  min-height: auto;
  font-family: var(--font-accent);
  font-weight: 400;
  font-size: var(--fs-sm);
  letter-spacing: var(--ls-mono);
  text-transform: uppercase;
}
.n-btn--editorial:hover { color: var(--clay-text); border-bottom-color: var(--clay-mark); }

.n-iconbtn {
  appearance: none;
  display: inline-grid;
  place-items: center;
  width: var(--hit-min);
  height: var(--hit-min);
  padding: 0;
  border: none;
  border-radius: 50%;
  background: transparent;
  color: var(--fg);
  cursor: pointer;
  transition: color var(--dur-base) var(--ease-ui), background var(--dur-base) var(--ease-ui);
}
.n-iconbtn:hover { color: var(--clay-text); background: rgba(244,236,222,0.06); }
.n-iconbtn--nebula { background: var(--nebula); border: 1px solid var(--border-soft); }
.n-iconbtn--moonlight { background: var(--moonlight); color: var(--night); box-shadow: var(--halo-moonlight); }
.n-iconbtn--sm { width: 36px; height: 36px; }

/* ---------------------------------------------------------
   BRAND MOTIFS
   moon · ray · sun · triangle-burst · zen. These are the project's ENTIRE
   decorative icon language — there is no icon font and no icon pack.

   Two ways to place one, and the choice is not cosmetic:

   .n-motif  — a CSS mask. DOES NOT WORK in this environment: an external SVG
               mask-image renders as a solid rectangle rather than the shape, even
               with width/height present. Kept only so old markup does not break.
               Use <brand-motif> instead.
   inline    — paste the <svg> into the markup; `.cls-1 { fill: currentColor }`
               then picks up the parent colour too. Use when the motif must
               scale with type or carry a title for accessibility.

   An <img> cannot be recoloured — the file's own currentColor resolves to black
   inside an image context — so <img> is only for a motif that is meant to be ink.

   USE <brand-motif name="zen"> (motif.js). It fetches each file once and inlines
   it, which is the only method here that both renders the shape AND takes a
   palette hue. Size with --size, colour with `color`.

   CONVENTIONS. Decorative: 5–20% opacity, 160–400px, behind or beside content,
   never centred behind a heading. Featured: 80–95%, 24–48px as an ornament.
   One motif per screen. They rotate 40–80s if they move at all, counter-rotating
   in pairs — never faster, or the page acquires a spinner. */
.n-motif {
  display: block; flex: 0 0 auto;
  width: var(--motif-size, 240px); height: var(--motif-size, 240px);
  background-color: currentColor;
  -webkit-mask-position: center; mask-position: center;
  -webkit-mask-repeat: no-repeat; mask-repeat: no-repeat;
  -webkit-mask-size: contain; mask-size: contain;
  pointer-events: none;
}
.n-motif--moon  { -webkit-mask-image: url("./assets/brand/moon.svg");           mask-image: url("./assets/brand/moon.svg"); }
.n-motif--ray   { -webkit-mask-image: url("./assets/brand/ray.svg");            mask-image: url("./assets/brand/ray.svg"); }
.n-motif--sun   { -webkit-mask-image: url("./assets/brand/sun.svg");            mask-image: url("./assets/brand/sun.svg"); }
.n-motif--burst { -webkit-mask-image: url("./assets/brand/triangle-burst.svg"); mask-image: url("./assets/brand/triangle-burst.svg"); }
.n-motif--zen   { -webkit-mask-image: url("./assets/brand/zen.svg");            mask-image: url("./assets/brand/zen.svg"); }
/* sun is wide, not square — let it keep its own ratio */
.n-motif--sun { height: calc(var(--motif-size, 240px) * 0.511); }
.n-motif--ornament { --motif-size: 34px; opacity: 0.9; }
.n-motif--quiet { opacity: 0.09; }

/* ---------------------------------------------------------
   LINKS
--------------------------------------------------------- */
.n-link { color: var(--fg); text-decoration: none; position: relative; }
.n-link::after {
  content: ""; position: absolute; left: 0; bottom: -2px;
  width: 0; height: 1px; background: currentColor;
  transition: width 320ms var(--ease-ui);
}
.n-link:hover { color: var(--terracotta-link); }
.n-link:hover::after { width: 100%; }
/* .n-link--accent — Kilimanjaro, not monospace. The old --mono selector is kept
   as an alias so existing markup resolves, exactly as the retired button
   variants are, but nothing new should author it. */
.n-link--accent, .n-link--mono {
  font-family: var(--font-accent); font-size: var(--fs-xs); font-weight: 400;
  letter-spacing: var(--ls-mono); text-transform: uppercase;
}

/* ---------------------------------------------------------
   CHIPS · BADGES · TAGS
--------------------------------------------------------- */
.n-chip {
  appearance: none; cursor: pointer; flex: 0 0 auto;
  min-height: var(--hit-min); padding: 11px 20px;
  border: 1px solid var(--border); border-radius: var(--radius-pill);
  /* The resting chip was SOLID MAGENTA, so every chip on screen looked selected —
     and :hover then LIGHTENED it, which inverted the two states. A chip at rest
     is a hairline and a label; hover firms the hairline; only ACTIVE is filled. */
  background: transparent; color: var(--fg);
  font-family: var(--font-accent); font-size: var(--fs-sm); font-weight: 400;
  letter-spacing: var(--ls-mono); text-transform: uppercase; white-space: nowrap;
  transition: background var(--dur-base) var(--ease-ui), color var(--dur-base) var(--ease-ui),
              border-color var(--dur-base) var(--ease-ui);
}
.n-chip:hover { background: color-mix(in srgb, var(--fg) 7%, transparent); border-color: var(--border-strong); }
.n-chip[aria-pressed="true"], .n-chip--active {
  background: var(--indigo-deep); color: var(--moonlight); border-color: transparent;
}
.n-chip--quiet { background: transparent; color: var(--fg-mute); border-color: transparent; }
.n-chip--quiet:hover { background: color-mix(in srgb, var(--fg) 6%, transparent); color: var(--fg); }

.n-badge {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 12px; border-radius: var(--radius-pill);
  background: rgba(244,236,222,0.08); border: 1px solid var(--border-soft);
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-dim);
}
.n-badge--hot { background: rgba(245,26,23,0.14); border-color: rgba(245,26,23,0.4); color: var(--signal-red); }
.n-badge--good { background: rgba(50,166,82,0.14); border-color: rgba(50,166,82,0.4); color: var(--signal-green); }
.n-badge--warn { background: rgba(247,169,59,0.14); border-color: rgba(247,169,59,0.4); color: var(--signal-amber); }
.n-badge__dot { width: 7px; height: 7px; border-radius: 50%; background: currentColor; }

/* ---------------------------------------------------------
   DIVIDERS
--------------------------------------------------------- */
.n-rule { height: 1px; border: 0; background: var(--border-soft); margin: 0; }
.n-rule--strong { background: var(--border); }
/* Fading rule — reads as light rather than as a line */
.n-rule--fade {
  height: 1px; border: 0;
  background: linear-gradient(90deg, transparent, var(--border), transparent);
}
/* Marked rule: a hairline broken by a centred ornament */
.n-rule-mark { display: grid; grid-template-columns: 1fr auto 1fr; align-items: center; gap: var(--space-4); }
.n-rule-mark::before, .n-rule-mark::after { content: ""; height: 1px; background: var(--border-soft); }
.n-rule-mark__glyph { color: var(--fg-low); display: grid; place-items: center; }
/* Vertical channel with sideways mono text — the Cosmic Desert signature */
.n-channel {
  display: grid; grid-template-columns: 1px 1fr; gap: var(--space-5);
  background:
    linear-gradient(var(--border-soft), var(--border-soft)) left / 1px 100% no-repeat;
}
.n-channel__label {
  writing-mode: vertical-rl; text-orientation: mixed;
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 500;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute);
}

/* ---------------------------------------------------------
   FORMS
--------------------------------------------------------- */
.n-field { display: grid; gap: 9px; }
.n-label {
  font-family: var(--font-accent); font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-dim);
}
.n-hint { font-family: var(--font-body); font-size: var(--fs-sm); font-weight: 400; color: var(--fg-mute); }
.n-error { font-family: var(--font-body); font-size: var(--fs-sm); font-weight: 400; color: var(--signal-red); }

.n-input, .n-textarea, .n-select {
  width: 100%;
  min-height: var(--hit-min);
  padding: 14px 16px;
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--border);
  border-radius: var(--radius-4);
  color: var(--fg);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: var(--fs-base);
  line-height: 1.45;
  transition: border-color var(--dur-base) var(--ease-ui), background var(--dur-base) var(--ease-ui), box-shadow var(--dur-base) var(--ease-ui);
}
.n-input::placeholder, .n-textarea::placeholder { color: var(--fg-mute); }
.n-input:hover, .n-textarea:hover, .n-select:hover { border-color: var(--border-strong); }
.n-input:focus, .n-textarea:focus, .n-select:focus {
  outline: none; border-color: var(--terracotta-link); box-shadow: 0 0 0 3px rgba(194,85,56,0.20);
}
.n-textarea { min-height: 132px; resize: vertical; }
.n-input--invalid, .n-textarea--invalid { border-color: var(--signal-red); }
.n-input--invalid:focus { box-shadow: 0 0 0 3px rgba(245,26,23,0.18); }
.n-input[disabled], .n-textarea[disabled], .n-select[disabled] { opacity: 0.45; cursor: not-allowed; }

/* Underline variant — editorial forms (newsletter, single-field) */
.n-input--line {
  background: transparent; border: 0; border-bottom: 1px solid var(--border);
  border-radius: 0; padding: 12px 2px;
}
.n-input--line:focus { box-shadow: none; border-bottom-color: var(--terracotta-link); }

/* Native select: our own caret, no OS arrow */
.n-select {
  appearance: none;
  padding-right: 44px;
  background-image:
    linear-gradient(45deg, transparent 50%, currentColor 50%),
    linear-gradient(135deg, currentColor 50%, transparent 50%);
  background-position: calc(100% - 22px) calc(50% + 2px), calc(100% - 16px) calc(50% + 2px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}

/* Checkbox / radio */
.n-check { display: flex; align-items: flex-start; gap: 12px; cursor: pointer; }
.n-check__box, .n-check__dot {
  appearance: none; flex: 0 0 auto;
  width: 22px; height: 22px; margin: 1px 0 0;
  background: var(--bg-raised); border: 1px solid var(--border);
  cursor: pointer;
  transition: background var(--dur-base) var(--ease-ui), border-color var(--dur-base) var(--ease-ui);
}
.n-check__box { border-radius: var(--radius-1); }
.n-check__dot { border-radius: 50%; }
.n-check:hover .n-check__box, .n-check:hover .n-check__dot { border-color: var(--border-strong); }
.n-check__box:checked { background: var(--clay-text); border-color: var(--terracotta-link); }
.n-check__box:checked::after {
  content: ""; display: block; width: 11px; height: 6px; margin: 4px auto 0;
  border-left: 2px solid var(--night); border-bottom: 2px solid var(--night);
  transform: rotate(-45deg);
}
.n-check__dot:checked { border-color: var(--terracotta); background: radial-gradient(circle, var(--terracotta) 0 42%, transparent 46%); }
.n-check__box:focus-visible, .n-check__dot:focus-visible { outline: 2px solid var(--terracotta-soft); outline-offset: 2px; }
.n-check__text { font-family: var(--font-body); font-size: var(--fs-base); color: var(--fg); line-height: 1.45; }

/* Switch */
.n-switch { appearance: none; position: relative; width: 52px; height: 30px; flex: 0 0 auto;
  background: var(--nebula); border: 1px solid var(--border); border-radius: var(--radius-pill);
  cursor: pointer; transition: background var(--dur-base) var(--ease-ui); }
.n-switch::after {
  content: ""; position: absolute; top: 3px; left: 3px; width: 22px; height: 22px;
  border-radius: 50%; background: var(--fg-mute);
  transition: transform var(--dur-base) var(--ease-ui), background var(--dur-base) var(--ease-ui);
}
.n-switch:checked { background: var(--violet); border-color: transparent; }
.n-switch:checked::after { transform: translateX(22px); background: var(--moonlight); }
.n-switch:focus-visible { outline: 2px solid var(--terracotta-soft); outline-offset: 2px; }

/* Segmented control */
.n-seg {
  display: inline-flex; padding: 4px; gap: 0;
  background: var(--dusk-violet); border: 1px solid var(--border-soft);
  /* 6px track, 4px options — nested radii, and no pill: these options are
     buttons, and the pill belongs to meta tags only. */
  border-radius: var(--radius-3);
}
.n-seg__opt {
  appearance: none; border: none; cursor: pointer;
  min-height: 40px; padding: 10px 22px; border-radius: var(--radius-2);
  background: transparent; color: var(--moonlight);
  font-family: var(--font-accent); font-size: var(--fs-sm); font-weight: 600;
  letter-spacing: var(--ls-mono-x); text-transform: uppercase;
  transition: background var(--dur-base) var(--ease-ui), color var(--dur-base) var(--ease-ui);
}
.n-seg__opt:hover { color: var(--moonlight); background: rgba(244,236,222,0.08); }
.n-seg__opt[aria-selected="true"] { background: var(--moonlight); color: var(--night); }

/* Field row helpers */
.n-form { display: grid; gap: var(--space-5); }
.n-form-row { display: grid; gap: var(--space-4); grid-template-columns: 1fr 1fr; }
@media (max-width: 640px) { .n-form-row { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------
   DROPDOWN / MENU
--------------------------------------------------------- */
.n-menu {
  min-width: 220px; padding: 8px;
  background: var(--glass-fill-deep);
  -webkit-backdrop-filter: var(--glass-blur-heavy); backdrop-filter: var(--glass-blur-heavy);
  border: 1px solid var(--border); border-radius: var(--radius-4);
  box-shadow: var(--shadow-3), var(--glass-catch);
}
.n-menu__item {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 12px 14px; border: none; border-radius: var(--radius-2);
  background: transparent; color: var(--fg); cursor: pointer; text-align: left;
  font-family: var(--font-body); font-size: var(--fs-base);
  transition: background var(--dur-base) var(--ease-ui), color var(--dur-base) var(--ease-ui);
}
.n-menu__item:hover { background: rgba(244,236,222,0.07); color: var(--terracotta-link); }
.n-menu__item--current { color: var(--terracotta-link); }
.n-menu__sep { height: 1px; background: var(--border-soft); margin: 8px 4px; }
.n-menu__label {
  padding: 10px 14px 6px;
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute);
}

/* ---------------------------------------------------------
   ACCORDION
--------------------------------------------------------- */
.n-acc { border-top: 1px solid var(--border-soft); }
.n-acc__item { border-bottom: 1px solid var(--border-soft); }
.n-acc__head {
  display: grid; grid-template-columns: 1fr auto; align-items: center; gap: var(--space-4);
  width: 100%; padding: 24px 0; border: none; background: transparent; cursor: pointer;
  text-align: left; color: var(--fg);
  font-family: var(--font-display); font-variation-settings: var(--fv-title);
  font-size: var(--fs-lg); font-weight: 400; line-height: var(--lh-snug);
  transition: color var(--dur-base) var(--ease-ui);
}
.n-acc__head:hover { color: var(--terracotta-link); }
.n-acc__sign { position: relative; width: 18px; height: 18px; flex: 0 0 auto; color: var(--fg-mute); }
.n-acc__sign::before, .n-acc__sign::after {
  content: ""; position: absolute; inset: 0; margin: auto;
  background: currentColor; transition: transform var(--dur-base) var(--ease-ui), opacity var(--dur-base) var(--ease-ui);
}
.n-acc__sign::before { width: 100%; height: 1px; }
.n-acc__sign::after { width: 1px; height: 100%; }
.n-acc__item[open] .n-acc__sign::after,
.n-acc__item--open .n-acc__sign::after { opacity: 0; transform: rotate(90deg); }
.n-acc__body { padding: 0 0 26px; max-width: var(--measure); }
.n-acc__body p { color: var(--fg-dim); }
/* <details>/<summary> version */
details.n-acc__item > summary { list-style: none; }
details.n-acc__item > summary::-webkit-details-marker { display: none; }

/* ---------------------------------------------------------
   TABS
--------------------------------------------------------- */
.n-tabs { display: flex; gap: var(--space-6); border-bottom: 1px solid var(--border-soft); }
.n-tab {
  appearance: none; background: transparent; border: none; cursor: pointer;
  padding: 14px 0; margin-bottom: -1px; border-bottom: 1px solid transparent;
  color: var(--fg-mute);
  font-family: var(--font-accent); font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase;
  transition: color var(--dur-base) var(--ease-ui), border-color var(--dur-base) var(--ease-ui);
}
.n-tab:hover { color: var(--fg); }
.n-tab[aria-selected="true"] { color: var(--fg); border-bottom-color: var(--terracotta-link); }

/* ---------------------------------------------------------
   CARDS
--------------------------------------------------------- */
/* Glass. .n-glass is the surface; --glass-* carries every value so one edit
   restyles every floating surface in the system. */
.n-glass, .n-glass--raised, .n-glass--deep {
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-edge), var(--glass-shadow);
}
.n-glass--raised { background: var(--glass-fill-raised); border-color: var(--glass-border-lit); }
.n-glass--deep {
  background: var(--glass-fill-deep);
  -webkit-backdrop-filter: var(--glass-blur-heavy); backdrop-filter: var(--glass-blur-heavy);
}
/* No backdrop-filter (older Firefox): fall back to an opaque fill rather than
   a transparent panel with unreadable type over it. */
@supports not (backdrop-filter: blur(1px)) {
  .n-glass, .n-glass--raised, .n-glass--deep { background: var(--night-raised); }
}

.n-card {
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur); backdrop-filter: var(--glass-blur);
  border: 1px solid var(--glass-border);
  box-shadow: var(--glass-edge), var(--glass-shadow);
  border-radius: var(--radius-5); padding: var(--space-5);
  transition: border-color var(--dur-base) var(--ease-ui), transform var(--dur-base) var(--ease-ui);
}
.n-card--flat { background: transparent; }
.n-card--editorial { border-radius: var(--radius-2); }
a.n-card:hover, .n-card--interactive:hover { border-color: var(--border-strong); transform: translateY(-2px); }

/* Numbered hub card — the Cosmic Desert editorial card, unchanged */
.n-hub { display: grid; gap: var(--space-4); }
.n-hub__media { position: relative; aspect-ratio: 4 / 3; border-radius: var(--radius-2); overflow: hidden; }

.n-hub__num {
  font-family: var(--font-display); font-style: italic; font-weight: 350;
  font-variation-settings: var(--fv-heading);
  font-size: var(--fs-2xl); color: var(--clay-text); line-height: 1;
}
.n-hub__head { display: grid; grid-template-columns: 1fr auto; align-items: start; gap: var(--space-4); }

/* ---------------------------------------------------------
   MEDIA — image + video styling
--------------------------------------------------------- */
.n-media { position: relative; overflow: hidden; border-radius: var(--radius-4); background: var(--bg-raised); }
.n-media--square { aspect-ratio: 1; }
.n-media--portrait { aspect-ratio: 3 / 4; }
.n-media--landscape { aspect-ratio: 3 / 2; }
.n-media--wide { aspect-ratio: 16 / 9; }
.n-media--editorial { border-radius: var(--radius-2); }
.n-media--arch { border-radius: 50% 50% var(--radius-4) var(--radius-4) / 32% 32% var(--radius-4) var(--radius-4); }
.n-media--circle { border-radius: 50%; aspect-ratio: 1; }
.n-media--bleed { border-radius: 0; }
.n-media > img, .n-media > video, .n-media > image-slot { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Duotone treatment for supporting imagery: warm dusk, never cool */
.n-media--duotone > img { filter: saturate(0.7) contrast(1.05); }
.n-media--duotone::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(190deg, rgba(199,138,62,0.22), rgba(36,47,84,0.42));
  mix-blend-mode: soft-light;
}
/* Protection gradient so type can sit on an image */
.n-media__scrim {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg, transparent 34%, var(--scrim-media) 100%);
}
.n-media__caption {
  position: absolute; left: 0; right: 0; bottom: 0; padding: var(--space-5);
  display: grid; gap: 8px;
}
.n-caption { font-family: var(--font-body); font-size: var(--fs-sm); font-weight: 400; color: var(--fg-mute); }
/* Seals sit ON the media, so they must beat the fill rule above. */
.n-media > .n-media__seal,
.n-hub__media > .n-hub__seal {
  position: absolute; left: 16px; bottom: 16px;
  width: 30px; height: auto; object-fit: contain;
  color: var(--moonlight); opacity: 0.85;
}
.n-media > .n-media__seal { z-index: 2; }

.n-video { position: relative; }
.n-video__play {
  position: absolute; inset: 0; margin: auto; width: 82px; height: 82px;
  display: grid; place-items: center; border: none; cursor: pointer;
  border-radius: 50%; background: var(--moonlight); color: var(--night);
  box-shadow: var(--halo-moonlight);
  transition: box-shadow var(--dur-base) var(--ease-ui), transform var(--dur-base) var(--ease-ui);
}
.n-video__play:hover { box-shadow: 0 0 34px 8px rgba(244,236,222,0.42); }
.n-video__bar {
  position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: rgba(244,236,222,0.18);
}
.n-video__bar > span { display: block; height: 100%; background: var(--moonlight); }
.n-video__time {
  position: absolute; right: 14px; bottom: 14px;
  font-family: var(--font-accent); font-size: var(--fs-2xs); letter-spacing: var(--ls-mono);
  color: var(--moonlight); background: var(--scrim-chip); padding: 4px 8px; border-radius: var(--radius-1);
}

.n-avatar { border-radius: 50%; overflow: hidden; background: var(--bg-raised-2); flex: 0 0 auto; }
.n-avatar > img, .n-avatar > image-slot { width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---------------------------------------------------------
   TESTIMONIALS
--------------------------------------------------------- */
/* Terracotta is AA-large only on the navy ground (3.03:1), so anything that
   uses it as text is size-locked at 24px and above. */
.n-quote {
  min-height: 0; font-size: var(--fs-xl);
  font-family: var(--font-display); font-style: italic; font-weight: 350;
  font-variation-settings: var(--fv-title);
  font-size: var(--fs-xl); line-height: var(--lh-snug); color: var(--terracotta);
  max-width: var(--measure-sm); margin: 0; text-wrap: balance;
}
.n-quote--ochre { color: var(--terracotta-link); }
.n-testi { display: grid; gap: var(--space-5); }
.n-testi__attrib { display: flex; align-items: center; gap: 14px; }
.n-testi__name { font-family: var(--font-body); font-weight: 600; font-size: var(--fs-base); color: var(--fg); }
.n-testi__role {
  font-family: var(--font-accent); font-size: var(--fs-2xs); letter-spacing: var(--ls-mono);
  text-transform: uppercase; color: var(--fg-mute);
}
/* Card variant */
.n-testi--card {
  padding: var(--space-6); background: var(--bg-raised);
  border: 1px solid var(--border-soft); border-radius: var(--radius-5);
}
/* Portrait-left variant */
.n-testi--portrait { grid-template-columns: 200px 1fr; gap: var(--space-6); align-items: center; }
@media (max-width: 640px) { .n-testi--portrait { grid-template-columns: 1fr; } }

/* ---------------------------------------------------------
   NAV / PAGE HEADER
--------------------------------------------------------- */
.n-nav {
  position: sticky; top: 0; z-index: 40;
  display: grid; grid-template-columns: auto 1fr auto; align-items: center; gap: var(--space-6);
  padding: 18px var(--gutter);
  background: transparent;
  transition: background var(--dur-mid) var(--ease-ui), border-color var(--dur-mid) var(--ease-ui);
  border-bottom: 1px solid transparent;
}
.n-nav--scrolled {
  background: var(--glass-fill);
  -webkit-backdrop-filter: var(--glass-blur-heavy);
  backdrop-filter: var(--blur-chrome);
  border-bottom-color: var(--border-soft);
}
.n-nav__brand { display: flex; align-items: center; gap: 12px; color: var(--fg); }
.n-nav__brand img { height: 22px; width: auto; filter: brightness(0) invert(1); }
[data-mode="warm"] .n-nav__brand img { filter: brightness(0); }
.n-footer__col img { filter: brightness(0) invert(1); }
[data-mode="warm"] .n-footer__col img { filter: brightness(0); }
.n-nav__links { display: flex; justify-content: center; gap: var(--space-6); }
.n-nav__link {
  font-family: var(--font-accent); font-size: var(--fs-xs); font-weight: 500;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-dim);
  text-decoration: none; position: relative; padding: 6px 0;
  transition: color var(--dur-base) var(--ease-ui);
}
.n-nav__link::after {
  content: ""; position: absolute; left: 0; bottom: 0; width: 0; height: 1px;
  background: var(--clay-text); transition: width 320ms var(--ease-ui);
}
.n-nav__link:hover, .n-nav__link[aria-current="page"] { color: var(--fg); }
.n-nav__link:hover::after, .n-nav__link[aria-current="page"]::after { width: 100%; }
.n-nav__burger { display: none; }
@media (max-width: 900px) {
  .n-nav { grid-template-columns: auto 1fr; }
  .n-nav__links { display: none; }
  .n-nav__burger { display: inline-grid; justify-self: end; }
}

/* Page header block (title area of an inner page) */
.n-pagehead { display: grid; gap: var(--space-4); padding-block: clamp(3rem, 8vh, 6rem) clamp(2rem, 4vh, 3rem); }
.n-pagehead--center { justify-items: center; text-align: center; }
.n-eyebrow {
  font-family: var(--font-accent); font-size: var(--fs-xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-dim);
}
.n-eyebrow--moonlight { color: var(--fg); }
.n-eyebrow--gold { color: var(--terracotta-link); }   /* warm/desert editorial only */
.n-eyebrow--terracotta { color: var(--terracotta-link); }
.n-eyebrow--mute { color: var(--fg-mute); }
.n-crumbs { display: flex; gap: 10px; align-items: center; }
.n-crumbs a, .n-crumbs span {
  font-family: var(--font-accent); font-size: var(--fs-2xs); letter-spacing: var(--ls-mono);
  text-transform: uppercase; color: var(--fg-mute); text-decoration: none;
}
.n-crumbs a:hover { color: var(--terracotta-link); }

/* ---------------------------------------------------------
   FOOTER
--------------------------------------------------------- */
.n-footer { border-top: 1px solid var(--border-soft); padding-block: var(--space-8) var(--space-6); }
.n-footer__grid { display: grid; gap: var(--space-7); grid-template-columns: 2fr 1fr 1fr 1fr; }
@media (max-width: 900px) { .n-footer__grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 560px) { .n-footer__grid { grid-template-columns: 1fr; } }
.n-footer__col { display: grid; gap: 14px; align-content: start; }
.n-footer__head {
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute);
}
.n-footer__link { font-family: var(--font-body); font-size: var(--fs-sm); color: var(--fg-dim); text-decoration: none; }
.n-footer__link:hover { color: var(--terracotta-link); }
.n-footer__base {
  display: flex; justify-content: space-between; gap: var(--space-4); flex-wrap: wrap;
  margin-top: var(--space-7); padding-top: var(--space-5); border-top: 1px solid var(--border-soft);
}
.n-footer__fine { font-family: var(--font-accent); font-size: var(--fs-2xs); letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute); }

/* ---------------------------------------------------------
   NEWSLETTER
--------------------------------------------------------- */
.n-news { display: grid; gap: var(--space-5); max-width: 640px; }
.n-news--center { justify-items: center; text-align: center; margin-inline: auto; }
.n-news__form { display: flex; gap: var(--space-3); width: 100%; }
.n-news__form .n-input { flex: 1; }
@media (max-width: 560px) { .n-news__form { flex-direction: column; } }
.n-news__fine { font-family: var(--font-accent); font-size: var(--fs-2xs); letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute); }

/* ---------------------------------------------------------
   BLOG / LONG-FORM
--------------------------------------------------------- */
.n-post { max-width: 680px; margin-inline: auto; }
.n-post__meta { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.n-prose { display: grid; gap: var(--space-5); }
.n-prose > p { font-size: var(--fs-md); line-height: var(--lh-loose); color: var(--fg-dim); max-width: none; }
.n-prose > h2 { margin-top: var(--space-5); }
.n-prose > h3 { margin-top: var(--space-4); }
.n-prose > ul, .n-prose > ol { margin: 0; padding-left: 1.35em; display: grid; gap: 10px; }
.n-prose li { font-family: var(--font-body); font-size: var(--fs-md); line-height: var(--lh-loose); color: var(--fg-dim); }
.n-prose > ul { list-style: none; padding-left: 0; }
.n-prose > ul > li { position: relative; padding-left: 1.5em; }
.n-prose > ul > li::before {
  content: ""; position: absolute; left: 0; top: 0.72em;
  width: 6px; height: 6px; border-radius: 50%; background: var(--terracotta-soft);
}
.n-prose blockquote {
  margin: 0; padding-left: var(--space-5); border-left: 1px solid var(--clay-text);
  font-family: var(--font-body); font-weight: 400; font-size: var(--fs-md);
  color: var(--fg); line-height: var(--lh-loose);
}
.n-prose figure { margin: 0; display: grid; gap: 12px; }
.n-prose a { color: var(--clay-text); text-decoration: underline; text-underline-offset: 3px; }
/* Hover moves to INDIGO, which owns links, rather than to a lighter clay.
   --ochre-soft resolved to --clay-soft: 2.76:1 on cream, so the hover state was
   less legible than the resting state in daylight. Both --clay-text and
   --indigo-text are mode-aware, so the pair stays legal on either ground. */
.n-prose a:hover { color: var(--indigo-text); }
.n-postcard { display: grid; gap: var(--space-4); text-decoration: none; }
.n-postcard__title {
  font-family: var(--font-display); font-variation-settings: var(--fv-title);
  font-size: var(--fs-lg); color: var(--fg); line-height: var(--lh-snug);
  transition: color var(--dur-base) var(--ease-ui);
}
.n-postcard:hover .n-postcard__title { color: var(--terracotta-link); }

/* ---------------------------------------------------------
   TABLE
--------------------------------------------------------- */
.n-table { width: 100%; border-collapse: collapse; }
.n-table th {
  text-align: left; padding: 12px 14px; border-bottom: 1px solid var(--border);
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute);
}
.n-table td {
  padding: 16px 14px; border-bottom: 1px solid var(--border-soft);
  font-family: var(--font-body); font-size: var(--fs-base); color: var(--fg-dim);
}
.n-table tr:hover td { color: var(--fg); }

/* ---------------------------------------------------------
   MISC UI
--------------------------------------------------------- */
.n-tooltip {
  padding: 8px 12px; border-radius: var(--radius-2);
  background: var(--bg-raised-2); border: 1px solid var(--border);
  box-shadow: var(--shadow-2);
  font-family: var(--font-body); font-size: var(--fs-sm); color: var(--fg);
}
.n-progress { height: 3px; background: rgba(244,236,222,0.14); border-radius: var(--radius-pill); overflow: hidden; }
.n-progress > span { display: block; height: 100%; background: var(--terracotta-soft); }
.n-steps { display: flex; align-items: center; gap: 12px; }
.n-step {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute);
}
.n-step__num {
  width: 26px; height: 26px; border-radius: 50%; display: grid; place-items: center;
  border: 1px solid var(--border); color: var(--fg-mute);
}
.n-step--done .n-step__num { background: var(--terracotta); border-color: var(--terracotta); color: var(--night); }
.n-step--current { color: var(--fg); }
.n-step--current .n-step__num { border-color: var(--moonlight); color: var(--fg); }
.n-step__bar { width: 34px; height: 1px; background: var(--border); }

.n-empty {
  display: grid; gap: var(--space-4); justify-items: center; text-align: center;
  padding: var(--space-8) var(--space-5);
  border: 1px dashed var(--border); border-radius: var(--radius-5);
}
.n-skeleton {
  background: linear-gradient(90deg, rgba(244,236,222,0.05), rgba(244,236,222,0.12), rgba(244,236,222,0.05));
  background-size: 200% 100%;
  border-radius: var(--radius-2);
  animation: n-shimmer 1.6s var(--ease-ui) infinite;
}
@keyframes n-shimmer { to { background-position: -200% 0; } }

/* ---------------------------------------------------------
   BLOOM / GROUND helpers for web pages
--------------------------------------------------------- */
/* The ground carries a CONTAINED nebula. Glass panels laid on it — cards,
   chrome bars, sheets — need colour behind them to refract; over a flat dark
   fill a translucent panel is just a lighter flat panel. Contained rather
   than fixed, so it works inside a phone frame on a board as well as on a
   full page. */
.n-ground { position: relative; background: var(--grad-night); isolation: isolate; }
.n-ground::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(76% 52% at 14% 6%,  rgba(79,63,214,0.40) 0%, transparent 64%),
    radial-gradient(64% 48% at 90% 26%, rgba(142,44,156,0.32) 0%, transparent 66%),
    radial-gradient(70% 52% at 78% 86%, rgba(203,88,66,0.26) 0%, transparent 68%),
    radial-gradient(58% 44% at 16% 94%, rgba(184,70,90,0.22) 0%, transparent 66%);
}
.n-ground > * { position: relative; z-index: 1; }
[data-mode="warm"] .n-ground::before { opacity: 0.30; }
.n-ground--flat { background: var(--bg); }
.n-ground__stars {
  position: absolute; inset: 0; pointer-events: none; z-index: 1;
  background-image: var(--starfield); background-size: var(--starfield-size); opacity: 0.9;
}
[data-mode="warm"] .n-ground { background: var(--bg); }
[data-mode="warm"] .n-ground__stars { display: none; }
.n-bloom { position: relative; }
.n-bloom::before {
  content: ""; position: absolute; left: 50%; top: 50%; z-index: -1;
  width: var(--bloom-size, 200%); aspect-ratio: 1; transform: translate(-50%, -50%);
  background-image: var(--bloom, var(--bloom-violet)); pointer-events: none;
}
[data-mode="warm"] .n-bloom::before { opacity: 0.4; }

/* ---------------------------------------------------------
   DESERT IRIS helpers
--------------------------------------------------------- */
.n-iris-text {
  background: var(--grad-iris);
  -webkit-background-clip: text; background-clip: text;
  color: transparent;
}
/* Hairline rule that carries the spectrum instead of a flat colour */
.n-rule--iris { height: 1px; border: 0; background: var(--grad-iris); opacity: 0.7; }
/* Ring: a spectrum arc around a focal object */
.n-iris-ring {
  position: relative; border-radius: 50%;
  background: var(--grad-iris-ring);
  padding: var(--iris-ring, 2px);
}
.n-iris-ring > * { border-radius: 50%; background: var(--bg); display: block; }


/* ---------------------------------------------------------
   GLASS FALLBACK
   Where backdrop-filter is unsupported the tints are far too
   transparent to carry a label, so the controls go opaque.
--------------------------------------------------------- */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .n-menu, .n-input, .n-textarea, .n-select, .n-nav--scrolled { background: var(--bg-raised-2); }
  .n-chip[aria-pressed="true"], .n-chip--active { background: #f4eddf; }
  .n-btn--primary { background: #2f2585; }
  .n-btn--primary::before { display: none; }
  .n-btn--magenta    { background: #6e1f7a; }
}


/* ---------------------------------------------------------
   AMBIENT GROUND
   The iridescent CTA is calibrated for a LIT ground, not the
   flat void. On #0A0E16 any bloom reads as neon, because there
   is nothing between the glow and black for it to fall off
   into. This is the mid-tone the CTA expects: soft pools of
   warm low-left and cool high-right over the night base.
   Use it behind any hero or section that carries the CTA.
--------------------------------------------------------- */
.n-ambient {
  position: relative; isolation: isolate;
  background:
    radial-gradient(120% 90% at 18% 82%, rgba(203,88,66,0.20) 0%, transparent 58%),
    radial-gradient(110% 85% at 82% 12%, rgba(79,63,214,0.26) 0%, transparent 60%),
    radial-gradient(90% 70% at 50% 50%, rgba(142,44,156,0.16) 0%, transparent 70%),
    var(--night);
}
.n-ambient--deep {
  position: relative; isolation: isolate;
  background:
    radial-gradient(120% 90% at 18% 82%, rgba(203,88,66,0.30) 0%, transparent 58%),
    radial-gradient(110% 85% at 82% 12%, rgba(79,63,214,0.38) 0%, transparent 60%),
    radial-gradient(90% 70% at 50% 50%, rgba(142,44,156,0.24) 0%, transparent 70%),
    var(--night);
}


/* ==== tokens/systems.css =================================================== */
/* =========================================================
   NOCTURNE — SYSTEMS CSS
   Tarot furniture and chart chrome. Imported by styles.css.
   ========================================================= */

/* ---------- Tarot ---------- */
.n-tarot {
  margin: 0; display: grid; gap: 0;
  border-radius: var(--radius-4);
  overflow: hidden;
  background: var(--night-raised);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-2);
}
.n-tarot__art { position: relative; background: var(--night-lift); }
.n-tarot__art > image-slot, .n-tarot__art > img { width: 100%; height: 100%; object-fit: cover; display: block; }
.n-tarot__await {
  position: absolute; inset: 0; display: grid; place-items: center; text-align: center;
  padding: 14px;
  font-family: var(--font-accent); font-size: var(--fs-2xs); letter-spacing: var(--ls-mono);
  text-transform: uppercase; color: var(--fg-low);
  background: repeating-linear-gradient(135deg, rgba(244,236,222,0.03) 0 8px, transparent 8px 16px);
}
.n-tarot__cap { display: grid; gap: 5px; padding: 14px 16px 16px; justify-items: center; text-align: center; }
.n-tarot__num {
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 700;
  letter-spacing: var(--ls-mono); color: var(--clay-text);
}
.n-tarot__name {
  font-family: var(--font-display); font-variation-settings: var(--fv-title);
  font-size: var(--fs-lg); color: var(--fg); line-height: 1.15;
}
.n-tarot__meta {
  font-family: var(--font-accent); font-size: var(--fs-2xs); letter-spacing: var(--ls-mono);
  text-transform: uppercase; color: var(--fg-mute);
}
/* Card back — the one place a saturated gradient covers a whole object */
.n-tarot--back {
  border-radius: var(--radius-4);
  border: 1px solid var(--border-strong);
  background:
    radial-gradient(circle at 50% 34%, rgba(244,236,222,0.5) 0 3px, transparent 4px),
    var(--grad-aurora);
  position: relative; overflow: hidden;
}
.n-tarot--back::after {
  content: ""; position: absolute; inset: 8px;
  border: 1px solid rgba(244,236,222,0.28); border-radius: var(--radius-2);
}
.n-tarot--reversed .n-tarot__art { transform: rotate(180deg); }
.n-tarot--reversed .n-tarot__num::after { content: " · reversed"; }

/* Fanned deck */
.n-fan { position: relative; height: 300px; }
.n-fan > * {
  position: absolute; left: 50%; top: 0; margin-left: -64px;
  transform-origin: 50% 132%;
  transition: transform var(--dur-reveal) var(--ease-reveal);
}
.n-fan > *:hover { transform: translateY(-14px) rotate(var(--fan-deg, 0deg)); }

/* Spread layouts */
.n-spread { display: grid; gap: var(--space-4); justify-items: center; }
.n-spread--one { grid-template-columns: 1fr; }
.n-spread--three { grid-template-columns: repeat(3, 1fr); }
.n-spread--five {
  grid-template-columns: repeat(3, 1fr);
  grid-template-areas: ". past ." "left centre right" ". future .";
}
.n-spread--five > *:nth-child(1) { grid-area: centre; }
.n-spread--five > *:nth-child(2) { grid-area: past; }
.n-spread--five > *:nth-child(3) { grid-area: left; }
.n-spread--five > *:nth-child(4) { grid-area: right; }
.n-spread--five > *:nth-child(5) { grid-area: future; }
.n-spread__pos {
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute);
  text-align: center; margin-bottom: 10px;
}
@media (max-width: 700px) {
  .n-spread--three { grid-template-columns: 1fr; }
  .n-spread--five { grid-template-columns: 1fr; grid-template-areas: "centre" "past" "left" "right" "future"; }
}

/* ---------- Chart chrome ---------- */
.n-chart { position: relative; }
.n-chart__key { display: flex; flex-wrap: wrap; gap: 10px 22px; }
.n-chart__keyitem {
  display: flex; align-items: center; gap: 9px;
  font-family: var(--font-accent); font-size: var(--fs-2xs); letter-spacing: var(--ls-mono);
  text-transform: uppercase; color: var(--fg-mute);
}
.n-chart__swatch { width: 20px; height: 2px; border-radius: 2px; background: currentColor; }
.n-chart__stat { display: grid; gap: 5px; }
.n-chart__stat dt {
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 600;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute);
}
.n-chart__stat dd {
  margin: 0;
  font-family: var(--font-display); font-variation-settings: var(--fv-title);
  font-size: var(--fs-xl); color: var(--fg);
}
.n-centres { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.n-centre {
  padding: 14px 10px; border-radius: var(--radius-4);
  border: 1px solid var(--border-soft); display: grid; gap: 8px; justify-items: center;
}
.n-centre--on { border-color: var(--border-strong); background: var(--night-lift); }
.n-centre__mark { width: 12px; height: 12px; border-radius: 3px; border: 1px solid var(--border); }
.n-centre--on .n-centre__mark { background: var(--clay-text); border-color: var(--clay-text); }
.n-centre__label {
  font-family: var(--font-accent); font-size: var(--fs-2xs); font-weight: 500;
  letter-spacing: var(--ls-mono); text-transform: uppercase; color: var(--fg-mute); text-align: center;
}
.n-centre--on .n-centre__label { color: var(--fg); }


/* ==== tokens/modes.css ===================================================== */
/* =========================================================
   MODES — one dark, one light, nothing in between.
   ---------------------------------------------------------
   This file is authoritative and loads LAST. Everything above
   it in styles.css defines the dark system; this file restates
   dark explicitly and gives light a complete, equal definition.

   Two modes only:

     [data-mode="dark"]  (or no attribute)  — the night system
     [data-mode="light"] (or "warm")        — the daylight system

   "warm" and "desert" are kept as aliases so existing markup
   keeps working, but they are not separate modes any more.

   THE RULE THAT MATTERS: light mode is not dark mode with the
   values flipped. Glow is the depth model on dark; on a light
   ground a glow is a smudge, so light mode uses SHADOW as its
   depth model instead. Every halo token becomes a tinted drop
   shadow rather than a bloom. That is the one structural
   difference between the two, and it is deliberate.
   ========================================================= */

/* ---------------------------------------------------------
   DARK — restated explicitly so [data-mode="dark"] works
   as a real value rather than relying on the absence of one.
--------------------------------------------------------- */
:root,
[data-mode="dark"],
.force-dark {
  color-scheme: dark;

  --bg:            #0a0e16;
  --bg-deep:       #06090f;
  --bg-raised:     #121826;
  --bg-raised-2:   #1a2233;
  --bg-chrome:     rgba(18, 24, 38, 0.84);
  --bg-sunken:     #05070c;

  --fg:            #f4ecde;
  /* CREAM AT ALPHA, NOT A TINTED GREY.
     These were #c4c7b2 / #8f9385 / #5f6459 — all three green-tinted (G above R),
     and they overrode the corrected moonlight ramp because this block comes
     after :root. They were also one digit off the #c3c4b2 that was swept, which
     is why a literal search missed them. Dimming the cream itself cannot drift
     to another hue: there is no second pigment in the mix. */
  --fg-dim:        rgba(244, 236, 222, 0.82);
  --fg-mute:       rgba(244, 236, 222, 0.62);
  --fg-low:        rgba(244, 236, 222, 0.34);
  --fg-on-accent:  #f4ecde;

  /* CLAY AS TYPE. Clay is the statement colour, but the step that works as type
     depends on the ground: --clay-soft #DC6E59 is right on night and only
     2.76:1 on cream, while --clay-deep #A44030 is 4.8:1 on cream and too dark
     on night. Use --clay-text for any clay TEXT and it follows the mode.
     --clay-mark is for bars, dots and fills, where 3:1 is the bar. */
  --clay-text: var(--clay-soft);
  /* --ochre is the legacy name for clay and is still used for TYPE in ~20 places
     (section numerals, board chrome, prose links, hub numbers, tarot numbers).
     It was a flat alias to --clay in colors.css, so it did not flip with the
     mode and measured 3.53:1 on cream wherever it carried text. Pointing it at
     --clay-text makes every one of those sites mode-correct at once. Mark uses
     (focus rings, nav underlines, chart fills) shift by one step and stay well
     clear of 3:1. */
  --ochre: var(--clay-text);
  --clay-mark: var(--clay);

  /* THE ACCENT COMPLEMENTS THE GROUND, AND THE GROUND FLIPS WITH THE MODE.
     Night is a cool blue-black, so its accent is warm — clay. Daylight is a warm
     cream, so its accent must be COOL, or the page is only near-black and brick
     red, which reads corporate. Same complementary logic, mirrored. Use
     --accent-text for any accent TYPE and --accent-mark for bars, dots and
     fills; both follow the mode. --clay-text stays for the rare case where the
     accent must be clay specifically. */
  --accent-text: var(--clay-soft);
  --accent-mark: var(--clay);

  /* ALL FOUR HUES ARE AVAILABLE — each with a text-safe step per mode.
     Assign by ROLE, not by picking one winner, so the palette can be broad
     without being noisy:
       clay     statements, emphasis, the script word
       rose     data and the second arc step
       magenta  labels, eyebrows, meta
       indigo   controls, links, marks, large numerals
     -text is the legible step for TYPE on this ground; -mark is the base hue,
     for bars, dots and fills where 3:1 is the bar.
     CAVEAT ON NIGHT: --magenta-text (3.64:1) and --indigo-text (3.96:1) are the
     LIGHTEST steps their hues have, so neither clears AA at small size on ink and
     neither can be fixed by tuning. On a dark ground both are for MARKS and type
     at 24px and up only. Small labels take --label-text, which is rose on night
     and magenta on cream — so the label ROLE keeps a cool feel in daylight and a
     legible warm one at night. */
  --clay-text:    var(--clay-soft);
  /* --ochre is the legacy name for clay and is still used for TYPE in ~20 places
     (section numerals, board chrome, prose links, hub numbers, tarot numbers).
     It was a flat alias to --clay in colors.css, so it did not flip with the
     mode and measured 3.53:1 on cream wherever it carried text. Pointing it at
     --clay-text makes every one of those sites mode-correct at once. Mark uses
     (focus rings, nav underlines, chart fills) shift by one step and stay well
     clear of 3:1. */
  --ochre: var(--clay-text);
  --rose-text:    var(--rose-soft);
  --magenta-text: var(--magenta-soft);
  --indigo-text:  var(--indigo-soft);
  --label-text:   var(--rose-soft);
  --clay-mark:    var(--clay);
  --rose-mark:    var(--rose);
  --magenta-mark: var(--magenta);
  --indigo-mark:  var(--indigo);

  --border:        rgba(244, 236, 222, 0.14);
  --border-soft:   rgba(244, 236, 222, 0.08);
  --border-strong: rgba(244, 236, 222, 0.28);

  --pane-blur:         blur(14px) saturate(1.5);
  --glass-blur:        blur(16px) saturate(165%);
  --glass-blur-heavy:  blur(28px) saturate(180%);
  --glass-fill:        linear-gradient(150deg, rgba(244,236,222,0.070) 0%, rgba(244,236,222,0.028) 100%);
  --glass-fill-hi:     linear-gradient(150deg, rgba(244,236,222,0.115) 0%, rgba(244,236,222,0.050) 100%);
  --glass-fill-deep:   linear-gradient(150deg, rgba(30,24,58,0.72) 0%, rgba(16,14,34,0.62) 100%);
  --glass-border:      rgba(244, 236, 222, 0.16);
  --glass-shadow:      0 24px 60px -30px rgba(0, 0, 0, 0.72);

  --shadow-1: 0 1px 0 rgba(0,0,0,0.25);
  --shadow-2: 0 4px 16px rgba(0,0,0,0.30);
  --shadow-3: 0 20px 60px rgba(0,0,0,0.50);

  --ring:       var(--parchment);
  --ring-wash:  rgba(220, 205, 180, 0.22);

  --accent:      var(--clay);
  --link:        var(--parchment);
  --link-hover:  var(--moonlight);

  --state-good: var(--sage);
  --state-warn: var(--parchment-deep, #b9a684);
  --state-crit: var(--clay);
  --state-info: var(--indigo);

  /* Ground: the night has a sky. */
  --ground-stars: 0.9;
  --ground-bloom: 1;
}

/* ---------------------------------------------------------
   LIGHT — the daylight system. A complete definition, not a
   set of exceptions.
--------------------------------------------------------- */
[data-mode="light"],
[data-mode="warm"],
[data-mode="desert"] {
  color-scheme: light;

  /* Surfaces step UP toward white as they come forward — the
     opposite direction to dark mode, where they step up toward
     light out of black. Base is warm off-white, not pure white:
     pure white under a serif this contrasty reads clinical. */
  --bg:            #fbf7f0;
  --bg-deep:       #f2ebdd;
  --bg-raised:     #ffffff;
  --bg-raised-2:   #fffdf9;
  --bg-chrome:     rgba(251, 247, 240, 0.82);
  --bg-sunken:     #ede5d5;

  --fg:            #0a0e16;
  /* Not pure ink. #0A0E16 is technically blue-black but renders as flat black,
     and black type plus a red accent on cream is the corporate combination.
     Tinting the ink toward indigo keeps it at ~15:1 on bone while giving the
     whole daylight page a violet cast instead of a grey one. Derived from
     palette tokens, not a new hex. */
  --fg:            color-mix(in srgb, var(--ink) 88%, var(--indigo-deep));
  --fg-dim:        color-mix(in srgb, var(--fg) 82%, transparent);
  --fg-mute:       color-mix(in srgb, var(--fg) 64%, transparent);
  --fg-low:        color-mix(in srgb, var(--fg) 38%, transparent);
  --fg-on-accent:  #fffdf9;

  --clay-text: var(--clay-deep);
  /* --ochre is the legacy name for clay and is still used for TYPE in ~20 places
     (section numerals, board chrome, prose links, hub numbers, tarot numbers).
     It was a flat alias to --clay in colors.css, so it did not flip with the
     mode and measured 3.53:1 on cream wherever it carried text. Pointing it at
     --clay-text makes every one of those sites mode-correct at once. Mark uses
     (focus rings, nav underlines, chart fills) shift by one step and stay well
     clear of 3:1. */
  --ochre: var(--clay-text);
  --clay-mark: var(--clay);
  /* Cool accent on a warm ground — see the note in the dark block. */
  --accent-text: var(--magenta-deep);
  --accent-mark: var(--magenta);

  /* The deep step is the legible one on cream. No size caveat here — all four
     clear AA at text size on bone. */
  --clay-text:    var(--clay-deep);
  /* --ochre is the legacy name for clay and is still used for TYPE in ~20 places
     (section numerals, board chrome, prose links, hub numbers, tarot numbers).
     It was a flat alias to --clay in colors.css, so it did not flip with the
     mode and measured 3.53:1 on cream wherever it carried text. Pointing it at
     --clay-text makes every one of those sites mode-correct at once. Mark uses
     (focus rings, nav underlines, chart fills) shift by one step and stay well
     clear of 3:1. */
  --ochre: var(--clay-text);
  --rose-text:    var(--rose-deep);
  --magenta-text: var(--magenta-deep);
  --indigo-text:  var(--indigo-deep);
  --label-text:   var(--magenta-deep);
  --clay-mark:    var(--clay);
  --rose-mark:    var(--rose);
  --magenta-mark: var(--magenta);
  --indigo-mark:  var(--indigo);

  /* Ink at low alpha, NOT a warm literal. This was #dcd2c2 — rgb(220,210,194),
     hue ~41 degrees, a khaki — while both its siblings were already ink-alpha.
     It is the default hairline for every card, board and kit in light mode, so
     one warm literal put a tan line around the whole system. .14 sits between
     soft (.09) and strong (.26). */
  --border:        rgba(10, 14, 22, 0.14);
  --border-soft:   rgba(10, 14, 22, 0.09);
  --border-strong: rgba(10, 14, 22, 0.26);

  /* Glass on light is white haze over the ground, held by a DARK
     hairline. The saturate is lower — on a light ground pushing
     saturation past ~140% tints the haze and it stops reading
     as glass. brightness lifts it clear of the surface behind. */
  --pane-blur:         blur(14px) saturate(1.25) brightness(1.02);
  --glass-blur:        blur(16px) saturate(140%) brightness(1.03);
  --glass-blur-heavy:  blur(28px) saturate(150%) brightness(1.04);
  --glass-fill:        linear-gradient(150deg, rgba(255,255,255,0.74) 0%, rgba(255,255,255,0.48) 100%);
  --glass-fill-hi:     linear-gradient(150deg, rgba(255,255,255,0.90) 0%, rgba(255,255,255,0.64) 100%);
  --glass-fill-deep:   linear-gradient(150deg, rgba(255,255,255,0.90) 0%, rgba(250,245,236,0.80) 100%);
  --glass-border:      rgba(10, 14, 22, 0.10);
  --glass-shadow:      0 20px 48px -26px rgba(48, 38, 28, 0.34);

  /* Real shadows, warm-tinted. Never neutral grey — a grey shadow
     on a warm ground reads as dirt. */
  --shadow-1: 0 1px 2px rgba(48, 38, 28, 0.08);
  --shadow-2: 0 6px 18px -6px rgba(48, 38, 28, 0.16);
  --shadow-3: 0 24px 60px -24px rgba(48, 38, 28, 0.26);
  --shadow-sheet: 0 -12px 40px rgba(48, 38, 28, 0.18);

  /* DEPTH IS SHADOW, NOT GLOW. Every halo becomes a tinted drop
     shadow that keeps the hue but drops the bloom. */
  --halo-signature:
    0 8px 20px -8px rgba(238,74,48,0.36),
    8px -2px 16px -10px rgba(78,124,232,0.28),
    0 14px 34px -14px rgba(150,72,220,0.24);
  --halo-signature-hover:
    0 10px 26px -8px rgba(238,74,48,0.46),
    10px -3px 20px -10px rgba(78,124,232,0.36),
    0 18px 42px -14px rgba(150,72,220,0.30);
  --halo-moonlight:   0 6px 18px -8px rgba(48,38,28,0.26);
  --halo-violet:      0 8px 22px -8px rgba(79,63,214,0.40);
  --halo-terracotta:  0 8px 22px -8px rgba(203,88,66,0.40);
  --halo-iris:        0 10px 28px -12px rgba(203,88,66,0.34), 0 16px 40px -18px rgba(79,63,214,0.26);
  --halo-iris-soft:   0 8px 20px -10px rgba(203,88,66,0.24);
  --halo-red:         0 6px 18px -8px rgba(164,64,48,0.42);
  --halo-green:       0 6px 18px -8px rgba(90,104,74,0.42);

  --ring:       var(--clay-deep);
  --ring-wash:  rgba(164, 64, 48, 0.18);

  /* On a light ground the base hues are too light to be legible as
     type or as a 1px line, so the deep steps carry those jobs. */
  --accent:      var(--clay-deep);
  --link:        var(--clay-deep);
  --link-hover:  #7d2f22;

  --state-good: #5a6849;
  --state-warn: #97803f;
  --state-crit: var(--clay-deep);
  --state-info: #3a2caa;

  /* No sky in daylight. */
  --ground-stars: 0;
  --ground-bloom: 0.22;
}

/* ---------------------------------------------------------
   Material corrections that a token swap alone cannot make.
--------------------------------------------------------- */

/* The ground loses its starfield and most of its bloom. */
[data-mode="light"] .n-ground,
[data-mode="warm"] .n-ground,
[data-mode="light"] .ambient,
[data-mode="warm"] .ambient { background: var(--bg); }
[data-mode="light"] .n-ground__stars,
[data-mode="warm"] .n-ground__stars { display: none; }
[data-mode="light"] .n-ground::before,
[data-mode="warm"] .n-ground::before,
[data-mode="light"] .ambient::before,
[data-mode="warm"] .ambient::before,
[data-mode="light"].ambient::before,
[data-mode="warm"].ambient::before { opacity: var(--ground-bloom); }
[data-mode="light"] .n-bloom::before,
[data-mode="warm"] .n-bloom::before { opacity: 0.3; }

/* Cards gain a shadow they do not have on dark, and lose the
   translucent lift that only reads against a void. */
[data-mode="light"] .n-card,
[data-mode="warm"] .n-card { box-shadow: var(--shadow-2); }
[data-mode="light"] .n-menu,
[data-mode="warm"] .n-menu { box-shadow: var(--shadow-3); }

/* THE SIGNATURE CTA INVERTS. A cream glass pane over coloured light
   is the whole idea on dark — and it cannot survive on a light
   ground, because cream on cream has no silhouette and glass has
   nothing dark to reveal.

   IT INVERTS TO INDIGO, NOT TO INK. A solid black pill on cream is the
   corporate default, and it wastes the one role the palette already assigns:
   indigo carries controls. Indigo-deep is 8.1:1 under cream type, it complements
   the warm ground the way clay complements the cool one, and the coloured fringe
   still reads underneath it. */
[data-mode="light"] .n-btn--iridescent,
[data-mode="warm"] .n-btn--iridescent {
  background: var(--indigo-deep);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  color: var(--moonlight);
  border: 1.5px solid rgba(255, 255, 255, 0.16);
  box-shadow: var(--halo-signature);
}
[data-mode="light"] .n-btn--iridescent::before,
[data-mode="warm"] .n-btn--iridescent::before { opacity: 0.55; filter: blur(13px); inset: -11px; }
[data-mode="light"] a.n-btn--iridescent:hover,
[data-mode="warm"] a.n-btn--iridescent:hover { color: var(--moonlight); }

/* Moonlight follows it — a cream pill is invisible in daylight. Indigo again,
   and --halo-moonlight is a cream glow with nothing to glow against on cream, so
   it becomes a warm-tinted drop shadow: daylight has shadows, not halos. */
[data-mode="light"] .n-btn--moonlight,
[data-mode="warm"] .n-btn--moonlight {
  background: var(--indigo-deep);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  color: var(--moonlight);
  border: 1.5px solid rgba(255, 255, 255, 0.14);
  box-shadow: 0 10px 26px -12px rgba(58, 44, 171, 0.55);
}
[data-mode="light"] .n-btn--moonlight:hover,
[data-mode="warm"] .n-btn--moonlight:hover { background: var(--indigo); }
[data-mode="light"] .n-btn--moonlight::before,
[data-mode="warm"] .n-btn--moonlight::before,
[data-mode="light"] .n-btn--primary::before,
[data-mode="warm"] .n-btn--primary::before,
[data-mode="light"] .n-btn--halo::before,
[data-mode="warm"] .n-btn--halo::before,
[data-mode="light"] .n-btn--iridescent::before,
[data-mode="warm"] .n-btn--iridescent::before { display: none; }
[data-mode="light"] a.n-btn--moonlight:hover,
[data-mode="warm"] a.n-btn--moonlight:hover { color: var(--moonlight); }

/* GLASS FILLS ARE A NIGHT DEVICE — ON CREAM THEY GO PASTEL.
   A translucent fill takes its perceived colour from whatever is behind it, so
   --glass-violet (indigo at 54%) reads as saturated indigo over ink and as pale
   lavender over cream. Same failure as the bloom: the effect depends on a dark
   ground existing. In daylight every filled button becomes SOLID — no alpha, no
   backdrop-filter — and keeps its role hue: indigo for controls, clay for the
   warm statement CTA. */
[data-mode="light"] .n-btn--primary,
[data-mode="warm"] .n-btn--primary {
  background: var(--indigo-deep);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  color: var(--moonlight);
  border-color: transparent;
  box-shadow: 0 10px 26px -12px rgba(58, 44, 171, 0.5);
}
[data-mode="light"] .n-btn--primary:hover,
[data-mode="warm"] .n-btn--primary:hover { background: var(--indigo); border-color: transparent; }
[data-mode="light"] .n-btn--primary:active,
[data-mode="warm"] .n-btn--primary:active { background: var(--indigo-deep); }

[data-mode="light"] .n-btn--iris,
[data-mode="warm"] .n-btn--iris {
  background: var(--clay-deep);
  -webkit-backdrop-filter: none; backdrop-filter: none;
  color: var(--moonlight);
  border-color: transparent;
  box-shadow: 0 10px 26px -12px rgba(164, 64, 48, 0.5);
}
[data-mode="light"] .n-btn--iris:hover,
[data-mode="warm"] .n-btn--iris:hover { background: var(--clay); border-color: transparent; }

/* A cream pill is invisible on cream, and its violet halo has nothing to glow
   against, so the halo variant goes solid too. */
[data-mode="light"] .n-btn--halo,
[data-mode="warm"] .n-btn--halo {
  background: var(--indigo-deep); color: var(--moonlight);
  box-shadow: 0 10px 26px -12px rgba(58, 44, 171, 0.5);
}
[data-mode="light"] .n-btn--halo:hover,
[data-mode="warm"] .n-btn--halo:hover { background: var(--indigo); box-shadow: 0 12px 30px -12px rgba(58, 44, 171, 0.6); }
[data-mode="light"] a.n-btn--halo:hover,
[data-mode="warm"] a.n-btn--halo:hover { color: var(--moonlight); }

/* NOTHING GLOWS ON CREAM. The aura is a night device: on a light ground the
   blurred pool has no darkness to read against and just muddies the edge, so
   the pool is removed and the halo becomes a warm-tinted drop shadow in the
   button's own hue. The fill was already solid, so the pill itself is unchanged
   — only its light goes. */
[data-mode="light"] .n-btn--aura::before,
[data-mode="warm"] .n-btn--aura::before { display: none; }
[data-mode="light"] .n-btn--aura,
[data-mode="warm"] .n-btn--aura { box-shadow: 0 10px 26px -12px var(--aura-shadow, rgba(164,64,48,0.5)); }
[data-mode="light"] .n-btn--aura:hover,
[data-mode="warm"] .n-btn--aura:hover { box-shadow: 0 13px 32px -12px var(--aura-shadow, rgba(164,64,48,0.6)); }
[data-mode="light"] .n-btn--aura-rose,
[data-mode="warm"] .n-btn--aura-rose { --aura-shadow: rgba(140,44,64,0.5); }
[data-mode="light"] .n-btn--aura-magenta,
[data-mode="warm"] .n-btn--aura-magenta { --aura-shadow: rgba(104,28,116,0.5); }
[data-mode="light"] .n-btn--aura-indigo,
[data-mode="warm"] .n-btn--aura-indigo,
[data-mode="light"] .n-btn--aura-iris,
[data-mode="warm"] .n-btn--aura-iris { --aura-shadow: rgba(58,44,171,0.5); }

/* Logos: dark ink in daylight, cream at night. */
[data-mode="light"] .n-nav__brand img,
[data-mode="warm"] .n-nav__brand img,
[data-mode="light"] .n-footer__col img,
[data-mode="warm"] .n-footer__col img { filter: brightness(0); }

/* Chips: the active chip is indigo rather than cream glass — controls are indigo,
   in both modes. Ink here would be the same black-on-cream problem. */
[data-mode="light"] .n-chip[aria-pressed="true"],
[data-mode="light"] .n-chip--active,
[data-mode="warm"] .n-chip[aria-pressed="true"],
[data-mode="warm"] .n-chip--active {
  background: var(--indigo-deep); color: var(--moonlight); border-color: transparent;
}

/* Iris text needs the deep stops to stay legible on white. */
[data-mode="light"] .n-iris-text,
[data-mode="warm"] .n-iris-text {
  background-image: linear-gradient(102deg, var(--clay-deep) 0%, var(--rose-deep) 42%, #6e1f7a 70%, #3a2caa 100%);
}

/* A SPECIMEN THAT MUST STAY DARK. Glow is the dark-mode depth model; a bloom
   specimen on a light ground is demonstrating something that does not exist
   there. So the glow plate keeps its own night ground in both modes rather
   than degrading into a set of invisible smudges. .force-dark re-declares the
   full dark token set above, and these restate the halos that live in
   effects.css under :root. */
[data-mode="light"] .force-dark,
[data-mode="warm"] .force-dark {
  background: var(--bg-deep);
  --halo-signature:
    0 0 34px -6px rgba(238,74,48,0.50),
    0 0 44px -4px rgba(150,72,220,0.42),
    0 0 60px -10px rgba(78,124,232,0.34);
  --halo-signature-hover:
    0 0 42px -4px rgba(238,74,48,0.60),
    0 0 54px -2px rgba(150,72,220,0.52),
    0 0 74px -8px rgba(78,124,232,0.42);
  --halo-moonlight:   0 0 30px -6px rgba(244,236,222,0.34);
  --halo-violet:      0 0 32px -6px rgba(79,63,214,0.55);
  --halo-terracotta:  0 0 32px -6px rgba(203,88,66,0.55);
  --halo-iris:        0 0 34px -6px rgba(203,88,66,0.42), 0 0 48px -8px rgba(79,63,214,0.34);
  --halo-iris-soft:   0 0 26px -8px rgba(203,88,66,0.28);
  --halo-red:         0 0 28px -8px rgba(245,26,23,0.45);
  --halo-green:       0 0 28px -8px rgba(50,166,82,0.45);
  --shadow-2: 0 4px 16px rgba(0,0,0,0.30);
  --shadow-3: 0 20px 60px rgba(0,0,0,0.50);
}
/* Inside a forced-dark specimen the CTA is the real cream-glass build again,
   not the light-mode ink inversion. */
[data-mode="light"] .force-dark .n-btn--iridescent,
[data-mode="warm"] .force-dark .n-btn--iridescent {
  background: var(--fill-signature);
  -webkit-backdrop-filter: var(--pane-blur); backdrop-filter: var(--pane-blur);
  color: #15111f;
  border: 1.5px solid #ffffff;
}
[data-mode="light"] .force-dark .n-btn--iridescent::before,
[data-mode="warm"] .force-dark .n-btn--iridescent::before { opacity: 1; }
[data-mode="light"] .force-dark .n-btn--moonlight,
[data-mode="warm"] .force-dark .n-btn--moonlight {
  background: var(--glass-light, var(--moonlight)); color: var(--ink);
}

/* Respect the OS when the page has not chosen for itself. */
@media (prefers-color-scheme: light) {
  html[data-mode-auto]:not([data-mode]) { color-scheme: light; }
}
