/* radius-shadow-v1 — W-60-1 — Saadjie radius + shadow utility classes. */
/*
 * Planning: .archon/queued-builds/WAVE-60-radius-shadow.md
 *
 * WHY this file exists: public/css/tokens/radius.css and
 * public/css/tokens/shadow.css define the *atoms* (--radius-* and
 * --shadow-*). Component CSS has been reaching for those atoms with
 * one-off declarations ("border-radius: var(--radius-md)" repeated
 * across every card, list-row, modal, and chip). This file is the
 * *utility* layer that wraps each scale step in a class so templates
 * compose surface shape + elevation from class names
 * (`<article class="surface-card">`) instead of pulling a new CSS
 * block for every new container. The token layer remains the source
 * of truth; this file is just a typed handle to it.
 *
 * WHY "3 radii + 3 shadow tiers used consistently" (the wave brief):
 *   - Radius tiers in real use:
 *       sm  ( 4px) — inputs, tags, small badges, hairline elements
 *       md  ( 8px) — cards, buttons, list rows (the workhorse)
 *       lg  (16px) — hero blocks, modal sheets, full-bleed surfaces
 *   - Shadow tiers in real use:
 *       sm  — "rests on the page"           (cards at rest)
 *       md  — "interactive / raised"        (cards on hover, dropdowns)
 *       lg  — "floats above the page"       (modals, popovers)
 *   The xl / xs rungs in the token layer survive for one-off cases
 *   (marketing feature blocks, ultra-subtle dividers) but the THREE
 *   tiers above are what every standard surface should pick from.
 *   Locking the standard pairings into `.surface-*` composite classes
 *   below is how "ad-hoc box-shadow strings" stop being written.
 *
 * WHY surface-* composite classes (not just .rounded-md + .shadow-sm
 * pasted into every template): the three canonical surface tiers
 * (card / raised / floating) each pair a SPECIFIC radius with a
 * SPECIFIC shadow. Spreading that pairing across two utility classes
 * loses the intent — and lets the next author write `.rounded-lg
 * .shadow-sm` (visual mismatch: hero block radius, business-card
 * shadow). One composite class per intent keeps the pairing in ONE
 * place. The single-property `.rounded-*` and `.shadow-*` utilities
 * stay available for the edge cases composites cannot express.
 *
 * GOTCHA: NO raw px / hex / rgb / rgba values appear below. Every
 * value goes through var(--radius-*) or var(--shadow-*). The
 * stylelint config (color-no-hex, function-disallowed-list) ignores
 * public/css/tokens/** but ENFORCES on this file — and the W56/W60
 * ANTI-RAW-VALUE git-diff gate would reject the commit otherwise.
 *
 * GOTCHA: never stack two `.shadow-*` classes on one element. The
 * shadow scale is a ladder — pick one rung. Compounding shadows
 * muddies the elevation language and inflates paint cost on low-end
 * Android (per public/css/tokens/shadow.css CONSTRAINT).
 *
 * GOTCHA: never apply `.rounded-lg` (or `.rounded-xl`) to elements
 * smaller than ~32px square — the corner radius would dominate the
 * shape and collapse the visual hierarchy. Use `.rounded-sm` /
 * `.rounded-md` instead (per public/css/tokens/radius.css CONSTRAINT).
 *
 * CONSTRAINT: every utility here is a *single-property* class EXCEPT
 * the `.surface-*` composites and `.focus-ring`. Composite classes
 * are explicitly scoped to "named surface intents" (the wave brief's
 * three tiers) — they are NOT a general escape hatch to bundle more
 * properties under one selector. That belongs 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 → radius-shadow.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 radius / elevation
 *       opinion of its own).
 */

/* ============================================================
 * Border-radius (all corners)
 * WHY all seven token steps emitted (not just the brief's three):
 * the *standard* surface tiers are sm/md/lg, but tokens/radius.css
 * also defines none/xl/pill/circle for non-surface uses (avatars,
 * chip clusters, marketing blocks). Naming the utility after the
 * token step (.rounded-md, not .rounded-8) preserves the token
 * indirection — a future re-scale changes the token, not the class.
 * ============================================================ */

