/* ===========================================================================
   PlaySapien design tokens — one language, three surfaces.

   THE CONTRACT

   Every surface (the shell and each game) defines the SAME role names. A
   surface differs only in the values it gives them. So a component written
   against `--bg` / `--fg` / `--accent` is portable, and a reader of any
   stylesheet in this repo knows what a name means without looking it up.

   Three themes everywhere: light, dark, and system. One mechanism:

     1. The choice lives in localStorage under `ps:theme` — ONE key, shared by
        all three surfaces, because they are one origin. Choose dark in Word
        Chain and the shell is dark when you navigate back to it.
        Values: "light" | "dark" | "system".
     2. A pre-paint inline script stamps data-theme="light"|"dark" on <html>,
        or removes the attribute for "system". It must run BEFORE first paint
        or the page flashes the wrong theme.
     3. CSS resolves in three blocks, in this order:
          :root                                     light (the base)
          @media (prefers-color-scheme: dark)
            :root:not([data-theme="light"])          system, following dark
          :root[data-theme="dark"]                   explicit dark, wins
        The `:not([data-theme="light"])` is what lets an explicit light choice
        beat a dark system. Leave it out and "light" silently stops working on
        a dark machine.

   THE ROLE NAMES

     Ground        --bg          the page
                   --bg-raise    above the page: sheets, cards, bars
                   --bg-sink     below it: wells, tracks, keycaps
                   --bg-edge     the far end of the ground ramp, for vignettes
     Text          --fg          primary
                   --fg-2        secondary
                   --fg-3        tertiary, hints
                   --fg-on-accent  text sitting on --accent
     Rules         --line        hairline
                   --line-2      a rule you are meant to notice
     Colour        --accent      the surface's signature, SAFE FOR TEXT
                   --accent-soft the same colour as a FILL — decorative only,
                                 never text; it is not contrast-checked
                   --good        success / correct
                   --warn        error / caution
     Effects       --shadow  --scrim
                   --texture-ink    colour of the paper grain overlay
                   --texture-alpha  how strongly the grain shows
     Stage         --stage       a ground that stays DARK IN BOTH THEMES
                   --stage-fg    text that sits on it

   WHY --stage EXISTS

   Sojourner is a lit globe. Its terrain, borders and region fills are a WebGL
   scene whose colours are baked into textures, not CSS — and they are designed
   against black. A light theme that lightened the globe's ground would wreck
   the artwork. So the globe keeps a dark stage in both themes while the chrome
   around it — bar, sheets, prompts, settings — goes light. Dark stage, light
   room, like a gallery. Any surface with artwork that must not re-theme uses
   the same pair.

   CONTRAST

   Every token in the text group clears 4.5:1 against the ground it is used on,
   verified by `packages/tokens/check-contrast.mjs`, which runs in CI. Run it
   after changing any value here. `--accent-soft` is deliberately exempt: it is
   a fill, and the checker skips it by name.

   A NOTE ON THE LIGHT SHELL. Its ground #C5C6C1 is a mid-tone, so there is
   little luminance headroom between primary and tertiary text. --fg-2 and
   --fg-3 are therefore separated by HUE rather than by lightness — one stays
   blue, one goes neutral. They read as different weights without either
   dropping below 4.5:1. This is a constraint of the anchor colour, not an
   oversight.
   =========================================================================== */

/* ---------------------------------------------------------------- type ---- */
:root {
  --f-disp:   "Fraunces", Georgia, "Times New Roman", serif;
  --f-body:   "Public Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif;
  --f-mono:   "IBM Plex Mono", ui-monospace, "SF Mono", Menlo, Consolas, monospace;
  --f-script: "Petit Formal Script", "Snell Roundhand", "Apple Chancery", cursive;
  /* A geometric sans, distinct from --f-body, used where the platform speaks in
     its own voice rather than a game's -- currently the shell's tagline.
     NOT the wordmark: PLAYSAPIEN is set in --f-disp (Fraunces), because the
     letterpress proof it is taken from is a serif and Montserrat flattened it.
     Defined here rather than in the shell because a value defined only in an
     inlined copy is overwritten the next time sync-inline runs. */
  --f-sans:   "Montserrat", "Helvetica Neue", Arial, sans-serif;

  /* Sojourner sets display headings at 700, the platform and Word Chain at
     900. Deliberate: a serif at 900 on a black ground closes up, and
     Sojourner's headings sit on black. Both are in the union font url. */
  --w-disp-game:     700;
  --w-disp-platform: 900;

  /* ------------------------------------------------------------ metrics -- */
  --bar-h: 58px;
  --icon-btn: 38px;
  --icon-stroke: 1.8;
  --corner-gap: 4px;
  --sheet-radius: 20px;
  --sheet-ease: transform .42s cubic-bezier(.22,.9,.3,1);
}

