/* Design tokens — CSS_THEME_ARC Phase 1. See docs/tads/completed/CSS_THEME_ARC_TAD.md
   "Phase 1 DESIGN (LOCKED 2026-06-27)" section for the catalog spec.

   Light is the unconditional default (Decision 5). Dark is the OS-preference
   opt-in OR explicit operator toggle via [data-theme="dark"] on <html>. */

/* -------------------------------------------------------------------------- */
/* Color tokens — light theme (default)                                       */
/* -------------------------------------------------------------------------- */

:root,
:root[data-theme="light"] {
  /* Surfaces */
  --color-bg:                  #f5f5f5;
  --color-bg-elevated:         #ffffff;   /* modals, popovers, cards */
  --color-bg-raised:           #ebebeb;   /* hover states */
  /* Desk = the page/body backdrop, split out from --color-bg so a theme
     can darken the desk WITHOUT dragging the input/well/inset fields
     (which also read --color-bg) along with it. Aliased to --color-bg
     here (and in dark) so light/dark render byte-identically; only the
     olive theme diverges it. Consumed by `body` (shell.css) + songs `html`. */
  --color-bg-desk:             var(--color-bg);

  /* Text — #767676 picked over #777777 so subtle-on-elevated computes
     to 4.54:1, cleanly above WCAG AA 4.5:1 (vs 4.48:1 at #777777). */
  --color-fg:                  #1a1a1a;
  --color-fg-muted:            #555555;
  --color-fg-subtle:           #767676;
  --color-fg-on-accent:        #ffffff;
  /* On-desk text variants — for the handful of text spots that render
     DIRECTLY on the desk (not on a card): Sprites section heading + status,
     Play keyboard legend. Aliased to their base role here (and inherited
     unchanged by dark via the bare :root), so light/dark are untouched; the
     olive theme overrides them to light tones that read on the dark-olive
     desk. (Maps' .map-status was another consumer until E3 moved its messages
     to toasts.) */
  --color-fg-on-desk:          var(--color-fg);
  --color-fg-muted-on-desk:    var(--color-fg-muted);
  --color-accent-on-desk:      var(--color-accent);
  --color-danger-on-desk:      var(--color-danger);

  /* Borders */
  --color-border:              #d0d0d0;
  --color-border-strong:       #b0b0b0;

  /* Accent + state — PROVISIONAL per OD-5; operator finalizes at PR Z+1.
     #347820 picked over #4a9930 (originally drafted) so accent-on-white
     hits 5.53:1 (passes WCAG AA 4.5:1) — #4a9930 was 3.56:1 which fails
     AA for the .gb-button--accent text + selected-tab text usages. */
  --color-accent:              #347820;
  --color-accent-hover:        color-mix(in oklch, var(--color-accent) 88%, black);
  --color-accent-tint:         color-mix(in oklch, var(--color-accent) 14%, transparent);
  --color-danger:              #c8312e;
  --color-danger-tint:         color-mix(in oklch, var(--color-danger) 14%, transparent);
  --color-warn:                #b88419;
  --color-success:             var(--color-accent);

  /* Scrim + scrollbar */
  --color-scrim:               rgba(0, 0, 0, 0.35);
  --color-scrollbar-thumb:     #b0b0b0;
  --color-scrollbar-track:     #f5f5f5;

  /* Optional high-contrast pair (audit §15 #9) */
  --color-accent-hc:           #2a6b1a;
}

/* -------------------------------------------------------------------------- */
/* Color tokens — dark theme (opt-in)                                         */
/* -------------------------------------------------------------------------- */

:root[data-theme="dark"] {
  --color-bg:                  #1a1a1a;
  --color-bg-elevated:         #2a2a2a;
  --color-bg-raised:           #333333;

  --color-fg:                  #e0e0e0;
  --color-fg-muted:            #b8b8b8;
  --color-fg-subtle:           #999999;
  --color-fg-on-accent:        #1a1a1a;

  --color-border:              #444444;
  --color-border-strong:       #555555;

  --color-accent:              #86c06c;
  --color-accent-hover:        color-mix(in oklch, var(--color-accent) 88%, white);
  --color-accent-tint:         color-mix(in oklch, var(--color-accent) 12%, transparent);
  --color-danger:              #ff6b6b;
  --color-danger-tint:         color-mix(in oklch, var(--color-danger) 14%, transparent);
  --color-warn:                #f0c060;
  --color-success:             var(--color-accent);

  --color-scrim:               rgba(0, 0, 0, 0.55);
  --color-scrollbar-thumb:     #444444;
  --color-scrollbar-track:     #1a1a1a;

  --color-accent-hc:           #a8e088;
}

