/* ==========================================================================
   base.css — reset + typographic defaults.
   Loads after tokens.css. The floor is baked in here so an un-styled page
   already sits at "competent" before any design decision is made.
   ========================================================================== */

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

* { margin: 0; }

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

body {
  background: var(--ground);
  color: var(--ink);
  font-family: var(--f-text);
  font-size: var(--t-0);            /* 17 → 20. never 16 */
  line-height: var(--lh-body);
  font-synthesis-weight: none;
  text-rendering: optimizeLegibility;
  -webkit-font-smoothing: antialiased;
}

/* --- Headings ------------------------------------------------------------
   Tight leading and negative tracking are what make display type read as
   designed rather than as a large paragraph.                             */

h1, h2, h3, h4 {
  font-family: var(--f-display);
  line-height: var(--lh-display);
  letter-spacing: var(--tr-display);
  text-wrap: balance;
  max-width: var(--measure-tight);
  font-weight: 500;
}

h1 { font-size: var(--t-5); }
h2 { font-size: var(--t-4); }
h3 { font-size: var(--t-3); }
h4 { font-size: var(--t-2); line-height: var(--lh-tight); }

.display {
  font-family: var(--f-display);
  font-size: var(--t-display);       /* 44 → 160 */
  line-height: 0.92;
  letter-spacing: -0.04em;
  text-wrap: balance;
  max-width: none;
}

.lead { font-size: var(--t-1); line-height: 1.4; max-width: var(--measure-tight); }

.label {
  font-size: var(--t--1);
  letter-spacing: var(--tr-label);
  text-transform: uppercase;
  line-height: 1.1;                  /* Finnish Ä/Ö need >= 1.05 in caps */
  color: var(--ink-2);
}

/* --- Body copy ----------------------------------------------------------- */

p, li { max-width: var(--measure); text-wrap: pretty; }
p + p { margin-top: var(--s-4); }

strong { font-weight: 600; }

a {
  color: inherit;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.18em;
  transition: opacity var(--dur-fast) var(--ease-out);
}
a:hover { opacity: 0.6; }

hr { border: 0; border-top: 1px solid var(--hairline); }

/* --- Media --------------------------------------------------------------- */

img, picture, video, canvas, svg { display: block; max-width: 100%; }
img, video { height: auto; }

/* --- Forms --------------------------------------------------------------- */

input, button, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: 0; padding: 0; }

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

/* --- Layout primitives ---------------------------------------------------
   Three classes, no framework. `.wrap` never becomes the only layout
   decision on the page — see the design floor.                           */

.wrap {
  padding-inline: var(--gutter);
  margin-inline: auto;
  width: 100%;
  max-width: 82rem;
}

.wrap--narrow { max-width: 46rem; }
.wrap--bleed  { max-width: none; padding-inline: 0; }

.section { padding-block: var(--section-y); }   /* 72 → 160 */

.hero {
  /* --hero-h overrides the viewport unit. Set it to a fixed px value when
     capturing a full-page screenshot: dvh resolves against the capture
     window, so a tall window inflates the hero to nonsense. */
  min-height: var(--hero-h, 88dvh);                             /* dvh, not vh */
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding-block: var(--s-9) var(--s-8);
}

/* Spacing contrast: tight inside a group, wide between groups. */
.stack     > * + * { margin-top: var(--s-4); }
.stack-lg  > * + * { margin-top: var(--s-8); }
.stack-xl  > * + * { margin-top: var(--s-10); }

/* --- Scroll reveal -------------------------------------------------------
   Pair with an IntersectionObserver that adds .is-in. Never a scroll
   listener.                                                              */

.reveal {
  opacity: 0;
  transform: translateY(1.5rem);
  transition: opacity var(--dur-scene) var(--ease-out-exp),
              transform var(--dur-scene) var(--ease-out-exp);
}
.reveal.is-in { opacity: 1; transform: none; }


/* --- Split text (motion.js) ----------------------------------------------
   Hidden only when JS is present, and only until motion.js has split it.
   The failsafe in the head snippet reveals it if motion.js never runs.   */

html.js [data-split] { visibility: hidden; }
.m-line { display: block; will-change: transform; }

@media (prefers-reduced-motion: reduce) {
  html.js [data-split] { visibility: visible !important; }
}

/* --- Hero canvas ---------------------------------------------------------
   The canvas fills its positioned parent, so the parent must be the
   full-bleed element: put .wrap on an inner div, never on .hero itself, or
   the canvas ends up inset by the gutter.                                */

.hero { position: relative; }
.hero-canvas {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 0;
}
.hero > *:not(.hero-canvas) { position: relative; z-index: 1; }

/* --- Reduced motion ------------------------------------------------------ */

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