/* ==========================================================================
   base.css, reset + element defaults. Consumes Tier 2/3 tokens only.
   ========================================================================== */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-ui);
  font-size: var(--text-md);
  line-height: var(--leading-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  min-height: 100dvh;
  display: flex;
  flex-direction: column;
  transition: background-color var(--t-event) var(--ease-sit),
              color var(--t-event) var(--ease-sit); /* the Morph rides this */
}

main { flex: 1; width: 100%; }

h1, h2, h3, h4 {
  line-height: var(--leading-head);
  letter-spacing: -0.01em;
  margin: 0 0 var(--s-2);
  font-weight: 700;
}
h1 { font-size: var(--text-2xl); }
h2 { font-size: var(--text-xl); }
h3 { font-size: var(--text-lg); }
p  { margin: 0 0 var(--s-2); max-width: var(--measure); }

a {
  color: var(--link);
  text-decoration: none;
  text-underline-offset: 0.15em;
}
a:hover { color: var(--link-hover); text-decoration: underline; }

hr { border: 0; border-top: 1px solid var(--line); margin: var(--s-3) 0; }

/* Focus, visible in every tone, never removed (§7.10) */
:focus-visible {
  outline: 2px solid var(--focus);
  outline-offset: 2px;
  border-radius: var(--r-1);
}

/* Forms */
label { display: block; font-size: var(--text-sm); font-weight: 600; margin-bottom: var(--s-1); }
input[type="text"],
input[type="email"],
input[type="password"] {
  width: 100%;
  min-height: var(--u);                 /* Law 3.2: nothing tappable under a half-inch */
  padding: 0 var(--s-1);
  font: inherit;
  color: var(--input-text);
  background: var(--input-bg);
  border: 1px solid var(--input-line);
  border-radius: var(--r-1);
  transition: border-color var(--t-micro) var(--ease-sit),
              box-shadow var(--t-micro) var(--ease-sit);
}
input:focus-visible { outline: 2px solid var(--focus); outline-offset: 1px; border-color: var(--accent); }
input[aria-invalid="true"] { border-color: var(--err); }

.field { margin-bottom: var(--s-2); }
.field .hint { font-size: var(--text-sm); color: var(--muted); margin: var(--s-1) 0 0; }
.field .error-text { font-size: var(--text-sm); color: var(--err); margin: var(--s-1) 0 0; }

/* Layout spine */
.container {
  width: 100%;
  max-width: calc(var(--u) * 24);  /* 1152px, 24 half-inches */
  margin-inline: auto;
  padding-inline: var(--s-2);
}

.prose { max-width: var(--measure); }

/* ── Utilities ────────────────────────────────────────────── */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0);
  white-space: nowrap; border: 0;
}
.muted { color: var(--muted); }
.small { font-size: var(--text-sm); }
.center { text-align: center; }

/* ── Delight patterns (hand-rolled scroll-craft *feeling*) ─────
   Every reveal is opacity+translate, composited-only; 0 ember cost.
   prefers-reduced-motion kills all motion; the content still reads.

   Directional reveals (data-wow="up|down|left|right") use clip-path
   wipe for a more cinematic entry, the element slides from behind its
   own mask, not just fading in. The mask collapses to a hairline
   under reduced motion so content always settles visibly. */
.wow {
  opacity: 0;
  transform: translateY(calc(var(--u) * 0.1875)); /* 8px, the smallest honest step */
  transition: opacity var(--t-std) var(--ease-sit),
              transform var(--t-std) var(--ease-sit),
              clip-path var(--t-std) var(--ease-sit);
}
.wow.revealed { opacity: 1; transform: translateY(0); clip-path: inset(0); }

/* Clip-path wipe variants, a more polished entry than fade-only.
   The mask applies ONLY before reveal (the old rules left it on forever,
   which silently hid the terminal box and the FAQ answers). Once
   .revealed lands, the wipe animates open via the transition above. */
.wow[data-wow="up"]:not(.revealed) { clip-path: inset(60% 0 40% 0); transform: translateY(var(--u)); }
.wow[data-wow="down"]:not(.revealed) { clip-path: inset(40% 0 60% 0); transform: translateY(calc(var(--u) * -1)); }
.wow[data-wow="left"]:not(.revealed) { clip-path: inset(0 100% 0 0); transform: translateX(var(--u)); }
.wow[data-wow="right"]:not(.revealed) { clip-path: inset(0 0 0 100%); transform: translateX(calc(var(--u) * -1)); }

/* Reduced motion: no wipes, no travel, content settles visibly. */
@media (prefers-reduced-motion: reduce) {
  .wow, .wow:not(.revealed) { opacity: 1; transform: none; clip-path: none; transition: none; }
}

/* Staggered children, data-wow-stagger="60" on the parent delays each
   child's reveal by the given ms, creating a kinetic cascade. */
[data-wow-stagger] > * {
  --_child-delay: calc(attr(data-wow-stagger) * var(--child-i, 0));
}

/* Kinetic text splitting, data-wow="split" splits the element's text
   into word-level spans and reveals each staggered. The JS in delight.js
   handles the DOM split; this is the pre-paint state. */
.wow[data-wow="split"] .wow-word { opacity: 0; transform: translateY(12px); }
.wow[data-wow="split"].revealed .wow-word {
  opacity: 1; transform: none;
}

.parallax { will-change: transform; }

/* Subtle cursor-tilt on the hero headline, the earnest mask
   *breathes* when the human approaches. Just enough to notice it's alive. */
.hero-headline {
  transform: perspective(64rem) rotateX(calc(var(--mouse-y, 0) * 2.2deg))
                                 rotateY(calc(var(--mouse-x, 0) * -2.2deg));
  transition: transform var(--t-std) var(--ease-sit);
  transform-style: preserve-3d;
}

/* Scrim that eases as you scroll, focus narrows downward. */
.scrim-wrap {
  position: relative;
  isolation: isolate;
}
.scrim-wrap::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(to bottom, var(--bg) 0%, transparent 120%);
  opacity: var(--scroll-scrim, 1);
  pointer-events: none;
}

::selection { background: var(--accent-tint); }

/* --------------------------------------------------------------------------
   Motion law, Law E2: reduced motion collapses everything to ≤120ms fades.
   No parallax, no trails, no morph. The palace still works, told in stills.
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 120ms !important;
  }
}
