/* =========================================================================
 * Maegen Online + Azakhan Studios - the design tokens.
 *
 * ONE source of truth. Nothing below this file hard-codes a colour, a size,
 * a duration or an easing curve. If you find yourself typing a hex or a ms
 * anywhere else, the token is missing - add it here.
 *
 * Authority: DESIGN-SPEC.md sections 3, 4, 5. Every hex is either a MEASURED
 * percentile of brand/key-art-original.jpeg or is marked DERIVED with the
 * reason. Re-derive the palette with:  python3 brand/judge_tokens_lock.py
 *
 * The two sites share this file. azakhanstudios.com inverts the ground with
 * the [data-theme="studio"] block at the bottom - the same two tokens in
 * opposite roles, which is most of the sibling relationship for free.
 * ========================================================================= */

:root{

  /* ------------------------------------------------------------- colour --
   * ground - measured, whole-image luminance percentiles */
  --night:        #080b13;  /* mean of the darkest 2% of the key art          */
  --night-2:      #0e121d;  /* whole-image p5 - raised surfaces, plate interior */
  --fog-deep:     #26364c;  /* whole-image p25 - 3D ONLY, 1.61:1 as text       */
  --fog:          #394c69;  /* whole-image p50 = the art's average colour      */

  /* steel - measured off the MAEGEN strip */
  --steel-deep:   #41567b;  /* strip p50, the letter face. RULES ONLY - 2.66:1 */
  --steel-dim:    #7392b6;  /* strip p75 - labels, captions, nav       6.10:1  */
  --steel:        #b7d4ea;  /* strip p90, the bevel face - headlines  12.76:1  */
  --steel-bright: #e8fbff;  /* strip p97, the specular band           18.43:1  */

  /* rune light - measured off the crystal */
  --rune:         #6bdcfa;  /* crystal p75 - THE accent              12.40:1  */
  --rune-core:    #4cb1ed;  /* crystal p50 - the emitting body, the pool      */
  --rune-ink:     #046d9f;  /* DERIVED: H202 walked down in L for light grounds */
  --rune-ink-sm:  #03567d;  /* DERIVED: 6.47:1 on parchment, for text < 17px  */

  /* violet - measured. Wave 2 re-derived both of these from the region each
   * one is actually USED in, because the shipped values were measured on the
   * whole frame while their comments named the leaves and the galaxy.
   * Re-derive: python3 brand/_wave2/tokens_check.py */
  --violet:       #635594;  /* leaf columns pooled, violet-hue p50 at S>0.30,
                             * H253. 3.02:1 - NEVER text. (Was #6c5a9f, about
                             * 9 units brighter than the leaves it names.)   */
  --violet-lit:   #c3b1f1;  /* the galaxy region's own violet p50, H257. The
                             * previous #9a87ca was the WHOLE-IMAGE p85, which
                             * is a good deal darker than the galaxy it is
                             * named for; the galaxy really is this pale.    */

  /* warm - CANNOT be measured: warm is 0.0014% of the art. A CHOICE.
   * DESIGN-SPEC 3.5. If Azamet finds it too yellow against the steel, the
   * whole swap is the ONE line below marked (A); nothing else moves. */
  --parchment:    #ece7dc;  /* DERIVED H41 S30 L89                   15.95:1  */

  /* ---- semantic roles. Components reference THESE, never the raws. ---- */
  --bg:           var(--night);
  --bg-raised:    var(--night-2);
  --ink:          var(--parchment);   /* (A) -> var(--steel-bright) to go cool */
  --ink-strong:   var(--steel-bright);
  --ink-quiet:    var(--steel-dim);
  --ink-heading:  var(--steel);
  --accent:       var(--rune);
  --accent-sm:    var(--rune);        /* the accent BELOW 17px. On night these
                                       * are the same token, because --rune
                                       * measures 12.40:1 at any size. On the
                                       * studio's light ground they are NOT:
                                       * --rune-ink is 4.61:1 and the spec
                                       * restricts it to >=17px, so the small
                                       * role has to resolve to --rune-ink-sm
                                       * (6.47:1). Components that set type
                                       * below 17px - .caption .fig, a <details>
                                       * summary - must use THIS, or they read
                                       * correctly on one site and marginally
                                       * on the other. DESIGN-SPEC 13.3.      */
  --focus-ring:   var(--rune);
  --focus-gap:    var(--night);       /* the offset must expose the ground, or
                                       * cyan on steel measures 1.03:1        */

  /* -------------------------------------------------------------- rules --
   * Two weights, and the reason is a measurement: below 44% alpha a steel
   * line cannot reach 3.0:1, so it can never carry meaning. */
  --rule-hair:  rgba(183,212,234,.12);  /* -> #1e232c, 1.24:1. DECORATIVE ONLY.
                                         * Legal because WCAG 1.4.11 exempts
                                         * pure decoration. This is the line
                                         * that makes a page look typeset. */
  --rule-frame: rgba(183,212,234,.48);  /* -> #5c6b7a, 3.60:1. MEANINGFUL.
                                         * 44% is the threshold; 48% is margin
                                         * against sub-pixel rendering. */
  /* Guardrail: never more than FOUR horizontal rules in one viewport, all
   * baseline-aligned across the three grid tracks. Four is a magazine, eight
   * is a spreadsheet, and it degrades so gradually nobody notices in time. */

  /* ---------------------------------------------------------------- type --
   * Apple's live scale, measured at 390px and 1440px, adopted verbatim
   * except for the three deviations named in DESIGN-SPEC 4.2. */
  --step-display-xl: clamp(3rem,      1.886rem + 4.571vw, 6rem);    /* 48->96 */
  --step-display-l:  clamp(2rem,      1.257rem + 3.048vw, 4rem);    /* 32->64 */
  --step-display-m:  clamp(1.75rem,   1.100rem + 2.667vw, 3.5rem);  /* 28->56 */
  --step-stat:       clamp(3rem,      2.257rem + 3.048vw, 5rem);    /* 48->80 */
  --step-sub:        clamp(1.5rem,    1.314rem + 0.762vw, 2rem);    /* 24->32 */

  /* FIXED. These never scale, and body copy not scaling is the single most
   * valuable thing in the whole scale: fluid-typing the body is the most
   * common way to make desktop reading worse. */
  --step-body:    1.0625rem;  /* 17px  Source Serif 4 400          */
  --step-caption: .875rem;    /* 14px  Inter 400, figure captions  */
  --step-label:   .8125rem;   /* 13px  Inter 500, the eyebrow      */
  --step-micro:   .6875rem;   /* 11px  Inter 500, the running head */

  /* Letter-spacing crosses zero: positive below ~28px, negative above. One
   * tracking value across a whole scale is the loudest amateur tell there is. */
  --lh-display-xl: 1.04;  --ls-display-xl: -.015em;
  --lh-display-l:  1.06;  --ls-display-l:  -.009em;
  --lh-display-m:  1.07;  --ls-display-m:  -.005em;
  --lh-stat:       1.00;  --ls-stat:       -.015em;
  --lh-sub:        1.13;  --ls-sub:         .004em;
  --lh-body:       1.55;  --ls-body:       -.011em;  /* dark-ground correction:
                            light type on dark blooms optically, so it wants
                            MORE leading and LESS negative tracking than the
                            same face on white. The studio site reverts to the
                            measured 1.47 / -.022em. */
  --lh-caption:    1.45;
  --ls-label:       .16em;
  --ls-micro:       .18em;

  --measure: 62ch;            /* prose cap. Two lines of support copy, by rule. */

  /* -------------------------------------------------------------- motion --
   * Counted across 1.55 MB of Apple's live CSS: cubic-bezier(.4,0,.6,1)
   * appears 316 times, 240ms 98 times, 320ms 78 times. */
  --ease-standard: cubic-bezier(.4, 0, .6, 1);
  --ease-out:      cubic-bezier(0, 0, .2, 1);
  --dur-fast:  80ms;
  --dur-base:  240ms;
  --dur-slow:  320ms;
  --stagger:   50ms;
  /* NOTHING BOUNCES. No overshoot curve exists on either site. The material
   * is polished steel and marble; steel does not wobble and marble does not
   * spring. (Apple's own overshoot curve appears 5 times in 316 - a rounding
   * error, not a pattern.) */

  /* -------------------------------------------------------------- space --
   * 96px section unit, 192px chapter break. Measured: Apple's section padding
   * is a flat 96px top and bottom and does NOT shrink on mobile. */
  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;  --space-4: 16px;
  --space-5: 24px;  --space-6: 32px;  --space-7: 48px;  --space-8: 64px;
  --section:  96px;
  --chapter: 192px;

  /* --------------------------------------------------------------- grid --
   * Content max-width 1280, 12 columns, 24px gutters, column = 84.67px.
   * At 1440 the content margins land at x=80 and x=1360. */
  --content: 1280px;
  --gutter:  24px;
  --col:     84.67px;
  --page-pad: clamp(20px, 5.5vw, 80px);

  /* ------------------------------------------------------------- radii --
   * Marble and steel are cut, not moulded. Radii stay near zero except on
   * the two things a browser rounds anyway. */
  --radius-0: 0px;
  --radius-1: 2px;
  --radius-2: 4px;

  /* --------------------------------------------------------------- misc */
  --plate-ratio: .796;        /* 519 x 652, the hero plate                */
  --floor-line: 78%;          /* where the floor sits inside a plate       */
  --header-h: 56px;
  --rail-x: 64px;
}

