/* ===========================================================================
   Design tokens
   ---------------------------------------------------------------------------
   Direction (the author, 2026-10-12): a place in a fantasy world, in two
   registers. The wiki is a page of a chronicle — warm parchment on a dark desk,
   brass flourishes, scrollwork. The game's screens are panels of the world —
   stone frames, ribbons, crafted buttons. Both follow the reader's theme
   (`data-register`, set by MainLayout, picks the ornament). The art is in
   wwwroot/art, built by tools/art/prepare.py; docs/GRAPHICS.md records each piece.

   THE ACCENT IS PURPLE BECAUSE THE CORPUS SAYS SO. This is not a preference.
   Purple is already the colour of congruence across seven pages, written years
   before there was a stylesheet:

     - Wayat'ujan's wall carries "purple-leafed vines that the Vas'n adepts have
       shaped to drink ambient congruence"      (vastek, national-technologies)
     - The healing fruit grows "at the largest congruence hot spot on the
       continent" and is "dark purple", with "glowing purple veins" and "a faint
       purple hue to the shadow the plant casts"          (medicinal-plants)
     - Zingare's bedrock "has a purple hue. Exactly why that is, is still a
       matter of speculation"                                     (zingare)
     - The Blighted Lands, where congruence cannot be reached at all, are tinted
       with it too                                           (blighted-lands)

   So the accent is congruence made visible. The paper was cold, with a faint
   violet cast, until 2026-10-12; the author then chose warm parchment for the
   overhaul and kept the amethyst. The ink and rules are warmed with it.

   Verdigris was the previous accent and is kept, demoted, with one job: the
   production layer. Purple is the world; green is the writing team. See
   --secondary.

   Type is Literata for the body — designed specifically for long-form reading on
   screens, which is exactly the brief when you are asking someone to read
   120,000 words on a phone. Fraunces carries the display voice. Archivo handles
   labels and data.

   Everything here is meant to be overridden. If you want a different look, the
   whole visual identity lives in this one file. Contrast was computed rather
   than eyeballed: every pairing below that carries text meets WCAG AA, in both
   themes. If you change a value, recompute — do not assume.

   Watch out — --ink-faint is a TEXT colour, not a decoration. It carries .label,
   .facts__label and .account__heading, all of which are 12px, which is nowhere
   near WCAG's large-text threshold and therefore needs the full 4.5:1. It sat at
   3.30:1 for the life of the green palette and nobody caught it, because a
   contrast bug on an uppercase label reads as "quiet" rather than as broken.
   ======================================================================== */