/* ===========================================================================
   PLAYSAPIEN — the shell.

   Sampled from the letterpress proof in the letterpress proof (01): cool grey rag paper, steel-blue foil on the rings and bars, a
   near-black navy for SAPIEN, and a warm taupe outline on PLAY. Those four
   are the whole brand.
   =========================================================================== */

.ps-shell {
  /* the proof's own inks, theme-independent */
  --brand-steel:      #5A7085;   /* the foil on the rings and bars           */
  --brand-steel-deep: #2F434C;   /* its shadowed side                        */
  --brand-navy:       #16242E;   /* SAPIEN                                   */
  --brand-taupe:      #9D8D85;   /* the PLAY outline                         */
  --brand-paper:      #C5C6C1;   /* the sheet                                */

  --bg:        #C5C6C1;
  --bg-raise:  #D6D7D3;
  --bg-sink:   #B3B4AF;
  --bg-edge:   #AFB0AA;
  --fg:        #213946;
  --fg-2:      #3D5465;          /* blue-leaning                            */
  --fg-3:      #485259;          /* neutral-leaning — see the note above     */
  --fg-on-accent: #EDEEEA;
  --line:      #ABADA7;
  --line-2:    #94968F;
  --accent:    #3F5569;
  --accent-soft: #5A7085;        /* fill only                                */
  --lockup-play:   #62768a;      /* PLAY, weight 300                         */
  --lockup-sapien: #213946;      /* SAPIEN, weight 700                       */
  --good:      #325843;
  --warn:      #863921;
  --shadow:    0 18px 50px rgba(33,57,70,.22);
  --scrim:     rgba(33,57,70,.30);
  --texture-ink:   #4B4F4A;
  --texture-alpha: .40;
}

.ps-shell[data-theme="dark"],
.ps-shell.t-dark {
  --bg:        #3D352A;
  --bg-raise:  #4A4137;
  --bg-sink:   #2F2921;
  --bg-edge:   #2A241D;
  --fg:        #EDE7DC;
  --fg-2:      #C9BFAF;
  --fg-3:      #BCAF9C;
  --fg-on-accent: #1A2229;
  --line:      #554B3E;
  --line-2:    #6B5F4F;
  --accent:    #9FB6C9;
  --accent-soft: #7A93A8;
  --lockup-play:   #93A7B8;
  --lockup-sapien: #EDE7DC;
  --good:      #7FBF9B;
  --warn:      #F29C74;
  --shadow:    0 18px 50px rgba(0,0,0,.48);
  --scrim:     rgba(20,16,11,.58);
  --texture-ink:   #0E0B07;
  --texture-alpha: .34;
}

@media (prefers-color-scheme: dark) {
  .ps-shell:not([data-theme="light"]) {
    --bg:        #3D352A;
    --bg-raise:  #4A4137;
    --bg-sink:   #2F2921;
    --bg-edge:   #2A241D;
    --fg:        #EDE7DC;
    --fg-2:      #C9BFAF;
    --fg-3:      #BCAF9C;
    --fg-on-accent: #1A2229;
    --line:      #554B3E;
    --line-2:    #6B5F4F;
    --accent:    #9FB6C9;
    --accent-soft: #7A93A8;
  --lockup-play:   #93A7B8;
  --lockup-sapien: #EDE7DC;
    --good:      #7FBF9B;
    --warn:      #F29C74;
    --shadow:    0 18px 50px rgba(0,0,0,.48);
    --scrim:     rgba(20,16,11,.58);
    --texture-ink:   #0E0B07;
    --texture-alpha: .34;
  }
}

/* ===========================================================================
   SOJOURNER — ink and amber.

   Dark is the original and is unchanged. Light is its inverse: the cream
   becomes the ground, the near-black becomes the text. Amber cannot simply
   invert — #E0A44A on cream is 1.8:1 — so the light theme darkens it to a
   burnt gold for text and keeps the bright amber as a fill only.

   --stage stays #0C0B0A in both, because the globe does.
   =========================================================================== */

