/* DT Huolto Oy — etusivu. Brief B (docs/design-brief-B-2026-07-31.md) + synthesis grafts G1–G6.
   Style bans in force: tools/bans.txt section C (checked against this file by the sweep).
   Depth comes from surfaces; the only angle on the page is the 73° terminal cut. */

@font-face {
  font-family: 'Big Shoulders';
  src: url(big-shoulders-var.woff2) format('woff2');
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Schibsted Grotesk';
  src: url(schibsted-grotesk-var.woff2) format('woff2');
  font-weight: 400 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Overpass Mono';
  src: url(overpass-mono-600.woff2) format('woff2');
  font-weight: 600; font-style: normal; font-display: swap;
}

:root {
  /* 4.8. de-green (team round: two-shade green combo read as S-ryhmä; photos carried a green
     filter). Ground/surfaces/inks are neutral warm gray, display ink is charcoal — green
     survives ONLY as --green-mid accent hits on light, --green-accent on dark charcoal. */
  --ground: oklch(0.965 0.003 106);
  --surface-1: oklch(0.925 0.005 106);
  --surface-2: oklch(0.885 0.007 106);
  --surface-3: oklch(0.845 0.009 106);
  --ink: oklch(0.29 0.006 106);
  --ink-muted: oklch(0.45 0.008 106);
  --ink-display: oklch(0.25 0.010 106);
  --green-mid: oklch(0.46 0.119 149);
  --green-accent: oklch(0.65 0.136 148);
  --paper: oklch(0.975 0.003 106);
  --state-error: oklch(0.44 0.09 45);

  --f-display: 'Big Shoulders', 'Arial Narrow', sans-serif;
  --f-body: 'Schibsted Grotesk', system-ui, sans-serif;
  --f-mono: 'Overpass Mono', ui-monospace, monospace;

  --t-display: clamp(3.75rem, 9.7vw, 8.75rem);
  /* Brief B §3 gives --t-display: clamp(3.75rem, 9.7vw, 8.75rem). The hero h1 carries two
     extra terms the fold contract forces (brief B §4 authorises the tuning):
     · 15.5vh cap — the fold must FIT on short laptops (1366×635); min-height stretches but
       never shrinks, so the type itself is the compression lever (testing.md 7a).
     · 15.8vw floor — the h1 must hold TWO lines down to 320px. The constraining line is
       JA -KORJAUS. (measured 5.37 × font-size, wider than REKKAHUOLTO's 5.25), so the
       320-2×20px gutter allows at most 52.1px; at 16.4vw it wrapped at the hanging hyphen
       into a third line. */
  --t-h1: clamp(min(15.8vw, 4rem), min(9.7vw, 15.5vh), 8.75rem);
  --t-display-2: clamp(2.5rem, 5.6vw, 4.75rem);
  --t-h2: clamp(2.25rem, 4.5vw, 3.75rem);
  --t-h3: 1.5rem;
  --t-standfirst: clamp(1.125rem, 1.6vw, 1.375rem);
  --t-body: 1.0625rem;
  --t-meta: 0.8125rem;
  --t-field-label: 0.75rem;

  --s1: 8px; --s2: 16px; --s3: 24px; --s4: 40px; --s5: 64px; --s6: 96px; --s7: 128px;
  --gutter: clamp(20px, 4.45vw, 64px);
  --header-h: 76px;
  --btn-h: 48px;
  --cut: 48px;
  /* 4.8. the inner right lane: hero plate geometry, shared by every plate-lane element */
  --lane: clamp(280px, 30vw, 640px);
}

/* --- the 73° terminal cut ------------------------------------------------------------
   Measured off assets/logo/dt-logo.svg (three segments, 73.0° from horizontal):
   horizontal run = 0.306 × vertical run. --cut is the cut's vertical extent; when --cut
   equals the element height the polygon degenerates to brief A §5's full-shear rule. */
.cut-tl { clip-path: polygon(calc(0.306 * var(--cut)) 0, 100% 0, 100% 100%, 0 100%, 0 var(--cut)); }
.cut-tr { clip-path: polygon(0 0, calc(100% - 0.306 * var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%); }
.cut-br { clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - 0.306 * var(--cut)) 100%, 0 100%); }
.cut-bl { clip-path: polygon(0 0, 100% 0, 100% 100%, calc(0.306 * var(--cut)) 100%, 0 calc(100% - var(--cut))); }

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

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

body {
  margin: 0;
  background: var(--ground);
  color: var(--ink);
  font-family: var(--f-body);
  font-size: var(--t-body);
  line-height: 1.6;
  hyphens: auto;
  -webkit-hyphens: auto;
  overflow-x: hidden;
}

h1, h2, h3, p, ol, figure, fieldset { margin: 0; }
ol { list-style: none; padding: 0; }
fieldset { border: 0; padding: 0; min-width: 0; }
legend { padding: 0; }
img, svg { display: block; max-width: 100%; }

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

.svg-defs { position: absolute; width: 0; height: 0; overflow: hidden; }

::selection { background: var(--green-mid); color: var(--paper); }

/* --- skip link ----------------------------------------------------------------------- */
.skip {
  position: absolute; left: var(--s2); top: -200px; z-index: 70;
  background: var(--green-mid); color: var(--paper);
  font-family: var(--f-mono); font-size: var(--t-meta);
  text-transform: uppercase; letter-spacing: 0.08em; text-decoration: none;
  padding: 14px 20px;
}
.skip:focus { top: var(--s2); }

/* --- header -------------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 60;
  height: var(--header-h);
  display: flex; align-items: center; gap: var(--s4);
  padding-inline: var(--gutter);
  background: oklch(0.965 0.003 106 / 0.98);
}

.brand { display: block; }
.brand svg { height: 40px; width: auto; }
.brand--mono { display: none; }
.brand--mono svg { height: 40px; }

.nav {
  margin-left: auto;
  display: flex; align-items: center; gap: clamp(14px, 1.8vw, 32px);
}
.nav a {
  position: relative;
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); letter-spacing: 0.08em;
  color: var(--ink); text-decoration: none;
  padding: 10px 0;
}
.nav a::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 2px; height: 3px;
  background: var(--green-mid);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 120ms ease-out;
}
.nav a:hover::after { transform: scaleX(1); }
.nav a:active { color: var(--green-mid); }

.hdr-cta { --btn-h: 40px; margin-left: var(--s3); }

/* --- buttons ------------------------------------------------------------------------- */
.btn {
  --cut: var(--btn-h);
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  height: var(--btn-h); padding-inline: clamp(18px, 2vw, 28px);
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(1.0625rem, 1.35vw, 1.375rem);
  line-height: 1; letter-spacing: 0.02em; text-transform: uppercase;
  text-decoration: none; border: 0; border-radius: 0; cursor: pointer;
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - 0.306 * var(--cut)) 100%, 0 100%);
  /* felt-polish (owner 3.8.: "buttons feel satisfying"): quick eased response instead of
     an instant swap; press stays a 1px drop — transform+bg only, budget intact */
  transition: background-color 120ms ease-out, transform 80ms ease-out;
}
.btn--primary { background: var(--green-mid); color: var(--paper); }
.btn--primary:hover { background: var(--ink-display); }
/* the submit ships disabled until site.js runs (JS-off honesty). Memo 0.2: the state
   reads ARMED-waiting, not switched-off — outlined in the accent on paper, the 73° cut
   slicing the ring keeps it in the house grammar; the honest line below is its caption.
   (Border here is a state ring, not depth — deliberate deviation from surfaces-only.) */
