/* tokens.css — every value the interface is allowed to use.
 *
 * Custom properties are the only theming mechanism (0014). Components name
 * semantic tokens (--surface, --text, --accent) and never raw palette entries,
 * so a retheme is this file and nothing else.
 *
 * The palette is the logo's, not an invention. The mark is warm apricot, so the
 * accent is that hue taken down to a value that is legible on paper: terracotta
 * #8f5924, measured at 5.43:1. The logo's own two colours are not discarded —
 * apricot becomes the wash and cream the faint tint, which is why the brand and
 * the interface cannot drift apart.
 *
 * Five rules in here do not bend:
 *
 *   1. No red anywhere in the child's view. Red is marking. A child who has had
 *      work handed back covered in it reads red as a verdict no matter what the
 *      words say. There is no --error token for child-facing use.
 *   2. No separate alarm hue either. --attention resolves to the accent and its
 *      wash to apricot, deliberately: a pre-check nudge is instant, unarguable
 *      and not a judgement, so nothing about it should look urgent. The token
 *      survives because the *concept* is real; the second colour does not.
 *   3. --done (moss) appears only on a satisfied contract item.
 *   4. Focus rings are an ink outline with an offset, never the accent. An
 *      accent ring on an accent button is invisible, and the child who most
 *      needs the focus ring is the one navigating by keyboard.
 *   5. Body text at 7:1 contrast, everything else at 4.5:1, in both themes.
 *      Every pair below has been measured; see docs/decisions/0014.
 */

/* --- Faces ---------------------------------------------------------------- */

@font-face {
  font-family: "Atkinson Hyperlegible";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("/static/fonts/atkinson-hyperlegible-400.woff2") format("woff2");
}

@font-face {
  font-family: "Atkinson Hyperlegible";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("/static/fonts/atkinson-hyperlegible-700.woff2") format("woff2");
}

@font-face {
  font-family: "Literata";
  font-style: normal;
  font-weight: 200 900;
  font-display: swap;
  src: url("/static/fonts/literata-variable.woff2") format("woff2");
}

@font-face {
  font-family: "Literata";
  font-style: italic;
  font-weight: 200 900;
  font-display: swap;
  src: url("/static/fonts/literata-variable-italic.woff2") format("woff2");
}

:root {
  /* --- Palette, light ---------------------------------------------------- */

  --paper: #fbf7f0;
  --paper-raised: #fffdf8;
  --paper-sunk: #f3ece1;
  --rule: #e3d9c9;

  --ink: #231f1c;
  --ink-soft: #4a423c;
  --ink-faint: #7a6f66;

  /* The logo's hue, taken to a legible value. 5.43:1 on paper, 4.94:1 on sunk. */
  --terracotta: #8f5924;
  --terracotta-deep: #7c4a1e;  /* 6.89:1 */

  /* The logo's own two colours. Brand constants: these are the same value in
   * every theme, which is what makes them safe to draw the mark with. The
   * washes below vary by theme and are separate tokens for that reason. */
  --brand-apricot: #f7d8ba;    /* ink on it: 12.06:1 */
  --brand-cream: #fef8dd;      /* ink on it: 15.33:1 */

  --moss: #3f6644;             /* 6.15:1 */
  --moss-wash: #e8f0e7;

  /* Theme-varying leaves. Declared per theme, not aliased, because their value
   * flips rather than tracking a palette entry: a tinted surface sits lighter
   * than the ground on paper and darker than it on ink. */
  --accent-wash: var(--brand-apricot);
  --accent-faint: var(--brand-cream);
  --text-on-accent: #fffdf8;
  --logo: var(--terracotta);
  --logo-highlight: var(--brand-apricot);

  /* Semantic aliases are NOT declared here — see the shared rule below, and
   * the comment on it, which is load-bearing. */

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

  --font-ui: "Atkinson Hyperlegible", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-prose: "Literata", Georgia, "Times New Roman", serif;

  /* 1.2 from an 18px base. Larger than a typical adult interface on purpose. */
  --size-xs: 0.778rem;   /* 14 */
  --size-sm: 0.889rem;   /* 16 */
  --size-base: 1rem;     /* 18 */
  --size-md: 1.167rem;   /* 21 */
  --size-lg: 1.389rem;   /* 25 */
  --size-xl: 1.667rem;   /* 30 */
  --size-2xl: 2rem;      /* 36 */

  --size-prose: 1.111rem; /* 20 — the child's own writing, always */
  --leading-prose: 1.7;
  --leading-ui: 1.5;
  --measure: 62ch;

  /* --- Space, shape, shadow ---------------------------------------------- */

  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-6: 1.5rem;
  --space-8: 2rem;
  --space-12: 3rem;
  --space-16: 4rem;

  --radius-sm: 6px;
  --radius-md: 10px;
  --radius-lg: 14px;
  --radius-xl: 22px;

  /* Warm-tinted, because a neutral grey shadow on warm paper reads as dirt. */
  --shadow-low: 0 1px 2px rgba(60, 42, 28, 0.08), 0 2px 6px rgba(60, 42, 28, 0.05);
  --shadow-high: 0 2px 4px rgba(60, 42, 28, 0.1), 0 8px 24px rgba(60, 42, 28, 0.09);

  /* --- Motion ------------------------------------------------------------ */

  --fast: 120ms;
  --base: 200ms;
  --slow: 420ms;
  --ease: cubic-bezier(0.2, 0.7, 0.3, 1);

  /* Smallest interactive target. A nine-year-old on a tablet, not a mouse. */
  --tap: 44px;
}

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

