/* Ostan Autosi — theme stylesheet (Wamo-style: purple + teal).
 *
 * Foundation (reset, tokens, base type, .container, utilities, dark mode) is in
 * globals.css — a GENERATED ACSS-mirror framework (DO NOT EDIT BY HAND) that
 * ships everything inside @layer reset/primitives/tokens/base/layout/
 * components/utilities. It is linked BEFORE this file.
 *
 * This file is PLAIN, UNLAYERED CSS on purpose: unlayered declarations beat
 * every layered rule in globals.css regardless of specificity, so site chrome +
 * the section component library here always win over the framework without any
 * @layer wrapper or specificity fights. (Earlier revisions wrapped this in
 * `@layer custom` — removed; unlayered is simpler and gives the same override.)
 *
 * Vocabulary: ACSS semantic tokens from globals.css (--primary*, --surface*,
 * --text*, --space-*, --text-*, --h*, --radius-*, --border …). Brand-local
 * tokens below cover the few roles the perceptual ramp can't express (neon
 * teal CTA, near-black ink, rating gold, on-dark whites, shadows, gradient).
 */

/* ===== brand-local tokens (roles the ACSS ramp can't reproduce) ===== */
:root {
  --ink: var(--clr-base-950);              /* indigo-black — footer, dark text */
  --teal: oklch(89% 0.17 170);             /* exact Wamo neon mint (CTA)    */
  --teal-hover: oklch(82% 0.17 170);
  --on-dark: oklch(100% 0 0);
  --on-dark-soft: oklch(100% 0 0 / 0.86);
  --gold: oklch(88.7% 0.182 95);           /* rating stars                  */
  --shadow-card: 0 1px 2px oklch(from var(--ink) l c h / 0.06),
                 0 10px 30px oklch(from var(--ink) l c h / 0.10);
  --shadow-raise: 0 18px 50px oklch(from var(--ink) l c h / 0.22);
  --shadow-lift: 0 1px 2px oklch(from var(--ink) l c h / 0.05),
                 0 14px 34px oklch(from var(--ink) l c h / 0.11);  /* cards floating on tinted bands */
  --hero-grad: linear-gradient(150deg, var(--clr-primary-600), var(--clr-primary-800));

  /* ---- heading scale override (REVERSIBLE) ----
     The generated globals.css scale tops out too large on desktop (h2 maxed
     at 4.68rem). Recomputed here with a consistent ~1.28 per-step ratio
     anchored at h2 max = 3.328rem. Each heading keeps its ORIGINAL min +
     fluid slope (so mobile sizes are unchanged); only the desktop cap drops.
     Body text (--text-*) is deliberately untouched. globals.css is left
     pristine — delete this block to restore the original scale. */
  --h1: clamp(3.2973rem, 2.2658rem + 4.4011vw, 4.2601rem);
  --h2: clamp(2.7027rem, 2.0059rem + 2.9732vw, 3.3282rem);
  --h3: clamp(2.2153rem, 1.7559rem + 1.9603vw, 2.6001rem);
  --h4: clamp(1.8158rem, 1.5233rem + 1.2483vw, 2.0313rem);
  --h5: clamp(1.4884rem, 1.3118rem + 0.7536vw, 1.5870rem);
  --h6: clamp(1.2200rem, 1.1227rem + 0.4150vw, 1.2399rem);
}

body { background: var(--surface); }

/* Wider content container than the engine default (full = 90rem vs globals'
   75rem) with a tighter fluid gutter (1rem → 2.25rem) instead of --space-l, so
   phones get edge-to-edge breathing room and desktop runs fuller-width. Set on
   :root (NOT on .container) so the .container--narrow / .container--full
   modifiers keep overriding --width-wide per element; this unlayered .container
   width just swaps the engine's --space-l gutter for --gutter. */
:root { --gutter: clamp(1rem, 4vw, 2.25rem); --width-wide: var(--width-full); }
.container { width: min(100% - (var(--gutter) * 2), var(--width-wide)); }

/* heavier display headings (Montserrat 800) to echo Wamo's Agrandir weight */
h1, h2, h3 { font-weight: 800; letter-spacing: -0.01em; }

/* ===== buttons ===== */
.button {
  font-family: var(--font-secondary); font-weight: 700; letter-spacing: 0.005em;
  padding: var(--space-xs) var(--space-l); border-radius: var(--radius-pill);
  background: var(--teal); color: var(--ink); border: 2px solid transparent;
  line-height: 1.1; text-decoration: none;
}
.button:hover { background: var(--teal-hover); }
.button--lg { padding: var(--space-s) var(--space-m); font-size: var(--text-l); }
.button--purple { background: var(--primary); color: var(--on-dark); }
.button--purple:hover { background: var(--primary-hover); }
.button--ghost { background: transparent; color: var(--primary); border-color: currentColor; }
.button--ghost:hover { background: var(--primary-trans-10); }
.button--on-dark { color: var(--on-dark); border-color: oklch(100% 0 0 / 0.4); background: transparent; }
.button--on-dark:hover { background: oklch(100% 0 0 / 0.12); }
/* "Sonar-ping" pulse for the primary conversion CTAs (global header + hero),
   copied from the ibramuscarpentry chat-fab: a teal clone of the button sits
   BEHIND it (z-index:-1, same pill radius) and blooms outward while fading,
   then rests for 30% of the cycle — that hold is what gives the calm heartbeat
   rhythm rather than constant breathing. Scoped to the modifier; off under
   reduced-motion. (position:relative on the button anchors the clone; the
   button's own opaque bg masks the clone's centre so only the ring shows.) */
.button--pulse { position: relative; }
/* Double ripple driven by an expanding box-shadow (not transform:scale) so it
   grows EQUALLY on every side — a scaled wide pill only stretches left/right,
   whereas box-shadow spread adds the same px all around and follows the pill
   radius. Two pseudos stagger for a primary ring + fainter echo; --pulse-o
   sets each ring's start alpha. Small spread keeps it tight and close to the
   button. Off under reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
  .button--pulse::before,
  .button--pulse::after {
    content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
    border-radius: inherit;
    animation: cta-pulse 2.6s cubic-bezier(0.2, 0.6, 0.2, 1) infinite;
  }
  .button--pulse::before { --pulse-o: 0.55; }
  .button--pulse::after  { --pulse-o: 0.32; animation-delay: 0.4s; }
}
/* The ring must reach peak alpha AFTER it has emerged a few px past the button
   edge — peaking at spread 0 (the obvious way) hides the brightest moment
   behind the button, leaving only a faint already-fading sliver. So: start
   invisible, ramp to a visible soft ring at 20%, then expand + fade, then rest. */
