:root {
  /* ---- palette ----------------------------------------------------------
     --cream used to be a build invariant: every photograph was shot on it and
     the plates shipped opaque with it baked in, so a section background set
     to the same number met the plate with no seam. Nothing ships opaque any
     more - every plate, step and ingredient is a cutout - so this is once
     again an ordinary colour, free to change without re-shooting anything.
     tools/images.py --verify now checks the invariant that replaced it: a
     delivered file must still carry its matte.                            */
  --cream:    #F5F0E6;
  --paper:    #FBF8F1;
  /* The ground the exploded ring stands on. The cutouts are pale beige food
     on a pale cream field, and at chip size that is almost no contrast at all
     - the chickpeas were legible only once something darker sat behind them.
     Deepening the ground for act 2 alone buys the separation without spending
     the one dark chamber, which belongs to the recipe. */
  --sand:     #EADFC7;
  --ink:      #1A1712;
  --ink-2:    #4A443A;
  --stone:    #8C8578;
  --chickpea: #D9B26A;
  --olive:    #6B7B4A;
  --paprika:  #B4472B;   /* the one break. Used at a point, never over an area. */
  --charcoal: #16150F;   /* the dark chamber - the recipe section only */
  --hair:     rgba(26, 23, 18, .14);

  /* ---- type -------------------------------------------------------------
     The house faces from mikdash-scroll: Basalt Tall for display, Regular
     for body, Light for the airy lede/note voice.                         */
  --f-display: "Basalt Tall", system-ui, sans-serif;
  --f-body:    "Basalt Regular", system-ui, sans-serif;
  --f-air:     "Basalt Light", system-ui, sans-serif;

  --t-kicker:  clamp(0.72rem, 0.9vw, 0.9rem);
  --t-lede:    clamp(1rem, 1.5vw, 1.35rem);
  --t-h:       clamp(2.4rem, 7vw, 7rem);
  --t-h2:      clamp(1.9rem, 4vw, 3.4rem);
  --t-name:    clamp(1.8rem, 3.6vw, 3.2rem);
  --t-counter: clamp(2.2rem, 3.4vw, 3.6rem);

  /* Tracking matched to mikdash-scroll - the tracked-out kicker over a
     Basalt display face is the house label voice. */
  --track-kicker: 0.42em;
  --track-h: 0.02em;
  --lead-h: 1.02;

  /* ---- motion -----------------------------------------------------------
     The house curve, from the MotionSites report: it appears in 13 of the
     76 templates and is the studio default.                              */
  --ease-house: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-fly:   cubic-bezier(0.22, 1, 0.36, 1);
  --dur-veil:   700ms;
  --stagger:    120ms;   /* index * 120ms - the house entrance ladder */

  /* ---- stage geometry ---------------------------------------------------
     Act lengths live here so the scroll budget is one number a designer can
     retune. js reads the rendered spacer heights, never these values, so a
     media query below cannot desync from what ScrollTrigger measured.     */
  /* Seven, not six: six varieties is six hand-offs plus the return of the
     opening plate, and a hold at each end. Must equal arcScreens() in
     js/arc.js - js reads the rendered spacer height, so a mismatch here does
     not desync the motion, it just makes the act longer or shorter than the
     travel it contains. */
  --act1-screens: 7;
  --act2-screens: 3.5;

  /* ---- layout ----------------------------------------------------------- */
  --pad-x:   clamp(1.25rem, 5vw, 5rem);
  --chrome-z: 40;

  /* Direction scalar. CSS transforms are physical and do NOT flip in RTL,
     so any horizontal text entrance has to carry the sign explicitly.
     Picture geometry (#arc, #ring) never uses this - see sections.css.   */
  --dir: -1;
}

html[lang="en"] { --dir: 1; }

/* Ring geometry. Three scalars retune the whole exploded diagram; the
   per-ingredient polar spec lives in js/ingredients.js because CSS cannot
   do arithmetic over eight items. */
#ring {
  /* The ring radius, and the point everything orbits.
     The orbited point is now the SIXTH PLATE OF THE ARC, which act 2 does not
     replace - it simply opens what act 1 left centred. So these two values do
     not describe a plate of their own: they have to repeat where .plate sits
     in sections.css (left 50%, top 46%). Two numbers that must agree, and the
     older pair of the same kind already went wrong once - the chips orbited a
     point the plate was not at. If .plate moves, this moves.

     The radius clears the plate rather than being tuned by eye, and the chip
     that decides it is the CLOSEST one, not the average: js/ingredients.js
     gives each chip its own radius multiplier and shum sits at 0.86. Plate
     min(62vw, 62svh) settling to 0.80 puts its rim at 0.248 of the stage;
     shum's inner edge lands at 0.86 x 0.40 - its own half width, which clears
     it. Tuned against the average instead, three chips sat on the plate. */
  --ring-r: min(40vw, 36svh);
  --bowl-x: 50%;
  /* 46%, matching .plate's own top. It used to be 55%, which balanced a ring
     whose arc is clipped at +/-155 degrees and therefore hangs lower than it
     reaches. That correction belonged to a ring drawn around a plate of its
     own; here the plate is a real element already sitting at 42% and the ring
     has to meet it, not balance itself. */
  --bowl-y: 46%;
}