.btn--primary:disabled {
  background: var(--paper); color: var(--green-mid);
  border: 2px solid var(--green-mid);
  cursor: default;
}
.btn--primary:disabled:hover { background: var(--paper); }
.btn--primary:disabled:hover .arrow { transform: none; }
.btn--primary:hover .arrow { transform: translateX(4px); }
.btn--primary:active { transform: translateY(1px); }
.arrow { display: inline-block; transition: transform 120ms ease-out; }

.link-secondary {
  font-family: var(--f-body); font-weight: 500;
  font-size: var(--t-standfirst); color: var(--ink);
  text-decoration: none; padding: 10px 2px;
}
.link-secondary:hover { text-decoration: underline; text-underline-offset: 4px; }

:where(a, button, input, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--green-mid); outline-offset: 2px;
}

/* --- burger (G5: three bars, sheared left ends) --------------------------------------- */
.burger {
  display: none;
  align-items: center; justify-content: flex-end; gap: 10px;
  min-width: 44px; height: 44px; margin-left: auto;
  background: none; border: 0; padding: 0 4px; cursor: pointer;
}
/* without JS the burger cannot open anything — a 44px control that does nothing is worse
   than no control. The sections stay reachable by scrolling and by the in-page anchors. */
.no-js .burger { display: none; }
.burger-bars { display: flex; flex-direction: column; justify-content: center; gap: 6px; width: 36px; height: 44px; }
/* the crossed bars alone do not say WHAT they do; the word does, in the record voice */
.burger-label {
  display: none;
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); line-height: 1; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--green-mid);
}
.burger[aria-expanded="true"] .burger-label { display: block; }
.burger-bar {
  --cut: 4px;
  display: block; height: 4px; background: var(--ink-display);
  clip-path: polygon(calc(0.306 * var(--cut)) 0, 100% 0, 100% 100%, 0 100%, 0 var(--cut));
  transition: transform 160ms ease-out, opacity 120ms ease-out;
}
.burger-bar:nth-child(2) { width: 82%; }
.burger-bar:nth-child(3) { width: 64%; }
/* open = a close form: the outer two sheared bars cross, the middle one leaves. The bars
   keep their 73° ends, so the X is cut from the same vocabulary as everything else. */
.burger[aria-expanded="true"] .burger-bar { background: var(--green-mid); }
.burger[aria-expanded="true"] .burger-bar:nth-child(1) { transform: translateY(10px) rotate(45deg); }
.burger[aria-expanded="true"] .burger-bar:nth-child(2) { opacity: 0; transform: scaleX(0.2); }
.burger[aria-expanded="true"] .burger-bar:nth-child(3) { width: 100%; transform: translateY(-10px) rotate(-45deg); }

/* --- mobile menu overlay -------------------------------------------------------------- */
.menu {
  /* the header stays ABOVE the overlay so the burger remains the visible close
     affordance while it is open — a full-screen paper sheet with no way out is a trap */
  position: fixed; inset: 0; z-index: 50;
  display: flex; flex-direction: column; justify-content: flex-start;
  gap: var(--s3);
  padding: calc(var(--header-h) + var(--s3)) var(--gutter)
           calc(var(--gutter) + env(safe-area-inset-bottom, 0px));
  background: var(--ground);
  opacity: 0; visibility: hidden; transform: translateY(-10px);
  transition: opacity 160ms ease-out, transform 160ms ease-out, visibility 0s linear 160ms;
}
.menu.is-open { opacity: 1; visibility: visible; transform: none; transition-delay: 0s; }
.menu-nav { display: flex; flex-direction: column; gap: var(--s2); }
.menu-nav a {
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(2rem, 9vw, 3rem); line-height: 1;
  text-transform: uppercase; color: var(--ink-display); text-decoration: none;
  padding: 6px 0;
}
.menu-nav a:hover { color: var(--green-mid); }
/* the primary action sits on the overlay's bottom edge (thumb reach), clear of the home
   indicator via the safe-area inset in .menu's padding */
.menu-cta { --btn-h: 54px; margin-top: auto; align-self: flex-start; }

/* --- fold ----------------------------------------------------------------------------- */
.fold {
  height: calc(100vh - var(--header-h));
  height: calc(100svh - var(--header-h));
  display: flex; flex-direction: column;
}

/* space-evenly, not center: leftover height becomes three equal bands of rhythm instead of
   one void at each end. It only ever distributes POSITIVE free space, so a short laptop
   (1366×635) degrades to the gap minimums with zero overflow risk — the density floor and
   the fold contract are then satisfied by the same mechanism (canvas: whitespace is rhythm;
   testing.md 7a: the void at ultrawide is a real defect, not a matter of taste). */
.hero {
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; justify-content: space-evenly;
  gap: clamp(10px, 3.6vh, 44px);
  padding-block: clamp(10px, 2vh, 28px);
}
.hero-inner { padding-inline: var(--gutter); }
.hero-inner--b {
  display: flex; flex-direction: column;
  gap: clamp(14px, 3.4vh, 44px);
}

.eyebrow {
  display: flex; align-items: center; gap: 12px;
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); line-height: 1.4;
  letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--green-mid);
  margin-bottom: clamp(8px, 1.4vh, 20px);
}
.tick {
  --cut: 14px;
  flex: none; display: block; width: 10px; height: 14px;
  background: var(--green-mid);
  clip-path: polygon(calc(0.306 * var(--cut)) 0, 100% 0, calc(100% - 0.306 * var(--cut)) 100%, 0 100%);
}

h1 {
  font-family: var(--f-display); font-weight: 800;
  font-size: var(--t-h1); line-height: 0.92;
  letter-spacing: 0.005em; text-transform: uppercase;
  color: var(--ink-display);
  /* the two authored lines ARE the design, and the hanging hyphen in JA -KORJAUS. is
     correct copy — never a break opportunity. A too-large floor then overflows loudly
     (the rig catches it) instead of silently rewrapping to three lines. */
  white-space: nowrap;
  hyphens: none; -webkit-hyphens: none;
}

/* full-bleed from the page's left edge to ~76% of page width (brief B §4), so it escapes
   the hero's gutter rather than the 76% of an inner box */
.flank {
  --cut: 12px;
  margin-left: calc(-1 * var(--gutter));
  margin-top: clamp(14px, 2.6vh, 34px);
  width: 76vw; height: 12px;
  background: var(--green-mid);
  clip-path: polygon(0 0, 100% 0, calc(100% - 0.306 * var(--cut)) 100%, 0 100%);
}