@keyframes cta-pulse {
  0%   { box-shadow: 0 0 0 0      oklch(89% 0.17 170 / 0); }
  20%  { box-shadow: 0 0 5px 5px   oklch(89% 0.17 170 / var(--pulse-o, 0.55)); }
  75%  { box-shadow: 0 0 10px 15px oklch(89% 0.17 170 / 0); }
  100% { box-shadow: 0 0 10px 15px oklch(89% 0.17 170 / 0); }
}

/* ===== site header (sticky, purple) ===== */
.site-header {
  position: sticky; inset-block-start: 0; z-index: 50;
  background: oklch(from var(--primary-dark) l c h / 0.92);
  backdrop-filter: blur(12px);
  border-block-end: 1px solid oklch(100% 0 0 / 0.12);
}
.site-header__bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: var(--space-m); padding-block: var(--space-xs); flex-wrap: wrap;
}
.site-logo img { height: clamp(3.7rem, 4.2vw, 4.9rem); width: auto; }
/* gap is a BOUNDED token (caps at --space-m = 1.5rem): the header is a fixed
   wide .container, so a fluid/vw gap balloons on ultrawide and overflows
   the FI nav (longer labels) onto a 2nd row. --space-m gives breathing room
   without growing past the budget. */
.site-nav ul { display: flex; gap: var(--space-m); list-style: none; flex-wrap: wrap; align-items: center; }
.site-nav a { text-decoration: none; font-weight: 600; color: var(--on-dark-soft); transition: color 0.15s ease; }
.site-nav a:hover, .site-nav a[aria-current="page"] { color: var(--on-dark); }
.site-header__cta { display: flex; gap: var(--space-s); align-items: center; }
/* phones: tighten the bar gap + compact the CTA so the bigger logo + CTA + burger fit one row */
@media (width < 30rem) {
  .site-header__bar { gap: var(--space-s); }
  .site-header__cta .button { padding-inline: var(--space-s); font-size: var(--text-s); }
}
/* very small phones only: below this the logo + CTA + burger stop fitting on one row */
@media (width < 24rem) { .site-header__cta { display: none; } }

/* CSS-only nav: inline on desktop, checkbox-toggled hamburger dropdown on mobile */
.nav-toggle { position: absolute; opacity: 0; pointer-events: none; }  /* a11y-friendly hide */
.nav-burger { display: none; }
/* Inline nav only when logo + 5 long FI labels + CTA genuinely fit (wide container);
   below that the labels would shove the CTA onto a 2nd row, so switch to the hamburger. */
@media (width < 75rem) {
  /* push logo left, group controls right; CTA before the hamburger so burger stays rightmost */
  .site-logo { margin-inline-end: auto; }
  .site-header__cta { order: 1; }
  .nav-burger {
    display: grid; place-items: center; cursor: pointer; order: 2;
    inline-size: 2.75rem; block-size: 2.75rem; border-radius: var(--radius-m);
    border: 1px solid oklch(100% 0 0 / 0.3);
  }
  .nav-burger span, .nav-burger span::before, .nav-burger span::after {
    content: ""; display: block; inline-size: 1.1rem; block-size: 2px; background: var(--on-dark);
    transition: transform 0.2s ease, background 0.2s ease;
  }
  .nav-burger span::before { transform: translateY(-6px); }
  .nav-burger span::after  { transform: translateY(4px); }
  .nav-toggle:checked ~ .nav-burger span { background: transparent; }
  .nav-toggle:checked ~ .nav-burger span::before { transform: rotate(45deg); }
  .nav-toggle:checked ~ .nav-burger span::after  { transform: rotate(-45deg) translate(3px, -3px); }
  .nav-toggle:focus-visible ~ .nav-burger { outline: 2px solid var(--teal); outline-offset: 2px; }
  .site-nav {
    position: absolute; inset-inline: 0; inset-block-start: 100%; display: none;
    background: var(--primary-dark); padding: var(--space-m) var(--space-l) var(--space-l);
    border-block-end: 1px solid oklch(100% 0 0 / 0.12); box-shadow: var(--shadow-card);
  }
  .nav-toggle:checked ~ .site-nav { display: block; }
  .site-nav ul { flex-direction: column; align-items: flex-start; gap: var(--space-m); }
  .site-nav a { font-size: var(--text-l); }
}

/* ≤450px the bar gets cramped (the logo scales up + FI/SV), so the "Pyydä
   tarjous" CTA leaves the header bar and becomes the LAST item in the
   hamburger menu. display-toggled (not just visually hidden) so only one CTA
   is ever in the a11y tree / tab order — no duplicate focus target. */
.site-nav__cta { display: none; }
@media (width <= 28.125rem) {                 /* 450px (rem-based: respects zoom) */
  .site-header__cta .button--pulse { display: none; }   /* CTA leaves the bar */
  .site-nav__cta { display: block; }                    /* ...and joins the menu, last */
  .site-nav__cta .button,
  .site-nav__cta .button:hover { color: var(--ink); }   /* beat `.site-nav a` colour */
  .site-nav__cta .button:focus-visible { outline: 2px solid var(--on-dark); outline-offset: 2px; }
}

/* ===== section rhythm ===== */
.section { padding-block: var(--section-space); }
.section--lg { padding-block: calc(var(--section-space) * 1.35); }
.section--ink { background: var(--ink); color: var(--on-dark); }
.section--purple { background: var(--hero-grad); color: var(--on-dark); }
/* legible focus ring on dark/purple surfaces (global ring is purple = invisible there) */
.site-header :focus-visible, .site-footer :focus-visible, .hero :focus-visible,
.page-hero :focus-visible, .section--purple :focus-visible, .section--ink :focus-visible { outline-color: var(--teal); }
/* skip-to-content link: hidden until focused */
.skip-link {
  position: absolute; inset-block-start: var(--space-s); inset-inline-start: var(--space-s); z-index: 2000;
  background: var(--ink); color: var(--on-dark); padding: var(--space-2xs) var(--space-m);
  border-radius: var(--radius-m); font-weight: 700; text-decoration: none;
  transform: translateY(-200%); transition: transform 0.18s ease;
}
.skip-link:focus { transform: translateY(0); }
main:focus { outline: none; }
/* tinted bands: a clearly-perceptible soft-lavender plane (≈2.4% darker than the
   page --surface, chroma lifted ~4x) so alternating sections read as distinct
   planes instead of one near-white field. Derived from --surface so it tracks
   light/dark mode; dark-on-light text keeps AAA contrast. */
