/* spacing-utils-v1 — W-59-1 — Saadjie spacing utility classes. */
/*
 * Planning: .archon/queued-builds/WAVE-59-spacing-grid.md
 *
 * WHY this file exists: public/css/tokens/spacing.css defines the *atoms*
 * (--space-0 … --space-12). Component CSS has been reaching for those atoms
 * directly with one-off rules ("padding: var(--space-5)" repeated four
 * times per template). This file is the *utility* layer that wraps each
 * scale step in a class so templates can compose layout from class names
 * (`<section class="section-pad stack-5">`) instead of pulling a new CSS
 * block for every new container. The token layer is the source of truth;
 * the utility layer is just a typed handle to it.
 *
 * WHY a 4-pt scale (not 8-pt): the underlying token grid is 4-pt
 * (see tokens/spacing.css). The wave brief calls it an "8px base scale"
 * because the *exposed* steps used in layouts (.p-2 = 8px, .p-4 = 16px,
 * .p-5 = 24px, .p-6 = 32px, .p-7 = 48px, .p-8 = 64px, .p-10 = 96px) are
 * all multiples of 8. The 4-pt atoms (.p-1 = 4px, .p-3 = 12px) stay
 * available for half-step adjustments (icon insets, hairline gaps) that
 * the 8-pt rhythm can't express. Both names refer to the same grid —
 * "4-pt grid, 8-pt rhythm" is the precise description.
 *
 * WHY class names follow the token *step* (not pixels): .p-5 means
 * "padding equal to --space-5" (24px). A future palette migration that
 * remapped --space-5 to a different rem value would update every .p-5
 * automatically. A name like .p-24 would freeze the pixel value into the
 * markup and lose the indirection the token layer pays for.
 *
 * WHY only the steps used in real layouts are emitted (not every step
 * × every direction × padding/margin/gap): the file would balloon to
 * ~500 rules with most never referenced. The included set covers every
 * layout pattern observed in existing components (cards, forms, lists,
 * section blocks). Future templates that need a missing combination
 * should add the single rule here, not invent a one-off in component CSS.
 *
 * GOTCHA: NO raw px / hex / rgb values appear below. Every numeric value
 * goes through var(--space-*) or var(--container-*). The W56 stylelint
 * config (color-no-hex, function-disallowed-list) ignores public/css/
 * tokens/** but ENFORCES on this file — anything raw will fail lint
 * the moment stylelint lands in package.json.
 *
 * GOTCHA: section padding is the one place where the responsive jump
 * matters. Mobile pages need to feel held-in (24/32 vertical), but on
 * desktop the same 32px feels squashed against the surrounding chrome.
 * The .section-pad rule below switches at min-width:768px (tablet+) so
 * the desktop reading rhythm doesn't carry mobile's tighter feel.
 *
 * CONSTRAINT: every utility here is a *single-property* class. Multi-property
 * classes (e.g. ".card { padding + radius + shadow }") belong in the
 * component layer (W63 card-primitives), not here. Mixing the two layers
 * is how utility CSS systems collapse into specificity wars.
 *
 * FLOW: a template loads tokens.css → spacing.css → component CSS in that
 *       order. The cascade means a component rule can override a utility
 *       if it has to, but the utility wins over the bare element (which
 *       has no padding/margin opinion of its own).
 */

/* ============================================================
 * Padding (all sides)
 * ============================================================ */

.p-0  { padding: var(--space-0); }
.p-1  { padding: var(--space-1); }   /*  4px — icon inset, hairline gap */
.p-2  { padding: var(--space-2); }   /*  8px */
.p-3  { padding: var(--space-3); }   /* 12px — chip / pill */
.p-4  { padding: var(--space-4); }   /* 16px — default card body */
.p-5  { padding: var(--space-5); }   /* 24px — comfortable card */
.p-6  { padding: var(--space-6); }   /* 32px — section block */
.p-7  { padding: var(--space-7); }   /* 48px — hero block */
.p-8  { padding: var(--space-8); }   /* 64px */

/* ============================================================
 * Padding (x / y axis)
 * ============================================================ */

.px-0 { padding-left: var(--space-0); padding-right: var(--space-0); }
.px-1 { padding-left: var(--space-1); padding-right: var(--space-1); }
.px-2 { padding-left: var(--space-2); padding-right: var(--space-2); }
.px-3 { padding-left: var(--space-3); padding-right: var(--space-3); }
.px-4 { padding-left: var(--space-4); padding-right: var(--space-4); }
.px-5 { padding-left: var(--space-5); padding-right: var(--space-5); }
.px-6 { padding-left: var(--space-6); padding-right: var(--space-6); }
.px-7 { padding-left: var(--space-7); padding-right: var(--space-7); }
.px-8 { padding-left: var(--space-8); padding-right: var(--space-8); }