.standfirst {
  font-family: var(--f-body); font-weight: 500;
  font-size: var(--t-standfirst); line-height: 1.5;
  max-width: 52ch;
}

/* 2026-08-03 council SPEC A: the työmääräys-liite — a photo mounted on a dark plate in the
   fold's right field, ≥1100px only. The plate is a flat surface (depth by surface, never
   shadow), cut-bl so the ONE angle points at the flank; the flank bar passes BEHIND it
   (the second layer both liked drafts had). No caption — the KALUSTO strip below IS the
   caption layer; a KOHDE-tag on stock would fabricate ownership. Fold contract PRESERVED:
   the img is absolute (zero intrinsic height), rows size from the type column. */
.hero-liite { display: none; margin: 0; }
@media (min-width: 1100px) {
  .hero {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) var(--lane);
    grid-template-rows: auto auto;
    align-content: space-evenly;
    row-gap: clamp(10px, 3.6vh, 44px);
    column-gap: clamp(24px, 3vw, 56px);
  }
  /* wave 2.5 (owner: "hero 80% empty"): ambient right field — a flat surface plane the
     liite plate and the flank both overlap. Three flat layers = the fold's depth,
     no gradient, no shadow. Paints under all hero children (::before, z auto). */
  .hero::before {
    content: '';
    position: absolute; top: 0; right: 0; height: 100%;
    width: clamp(340px, 42%, 760px);
    background: var(--surface-1);
    --fc: clamp(72px, 8vw, 128px);
    clip-path: polygon(0 0, 100% 0, 100% 100%, calc(0.306 * var(--fc)) 100%, 0 calc(100% - var(--fc)));
  }
  .hero-inner, .hero-inner--b { grid-column: 1; }
  .hero-liite {
    --cut: 48px;
    display: block;
    grid-column: 2; grid-row: 1 / 3;
    align-self: stretch;
    margin-right: var(--gutter);
    background: var(--ink-display);
    padding: var(--s2);
    clip-path: polygon(0 0, 100% 0, 100% 100%, calc(0.306 * var(--cut)) 100%, 0 calc(100% - var(--cut)));
  }
  .hero-liite .ph { position: relative; height: 100%; }
  /* absolute-inset img: kills the WebKit circular-height trap (jalator 2026-07-30 specimen) */
  .hero-liite .ph img { position: absolute; inset: 0; }
}
/* R20 on body copy only — the display H2 rags are hand-tuned (20ch window), balance would
   rewrap them; body paragraphs get the cheap one-word-last-line insurance */
.standfirst, .prose p, .stmt-b, .palvelu-row p, .seg-block p, .band-body, .chev-b, .sec-lede { text-wrap: pretty; }

.cta-row { display: flex; align-items: center; gap: clamp(18px, 2.4vw, 36px); flex-wrap: wrap; }

/* --- kalusto + record strips (the fold's two record bands) ----------------------------- */
.kalusto, .record {
  display: flex; align-items: center;
  gap: clamp(10px, 1.4vw, 20px);
  padding: clamp(9px, 1.5vh, 16px) var(--gutter);
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); line-height: 1.4;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.kalusto { display: block; background: var(--surface-1); color: var(--ink); }
.kalusto-label { color: var(--green-mid); margin-right: clamp(10px, 1.4vw, 20px); }
/* manual, not none: authored &shy; must still be able to fire in the compounds at 320px,
   while automatic hyphenation stays off in the record grammar */
.kalusto-items { hyphens: manual; -webkit-hyphens: manual; }
.sep { color: var(--green-mid); }
/* R3 + wrap-safety (handoff trio): separators live in CSS glued to the PRECEDING item, so
   a wrapped line can never start with a stray · */
.kal { white-space: nowrap; }
.kal:not(:last-child)::after, .rb:not(:last-child)::after { content: ' ·'; color: var(--green-mid); }

.record {
  background: var(--surface-2); color: var(--ink-muted);
  display: grid; grid-template-columns: 2fr 1fr 1fr;
  align-items: center; column-gap: clamp(16px, 2.4vw, 40px);
}
.rec-cell { display: flex; align-items: baseline; gap: 8px; min-width: 0; }
.rec-k { color: var(--green-mid); flex: none; }
.rec-v { color: var(--ink); overflow-wrap: anywhere; }
/* memo 0.3: verified facts are affordances, not inert cells — map/YTJ links in the
   record voice; underline only on approach */
a.rec-link { text-decoration: none; transition: color 120ms ease-out; }
a.rec-link:hover { text-decoration: underline; text-underline-offset: 3px; color: var(--green-mid); }
.yht-band a.rec-link { color: var(--paper); }
.yht-band a.rec-link:hover { color: var(--green-accent); }
/* A label and the blank it opens are ONE thing. Left to normal inline flow the bar orphans
   onto its own line at 320–375 and reads as a stray rule; as an inline-flex nowrap unit the
   pair breaks as a whole and the bar shrinks instead (measured: 320px leaves 61px for it). */
.slot {
  display: inline-flex; align-items: baseline; gap: 8px;
  white-space: nowrap; max-width: 100%; min-width: 0;
}
.rec-cell > .slot, .sidenote > .slot, .band-field > .slot { flex: 1 1 auto; }
.blank {
  display: inline-block; flex: 1 1 auto;
  min-width: 64px; max-width: 220px; height: 1em;
  background: var(--surface-3);
  border-bottom: 2px solid var(--ink-muted);
}
.nowrap { white-space: nowrap; }
.blank--dark { background: none; border-bottom-color: var(--green-accent); }

/* --- sections ------------------------------------------------------------------------- */
.sec { padding-inline: var(--gutter); }
.sec--palvelut { padding-block: clamp(56px, 8vw, 96px) 0; }
.sec--toiminta { padding-block: clamp(56px, 8vw, 96px); }
.sec--miksi { padding-block: clamp(48px, 6vw, 80px) clamp(56px, 8vw, 96px); }
.sec--pyynto { padding-block: clamp(64px, 10vw, 128px); }
.sec--yht { padding: 0; }

.sec-head { max-width: 24ch; }
.sec--toiminta .sec-head, .sec--pyynto .sec-head { max-width: none; }

h2 {
  font-family: var(--f-display); font-weight: 700;
  font-size: var(--t-h2); line-height: 1.0;
  text-transform: uppercase; color: var(--ink-display);
  max-width: 18ch;
  hyphens: none; -webkit-hyphens: none;
}
.eyebrow--h { font-family: var(--f-mono); font-weight: 600; font-size: var(--t-meta); max-width: none; }

/* --- palvelut bands (G3: each band preselects its segment in the form) ------------------
   2026-08-03 rebuild for the comp: identical markup per band (R4), position-based styling
   (R1/R2 — :first-child carries dominance), photo panel per band (reframe: stock
   placeholders show the client what to shoot). */
