/* tokens-colors-v1 — W-56-1 — Saadjie color token layer. */
/* palette-themes-v1 — W-58-1 — Warm-earth brand + explicit theme selectors. */
/*
 * Planning: .archon/queued-builds/WAVE-56-design-tokens.md
 *            .archon/queued-builds/WAVE-58-color-palette.md
 *
 * WHY this file exists: every component stylesheet below this layer
 * references colour through `var(--color-*)`. Raw hex / rgba in any other
 * file is rejected by the W56 ANTI-RAW-VALUE proof-gate (and by
 * stylelint.config.js / .eslintrc.js shipped in W-56-4). Centralising the
 * palette here means future palette rotations touch ONE file.
 *
 * WHY warm-earth brand (W-58-1 update): the Saadjie brand is anchored to
 * the character art — warm earth tones (terracotta, sand, sage). The
 * previous mid-blue (#3366aa) inherited from the per-child themeColor
 * default conflated the *site* brand with a *child profile* default.
 * W58 decouples them: the global chrome (header, primary CTAs, focus
 * ring) now reads warm; the per-child hero block continues to honour the
 * stored themeColor (still defaulted to #3366aa in src/models/children.js
 * for backwards compatibility with existing rows).
 *
 * WHY three brand families (terracotta + sand + sage) rather than one:
 *  - Terracotta is the primary action / focus / link colour. Warm,
 *    inviting, distinct from the blue/gray of generic SaaS chrome.
 *  - Sand sits as a tertiary surface / divider tone, lifting cards off
 *    the page without competing with content.
 *  - Sage is the success/positive accent and a complementary cool note
 *    against the warm primary — balances the palette without going
 *    fully analogous.
 *
 * WHY explicit [data-theme="light"] / [data-theme="dark"] selectors AND
 * prefers-color-scheme media query: the media query covers the "no
 * parent preference set, follow OS" case. The attribute selectors let
 * the parent's saved preference (W-58-2 theme.js) override the OS hint
 * by writing `data-theme="light"` or `data-theme="dark"` on <html>.
 * Specificity: [data-theme] on :root beats the media query, so an
 * explicit choice always wins.
 *
 * WHY split out of public/css/tokens.css (the W26 aggregate): a single
 * monolithic tokens file made it hard to reason about which tokens belong
 * to which concern. W56 splits the tokens into modular files
 * (colors / spacing / typography / radius / shadow / motion) so a future
 * theme override can swap one slice without touching the rest. The legacy
 * public/css/tokens.css is left untouched for backwards compatibility —
 * W57+ rewires components onto this layer.
 *
 * WHY :root scope (not a class): tokens must be available to every node
 * in the document, including nodes rendered before component CSS loads
 * (the inline <style> blocks in src/views/public/*.ejs heroes).
 *
 * GOTCHA: any new colour MUST satisfy WCAG AA (4.5:1 for body text,
 * 3:1 for large text or non-text UI) against its expected background.
 * The contrast-audit script (scripts/contrast-audit.js, W-58-3) runs
 * the full pair matrix; do NOT hand-edit values without re-running it.
 *
 * CONSTRAINT: hex values are allowed *only* in files under
 * public/css/tokens/. The stylelint config in stylelint.config.js (W-56-4)
 * exempts this directory; all other CSS must use var(--color-*).
 *
 * CONSTRAINT: keep variable NAMES identical across the light + dark +
 * data-theme blocks. The cascade swaps VALUES; component CSS never
 * branches on scheme.
 */