.section--tint, .section--steps { background: oklch(from var(--surface) calc(l - 0.024) 0.032 286); }
/* pure white (vs the off-white page --surface) so adjacent plain sections don't bleed together */
.section--white { background: var(--surface-raised); }
/* hairline edge between any two ADJACENT LIGHT sections so plain-on-plain and
   white-on-plain runs still get a crisp boundary. Suppressed next to the dark
   purple/ink sections (those edges are already high-contrast). */
.section + .section { border-block-start: 1px solid var(--border); }
.section--ink + .section, .section--purple + .section,
.section + .section--ink, .section + .section--purple { border-block-start: 0; }
/* cards lift a touch so they read as floating on the tinted bands */
.feature, .factor, .review { box-shadow: var(--shadow-lift); }
.section__head { max-width: 50rem; margin-inline: auto; text-align: center; margin-block-end: var(--space-2xl); }
.section__head .lead { margin-block-start: var(--space-s); }
.eyebrow {
  display: inline-block; font-family: var(--font-secondary); font-weight: 700;
  font-size: var(--text-xs); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--primary-dark); margin-block-end: var(--space-2xs);
}
.section--purple .eyebrow, .section--ink .eyebrow { color: var(--teal); }
.lead { font-size: var(--text-l); color: var(--text-soft); text-wrap: pretty; }
.section--purple .lead, .section--ink .lead { color: var(--on-dark-soft); }
.text-teal { color: var(--teal); }

/* ===== hero ===== */
.hero { position: relative; background: var(--hero-grad); color: var(--on-dark); overflow: clip; container-type: inline-size; }
/* Faint hand-sketch watermark, bottom-left. v3 source is already brand-cyan
   line-art on a transparent bg, so no filter needed; opacity keeps it a
   whisper behind the copy. pointer-events:none + low z so it never catches
   clicks or fights the text. */
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: url("img/hero-sketch-v3.webp") no-repeat left bottom;
  background-size: 67rem;   /* intentionally large: stays big + abstract on mobile too */
  opacity: 0.16;
  bottom: -8rem;            /* bleed below the hero (clipped) so the car sits low */
}
/* "drives in": reveal the sketch left→right (the car faces right) with a small
   slide, so it reads as the car rolling into frame. Static for reduced-motion. */
@media (prefers-reduced-motion: no-preference) {
  .hero::before {
    animation: hero-sketch-drive 1.8s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s both;
  }
}
@keyframes hero-sketch-drive {
  from { clip-path: inset(0 100% 0 0); transform: translateX(-4rem); opacity: 0; }
  to   { clip-path: inset(0 0 0 0);    transform: translateX(0);     opacity: 0.16; }
}
/* lift the real content above the watermark */
.hero > .container { position: relative; z-index: 1; }

/* ===== section line-art car watermarks (echo the hero "drives in" sketch) =====
   One uniform-alpha asset per car (the webp IS an alpha mask: strokes opaque,
   rest transparent). CSS mask tints it per section — purple on light surfaces,
   teal on the dark ink section — so a single asset adapts. The car "drives in"
   when its section scrolls into view (scroll-driven view() timeline); browsers
   without that, or reduced-motion users, just get the faint static sketch. */
.section--sk-crashed, .section--sk-van,
.section--sk-tow, .section--sk-wagon, .section--sk-suv { position: relative; overflow: clip; }
.section--sk-crashed > .container, .section--sk-van > .container,
.section--sk-tow > .container, .section--sk-wagon > .container, .section--sk-suv > .container { position: relative; z-index: 1; }
.section--sk-crashed::after, .section--sk-van::after,
.section--sk-tow::after, .section--sk-wagon::after, .section--sk-suv::after {
  content: ""; position: absolute; z-index: 0; pointer-events: none;
  inline-size: var(--sk-w); aspect-ratio: var(--sk-ar);
  inset-block-end: var(--sk-b, -3rem);
  background-color: var(--sk-tint);
  -webkit-mask: var(--sk-src) no-repeat bottom / contain;
          mask: var(--sk-src) no-repeat bottom / contain;
  opacity: var(--sk-o);
}
/* crashed sedan: purple, faces right, enters from the LEFT (like the hero) */
.section--sk-crashed::after {
  --sk-src: url("img/sketch-crashed.webp"); --sk-tint: var(--primary);
  --sk-ar: 720 / 340; --sk-w: clamp(22rem, 50vw, 44rem); --sk-o: 0.07;
  inset-inline-start: clamp(-4rem, -5vw, -2rem);
}
/* delivery van: teal, faces left, enters from the RIGHT of the dark section */
.section--sk-van::after {
  --sk-src: url("img/sketch-van.webp"); --sk-tint: var(--teal);
  --sk-ar: 720 / 415; --sk-w: clamp(19rem, 42vw, 38rem); --sk-o: 0.13;
  inset-inline-end: clamp(-4rem, -5vw, -2rem);
}
/* flatbed tow truck: purple, faces left, enters from the RIGHT (the "nouto") */
.section--sk-tow::after {
  --sk-src: url("img/sketch-tow.webp"); --sk-tint: var(--primary);
  --sk-ar: 720 / 326; --sk-w: clamp(24rem, 54vw, 48rem); --sk-o: 0.06;
  inset-inline-end: clamp(-4rem, -5vw, -2rem);
}
/* estate wagon: purple, faces right, enters from the LEFT */
.section--sk-wagon::after {
  --sk-src: url("img/sketch-wagon.webp"); --sk-tint: var(--primary);
  --sk-ar: 720 / 242; --sk-w: clamp(22rem, 50vw, 44rem); --sk-o: 0.06;
  inset-inline-start: clamp(-4rem, -5vw, -2rem);
}
/* SUV / 4x4: purple, faces left, enters from the RIGHT */
.section--sk-suv::after {
  --sk-src: url("img/sketch-suv.webp"); --sk-tint: var(--primary);
  --sk-ar: 720 / 330; --sk-w: clamp(20rem, 46vw, 40rem); --sk-o: 0.06;
  inset-inline-end: clamp(-4rem, -5vw, -2rem);
}
/* on a dark band the purple stroke would vanish — switch the tint to teal
   (like the van on the ink section) and lift opacity so it reads */
