/* ============================================================================
   Rekaro design tokens
   ----------------------------------------------------------------------------
   This is the adjustment layer. Everything visual in the launch page resolves
   to a token declared here, so a designer can retheme the page without opening
   a component or touching layout code.

   Three tiers, and they only ever flow downward:

     1. PRIMITIVE   raw values with no opinion about where they are used
     2. SEMANTIC    what a value means in the product (surface, rule, accent)
     3. COMPONENT   the handful of places a component needs its own knob

   Rules of the road:
     - Components read tier 2 and 3. Never tier 1.
     - Dark mode overrides tier 2 only. If a component hardcodes a primitive,
       dark mode breaks, so it must not.
     - Colour is authored in OKLCH. Lightness is perceptual there, which means
       a palette stays legible when a hue is swapped. Hex would not.

   Colour direction: paper and ink. Rekaro publishes public records, so the
   surface reads as a printed register rather than a software dashboard. The
   accent is pulled down from the teal in the wordmark and desaturated until it
   behaves as an institutional colour instead of a technology one. Deliberately
   no violet, no indigo, no gradient field: those read as generated.
   ============================================================================ */

:root {
  /* --- 1. PRIMITIVE ------------------------------------------------------ */

  /* Warm greys. The slight positive chroma at hue 85 keeps white off-white,
     which is what stops a large light surface from glaring. */
  --c-paper-50:   oklch(98.4% 0.004 85);
  --c-paper-100:  oklch(96.6% 0.006 85);
  --c-paper-200:  oklch(93.8% 0.007 85);

  /* Blue-blacks. Hue 250 at low chroma: reads black, prints cold, never muddy. */
  --c-ink-900:    oklch(21.5% 0.019 250);
  --c-ink-800:    oklch(26.5% 0.019 250);
  --c-ink-700:    oklch(33.0% 0.017 250);
  --c-ink-500:    oklch(52.0% 0.014 250);
  /* 54%, not the 64% this started at. Measured against both paper surfaces it
     was landing at 3.0:1, which fails AA for body text, and it carries the
     colophon and the register's status line. */
  --c-ink-400:    oklch(54.0% 0.013 250);
  /* Rules are not text. WCAG asks 3:1 of a UI boundary rather than 4.5:1, so
     this keeps the lighter value that --c-ink-400 used to carry. Kept separate
     precisely so a future contrast fix on body text does not drag every hairline
     on the page darker with it. */
  --c-ink-300:    oklch(55.0% 0.012 250);
  --c-ink-200:    oklch(86.5% 0.008 250);

  /* Pine. The wordmark teal, taken down in lightness and chroma until it can
     carry body-size text on paper at AA. */
  --c-pine-700:   oklch(41.0% 0.078 195);
  --c-pine-600:   oklch(48.0% 0.088 195);
  --c-pine-300:   oklch(78.0% 0.070 190);
  --c-pine-200:   oklch(88.0% 0.045 190);

  /* Ochre. Used only as a mark: rules, indices, the underline on a live field.
     Never as a fill behind text. */
  /* Pulled down from 58%, where the row indices measured 4.21:1 on paper and
     missed AA by a fraction. */
  --c-ochre-600:  oklch(53.0% 0.108 68);
  --c-ochre-500:  oklch(66.0% 0.120 68);
  --c-ochre-300:  oklch(80.0% 0.090 70);

  /* Feedback. Muted on purpose; a launch page should not shout. */
  --c-error-600:  oklch(52.0% 0.150 27);
  --c-error-300:  oklch(78.0% 0.090 27);

  /* Type stacks. The local() entries let a machine that already has the face
     skip the download. System fallbacks are listed for the swap window. */
  --f-display: 'Literata', Georgia, 'Times New Roman', serif;
  --f-text: 'Golos Text', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;

  /* Spacing. A 4px base on a roughly 1.5 ratio. Named by size, not by use,
     so a rename is never needed when a component changes. */
  --s-1: 0.25rem;
  --s-2: 0.5rem;
  --s-3: 0.75rem;
  --s-4: 1rem;
  --s-5: 1.5rem;
  --s-6: 2rem;
  --s-7: 3rem;
  --s-8: 4rem;
  --s-9: 6rem;
  --s-10: 8rem;

  /* Radii. Small on purpose. A 16px radius on every box is the single most
     reliable tell of a generated interface; a register does not have one. */
  --r-sm: 2px;
  --r-md: 3px;
  --r-pill: 999px;

  /* Motion. Short, and on an ease that decelerates, so it reads as physical
     rather than as a default transition. */
  --t-fast: 120ms;
  --t-base: 220ms;
  --t-slow: 420ms;
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);

  --measure: 34ch;      /* comfortable line length for the deck */
  --page-max: 82rem;
  --rule-w: 1px;

  /* --- 2. SEMANTIC (light) ----------------------------------------------- */

  --surface:          var(--c-paper-50);
  --surface-sunk:     var(--c-paper-100);
  --surface-raised:   oklch(100% 0 0);

  --ink:              var(--c-ink-900);
  --ink-secondary:    var(--c-ink-700);
  --ink-muted:        var(--c-ink-500);
  --ink-faint:        var(--c-ink-400);
  --ink-inverse:      var(--c-paper-50);

  --rule:             var(--c-ink-200);
  --rule-strong:      var(--c-ink-300);

  --accent:           var(--c-pine-700);
  --accent-hover:     var(--c-pine-600);
  --accent-soft:      var(--c-pine-200);
  --accent-ink:       oklch(100% 0 0);

  --mark:             var(--c-ochre-600);
  --mark-soft:        var(--c-ochre-300);

  --error:            var(--c-error-600);

  --focus:            var(--c-pine-600);
  --focus-w: 2px;
  --focus-offset: 3px;

  /* Weight of the two families at the sizes we use them. Literata needs less
     weight than Golos to hold the same optical colour. */
  --w-display: 420;
  --w-body: 400;
  --w-medium: 500;
  --w-strong: 620;

  color-scheme: light;
}

