/* ===================================================================
 * tw-tokens.css — TriviaWorks unified design tokens (2026-04-29)
 *
 * Authoritative semantic-token layer for the editor unification arc
 * (memory/editor-unification-arc-2026-04-29.md). Coexists with
 * tw-design-tokens-v4.css; v4 tokens remain in place for surfaces
 * not yet retoken'd. Phase 5 retokens migrate them across.
 *
 * Token namespaces (no collisions with v4 --paper-* / --ink-v4 / etc.):
 *   --surface-*    canvas / raised / overlay / scrim
 *   --text-*       primary / secondary / tertiary / inverse / link
 *   --border-*     subtle / strong / focus
 *   --accent-*     brand
 *   --state-*      success / warning / error / info (text + bg pair)
 *   --pool-*       internal / external / archive (semantic, distinct
 *                  from v4 --pool-import/internal/external)
 *   --type-*       semantic type scale (Gotham)
 *   --space-*      4 / 8 / 12 / 16 / 24 / 32 / 48 / 64
 *   --radius-*     xs / sm / md / lg / xl / pill
 *   --elev-*       elevation shadows 0..4
 *   --motion-*     instant / quick / standard / deliberate
 *   --ease-*       standard / enter / exit / emphasized
 *   --row-h, --pad-x, --pad-y, --gap, --target-min  (density-driven)
 *   --z-*          z-index scale
 *
 * Theming:
 *   :root                 light (default)
 *   [data-theme="dark"]   dark (explicit)
 *   prefers-color-scheme: dark on :root:not([data-theme])  system fallback
 *
 * Density (default compact):
 *   [data-density="comfortable"]   larger row + padding
 *
 * Reduced motion:
 *   prefers-reduced-motion: reduce  collapses all motion tokens to 0
 *
 * Fonts: assumes Gotham faces are loaded by tw-design-tokens-v4.css
 * (which any page using the new tokens should also include for now).
 * =================================================================== */