.section--purple.section--sk-tow::after, .section--ink.section--sk-tow::after,
.section--purple.section--sk-wagon::after, .section--ink.section--sk-wagon::after,
.section--purple.section--sk-suv::after, .section--ink.section--sk-suv::after,
.section--purple.section--sk-crashed::after, .section--ink.section--sk-crashed::after {
  --sk-tint: var(--teal); --sk-o: 0.12;
}
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .section--sk-crashed::after,
    .section--sk-wagon::after   { animation: sk-drive-ltr linear both; animation-timeline: view(); animation-range: entry 0% cover 35%; }
    .section--sk-van::after,
    .section--sk-tow::after,
    .section--sk-suv::after     { animation: sk-drive-rtl linear both; animation-timeline: view(); animation-range: entry 0% cover 35%; }
  }
}
@keyframes sk-drive-ltr {
  from { clip-path: inset(0 100% 0 0); transform: translateX(-2rem); opacity: 0; }
  to   { clip-path: inset(0 0 0 0);    transform: translateX(0);     opacity: var(--sk-o); }
}
@keyframes sk-drive-rtl {
  from { clip-path: inset(0 0 0 100%); transform: translateX(2rem); opacity: 0; }
  to   { clip-path: inset(0 0 0 0);    transform: translateX(0);    opacity: var(--sk-o); }
}
.hero__inner { display: grid; gap: var(--space-2xl); align-items: center; padding-block: var(--section-space); grid-template-columns: 1fr; }
@container (min-width: 56rem) { .hero__inner { grid-template-columns: 1.55fr 0.95fr; } }
/* Fluid hero headline, scaling across 360px → 1440px (the viewport range the
   global --h1 token itself spans). Endpoints match the brief exactly:
     360px : --h1 floor 3.2973rem × 0.56 = 1.8465rem, line-height 1.22
     1440px: capped at 4.5rem (trimmed from the 4.9814rem ceiling), line-height ~5.08rem
   The vw slope is unchanged, so the cap just clamps the top end sooner.
   line-height is set as a LENGTH so it can interpolate (a unitless
   line-height can't carry a vw term); it holds flat outside the range. */
.hero h1 {
  font-size: clamp(1.8465rem, 0.8015rem + 4.6443vw, 4.15rem);
  line-height: clamp(2.2527rem, 1.3099rem + 4.1901vw, 5.0811rem);
  text-wrap: balance;
}
.hero h1 .accent { color: var(--teal); }
.hero__lead { margin-block: var(--space-m) var(--space-l); max-width: 40ch; color: var(--on-dark-soft); font-size: var(--text-l); }
.hero__cta { display: flex; flex-wrap: wrap; gap: var(--space-s); }
.badge-pill {
  display: inline-flex; align-items: center; gap: var(--space-2xs);
  background: oklch(100% 0 0 / 0.14); color: var(--on-dark);
  border: 1px solid oklch(100% 0 0 / 0.22);
  padding: var(--space-3xs) var(--space-s); border-radius: var(--radius-pill);
  font-size: var(--text-s); font-weight: 600; margin-block-end: var(--space-m);
}
.badge-pill .dot { inline-size: 0.5rem; block-size: 0.5rem; border-radius: 50%; background: var(--teal); }
.hero__media img { border-radius: var(--radius-l); box-shadow: var(--shadow-raise); }

/* instant-quote widget (hero card) */
.quote-card {
  background: var(--surface-raised); color: var(--text);
  border-radius: var(--radius-l); padding: var(--space-l); box-shadow: var(--shadow-raise);
}
.quote-card h2 { font-size: calc(var(--h4) * 0.7); }
.quote-card p.sub { color: var(--text-soft); font-size: var(--text-s); margin-block-start: var(--space-3xs); }
.quote-card .button { width: 100%; justify-content: center; margin-block-start: var(--space-m); }
.fineprint { font-size: var(--text-2xs); color: var(--text-soft); text-align: center; margin-block-start: var(--space-2xs); }
.formerror { background: oklch(62% 0.2 25 / 0.12); color: oklch(45% 0.18 25); border: 1px solid oklch(62% 0.2 25 / 0.35); border-radius: var(--radius-m); padding: var(--space-s) var(--space-m); margin-block-end: var(--space-m); font-weight: 600; }

/* ===== form fields ===== */
.field { display: grid; gap: var(--space-3xs); margin-block-start: var(--space-m); }
.field label { font-weight: 600; font-size: var(--text-s); }
.field input, .field select, .field textarea {
  inline-size: 100%; /* fill the grid column — appearance:none selects size to content otherwise */
  border: 1px solid var(--border); border-radius: var(--radius-m);
  padding: var(--space-2xs) var(--space-s); background: var(--surface); font-size: var(--text-m);
  line-height: 1.6; /* lock height so native selects match text inputs (was 36.7 vs 42.5px) */
  transition: border-color 0.18s ease, box-shadow 0.18s ease, background 0.18s ease;
}
/* selects: kill native chrome so they match inputs exactly + custom chevron */
.field select {
  appearance: none; -webkit-appearance: none;
  padding-inline-end: var(--space-xl);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' viewBox='0 0 16 16' fill='none' stroke='%236b7280' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 6l4 4 4-4'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right var(--space-s) center; background-size: 0.7em auto;
}
.field input:focus, .field select:focus, .field textarea:focus {
  border-color: var(--primary); box-shadow: 0 0 0 3px oklch(from var(--primary) l c h / 0.2); outline: none;
}
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible { outline: 2px solid var(--primary); outline-offset: 1px; }
.field input:user-invalid { outline: 2px solid var(--danger); outline-offset: 1px; }
.field input[type="checkbox"] { accent-color: var(--primary); }
.field--plate input { text-transform: uppercase; letter-spacing: 0.12em; font-weight: 700; font-family: var(--font-mono); }