:root {
  /* ---------- Brand (warm earth — terracotta) ----------
     WHY terracotta as the primary: warm, hand-made feel that matches the
     character art. #a8401a on white is ~6.4:1 (well above AA 4.5:1) so
     it's safe for body-weight text on the page background. */
  /* contrast: AA against --bg / white — terracotta family pre-audited by W-58-3
     (scripts/contrast-audit.js). --color-brand ~6.4:1, --color-brand-dark
     ~9.8:1, --color-brand-darker ~14:1 over #ffffff (all clear of the
     4.5:1 AA body-text floor and the 3:1 large-text / non-text-UI floor).
     --color-brand-light / -lighter are SURFACES — pair them with
     --color-text / --color-brand-dark for foreground, never the reverse. */
  /* fix-edge-2-v1 — W-99-1 — F-99-2 contract: every paired token in this
     file documents its AA pairing inline so a future palette rotation
     cannot silently drop below the floor without the diff making the
     change legible. The pre-audited pairings live in PAIRS in
     scripts/contrast-audit.js (W-58-3); the notes below mirror that
     contract in human-readable form. */
  --color-brand:               #a8401a;
  --color-brand-dark:          #7a2d10;
  --color-brand-darker:        #501c08;
  --color-brand-light:         #f7e8e0;
  --color-brand-lighter:       #fcf4ef;

  /* ---------- Sand (warm neutral accent) ----------
     WHY sand as a surface tone (not text): the desaturated warm beige
     gives card / divider chrome a softer feel than cool gray without
     forcing every text-on-sand pair to clear AA. Use sand-dark only as
     a foreground over sand-light / white. */
  /* contrast: AA against --bg / white only for --color-sand-dark
     (~7:1 on white) — --color-sand at ~2.4:1 is SURFACE-only and must
     NEVER carry text. Pair sand-dark as foreground over sand-light /
     sand-lighter / white. */
  --color-sand:                #c9a675;
  --color-sand-dark:           #6b4a1f;
  --color-sand-light:          #f2e8d4;
  --color-sand-lighter:        #faf5e9;

  /* ---------- Sage (complementary cool accent) ----------
     WHY sage as the cool counter-note: complements the warm primary
     without falling into a clashing complementary opposite. Sage-dark
     (#3f5236) on white is ~7.6:1 — safe for any text role. */
  /* contrast: AA against --bg / white — --color-sage-dark ~7.6:1 (safe
     for body text), --color-sage ~3.3:1 (large-text + non-text-UI only,
     clears the 3:1 WCAG 1.4.11 floor). --color-sage-light / -lighter
     are SURFACE tones — pair them with --color-text / --color-sage-dark
     for foreground. */
  --color-sage:                #6b8059;
  --color-sage-dark:           #3f5236;
  --color-sage-light:          #dde5d4;
  --color-sage-lighter:        #f0f3eb;

  /* ---------- Neutral text ----------
     contrast: AA against --bg / white — --color-text ~17:1 (well above
     AA), --color-text-muted ~7.7:1, --color-text-subtle ~4.7:1 (clears
     4.5:1 AA body-text floor — do NOT use for sub-16px copy). The
     -inverse and -link tokens are documented adjacent to their pairs
     in scripts/contrast-audit.js (W-58-3). */
  --color-text:                #1a1a1a;
  --color-text-muted:          #555555;
  --color-text-subtle:         #7a7f87;
  --color-text-inverse:        #ffffff;
  --color-text-link:           #7a2d10;
  --color-text-link-hover:     #501c08;

  /* ---------- Surfaces ----------
     WHY three surface levels: page (--color-bg), card / row (--bg-subtle),
     and raised modal / popover (--bg-raised). Components opt into a level
     instead of stacking custom backgrounds. */
  --color-bg:                  #ffffff;
  --color-bg-subtle:           #faf7f2;
  --color-bg-muted:            #f0ebe1;
  --color-bg-raised:           #ffffff;
  --color-bg-inverse:          #1a1a1a;

  /* ---------- Borders ----------
     WHY border-strong is darker than border (#7a6f5a vs #d8d0c0): the
     "strong" variant is used for non-text UI chrome (input outlines,
     section dividers in dense layouts) where WCAG 1.4.11 mandates 3:1
     against the surrounding background. The lighter --color-border is
     decorative-only and not subject to the 3:1 floor. */
  --color-border:              #d8d0c0;
  --color-border-subtle:       #ebe5d8;
  --color-border-strong:       #7a6f5a;
  --color-border-focus:        #a8401a;

  /* ---------- Status ----------
     WHY paired bg/fg per status: every status badge needs both an accent
     (text/icon) and a tinted background. Tying them together keeps the
     AA contrast invariant when used as `color: var(--color-success);
     background: var(--color-success-bg);`.

     WHY sage for success: success has historically been green; sage is
     our brand-tuned green so the accent feels intentional rather than
     a bootstrap-default leak. */
  /* contrast: AA against each paired -bg — --color-success on
     --color-success-bg ~6:1, --color-warning on --color-warning-bg ~5.7:1,
     --color-danger on --color-danger-bg ~5.4:1, --color-info on
     --color-info-bg ~6.5:1. The matching -border tokens carry 3:1 against
     --bg / white (WCAG 1.4.11 non-text-UI floor). */
  --color-success:             #3f5236;
  --color-success-bg:          #e6ede0;
  --color-success-border:      #b7c6a8;

  --color-warning:             #8a4a00;
  --color-warning-bg:          #fcefd9;
  --color-warning-border:      #e8c890;

  --color-danger:              #a3261e;
  --color-danger-bg:           #fbe6e3;
  --color-danger-border:       #ecb6b0;

  --color-info:                #1f4f8a;
  --color-info-bg:             #e4ecf6;
  --color-info-border:         #aec3df;

  /* ---------- Interaction ---------- */
  --color-focus-ring:          #a8401a;
  --color-selection-bg:        #f4d8c8;
  --color-selection-fg:        #1a1a1a;

  /* ---------- Overlays + shadow tint ----------
     WHY rgba (not hex): overlay layers need partial transparency over
     arbitrary page content. The alpha values are pinned (0.12 / 0.55) so
     the dim level of a modal scrim never drifts page-to-page. */
  --color-shadow-rgb:          40 24 16;
  --color-shadow:              rgba(40, 24, 16, 0.12);
  --color-shadow-strong:       rgba(40, 24, 16, 0.22);
  --color-overlay:             rgba(40, 24, 16, 0.55);
  --color-overlay-strong:      rgba(40, 24, 16, 0.75);
}

