/* © 2026 William C. Chesher. All Rights Reserved.
   tokens - spawn's colours, type and motion, the ONE source every page reads (the studio, the
   landing, gamecenter, the brand page, the code room, the admin).

   Glitch's method (operator, 2026-10-09: "use glitch as a source of truth for the way we do this"):
   every colour is a token here, no page restates one. Two players on a dark screen: lime is player
   one (the student) and leads; royal is player two (Claude) and appears only where player two is.

   GENESIS (wchesher, 2026-10-13: "Go back to the genesis. A spawn is a new instance. Fresh. The green
   works. It needs a more vibrant complement" / "elegant AF and playful and fun" / "WORLD CLASS" /
   "purple is teenyverse" / "the green and royal or cerulean?"). The ground was a grey-green near-black
   and player two a washed sky; together they made the whole product grey. Now the void leans blue, so
   it reads as a place rather than an absence, and player two is royal: a hard, saturated blue that
   stands off lime, and is neither teenyverse's purple nor glitch's magenta. The one gradient
   (--genesis) walks lime to royal through spring green and cerulean, player one into player two, and
   is spent on display type, the four stations and the spawn point only. The bloom is light at the
   moment a thing appears; white display type carries a faint royal glow (--ink-glow). */

:root {
  --surface: #070b18;              /* the ground: a void leaning blue, never grey */
  --panel: #0f1629;
  --panel-2: #172038;
  --well: #070b18;                 /* code and text wells sink back to the ground */
  --line: #233052;
  --line-2: #33426a;               /* a LINE, never text: 1.99 : 1, which passes for a border (3 : 1 is not
                                      asked of a decorative rule) and fails every word painted in it */
  --faint: #7f8bab;                /* the quietest TEXT: 5.78 : 1 on the ground, 5.30 on a panel, 4.76 on panel-2 */
  --ink: #f2f5ff;                  /* 18.02 : 1 on the ground */
  --ink-2: #c8d2ea;                /* 12.95 : 1 */
  --muted: #97a3c2;                /* 7.79 : 1 */
  --accent: #c6f432;               /* player one, 15.31 : 1 */
  --accent-hover: #d6ff5c;
  --accent-ink: #070b18;
  --accent-soft: rgba(198, 244, 50, .1);
  --p2: #5b7fff;                   /* player two, royal: 5.5 : 1 on the ground, 4.55 on panel-2 (pure royal #2f5bff is 3.8: lifted to read as text) */
  --p2-hover: #8fa8ff;
  --p2-soft: rgba(91, 127, 255, .14);
  --good: #c6f432;                 /* "gold" is the house colour on purpose: gold is the goal (it was "solid" before the stages) */
  --caution: #ffb547;              /* works, 10.73 : 1 */
  --bad: #ff5c7a;                  /* breaks, 6.34 : 1 */
  --series-out: #d95926;           /* a chart's second series beside --p2 (the trial's out-of-half, trial_charts.py):
                                      validated with royal on the panel, dark, every check passing (dataviz
                                      validate_palette.js: CVD dE 30.3, tritan 32.5); never a status colour */
  --display: "Bricolage Grotesque", "Bricolage Fallback", system-ui, sans-serif;
  --body: "Bricolage Grotesque", "Bricolage Fallback", system-ui, -apple-system, sans-serif;
  --pixel: "Silkscreen", "Silkscreen Fallback", ui-monospace, monospace;
  --mono: "IBM Plex Mono", ui-monospace, monospace;
  --type-label: 11px;             /* the pixel and mono labels */
  --type-small: 13px;             /* notes, chips, code, the dense rails */
  --type-body: 15px;              /* everything a student reads */
  --type-lead: 17px;              /* a place's lead and the lines a student writes */
  --radius: 14px;
  --radius-sm: 10px;
  --ease: cubic-bezier(.2, 0, .2, 1);
  --enter: cubic-bezier(.16, 1, .3, 1);
  --fast: 140ms;
  --maxw: 1440px;
  --side: #0a0f20;                 /* the side columns: the screen and player two (2026-10-10 handoff) */
  --shadow: 0 30px 80px -20px rgba(2, 4, 12, .92);
  --p2-wash: rgba(91, 127, 255, .1);
  --step: 160ms steps(4, end);     /* the one motion: spawn-in */
  --screen: #000;                  /* the game's own black, behind its canvas (gamecenter, spawn admin) */

  /* genesis: the one gradient, the light a spawn gives off, and the void's grid */
  --genesis-2: #3ee6a0;            /* spring green: the step after lime. A straight mix of lime and royal is a dull */
  --genesis-3: #22c4ff;            /* sea-grey; the walk between them goes through these two, and its third step is cerulean */
  --genesis: linear-gradient(100deg, var(--accent) 6%, var(--genesis-2) 40%, var(--genesis-3) 70%, var(--p2) 96%);   /* player one into player two */
  --bloom-1: rgba(62, 230, 160, .14);    /* the light at the spawn point: spring green, because lime light on blue greys out */
  --bloom-2: rgba(91, 127, 255, .24);    /* the royal halo around it */
  --grid: rgba(91, 127, 255, .08);       /* the void's pixel grid: texture, never a line you read */
  --ink-glow: 0 0 28px rgba(91, 127, 255, .32), 0 0 2px rgba(143, 168, 255, .3);   /* white display type, lit royal from behind */
  --glow: 0 0 0 1px rgba(198, 244, 50, .35), 0 10px 40px -8px rgba(198, 244, 50, .45);   /* a primary under the hand */
  --meter-lit: repeating-linear-gradient(90deg, var(--accent) 0 7px, transparent 7px 9px);    /* a slider's track: blocks lit up to */
  --meter-dark: repeating-linear-gradient(90deg, var(--line-2) 0 7px, transparent 7px 9px);   /* the value, dark past it; the gaps are clear */
}