.sec-lede {
  margin-top: clamp(14px, 2vw, 24px);
  font-size: var(--t-body); max-width: 46ch;
}
.bands {
  margin-inline: calc(-1 * var(--gutter));
  margin-top: clamp(32px, 4vw, 56px);
  display: flex; flex-direction: column;
}
.band {
  --cut: clamp(40px, 5vw, 72px);
  position: relative;
  display: grid; align-content: center;
  gap: clamp(6px, 0.8vw, 12px);
  min-height: clamp(150px, 18vw, 230px);
  padding: clamp(24px, 3vw, 40px) var(--gutter);
  text-decoration: none; color: var(--ink);
  clip-path: polygon(calc(0.306 * var(--cut)) 0, 100% 0, 100% 100%, 0 100%, 0 var(--cut));
  transition: background-color 120ms ease-out;
}
.band:nth-child(odd) { background: var(--surface-1); }
.band:nth-child(even) { background: var(--ground); }
/* 4.8. uniform hover (owner: middle band blended into its neighbors) — surface-2 touches
   no band's resting tone, so any hovered band separates from BOTH neighbors */
.band:hover, .band:focus-visible { background: var(--surface-2); }
.band:first-child { min-height: clamp(260px, 30vw, 400px); }
.band:focus-visible { outline-offset: -4px; }

.band-name {
  font-family: var(--f-display); font-weight: 800;
  font-size: var(--t-h2); line-height: 1;
  text-transform: uppercase; color: var(--ink-display);
}
.band:first-child .band-name { font-size: clamp(2.75rem, 6.4vw, 5.25rem); }
.band-field {
  display: flex; align-items: baseline; gap: 8px;
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-field-label); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-muted); margin-top: 4px; max-width: 60ch;
}
.band-field .rec-k { flex: none; }
.band-worklist { color: var(--ink); letter-spacing: 0.06em; }
/* 4.8. action strip: closes the band stack AND separates it from the room threshold on
   ground (rooms are designed to cut against ground — the gap gets a job, not padding) */
.band-more {
  margin-inline: calc(-1 * var(--gutter));
  padding: clamp(28px, 3.6vw, 48px) var(--gutter);
  display: flex; align-items: baseline; gap: clamp(14px, 2vw, 24px); flex-wrap: wrap;
  background: var(--ground);
  text-decoration: none;
  transition: background-color 120ms ease-out;
}
.band-more:hover, .band-more:focus-visible { background: var(--surface-2); }
.band-more .rec-k {
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); letter-spacing: 0.08em; text-transform: uppercase;
}
.band-more-t {
  font-family: var(--f-display); font-weight: 800;
  font-size: clamp(1.5rem, 2.6vw, 2.25rem); line-height: 1;
  letter-spacing: 0.02em; text-transform: uppercase;
  color: var(--green-mid);
}
.band-more:hover .band-more-t { color: var(--ink-display); }

/* --- toimintatapa --------------------------------------------------------------------- */
.pull {
  font-family: var(--f-display); font-weight: 800;
  font-size: var(--t-display-2); line-height: 0.96;
  text-transform: uppercase; color: var(--ink-display);
  margin-top: clamp(24px, 3vw, 40px);
  max-width: 16ch;
  hyphens: none; -webkit-hyphens: none;
}

/* The chevron joins are full-height 73° edges, so the shear run = 0.306 × segment height.
   CSS cannot read an element's used height, so the height is PINNED (min-height = the same
   token the clip-path uses) and the rig asserts the used height still equals it — a guessed
   total would rot silently (testing.md 7a physics). */
.chevrons {
  --chev-h: 160px;
  --chev-run: calc(0.306 * var(--chev-h));
  --chev-pad: clamp(18px, 2vw, 30px);
  margin-inline: calc(-1 * var(--gutter));
  margin-top: clamp(40px, 5vw, 64px);
  display: flex;
}
/* Flex, not grid: the negative margins that interlock the sheared edges also feed the
   free-space calculation back, so four segments still span exactly 100% of the strip. */
.chev {
  flex: 1 1 0; min-width: 0;
  min-height: var(--chev-h);
  padding: clamp(18px, 2.2vw, 28px) var(--chev-pad);
  display: grid; align-content: start; gap: 6px;
}
.chev:nth-child(odd) { background: var(--surface-1); }
.chev:nth-child(even) { background: var(--surface-2); }
/* R1 (2026-08-03): positional selectors, not --1..--4 — the strip survives a fifth step */
.chev {
  clip-path: polygon(var(--chev-run) 0, 100% 0, calc(100% - var(--chev-run)) 100%, 0 100%);
  margin-left: calc(-1 * var(--chev-run));
  padding-left: calc(var(--chev-pad) + var(--chev-run));
}
.chev:first-child {
  clip-path: polygon(0 0, 100% 0, calc(100% - var(--chev-run)) 100%, 0 100%);
  margin-left: 0;
  padding-left: var(--gutter);
}
.chev:last-child {
  clip-path: polygon(var(--chev-run) 0, 100% 0, 100% 100%, 0 100%);
  padding-right: var(--gutter);
}
/* the trailing join eats the bottom-right corner over the full run, so the content box of
   every sheared segment clears it by the whole run — a glyph on the last line can never
   reach the angle (fidelity review: segment 1 lost its final period into the join) */
.chev:not(:last-child) { padding-right: calc(var(--chev-pad) + var(--chev-run)); }
.chev-k {
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--green-mid);
}
.chev-b { font-size: var(--t-body); line-height: 1.5; }

/* --- miksi DT (G4 stagger) -------------------------------------------------------------- */
.statements { margin-top: clamp(32px, 4vw, 56px); display: grid; gap: clamp(24px, 3vw, 40px); }
/* R1: G4 stagger by position — 0 / 96 / 48, repeating for any count */
.stmt:nth-child(3n+2) { margin-left: 96px; }
.stmt:nth-child(3n) { margin-left: 48px; }
.stmt-t {
  font-family: var(--f-display); font-weight: 700;
  font-size: var(--t-h2); line-height: 1;
  text-transform: uppercase; color: var(--ink-display);
  max-width: 20ch;
  hyphens: none; -webkit-hyphens: none;
}
.stmt-b { margin-top: 10px; font-size: var(--t-body); max-width: 46ch; }

.recbox {
  --cut: 32px;
  margin-top: clamp(40px, 5vw, 64px);
  padding: clamp(20px, 2.4vw, 28px) clamp(20px, 2.4vw, 32px);
  background: var(--surface-1); color: var(--ink);
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); line-height: 1.8;
  letter-spacing: 0.08em; text-transform: uppercase;
  clip-path: polygon(calc(0.306 * var(--cut)) 0, 100% 0, 100% 100%, 0 100%, 0 var(--cut));
}

