/* Bloom and Grow: design tokens.
 *
 * Direction A, the New Naturalist jacket. Seed key 7f20d95a.
 *
 * Every colour below is derived from a measured Collins New Naturalist jacket
 * (Clifford and Rosemary Ellis, 1945 to 1982) or from the green buckram board
 * the jackets wrapped. The documented working rule for those jackets was three
 * colours plus black, using tones and overlays, and this palette keeps it: one
 * ink, one accent, three fields, two state colours.
 *
 * The ground is deliberately NOT cream. Warm, bookish, child-facing subjects
 * reliably render as cream paper with a serif display face, on every model,
 * every time. That palette is treated as already spent. The Ellis jackets are
 * in fact full of cool grey, chrome yellow, dusty rose and sepia, and this
 * system takes the saturated half of that world rather than its softest corner.
 *
 * Contrast is not asserted here. Every pair a surface actually uses is declared
 * in design-lint.config.json and checked by tools/design-lint. The pairs were
 * written before this file existed: the colours came up to the floor, the floor
 * did not come down to the colours.
 *
 * NO NEW COLOUR WAS ADDED at the design pass. Everything below the colour block
 * is a scale, and a scale is how this system grows: a new step, never a new
 * one-off value at a call site.
 */

:root {
  /* --- Ink and ground -------------------------------------------------- */
  /* Reading surface. A pale cool grey with a green cast, not cream. */
  --ground: #E4E6E0;
  /* The recessed surface: the pale oval interior sitting over a field. */
  --ground-sunk: #D6D9D0;
  /* Near-black, warmed. The Ellis jackets never use pure black. */
  --ink: #2E2820;
  --ink-muted: #5C5648;
  --ink-inverse: #E4E6E0;

  /* --- Accent ----------------------------------------------------------- */
  /* Green buckram: the cloth board under every New Naturalist jacket.
   * Carries all primary interactive surfaces. */
  --accent: #2F4A34;

  /* --- Fields ------------------------------------------------------------
   * Large regions only, never small marks. Sampled from real artefacts:
   *   grey  = the wood behind the ants, Monograph M2
   *   rose  = the oval carrying the title, Monograph M1
   *   sun   = the radiating chrome yellow, Monograph M3
   *   sepia = the wren's plumage, Monograph M3
   *
   * There are two field families and the distinction is binding, because a
   * mid-tone field serves neither: the wren's sepia as measured (#7B6937) is
   * 2.72:1 under --ink and 4.26:1 under --ink-inverse, so it fails both ways.
   * It is darkened here to sit properly in the dark family. */

  /* LIGHT fields: carry --ink. */
  --field-grey: #9A9E9E;
  --field-rose: #EBC0B0;
  --field-sun: #D9C11B;

  /* DARK fields: carry --ink-inverse. --accent belongs to this family too. */
  --field-sepia: #6E5D30;

  /* --- State ------------------------------------------------------------- */
  /* Distinct from each other by hue AND by role. Neither is ever the sole
   * carrier of meaning: word plus shape, always. */
  /* Two-tone by necessity, not by preference. The dark ring and the pale halo
   * contrast with each other at 4.71:1, so the indicator survives on any
   * background including the mid-tone fields, where no single colour can clear
   * 3:1 either way. Gate round 1 finding A-F1. */
  --focus-ring: #8A5A00;
  --focus-ring-halo: #E4E6E0;
  --state-error: #8A2B1E;
  --border: #6E6A5C;

  /* Build state. Not a brand colour and not a field: it marks a fact that is
   * still to be confirmed. It has its own token because "content not yet
   * resolved" is a real semantic role in a build that ships with honest gaps,
   * and gate round 1 finding DS-2 caught the placeholder borrowing --field-sun
   * instead, which broke that token's own usage rule. */
  --pending-ground: #E9DFA6;
  --pending-rule: #6E5D30;

  /* --- Type scale --------------------------------------------------------
   * Major third (1.25) from a 17px base. Body sits at 1rem and never below.
   * Display tops out well short of impeccable's 6rem ceiling: this is a
   * reading surface for a distressed reader, not a poster. */
  --text-xs: 0.8rem;
  --text-sm: 0.9rem;
  --text-base: 1rem;
  --text-lg: 1.25rem;
  --text-xl: 1.5rem;
  --text-2xl: 1.95rem;
  --text-3xl: 2.45rem;
  --text-display: 3.05rem;

  /* Fluid steps. Every one is BOUNDED BY TWO EXISTING STEPS of the scale
   * above, so the scale still governs and clamp() only decides where between
   * two of its rungs a given viewport lands. This replaces three width
   * breakpoints that existed only to resize type, which is not what a
   * breakpoint is for: a breakpoint should change a LAYOUT, and type that
   * steps in jumps is visibly coarser than type that does not.
   *
   * Read each as: never smaller than X, never larger than Y. */
  --text-fluid-lg: clamp(var(--text-base), 0.94rem + 0.5vw, var(--text-lg));
  --text-fluid-xl: clamp(var(--text-lg), 1.13rem + 0.8vw, var(--text-xl));
  --text-fluid-2xl: clamp(var(--text-xl), 1.36rem + 1.1vw, var(--text-2xl));
  --text-fluid-3xl: clamp(var(--text-2xl), 1.4rem + 1.8vw, var(--text-3xl));
  --text-fluid-display: clamp(var(--text-2xl), 1.05rem + 3.6vw, var(--text-display));

  --leading-tight: 1.15;
  --leading-snug: 1.35;
  --leading-body: 1.6;

  /* Measure. 62ch, at the short end of the 65 to 75 band, because the reader
   * is on a phone at 11pm with reduced working memory. */
  --measure: 62ch;
  /* The short measure. A form column and an oval are not prose: they are read
   * in single glances, so they sit well inside the prose measure. This was
   * three separate hard-coded 34rem values at call sites before the design
   * pass, which is the definition of a value that should have been a token. */
  --measure-short: 34rem;
  /* The standfirst measure, in characters because it is set as one held
   * sentence rather than as a column. */
  --measure-standfirst: 34ch;

  /* --- Spacing -----------------------------------------------------------
   * A single rhythm throughout, 4px base. More space above a heading than
   * below it: that relationship is enforced in the component layer. */
  --space-1: 0.25rem;
  --space-2: 0.5rem;
  --space-3: 0.75rem;
  --space-4: 1rem;
  --space-5: 1.5rem;
  --space-6: 2rem;
  --space-7: 3rem;
  --space-8: 4rem;
  --space-9: 6rem;

  /* --- Stroke ------------------------------------------------------------
   * Added at the design pass. Five different stroke widths were in use across
   * the stylesheet (1, 2, 3, 4 and 6px) with nothing naming them and nothing
   * saying what each one meant, so the next person needing a rule picked a
   * number. That is exactly the failure mode the spacing scale exists to stop,
   * and strokes had no equivalent.
   *
   * Four steps, each with a job:
   *   hair  a printed rule. Separators, table rules, quiet boundaries.
   *   1     an ordinary boundary. Control borders, the plain signpost box.
   *   2     an emphatic boundary. The focus ring, an error box, a chosen row.
   *   3     a structural rule. The heaviest thing in the system.
   *
   * The old 6px value is retired. It existed as a coloured left border on an
   * invalid field, and a coloured left bar is a decorative device that carries
   * meaning by colour and position alone. The invalid state now thickens the
   * WHOLE control boundary, which survives colour removal and does not invent
   * a fifth width to do it. */
  --stroke-hair: 1px;
  --stroke-1: 2px;
  --stroke-2: 3px;
  --stroke-3: 4px;

  /* --- Motion budget -----------------------------------------------------
   * One authored moment per surface, not scattered effects. Durations sit
   * inside the 120ms to 400ms band the linter enforces. Exponential ease-out
   * from an already-visible default: nothing is hidden waiting to animate. */
  --motion-quick: 160ms;
  --motion-base: 240ms;
  --motion-considered: 360ms;
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);


  /* --- The oval ----------------------------------------------------------
   * The signature device: a soft-edged pale shape laid over a complex
   * illustrated field so that a few words can be read clearly. On the real
   * jackets its edge is feathered, never a ruled ellipse.
   *
   * FOUR shapes, not one. Before the design pass every oval on the home page
   * carried the identical radius, so three saturated fields read as the same
   * component printed three times rather than as one device recurring. The
   * Ellises drew each halo by hand and no two are the same shape.
   *
   * --oval-radius-ruled is the one shape this world forbids: a true, ruled,
   * symmetrical ellipse. It is here on purpose, as the state the oval is in
   * BEFORE it has formed. See the authored moment in site.css section 9. */
  --oval-radius: 48% 52% 46% 54% / 54% 46% 54% 46%;
  --oval-radius-a: 46% 54% 43% 57% / 57% 42% 58% 43%;
  --oval-radius-b: 55% 45% 57% 43% / 43% 58% 42% 57%;
  --oval-radius-c: 51% 49% 41% 59% / 60% 44% 56% 40%;
  --oval-radius-ruled: 50% 50% 50% 50% / 50% 50% 50% 50%;

  --oval-pad-block: var(--space-7);
  --oval-pad-inline: var(--space-6);

  /* --- The painted halo --------------------------------------------------
   * The other half of the signature device, and the half that lives in the
   * illustration rather than in the stylesheet. Each image brief states where
   * its painted halo sits as a percentage of the picture. The build reads that
   * registry and writes these four values onto the field element, so the live
   * CSS oval lands inside the painted halo at every viewport width instead of
   * drifting away from it.
   *
   * The values below are the NO-ART defaults: a centred halo filling most of
   * the frame, which is what a flat Tier 1 field wants. A field with art
   * overrides them inline. Nothing here is guessed, and nothing breaks if the
   * illustration never arrives. */
  --art-ratio: auto;
  --halo-x: 50%;
  --halo-y: 50%;
  --halo-inline-size: 100%;
  --halo-pad-block-start: 0%;
  --halo-pad-block-end: 0%;
  --halo-pad-inline-start: 0%;
  --halo-pad-inline-end: 0%;

  /* --- Targets ------------------------------------------------------------ */
  --target-min: 48px;
}