:root {
  /* --- Colour ------------------------------------------------------------ */

  --paper:          #F2E8D2;  /* warm parchment (the author, 2026-10-12) */
  --paper-raised:   #F8F1E1;
  --paper-sunken:   #E8DCBF;

  --ink:            #2B2119;  /* near-black, warmed with the paper: 12.93:1 */
  --ink-soft:       #574638;  /* 7.38:1 */
  --ink-faint:      #6B5847;  /* 5.54:1 on paper, 4.96:1 on sunken — labels are 12px and need AA */

  --amethyst:       #5B3E9E;  /* the accent — congruence made visible: 6.56:1 */
  --amethyst-deep:  #43296F;  /* text weight: 9.66:1 on paper */
  --amethyst-wash:  #E5DAE6;

  --verdigris:      #1D5749;  /* demoted to secondary: the production layer — 6.87:1 */
  --verdigris-wash: #D9E3D2;

  --madder:         #8E2F3D;  /* warnings, destructive actions, urgency — 6.57:1 */
  --madder-wash:    #F1DAD2;

  --gold-leaf:      #B08A3E;  /* rare and precious. Use almost never. */

  --rule:           #D6C49F;
  --rule-strong:    #B19B73;

  /* Semantic aliases — reference these in components, not the raw names */
  --bg:             var(--paper);
  --bg-raised:      var(--paper-raised);
  --fg:             var(--ink);
  --fg-muted:       var(--ink-soft);
  --fg-faint:       var(--ink-faint);
  --accent:         var(--amethyst);
  --accent-strong:  var(--amethyst-deep);
  --accent-wash:    var(--amethyst-wash);
  --secondary:      var(--verdigris);       /* writer notes, gated pages, staff affordances */
  --secondary-wash: var(--verdigris-wash);
  --danger:         var(--madder);
  --danger-wash:    var(--madder-wash);
  --border:         var(--rule);

  /* --- Type -------------------------------------------------------------- */

  --font-display: 'Fraunces', Georgia, 'Times New Roman', serif;
  --font-body:    'Literata', Georgia, 'Times New Roman', serif;
  --font-ui:      'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* The game's ribbon titles only: a calligraphic face that still reads at a phone's size (the author, 2026-10-12,
     chosen from nine on the ribbon). It falls back to the display face, never to a bare serif. */
  --font-ribbon:  'Almendra', 'Fraunces', Georgia, serif;
  --font-mono:    ui-monospace, 'SF Mono', 'Cascadia Mono', monospace;

  /* Fluid scale. Minimums are sized for a 390px phone, maximums for desktop.
     Body sits at 17px on mobile — larger than the usual 16px because this site
     asks people to read for a long time. */
  --text-xs:   0.75rem;
  --text-sm:   0.875rem;
  --text-base: clamp(1.0625rem, 1rem + 0.25vw, 1.125rem);
  --text-lg:   clamp(1.1875rem, 1.1rem + 0.4vw, 1.375rem);
  --text-xl:   clamp(1.375rem, 1.25rem + 0.7vw, 1.75rem);
  --text-2xl:  clamp(1.625rem, 1.4rem + 1.1vw, 2.25rem);
  --text-3xl:  clamp(2rem, 1.6rem + 1.8vw, 3rem);

  --leading-tight: 1.15;
  --leading-snug:  1.35;
  --leading-body:  1.7;   /* generous — also stops tooltip hit areas colliding */
  --leading-loose: 1.85;

  --tracking-tight: -0.015em;
  --tracking-wide:   0.06em;

  /* --- Space ------------------------------------------------------------- */

  --space-3xs: 0.25rem;
  --space-2xs: 0.5rem;
  --space-xs:  0.75rem;
  --space-sm:  1rem;
  --space-md:  1.5rem;
  --space-lg:  2.25rem;
  --space-xl:  3.5rem;
  --space-2xl: 5rem;

  /* --- Layout ------------------------------------------------------------ */

  --measure:      66ch;    /* reading column — do not exceed for body text */
  --measure-wide: 88ch;
  --page-max:     72rem;
  --gutter:       clamp(1rem, 4vw, 2.5rem);

  /* --- Interaction ------------------------------------------------------- */

  --tap-min: 44px;   /* minimum comfortable touch target */
  --radius-sm: 3px;
  --radius:    6px;
  --radius-lg: 12px;
  --radius-sheet: 16px;

  --shadow-sm: 0 1px 2px rgb(26 23 32 / 0.06);
  --shadow:    0 4px 14px rgb(26 23 32 / 0.10);
  --shadow-lg: 0 -8px 32px rgb(26 23 32 / 0.18);

  --ease: cubic-bezier(0.2, 0, 0, 1);
  --dur-fast: 120ms;
  --dur:      200ms;
  --dur-slow: 320ms;

  --z-header: 100;
  --z-drawer: 200;
  --z-tooltip: 300;
  --z-sheet:  400;

  /* --- Ornament ----------------------------------------------------------
     Congruence reads as a glow in the corpus — "glowing purple veins", "a faint
     purple hue to the shadow the plant casts". These are the two ways that is
     expressed as surface, and both are generated rather than downloaded: no
     bytes, no HTTP request, no provenance to record, and they re-tint with the
     theme because they are built from the tokens above.

     --veil  a soft off-centre bloom, for a surface that should feel lit
     --grain a fine tooth, so a large flat panel reads as paper rather than as
             a filled rectangle. 0.035 alpha is the point where it registers
             without becoming visible texture.                              */

  --veil: radial-gradient(
            120% 90% at 15% 0%,
            color-mix(in oklab, var(--accent) 14%, transparent) 0%,
            transparent 62%);

  /* The lozenge, as a mask so it can take any colour. Since the overhaul (280) only the character sheet's list
     bullet and the commission brief still use it; the sheet's own PR replaces the bullet. */
  --lozenge-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2 20 12l-8 10L4 12Z' fill='%23000'/%3E%3C/svg%3E");

  /* The parchment's tooth: a warm fractal noise drawn here, so a sheet of paper is not a flat fill, and the burn
     at its edges. Both follow the theme (the overhaul, 2026-10-12). */
  --parchment-grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.6' numOctaves='4' seed='7'/%3E%3CfeColorMatrix values='0 0 0 0 0.45 0 0 0 0 0.32 0 0 0 0 0.18 0 0 0 0.09 0'/%3E%3C/filter%3E%3Crect width='220' height='220' filter='url(%23n)'/%3E%3C/svg%3E");
  --parchment-burn: rgb(184 151 95 / 0.33);

  --grain: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)' opacity='0.035'/%3E%3C/svg%3E");
}

/* --- Dark ---------------------------------------------------------------- */

@media (prefers-color-scheme: dark) {
  :root {
    /* The page by candlelight: warm near-black paper, parchment-coloured ink. */
    --paper:        #1C1712;
    --paper-raised: #251F18;
    --paper-sunken: #15110D;

    --ink:          #ECE2CE;   /* 13.84:1 */
    --ink-soft:     #C7B89E;   /* 9.13:1 */
    --ink-faint:    #A8977C;   /* 6.25:1, 5.73:1 on raised */

    --amethyst:      #B39BE6;   /* 7.41:1 on paper */
    --amethyst-deep: #CDBBF2;   /* 10.15:1 — links carry this one */
    --amethyst-wash: #2C2340;

    --verdigris:      #5FB8A2;
    --verdigris-wash: #1B3630;

    --madder:      #E07F8B;
    --madder-wash: #3A1D22;

    --gold-leaf: #D4AE64;

    --rule:        #3A3027;
    --rule-strong: #5A4A39;

    --shadow-sm: 0 1px 2px rgb(0 0 0 / 0.4);
    --shadow:    0 4px 14px rgb(0 0 0 / 0.5);
    --shadow-lg: 0 -8px 32px rgb(0 0 0 / 0.6);

    --parchment-burn: rgb(0 0 0 / 0.45);

    /* The bloom carries further on a dark ground before it reads as a smudge. */
    --veil: radial-gradient(
              120% 90% at 15% 0%,
              color-mix(in oklab, var(--accent) 20%, transparent) 0%,
              transparent 68%);
  }
}