/* ===== trust ticker (scrolling marquee) ===== */
.ticker { background: #271c60 /* sRGB mirror of --clr-primary-900; oklch() breaks contrast scanners, real ratio 14.8:1 */; color: var(--on-dark); overflow: clip; padding-block: var(--space-s); }
.ticker__track { display: flex; gap: 0; width: max-content; animation: ticker-scroll 38s linear infinite; }
.ticker__group { display: flex; gap: 0; }
.ticker__item { display: inline-flex; align-items: center; gap: var(--space-2xs); padding-inline: var(--space-xl); font-weight: 600; white-space: nowrap; background: #271c60; /* seamless purple per-item so contrast scanners sample it directly (track overflows .ticker) */ }
.ticker__item b, .ticker__item .hl { color: var(--teal); font-weight: 800; }
.ticker__item::before { content: "•"; color: var(--teal); opacity: 0.6; }
@keyframes ticker-scroll { to { transform: translateX(-50%); } }
@media (prefers-reduced-motion: reduce) {
  .ticker__track { animation: none; flex-wrap: wrap; width: auto; justify-content: center; }
}

/* ===== reviews strip (Trustpilot-style) ===== */
.ratingbar { display: flex; flex-wrap: wrap; gap: var(--space-l) var(--space-2xl); align-items: center; justify-content: center; }
.rating { text-align: center; }
.rating__score { font-family: var(--font-secondary); font-weight: 800; font-size: var(--h4); }
.ratingbar + .lead { text-align: center; max-inline-size: 60ch; margin-inline: auto; margin-block-start: var(--space-m); }
.stars { color: var(--gold); letter-spacing: 0.08em; font-size: var(--text-l); }
.ministrip { display: grid; gap: var(--space-l); grid-template-columns: repeat(auto-fit, minmax(min(15rem,100%),1fr)); }
.ministrip__item .stars { font-size: var(--text-m); }
.ministrip__item b { display: block; margin-block: var(--space-3xs); }
.ministrip__item p { color: var(--text-soft); font-size: var(--text-s); }
.ministrip__item span { color: var(--text-soft); font-size: var(--text-xs); }

/* ===== feature cards ===== */
.cardgrid { display: grid; gap: var(--space-l); grid-template-columns: 1fr; }
@media (width >= 40rem) { .cardgrid { grid-template-columns: repeat(2, 1fr); } }
@media (width >= 64rem) { .cardgrid { grid-template-columns: repeat(3, 1fr); } }
/* icon-card: tinted icon box + radial background reveal that spreads from the
   icon centre on hover/focus, so the icon box blends into the filling card.
   Shared by .feature and .factors--3 .factor (origin tracks the icon centre). */
.icon-card, .feature, .factors--3 .factor {
  position: relative; isolation: isolate; overflow: clip;
  transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
  --reveal-origin: calc(var(--space-l) + 2.25rem);
}
/* feature cards carry their own padding/radius/border so the hover reveal
   (the ::before fill, clipped by overflow:clip) shows rounded corners with
   breathing room around the content. padding matches --reveal-origin. */
.feature, .icon-card {
  padding: var(--space-l);
  border: 1px solid var(--primary-trans-30);
  border-radius: var(--radius-l);
}
.feature::before, .factors--3 .factor::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: var(--primary-trans-10);
  clip-path: circle(0% at var(--reveal-origin) var(--reveal-origin));
  transition: clip-path 0.5s cubic-bezier(0.4, 0, 0.2, 1);
}
.feature:hover, .feature:has(a:focus-visible),
.factors--3 .factor:hover {
  transform: translateY(-2px);
  border-color: var(--primary-trans-30);
}
.feature:hover::before, .feature:has(a:focus-visible)::before,
.factors--3 .factor:hover::before {
  clip-path: circle(150% at var(--reveal-origin) var(--reveal-origin));
}
/* on reveal, drop the icon box's own tint so it merges into the filled card */
.feature:hover .feature__icon, .feature:has(a:focus-visible) .feature__icon,
.factors--3 .factor:hover .ico { background: transparent; }
.feature__img { aspect-ratio: 16/10; object-fit: cover; border-radius: var(--radius-m); margin-block-end: var(--space-m); width: 100%; }
.feature__icon {
  display: grid; place-items: center; inline-size: 4.5rem; block-size: 4.5rem;
  margin-block-end: var(--space-s);
}
.feature__icon img { inline-size: 100%; block-size: 100%; object-fit: contain; }
.feature h3 { font-size: var(--text-l); text-wrap: balance; hyphens: none; }
/* whole-card link: anchor lives on the title, ::after stretches over the card
   so the entire card is clickable but only ONE focus stop per card */
.feature h3 a { color: inherit; text-decoration: none; }
.feature h3 a::after { content: ""; position: absolute; inset: 0; z-index: 1; border-radius: var(--radius-l); }
.feature h3 a:focus-visible { outline: none; }
.feature:has(a:focus-visible) { outline: 2px solid var(--primary); outline-offset: 2px; }
.feature p { color: var(--text-soft); margin-block-start: var(--space-2xs); }
.feature .more { display: inline-flex; align-items: center; gap: var(--space-3xs); margin-block-start: var(--space-s); color: var(--primary); font-weight: 700; text-decoration: none; }
.feature:hover .more { gap: var(--space-2xs); }
/* anchor-variant card: whole <a class="feature"> is the link (used in hub +
   related grids). Reset link chrome so the text reads like the article variant. */
a.feature { display: block; text-decoration: none; color: inherit; }
a.feature h3 { color: var(--ink); }
/* linkable price-factor card (hinta-arvio hub). Same reveal treatment as
   .factor already gets via the shared .factors--3 .factor rules above. */
a.factor { display: block; text-decoration: none; color: inherit; }
a.factor h3 { color: var(--ink); }
a.factor .more { display: inline-flex; align-items: center; gap: var(--space-3xs); margin-block-start: var(--space-s); color: var(--primary); font-weight: 700; }
a.factor:hover .more { gap: var(--space-2xs); }

/* ===== split feature band (image + checklist) ===== */
.split { display: grid; gap: var(--space-2xl); align-items: start; grid-template-columns: 1fr; }
@media (width >= 52rem) { .split { grid-template-columns: 1fr 1fr; } .split--media-first .split__media { order: -1; } }
.split__media img { border-radius: var(--radius-l); box-shadow: var(--shadow-card); }
.section--purple .split__media img, .section--ink .split__media img { box-shadow: var(--shadow-raise); }
.checklist { list-style: none; padding-inline-start: 0; margin-inline: 0; display: grid; gap: var(--space-s); margin-block-start: var(--space-l); }
.checklist li { display: grid; grid-template-columns: auto 1fr; gap: var(--space-s); align-items: start; }
.checklist .ico {
  display: grid; place-items: center; inline-size: 1.6rem; block-size: 1.6rem;
  border-radius: var(--radius-circle); background: var(--teal); color: var(--ink);
  font-size: var(--text-s); font-weight: 800; margin-block-start: 0.15em;
}
.checklist strong { display: block; }
.checklist div span { color: var(--text-soft); font-size: var(--text-s); }
.section--purple .checklist div span, .section--ink .checklist div span { color: var(--on-dark-soft); }

/* ===== two-audience cards ===== */
.duo { display: grid; gap: var(--space-l); grid-template-columns: repeat(auto-fit, minmax(min(18rem,100%),1fr)); }
.duo__card {
  background: oklch(100% 0 0 / 0.08); border: 1px solid oklch(100% 0 0 / 0.18);
  border-radius: var(--radius-l); padding: var(--space-xl); color: var(--on-dark);
}
.duo__card h3 { font-size: var(--h4); }
.duo__card p { color: var(--on-dark-soft); margin-block: var(--space-s) var(--space-l); }

/* ===== process steps ===== */
.steps { display: grid; gap: var(--space-xl); grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr)); }
.step__card { background: oklch(100% 0 0 / 0.07); border: 1px solid oklch(100% 0 0 / 0.16); border-radius: var(--radius-l); padding: var(--space-l); }
.step__n {
  display: grid; place-items: center; inline-size: 2.75rem; block-size: 2.75rem;
  border-radius: var(--radius-circle); background: var(--teal); color: var(--ink);
  font-family: var(--font-secondary); font-weight: 800; font-size: var(--text-l);
  margin-block-end: var(--space-s);
}
.step__card h3 { font-size: var(--h5); }
.step__card p { color: var(--on-dark-soft); margin-block-start: var(--space-2xs); }
/* light/inverted variant: same cards on a light section (under the hero).
   The hero+ticker above are already purple, so this block reads as solid
   surface cards with dark text. The teal number disc works on both. */
