/* tokens.css — the single source of truth.
   Governed by docs/BUILD-CONTRACT.md. Every value here is either SAMPLED from a
   photograph of the southwest Florida Gulf coast, COMPUTED from CIE 1931 against
   a Planckian spectrum, or AUTHORED with its derivation stated.
   Derivation: research/SUBJECT-REFERENCE.md.

   Zero hex literals exist anywhere else in this project.
   Enforced by _qa/check-contract.js. */

:root {

  /* ---- GROUNDS ------------------------------------------------------ */
  --pitch:      #050C0E;  /* SAMPLED  moonlight-on-water, largest cluster 29.4% */
  --vespers:    #191220;  /* AUTHORED the purple lock, resolved near-neutral    */
  --tannin:     #221E15;  /* SAMPLED  Estero Bay foreground at sunset, p75      */
  --brack:      #1F3334;  /* SAMPLED  blackwater shallow, tannin-stained        */
  --harbor:     #0A4453;  /* SAMPLED  night water band median                   */

  /* THE PAGE GROUND. Derived from the approved anchor, NOT from --pitch.
     --pitch is R5 G12 B14 — a teal-black — and using it as the surface made
     the whole site shift from violet to cold cyan the moment you left the
     hero, which read as editorial instead of mystical. --pitch keeps its
     place in the palette as a deepest-accent value; it is not a surface. */
  --ground:     color-mix(in srgb, var(--vespers) 82%, var(--pitch));

  /* ---- READING ------------------------------------------------------ */
  --chalk:      #E0E3E7;  /* SAMPLED  eastern oyster shell, p95                 */
  --pewter:     #8E999E;  /* SAMPLED  Sarasota Bay water median, January        */
  --moonspill:  #6E7FA3;  /* SAMPLED  moonlit water p90 — THE ACCENT            */

  /* ---- LIGHTS ------------------------------------------------------- */
  /* The moon is WARM. 4100K is the measured CCT of moonlight; the silvery-blue
     everyone paints is the Purkinje shift in the eye, not the light itself.  */
  --moondisc:   #FFD6AA;  /* COMPUTED 4100K Planckian -> sRGB                   */
  /* Low-pressure sodium is mandated on Florida beach roads: it emits nothing
     below 570nm, which is what disorients turtle hatchlings. Place-specific. */
  --sodium:     #FF8B16;  /* COMPUTED 2000K HPS dock lamp                       */

  /* ---- LAND --------------------------------------------------------- */
  --ember:      #C48322;  /* SAMPLED  sea grape, turning leaf                   */
  --seagrape:   #4B8334;  /* SAMPLED  sea grape leaf, Sanibel                   */
  --sabal:      #535639;  /* SAMPLED  sabal palmetto frond, dominant cluster    */
  --frond:      #905D5A;  /* SAMPLED  frond oyster, Sanibel — mauve-red flats   */

  /* NOTE: there is deliberately no --bloom. Cool-green bioluminescence is the
     ATLANTIC side (Mosquito Lagoon, Indian River). The Gulf has red tide.    */

  /* ---- MOTION ------------------------------------------------------- */
  /* Two curves, and the first does nearly all the work. Obys uses a single
     curve on 82 of its 84 transitions; four curves used once each read as
     four unrelated statements about the brand.                              */
  --ease:       cubic-bezier(.16, 1, .3, 1);       /* primary   — expo-out    */
  --ease-alt:   cubic-bezier(.215, .61, .355, 1);  /* secondary — cubic-out   */
  /* ease-in-out is banned by contract. */

  /* Interface response. Exactly three, nothing longer. */
  --t-fast:     .15s;
  --t-base:     .2s;
  --t-slow:     .3s;
  /* Content reveal is a separate, slower family — measured off gsap.com at
     0.7s power3.out with a 0.15s stagger. It drives the section entrances
     from JS (REVEAL in home.js) and, since the almanac rail, one thing in CSS
     too, so the number lives here now instead of being written twice.
     This is NOT a fourth interface duration. §5 defines two families and is
     explicit that they are not the same thing: 0.3s governs interface
     RESPONSE, 0.7s governs CONTENT ARRIVING. A moon replacing another moon in
     a media slot is content arriving.                                       */
  --t-reveal:   .7s;

  /* ---- TYPE --------------------------------------------------------- */
  /* Root is 0.9rem so the scale lands on 12.6 / 14.4 / 16.2 / 45 / 90 — the
     values three of the four studied winners actually use.                  */
  --display:    Fraunces, Georgia, "Times New Roman", serif;
  --body:       Piazzolla, Georgia, serif;
  --mono:       "Space Mono", ui-monospace, SFMono-Regular, monospace;

  /* Line-height inverts against size; tracking ramps against size. Formulas
     applied everywhere, not per-element taste.                              */
  --lh-display: 1;
  --lh-mid:     1.2;
  --lh-body:    2;      /* IZANAMI body is 14.4/28.8 — exactly 2.0           */
  --lh-utility: 1.35;

  --tr-display: -.05em;
  --tr-mid:     -.035em;
  --tr-body:    -.028em;
  --tr-utility: .03em;  /* uppercase utility tracks POSITIVE                 */

  /* ---- GRID --------------------------------------------------------- */
  /* 1440 - (72 x 2) = 1296; 1296 / 4 = 324. Lusion and IZANAMI both use it;
     IZANAMI's body measure AND its image plates are exactly one 324 column. */
  --margin:     72px;
  --columns:    4;
  --measure:    324px;
  --rule:       1px;
  /* THE GRID SCALES. §4 is a FORMULA — "1440 - 144 = 1296; 1296 / 4 = 324" —
     and 324px was its value at 1440, not a constant. Freezing the output while
     the window kept growing is why a 2309px screen showed 279px of dead edge
     and columns that looked like they were waiting for content. Charles:
     "this site has way too much blank space... it gets the point across to
     fill the space up."
     Every step below is the same formula evaluated at that width, and the
     1900 row lands on 432 — exactly what izanami measures at 1920
     (research/izanami/MOTION.md §3). Steps rather than a vw calc because rule
     L1 bans 100vw (it counts the scrollbar) and container queries would put
     `contain: layout` on stations that carry the sticky plates. */

  /* Spacing scale — nothing off-scale. */
  --s-1: .25rem; --s-2: .5rem;  --s-3: .75rem; --s-4: 1rem;   --s-5: 1.5rem;
  --s-6: 2rem;   --s-7: 3rem;   --s-8: 4.5rem; --s-9: 7rem;   --s-10: 10.5rem;
}

@media (max-width: 899px) {
  :root {
    --margin: 24px;
    --columns: 2;
  }
}

/* measure = (viewport - 2 x margin) / 4, at each step. Not taste — arithmetic. */
@media (min-width: 1600px) { :root { --margin:  80px; --measure: 360px; } }
@media (min-width: 1900px) { :root { --margin:  96px; --measure: 432px; } }
@media (min-width: 2200px) { :root { --margin: 110px; --measure: 495px; } }
@media (min-width: 2560px) { :root { --margin: 128px; --measure: 576px; } }