/* -------------------------------------------------------------------------- */
/* Color tokens — olive theme (opt-in)                                        */
/* -------------------------------------------------------------------------- */

/* Olive = the LIGHT theme with a dark-olive "desk" (page backdrop). Cards,
   inputs, wells and their dark text all inherit the light values from the
   bare `:root` block above (no --color-* redeclared here except the deltas),
   so the editor keeps its light "front"; only the desk and the few text spots
   that sit directly on it change. This mirrors the public-play page the
   operator liked: a light object floating on an olive desk.

   The olive #6d7256 is a muddy mid-dark (rel. luminance ~0.16), so on-desk
   text must be near-white to clear WCAG AA — measured contrasts on the desk:
   fg #f5f6ef → 4.61:1, muted #f2f4ec → 4.52:1, accent (faint-green) #f3f6ec
   → 4.58:1 all clear AA 4.5:1. Danger #ffe0db → 4.04:1 is the exception: a
   red that keeps any error identity physically caps below AA on olive (pure
   white-pink would be needed for 4.5), so it lands as a soft salmon — legible,
   AA-large-plus. Consumer: Sprites `.sprite-status.error` (Maps' `.map-status`
   used it too until E3 moved Maps messages to toasts). */
:root[data-theme="olive"] {
  --color-bg-desk:             #6d7256;   /* dark-olive page backdrop */
  --color-fg-on-desk:          #f5f6ef;   /* near-white desk text */
  --color-fg-muted-on-desk:    #f2f4ec;   /* dimmer desk text (Play legend) */
  --color-accent-on-desk:      #f3f6ec;   /* faint-green heading on the desk */
  --color-danger-on-desk:      #ffe0db;   /* soft-salmon error on the desk */
  --color-scrollbar-track:     #6d7256;   /* scrollbar rail matches the desk */
}

/* :root is a pseudo-class so its specificity is (0,1,0). The explicit
   theme blocks `:root[data-theme="light|dark|olive"]` add an attribute
   selector for (0,2,0). `:root[data-theme]` carries the same (0,2,0)
   — equal specificity to the explicit blocks. The high-contrast
   override fires because this @media rule comes LATER in source order
   and ties on specificity. (Bare `:root` here would lose at (0,1,0)
   vs the explicit theme blocks' (0,2,0) and the override would never
   apply on a themed page.) */
@media (prefers-contrast: more) {
  :root[data-theme] { --color-accent: var(--color-accent-hc); }
}

/* -------------------------------------------------------------------------- */
/* Theme-neutral game-data tokens — NEVER theme-scoped.                       */
/* Consumed by per-tab CSS (collision-class legend swatches in maps) and by   */
/* canvas overlays. Background-neutral so the overlays read the same against  */
/* the map PNG on every theme.                                                */
/* -------------------------------------------------------------------------- */

:root {
  --collision-walkable:       rgba(200, 200, 200, 0.25);
  --collision-unwalkable:     rgba(255,  30,  30, 0.70);
  --collision-ladder:         rgba( 60, 140, 255, 0.65);
  --collision-ladder-top:     rgba(120, 200, 255, 0.65);
  --collision-cloud:          rgba(255, 215,  60, 0.55);
  --collision-slope-up-left:  rgba(180, 100, 220, 0.65);
  --collision-slope-up-right: rgba(100, 200, 120, 0.65);
  /* CONDITIONAL_COLLISION D11: state-gated collision overrides — a distinct
     hot-pink so they pop against base collision (red) + the rest of the
     palette. */
  --collision-conditional:    rgba(255,  40, 150, 0.80);
  /* CONDITIONAL_SEARCH: state-gated search overrides — a distinct amber so a
     conditionally-searchable cell pops against base search (teal) + conditional
     collision (hot-pink). */
  --search-conditional:       rgba(255, 150,  40, 0.85);
  --portal-fill:              rgba(220,  60, 220, 0.80);
}

/* -------------------------------------------------------------------------- */
/* Spacing scale — base 4px                                                   */
/* -------------------------------------------------------------------------- */

:root {
  --space-0: 0;
  --space-1: 4px;
  --space-2: 8px;
  --space-3: 12px;
  --space-4: 16px;
  --space-5: 20px;
  --space-6: 24px;
  --space-7: 32px;
  --space-8: 48px;
}

/* -------------------------------------------------------------------------- */
/* Sizing tokens                                                              */
/* -------------------------------------------------------------------------- */