.steps--light .step__card { background: var(--surface-raised); border-color: var(--border); box-shadow: var(--shadow-lift); }
.steps--light .step__card h3 { color: var(--ink); }
.steps--light .step__card p { color: var(--text-soft); }

/* ===== testimonials ===== */
.reviews { display: grid; gap: var(--space-l); grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr)); }
.review { background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius-l); padding: var(--space-l); display: flex; flex-direction: column; gap: var(--space-s); }
.review blockquote { text-wrap: pretty; font-size: var(--text-l); }
.review__who { display: flex; align-items: center; gap: var(--space-s); margin-block-start: auto; text-align: start; }
.review__avatar { inline-size: 3rem; block-size: 3rem; border-radius: var(--radius-circle); object-fit: cover; flex: none; }
.review__avatar.is-initials { display: grid; place-items: center; background: var(--primary-dark); color: var(--on-dark); font-family: var(--font-secondary); font-weight: 800; }
.review__name { font-weight: 700; }
.review__loc { color: var(--text-soft); font-size: var(--text-s); }

/* ===== valuation factors (replaces Wamo pricing tiers) ===== */
.factors { display: grid; gap: var(--space-l); grid-template-columns: repeat(auto-fit, minmax(min(15rem,100%),1fr)); }
.factor { background: var(--surface-raised); border: 1px solid var(--border); border-radius: var(--radius-l); padding: var(--space-l); }
.factor .ico { font-size: var(--text-2xl); }
/* image icons (brand line-art): no tinted box, no padding so the icon reads
   bigger; sits straight on the white card (these factor cards aren't links,
   so there's no hover-reveal state to merge into). */
.factor .ico:has(img) { inline-size: 4.5rem; block-size: 4.5rem; margin-block-end: var(--space-s); }
.factor .ico img { inline-size: 100%; block-size: 100%; object-fit: contain; }
/* explicit ink: .factor cards are always white (--surface-raised), so inside a
   section--ink the heading would inherit white-on-white and vanish. */
.factor h3 { color: var(--ink); font-size: var(--text-m); text-wrap: balance; hyphens: none; margin-block: var(--space-2xs); }
.factor p { color: var(--text-soft); font-size: var(--text-s); }
/* 6-item factor grid: 3 columns / 2 rows, with line-art icons */
.factors--3 { grid-template-columns: 1fr; }
@media (width >= 40rem) { .factors--3 { grid-template-columns: repeat(2, 1fr); } }
@media (width >= 64rem) { .factors--3 { grid-template-columns: repeat(3, 1fr); } }
.factors--3 .ico {
  display: grid; place-items: center; inline-size: 4.5rem; block-size: 4.5rem;
  margin-block-end: var(--space-s);
}
.factors--3 .ico img { inline-size: 100%; block-size: 100%; object-fit: contain; }

/* ===== FAQ (native exclusive accordion) ===== */
.faq { max-width: var(--width-narrow); margin-inline: auto; display: grid; gap: var(--space-s); }
.faq details { border: 1px solid var(--border); border-radius: var(--radius-m); background: var(--surface-raised); overflow: clip; }
.faq summary { cursor: pointer; list-style: none; padding: var(--space-m) var(--space-l); font-weight: 700; font-family: var(--font-secondary); display: flex; justify-content: space-between; align-items: center; gap: var(--space-m); }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--primary); font-size: var(--text-xl); line-height: 1; transition: rotate 0.2s ease; }
.faq details[open] summary::after { rotate: 45deg; }
.faq details > div { padding: 0 var(--space-l) var(--space-m); color: var(--text-soft); text-wrap: pretty; }
/* smooth open/close: animate ::details-content height 0<->auto (the panels are an
   exclusive group via name="faq", so opening one slides the previous one shut just
   as smoothly). Progressive enhancement — browsers without ::details-content /
   interpolate-size, and reduced-motion users, fall back to the native instant
   toggle. interpolate-size unlocks transitioning to the intrinsic (auto) height. */
