/* Shared scaffolding for all three style variants.
   Owns only what must not diverge: the dithered canvas background, the pinned
   wheel mechanics, and reveal/accessibility primitives. Every colour, face,
   control and motion decision belongs to the variant stylesheet. */

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

html {
  /* clip, NOT hidden: overflow-x:hidden makes this a scroll container, which
     silently breaks position:sticky on the wheel's pin. */
  overflow-x: clip;
  scroll-behavior: smooth;
}

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--font-text);
  font-size: var(--text-base, 1rem);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: clip;
}

h1, h2, h3 { text-wrap: balance; }
p { text-wrap: pretty; }

img, svg { display: block; max-width: 100%; }

a { color: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 99;
  padding: 0.75rem 1.25rem;
  background: var(--accent);
  color: var(--ground);
  text-decoration: none;
}
.skip:focus { left: 0.5rem; top: 0.5rem; }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* --------------------------- hero canvas --------------------------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--ground);
}

.hero__canvas,
.wheel__canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  opacity: 0;
  transition: opacity 0.9s ease;
}
/* The drawings paint at FULL strength. Dimming every field with one token was
   tried and rejected on sight — it washed the windmill out, took the contrast off
   the wheel, and greyed the cart train at the bottom right of the mill. Keeping
   text first is the SCRIM's job, and the scrim can be shaped to sit only where the
   copy is; opacity cannot, it flattens the whole picture.
   The token stays, because narrow screens still need wallpaper — there the copy
   sits directly on the artwork with nowhere else to go. */
:root { --field-opacity: 1; }

.hero.is-ready .hero__canvas,
.wheel.is-ready .wheel__canvas { opacity: var(--field-opacity); }
/* The hero does not fade up as a sheet: its dots resolve in Bayer order out from
   the sail hub (dither-field.js, beginIntro). The canvas is first shown already
   painted with the empty first step of that entrance — identical to the ground —
   so an opacity ramp on top would only blur the effect. */
.hero__canvas { transition: none; }

/* Dissolve the field into the section break instead of cutting it on a hard
   horizontal edge above the wheel. */
/* Stops in px, published by dither-field.js from the drawn geometry. The artwork
   is allowed to be shorter than the section on a narrow screen (so the windmill's
   sails survive), and a fixed 86% would then fade empty ground while leaving a
   hard horizontal cut across the wheat. The percentages are the no-JS fallback. */
.hero__canvas {
  -webkit-mask-image: linear-gradient(to bottom,
    #000 var(--hero-mask-start, 86%), transparent var(--hero-mask-end, 100%));
  mask-image: linear-gradient(to bottom,
    #000 var(--hero-mask-start, 86%), transparent var(--hero-mask-end, 100%));
}

/* --------------------------- pinned wheel --------------------------- */
.wheel { position: relative; background: var(--ground); }

.wheel__pin {
  position: sticky;
  top: 0;
  height: 100svh;
  overflow: hidden;
}

.wheel__panels {
  position: relative;
  z-index: 2;
  margin-top: -100svh;   /* overlay the panels onto the pinned canvas */
  pointer-events: none;  /* the canvas keeps its pointer interaction */
}
.wheel__panels a,
.wheel__panels button { pointer-events: auto; }

.wheel__panel {
  min-height: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: 12vh;
  /* never run under the wheel: stop short of the shaft axis */
  max-width: min(38rem, var(--windmill-axis, 72%) - 3rem);
}

.hero__scrim,
.wheel__scrim {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
}

/* Loading / failure notice, shared. */
.field-status {
  position: absolute;
  z-index: 3;
  right: var(--gutter);
  bottom: 1.25rem;
  margin: 0;
  font-size: 0.7rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  opacity: 0.55;
}
.is-ready .field-status { display: none; }
.is-failed .field-status::after { content: " — nav pieejams"; }

/* ----------------------------- reveals ----------------------------- */
/* Elements start visible and are only hidden once JS confirms it can reveal
   them, so a failed script never leaves the page blank. */
.js .reveal { opacity: 0; }
.js .reveal.is-in { opacity: 1; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  .js .reveal { opacity: 1 !important; transform: none !important; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    transition-duration: 0.01ms !important;
  }
}