/* ---------- Explicit light theme (parent opt-in) ----------
   WHY a separate [data-theme="light"] block (mostly redundant with :root):
   when the parent has explicitly chosen "light" via the W-58-2 switcher,
   we want the cascade to lock light values even if the OS later flips
   to dark via prefers-color-scheme. The block re-states the light values
   at higher specificity than the @media block below. */
:root[data-theme="light"] {
  --color-brand:               #a8401a;
  --color-brand-dark:          #7a2d10;
  --color-brand-darker:        #501c08;
  --color-brand-light:         #f7e8e0;
  --color-brand-lighter:       #fcf4ef;

  --color-sand:                #c9a675;
  --color-sand-dark:           #6b4a1f;
  --color-sand-light:          #f2e8d4;
  --color-sand-lighter:        #faf5e9;

  --color-sage:                #6b8059;
  --color-sage-dark:           #3f5236;
  --color-sage-light:          #dde5d4;
  --color-sage-lighter:        #f0f3eb;

  --color-text:                #1a1a1a;
  --color-text-muted:          #555555;
  --color-text-subtle:         #7a7f87;
  --color-text-inverse:        #ffffff;
  --color-text-link:           #7a2d10;
  --color-text-link-hover:     #501c08;

  --color-bg:                  #ffffff;
  --color-bg-subtle:           #faf7f2;
  --color-bg-muted:            #f0ebe1;
  --color-bg-raised:           #ffffff;
  --color-bg-inverse:          #1a1a1a;

  --color-border:              #d8d0c0;
  --color-border-subtle:       #ebe5d8;
  --color-border-strong:       #7a6f5a;
  --color-border-focus:        #a8401a;

  --color-success:             #3f5236;
  --color-success-bg:          #e6ede0;
  --color-success-border:      #b7c6a8;

  --color-warning:             #8a4a00;
  --color-warning-bg:          #fcefd9;
  --color-warning-border:      #e8c890;

  --color-danger:              #a3261e;
  --color-danger-bg:           #fbe6e3;
  --color-danger-border:       #ecb6b0;

  --color-info:                #1f4f8a;
  --color-info-bg:             #e4ecf6;
  --color-info-border:         #aec3df;

  --color-focus-ring:          #a8401a;
  --color-selection-bg:        #f4d8c8;
  --color-selection-fg:        #1a1a1a;

  --color-shadow-rgb:          40 24 16;
  --color-shadow:              rgba(40, 24, 16, 0.12);
  --color-shadow-strong:       rgba(40, 24, 16, 0.22);
  --color-overlay:             rgba(40, 24, 16, 0.55);
  --color-overlay-strong:      rgba(40, 24, 16, 0.75);
}