:root {
  /* ====== Surfaces ====== */
  --surface-base:     #FBF8F2;
  --surface-raised:   #FFFFFF;
  --surface-overlay:  #FAF6E9;
  --surface-sunk:     #F3EEE3;
  --surface-scrim:    rgba(28, 20, 16, 0.45);

  /* ====== Borders ====== */
  --border-subtle:    #EFE7D3;
  --border-strong:    #D9CFBD;
  --border-focus:     #1F6FEB;

  /* ====== Text ====== */
  --text-primary:     #1C1410;
  --text-secondary:   #3D342E;
  --text-tertiary:    #6B5F55;
  --text-quaternary:  #888888;
  --text-inverse:     #F2ECD9;
  --text-link:        #1F6FEB;
  --text-link-hover:  #1858C7;

  /* ====== Brand ====== */
  --accent-primary:         #8A6500;
  --accent-primary-pressed: #5E4500;
  --accent-primary-bg:      #FCF6E6;
  --accent-primary-hi:      #C89200;
  /* Text/glyph colour painted ON an --accent-primary fill (Track A
   * 2026-06-10). Light theme: white on the deep gold (5.3:1). Dark
   * theme: charcoal on the bright stage gold (10.8:1). */
  --accent-contrast:        #FFFFFF;

  /* ====== Mechanic panels (music-mashup / music-themed / sounds-like
   * family). Warm beige background + dark gold accent. Distinct from
   * generic --border-subtle / --accent-primary; used for the boxed
   * "stage mechanic" inspector panels in the editors. ====== */
  --mechanic-panel-bg:     #E5E0D5;
  --mechanic-panel-accent: #9B7400;

  /* ====== Question card ink ======
   * Body-ink colour for the tw-question-card surface (catalogue + grid
   * thumbnail). Sits one step lighter than --text-primary, used for
   * mechanic-icon glyphs + minor metadata rows. */
  --card-ink-body:    #3A3A42;

  /* ====== Stage ink cream ======
   * Off-white cream used by stage chrome (BBZ MC modals, overlay
   * scoreboard, player-join, grid view, mechanic style defaults).
   * Distinct from --stage-ink (#F2ECD9) which is the warmer brand
   * cream. --stage-ink-cream is the cooler neutral white used inside
   * the navy stage surfaces for body copy + controls. */
  --stage-ink-cream:  #F0F0F0;

  /* ====== Stage navy mid ======
   * Intermediate navy that sits between --stage (#0A1628) and
   * --stage-hi (#132240). Used as the gradient mid-stop on overlay
   * scoreboard backgrounds, BBZ MC actions row, player-reconnect
   * text colour, and element-media SVG fill. */
  --stage-navy-mid:   #0E1B34;

  /* ====== Audio trim dialog (purple modal skin) ======
   * The tw-audio-trim modal uses a deliberate purple palette distinct
   * from the rest of the editor chrome to signal "destructive media
   * edit". These tokens keep the colour family centralised so a future
   * skin swap is a one-line change. */
  --audio-trim-purple-border: #3A2F5A;
  --audio-trim-text-soft:     #9A8AB8;
  --audio-trim-canvas-bg:     #0E0920;

  /* ====== Semantic state ====== */
  --state-success:     #2E6B3E;
  --state-success-bg:  #DDEEDF;
  --state-warning:     #B06A14;
  --state-warning-bg:  #FBEBD2;
  --state-error:       #A83A2A;
  --state-error-bg:    #F7DCD6;
  --state-info:        #2B5E8A;
  --state-info-bg:     #D6E4F0;

  /* ====== Pool tints (semantic; distinct from v4 names) ====== */
  --pool-internal:     #3B6B4A;
  --pool-internal-bg:  #F0F7EC;
  --pool-external:     #3E4F87;
  --pool-external-bg:  #EDF0F9;
  --pool-archive:      #6A5784;
  --pool-archive-bg:   #F1ECF6;

  /* ====== Stage (slide canvas brand: navy + gold) ======
   * The dark "stage" is a brand surface, not a theme surface; the canvas
   * stays navy in both light and dark themes (broadcast slides should
   * look the same to viewers regardless of editor chrome theme).
   *
   * Canonical names (no -v4 / -navy suffix variants):
   *   --stage           primary navy canvas fill          (#0A1628)
   *   --stage-hi        raised navy (gradient top)        (#132240)
   *   --stage-lo        sunken navy (gradient bottom)     (#050B17)
   *   --stage-ink       cream text/ink on stage           (#F2ECD9)
   *   --stage-gold      brand gold                        (#FFC000)
   *   --stage-gold-dim  pressed/dimmed gold               (#BF9000)
   *   --stage-gold-hi   bright/highlight gold             (#FFD84D)
   *   --stage-bg-deep   slide-strip neutral near-black    (#1a1a1a)
   *
   * The v4 layer (`tw-design-tokens-v4.css`) declares longer-name
   * variants (--stage-v4, --stage-navy, --stage-gold-v4, etc.) that
   * resolve to the same hex values; this canonical block is the source
   * of truth for any module that loads only `tw-tokens.css`. */
  --stage:             #0A1628;
  --stage-hi:          #132240;
  --stage-lo:          #050B17;
  --stage-ink:         #F2ECD9;
  --stage-gold:        #FFC000;
  --stage-gold-dim:    #BF9000;
  --stage-gold-hi:     #FFD84D;
  --stage-bg-deep:     #1a1a1a;

  /* ====== Editor chrome (dark-on-dark UI surfaces) ======
   * Inline-style dark chrome used by overlay tools that float over the
   * stage/canvas: media browser, orphan gallery, slide sorter, canvas
   * timeline scrubber. These surfaces stay dark in both light + dark
   * themes (the host is reading them against the navy stage). M2's hex
   * sweep parked the recurring cluster as `var(--legacy, #...)` fallback
   * placeholders; this block promotes them to a real semantic family.
   *
   *   --editor-chrome-bg-base      deepest dark fill (input wells)
   *   --editor-chrome-bg-elevated  raised dark surface (canvas timeline)
   *   --editor-chrome-surface      generic dark button / control body
   *   --editor-chrome-border       hairline border on dark chrome
   *
   * Consumers wrap as `var(--editor-chrome-surface, #2b2b2b)` etc., so
   * the inlined hex remains as a fallback if the token cascade fails. */
  --editor-chrome-bg-base:     #0d0d0d;
  --editor-chrome-bg-elevated: #1a1a2e;
  --editor-chrome-surface:     #2b2b2b;
  --editor-chrome-border:      #444;

  /* ====== Skeleton loading (placeholder shimmer) ======
   * --skeleton-base      resting fill of a placeholder block
   * --skeleton-highlight the brighter band the shimmer sweep travels in
   * Consumed by the skeleton primitive in tw-state-patterns.js. Themed
   * here so the shimmer never hard-codes a hex value. */
  --skeleton-base:      #ECE4D2;
  --skeleton-highlight: #F7F1E1;

  /* ====== Type scale (Gotham) ====== */
  --type-family-sans: 'Gotham','Inter','Söhne',-apple-system,system-ui,sans-serif;
  --type-family-mono: 'JetBrains Mono','Berkeley Mono',ui-monospace,monospace;

  --type-display-large: 800 56px/64px var(--type-family-sans);
  --type-display:       700 32px/40px var(--type-family-sans);
  --type-h1:            700 24px/30px var(--type-family-sans);
  --type-h2:            700 18px/24px var(--type-family-sans);
  --type-h3:            500 14px/20px var(--type-family-sans);
  --type-body:          400 14px/20px var(--type-family-sans);
  --type-body-strong:   500 14px/20px var(--type-family-sans);
  --type-caption:       400 12px/16px var(--type-family-sans);
  --type-mono:          400 13px/18px var(--type-family-mono);

  --type-h3-tracking:   0.06em;
  --type-h3-transform:  uppercase;

  /* ====== Spacing scale ====== */
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 24px;
  --space-6: 32px;
  --space-7: 48px;
  --space-8: 64px;

  /* ====== Radius ====== */
  --radius-xs:   3px;
  --radius-sm:   5px;
  --radius-md:   8px;
  --radius-lg:   12px;
  --radius-xl:   18px;
  --radius-pill: 999px;

  /* ====== Elevation ====== */
  --elev-0: none;
  --elev-1: 0 1px 0 rgba(28, 20, 16, 0.04);
  --elev-2: 0 1px 3px rgba(28, 20, 16, 0.06), 0 0 0 0.5px rgba(28, 20, 16, 0.04);
  --elev-3: 0 6px 20px rgba(28, 20, 16, 0.08), 0 1px 3px rgba(28, 20, 16, 0.05);
  --elev-4: 0 24px 64px rgba(28, 20, 16, 0.14), 0 2px 8px rgba(28, 20, 16, 0.06);

  /* ====== Motion ====== */
  --motion-instant:    0ms;
  --motion-quick:      120ms;
  --motion-standard:   200ms;
  --motion-deliberate: 300ms;

  --ease-standard:   cubic-bezier(0.4, 0, 0.2, 1);
  --ease-enter:      cubic-bezier(0, 0, 0.2, 1);
  --ease-exit:       cubic-bezier(0.4, 0, 1, 1);
  --ease-emphasized: cubic-bezier(0.22, 1, 0.36, 1);

  /* ====== Density (compact default) ====== */
  --row-h:        32px;
  --pad-x:        8px;
  --pad-y:        4px;
  --gap:          var(--space-2);
  --target-min:   32px;
  --input-h:      32px;

  /* ====== Z-index scale ====== */
  --z-base:    0;
  --z-raised:  1;
  --z-sticky:  10;
  --z-drawer:  100;
  --z-modal:   1000;
  --z-toast:   2000;
  --z-palette: 3000;
}