@media (prefers-color-scheme: dark) {
  :root {
    --paper: #191512;
    --paper-raised: #221d19;
    --paper-sunk: #120f0d;
    --rule: #3a322c;

    --ink: #f0e7da;
    --ink-soft: #cdc2b4;
    --ink-faint: #9a8f83;

    --terracotta: #e3a76a;       /* 8.64:1 on the dark ground */
    --terracotta-deep: #f0bc86;  /* 10.58:1 */
    --moss: #8fbf93;
    --moss-wash: #1d2620;

    /* The washes invert. A tinted *surface* has to sit darker than the ground
     * here, so these are set directly instead of tracking the brand pair —
     * which stays fixed, because the mark is drawn with it. */
    --accent-wash: #2a1f14;
    --accent-faint: #201a12;

    --text-on-accent: #191512;
    --focus-ring: var(--ink);

    /* On a dark ground the mark goes back to the colour it was drawn in. */
    --logo: var(--brand-apricot);      /* 13.38:1 */
    --logo-highlight: var(--brand-cream);

    --shadow-low: 0 1px 2px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.3);
    --shadow-high: 0 2px 4px rgba(0, 0, 0, 0.45), 0 8px 24px rgba(0, 0, 0, 0.4);
  }
}

/* The styleguide forces each theme so both can be seen at once, and a child on
 * a device set to the wrong one can be given the other. Explicit choice wins
 * over the media query in both directions.
 *
 * The class forms exist so the styleguide can put both themes on one page:
 * custom properties inherit, so a container that redeclares them themes its
 * whole subtree. Same values, one place to edit them. */
:root[data-theme="light"],
.theme-light {
  color-scheme: light;
  --paper: #fbf7f0;
  --paper-raised: #fffdf8;
  --paper-sunk: #f3ece1;
  --rule: #e3d9c9;
  --ink: #231f1c;
  --ink-soft: #4a423c;
  --ink-faint: #7a6f66;
  --terracotta: #8f5924;
  --terracotta-deep: #7c4a1e;
  --moss: #3f6644;
  --moss-wash: #e8f0e7;
  --accent-wash: var(--brand-apricot);
  --accent-faint: var(--brand-cream);
  --text-on-accent: #fffdf8;
  --logo: var(--terracotta);
  --logo-highlight: var(--brand-apricot);
  --shadow-low: 0 1px 2px rgba(60, 42, 28, 0.08), 0 2px 6px rgba(60, 42, 28, 0.05);
  --shadow-high: 0 2px 4px rgba(60, 42, 28, 0.1), 0 8px 24px rgba(60, 42, 28, 0.09);
}

:root[data-theme="dark"],
.theme-dark {
  color-scheme: dark;
  --paper: #191512;
  --paper-raised: #221d19;
  --paper-sunk: #120f0d;
  --rule: #3a322c;
  --ink: #f0e7da;
  --ink-soft: #cdc2b4;
  --ink-faint: #9a8f83;
  --terracotta: #e3a76a;
  --terracotta-deep: #f0bc86;
  --moss: #8fbf93;
  --moss-wash: #1d2620;
  --accent-wash: #2a1f14;
  --accent-faint: #201a12;
  --text-on-accent: #191512;
  --logo: var(--brand-apricot);
  --logo-highlight: var(--brand-cream);
  --shadow-low: 0 1px 2px rgba(0, 0, 0, 0.4), 0 2px 6px rgba(0, 0, 0, 0.3);
  --shadow-high: 0 2px 4px rgba(0, 0, 0, 0.45), 0 8px 24px rgba(0, 0, 0, 0.4);
}

/* --- Semantic aliases ------------------------------------------------------
 *
 * This selector list is not padding, and shortening it to `:root` breaks the
 * themes in a way that is genuinely hard to see.
 *
 * A custom property whose value is `var(--x)` is resolved **where it is
 * declared**, not where it is used, and the resolved value is what inherits. So
 * `--surface: var(--paper)` declared on `:root` computes to the *light* paper
 * and inherits that literal everywhere. A descendant that overrides `--paper`
 * — which is exactly what `.theme-dark` is — cannot reach back and change it.
 *
 * The dark media query gets away with it because it re-declares `:root` itself,
 * so the alias and the override land on the same element. The forced-theme
 * classes do not, which is why the styleguide's dark frame rendered a dark
 * palette on a light background until this rule was split out.
 *
 * Every element that overrides a palette entry therefore has to declare the
 * aliases too. Adding a new theme scope means adding it here.
 */
:root,
.theme-light,
.theme-dark,
:root[data-theme="light"],
:root[data-theme="dark"] {
  --surface: var(--paper);
  --surface-raised: var(--paper-raised);
  --surface-sunk: var(--paper-sunk);
  --border: var(--rule);

  --text: var(--ink);
  --text-soft: var(--ink-soft);
  --text-faint: var(--ink-faint);

  --accent: var(--terracotta);
  --accent-strong: var(--terracotta-deep);

  /* Something needs doing or has not gone through. Never red, and — rule 2 —
   * never a hue of its own either. These resolve to the accent on purpose. */
  --attention: var(--accent);
  --attention-wash: var(--accent-wash);

  /* A satisfied contract item. Nothing else. */
  --done: var(--moss);
  --done-wash: var(--moss-wash);

  --focus-ring: var(--ink);
}

/* Nothing moves for someone who asked for nothing to move. This includes the
 * coach's blink and the page-turn: they are decoration, and decoration is the
 * first thing to go. */
@media (prefers-reduced-motion: reduce) {
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}