@media (prefers-reduced-motion: no-preference) {
  :root { interpolate-size: allow-keywords; }
  .faq details::details-content {
    block-size: 0; overflow: clip;
    transition: block-size 0.34s ease, content-visibility 0.34s ease;
    transition-behavior: allow-discrete;
  }
  .faq details[open]::details-content { block-size: auto; }
}

/* ===== full lead form ===== */
.formcard { max-width: var(--width-narrow); margin-inline: auto; }
.leadform { display: grid; gap: var(--space-m) var(--space-m); grid-template-columns: repeat(auto-fit, minmax(min(14rem, 100%), 1fr)); }
.leadform .field { margin-block-start: 0; }
.leadform .field--wide { grid-column: 1 / -1; }
.leadform .button { grid-column: 1 / -1; justify-content: center; }

/* ===== closing CTA band ===== */
/* the closing CTA is a centered card on a plain section that usually follows
   another plain section, so the two light planes blend. Give the wrapping
   section its own accent: a soft-lavender tint plane (matching --tint) plus a
   gentle brand glow radiating from behind the card, and lift the card with a
   shadow so it reads as a distinct, floating focal point. */
.section:has(> .container > .cta-band) {
  background:
    radial-gradient(75% 130% at 50% 50%, var(--primary-trans-10) 0%, transparent 68%),
    oklch(from var(--surface) calc(l - 0.024) 0.032 286);
}
.cta-band { position: relative; border-radius: var(--radius-l); overflow: clip; isolation: isolate; padding: calc(var(--section-space) * 1.1) var(--space-xl); color: var(--on-dark); box-shadow: var(--shadow-raise); }
.cta-band img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: -2; }
.cta-band::after { content: ""; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, oklch(from var(--clr-primary-900) l c h / 0.92), oklch(from var(--clr-primary-800) l c h / 0.6)); }
.cta-band h2 { font-size: var(--h2); max-width: 22ch; }
.cta-band p { color: var(--on-dark-soft); margin-block: var(--space-s) var(--space-l); max-width: 40ch; }

/* ===== footer ===== */
.site-footer { background: var(--ink); color: var(--on-dark-soft); padding-block: var(--section-space) var(--space-xl); border: 0; margin: 0; }
.site-footer a { color: var(--on-dark-soft); text-decoration: none; }
.site-footer a:hover { color: var(--on-dark); }
/* brand + 4 link columns; tighter column-gap (the 5th column for the sell
   pages needs the room) while the row-gap stays generous. */
.footer__grid { display: grid; gap: var(--space-2xl) var(--space-l); grid-template-columns: 2fr repeat(4, 1fr); }
@media (width < 52rem) { .footer__grid { grid-template-columns: repeat(auto-fit, minmax(min(13rem,100%),1fr)); } }
.footer__brand img { height: 3.9rem; width: auto; margin-block-end: var(--space-s); }
.footer__brand p { max-width: 30ch; }
.footer h2 { color: var(--on-dark); font-size: var(--text-m); font-weight: 800; margin-block-end: var(--space-s); }
/* link text one step smaller so 5 columns breathe; balances the denser footer */
.footer ul { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-2xs); font-size: var(--text-s); }
.footer__legal { margin-block-start: var(--space-2xl); padding-block-start: var(--space-l); border-block-start: 1px solid oklch(100% 0 0 / 0.14); font-size: var(--text-s); display: flex; justify-content: space-between; flex-wrap: wrap; gap: var(--space-s); }
.footer__legal-links { display: flex; gap: var(--space-m); flex-wrap: wrap; }

/* ===== HTML sitemap page (/sivukartta) ===== */
.sitemap { display: grid; gap: var(--space-2xl) var(--space-l); grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr)); }
.sitemap__group h2 { font-size: var(--h5); margin-block-end: var(--space-s); text-wrap: balance; }
.sitemap__group ul { list-style: none; padding: 0; margin: 0; display: grid; gap: var(--space-2xs); }
.sitemap__group a { color: var(--primary); font-weight: 600; text-decoration: none; }
.sitemap__group a:hover { text-decoration: underline; }

/* ===== generic prose (subpage body copy) ===== */
.prose { max-width: var(--width-content); margin-inline: auto; }
.prose > * + * { margin-block-start: var(--space-m); }
/* In-body content headings (prose + split copy) sit one step below the section
   display scale, so an h2 inside copy reads as content, not a banner. :is()
   folds both content wrappers into one rule at the exact (0,1,1) specificity
   `.prose h2` always had — so the rhythm interplay with `.prose > * + *` and
   `.split__copy > * + *` is unchanged. Token-driven, no magic sizes. */
:is(.prose, .split__copy) h2 { font-size: var(--h4); text-wrap: balance; hyphens: none; margin-block-start: var(--space-xl); }
:is(.prose, .split__copy) h3 { font-size: var(--h5); text-wrap: balance; hyphens: none; margin-block-start: var(--space-l); }
.prose ul, .prose ol { padding-inline-start: var(--space-l); display: grid; gap: var(--space-2xs); }
.page-hero { position: relative; overflow: clip; background: var(--hero-grad); color: var(--on-dark); padding-block: var(--section-space); }
/* Mirror of the home-hero watermark: same faint cyan sketch, but flipped (the
   car faces left) and anchored bottom-RIGHT, since the inner-page copy sits
   left and the empty space is on the right. Pre-flipped asset (not scaleX) so
   the clip-path wipe + slide stay un-mirrored and read correctly. */