/* Comfortable density — larger row + padding for new editors */
[data-density="comfortable"] {
  --row-h:      40px;
  --pad-x:      12px;
  --pad-y:      8px;
  --gap:        var(--space-3);
  --target-min: 40px;
  --input-h:    40px;
}

/* Dark theme — explicit selector.
 *
 * Track A retune (2026-06-10, Andrew-approved W6.1): the original dark set
 * was a warm near-black (#0E0B08 family) authored before the user-facing
 * toggle existed. The approved spec is "charcoal surfaces, off-white ink,
 * the stage gold as accent" - a cool neutral #16181D family that keeps the
 * navy+gold stage brand recognisable inside the editor chrome.
 * Contrast pass (2026-06-10 follow-up, Andrew: "dark mode might be TOO
 * dark - thin lines are hard to see"). Surfaces step wider (base->raised
 * ->overlay luminance steps 1.08/1.10 -> 1.20/1.18) and the border/rule
 * family lifts to clear ~3:1 non-text contrast on the surfaces it sits
 * on. --border-subtle lands 3.9:1 on base / 3.2:1 on raised (2.7:1 on
 * overlay - use --border-strong inside overlays, 4.1:1 there).
 * Contrast (WCAG):
 *   --text-primary  #ECEDEF on #16181D  = 15.2:1  (AAA)
 *   --text-secondary #C3C7CE on #242832 =  8.7:1  (AAA)
 *   --text-tertiary #9CA3AE on #2F3440  =  4.9:1  (AA on every surface)
 *   --border-subtle #6F7685 on #16181D  =  3.9:1  (non-text)
 *   --border-strong #8B94A4 on #2F3440  =  4.1:1  (non-text)
 *   --accent-primary #FFC000 on #16181D = 10.8:1  (AAA; gold-as-text safe)
 *   --accent-contrast #16181D on #FFC000 = 10.8:1 (text on gold fills)
 */