/* --- 2b. SEMANTIC (dark) --------------------------------------------------
   Not an inversion. Ink ground needs lower contrast text than paper ground
   does, or the type vibrates; and the accent has to travel up in lightness to
   stay visible, which costs it chroma. Both are handled here so no component
   has to know a theme exists. */

:root[data-theme='dark'] {
  --surface:          oklch(17.0% 0.014 250);
  --surface-sunk:     oklch(13.5% 0.014 250);
  --surface-raised:   oklch(24.5% 0.015 250);

  --ink:              oklch(94.5% 0.005 85);
  --ink-secondary:    oklch(83.0% 0.008 250);
  --ink-muted:        oklch(68.0% 0.011 250);
  --ink-faint:        oklch(62.0% 0.012 250);
  --ink-inverse:      var(--c-ink-900);

  --rule:             oklch(36.0% 0.014 250);
  --rule-strong:      oklch(50.0% 0.014 250);

  --accent:           var(--c-pine-300);
  --accent-hover:     oklch(85.0% 0.062 190);
  --accent-soft:      oklch(32.0% 0.048 195);
  --accent-ink:       var(--c-ink-900);

  --mark:             var(--c-ochre-300);
  --mark-soft:        oklch(38.0% 0.062 70);

  --error:            var(--c-error-300);
  --focus:            var(--c-pine-300);

  color-scheme: dark;
}

/* Visitors who never touch the toggle get their OS preference. The attribute
   above always wins, because an explicit choice outranks an inferred one. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme='light']) {
    --surface:          oklch(17.0% 0.014 250);
    --surface-sunk:     oklch(13.5% 0.014 250);
    --surface-raised:   oklch(24.5% 0.015 250);

    --ink:              oklch(94.5% 0.005 85);
    --ink-secondary:    oklch(83.0% 0.008 250);
    --ink-muted:        oklch(68.0% 0.011 250);
    --ink-faint:        oklch(62.0% 0.012 250);
    --ink-inverse:      var(--c-ink-900);

    --rule:             oklch(36.0% 0.014 250);
    --rule-strong:      oklch(50.0% 0.014 250);

    --accent:           var(--c-pine-300);
    --accent-hover:     oklch(85.0% 0.062 190);
    --accent-soft:      oklch(32.0% 0.048 195);
    --accent-ink:       var(--c-ink-900);

    --mark:             var(--c-ochre-300);
    --mark-soft:        oklch(38.0% 0.062 70);

    --error:            var(--c-error-300);
    --focus:            var(--c-pine-300);

    color-scheme: dark;
  }
}

/* Fallback for engines without OKLCH. Everything above still parses and is
   simply ignored, so these hex values are what those browsers land on.

   The doubled :root is load-bearing, not a typo. The dark branch above selects
   :root:not([data-theme='light']), specificity (0,2,0); a plain :root here is
   (0,1,0) and loses to it. On the exact machine this block exists for, an
   engine with no OKLCH support and a dark OS preference, the branch above would
   win and re-declare every colour as an oklch() string the engine cannot parse,
   so the page computed to no background and no text colour at all. Doubling the
   selector matches the specificity, and source order then decides in favour of
   the values that engine can actually read.

   There is deliberately no prefers-color-scheme variant of the dark hex values
   below. theme-init.js now always writes an explicit data-theme, so the only
   visitor who would need one has JavaScript disabled AND an engine older than
   Chrome 111, Safari 15.4 and Firefox 113. A third copy of the ramp to serve
   that intersection would drift out of step with the other two long before it
   was ever read. */
@supports not (color: oklch(50% 0.1 200)) {
  :root:root {
    --surface: #faf9f6;
    --surface-sunk: #f2f0eb;
    --surface-raised: #ffffff;
    --ink: #14192b;
    --ink-secondary: #3d4356;
    --ink-muted: #6b7285;
    --ink-faint: #71778a;
    --rule: #d8dae2;
    --rule-strong: #85899a;
    --accent: #185f66;
    --accent-hover: #1e7580;
    --accent-soft: #cfe6e6;
    --accent-ink: #ffffff;
    --mark: #96601c;
    --mark-soft: #d9b183;
    --error: #a52d1e;
    --focus: #1e7580;
  }
  :root:root[data-theme='dark'] {
    --surface: #12151f;
    --surface-sunk: #0d1017;
    --surface-raised: #232838;
    --ink: #eeece7;
    --ink-secondary: #c3c7d1;
    --ink-muted: #969bab;
    --ink-faint: #868c9d;
    --rule: #3d4356;
    --rule-strong: #6c7285;
    --accent: #86c9c8;
    --accent-hover: #a4dad8;
    --accent-soft: #23474a;
    --accent-ink: #14192b;
    --mark: #d9b183;
    --mark-soft: #5c4526;
    --error: #e3a99f;
  }
}