.sj-game {
  --stage:     #0C0B0A;          /* the globe's ground, both themes          */
  --stage-fg:  #F0E8DA;
  --stage-line: #38302A;

  --bg:        #F0E8DA;
  --bg-raise:  #FAF5EB;
  --bg-sink:   #E0D5C2;
  --bg-edge:   #D8CBB4;
  --fg:        #0C0B0A;
  --fg-2:      #3A332B;
  --fg-3:      #5E5448;
  --fg-on-accent: #F7F2E7;
  --line:      #CFC3AE;
  --line-2:    #B2A48C;
  --accent:    #8A5E16;
  --accent-soft: #E0A44A;        /* fill only                                */
  --good:      #26705F;
  --warn:      #A63D17;
  --shadow:    0 18px 50px rgba(40,32,18,.18);
  --scrim:     rgba(30,24,14,.42);
  --texture-ink:   #6B5E48;
  --texture-alpha: .14;
}

.sj-game[data-theme="dark"],
.sj-game.t-dark {
  --bg:        #0C0B0A;
  --bg-raise:  #171412;
  --bg-sink:   #221D19;
  --bg-edge:   #050504;
  --fg:        #F0E8DA;
  --fg-2:      #C3B9AD;
  --fg-3:      #A99D8F;
  --fg-on-accent: #1A1206;
  --line:      #38302A;
  --line-2:    #4C423A;
  --accent:    #E0A44A;
  --accent-soft: #8E6B2C;
  --good:      #59B9A4;
  --warn:      #E8734A;
  --shadow:    0 18px 50px rgba(0,0,0,.55);
  --scrim:     rgba(6,5,4,.62);
  --texture-ink:   #000000;
  --texture-alpha: .10;
}

@media (prefers-color-scheme: dark) {
  .sj-game:not([data-theme="light"]) {
    --bg:        #0C0B0A;
    --bg-raise:  #171412;
    --bg-sink:   #221D19;
    --bg-edge:   #050504;
    --fg:        #F0E8DA;
    --fg-2:      #C3B9AD;
    --fg-3:      #A99D8F;
    --fg-on-accent: #1A1206;
    --line:      #38302A;
    --line-2:    #4C423A;
    --accent:    #E0A44A;
    --accent-soft: #8E6B2C;
    --good:      #59B9A4;
    --warn:      #E8734A;
    --shadow:    0 18px 50px rgba(0,0,0,.55);
    --scrim:     rgba(6,5,4,.62);
    --texture-ink:   #000000;
    --texture-alpha: .10;
  }
}

/* ===========================================================================
   WORD CHAIN — rose and plum.

   Was a clay ochre, which sat too close to Sojourner's amber; side by side on
   the shell's rail the two games read as one. This palette is deliberately in
   a different family so each game keeps its own identity.
   =========================================================================== */

.wc-game {
  --bg:        #E8D1DA;
  --bg-raise:  #F5E6EC;
  --bg-sink:   #D8BCC8;
  --bg-edge:   #D0B0BF;
  --fg:        #33262C;
  --fg-2:      #57444C;
  --fg-3:      #6B535D;
  --fg-on-accent: #FBF2F6;
  --line:      #CFB2BF;
  --line-2:    #B593A2;
  --accent:    #8E3A5A;
  --accent-soft: #C77E98;        /* fill only                                */
  --good:      #35603F;
  --warn:      #9A3520;
  --shadow:    0 18px 50px rgba(60,47,52,.20);
  --scrim:     rgba(51,38,44,.44);
  --texture-ink:   #6B4E59;
  --texture-alpha: .10;
}

.wc-game[data-theme="dark"],
.wc-game.t-dark {
  --bg:        #3C2F34;
  --bg-raise:  #4A3A41;
  --bg-sink:   #2E2429;
  --bg-edge:   #251D21;
  --fg:        #F2E6EB;
  --fg-2:      #D2BDC6;
  --fg-3:      #BEA4B1;
  --fg-on-accent: #2A1C22;
  --line:      #55444B;
  --line-2:    #6B565E;
  --accent:    #E8A6BE;
  --accent-soft: #B4728B;
  --good:      #8FC6A3;
  --warn:      #E8977E;
  --shadow:    0 18px 50px rgba(0,0,0,.46);
  --scrim:     rgba(20,14,17,.60);
  --texture-ink:   #150F12;
  --texture-alpha: .10;
}