[data-theme="dark"] {
  --surface-base:     #16181D;
  --surface-raised:   #242832;
  --surface-overlay:  #2F3440;
  --surface-sunk:     #111318;
  --surface-scrim:    rgba(0, 0, 0, 0.6);

  --border-subtle:    #6F7685;
  --border-strong:    #8B94A4;
  --border-focus:     #4D8FF5;

  --text-primary:     #ECEDEF;
  --text-secondary:   #C3C7CE;
  --text-tertiary:    #9CA3AE;
  --text-quaternary:  #828A99;
  --text-inverse:     #16181D;
  --text-link:        #6FA6F8;
  --text-link-hover:  #8FBAFA;

  --accent-primary:         #FFC000;
  --accent-primary-pressed: #FFD84D;
  --accent-primary-bg:      #332B12;
  --accent-primary-hi:      #FFD84D;
  --accent-contrast:        #16181D;

  --mechanic-panel-bg:     #2E333F;
  --mechanic-panel-accent: #E0B321;

  /* Question-card ink picks up the off-white in dark mode so the body
   * text on --surface-raised stays legible. Stage-ink-cream /
   * stage-navy-mid / audio-trim purples are brand-stage surfaces
   * (always navy) and do NOT get a dark variant. */
  --card-ink-body:    #C3C7CE;

  --state-success:     #7DD18B;
  --state-success-bg:  #16271B;
  --state-warning:     #E8A554;
  --state-warning-bg:  #2A2113;
  --state-error:       #F08577;
  --state-error-bg:    #2B1714;
  --state-info:        #79ABF2;
  --state-info-bg:     #141C2B;

  --pool-internal:     #7DD18B;
  --pool-internal-bg:  #16271B;
  --pool-external:     #98A8E8;
  --pool-external-bg:  #181D2D;
  --pool-archive:      #B5A4E3;
  --pool-archive-bg:   #201A2E;

  --skeleton-base:      #2C313C;
  --skeleton-highlight: #3A4150;

  --elev-1: 0 1px 0 rgba(0, 0, 0, 0.3);
  --elev-2: 0 1px 3px rgba(0, 0, 0, 0.5), 0 0 0 0.5px rgba(255, 255, 255, 0.03);
  --elev-3: 0 6px 20px rgba(0, 0, 0, 0.6), 0 1px 3px rgba(0, 0, 0, 0.5);
  --elev-4: 0 24px 64px rgba(0, 0, 0, 0.8), 0 2px 8px rgba(0, 0, 0, 0.5);
}