.py-0 { padding-top: var(--space-0); padding-bottom: var(--space-0); }
.py-1 { padding-top: var(--space-1); padding-bottom: var(--space-1); }
.py-2 { padding-top: var(--space-2); padding-bottom: var(--space-2); }
.py-3 { padding-top: var(--space-3); padding-bottom: var(--space-3); }
.py-4 { padding-top: var(--space-4); padding-bottom: var(--space-4); }
.py-5 { padding-top: var(--space-5); padding-bottom: var(--space-5); }
.py-6 { padding-top: var(--space-6); padding-bottom: var(--space-6); }
.py-7 { padding-top: var(--space-7); padding-bottom: var(--space-7); }
.py-8 { padding-top: var(--space-8); padding-bottom: var(--space-8); }

/* ============================================================
 * Padding (single side)
 * WHY only t/b kept for steps 3-6: directional padding is overwhelmingly
 * used for vertical spacing between siblings (heading-to-body, list-to-
 * footer). Single-side horizontal padding nearly always wants px-* to
 * stay symmetric — if a real template needs pl-* / pr-* add it here.
 * ============================================================ */

.pt-0 { padding-top: var(--space-0); }
.pt-2 { padding-top: var(--space-2); }
.pt-3 { padding-top: var(--space-3); }
.pt-4 { padding-top: var(--space-4); }
.pt-5 { padding-top: var(--space-5); }
.pt-6 { padding-top: var(--space-6); }
.pt-7 { padding-top: var(--space-7); }
.pt-8 { padding-top: var(--space-8); }

.pb-0 { padding-bottom: var(--space-0); }
.pb-2 { padding-bottom: var(--space-2); }
.pb-3 { padding-bottom: var(--space-3); }
.pb-4 { padding-bottom: var(--space-4); }
.pb-5 { padding-bottom: var(--space-5); }
.pb-6 { padding-bottom: var(--space-6); }
.pb-7 { padding-bottom: var(--space-7); }
.pb-8 { padding-bottom: var(--space-8); }

/* ============================================================
 * Margin (all sides, x / y axis)
 * WHY margin utilities are narrower than padding: margin between siblings
 * is now mostly expressed via .stack-* (parent owns the rhythm). Margin
 * utilities stick around for the few cases where the parent can't (a
 * standalone block that needs to push away from a fixed header).
 * ============================================================ */

.m-0  { margin: var(--space-0); }
.m-1  { margin: var(--space-1); }
.m-2  { margin: var(--space-2); }
.m-3  { margin: var(--space-3); }
.m-4  { margin: var(--space-4); }
.m-5  { margin: var(--space-5); }
.m-6  { margin: var(--space-6); }

.mx-auto { margin-left: auto; margin-right: auto; }

.my-0 { margin-top: var(--space-0); margin-bottom: var(--space-0); }
.my-2 { margin-top: var(--space-2); margin-bottom: var(--space-2); }
.my-3 { margin-top: var(--space-3); margin-bottom: var(--space-3); }
.my-4 { margin-top: var(--space-4); margin-bottom: var(--space-4); }
.my-5 { margin-top: var(--space-5); margin-bottom: var(--space-5); }
.my-6 { margin-top: var(--space-6); margin-bottom: var(--space-6); }
.my-7 { margin-top: var(--space-7); margin-bottom: var(--space-7); }
.my-8 { margin-top: var(--space-8); margin-bottom: var(--space-8); }

.mt-0 { margin-top: var(--space-0); }
.mt-2 { margin-top: var(--space-2); }
.mt-3 { margin-top: var(--space-3); }
.mt-4 { margin-top: var(--space-4); }
.mt-5 { margin-top: var(--space-5); }
.mt-6 { margin-top: var(--space-6); }
.mt-7 { margin-top: var(--space-7); }
.mt-8 { margin-top: var(--space-8); }

.mb-0 { margin-bottom: var(--space-0); }
.mb-2 { margin-bottom: var(--space-2); }
.mb-3 { margin-bottom: var(--space-3); }
.mb-4 { margin-bottom: var(--space-4); }
.mb-5 { margin-bottom: var(--space-5); }
.mb-6 { margin-bottom: var(--space-6); }
.mb-7 { margin-bottom: var(--space-7); }
.mb-8 { margin-bottom: var(--space-8); }

/* ============================================================
 * Gap (flex + grid)
 * WHY both `gap` and the legacy `column-gap` / `row-gap` are NOT both
 * emitted: every browser the site targets (Chromium 84+, Firefox 63+,
 * Safari 14.1+) supports the shorthand. The longhand fallback is dead.
 * ============================================================ */

.gap-0 { gap: var(--space-0); }
.gap-1 { gap: var(--space-1); }
.gap-2 { gap: var(--space-2); }
.gap-3 { gap: var(--space-3); }
.gap-4 { gap: var(--space-4); }
.gap-5 { gap: var(--space-5); }
.gap-6 { gap: var(--space-6); }
.gap-7 { gap: var(--space-7); }
.gap-8 { gap: var(--space-8); }