@media (prefers-color-scheme: dark) {
  .wc-game:not([data-theme="light"]) {
    --bg:        #3C2F34;
    --bg-raise:  #4A3A41;
    --bg-sink:   #2E2429;
    --bg-edge:   #251D21;
    --fg:        #F2E6EB;
    --fg-2:      #D2BDC6;
    --fg-3:      #BEA4B1;
    --fg-on-accent: #2A1C22;
    --line:      #55444B;
    --line-2:    #6B565E;
    --accent:    #E8A6BE;
    --accent-soft: #B4728B;
    --good:      #8FC6A3;
    --warn:      #E8977E;
    --shadow:    0 18px 50px rgba(0,0,0,.46);
    --scrim:     rgba(20,14,17,.60);
    --texture-ink:   #150F12;
    --texture-alpha: .10;
  }
}

/* ===========================================================================
   TEMPLATE — the palette games/_template/ ships with.

   It is here, in the real token file, on purpose. A new game's palette belongs
   in this file so `check-contrast.mjs` covers it from its first commit, and
   having one live example is what makes the shape obvious. Copy this block,
   rename the class, change the twelve values, run the checker.

   Sage, chosen only to be clearly none of the other three.
   =========================================================================== */

.tp-game {
  --bg:        #DCE3D9;
  --bg-raise:  #EAEFE7;
  --bg-sink:   #C7D0C3;
  --bg-edge:   #BFC9BB;
  --fg:        #24352C;
  --fg-2:      #3D5647;
  --fg-3:      #546754;
  --fg-on-accent: #F5FAF7;
  --line:      #C2CCBE;
  --line-2:    #A7B4A4;
  --accent:    #296D5F;
  --accent-soft: #6FA394;        /* fill only */
  --good:      #356E46;
  --warn:      #9F4833;
  --shadow:    0 18px 50px rgba(36,53,44,.20);
  --scrim:     rgba(36,53,44,.42);
  --texture-ink:   #4A5C50;
  --texture-alpha: .10;
}

.tp-game[data-theme="dark"] {
  --bg:        #2F3A33;
  --bg-raise:  #3B473F;
  --bg-sink:   #242D27;
  --bg-edge:   #1C231E;
  --fg:        #E6EFE8;
  --fg-2:      #BFD0C5;
  --fg-3:      #96BCA2;
  --fg-on-accent: #10201B;
  --line:      #47554C;
  --line-2:    #5A6A60;
  --accent:    #69C3B1;
  --accent-soft: #3F8476;
  --good:      #6EC588;
  --warn:      #FA9B78;
  --shadow:    0 18px 50px rgba(0,0,0,.46);
  --scrim:     rgba(12,18,14,.60);
  --texture-ink:   #0C120E;
  --texture-alpha: .10;
}

@media (prefers-color-scheme: dark) {
  .tp-game:not([data-theme="light"]) {
    --bg:        #2F3A33;
    --bg-raise:  #3B473F;
    --bg-sink:   #242D27;
    --bg-edge:   #1C231E;
    --fg:        #E6EFE8;
    --fg-2:      #BFD0C5;
    --fg-3:      #96BCA2;
    --fg-on-accent: #10201B;
    --line:      #47554C;
    --line-2:    #5A6A60;
    --accent:    #69C3B1;
    --accent-soft: #3F8476;
    --good:      #6EC588;
    --warn:      #FA9B78;
    --shadow:    0 18px 50px rgba(0,0,0,.46);
    --scrim:     rgba(12,18,14,.60);
    --texture-ink:   #0C120E;
    --texture-alpha: .10;
  }
}

/* ===========================================================================
   color-scheme — so the browser paints native controls, scrollbars, range
   thumbs and focus rings to match. Cheap, and its absence is what made
   Sojourner's sliders render in light chrome on a black page.
   =========================================================================== */
.ps-shell, .sj-game, .wc-game, .tp-game { color-scheme: light }
.ps-shell[data-theme="dark"], .sj-game[data-theme="dark"],
.wc-game[data-theme="dark"], .tp-game[data-theme="dark"] { color-scheme: dark }
@media (prefers-color-scheme: dark) {
  .ps-shell:not([data-theme="light"]),
  .sj-game:not([data-theme="light"]),
  .wc-game:not([data-theme="light"]),
  .tp-game:not([data-theme="light"]) { color-scheme: dark }
}
