/* ════════════════════════════════════════════════════════════════════════
   RHYTHM — one scale, applied.

   This is a thin normalising layer, loaded last. It does not restyle
   anything; it takes the handful of structures that repeat on every page
   and makes them agree, so the site reads as one thing rather than as a
   dozen pages that were each designed on their own day.

   Everything below is a spacing step from tokens.css. No hand-typed
   lengths — that is the whole point.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Bands get real breathing room ──────────────────────────────────────── */
.section:not([class*="--"]) { padding-block: var(--pad-section); }
.section--tight { padding-block: var(--s-6); }
.section--lg, .section--air { padding-block: var(--pad-section-lg); }

/* A band sitting directly on another needs a line, or they read as one. */
.env + .env { border-top: 1px solid var(--line); }
.env--dark + .env--dark { border-top-color: rgba(255, 255, 255, .08); }

/* ── Grids and rails agree on their gap ─────────────────────────────────── */
.grid, .cards, .rows, .rail { gap: var(--gap-items); }
.grid--tight { gap: var(--gap-tight); }

/* ── Anything that stacks gets the same beat ────────────────────────────── */
/* ⚠️ This is the default vertical rhythm for anything inside a .wrap, and it
   wins over a component's own margins whenever that component's container also
   carries .wrap. It has silently flattened four components so far. If you are
   wondering why your margin-top does nothing, this is why — opt the component
   out with a doubled-class rule (see .aca-dhero__inner.wrap in academy.css)
   rather than raising the specificity here. */
.wrap > * + *, .sec-head + *, .stack > * + * { margin-top: var(--gap-blocks); }
.stack--tight > * + * { margin-top: var(--gap-tight); }

/* ── Cards and panels are padded the same everywhere ────────────────────── */
.card__body, .card-code__text, .card-domain__text, .card-tool__text,
.panel, .callout, .prompt, .empty { padding: var(--pad-card); }
.cn-fold > summary, .cn-fold__body { padding-inline: var(--pad-panel); }

/* ── Every pill is the same pill ────────────────────────────────────────── */
.stage, .state, .chip, .draft-tag, .cn-range { padding: var(--pad-chip); }

/* ── Type: heads keep their distance from what follows ──────────────────── */
h1, h2, h3, .sec-head__title { text-wrap: balance; }
p, li { text-wrap: pretty; }
.sec-head { margin-bottom: var(--s-5); }

/* ── The gutter is never smaller than a thumb ───────────────────────────── */
.wrap { padding-inline: var(--gutter); }

/* ── Safe area, so nothing hides under the iOS toolbar ──────────────────── */
/* A page with the footer leaves the home bar's room to the footer alone:
   counted twice, the last line stood an inch off the bottom of an iPhone —
   Arian, 2026-09-25: "needs to end with words at the bottom of the screen
   not an inch above like it is". */
body { padding-bottom: env(safe-area-inset-bottom); }
body:has(> .footer) { padding-bottom: 0; }
.footer { padding-bottom: calc(var(--pad-section) + env(safe-area-inset-bottom)); }

/* ── More air, per section ──────────────────────────────────────────────────
   Arian: "just more breathing room for each section would help too."
   A band needs space above its heading and below its last line, or two bands
   read as one long one however good the type is. */
/* ⚠️ NOT `.env > .wrap`. On pages where the band carries .section AND holds
   a .wrap — /about does — both matched and every band was padded TWICE:
   204px where it should be 102. A band is padded exactly once, here.
   And :not([class*="--"]) so this does not kill --tight / --lg / --air,
   which it did: equal specificity, declared later, modifiers dead. */
.section:not([class*="--"]) { padding-block: var(--pad-section); }
/* A band that has no .section class still needs its air. */
.env:not(.section):not([class*="hero"]) > .wrap { padding-block: var(--pad-section); }
.env.section > .wrap { padding-block: 0; }
.section > .wrap > * + * { margin-top: var(--gap-blocks); }
/* A heading needs room beneath it before the thing it introduces. */
.sec-head, .sec-head--meta { margin-bottom: var(--s-6); }
/* And the last thing in a band should not touch the next band's first line. */
.section > .wrap > :last-child { margin-bottom: 0; }
/* Two dark bands in a row need a visible seam or they merge. */
.env--dark + .env--dark, .env--light + .env--light { border-top: 1px solid var(--line); }

/* ── Collapse the type spread ───────────────────────────────────────────────
   The census found 13 distinct body sizes on the homepage alone (8.93px to
   54.4px) and 7 line-heights that are indistinguishable from each other.
   Prose gets one size and one leading; the near-duplicates go. */
p, li, dd, .prose p { font-size: var(--fs-body); line-height: 1.6; }
.sec-head__sub, .card__sub, .hero__statement, .prose p { line-height: 1.6; }
/* Display type over ~28px sets tight, not at prose leading. */
.footer__statement, .hero__title, .phero__title { line-height: 1.12; }

/* Headings: one size per level. h2s were at five different sizes. */
/* .bal__name is the DAILY BALANCE METER's label-sized heading (balance-meter.css). */
h2:not([class*="hero"]):not(.sr):not(.bal__name) { font-size: var(--fs-h2); font-weight: 300; }
/* ⚠️ (0,1,1) and last in the cascade, so a component's own one-class rule on
   an <h3> loses to it. It silently reset the Lesson row's title to h3 size
   while the Module row beside it — a <span> — kept the size both were meant
   to share. Fifth component this file has flattened; see the note at line 27. */
h3:not([class*="hero"]) { font-size: var(--fs-h3); }
/* A section label is a LABEL, not a heading — it was sitting at h2 size
   with 5px of tracking, which reads as neither. */