.page-hero::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background: url("img/hero-sketch-v3-flip.webp") no-repeat right bottom;
  background-size: 67rem;
  opacity: 0.16;
  bottom: -8rem;
}
.page-hero > .container { position: relative; z-index: 1; }
/* drives in from the RIGHT: reveal right→left + slide from the right edge */
@media (prefers-reduced-motion: no-preference) {
  .page-hero::before {
    animation: hero-sketch-drive-right 1.8s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s both;
  }
}
@keyframes hero-sketch-drive-right {
  from { clip-path: inset(0 0 0 100%); transform: translateX(4rem); opacity: 0; }
  to   { clip-path: inset(0 0 0 0);    transform: translateX(0);    opacity: 0.16; }
}
.page-hero h1 { font-size: var(--h2); max-width: 25ch; }
.page-hero p { color: var(--on-dark-soft); margin-block-start: var(--space-s); max-width: 50ch; font-size: var(--text-l); }
.page-hero .breadcrumb { font-size: var(--text-s); color: var(--on-dark-soft); margin-block-end: var(--space-s); }
.breadcrumb a { color: var(--on-dark-soft); }

/* ===== blog chrome (subpages/blog reuse) ===== */
.archive-list { list-style: none; }
.archive-item { padding-block: var(--space-s); border-bottom: 1px solid var(--border); }
.archive-item:last-child { border-bottom: 0; }
.archive-item a { text-decoration: none; font-weight: 500; }
.archive-item a:hover { text-decoration: underline; }
.archive-meta { color: var(--text-soft); font-size: var(--text-s); }
.pagination { display: flex; gap: var(--space-m); align-items: center; margin-top: var(--space-xl); font-size: var(--text-s); }
article img, .prose img, figure img { margin-inline: auto; border-radius: var(--radius-m); }
figure { margin-block: var(--space-l); }
figcaption { text-align: center; font-size: var(--text-s); color: var(--text-soft); margin-top: var(--space-xs); }

/* language switcher (header, on the purple bar) */
.lang-switcher { display: flex; gap: var(--space-3xs, 0.25rem); align-items: center; }
.lang-switcher__link {
  font-size: var(--text-s); font-weight: 600; text-decoration: none; line-height: 1;
  color: var(--on-dark-soft); padding: var(--space-2xs) var(--space-xs);
  border-radius: var(--radius-s); transition: color 0.15s ease, background 0.15s ease;
}
.lang-switcher__link:hover { color: var(--on-dark); }
.lang-switcher__link.is-current { color: var(--on-dark); background: oklch(100% 0 0 / 0.14); }
/* footer copy of the switcher: sits under the strapline. The current-language
   chip carries a background, so we flush its BOX (not its text) to the column
   edge — a negative inline margin would make the chip bleed past the edge. */
.footer__brand .lang-switcher { margin-block-start: var(--space-m); }

/* ===== sticky-header-aware anchor scrolling =====
   The header is position:sticky, so a jump to any in-page anchor (#tarjous,
   section ids) must stop BELOW it with breathing room — otherwise the target
   hides under the bar (the bug we saw). --header-h is measured + kept live by
   app.js; the rem fallback keeps no-JS / pre-hydration jumps correct too.
   These unlayered rules override the generic :target rule in globals' reset. */
:root { --header-h: 4.5rem; }
html { scroll-padding-block-start: calc(var(--header-h) + var(--space-l)); }
:target { scroll-margin-block-start: calc(var(--header-h) + var(--space-l)); }
/* Lenis owns the <html> class and strips any it doesn't recognise on every
   scroll-state change (cleanUpClassName regex /lenis(-\w+)?/) — so our custom
   `lenis-on` got wiped on the first scroll, native smooth-scroll reasserted,
   and the browser re-animated every scrollTop Lenis wrote → the dragged/heavy
   feel. Hook Lenis's OWN `lenis` class (permanent) instead. No !important
   needed: this unlayered rule already outranks html{scroll-behavior:smooth} in
   globals' @layer reset (unlayered beats any layer). */
html.lenis { scroll-behavior: auto; }
html.lenis, html.lenis body { height: auto; }

@media (prefers-reduced-motion: reduce) {
  .feature, .faq summary::after, .feature .more,
  .field input, .field select, .field textarea { transition: none; }
}

/* =====================================================================
   SPACING & RHYTHM CONSISTENCY PASS (2026-06-03)
   Production hardening for uniform vertical rhythm across every page.
   The reset zeroes all margins and only .section__head / .prose re-added
   spacing, so any heading placed in a bare wrapper (contact .split__copy,
   etc.) sat flush against the next line → overlap. These rules give a
   token-driven safety net; class-level component margins keep winning on
   specificity, so this only fills the gaps that were 0. All values are
   framework tokens — no magic numbers.
   ===================================================================== */

/* 1) Display headings: 1.05 kissed the next line on wrapping 75px titles.
      1.1 keeps them tight but lets diacritics/descenders breathe. */
:root { --line-height-tight: 1.1; }

/* 2) Rhythm safety net — a heading is never flush against the copy under
      it, in any wrapper. .prose (space-m) and .section__head (space-s)
      out-specify this, so their tuned rhythm is untouched. */
:is(h1, h2, h3, h4, h5, h6) + p,
:is(h1, h2, h3, h4, h5, h6) + .lead,
:is(h1, h2, h3, h4, h5, h6) + ul,
:is(h1, h2, h3, h4, h5, h6) + ol { margin-block-start: var(--space-s); }

/* 3) Consistent eyebrow → heading gap everywhere an eyebrow appears. */
.eyebrow { margin-block-end: var(--space-xs); }
/* an eyebrow labels the heading right below it, so the heading must not push
   away — kills the content-h2 top margin (var(--space-xl)) in that pairing,
   e.g. the contact info column where eyebrow + h2 sit in .split__copy. */
.eyebrow + h2 { margin-block-start: 0; }

/* 4) Section intros: tighter + never floaty. space-2xl (≈98px) under the
      head pushed content into a void; space-xl reads as one unit. Balance
      the title so it doesn't leave a lonely last word. */
.section__head { margin-block-end: var(--space-xl); }
.section__head h2, .section__head h1 { text-wrap: balance; }

/* 5) Split copy column: internal flow so eyebrow/title/lead/list breathe
      evenly (it's a bare grid child with no rhythm of its own). */
.split__copy > * + * { margin-block-start: var(--space-s); }

/* 6) Section padding: trim the ceiling so adjacent full-pad sections don't
      stack into oversized empty bands, while staying generously modern.
      Drives .section, .hero, .page-hero and .cta-band uniformly. */
:root { --section-space: clamp(3.25rem, 2.55rem + 3.05vw, 5.25rem); }