.rounded-none   { border-radius: var(--radius-none); }
.rounded-sm     { border-radius: var(--radius-sm); }   /*  4px — inputs, tags */
.rounded-md     { border-radius: var(--radius-md); }   /*  8px — cards, buttons */
.rounded-lg     { border-radius: var(--radius-lg); }   /* 16px — hero, modals */
.rounded-xl     { border-radius: var(--radius-xl); }   /* 24px — feature blocks */
.rounded-pill   { border-radius: var(--radius-pill); } /* pill button / chip */
.rounded-circle { border-radius: var(--radius-circle); } /* avatar / icon button */

/* ============================================================
 * Border-radius (single corner pair)
 * WHY t / b / l / r split kept narrow: directional radii are
 * overwhelmingly used to "attach" a surface to an adjacent edge
 * (a tab's bottom flat against the panel below, a tooltip's tip
 * corner squared, a button group's inner corners flat). Only sm /
 * md are emitted because larger radii on a single-corner pair
 * almost always read as a mistake.
 *
 * WHY both corners on the named edge (not single-corner classes):
 * a "top-rounded" surface always rounds top-LEFT + top-RIGHT
 * symmetrically. A four-way single-corner matrix would balloon to
 * 16 rules with most never used; if a real template needs a single
 * corner it can use the longhand inline.
 * ============================================================ */

.rounded-t-sm {
  border-top-left-radius: var(--radius-sm);
  border-top-right-radius: var(--radius-sm);
}
.rounded-t-md {
  border-top-left-radius: var(--radius-md);
  border-top-right-radius: var(--radius-md);
}
.rounded-b-sm {
  border-bottom-left-radius: var(--radius-sm);
  border-bottom-right-radius: var(--radius-sm);
}
.rounded-b-md {
  border-bottom-left-radius: var(--radius-md);
  border-bottom-right-radius: var(--radius-md);
}
.rounded-l-md {
  border-top-left-radius: var(--radius-md);
  border-bottom-left-radius: var(--radius-md);
}
.rounded-r-md {
  border-top-right-radius: var(--radius-md);
  border-bottom-right-radius: var(--radius-md);
}

/* ============================================================
 * Box-shadow elevation ladder
 * WHY the names match the token names exactly (.shadow-md →
 * var(--shadow-md)): zero translation cost between "what the token
 * is called" and "what the class is called". Reduces the cognitive
 * load on the next author skimming the codebase.
 *
 * WHY .shadow-none exists as a class (not just "omit the class"):
 * lets a component explicitly cancel an inherited shadow without
 * having to write `box-shadow: none` inline. Useful when a card
 * variant temporarily flattens for a print stylesheet or a print-
 * adjacent context.
 * ============================================================ */

.shadow-none { box-shadow: var(--shadow-none); }
.shadow-xs   { box-shadow: var(--shadow-xs); }
.shadow-sm   { box-shadow: var(--shadow-sm); }   /* rests on page */
.shadow-md   { box-shadow: var(--shadow-md); }   /* interactive / raised */
.shadow-lg   { box-shadow: var(--shadow-lg); }   /* floats above page */
.shadow-xl   { box-shadow: var(--shadow-xl); }

/* ============================================================
 * Inset shadows (pressed state)
 * WHY a separate band: pressed-button state needs an inset shadow
 * that does NOT conflict with the resting outer shadow. Keeping
 * the two as different tokens (and different utility classes)
 * means a component can read `.shadow-md.shadow-inset-sm` for an
 * "interactive surface with a pressed-in highlight" without the
 * two box-shadow values clobbering each other inside the same var.
 * ============================================================ */

.shadow-inset-sm { box-shadow: var(--shadow-inset-sm); }
.shadow-inset-md { box-shadow: var(--shadow-inset-md); }