/* ============================================================
 * Stack (vertical rhythm between direct children)
 * WHY a .stack-* utility (not "use margin-top on every child"):
 *   - One declaration on the parent vs. N declarations on siblings.
 *   - No margin-collapse surprises against floated / abs-positioned kin.
 *   - Removes the "first child has no top margin" exception that every
 *     hand-written list eventually has to special-case.
 *
 * WHY the `>` direct-child combinator: a .stack-5 around a card grid
 * should not push every <p> inside every card down by 24px — only the
 * direct cards. Descendants past the first level keep their own rhythm.
 *
 * WHY margin-top (not margin-bottom): if the last child of a stack needs
 * to butt up against a sibling, the parent's :last-child rule doesn't
 * have to fight a trailing margin. Lobotomized-Owl pattern (Heydon
 * Pickering) — top margin on every-child-except-first.
 * ============================================================ */

.stack-0 > * + * { margin-top: var(--space-0); }
.stack-1 > * + * { margin-top: var(--space-1); }
.stack-2 > * + * { margin-top: var(--space-2); }
.stack-3 > * + * { margin-top: var(--space-3); }
.stack-4 > * + * { margin-top: var(--space-4); }
.stack-5 > * + * { margin-top: var(--space-5); }
.stack-6 > * + * { margin-top: var(--space-6); }
.stack-7 > * + * { margin-top: var(--space-7); }
.stack-8 > * + * { margin-top: var(--space-8); }

/* ============================================================
 * Cluster (horizontal row with consistent gap, wraps on overflow)
 * WHY a .cluster utility: chip rows, tag rows, button rows, and inline
 * meta rows all want the same behaviour — wrap horizontally with a
 * consistent gap and a consistent vertical gap on wrap. flex+gap+wrap
 * is the recipe; expressing it as one class stops every component
 * reinventing it.
 * ============================================================ */

.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-3);
}

.cluster-2 { gap: var(--space-2); }
.cluster-3 { gap: var(--space-3); }
.cluster-4 { gap: var(--space-4); }
.cluster-5 { gap: var(--space-5); }

/* ============================================================
 * Section padding (responsive, standardized)
 * WHY this is its own primitive (not just .py-5 / .py-7): the brief
 * standardizes section padding to mobile 24/32 and desktop 64/96. Those
 * exact pairings (small step at mobile, larger step at desktop) recur
 * on every public + dashboard page. Bundling them into named classes
 * keeps the responsive jump in ONE place — if pilot feedback wants the
 * desktop step tighter, it changes here and propagates everywhere.
 *
 * WHY the side padding stays at --content-padding-x (the token's job):
 * horizontal page gutters are owned by the container, not the section.
 * Section utilities are vertical rhythm only — pairing them with a
 * container width (.container or .container-wide) gives the full layout.
 *
 * GOTCHA: the breakpoint is 768px (tablet floor), NOT a desktop floor.
 * Most parents browse the dashboard on a phone in landscape (~640-740px
 * wide) — bumping the section padding there would crowd the content.
 * The jump waits for tablet portrait or wider.
 * ============================================================ */

.section-pad {
  padding-top:    var(--space-5);  /* 24px */
  padding-bottom: var(--space-6);  /* 32px */
}

.section-pad-tight {
  padding-top:    var(--space-4);  /* 16px */
  padding-bottom: var(--space-5);  /* 24px */
}

.section-pad-loose {
  padding-top:    var(--space-6);  /* 32px */
  padding-bottom: var(--space-7);  /* 48px */
}

@media (min-width: 768px) {
  .section-pad {
    padding-top:    var(--space-8);   /* 64px */
    padding-bottom: var(--space-10);  /* 96px */
  }

  .section-pad-tight {
    padding-top:    var(--space-6);   /* 32px */
    padding-bottom: var(--space-7);   /* 48px */
  }

  .section-pad-loose {
    padding-top:    var(--space-10);  /* 96px */
    padding-bottom: var(--space-12);  /* 128px — hero only */
  }
}

/* ============================================================
 * Container (centered reading column at the canonical max widths)
 * WHY these live here (not in a separate layout.css yet): until W64
 * lands the layout shell, the spacing layer owns "how wide is the
 * content column" alongside "how tall are the section blocks" — both
 * are layout-rhythm concerns. The horizontal padding pulls from
 * --content-padding-x so the gutter respects the token system.
 * ============================================================ */

.container {
  max-width: var(--container-max);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--content-padding-x);
  padding-right: var(--content-padding-x);
}

.container-narrow {
  max-width: var(--container-max-narrow);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--content-padding-x);
  padding-right: var(--content-padding-x);
}

.container-wide {
  max-width: var(--container-max-wide);
  margin-left: auto;
  margin-right: auto;
  padding-left: var(--content-padding-x);
  padding-right: var(--content-padding-x);
}

/* ============================================================
 * Reduced-motion belt-and-braces
 * WHY this file even mentions motion: section-pad responds to viewport
 * width, not user preference, so prefers-reduced-motion doesn't change
 * anything here directly. But ANY future utility that animates spacing
 * (a collapsing accordion, an expanding card) must wrap the transition
 * in the @media block below. Placeholder + reminder for future authors.
 * ============================================================ */

/* @media (prefers-reduced-motion: reduce) { … reserved … } */