/* --- työpyyntö form --------------------------------------------------------------------- */
.wo {
  --cut: clamp(40px, 5vw, 72px);
  margin-top: clamp(32px, 4vw, 56px);
  background: var(--surface-1);
  padding: clamp(28px, 4vw, 56px) clamp(24px, 3.4vw, 56px);
  clip-path: polygon(0 0, calc(100% - 0.306 * var(--cut)) 0, 100% var(--cut), 100% 100%, 0 100%);
}
.wo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(20px, 2.4vw, 32px); }
.f { display: flex; flex-direction: column; gap: 8px; min-width: 0; }
.f--wide { grid-column: 1 / -1; }
.f label, .seg legend {
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-field-label); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-muted);
}
.f input, .f textarea {
  font-family: var(--f-body); font-size: var(--t-body); color: var(--ink);
  background: var(--surface-2);
  border: 0; border-bottom: 2px solid var(--ink);
  border-radius: 0;
  padding: 12px 14px; min-height: 48px; width: 100%;
}
.f textarea { resize: vertical; min-height: 120px; line-height: 1.5; }
.f input:focus, .f textarea:focus {
  outline: none; border-bottom: 3px solid var(--green-mid); padding-bottom: 11px;
}
.f:focus-within label { color: var(--green-mid); }
.f input:user-invalid, .f textarea:user-invalid { border-bottom-color: var(--state-error); }

.seg { display: flex; flex-direction: column; gap: 8px; }
.seg-row { display: flex; flex-wrap: wrap; gap: 2px; }
.seg input {
  position: absolute; width: 1px; height: 1px; margin: -1px;
  padding: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap;
}
.seg label {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 48px; padding: 10px 18px;
  background: var(--surface-2); color: var(--ink);
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-field-label); letter-spacing: 0.1em; text-transform: uppercase;
  cursor: pointer;
}
.seg input:checked + label { background: var(--green-mid); color: var(--paper); }
.seg input:focus-visible + label { outline: 2px solid var(--green-mid); outline-offset: 2px; }

.wo-foot { margin-top: clamp(28px, 3.4vw, 44px); display: flex; flex-direction: column; gap: 14px; align-items: flex-start; }
#wo-submit { --btn-h: 54px; }
.honest {
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-field-label); letter-spacing: 0.06em;
  color: var(--ink-muted);
}
/* --state-error is reserved for validation (brief B §2: functional only), so the demo
   marker is stamped on a surface instead of borrowing the error ink */
.demo-note {
  display: inline-block;
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-field-label); letter-spacing: 0.06em;
  color: var(--ink); background: var(--surface-2);
  padding: 10px 14px;
  margin-bottom: clamp(20px, 2.4vw, 28px);
}
.demo-note[hidden] { display: none; }
.sidenote {
  display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  margin-top: clamp(24px, 3vw, 36px);
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-field-label); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-muted);
}
.sidenote .blank { background: var(--surface-2); max-width: 180px; }

/* --- yhteystiedot + footer -------------------------------------------------------------- */
.yht-band {
  background: var(--ink-display); color: var(--paper);
  padding: clamp(40px, 5vw, 72px) var(--gutter);
  display: grid; grid-template-columns: 1fr 1.2fr; gap: clamp(24px, 3vw, 48px);
  align-items: start;
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); line-height: 1.45;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.yht-cell { display: flex; align-items: baseline; gap: 10px; }
.yht-band .rec-k { color: var(--green-accent); }
.yht-band .rec-v { color: var(--paper); }
.yht-col { display: grid; gap: clamp(20px, 2.6vw, 36px); align-content: start; }
/* D-6: three slots of different label length ragged their bars at both edges and read as
   debris. Subgrid pins every bar to one value column — same start, same end — so the
   cluster reads as a form awaiting entries, which is exactly what it is. */
.yht-open { display: grid; grid-template-columns: max-content 1fr; row-gap: 12px; column-gap: 10px; align-content: start; }
.yht-open-k { color: var(--green-accent); grid-column: 1 / -1; }
.yht-open .yht-cell { display: grid; grid-template-columns: subgrid; grid-column: 1 / -1; }
.yht-mech {
  font-family: var(--f-body); font-weight: 400; font-size: var(--t-body);
  letter-spacing: 0; text-transform: none; line-height: 1.65;
  color: var(--paper); max-width: 46ch;
}

/* 2026-08-03 council SPEC B: the wordmark gains companions (desc + site nav) and the page
   CLOSES on a record strip (.foot-terminal reuses the fold record strip's recipe — open on
   a record, close on a record). */
.footmark {
  padding: clamp(48px, 6vw, 96px) var(--gutter) clamp(40px, 5vw, 72px);
  display: grid; gap: clamp(32px, 4vw, 56px);
  align-items: end;
}
@media (min-width: 1024px) { .footmark { grid-template-columns: minmax(0, 720px) 1fr; } }
.footmark-brand { display: grid; gap: var(--s3); justify-items: start; }
.foot-desc { font-size: var(--t-body); color: var(--ink-muted); }
.foot-nav {
  display: grid; gap: 12px; justify-items: start; align-content: end;
  font-family: var(--f-mono); font-weight: 600; font-size: var(--t-meta);
  letter-spacing: 0.08em; text-transform: uppercase;
}
@media (min-width: 1024px) { .foot-nav { justify-self: end; } }
.foot-nav a { color: var(--ink); text-decoration: none; transition: color 120ms ease-out; }
.foot-nav a:hover, .foot-nav a[aria-current="page"] { color: var(--green-mid); }
.foot-terminal {
  display: flex; justify-content: space-between; align-items: baseline; gap: var(--s3); flex-wrap: wrap;
  padding: clamp(9px, 1.5vh, 16px) var(--gutter);
  background: var(--surface-2); color: var(--ink-muted);
  font-family: var(--f-mono); font-weight: 600; font-size: var(--t-field-label);
  letter-spacing: 0.08em; text-transform: uppercase;
}
/* an inline <svg> with only a viewBox falls back to the CSS default object size (300px),
   so the shrink-to-fit span capped the set-piece at 300px and `width: min(100%,720px)` on
   the svg resolved against that 300. The SPAN carries the desktop width; mobile keeps the
   as-cut 300px default. */
.brand--big svg { height: auto; width: min(100%, 720px); }
/* SPEC C (council): yritys evidence grids + values 3-across; recbox goes full-bleed
   everywhere (wide/narrow rhythm — emptiness structured, not filled) */
.recbox { margin-inline: calc(-1 * var(--gutter)); padding-inline: var(--gutter); }
@media (min-width: 1100px) {
  #arki, #ihmiset {
    display: grid;
    grid-template-columns: minmax(0, 60ch) minmax(300px, 1fr);
    column-gap: clamp(40px, 5vw, 96px);
  }
  #arki .sec-head, #arki .prose { grid-column: 1; }
  #arki .media-panel { grid-column: 2; grid-row: 1 / 3; align-self: start; max-width: none; margin-top: 0; }
  #ihmiset .eyebrow--h, #ihmiset .prose, #ihmiset .fact-rows { grid-column: 1; }
  #ihmiset .photo-slot { grid-column: 2; grid-row: 1 / 4; align-self: start; max-width: none; margin-top: 0; }
  /* memo 0.1: the 3-across rule was #arvot-scoped by accident — palvelut's identical
     markup fell to single column and left 60% of the viewport empty (the KENEN AUTOT
     "emptiness" was a missing selector, not a design) */
  .seg-blocks { grid-template-columns: repeat(3, 1fr); gap: clamp(32px, 4vw, 64px); }
}