/* ============================================================
 * Focus ring (composite, replaces outline)
 * WHY a token-backed utility (not just `outline: 2px solid blue`):
 * some interactive surfaces (custom dropdowns, file pickers,
 * iframe-hosted widgets) replace outline entirely and need a
 * box-shadow ring as the focus indicator instead. Routing both
 * paths through --shadow-focus-ring keeps the ring colour +
 * width in lockstep with the system focus colour across the
 * codebase. WCAG 2.4.7 (focus-visible) compliance is non-
 * negotiable — see public/css/reset.css for the outline-based
 * default.
 * ============================================================ */

.focus-ring        { box-shadow: var(--shadow-focus-ring); }
.focus-ring\:focus:focus,
.focus-ring-focus:focus { box-shadow: var(--shadow-focus-ring); }

/* ============================================================
 * Surface composites — THE three canonical pairings
 * WHY composites (not loose utilities): these three pairings ARE
 * the wave brief. "3 radii + 3 shadow tiers used consistently"
 * means every standard surface picks ONE of these — not a
 * freeform combination of `.rounded-*` + `.shadow-*` that lets
 * radius/elevation drift apart over time. The .surface-* names
 * encode intent ("this is a card", "this is a raised surface",
 * "this floats") rather than mechanics (radius value + shadow
 * value), which is what a design system needs to survive a year
 * of accreted templates.
 *
 * WHY background is NOT set here: surface tiers express SHAPE +
 * ELEVATION, not COLOUR. The colour token a surface sits on
 * (--color-bg-raised vs --color-bg-subtle vs a brand-coloured
 * hero) is the component's call — bundling background into the
 * surface utility would make it impossible to recolour a card
 * variant without losing the radius+shadow pairing.
 *
 * WHY .surface-card includes a 1px hairline border: at rest, the
 * shadow alone is too subtle on white-on-white. A token-coloured
 * hairline (--color-border) gives the card a definite edge in
 * print + reduced-transparency rendering modes where the shadow
 * is suppressed. Raised / floating surfaces drop the border
 * because their shadow is strong enough to define the edge.
 * ============================================================ */

.surface-card {
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);  /* 8px — workhorse card radius */
  box-shadow: var(--shadow-sm);     /* rests on page */
}

.surface-raised {
  border-radius: var(--radius-md);  /* 8px — same shape as card */
  box-shadow: var(--shadow-md);     /* hover / interactive state */
}

.surface-floating {
  border-radius: var(--radius-lg);  /* 16px — modals, sheets, popovers */
  box-shadow: var(--shadow-lg);     /* floats above page */
}

/* ============================================================
 * Print + reduced-transparency overrides
 * WHY shadows collapse in these modes: print stylesheets strip
 * box-shadow because shadows do not render usefully on paper
 * (ink-heavy, low contrast). prefers-reduced-transparency users
 * have asked the OS to suppress translucency effects — shadows
 * are part of that family. Both modes fall back on the hairline
 * border that .surface-card already sets; .surface-raised and
 * .surface-floating gain a token-coloured border so they remain
 * visually distinct from surrounding content when the shadow
 * disappears.
 *
 * GOTCHA: prefers-reduced-transparency is a relatively new media
 * feature (Safari 17+, Chrome 118+). Older browsers ignore the
 * block entirely and continue to render the shadow — which is
 * the correct fallback (the user has not expressed a preference).
 * ============================================================ */

@media print, (prefers-reduced-transparency: reduce) {
  .shadow-xs,
  .shadow-sm,
  .shadow-md,
  .shadow-lg,
  .shadow-xl,
  .shadow-inset-sm,
  .shadow-inset-md {
    box-shadow: var(--shadow-none);
  }

  .surface-card,
  .surface-raised,
  .surface-floating {
    box-shadow: var(--shadow-none);
    border: 1px solid var(--color-border);
  }
}