/* THE VOID: every page's ground carries a faint light from above, player one's on the left and player
   two's on the right, so no screen is a flat slab. Fixed to the viewport, behind everything. */
body::before { content: ""; position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background:
    radial-gradient(60% 50% at 12% -10%, rgba(198, 244, 50, .07), transparent 70%),
    radial-gradient(70% 60% at 92% -6%, rgba(91, 127, 255, .14), transparent 70%); }

/* white display type is lit royal from behind (wchesher, 2026-10-13: "give the white font a blue glow?"):
   headings and the wordmark only, never a sentence a student reads */
h1, h2, .wordmark, .brand { text-shadow: var(--ink-glow); }

/* the gradient headline: player one into player two, clipped to the letters */
.genesis { background: var(--genesis); -webkit-background-clip: text; background-clip: text; color: transparent;
  -webkit-text-fill-color: transparent; padding-bottom: .08em; text-shadow: none; }   /* no glow: a shadow shows through clipped letters */

/* THE MINI HERO STAGE (wchesher, 2026-10-25: "build the top three now" / "dont overdo it. but make it a nice addition"),
   after the gate's mini hero and glitch's join door (Maestro, 2026-10-19: "make a minihero"). A door gets a lit stage:
   light pooled behind it (--stage, player two's royal unless the page names its own), faint scan lines, the genesis seam
   along its foot, and one scan bar that sweeps it on arrival. Compact on purpose: what the door is for stays on screen.
   Reduced motion skips the sweep. Used by the companion's header and a game's own page. */
.minihero { position: relative; isolation: isolate; overflow: hidden; border: 1px solid var(--line); border-radius: var(--radius);
  padding: clamp(16px, 4vw, 24px);
  background:
    radial-gradient(closest-side circle at 86% 26%, color-mix(in srgb, var(--stage, var(--p2)) 36%, transparent), transparent),
    radial-gradient(closest-side circle at 6% 100%, color-mix(in srgb, var(--accent) 12%, transparent), transparent),
    linear-gradient(160deg, rgba(255, 255, 255, .035), transparent 60%); }
.minihero::before { content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background: linear-gradient(180deg, transparent, color-mix(in srgb, var(--stage, var(--p2)) 30%, transparent) 90%, transparent) 0 -60% / 100% 26% no-repeat,
    repeating-linear-gradient(0deg, rgba(255, 255, 255, .03) 0 1px, transparent 1px 4px);
  animation: minihero-sweep 900ms var(--ease) 160ms 1 both; }
.minihero::after { content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; pointer-events: none; background: var(--genesis); }
@keyframes minihero-sweep { from { background-position: 0 -60%, 0 0; } to { background-position: 0 160%, 0 0; } }
@media (prefers-reduced-motion: reduce) { .minihero::before { animation: none; background-position: 0 -200%, 0 0; } }

/* THE COPYRIGHT LINE (wchesher, 2026-10-11): the one rule every page shares, so it lives with the
   tokens every page already reads. The quietest text, on the label scale. */