:root {
  --size-touch-min:        44px;
  /* Glyph size for icon-only buttons (.gb-button--icon + per-tab toggle
     glyphs). The 44px touch box dwarfs a 12–15px text glyph, so icons read
     as tiny; this sizes the mark to fill the button (MOBILE_RESPONSIVE).
     Legacy: still drives glyphs not yet migrated to the icon sheet. */
  --size-icon-glyph:       22px;
  /* Sprite-sheet icon display size (ICON_SYSTEM E1). .gb-icon fills the 44px
     touch box 1:1 with the 44×44 sheet cell; the art's internal padding gives
     the visual breathing room the old 22px glyph faked. --size-icon-sm is the
     inline/compact variant (.gb-icon--sm) for row affordances + status marks. */
  --size-icon:             44px;
  --size-icon-sm:          24px;
  --shell-header-h:        44px;
  --size-canvas-default:   512px;
  --size-modal-max:        720px;
  --size-layout-narrow:    1100px;
  --size-layout-wide:      1600px;
}

/* -------------------------------------------------------------------------- */
/* Type scale + family/weight/line/letter                                     */
/* Primitives use long-form font-family/size/weight/line-height/letter so the */
/* `font` shorthand doesn't silently reset letter-spacing.                    */
/* -------------------------------------------------------------------------- */

:root {
  --type-xs:    11px;
  --type-sm:    12px;
  --type-body:  13px;
  --type-md:    14px;
  --type-lg:    15px;
  --type-title: 18px;

  --font-mono:    ui-monospace, "SF Mono", Menlo, monospace;
  --font-display: "HelveticaNeue-Light", "Helvetica Neue Light",
                  "Helvetica Neue", Helvetica, Arial, sans-serif;

  --weight-regular: 500;
  --weight-bold:    600;
  --line-tight:     1;
  --line-default:   1.4;

  --letter-default: normal;
  --letter-tight:   0.02em;
  --letter-spaced:  0.05em;
}

/* -------------------------------------------------------------------------- */
/* Motion scale — reduced-motion neutralization lives here (canonical home)   */
/* -------------------------------------------------------------------------- */

:root {
  --motion-fast:    80ms;
  --motion-default: 150ms;
  --motion-slow:    250ms;
  --ease-out:       cubic-bezier(0.4, 0, 0.2, 1);
  --ease-in-out:    cubic-bezier(0.4, 0, 0.6, 1);
}

@media (prefers-reduced-motion: reduce) {
  :root {
    --motion-fast:    0ms;
    --motion-default: 0ms;
    --motion-slow:    0ms;
  }
}

/* -------------------------------------------------------------------------- */
/* z-index named scale                                                        */
/* -------------------------------------------------------------------------- */

:root {
  --z-base:         0;
  --z-toolbar:      20;
  --z-popover:      25;
  --z-sheet:        30;     /* mobile bottom-sheets (MOBILE_RESPONSIVE D9) — above popovers, below modals */
  --z-modal:        50;     /* legacy overlays; <dialog> bypasses via top-layer */
  --z-shell-header: 100;
  --z-toast:        110;    /* gbShell.toast — floats above the sticky header (E3). Still below a native <dialog> top-layer — see the TAD's D3 under-modal note. */
}

/* -------------------------------------------------------------------------- */
/* Breakpoints — device-class thresholds (MOBILE_RESPONSIVE D5).              */
/* CSS custom props can't be used inside @media conditions, so these values   */
/* are the CONTRACT, not consumed directly: each `@media (max-width: 640px)`  */
/* site carries a `--bp-phone` marker comment for grep-ability. Distinct from */
/* CSS_THEME_ARC's reserved (never-shipped) --bp-narrow/--bp-mid (760/1100).  */
/* -------------------------------------------------------------------------- */

:root {
  --bp-phone:  640px;   /* phone: hamburger nav + canvas chrome reflow */
  --bp-tablet: 960px;   /* tablet: at/above this width the desktop layout holds */
}

/* -------------------------------------------------------------------------- */
/* Radius + shadow                                                            */
/* -------------------------------------------------------------------------- */

:root {
  --radius-sm: 3px;
  --radius-md: 4px;
  --radius-lg: 6px;

  --shadow-popover:  0 4px 12px rgba(0, 0, 0, 0.30);
  --shadow-modal:    0 8px 24px rgba(0, 0, 0, 0.40);
  --shadow-elevated: 0 12px 32px rgba(0, 0, 0, 0.50);
}