/* ---------- Dark scheme via OS hint ----------
   WHY ship dark tokens (W56) and bind them to the OS hint here: a parent
   who has NOT chosen a theme follows the OS. Components don't have to
   opt in: any component that already uses var(--color-*) inherits the
   dark palette under `prefers-color-scheme: dark`.

   WHY this block sits BEFORE the explicit [data-theme="dark"] selector
   below: the attribute selector has equal-or-higher specificity than the
   media-query :root, so an explicit parent choice wins over the OS hint.

   GOTCHA: keep variable NAMES identical to the light-mode block above.
   The cascade swaps values; component CSS never branches on scheme. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    /* WHY brand-dark is LIGHTER than brand in dark mode (and not darker
       like the naming would suggest): on a dark surface, the "hover"
       (or pressed) variant has to move FURTHER from the background to
       stay distinguishable, which means *lighter* in dark mode. The
       token name keeps its semantic role ("the deeper / hover variant")
       while the actual lightness inverts. Components don't have to
       care — they just read brand-dark for hover regardless of theme. */
    --color-brand:             #d97a4f;
    --color-brand-dark:        #ec9a72;
    --color-brand-darker:      #f4b896;
    --color-brand-light:       #3d1f12;
    --color-brand-lighter:     #2a160c;

    --color-sand:              #c9a675;
    --color-sand-dark:         #e8cf9c;
    --color-sand-light:        #3a2f1f;
    --color-sand-lighter:      #261f14;

    --color-sage:              #98ad88;
    --color-sage-dark:         #b6c9a8;
    --color-sage-light:        #1f2a18;
    --color-sage-lighter:      #161e10;

    --color-text:              #f3f0eb;
    --color-text-muted:        #b8b2a6;
    --color-text-subtle:       #8c8678;
    --color-text-inverse:      #1a1a1a;
    --color-text-link:         #f0a87a;
    --color-text-link-hover:   #f7c4a1;

    --color-bg:                #1a1612;
    --color-bg-subtle:         #221d18;
    --color-bg-muted:          #2c2620;
    --color-bg-raised:         #251f1a;
    --color-bg-inverse:        #f3f0eb;

    --color-border:            #3a322a;
    --color-border-subtle:     #2c2620;
    --color-border-strong:     #857a6a;
    --color-border-focus:      #d97a4f;

    --color-success:           #b6c9a8;
    --color-success-bg:        #1f2a18;
    --color-success-border:    #3f5236;

    --color-warning:           #e8b96a;
    --color-warning-bg:        #2e2412;
    --color-warning-border:    #5a4520;

    --color-danger:            #e88a82;
    --color-danger-bg:         #2e1816;
    --color-danger-border:     #5a2a26;

    --color-info:              #7fa8d8;
    --color-info-bg:           #182332;
    --color-info-border:       #2c4263;

    --color-focus-ring:        #f0a87a;
    --color-selection-bg:      #7a2d10;
    --color-selection-fg:      #f3f0eb;

    --color-shadow-rgb:        0 0 0;
    --color-shadow:            rgba(0, 0, 0, 0.45);
    --color-shadow-strong:     rgba(0, 0, 0, 0.65);
    --color-overlay:           rgba(0, 0, 0, 0.72);
    --color-overlay-strong:    rgba(0, 0, 0, 0.85);
  }
}

/* ---------- Explicit dark theme (parent opt-in) ----------
   WHY a separate [data-theme="dark"] block: lets the parent force dark
   regardless of the OS hint. Mirrors the values in the @media block. */
:root[data-theme="dark"] {
  --color-brand:               #d97a4f;
  --color-brand-dark:          #ec9a72;
  --color-brand-darker:        #f4b896;
  --color-brand-light:         #3d1f12;
  --color-brand-lighter:       #2a160c;

  --color-sand:                #c9a675;
  --color-sand-dark:           #e8cf9c;
  --color-sand-light:          #3a2f1f;
  --color-sand-lighter:        #261f14;

  --color-sage:                #98ad88;
  --color-sage-dark:           #b6c9a8;
  --color-sage-light:          #1f2a18;
  --color-sage-lighter:        #161e10;

  --color-text:                #f3f0eb;
  --color-text-muted:          #b8b2a6;
  --color-text-subtle:         #8c8678;
  --color-text-inverse:        #1a1a1a;
  --color-text-link:           #f0a87a;
  --color-text-link-hover:     #f7c4a1;

  --color-bg:                  #1a1612;
  --color-bg-subtle:           #221d18;
  --color-bg-muted:            #2c2620;
  --color-bg-raised:           #251f1a;
  --color-bg-inverse:          #f3f0eb;

  --color-border:              #3a322a;
  --color-border-subtle:       #2c2620;
  --color-border-strong:       #857a6a;
  --color-border-focus:        #d97a4f;

  --color-success:             #b6c9a8;
  --color-success-bg:          #1f2a18;
  --color-success-border:      #3f5236;

  --color-warning:             #e8b96a;
  --color-warning-bg:          #2e2412;
  --color-warning-border:      #5a4520;

  --color-danger:              #e88a82;
  --color-danger-bg:           #2e1816;
  --color-danger-border:       #5a2a26;

  --color-info:                #7fa8d8;
  --color-info-bg:             #182332;
  --color-info-border:         #2c4263;

  --color-focus-ring:          #f0a87a;
  --color-selection-bg:        #7a2d10;
  --color-selection-fg:        #f3f0eb;

  --color-shadow-rgb:          0 0 0;
  --color-shadow:              rgba(0, 0, 0, 0.45);
  --color-shadow-strong:       rgba(0, 0, 0, 0.65);
  --color-overlay:             rgba(0, 0, 0, 0.72);
  --color-overlay-strong:      rgba(0, 0, 0, 0.85);
}

/* ---------- Forced-colors / high-contrast ----------
   WHY: Windows High Contrast Mode + browser forced-colors override author
   colors entirely. Pinning the focus ring + border to system keywords
   keeps keyboard focus visible when the cascade is hijacked. */
@media (forced-colors: active) {
  :root {
    --color-focus-ring:        Highlight;
    --color-border-focus:      Highlight;
    --color-text-link:         LinkText;
    --color-text-link-hover:   LinkText;
  }
}