/* -------------------------------------------------------------------------
 * REDUCED MOTION. Durations collapse to 1ms rather than 0 so that
 * transitionend still fires and no state machine hangs waiting for it.
 * ---------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce){
  :root{
    --dur-fast: 1ms; --dur-base: 1ms; --dur-slow: 1ms; --stagger: 0ms;
  }
}

/* The header's MOTION switch writes this attribute. It has to do everything
 * the media query does, because a reader susceptible to scroll-coupled motion
 * very often has not enabled the OS setting - and a visible switch is the
 * difference between managing that risk and quietly handing it to them. */
[data-motion="off"]{
  --dur-fast: 1ms; --dur-base: 1ms; --dur-slow: 1ms; --stagger: 0ms;
}

/* =========================================================================
 * azakhanstudios.com - the six inversions (DESIGN-SPEC 13.2).
 * The ground inverts: the same two tokens, opposite roles, 15.95:1 either
 * way. That single move does about 80% of the differentiation for free.
 * ========================================================================= */
[data-theme="studio"]{
  --bg:          var(--parchment);
  --bg-raised:   #f4f1ea;
  --ink:         var(--night);
  --ink-strong:  var(--night);
  --ink-quiet:   var(--fog);        /* 7.06:1 here; it FAILS on the game site */
  --ink-heading: var(--night);

  /* The accent's JOB inverts: emission on the game, annotation here. And it
   * has to change value, because --rune on parchment measures 1.29:1 -
   * cyan is simply unusable as light on a light ground. */
  --accent:      var(--rune-ink);   /* 4.61:1, >= 17px only */
  --accent-sm:   var(--rune-ink-sm);/* 6.47:1, the same annotation below 17px */
  --focus-ring:  var(--night);      /* 15.95:1. Cyan cannot carry the ring here */
  --focus-gap:   var(--parchment);

  /* Night over parchment measures differently: even 40% does not reach 3.0:1,
   * so the studio's meaningful frame is 1px at FULL --fog-deep (9.93:1)
   * rather than a tinted night. Stated because a builder will otherwise copy
   * the game site's alpha and get an invisible frame. */
  --rule-hair:  rgba(8,11,19,.12);
  --rule-frame: var(--fog-deep);

  /* Dark-on-light does not bloom, so revert to the measured values. */
  --lh-body: 1.47;
  --ls-body: -.022em;
}