/* --- breakpoints -------------------------------------------------------------------------- */
@media (min-width: 1024px) {
  .brand--big { width: min(100%, 720px); }

  /* The two quoted display H2s ragged into three narrow lines because the 18ch type cap
     (and the palvelut head's 24ch BODY-ch cap) both bite well before the measure does.
     20ch is measured, both engines, 1024→3440: the window that keeps the authored rag
     (”TEETTEKÖ TÄLLÄSTÄ / TYÖTÄ?” · ”MILLO ONNISTUU JA / MILLON ON VALMISTA?”) is
     [18.4ch, 21.9ch] — outside it the line either swallows MILLON or breaks a third time. */
  .sec--palvelut .sec-head { max-width: none; }
  .sec--palvelut h2, .sec--toiminta h2 { max-width: 20ch; }
}

@media (max-width: 1023px) {
  :root { --header-h: 60px; }
  .nav, .hdr-cta { display: none; }
  .burger { display: flex; }
  .brand--full { display: none; }
  .brand--mono { display: block; }

  .record { grid-template-columns: 1fr 1fr; row-gap: 6px; }
  .rec-osoite { grid-column: 1 / -1; }

  /* Stacked: the join cannot stay a full-height near-vertical edge, so each segment keeps
     the SAME measured cut on its leading (top-left) corner — one constant, no new angle. */
  .chevrons { --chev-h: 72px; flex-direction: column; }
  .chev, .chev:first-child, .chev:last-child, .chev:not(:last-child) {
    flex: 0 0 auto; margin-left: 0; min-height: 0;
    padding-block: clamp(18px, 4vw, 26px);
    padding-inline: var(--gutter);
    clip-path: polygon(var(--chev-run) 0, 100% 0, 100% 100%, 0 100%, 0 var(--chev-h));
  }

  .wo-grid { grid-template-columns: 1fr; }
  .yht-band { grid-template-columns: 1fr; }
  .stmt:nth-child(3n+2) { margin-left: 24px; }
  .stmt:nth-child(3n) { margin-left: 12px; }
}

@media (max-width: 560px) {
  #hero-cta, .menu-cta { --btn-h: 54px; width: 100%; }
  .cta-row { align-items: flex-start; flex-direction: column; gap: 14px; }
  .seg-row { display: grid; grid-template-columns: 1fr 1fr; }
  .blank { min-width: 48px; }
  .kalusto, .record { font-size: 0.75rem; letter-spacing: 0.05em; }
  .record { column-gap: 14px; }
  /* flow the record cells as text on phones: WebKit's mono advance is a hair wider than
     Chromium's, so the address wraps at 360px in one engine and not the other — as flex
     rows that produced a hanging indent under the label instead of a plain text wrap. */
  .record .rec-cell, .record .rec-k, .record .rec-v { display: inline; }
  .record .rec-cell { display: block; }
  .record .blank { width: 96px; min-width: 0; height: 0.85em; vertical-align: -1px; }
}

/* ==== 2026-08-03 wave 2: the ambient stack (memo A1+A2+A3) ==============================
   A1 TONAL ROOMS — sections get floors from the existing ramp; the 73° cut scaled up as
   the section threshold (next room's ground shows through the notch = depth from flat
   surfaces). Deployment varies corner and rhythm — never every section (zebra-at-scale).
   Content inside a room steps one surface up; the form panel steps LIGHTER (paper) —
   elevation-by-lighter is the house depth law at composed scale. */
.room { background-color: var(--surface-1); }
/* 4.8. (owner): a room following a surface-1 zebra list steps DEEPER so the threshold
   never carries the previous section's tint across the cut */
.room--deep { background-color: var(--surface-2); }
.room--deep .recbox { background: var(--surface-3); }
.room--cut-tl {
  --room-cut: clamp(56px, 9vw, 140px);
  clip-path: polygon(calc(0.306 * var(--room-cut)) 0, 100% 0, 100% 100%, 0 100%, 0 var(--room-cut));
  padding-top: calc(var(--room-cut) + clamp(24px, 3vw, 48px));
}
.room--cut-tr {
  --room-cut: clamp(56px, 9vw, 140px);
  clip-path: polygon(0 0, calc(100% - 0.306 * var(--room-cut)) 0, 100% var(--room-cut), 100% 100%, 0 100%);
  padding-top: calc(var(--room-cut) + clamp(24px, 3vw, 48px));
}
/* room content steps: chevrons up one, form/CTA plates go lighter than the floor */
.room .chev:nth-child(odd) { background: var(--surface-2); }
.room .chev:nth-child(even) { background: var(--surface-3); }
.room .wo { background: var(--paper); }
.room .recbox { background: var(--surface-2); }
.room .photo-slot { background: var(--surface-2); }

/* A3 — työmääräys ruling: faint ledger lines behind the form sections only (ruling under
   an actual form is content, not decoration). SVG hairline tile — no gradient function. */
.room--ruled {
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='4' height='44'%3E%3Crect y='43' width='4' height='1' fill='%23c6c6c2'/%3E%3C/svg%3E");
  background-size: 100% 44px;
}

/* A2 — paper grain, the measured whisper: mono SVG noise, multiply (ink-on-paper — only
   darkens), 0.05 at the perceptible-not-dirt point. One fixed layer, applied to the whole
   page so every surface shares the same material. */
body::after {
  content: '';
  position: fixed; inset: 0; z-index: 200;
  pointer-events: none;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  mix-blend-mode: multiply;
  opacity: 0.05;
}

/* ==== 2026-08-03 comp build: photos, subpages, motion additions =========================
   Photo policy (reframe): stock placeholders, self-hosted, DT-graded in CSS (grade never
   baked into files so the client's real photos drop in and match). NO text over photos —
   captions sit on the ground below. Grade = neutral desaturation only — the 4.8. team
   round killed the hue-148 cast ("even pics have green filter"). */

.ph { display: block; position: relative; overflow: hidden; background: var(--surface-2); }
.ph img {
  display: block; width: 100%; height: 100%; object-fit: cover;
  filter: grayscale(0.88) saturate(0.9);
}

/* full-bleed photo bands (index below-fold · outcome · yhteystiedot) */
.photo-band { margin: 0; }
.photo-band .ph {
  --cut: clamp(40px, 5vw, 72px);
  height: clamp(300px, 42vw, 560px);
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - 0.306 * var(--cut)) 100%, 0 100%);
}
.ph-caption {
  display: flex; align-items: center; gap: 12px;
  padding: clamp(12px, 1.6vh, 18px) var(--gutter);
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--green-mid);
}

/* band photo panel (right slab ≥900px, top strip below) */
.band-photo { display: block; }
.band-photo .ph, .band-photo img { height: 100%; }
@media (min-width: 900px) {
  .band-photo {
    position: absolute; inset-block: 0; right: 0;
    width: min(38%, 560px);
  }
  .band-photo .ph {
    --cut: 48px; height: 100%;
    clip-path: polygon(0 0, 100% 0, 100% 100%, calc(0.306 * var(--cut)) 100%, 0 calc(100% - var(--cut)));
  }
  .band > :not(.band-photo) { max-width: calc(100% - min(38%, 560px) - var(--s3)); }
}
@media (max-width: 899px) {
  .band-photo {
    order: -1;
    margin: calc(-1 * clamp(24px, 3vw, 40px)) calc(-1 * var(--gutter)) 8px;
  }
  .band-photo .ph { height: clamp(150px, 34vw, 240px); }
}