.copyright { margin: 0; max-width: none; padding: 20px 16px calc(20px + env(safe-area-inset-bottom)); text-align: center;
  font: var(--type-label)/1.4 var(--mono); letter-spacing: .04em; color: var(--faint); }

/* THE ICONS (Maestro, 2026-10-19: "I would like a fundamental icon pass", "Make this elegant AF and
   extensive", "adapt this to spawn brangin in a significant way"), the rule every page shares. One
   family (/icons.svg, cut from the teenyverse set by build_icons.py), one size, in the two players'
   colours: an icon is lime, player one's, wherever the student acts; royal where player two acts; and
   the control's own colour where that colour already means something (Undo's amber, a delete's red,
   saved). Under the hand it lights with the glow a lime action has. A lime action holds its icon in a
   dark notch, so the icon is lime on the ground there too. The word is always there: beside the icon,
   or as the control's aria-label and title. */
.icon { width: 16px; height: 16px; display: block; fill: currentColor; flex: none; color: var(--accent);
  transition: color var(--fast) var(--ease), filter var(--fast) var(--ease); }
:is(a, button, [role="button"]):hover:not(:disabled) > .icon { filter: drop-shadow(0 0 5px rgba(198, 244, 50, .55)); }
.btn.two .icon { color: var(--p2); }
.btn.two:hover:not(:disabled) > .icon { filter: drop-shadow(0 0 5px rgba(91, 127, 255, .6)); }
.btn.danger .icon, .undo-button .icon, :disabled > .icon { color: inherit; filter: none !important; }
.btn.primary .icon, .btn.danger.fill .icon { color: var(--accent-ink); filter: none !important; }
/* THE BUTTON SET (Maestro, 2026-10-21: "this interface sucks" / "buttons?"): one height scale every page reads,
   so a lime action and the button beside it are always the same height. Before, the tight rule below shrank only
   the lime one (34) while each skin kept its own 44, 46 and 52 for the rest, so no pair lined up. The skins
   (pages.css, spawn.css) take their heights and side padding from here and name none of their own.
   tight (Maestro, 2026-10-19: "the buttons need to be tight vertically"): the lime action hugs its notch, the
   same 5 of lime above, below and to the left of it, at every size */
:root { --btn-h: 34px; --btn-h-big: 40px; --btn-h-small: 30px; --btn-pad: 14px; --btn-pad-big: 18px; --btn-pad-small: 10px; }
.btn.primary:not(.small):not(.tiny):not(.inline):has(> .icon:first-child) { padding: 0 var(--btn-pad) 0 4px; gap: 9px; }
.btn.primary.big:not(.small):not(.tiny):not(.inline):has(> .icon:first-child) { padding: 0 var(--btn-pad-big) 0 4px; }
.btn.primary:not(.small):not(.tiny):not(.inline) > .icon { width: calc(var(--btn-h) - 10px); height: calc(var(--btn-h) - 10px);
  padding: 5px; margin: 0; box-sizing: border-box; background: var(--accent-ink); color: var(--accent); border-radius: 6px; }
.btn.primary.big:not(.small):not(.tiny):not(.inline) > .icon { width: calc(var(--btn-h-big) - 10px); height: calc(var(--btn-h-big) - 10px); padding: 7px; }
/* the focus ring: a lime ring round a lime button reads as a doubled border, so a lime action takes the ink ring;
   it shows for the keyboard only (:focus-visible), never at rest or under a click */
.btn.primary:focus-visible { outline-color: var(--ink); }
.icon-only { display: inline-grid; place-items: center; justify-content: center; align-items: center; padding: 0; }
:is(.quiet-link, .linkish, .mono-link, .back-pill, .link):has(> .icon) { display: inline-flex; align-items: center; gap: 7px; text-decoration: none; }
:is(.quiet-link, .linkish, .mono-link) > .icon { width: 14px; height: 14px; }
/* the one flourish: a switch turned on spawns its icon in, in the four steps everything that appears in
   spawn takes (--step), so turning a thing on reads as a small spawn of its own */
@keyframes icon-spawn { from { transform: scale(.4); opacity: 0; } to { transform: none; opacity: 1; } }
[aria-pressed="true"] > .icon { animation: icon-spawn var(--step) both; }

@keyframes spawn-in { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 1ms !important; transition-duration: 1ms !important; }
}