.sec-head__title { font-size: var(--fs-h3); letter-spacing: var(--track-wide); }

/* ── Brand law, the three the census caught ────────────────────────────────
   Pure white painted four surfaces; glass sat on two STATIC ones; and one
   control had a square corner among an all-capsule set. */
.join__row, .draft-tag { backdrop-filter: none; -webkit-backdrop-filter: none; }
.lab-panel__cta { border-radius: var(--r-pill); }

/* ── ONE radius, and no drop shadows. Both laws, enforced site-wide ────────
   The census found FOUR tokens each declaring itself the one true radius —
   two of them saying so in a comment — and roughly twenty drop shadows that
   are two ideas typed fifteen times. */
:root { --cn-r: var(--r-soft); --an-r: var(--r-soft); }

/* "No drop shadow, ever." Inset shadows are light on a surface, not a drop,
   so they stay. Everything that casts outward goes. */
.card-place__art, .loc__panel, .lab-journey__orb,
.card, .panel, .paywall__glass, .menu__inner, [class*="__panel"] {
  box-shadow: none;
  filter: none;
}

/* Glass belongs on what you tap. These are labels. */
.draft-tag, .state, .stage, .chip, [class*="__kind"], .cta-note {
  backdrop-filter: none; -webkit-backdrop-filter: none;
}

/* No pure white as a surface — "no pure black, no pure white, except text." */
.env--light, .section--light { background-color: var(--ice, #edf0f3); }

/* ════════════════════════════════════════════════════════════════════════
   THE LAST OF IT — everything the census measured and nothing more.
   Each block below names the number it is collapsing.
   ════════════════════════════════════════════════════════════════════════ */

/* ── Gaps and tracking are fixed AT SOURCE, not here. A blanket override
      on [class*="__list"] etc. lost to the real rules (equal specificity,
      but many originals are more specific) and only ADDED a value: the
      tracking count went 21 to 22. The hand-typed lengths in labyrinth.css,
      library.css, academy.css and the rest are mapped onto the scale in
      place instead, which is the only thing that actually reduces them. */

/* ── h1: six distinct sizes spanning 2.5x across sibling pages, and five
      line-height ratios. One size, one ratio, per level. ───────────────── */
/* .fc__title is excluded for the same reason .hero__title is: the daily
   focus card sets its own type deliberately, measured off the mockups, and
   this rule was silently winning over it — (0,2,1) against (0,1,0), from a
   sheet that loads last. The card's title was specified at 6.9vw/200 and was
   rendering at 2.2rem/300, which is why it filled the screen edge to edge
   and would not go thin. Same trap as .section--tight earlier in this file. */
/* The exclusion list keeps growing, and each addition has arrived the same
   way: a component sizes its own heading responsively, this rule outranks it
   from the sheet that loads last — (0,2,1) against a single class — and the
   heading renders at a size nobody chose. .fc__title filled the focus card
   edge to edge; .aca-dhero__title pushed the S off the end of RELATIONSHIPS.
   A heading that has been deliberately sized for its own measure belongs
   here. */
/* ⚠️ --fs-h1 floors at 2.2rem — 35.2px — and at 390px the display face needs
   417px for the word COMMUNICATION in a 353px column. A Lesson title ran off
   the right edge of an iPhone because of this rule, not because of its own.
   Sixth component this file has quietly resized; the Lesson hero joins the
   four already excused and sizes itself. */
/* .ch-top__title (a Code's own page) sizes itself across its world, too. */
h1:not(.hero__title):not(.sr):not(.fc__title):not(.aca-dhero__title):not(.aca-lhero__title):not(.ch-top__title) { font-size: var(--fs-h1); font-weight: 300; line-height: 1.02; }

/* ── Every page invented its own hero. Top padding ran 104 / 140 / 196 /
      106 / 116px across five sibling pages; bottom ran 72 / 64 / 104 / 0 /
      64px. One hero, one pad — and it always clears the fixed bar. ─────── */
[class*="hero"]:not(.hero):not([class*="__"]) {
  padding-top: calc(var(--nav-h) + var(--s-6));
  padding-bottom: var(--s-7);
}

/* ── Rims: 12 signatures where the dark environment declares four, and 75%
      of instances off-token — a .25/.26/.28 cluster within 0.03 of the
      token. One hairline. ─────────────────────────────────────────────── */
.env--dark [class*="__panel"], .env--dark .card, .env--dark .panel,
.env--dark [class*="__pad"], .env--dark .callout, .env--dark .prompt {
  border-color: var(--line);
}

/* ── No pure white as a surface. Four homepage surfaces were painting
      rgb(255,255,255) while /about correctly used --ice. ───────────────── */
.env--light, .section--light, .card--light, [class*="--onlight"] {
  background-color: var(--ice, #edf0f3);
}

/* ── Bands that never used .wrap had five different left edges at 1440
      (-28, -22, 0, 52, 78). Text and controls sit on the gutter; only art
      may bleed. ───────────────────────────────────────────────────────── */
#upgrade > :not([class*="bg"]):not([class*="art"]),
#tools-of-light > :not([class*="bg"]):not([class*="art"]),
#labyrinth > :not([class*="bg"]):not([class*="art"]):not([class*="panel"]) {
  padding-inline: var(--gutter);
}

/* ── Nothing decorative may change layout. This is the rule that broke the
      Code page, so it is enforced for every absolutely-placed backdrop. ── */
[class*="__geo"], [class*="__bg"], [class*="__wash"], .blooms {
  max-width: 100%;
  pointer-events: none;
}
.env, .section, [class*="hero"] { overflow-x: clip; }