/* toimintatapa: the CONVERSATION (4.8.) — customers' question top-left, the shop's answer
   in the right column dropped a beat LOWER: the vertical mismatch is what makes two quoted
   display lines read as question and reply. Mobile stacks like chat (answer indented). */
.toiminta-head { display: grid; gap: clamp(20px, 3vw, 40px); }
.pull--answer { margin-left: clamp(24px, 8vw, 48px); }
@media (min-width: 1024px) {
  .toiminta-head { grid-template-columns: minmax(0, 1fr) var(--lane); column-gap: clamp(40px, 5vw, 96px); }
  .pull--answer {
    grid-column: 2;
    margin-left: 0;
    margin-top: clamp(96px, 14vw, 200px);
    align-self: start;
  }
}

/* miksi: claims left, evidence right (the freed photo reads as quality inspection) */
@media (min-width: 1100px) {
  .miksi-grid { display: grid; grid-template-columns: minmax(0, 1fr) var(--lane); column-gap: clamp(40px, 5vw, 96px); align-items: center; }
  .miksi-media { margin-top: 0; max-width: none; }
}

/* two-up detail strip (palvelut) + standalone media panel (yritys) */
.detail-duo {
  margin-top: clamp(32px, 4vw, 56px);
  display: grid; gap: clamp(16px, 2vw, 24px);
}
.detail-duo .ph {
  --cut: 48px;
  aspect-ratio: 3 / 2;
  clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--cut)), calc(100% - 0.306 * var(--cut)) 100%, 0 100%);
}
@media (min-width: 700px) { .detail-duo { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); } }
/* 4.8. (owner): without the rail, ONE photo is the beat between list and CTA — a stack of
   three before the dark band read as filler on small screens */
@media (max-width: 1199px) {
  .detail-duo { grid-template-columns: 1fr; }
  .detail-duo .ph:not(:first-child) { display: none; }
}
.media-panel { margin-top: clamp(24px, 3vw, 40px); max-width: 560px; }
.media-panel .ph {
  --cut: 48px;
  aspect-ratio: 3 / 2;
  clip-path: polygon(calc(0.306 * var(--cut)) 0, 100% 0, 100% 100%, 0 100%, 0 var(--cut));
}

/* honest empty photo slot (yritys TIIMIKUVA — no stock faces as staff, ever) */
.photo-slot {
  --cut: 48px;
  min-height: clamp(220px, 30vw, 360px);
  display: grid; place-content: center;
  background: var(--surface-2);
  clip-path: polygon(calc(0.306 * var(--cut)) 0, 100% 0, 100% 100%, 0 100%, 0 var(--cut));
}
.photo-slot p {
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-muted);
}

/* --- subpage skeleton ------------------------------------------------------------------ */
:root { --t-page-h1: clamp(2.75rem, 6vw, 5.75rem); }
.page-hero { padding: clamp(40px, 6vw, 80px) var(--gutter) clamp(32px, 4vw, 56px); }
/* wave 2.5: subpage heroes get the same ambient right field as the fold */
@media (min-width: 1100px) {
  .page-hero { position: relative; }
  .page-hero::before {
    content: '';
    position: absolute; top: 0; right: 0; height: 100%;
    width: clamp(280px, 34%, 640px);
    background: var(--surface-1);
    --fc: clamp(64px, 7vw, 112px);
    clip-path: polygon(0 0, 100% 0, 100% 100%, calc(0.306 * var(--fc)) 100%, 0 calc(100% - var(--fc)));
  }
  .page-hero > * { position: relative; }
}
.page-h1 {
  font-family: var(--f-display); font-weight: 800;
  font-size: var(--t-page-h1); line-height: 0.95;
  letter-spacing: 0.005em; text-transform: uppercase;
  color: var(--ink-display);
  hyphens: none; -webkit-hyphens: none;
  /* the base h1 rule pins nowrap for the front page's authored two-liner (R17 note there);
     subpage H1s are normal wrapping copy */
  white-space: normal;
}
.page-hero .standfirst { margin-top: clamp(16px, 2.4vw, 28px); }

/* 73° curtain wipe — the one entrance beat per subpage (CSS-only). Inverted gating: the
   default state is fully visible; hiding + animating exists ONLY inside no-preference,
   so JS-off, reduced-motion and unknown UAs all get plain visible content. */
@media (prefers-reduced-motion: no-preference) {
  .page-h1 { clip-path: polygon(-2% 0, -2% 0, -8% 110%, -8% 110%); animation: h1-wipe 560ms cubic-bezier(0.16, 1, 0.3, 1) 80ms forwards; }
  @keyframes h1-wipe {
    to { clip-path: polygon(-2% 0, 102% 0, 96% 110%, -8% 110%); }
  }
}

/* palvelulista — scannable rows (NOT a numbered index: identity ledger), underline draw */
.palvelu-rows { margin-top: clamp(32px, 4vw, 56px); display: grid; }
.palvelu-row {
  position: relative;
  display: grid; gap: 6px;
  padding: clamp(18px, 2.4vw, 28px) clamp(16px, 2vw, 24px);
  transition: background-color 120ms ease-out;
}
.palvelu-row:nth-child(even) { background: var(--surface-1); }
.palvelu-row:hover { background: var(--surface-2); }
.palvelu-row h3 {
  position: relative; align-self: start; justify-self: start;
  font-family: var(--f-display); font-weight: 800;
  font-size: var(--t-h3); line-height: 1.1; text-transform: uppercase;
  color: var(--ink-display);
}
.palvelu-row h3::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -4px; height: 3px;
  background: var(--green-mid);
  transform: scaleX(0); transform-origin: left center;
  transition: transform 160ms ease-out;
}
.palvelu-row:hover h3::after { transform: scaleX(1); }
.palvelu-row p { font-size: var(--t-body); max-width: 60ch; }
@media (min-width: 900px) {
  .palvelu-row { grid-template-columns: minmax(220px, 320px) 1fr; gap: clamp(16px, 3vw, 48px); align-items: baseline; }
}

/* kalusto segments + arvot (yritys) — same statement+body grammar as #miksi */
.seg-blocks { margin-top: clamp(32px, 4vw, 56px); display: grid; gap: clamp(28px, 4vw, 48px); }
.seg-block h3 {
  font-family: var(--f-display); font-weight: 700;
  font-size: var(--t-h2); line-height: 1; text-transform: uppercase;
  color: var(--ink-display);
}
.seg-block p { margin-top: 10px; font-size: var(--t-body); max-width: 52ch; }

/* prose (yritys tarina) */
.prose { margin-top: clamp(24px, 3vw, 40px); max-width: 60ch; display: grid; gap: 1em; }
.prose p { font-size: var(--t-standfirst); line-height: 1.6; }