/* System dark-mode fallback REMOVED (Track A, 2026-06-10).
 *
 * The original :root:not([data-theme]) + prefers-color-scheme block meant
 * an OS-dark user landed on a dark editor with no way back. The approved
 * W6.1 model is explicit + user-selectable: editor-suite pages set
 * data-theme from localStorage 'tw.theme' before first paint (inline FOUC
 * guard, default light); the toggle lives in the profile menu. Pages
 * without the guard now deterministically render the light set. */

/* Reduced motion — collapse motion durations to 0 */
@media (prefers-reduced-motion: reduce) {
  :root,
  [data-theme="dark"],
  [data-theme="light"] {
    --motion-quick:      0ms;
    --motion-standard:   0ms;
    --motion-deliberate: 0ms;
  }
}

/* ===================================================================
 * Utility classes — semantic type roles + focus ring
 * Components should prefer the var() form; these utilities exist for
 * one-off applications and template authoring.
 * =================================================================== */

.tw-display-large { font: var(--type-display-large); color: var(--text-primary); }
.tw-display       { font: var(--type-display);       color: var(--text-primary); }
.tw-h1            { font: var(--type-h1);            color: var(--text-primary); }
.tw-h2            { font: var(--type-h2);            color: var(--text-primary); }
.tw-h3 {
  font: var(--type-h3);
  color: var(--text-secondary);
  letter-spacing: var(--type-h3-tracking);
  text-transform: var(--type-h3-transform);
}
.tw-body          { font: var(--type-body);          color: var(--text-primary); }
.tw-body-strong   { font: var(--type-body-strong);   color: var(--text-primary); }
.tw-caption       { font: var(--type-caption);       color: var(--text-tertiary); }
.tw-mono          { font: var(--type-mono);          color: var(--text-secondary); }

/* Consistent focus ring across all interactive elements that opt in */
.tw-focus-ring:focus-visible,
[data-tw-focus]:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
  border-radius: inherit;
}

/* ===================================================================
 * B5 (Arc B 2026-05-19): Global :focus-visible ring
 *
 * Every focusable element gets a visible focus ring when reached via
 * keyboard. The opt-in selectors above stay so authors can attach the
 * exact same ring via class. This block is the global safety net.
 *
 * We intentionally target :focus-visible (NOT :focus) so the ring only
 * appears for keyboard navigation; mouse-click focus stays clean. Modern
 * browsers (>= 2020) ship :focus-visible; legacy fallback is a graceful
 * no-op.
 *
 * Elements with their own focus styling (e.g. the auth-input :focus
 * box-shadow on login.html) are unaffected because we don't remove
 * those — we only ADD the outline. If a surface explicitly suppresses
 * outline:none, it must also provide a :focus-visible alternative.
 * =================================================================== */
:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}
/* Override stray `outline: none` that some legacy CSS files apply for
 * mouse-focus polish. We bring the keyboard ring back specifically. */
button:focus-visible,
a:focus-visible,
[role="button"]:focus-visible,
input:focus-visible,
textarea:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
  outline: 2px solid var(--border-focus);
  outline-offset: 2px;
}

/* Visually-hidden but screen-reader-accessible (ARIA labels, sr-only) */
.tw-sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