/* mono record rows (yhteystiedot facts + yritys person row) */
.fact-rows {
  margin-top: clamp(24px, 3vw, 40px);
  display: grid; gap: 12px;
  font-family: var(--f-mono); font-weight: 600;
  font-size: var(--t-meta); letter-spacing: 0.08em; text-transform: uppercase;
}
.fact-rows p { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.fact-rows .rec-v { letter-spacing: 0.06em; }

/* dark CTA band (4.8., owner swap + hover-carry fix): the mid-page conversion moment on
   an inverse ground — no zebra/hover surface can ever collide with it (genre: a dark CTA
   band mid-page was 4/6 on the premium live-web audit) */
.sec--cta {
  --cut: clamp(56px, 8vw, 120px);
  margin-top: clamp(48px, 6vw, 88px);
  padding-block: calc(var(--cut) * 0.5 + clamp(32px, 4.4vw, 56px)) clamp(48px, 6vw, 80px);
  background: var(--ink-display); color: var(--paper);
  display: grid; gap: clamp(18px, 2.6vw, 28px); justify-items: start;
  clip-path: polygon(calc(0.306 * var(--cut)) 0, 100% 0, 100% 100%, 0 100%, 0 var(--cut));
}
.sec--cta p { font-size: var(--t-standfirst); max-width: 46ch; color: var(--paper); text-wrap: pretty; }
.sec--cta .btn--primary:hover { background: var(--paper); color: var(--ink-display); }

/* ==== wave 4: microstates + section treatments (memo C2/C3a/C4/B3/D3) =================== */
/* C2 — the page's biggest links answer in three channels (65's liked hover grammar) */
.band-photo .ph img { transition: transform 300ms cubic-bezier(0.33, 1, 0.68, 1); }
.band:hover .band-photo .ph img, .band:focus-visible .band-photo .ph img { transform: scale(1.03); }
.band-name { transition: transform 200ms cubic-bezier(0.33, 1, 0.68, 1); }
.band:hover .band-name, .band:focus-visible .band-name { transform: translateX(8px); }

/* C3a REVERTED 4.8. (memo + owner): rows are inert information — hover stays as a
   reading aid; conversion lives in the CTA band ("Useampi työ samaan pyyntöön — kuvaus
   riittää."). Accordion decision gated on the record drafts (docs/memo-service-list). */

/* C4 — uniform microstate coverage: every interactive element answers in ≤160ms */
.link-secondary, .band-outro a, .seg label, .f input, .f textarea, .menu-nav a, .nav a {
  transition: color 120ms ease-out, background-color 120ms ease-out, border-color 120ms ease-out;
}
.foot-nav a .arrow { transition: transform 120ms ease-out; }
.foot-nav a:hover .arrow { transform: translateX(4px); }

/* B3 — photo bands drift a few percent slower than the page (scroll-driven, zero JS;
   Firefox and reduce get the static band) */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .photo-band .ph { overflow: hidden; }
    .photo-band .ph img {
      height: 116%;
      animation: band-drift linear both;
      animation-timeline: view();
    }
    @keyframes band-drift {
      from { transform: translateY(0); }
      to { transform: translateY(-13%); }
    }
  }
}

/* D3 — TYOLISTA side rail (owner's false-floor concern: the list stays UNBROKEN; photos
   carry mass beside it, anchored top and bottom of the rail; mobile keeps them after
   the list where an ending is correct) */
@media (min-width: 1200px) {
  .tyolista-wrap { display: grid; grid-template-columns: minmax(0, 1fr) minmax(300px, 380px); column-gap: clamp(32px, 4vw, 64px); }
  .tyolista-wrap .detail-duo { grid-template-columns: 1fr; align-content: space-between; margin-top: clamp(32px, 4vw, 56px); }
}

/* ==== wave 3: entrance grammar (memo B1+B2+B4) ==========================================
   Hidden states live ONLY under html.motion (JS-set, never under reduced-motion) AND
   inside no-preference — belt and braces: any failure mode lands on the painted page.
   One family: 500ms ease-out breath, 14px rise, group children cascade via --d. */
@media (prefers-reduced-motion: no-preference) {
  html.motion .rv {
    opacity: 0;
    transform: translateY(14px);
    transition:
      opacity 500ms cubic-bezier(0.33, 1, 0.68, 1) var(--d, 0ms),
      transform 500ms cubic-bezier(0.33, 1, 0.68, 1) var(--d, 0ms);
  }
  html.motion [data-inview].rv,
  html.motion [data-inview] > .rv {
    opacity: 1;
    transform: none;
  }
  /* B4: the eyebrow tick draws in after its section head lands */
  html.motion .sec-head.rv .tick, html.motion .eyebrow--h.rv .tick {
    transform: scaleY(0); transform-origin: bottom left;
    transition: transform 280ms cubic-bezier(0.33, 1, 0.68, 1) 260ms;
  }
  html.motion .sec-head[data-inview] .tick, html.motion .eyebrow--h[data-inview] .tick {
    transform: scaleY(1);
  }
}

/* header hairline: appears on first scroll (a divider as scroll feedback, not depth) */
.site-header { border-bottom: 1px solid transparent; transition: border-color 200ms ease-out; }
html.scrolled .site-header { border-bottom-color: var(--surface-3); }

/* sliding nav indicator (JS enhancement; static per-link underbar is the fallback) */
.nav { position: relative; }
.nav-indicator {
  position: absolute; left: 0; bottom: 2px; height: 3px; width: 1px;
  background: var(--green-mid);
  transform-origin: left center;
  transition: transform 160ms ease-out, opacity 120ms ease-out;
  opacity: 0; pointer-events: none;
}
.js .nav.has-indicator a::after { content: none; }
.nav a[aria-current="page"] { color: var(--green-mid); }
html:not(.js) .nav a[aria-current="page"]::after,
.nav:not(.has-indicator) a[aria-current="page"]::after { transform: scaleX(1); }

@media (prefers-reduced-motion: reduce) {
  .nav a::after { transition: none; transform: scaleX(1); opacity: 0; }
  .nav a:hover::after { opacity: 1; }
  .arrow, .btn, .menu, .band, .burger-bar { transition: none; }
  .btn--primary:hover .arrow { transform: none; }
  .btn--primary:active { transform: none; }
  .menu { transform: none; }
  .palvelu-row h3::after { transition: none; transform: scaleX(1); opacity: 0; }
  .palvelu-row:hover h3::after { opacity: 1; }
  .nav-indicator { transition: none; display: none; }
  .js .nav.has-indicator a::after { content: ''; }
  .nav a[aria-current="page"]::after { opacity: 1; }
  /* wave 4 states go static under reduce */
  .band-photo .ph img, .band-name, .foot-nav a .arrow,
  .link-secondary, .band-outro a, .seg label, .f input, .f textarea, .menu-nav a { transition: none; }
  .band:hover .band-photo .ph img, .band:hover .band-name { transform: none; }
  .foot-nav a:hover .arrow { transform: none; }
}
