/* Canonical SEO article stylesheet — Asuntoanalyysi.
 *
 * SINGLE source of brand/chrome truth for static SEO pages. Pages are
 * GENERATED from scripts/lib/render-seo-page.mjs and link ONLY this file.
 * They cannot drift from the live app brand.
 *
 * Header + footer are a 1:1 port of the live React shell
 * (src/components/shell/Header.jsx, Footer.jsx): charcoal masthead with a
 * Newsreader cream wordmark and a circle-arrow "Aloita analyysi" link;
 * charcoal footer with the serif wordmark, Tili/Käytännöt/Yhteys columns
 * and the legal bar. Tokens mirror src/index.css exactly. Top and bottom
 * are identical on every static page, matching the landing page.
 *
 * Body is the white editorial surface. Content is flush-left to the same
 * gutter as the masthead wordmark (news/blog alignment), not centred.
 *
 * NO cream warmth. NO uppercase text-transform. NO font-variant-caps
 * small-caps (it rendered labels as broken squished caps). NO middot.
 * NO em/en-dash in generated copy. Sentence case only.
 */

/* Metric-matched fallbacks: while Newsreader / Inter Tight download
   (font-display: swap), text renders in local Georgia / Arial scaled to
   the webfont's exact metrics, so the swap changes letterforms but NOT
   layout. Values from @capsizecss/metrics 4.1.0, fontaine formula.
   Keep in sync with the copy in src/index.css. */
@font-face {
  font-family: 'Inter Tight Fallback';
  src: local('Arial');
  size-adjust: 96.3857%;
  ascent-override: 100.5076%;
  descent-override: 25.0256%;
  line-gap-override: 0%;
}
@font-face {
  font-family: 'Newsreader Fallback';
  src: local('Georgia');
  size-adjust: 96.1191%;
  ascent-override: 76.4676%;
  descent-override: 27.5699%;
  line-gap-override: 0%;
}

:root {
  /* Light surface (mirrors --color-white* in src/index.css) */
  --paper:        #ffffff;
  --paper-deep:   #f0f0f0;
  --paper-edge:   #e5e5e5;

  /* Ink on white (mirrors --color-ink*) */
  --ink:          oklch(20% 0.012 240);
  --ink-muted:    oklch(42% 0.008 240);
  --ink-subtle:   oklch(58% 0.006 240);

  --rule:         oklch(84% 0.004 240);

  /* Dark surface (mirrors --color-charcoal / --color-rule-dark) */
  --charcoal:     oklch(16% 0.01 240);
  --rule-dark:    oklch(28% 0.01 240);

  /* Text on charcoal (mirrors --color-cream / -muted / -subtle) */
  --on-charcoal:        #ffffff;
  --on-charcoal-muted:  #d4d4d4;
  --on-charcoal-subtle: #a3a3a3;

  /* Bronze accent (mirrors --color-bronze) */
  --bronze:       oklch(58% 0.09 65);
  /* Bronze lifted for small type on charcoal: --bronze itself sits near
     the 4.5:1 AA line there; this tint clears it with margin. */
  --bronze-bright: oklch(74% 0.09 65);

  /* Brand v14 chart palette (owner-locked 2026-07-21). In site UI petrol is a
     FILL on white only (table header rows, per the owner exception) and the
     data accent inside figures; türkos-dark is the small-accent-text step.
     Everything else in UI chrome stays black/white/gray; bronze stays as the
     hover accent only. */
  --petrol:        oklch(42% 0.06 235);
  --petrol-tint:   oklch(77% 0.032 230);
  --turkos:        oklch(36% 0.11 205);
  --turkos-dark:   oklch(29% 0.10 207);

  /* Page layer: cool mist behind white content sheets (Terakeet-style
     surface layering, 2026-07-20). Brand v14 (2026-07-23): the warm 85-deg
     bronze axis is retired page-wide; the mist and sheet ride the same cool
     240 axis as the ink/slate neutrals. */
  --mist:         oklch(97.3% 0.003 240);
  /* The hero band's sheet tone: a full step deeper than --mist so the
     band reads as a MATERIAL surface against the white content area
     (owner 2026-07-21: near-white flat fill read artificial and weak).
     Ink on this still measures >13:1. */
  --sheet:        oklch(95% 0.006 240);

  --font-serif: 'Newsreader', 'Newsreader Fallback', Georgia, 'Times New Roman', serif;
  --font-sans:  'Inter Tight', 'Inter Tight Fallback', Inter, system-ui, -apple-system, sans-serif;

  /* Shell container = Tailwind max-w-6xl (72rem) + px-6 gutter, exactly
     as Header.jsx / Footer.jsx. The article shares this container so the
     prose left edge aligns with the masthead wordmark. */
  --container: 72rem;
  --pad:       1.5rem;
  /* Editorial reading measure, flush-left within the container.
     40rem = 640px at 17px body = ~75 chars/line (typographic ideal 60-75;
     44rem ran ~85 and read as walls of text). */
  --measure:   40rem;
}

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

html {
  scroll-behavior: smooth;
  /* Anchor/TOC targets land at ~40% from the top (upper-middle), not jammed at the top. */
  scroll-padding-top: 40vh;
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 1.0625rem;            /* 17px */
  line-height: 1.7;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'ss01' 1;
  text-rendering: optimizeLegibility;
}

/* ── Site header — 1:1 with Header.jsx (charcoal masthead) ──────────── */

.site-header {
  background: var(--charcoal);
  position: sticky;
  top: 0;
  z-index: 40;
}

.site-header .inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--pad);
  height: 76px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
}

.site-header a.logo {
  font-family: var(--font-serif);
  font-size: 1.375rem;             /* 22px, matches sm:text-[22px] */
  font-weight: 400;                /* font-normal — NOT 500 */
  line-height: 1;
  letter-spacing: -0.025em;        /* tracking-tight */
  font-variation-settings: 'opsz' 40;
  color: var(--on-charcoal);
  text-decoration: none;
}

.site-header a.cta {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  font-family: var(--font-sans);
  font-size: 0.875rem;             /* 14px */
  letter-spacing: -0.01em;
  color: var(--on-charcoal);
  text-decoration: none;
  transition: color 200ms ease;
}

.site-header a.cta span {
  white-space: nowrap;
}

.site-header a.cta .cta-short {
  display: none;
}

.site-header a.cta:hover {
  color: var(--bronze);
}

/* Mobile: shrink header CTA label to "Laskuri" + keep icon. Prevents 375px overflow. */
@media (max-width: 480px) {
  .site-header a.cta .cta-full {
    display: none;
  }
  .site-header a.cta .cta-short {
    display: inline;
  }
}

/* Mobile: .table-wrap scrolls horizontally; table keeps table-layout. */
@media (max-width: 640px) {
  .table-wrap {
    margin-left: calc(-1 * var(--pad));
    margin-right: calc(-1 * var(--pad));
    padding: 0 var(--pad);
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
  }

  article table {
    font-size: 0.875rem;
  }

  /* Cells WRAP on mobile (no nowrap): all three iter2 auditors watched a
     380px table clip its last column behind an unnoticed scroll. Wrapping
     lets every 2-3 col table fit the 335px content box; .table-wrap
     scrolling stays as the fallback for genuinely wide tables.
     The `article` prefix is load-bearing: the desktop `thead th` /
     `tbody td` rules sit LATER in this file at equal specificity, so a
     bare selector here silently loses the cascade and the desktop
     0.875rem cell padding pushes a 3-col table with one long compound
     header (Rakennusaikakausi) to 357px, clipping the last column
     mid-number behind the scroll. hyphens:auto cannot save it: headless
     Chromium ships no Finnish dictionary, so only the padding math
     (0.5rem: 3 cols x 2 sides x 6px = 36px saved) closes the gap. */
  article thead th {
    font-size: 0.75rem;
    padding: 0.5rem 0.5rem;
  }

  article tbody td,
  article tbody th {
    font-size: 0.8125rem;
    padding: 0.6rem 0.5rem;
  }
}

/* ── Reading progress bar (3px bronze, rides the viewport top edge) ──── */

.read-progress {
  position: fixed;
  /* Sits on the sticky masthead's BOTTOM edge (owner 2026-07-21), not the
     viewport top. 76px = .site-header .inner height; keep in sync. */
  top: 76px;
  left: 0;
  right: 0;
  height: 3px;
  z-index: 60;
  pointer-events: none;
}

.read-progress span {
  display: block;
  height: 100%;
  background: var(--charcoal);
  transform: scaleX(0);
  transform-origin: 0 50%;
}

@media print {
  .read-progress {
    display: none !important;
  }
}

/* ── Article — shares the masthead container, prose flush-left ──────── */

/* The article IS the reading-measure column, centred in the viewport
   (symmetric gutters), matching the live landing page. Children flow
   full-width within it, so per-element `margin: 0 0 Xrem` no longer
   fights a child-level centring rule. */
article {
  max-width: var(--measure);
  margin: 0 auto;
  padding: 4rem var(--pad) 5.5rem;
}

article > * {
  max-width: 100%;
}

.breadcrumb {
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  /* Full ink, weight 500: the path sits directly ON the uniform grid
     texture (no cleared strip behind it), so the text itself carries
     the clarity (owner 2026-07-21). */
  color: var(--ink);
  font-weight: 500;
  margin: 0 0 2rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.625rem;
  align-items: center;
}

.breadcrumb a {
  color: var(--ink);
  text-decoration: none;
}

.breadcrumb a:hover {
  color: var(--bronze);
}

.breadcrumb .sep {
  color: var(--ink-subtle);
  font-weight: 600;
}

/* The page the reader is ON: ink + bold, not a link. */
.breadcrumb > span:last-child {
  color: var(--ink);
  font-weight: 600;
}


.breadcrumb .sep {
  color: var(--ink-subtle);
  opacity: 0.55;
}

h1 {
  font-family: var(--font-serif);
  font-size: clamp(2.125rem, 5vw, 3.25rem);
  line-height: 1.12;
  letter-spacing: -0.021em;
  font-weight: 500;
  font-variation-settings: 'opsz' 60;
  color: var(--ink);
  margin: 0 0 1.25rem;
  text-wrap: balance;
  /* Finnish compounds are single unbreakable words and the H1 is the largest
     type on the page, so one of them can be wider than its own column with no
     wrap opportunity anywhere in it. Measured 2026-08-01 on /aineisto in
     WebKit, 3 runs per width: "Korjauskustannukset" ran 59.6px past a 270px
     box at 360 and 16.5px past a 496px box at 1920, and since nothing here
     clips, the glyphs painted straight off the right edge of the card and off
     the screen -- the reader saw "Korjauskustannukse".
     overflow-wrap is the half that actually guarantees containment: this
     file's own table rules note that headless Chromium ships no Finnish
     dictionary, so hyphens:auto is decoration that works where a dictionary
     exists and does nothing where it does not. Same trio as thead th / tbody
     td below, so the page has one wrapping idiom rather than two. */
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}

/* The lead is a SEAMLESS body intro (owner 2026-07-21: "below the line,
   body text size, we don't need it as a header section"): it opens the
   running text under its own section hairline, right above the first H2. */
.lead {
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  line-height: 1.7;
  font-weight: 400;
  color: var(--ink);
  border-top: 1px solid var(--rule);
  padding-top: 2rem;
  margin: 0 0 1.75rem;
}

/* Reviewer / byline line under the lead (E-E-A-T signal). */
.byline {
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  color: var(--ink-subtle);
  margin: 0;
}

/* ── Split article hero (Terakeet composition, 2026-07-20): photo left,
      breadcrumb + h1 + reading meta right, full content width. On mobile
      the TEXT stacks first (answer-first doctrine), photo after. ───────── */

/* Full-bleed mist band behind the hero zone only (owner 2026-07-20:
   "just the top section should have the background fill"). */
/* The band is a MATERIAL sheet, not a color fill (owner 2026-07-21: the
   flat smooth fill read artificial). Three layers, bottom up: a gentle
   warm tonal gradient (light falls from the top), the mist base, and a
   fine paper-grain tooth from an inline SVG turbulence tile. The grain
   rides at ~4% alpha: visible as surface texture at reading distance,
   irrelevant to text contrast. */
.article-hero-band {
  position: relative;
  overflow: hidden;
  background-color: var(--sheet);
  /* No top-light gradient: a bleached smooth strip under the masthead
     read as a third ambiguous zone (owner 2026-07-21 "now it just looks
     off"). The sheet tone runs uniform from the masthead down; only the
     LINE ART fades in via the .band-art mask, so the breadcrumb sits on
     clean but honest sheet, not on a bleached strip. */
  background-image:
    linear-gradient(to bottom, oklch(20% 0.012 240 / 0) 72%, oklch(20% 0.012 240 / 0.05)),
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='240' height='240'%3E%3Cfilter id='g'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='3' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3CfeComponentTransfer%3E%3CfeFuncA type='linear' slope='0.09'/%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Crect width='240' height='240' filter='url(%23g)'/%3E%3C/svg%3E");
  border-bottom: 1px solid var(--rule);
  padding-bottom: 2.5rem;
}

/* Band motif: the drafting sheet. Kerrostalo elevations drawn as visible
   ink linework with bronze dimension lines — a real composition, not a
   tint (owner 2026-07-20: background elements must read intentional).
   Desktop only; never intercepts input. */
.band-motif {
  display: none;
  position: absolute;
  right: -2rem;
  bottom: 0;
  /* 72%, bottom-anchored: the elevation's top edge must never climb
     into the breadcrumb corridor. At 118% the outline box crossed the
     path text once the art layer spanned the full band (owner caught
     it 2026-07-21). */
  height: 72%;
  width: auto;
  color: var(--ink);
  /* Opacity lives in the SVG's own groups (elevations 0.16, bronze 0.5). */
  pointer-events: none;
}

.band-motif--left {
  right: auto;
  left: -2rem;
  transform: scaleX(-1);
}

.band-motif .band-motif-dim {
  stroke: var(--ink-subtle);
}

/* All band art (motifs + grid) lives in this layer, running UNIFORM from
   the masthead edge down - no fade, no clean strip. Owner 2026-07-21,
   after two fade iterations: a smooth zone meeting a textured zone reads
   as two different backgrounds ("these are different, thats the issue");
   the sheet must be one surface. Breadcrumb legibility comes from full-
   ink crumb text, not from clearing the texture behind it. */
.band-art {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

@media (min-width: 64rem) {
  .band-motif {
    display: block;
  }

  /* Drafting grid under the motif: the band is a survey sheet, not a
     plain cream fill. Blueprint DOT grid at the researched standard
     (Vercel-school blueprint aesthetic, 2026-07-21): dots not lines so
     no stroke can collide with a text stroke, 24px module, ~8% ink.
     The governing rule from the reference: if you notice the pattern
     before the content, it is too strong. Uniform everywhere - no
     masked zones, no seams - and the breadcrumb stays untroubled
     because the pattern is felt, not seen. */
  .band-art {
    background-image:
      radial-gradient(circle at 1px 1px, oklch(20% 0.012 240 / 0.08) 1px, transparent 1.5px);
    background-size: 24px 24px;
  }
}

.article-hero {
  position: relative;
  z-index: 1;
}

.article-hero {
  max-width: 72rem;
  margin: 0 auto;
  padding: 1.25rem 1.25rem 0;
}
/* (position/z-index for .article-hero set above with the motif rules) */

/* The framed hero is the page's one bounded object: 1px ink frame, white
   inside, photo flush against the frame edge (Terakeet composition). */
.article-hero-frame {
  border: 1px solid var(--ink);
  background: var(--paper);
  display: flex;
  flex-direction: column;
}

.article-hero-media {
  order: 2;
}

.article-hero .breadcrumb {
  margin: 0 0 0.875rem;
}

.article-hero-media figure {
  margin: 0;
  height: 100%;
}

.article-hero-media picture {
  display: block;
  height: 100%;
}

.article-hero-media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.article-hero-text {
  order: 1;
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 1.75rem 1.5rem;
}

.article-hero-text h1 {
  margin: 0 0 1.25rem;
}

.hero-meta {
  font-family: var(--font-sans);
  font-size: 0.875rem;
  color: var(--ink-muted);
  margin: 0 0 0.75rem;
}

.hero-author {
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  color: var(--ink);
  margin: 0;
}

.hero-author a {
  color: var(--ink);
  text-decoration: none;
}

.hero-author a:hover,
.hero-author a:hover strong {
  color: var(--bronze);
}

.hero-author strong {
  font-weight: 600;
}

.article-hero-text h1 {
  font-size: clamp(2.25rem, 3.4vw, 3.5rem);
}


@media (min-width: 64rem) {
  .article-hero {
    padding: 1.5rem 2rem 0;
  }

  .article-hero-frame {
    flex-direction: row;
    align-items: stretch;
  }

  .article-hero-media {
    order: 1;
    flex: 0 0 44%;
    min-width: 0;
  }

  .article-hero-frame {
    min-height: 33rem;
  }

  /* Beats the later .page-photo img { height: auto } base rule. The
     max-height cap is for in-article photos; inside the hero frame it
     left a paper gap under the photo, so it is lifted here. */
  .article-hero-media .page-photo img,
  .article-hero-media img {
    height: 100%;
    max-height: none;
    object-fit: cover;
  }

  .article-hero-text {
    order: 2;
    flex: 1;
    min-width: 0;
    padding: 3rem 3.5rem;
  }
}

/* Text-only hero (pages without a hero photo). */
.article-hero--text .article-hero-text {
  max-width: var(--measure);
}

h2 {
  font-family: var(--font-serif);
  font-size: 1.6875rem;
  line-height: 1.2;
  letter-spacing: -0.014em;
  font-weight: 500;
  font-variation-settings: 'opsz' 40;
  color: var(--ink);
  margin: 3.25rem 0 1rem;
  text-wrap: balance;
}

h3 {
  font-family: var(--font-sans);
  font-size: 1.1875rem;
  line-height: 1.3;
  font-weight: 600;
  letter-spacing: -0.006em;
  color: var(--ink);
  margin: 2rem 0 0.625rem;
}

p {
  margin: 0 0 1.125rem;
}

/* One link format everywhere in the reading surfaces (Figure.com model,
   owner 2026-07-21): BOLD ink with an ink underline at rest; hover animates
   the whole link to bronze. Component chrome (masthead, footer, TOC, cards,
   buttons, chips) overrides. */
a {
  color: var(--ink);
  font-weight: 600;
  text-decoration: underline;
  text-decoration-color: currentColor;
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
  transition: color 160ms ease, text-decoration-color 160ms ease;
}

a:hover {
  color: var(--bronze);
  text-decoration-color: var(--bronze);
}

a:focus-visible {
  outline: 2px solid var(--bronze);
  outline-offset: 2px;
  border-radius: 0;
}

/* The bold body-link format must not leak into chrome and meta surfaces
   that carry their own weight scale. */
.breadcrumb a,
.site-header a,
.site-footer a,
.page-photo-credit a,
.vastuu-card-pinpoint-link,
.vastuu-card-lainsitaatti-cite a {
  font-weight: 400;
}

/* Profile page social link (LinkedIn) under the author bio. */
.profile-social {
  margin: 0.5rem 0 0;
}
.profile-social a {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
}
.profile-social a:hover {
  color: var(--bronze);
}
.profile-social svg {
  width: 18px;
  height: 18px;
  flex-shrink: 0;
}

ul,
ol {
  margin: 0 0 1.25rem;
  padding-left: 1.4rem;
}

li {
  margin-bottom: 0.5rem;
}

li::marker {
  color: var(--ink-subtle);
}

strong {
  font-weight: 600;
  color: var(--ink);
}

/* ── Definition block — white, left bronze rule (no grey fill) ──────── */

/* Named block system (owner 2026-07-20): each top-of-article object is a
   TITLED module with its own structural signal — Tiivistelmä a faint
   bronze-tint fill, Avaintiedot a bronze top rule, Määritelmä an ink top
   rule + serif prose. No soft gray rectangles. */
.block-label {
  font-family: var(--font-sans);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--ink-muted);
  margin: 0 0 0.875rem;
}

/* (lead-block wrapper retired 2026-07-20: the lead is a plain standfirst,
   not a labelled "Tiivistelmä" panel — the label overclaimed.) */

/* Määritelmä card (Terakeet term-card anatomy, our tokens): mist panel
   with the tool-card family's 1px ink frame (owner 2026-07-21: "hard
   black borders"), thin-bordered glyph square, tracked eyebrow, bold
   term, serif body. */
.definition {
  background: var(--mist);
  border: 1px solid var(--ink);
  padding: 1.75rem 2rem;
  margin: 1.75rem 0 2.75rem;
  display: grid;
  grid-template-columns: 3.25rem minmax(0, 1fr);
  gap: 0.25rem 1.5rem;
}

.definition-icon {
  grid-column: 1;
  width: 3.25rem;
  height: 3.25rem;
  border: 1px solid var(--ink);
  background: var(--paper);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--ink);
  user-select: none;
}

.definition-icon svg {
  width: 1.875rem;
  height: 1.875rem;
  display: block;
}

.definition-body {
  grid-column: 2;
  min-width: 0;
}

.definition-body .block-label {
  margin: 0.125rem 0 0.375rem;
}

.definition-term {
  font-family: var(--font-sans);
  font-size: 1.3125rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  color: var(--ink);
  margin: 0 0 0.625rem;
}

.definition p {
  margin: 0;
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  line-height: 1.65;
}

.definition p + p {
  margin-top: 0.875rem;
}

@media (max-width: 40rem) {
  .definition {
    padding: 1.375rem 1.375rem 1.5rem;
    grid-template-columns: 2.75rem minmax(0, 1fr);
    gap: 0.25rem 1rem;
  }

  .definition-icon {
    width: 2.75rem;
    height: 2.75rem;
  }

  .definition-icon svg {
    width: 1.5rem;
    height: 1.5rem;
  }
}

/* Avaintiedot: the page's headline module (owner 2026-07-21, "one of the
   most important"). Strong charcoal rule (brand v14 monochrome UI), larger
   facts, two calm columns on desktop so six points read as a fact panel,
   not a cramped list. */
.key-takeaways {
  border-top: 2px solid var(--charcoal);
  padding: 1.5rem 0 0;
  margin: 0 0 2.75rem;
}

.key-takeaways + .definition {
  margin-top: 2.5rem;
}

.key-takeaways h2 {
  font-family: var(--font-sans);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--ink-muted);
  margin: 0 0 1.125rem;
}

.key-takeaways ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: 1fr;
  gap: 0.875rem;
}

.key-takeaways li {
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  line-height: 1.55;
  margin: 0;
  position: relative;
  padding-left: 1.375rem;
}

.key-takeaways li::before {
  content: '>';
  position: absolute;
  left: 0;
  top: 0;
  color: var(--charcoal);
  font-weight: 700;
}

article > ul > li::marker {
  content: '>\a0\a0';
  color: var(--charcoal);
  font-family: var(--font-sans);
  font-weight: 700;
}

/* ── Callout (promoted money sentence, bronze rule, no fill) ─────────── */

.callout {
  border-left: 3px solid var(--charcoal);
  padding: 0.25rem 0 0.25rem 1.25rem;
  margin: 1.75rem 0 2rem;
  font-family: var(--font-serif);
  font-size: 1.1875rem;
  line-height: 1.5;
  font-weight: 500;
  color: var(--ink);
}

/* ── Cost / data tables (clean bordered, editorial) ─────────────────── */

.table-wrap {
  margin: 1.75rem 0;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  /* Swipe cue: edge shadows appear only when content actually overflows
     (scroll-driven background-attachment trick, no JS). */
  background:
    linear-gradient(to right, var(--paper), var(--paper)),
    linear-gradient(to right, var(--paper), var(--paper)),
    linear-gradient(to right, oklch(20% 0.012 240 / 0.14), transparent),
    linear-gradient(to left, oklch(20% 0.012 240 / 0.14), transparent);
  background-position: left center, right center, left center, right center;
  background-repeat: no-repeat;
  background-size: 28px 100%, 28px 100%, 14px 100%, 14px 100%;
  background-attachment: local, local, scroll, scroll;
}

table {
  width: 100%;
  border-collapse: collapse;
  /* Editorial rule structure (owner review 2026-07-23, variant B): horizontal
     rules only, three weights -- strong ink rule on top, thin ink rule under
     the header (on thead th), closing ink rule at the bottom. No frame, no
     vertical separators, open left/right edges. Equal-width lining figures so
     digit columns stack. */
  border-top: 2px solid var(--ink);
  border-bottom: 1px solid var(--ink);
  font-variant-numeric: lining-nums tabular-nums;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  /* table-layout: auto so columns size to content; long Finnish compounds
     (Tietoliikennekaapelointi, Rakennusautomaatio, Lämmitysjärjestelmä)
     get the room they need, narrow numeric columns ("85") shrink to fit.
     If a row still overflows the container, .table-wrap scrolls. The
     previous `table-layout: fixed` distributed width equally and forced
     mid-syllable breaks on the label column. */
}

caption {
  text-align: left;
  font-size: 0.8125rem;
  color: var(--ink);
  margin-bottom: 0.625rem;
}

/* Source footnote under a data table. Small, muted, consistent across
   all SEO pages so reader brains stop registering it as body content
   and learn to skim past as attribution. Use `<p class="table-source">`
   directly after a `</div>` closing a `.table-wrap`. */
.table-source {
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  /* Full ink, never gray (owner 2026-07-23: "make the fonts always black"):
     smaller size alone marks it as attribution. */
  color: var(--ink);
  margin: -1rem 0 1.75rem 0;
  line-height: 1.5;
}

/* Header row — deterministic premade treatment, identical on every table:
   plain semibold ink over an ink hairline (editorial variant B, owner review
   2026-07-23; replaces the petrol bar fill of brand v14 -- prestige sources
   are unanimous that headers are separated by rules, never fills). One
   shared rule, so no per-page table styling and no "sparse/broken" header. */
thead th {
  text-align: left;
  font-weight: 600;
  font-size: 0.8125rem;
  color: var(--ink);
  border-bottom: 1px solid var(--ink);
  padding: 0.55rem 0.875rem 0.4rem;
  vertical-align: bottom;
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}

tbody td {
  border-bottom: 1px solid var(--rule);
  padding: 0.55rem 0.875rem 0.5rem;
  line-height: 1.35;
  vertical-align: middle;
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}

/* Row-header cells (<th> inside <tbody>) — browser default centres them; the
 * SEO comparison tables use them as left-side row labels, so override to match
 * `tbody td:first-child` styling. */
tbody th {
  text-align: left;
  font-weight: 500;
  border-bottom: 1px solid var(--rule);
  padding: 0.55rem 0.875rem 0.5rem;
  line-height: 1.35;
  vertical-align: middle;
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}

tbody tr:last-child td,
tbody tr:last-child th {
  /* Table's own 1px border owns the bottom edge; no double hairline. */
  border-bottom: none;
}

/* Numeric cells: right-aligned so digit columns stack (the table already
   sets equal-width lining figures). Nowrap keeps ranges like
   "85 000-225 000 €/hissi" on one line; .table-wrap scrolls as fallback. */
th.num,
td.num {
  text-align: right;
  white-space: nowrap;
}

/* Category group rows: a bundle header carrying its own subtotal (owner
   2026-07-23). Bold text, a heavier ink rule under the row, and the
   subcomponent rows that follow indent so the hierarchy reads at a glance. */
table.grouped tbody tr.group td {
  font-weight: 700;
  border-bottom: 1.5px solid var(--ink);
  padding-top: 0.7rem;
}
table.grouped tbody tr:not(.group) td:first-child {
  padding-left: 1.9rem;
}

/* Links inside tables: the global bold+underline link style reads busy when
   nearly every row is a link (owner 2026-07-23). Quiet print treatment: the
   row's own weight with a light gray hairline underline (no arrow glyphs,
   owner 2026-07-23 second round); full-ink underline on hover. */
table a {
  font-weight: inherit;
  text-decoration: underline;
  text-decoration-color: var(--rule);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.22em;
}
table a:hover {
  text-decoration-color: currentColor;
}

tbody td:first-child {
  font-weight: 500;
  /* First-column labels are long Finnish compounds (Lämmitysjärjestelmä,
     Rakennusautomaatio, Vedenkulutuksen etäluettavuus). With
     table-layout: auto (set on `table`) the column sizes to content, so
     the only remaining wrap case is a single word longer than the
     container. Hyphens: auto delegates to the browser's Finnish
     hyphenation dictionary (renderer sets lang="fi" on <html>); on
     browsers without it, overflow-wrap: break-word falls back to a
     word-boundary break, never mid-syllable. */
  min-width: 12ch;
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}

/* Inline <code> in prose (e.g. a Finlex URL cited in a list item) must wrap.
   A long unbroken token has no break opportunity and otherwise pushes the page
   wider than the mobile viewport: /asunto-osakeyhtiolaki at 360px measured 72px
   of horizontal overflow from <code>finlex.fi/fi/laki/ajantasa/2009/20091599</code>.
   Break anywhere so the URL folds inside the content column. */
code {
  overflow-wrap: anywhere;
  word-break: break-word;
}

/* ── CTA card — editorial in-column module (redesigned 2026-07-20, owner:
      the charcoal slab read as an ad banner, "not editorial at all").
      Newsroom in-column signature instead: a strong ink rule on top, a
      hairline below, serif body at article voice, bordered button. No
      background slab, no fill. ────────────────────────────────────────── */

/* Conversion card in the approved tool-card language (owner 2026-07-21:
   the charcoal slab read as a banner and was rejected; the widget frame
   was approved). Same anatomy as .vastuu-search: mist panel, 1px ink
   border, eyebrow, serif question title. The CHARCOAL BUTTON is the one
   dark element, so the conversion weight sits on the action itself. */
.cta-card {
  margin: 3rem 0 2.5rem;
  padding: 1.75rem 2rem 2rem;
  border: 1px solid var(--ink);
  background: var(--mist);
  color: var(--ink);
}

.cta-eyebrow {
  font-family: var(--font-sans);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--ink-muted);
  margin: 0 0 0.5rem;
}

.cta-question {
  margin: 0 0 0.625rem;
  font-family: var(--font-serif);
  font-size: 1.4375rem;
  font-weight: 500;
  font-variation-settings: 'opsz' 32;
  line-height: 1.3;
  color: var(--ink);
  max-width: 30ch;
}

.cta-question strong {
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 600;
}

.cta-sub {
  margin: 0 0 1.5rem;
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink);
  max-width: 52ch;
}

.cta-card a {
  display: inline-flex;
  align-items: center;
  gap: 0.75rem;
  background: var(--charcoal);
  color: var(--on-charcoal);
  border: 1px solid var(--charcoal);
  text-decoration: none;
  font-family: var(--font-sans);
  font-weight: 600;
  font-size: 1rem;
  padding: 0.9rem 1.75rem;
  white-space: nowrap;
  transition: background 150ms ease, color 150ms ease, border-color 150ms ease;
}

.cta-card a svg {
  flex-shrink: 0;
  display: block;
}

.cta-card a:hover {
  background: var(--bronze);
  border-color: var(--bronze);
  color: var(--on-charcoal);
}

.cta-card a:focus-visible {
  outline: 2px solid var(--bronze);
  outline-offset: 2px;
}

/* ── Related — full-width "Lue myös" band after the article shell.
      Landing ArticlesSection system (eyebrow + short ink rule + serif
      heading) with Investopedia card anatomy: photo top, white fill below
      with category eyebrow, serif title, one-sentence explainer. ───────── */

/* Calm band (owner 2026-07-21: motif + grid here read busy): plain mist,
   the cards carry the section. The drafting composition lives in the hero. */
.related {
  position: relative;
  overflow: hidden;
  background: var(--mist);
  padding: 3.5rem 0 4rem;
  margin-top: 4rem;
}

.related-inner {
  position: relative;
  z-index: 1;
}

.related-inner {
  max-width: 72rem;
  margin: 0 auto;
  padding: 0 1.25rem;
}

@media (min-width: 44rem) {
  .related-inner {
    padding: 0 2rem;
  }
}

.related-eyebrow {
  font-family: var(--font-sans);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--ink);
  margin: 0;
}

.related-rule {
  width: 2.5rem;
  height: 1px;
  background: var(--ink);
  margin: 0.75rem 0 0;
}

.related h2 {
  font-family: var(--font-serif);
  font-weight: 400;
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.05;
  letter-spacing: -0.015em;
  font-variation-settings: 'opsz' 56;
  color: var(--ink);
  margin: 1.75rem 0 2rem;
}

.related ul {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  grid-template-columns: 1fr;
  gap: 1.5rem;
}

@media (min-width: 36rem) {
  .related ul {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (min-width: 64rem) {
  .related ul {
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 1.75rem;
  }
}

.related li {
  margin: 0;
  min-width: 0;
}

.related a {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: var(--paper);
  color: var(--ink);
  text-decoration: none;
}

.related picture {
  display: block;
}

/* Picture-forward card (owner 2026-07-21): taller photo, tighter white
   body, smaller type. */
.related img {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}

.related-body {
  display: block;
  padding: 0.875rem 1rem 1.125rem;
  /* Uniform white section on EVERY card (owner 2026-07-21): sized for a
     two-line title + eyebrow so per-row title length never changes the box. */
  min-height: 6.75rem;
}

.related-cat {
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 600;
  color: var(--ink);
  margin: 0 0 0.375rem;
}

.related-title {
  font-family: var(--font-serif);
  font-size: 1.0625rem;
  font-weight: 400;
  line-height: 1.3;
  letter-spacing: -0.005em;
  font-variation-settings: 'opsz' 24;
  margin: 0;
}

.related a:hover .related-title {
  text-decoration: underline;
  text-decoration-thickness: 1px;
  text-underline-offset: 6px;
}


/* ── Sources + reviewer line (small, muted) ─────────────────────────── */

.sources {
  margin-top: 2.5rem;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  color: var(--ink-muted);
}

.sources h2 {
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--ink-muted);
  margin: 0 0 1rem;
}

.sources ol {
  padding-left: 1.25rem;
  margin: 0.875rem 0 0;
}

/* Collapsed sources panel. Marker stripped via ::marker ONLY — never change
   the summary's own display (display:inline-block suppresses the iOS
   VoiceOver expanded/collapsed announcement). Chevron is a pseudo-element. */
.sources-panel summary {
  cursor: pointer;
  color: var(--ink-muted);
  line-height: 1.55;
  padding: 0.25rem 0;
}

.sources-panel summary::marker {
  content: '';
}

.sources-panel summary::-webkit-details-marker {
  display: none;
}

.sources-panel summary::before {
  content: '';
  display: inline-block;
  width: 0.4375rem;
  height: 0.4375rem;
  margin-right: 0.625rem;
  border-right: 1.5px solid var(--ink-muted);
  border-bottom: 1.5px solid var(--ink-muted);
  transform: rotate(-45deg) translateY(-1px);
  transition: transform 0.15s ease;
}

.sources-panel[open] summary::before {
  transform: rotate(45deg) translateY(-2px);
}

.sources-panel summary:hover {
  color: var(--ink);
}

.sources-panel summary:focus-visible {
  outline: 2px solid var(--bronze);
  outline-offset: 2px;
}

@media print {
  .sources-panel summary::before {
    display: none;
  }
}

.sources li {
  margin-bottom: 0.625rem;
  /* 1.6: tolerance for the metric-matched fallback frame; the lavish
     in-iframe audit twice sampled a transient glyph overlap here during
     font swap (persistent:false both times). */
  line-height: 1.6;
}

.sources .updated {
  font-size: 0.8125rem;
  color: var(--ink-muted);
  margin: 1.5rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
}

/* ── Site footer — 1:1 with Footer.jsx (charcoal) ───────────────────── */

.site-footer {
  background: var(--charcoal);
  /* Same inset as the TOC drawer above, for the same reason and one that is
     sharper here. The banner is fixed, full bleed and bottom: 0, so it paints
     over the foot of the LAST block on the page — and the page is already at
     its scroll end there, so nothing can be scrolled into view. Measured with
     the banner up: Kuvalahteet and Evasteasetukset occluded at 360, and
     Evasteasetukset at 1440.
     Evasteasetukset being covered is thin on its own, since it withdraws a
     consent the banner is at that moment still offering to refuse. Kuvalahteet
     is not thin: it is the CC BY 4.0 attribution page for the landing film
     photo (STATIC_CREDITS in scripts/lib/render-seo-page.mjs), so while the
     banner is up the licence condition has no reachable surface at all.
     --consent-banner-h is absent whenever no banner is up, so this resolves
     back to 0 and the footer keeps its own spacing. */
  padding-bottom: var(--consent-banner-h, 0px);
}

.site-footer .inner {
  max-width: var(--container);
  margin: 0 auto;
  padding: 0 var(--pad);
}

.site-footer .foot-top {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: space-between;
  gap: 2.5rem;
  padding: 4rem 0 2.5rem;
  border-top: 1px solid var(--rule-dark);
}

.site-footer .foot-brand {
  font-family: var(--font-serif);
  font-weight: 400;
  letter-spacing: -0.025em;
  font-size: 28px;
  line-height: 1.1;
  font-variation-settings: 'opsz' 40;
  color: var(--on-charcoal);
  margin: 0;
}

.site-footer .foot-cols {
  display: grid;
  grid-template-columns: auto auto;
  gap: 2rem 3rem;
  text-align: right;
}

.site-footer .foot-col {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
}

.site-footer .foot-col-label {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: 0.16em;
  color: var(--on-charcoal-subtle);
  margin: 0 0 0.75rem;
}

.site-footer .foot-col a {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--on-charcoal-muted);
  text-decoration: none;
  margin-bottom: 0.5rem;
  transition: color 160ms ease;
}

.site-footer .foot-col a:last-child {
  margin-bottom: 0;
}

.site-footer .foot-col a:hover {
  color: var(--bronze);
}

.site-footer .foot-legal {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  padding: 1.5rem 0;
  border-top: 1px solid var(--rule-dark);
}

.site-footer .foot-legal span {
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--on-charcoal-subtle);
}

/* ── Lead photo (one real, free-licensed image) ─────────────────────── */

.page-photo {
  margin: 0 0 2.5rem;
}

.page-photo-inline {
  margin: 3rem 0;
}

/* Founder portrait: a face, not a hero. Apex pattern (Vercel/Framer/Figma):
 * small diameter, clip on wrapper (not img) to avoid sub-pixel edge artefacts,
 * face-frame via object-position upper-third. */
.page-photo-portrait {
  width: 9rem;
  height: 9rem;
  margin: 0 0 1.5rem;
  border-radius: 50%;
  overflow: hidden;
  background: var(--paper-deep);
}

.page-photo-portrait img {
  width: 100%;
  height: 100%;
  display: block;
  border-radius: 0;
  object-fit: cover;
  object-position: 50% 28%;
}

.page-photo img {
  display: block;
  width: 100%;
  height: auto;
  /* Height cap: a portrait or over-tall source must not become a wall.
   * Sits just above the ~510px landscape render, so landscape photos are
   * untouched; only over-tall images clamp + crop to an editorial band. */
  max-height: 520px;
  object-fit: cover;
  object-position: 50% 50%;
  background: var(--paper-deep);
}

.page-photo-credit {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  color: var(--ink-subtle);
  margin: 0.5rem 0 0;
}

.page-photo-credit a {
  color: var(--ink-subtle);
  text-decoration: underline;
  text-decoration-color: var(--ink-subtle);
  text-underline-offset: 0.16em;
}

.page-photo-credit a:hover {
  color: var(--bronze);
}

/* ── Content hub (/oppaat) list ─────────────────────────────────────── */

.hub ul {
  margin: 1.5rem 0 0;
  padding: 0;
  list-style: none;
}

.hub li {
  margin: 0 0 1.25rem;
  padding-bottom: 1.25rem;
  border-bottom: 1px solid var(--rule);
}

.hub li:last-child {
  border-bottom: none;
}

.hub li a {
  font-family: var(--font-serif);
  font-size: 1.25rem;
  font-weight: 500;
  color: var(--ink);
  text-decoration: none;
}

.hub li a:hover {
  color: var(--bronze);
}

.hub-desc {
  display: block;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  color: var(--ink-subtle);
  margin-top: 0.375rem;
}

/* ── Focus visible (bronze ring, works on light + charcoal) ─────────── */

a:focus-visible,
summary:focus-visible {
  outline: 2px solid var(--bronze);
  outline-offset: 3px;
  border-radius: 0;
}

/* ── Wider gutter on larger viewports (matches sm:px-8) ──────────────── */

@media (min-width: 40rem) {
  :root {
    --pad: 2rem;
  }
}

/* ── Mobile (single column, left-aligned footer) ────────────────────── */

@media (max-width: 40rem) {
  :root {
    --pad: 1.25rem;
  }

  body {
    font-size: 1rem;
    line-height: 1.65;
  }

  article {
    padding-top: 2.5rem;
    padding-bottom: 4rem;
  }

  .lead {
    font-size: 1.1875rem;
  }

  h2 {
    font-size: 1.4375rem;
    margin-top: 2.5rem;
  }

  h3 {
    font-size: 1.0625rem;
  }

  .cta-card {
    padding: 1.5rem 1.375rem;
    flex-direction: column;
    align-items: flex-start;
  }

  .cta-card a {
    align-self: stretch;
    justify-content: center;
  }

  .site-footer .foot-top {
    flex-direction: column;
    align-items: flex-start;
    gap: 2rem;
  }

  .site-footer .foot-cols {
    text-align: left;
  }

  .site-footer .foot-col {
    align-items: flex-start;
  }
}

/* ── Print (clean, ink on white, no chrome) ─────────────────────────── */

@media print {
  @page {
    margin: 18mm 16mm;
  }

  body {
    background: #fff;
    color: #000;
    font-size: 11pt;
    line-height: 1.45;
  }

  .site-header,
  .site-footer,
  .cta-card,
  .related {
    display: none !important;
  }

  article,
  article > * {
    max-width: 100%;
    padding: 0;
  }

  a {
    color: #000;
    text-decoration: underline;
  }

  .definition {
    border-left: 2px solid #000;
  }

  h1, h2, h3 {
    page-break-after: avoid;
    break-after: avoid;
  }

  tr, li {
    page-break-inside: avoid;
    break-inside: avoid;
  }

  thead th {
    background: transparent;
    color: #000;
    border-bottom: 1.5px solid #000;
  }

  tbody td {
    border-bottom: 1px solid #999;
  }
}

/* ── Reduced motion ─────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  *,
  *::before,
  *::after {
    transition-duration: 0.01ms !important;
  }
}

/* ── Vastuunjakohaku — inline interactive search on /vastuunjakotaulukko.
      Editorial card: light surface, bronze accents, charcoal CTA tokens
      reused from the rest of the chrome. No new brand surface, no new
      fonts. Result cards stack vertically; verdict pill encodes
      osakas / yhtio / jaettu with a colour-blind-safe colour + label. */

/* Instrument frame (2026-07-20 redesign): the widget is a bounded TOOL,
   not restyled prose. Ink frame + mist fill (the hero frame's sibling),
   tracked eyebrow naming it, real bordered input, boxed chip buttons. */
.vastuu-search {
  border: 1px solid var(--ink);
  background: var(--mist);
  padding: 1.75rem 2rem 2rem;
  margin: 3rem 0;
}

.vastuu-search .block-label {
  margin: 0 0 0.5rem;
}

.vastuu-search-title {
  font-family: var(--font-serif);
  font-size: 1.4375rem;
  font-weight: 500;
  font-variation-settings: 'opsz' 32;
  letter-spacing: -0.01em;
  margin: 0 0 1.125rem;
}

.vastuu-search-help {
  margin: 0 0 1rem;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  line-height: 1.5;
  color: var(--ink-muted);
}

.vastuu-search-input-row {
  margin: 0 0 0.75rem;
}

.vastuu-search-input {
  width: 100%;
  font: inherit;
  font-size: 1.0625rem;
  padding: 0.85rem 1rem;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid var(--ink);
  border-radius: 0;
  appearance: none;
  cursor: text;
  transition: border-color 150ms ease;
}

.vastuu-search-input:hover {
  border-color: var(--bronze);
}

.vastuu-search-input:focus-visible {
  outline: 2px solid var(--bronze);
  outline-offset: 2px;
  border-color: var(--bronze);
}

.vastuu-search-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin: 0.75rem 0 1.25rem;
}

/* Chips are unmistakably pressable: bordered boxes on paper, charcoal
   inversion on hover (never underlined text pretending to be a link). */
.vastuu-search-chip {
  font-family: var(--font-sans);
  font-size: 0.875rem;
  font-weight: 500;
  background: var(--paper);
  color: var(--ink);
  border: 1px solid oklch(60% 0.008 240);
  border-radius: 0;
  min-height: 36px;
  padding: 0.4rem 0.9rem;
  cursor: pointer;
  transition: background 140ms ease, color 140ms ease, border-color 140ms ease;
}

.vastuu-search-chip:hover {
  background: var(--charcoal);
  border-color: var(--charcoal);
  color: var(--on-charcoal);
}

.vastuu-search-chip:focus-visible {
  outline: 2px solid var(--bronze);
  outline-offset: 2px;
}

/* Selected chip: same charcoal inversion as hover, but persistent. Synced
   to the query text by the widget script (typing the term = pressing it). */
.vastuu-search-chip.is-active {
  background: var(--charcoal);
  border-color: var(--charcoal);
  color: var(--on-charcoal);
}

/* Density redesign: borderless rows, hairline divider, rectangular pills.
   See docs/superpowers/specs/2026-05-18-vastuunjako-density-design.html. */
.vastuu-search-results {
  display: flex;
  flex-direction: column;
  margin-top: 0.75rem;
}

.vastuu-search-results:empty {
  display: none;
}

.vastuu-card {
  padding: 0.85rem 0;
}

.vastuu-card + .vastuu-card {
  border-top: 1px solid var(--rule);
}

.vastuu-card-head {
  display: flex;
  flex-wrap: nowrap;
  align-items: flex-start;
  justify-content: space-between;
  gap: 0.5rem 1rem;
  margin: 0 0 0.35rem;
}

.vastuu-card-title-cell {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.45rem;
  min-width: 0;
  flex: 1 1 auto;
}

.vastuu-card-tyo {
  font-family: var(--font-serif);
  font-size: 1.125rem;
  font-weight: 500;
  font-variation-settings: 'opsz' 24;
  margin: 0;
  color: var(--ink);
}

.vastuu-card-verdict {
  font-family: var(--font-sans);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.18rem 0.6rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
  flex: 0 0 auto;
  align-self: flex-start;
}

.vastuu-verdict-yhtio {
  background: var(--yhtio-bg, oklch(94% 0.05 145));
  color: oklch(28% 0.08 145);
}

.vastuu-verdict-osakas {
  background: var(--osakas-bg, oklch(95% 0.04 245));
  color: oklch(30% 0.08 245);
}

.vastuu-verdict-jaettu {
  background: var(--jaettu-bg, oklch(95% 0.04 75));
  color: oklch(30% 0.09 75);
}

.vastuu-card-rationale {
  margin: 0 0 0.35rem;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--ink);
}

/* Default-visible bronze-underlined click-out to Finlex. The whole
   pinpoint string ("AOYL 4 luku 2 §") plus a small "→ Finlex" affordance. */
.vastuu-card-pinpoint-link {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  color: var(--ink-muted);
  text-decoration: underline;
  text-decoration-color: var(--ink-subtle);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  margin: 0;
}

.vastuu-card-pinpoint-link:hover {
  color: var(--bronze);
}

/* Plain-text pinpoint fallback when the row has no Finlex URL. */
.vastuu-card-pinpoint {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  color: var(--ink-subtle);
  font-weight: 500;
}

/* Inline scenario tag sits next to the title. Load-bearing on derivative
   rows: tells the reader at a glance that this answer is for a special
   case (vaurio, ilmoittamaton muutos, vakuutus, yhtiöjärjestys, ...). */
.vastuu-card-scenario-tag {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--ink-muted);
}

/* Disclosure: verbatim AOYL § quote + huom + oikeuskäytäntö cases live
   here so the collapsed card stays four lines. Summary text names what's
   inside (e.g. "Lue AOYL 4:2 ja oikeustapaukset: KKO 2003:80") rather
   than a generic label. */
.vastuu-card-details {
  margin: 0.5rem 0 0;
}

.vastuu-card-details-summary {
  cursor: pointer;
  list-style: none;
  padding: 0.2rem 0;
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  color: var(--ink-muted);
}

.vastuu-card-details-summary::-webkit-details-marker {
  display: none;
}

.vastuu-card-details-summary::before {
  content: '';
  display: inline-block;
  width: 0.375rem;
  height: 0.375rem;
  margin-right: 0.5rem;
  border-right: 1.5px solid var(--ink-muted);
  border-bottom: 1.5px solid var(--ink-muted);
  transform: rotate(-45deg) translateY(-1px);
  transition: transform 0.15s ease;
}

.vastuu-card-details[open] .vastuu-card-details-summary::before {
  transform: rotate(45deg) translateY(-2px);
}

.vastuu-card-details-summary:hover {
  color: var(--ink);
}

.vastuu-card-details-body {
  margin: 0.5rem 0 0;
}

/* Verbatim Finlex/Pelastuslaki § snippet inside the disclosure body. */
.vastuu-card-lainsitaatti {
  margin: 0 0 0.55rem;
  padding: 0.75rem 1rem;
  background: var(--paper);
  font-family: var(--font-serif);
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--ink);
}

.vastuu-card-lainsitaatti-cite {
  display: block;
  margin-top: 0.4rem;
  font-style: normal;
  font-size: 0.75rem;
  color: var(--ink-subtle);
}

.vastuu-card-lainsitaatti-cite a {
  color: var(--ink-muted);
  text-decoration: underline;
  text-decoration-color: var(--ink-subtle);
  text-underline-offset: 2px;
}

.vastuu-card-lainsitaatti-cite a:hover {
  color: var(--bronze);
}

/* Huom inside disclosure: plain muted paragraph, no tinted block. */
.vastuu-card-huom {
  margin: 0 0 0.55rem;
  font-family: var(--font-sans);
  font-size: 0.875rem;
  line-height: 1.55;
  color: var(--ink-muted);
}

/* Oikeuskäytäntö cases inside disclosure. The disclosure summary already
   names what's inside, so we drop the redundant uppercase header. */
.vastuu-card-oikeuskaytanto {
  margin: 0;
}

.vastuu-card-oikeuskaytanto-item {
  margin: 0 0 0.3rem;
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  line-height: 1.5;
  color: var(--ink);
}

.vastuu-card-oikeuskaytanto-case {
  font-weight: 600;
}

.vastuu-card-oikeuskaytanto-case[href] {
  text-decoration: underline;
  text-decoration-color: var(--ink-subtle);
  text-underline-offset: 2px;
  color: var(--ink);
}

.vastuu-card-oikeuskaytanto-case[href]:hover {
  color: var(--bronze);
}

.vastuu-card-oikeuskaytanto-more {
  margin: 0.35rem 0 0;
  border-top: 1px dashed var(--line, #d6d2c8);
  padding-top: 0.4rem;
}

.vastuu-card-oikeuskaytanto-more > summary {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  color: var(--ink-muted);
  cursor: pointer;
  list-style: none;
  padding: 0.15rem 0;
  user-select: none;
  font-weight: 600;
}

.vastuu-card-oikeuskaytanto-more > summary::-webkit-details-marker {
  display: none;
}

.vastuu-card-oikeuskaytanto-more > summary::before {
  content: "+ ";
  display: inline;
  margin-right: 0.15rem;
}

.vastuu-card-oikeuskaytanto-more[open] > summary::before {
  content: "− ";
}

.vastuu-card-oikeuskaytanto-more[open] > summary {
  margin-bottom: 0.35rem;
}

.vastuu-card-oikeuskaytanto-more > summary:hover {
  color: var(--ink, #1b1b1b);
}

.vastuu-card-oikeuskaytanto-more > .vastuu-card-oikeuskaytanto-item {
  margin-left: 0.5rem;
}

.vastuu-search-empty {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--ink-muted);
}

.vastuu-search-meta {
  margin: 0.875rem 0 0;
  font-family: var(--font-sans);
  font-size: 0.75rem;
  color: var(--ink-subtle);
}

.vastuu-search-full-cta {
  margin: 1.1rem 0 0;
  padding-top: 1rem;
  border-top: 1px solid var(--rule);
  font-family: var(--font-sans);
  font-size: 0.875rem;
}

.vastuu-search-full-cta a {
  color: var(--ink);
  text-decoration: underline;
  text-decoration-color: var(--ink-subtle);
  text-decoration-thickness: 1px;
  text-underline-offset: 0.2em;
}

.vastuu-search-full-cta a:hover {
  color: var(--bronze);
  text-decoration-thickness: 2px;
}

@media (max-width: 36rem) {
  .vastuu-search { padding: 1.25rem 1.125rem 1.375rem; }
  .vastuu-card-head { flex-direction: column; align-items: flex-start; }
  .vastuu-card-tyo { font-size: 0.9375rem; }
  .vastuu-card-rationale { font-size: 0.875rem; }
}

/* ── Page-scoped vastuujakohaku (Widget A) — same shell, narrower scope.
      Used on per-renovation pages with inlineToolOptions.filter set. The
      hub at /vastuunjakotaulukko renders without this class and keeps the
      original unfiltered styling. Polish round may drop the bronze
      left-rule here to differentiate scoped vs hub; for now we keep the
      visual hint via `.vastuu-search-scoped`. */
.vastuu-search-scoped {
  /* Inherits everything from .vastuu-search. Reserved for the polish
     round (drop bronze rule etc.); behaviour is unchanged by default. */
}

/* ── Widget B — AOYL päätös-aikajana (vertical stepper) ───────────────── */

/* Infographic redesign (2026-07-20): a real timeline object. Strong 2px
   ink spine, solid charcoal numeral tiles riding it (masthead/table-header
   echo), serif step titles, statute pinpoints as bordered chips. */
.aoyl-aikajana {
  border-top: 2px solid var(--ink);
  padding: 1.75rem 0 0.5rem;
  margin: 3rem 0;
}

.aoyl-aikajana .block-label {
  margin: 0 0 0.5rem;
}

.aoyl-aikajana-title {
  font-family: var(--font-serif);
  font-size: 1.4375rem;
  font-weight: 500;
  font-variation-settings: 'opsz' 32;
  letter-spacing: -0.01em;
  margin: 0 0 0.625rem;
  color: var(--ink);
}

/* Selector carries `p.` on purpose: the generic `.aoyl-aikajana p` rule
   below outranks a bare class, and it silently ate every previous attempt
   to put air between this intro and the first step (owner asked 10x). */
.aoyl-aikajana p.aoyl-aikajana-help {
  margin: 0 0 4rem;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  line-height: 1.55;
  color: var(--ink-muted);
  max-width: 54ch;
}

.aoyl-aikajana ol {
  list-style: none;
  padding: 0;
  margin: 0;
  counter-reset: aoyl-aikajana;
}

.aoyl-aikajana ol li {
  position: relative;
  padding: 0 0 1.875rem 3.75rem;
  border-left: 2px solid var(--ink);
  margin-left: 1.25rem;
  counter-increment: aoyl-aikajana;
}

.aoyl-aikajana ol li:last-child {
  padding-bottom: 0.5rem;
  border-left: 2px solid transparent;
}

/* Solid charcoal tile, white serif numeral, centred on the spine. */
.aoyl-aikajana ol li::before {
  content: counter(aoyl-aikajana);
  position: absolute;
  left: calc(-1.25rem + 1px);
  top: -0.25rem;
  width: 2.5rem;
  height: 2.5rem;
  background: var(--charcoal);
  color: var(--on-charcoal);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-serif);
  font-size: 1.1875rem;
  font-weight: 500;
}

.aoyl-aikajana h3 {
  font-family: var(--font-serif);
  font-size: 1.25rem;
  font-weight: 500;
  font-variation-settings: 'opsz' 28;
  margin: 0 0 0.5rem;
  color: var(--ink);
}

.aoyl-aikajana p {
  margin: 0 0 0.5rem;
  font-size: 0.9375rem;
  line-height: 1.6;
  color: var(--ink);
  max-width: 58ch;
}

/* Statute pinpoint = a pressable law chip, not gray underlined smallprint. */
.aoyl-aikajana-pin {
  display: inline-block;
  margin-top: 0.25rem;
  font-family: var(--font-sans);
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--ink-subtle);
  padding: 0.3rem 0.75rem;
  text-decoration: none;
  transition: background 140ms ease, color 140ms ease;
}

.aoyl-aikajana-pin:hover {
  background: var(--bronze);
  color: var(--on-charcoal);
}

@media (max-width: 40rem) {
  .aoyl-aikajana ol li {
    padding-left: 3.25rem;
    margin-left: 1.125rem;
  }

  .aoyl-aikajana ol li::before {
    width: 2.25rem;
    height: 2.25rem;
    font-size: 1.0625rem;
    left: calc(-1.125rem + 1px);
  }
}

/* ── Widget C — stock-age cohort bars ─────────────────────────────────── */

.cohort-bars {
  background: var(--paper);
  border: 1px solid var(--rule);
  padding: 1.4rem 1.6rem;
  margin: 1.75rem 0 2rem;
}

.cohort-bars-title {
  font-family: var(--font-sans);
  font-size: 1.0625rem;
  font-weight: 600;
  margin: 0 0 0.9rem;
  color: var(--ink);
}

.cohort-bars-row {
  display: grid;
  grid-template-columns: 7rem 1fr 9rem;
  gap: 0.7rem;
  align-items: center;
  /* Uniform row height so a 2-line status and a 3-line status read as the
     same-height row. Sized to the tallest (3-line) status; align-items
     centres the shorter rows. Reset to auto on the stacked mobile layout. */
  min-height: 5rem;
  padding: 0.45rem 0;
  border-top: 1px solid var(--rule);
  font-size: 0.85rem;
}

.cohort-bars-row:first-of-type {
  border-top: 0;
}

.cohort-bars-range {
  font-family: var(--font-sans);
  font-weight: 600;
  color: var(--ink);
}

.cohort-bars-track {
  background: var(--paper-deep);
  height: 1.4rem;
  position: relative;
  border: 1px solid var(--paper-edge);
}

.cohort-bars-fill {
  height: 100%;
  display: flex;
  align-items: center;
  padding: 0 0.5rem;
  color: var(--paper);
  font-size: 0.75rem;
  font-weight: 600;
  font-family: var(--font-sans);
  background: var(--ink-subtle);
}

.cohort-bars-row-past .cohort-bars-fill { background: var(--ink-subtle); }
.cohort-bars-row-urgent .cohort-bars-fill,
.cohort-bars-row-peak .cohort-bars-fill { background: var(--turkos); }
.cohort-bars-row-near .cohort-bars-fill { background: var(--ink-muted); }
.cohort-bars-row-future .cohort-bars-fill {
  background: var(--paper-edge);
  color: var(--ink-muted);
}

.cohort-bars-status {
  font-family: var(--font-sans);
  font-size: 0.78rem;
  color: var(--ink-muted);
}

.cohort-bars-row-urgent .cohort-bars-status,
.cohort-bars-row-peak .cohort-bars-status {
  color: var(--turkos-dark);
  font-weight: 600;
}

.cohort-bars-footnote {
  margin: 1rem 0 0;
  font-size: 0.78rem;
  color: var(--ink-subtle);
  line-height: 1.55;
}

/* One-click "kopioi lähdeviite" control under the citation callout. Ships
   hidden (the inline script reveals it only when the Clipboard API exists),
   so no-JS readers just select the quote. Bronze is accent-only: neutral at
   rest, bronze on hover and on the copied confirmation. */
.copy-cite {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin: 0.6rem 0 0;
  padding: 0.35rem 0.75rem;
  font-family: var(--font-sans);
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--ink);
  background: transparent;
  border: 1px solid var(--rule-dark);
  border-radius: 0;
  cursor: pointer;
  transition: border-color 0.15s ease, color 0.15s ease;
}
.copy-cite:hover,
.copy-cite:focus-visible {
  border-color: var(--bronze);
  color: var(--bronze);
}
.copy-cite.is-copied {
  border-color: var(--bronze);
  color: var(--bronze);
}

@media (max-width: 44rem) {
  .cohort-bars-row {
    grid-template-columns: 1fr;
    gap: 0.25rem;
    /* Stacked layout is naturally taller; let each row size to content. */
    min-height: 0;
  }
}

/* ── On-page layout: sticky TOC sidebar (desktop) + scannable body ─────
   Strictly additive. Pages without a TOC keep .page-shell as a plain block,
   so the article centres itself exactly as before (zero regression). The
   sidebar only appears at >=64rem on pages that rendered .page-shell--toc
   (3+ sections); below that it is hidden and reading order is unchanged. */

/* Mobile default: the TOC is a collapsible "Sisällys" box at the top of the
   page (NN/g small-screen pattern). The 64rem block below turns it into a
   sticky sidebar on desktop and force-opens it. */
.toc {
  margin: 1.5rem var(--pad) 0.25rem;
  border: 1px solid var(--rule);
  padding: 0.4rem 1.1rem 0.9rem;
}

/* Summary doubles as the tracked section label and the mobile accordion
   toggle. Small + tracked is the DESIGN.md label pattern, not an accident. */
.toc-label {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  font-family: var(--font-sans);
  font-size: 0.75rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  color: var(--ink-muted);
  cursor: pointer;
  list-style: none;
  padding: 0.5rem 0;
}

.toc-label::-webkit-details-marker {
  display: none;
}

/* +/- accordion affordance, mobile only. Desktop gets a hairline instead
   (set in the 64rem block) and must not show the toggle glyph. */
@media (max-width: 63.999rem) {
  .toc-label::after {
    content: "+";
    font-size: 1.05rem;
    font-weight: 400;
    line-height: 1;
    color: var(--ink-subtle);
  }

  .toc[open] > .toc-label::after {
    content: "\2212";
  }
}

.toc-list {
  list-style: none;
  margin: 0.75rem 0 0;
  padding: 0;
}

.toc-list > li.toc-top {
  margin: 0 0 0.65rem;
}

/* Number column + label, baseline-aligned. Tabular numerals so 1, 1.1, 10
   line up. Numbering lives only in the nav (DESIGN.md bans heading tickers). */
.toc a {
  display: grid;
  grid-template-columns: 1.75rem 1fr;
  column-gap: 0.25rem;
  column-gap: 0.55rem;
  align-items: baseline;
  font-family: var(--font-sans);
  font-size: 0.9375rem;
  line-height: 1.4;
  font-weight: 500;
  color: var(--ink-muted);
  text-decoration: none;
  padding: 0.24rem 0.6rem;
  margin: 0 -0.6rem;
  border-radius: 0;
  transition: color 140ms ease, background-color 140ms ease;
}

.toc-num {
  font-variant-numeric: tabular-nums;
  font-size: 0.8125rem;
  font-weight: 400;
  color: var(--ink-subtle);
  transition: color 140ms ease;
}

.toc a:hover,
.toc a:hover .toc-num {
  color: var(--bronze);
}

/* Current section: an inset paper-deep band + ink + weight. Bronze is
   hover-only (DESIGN.md), so the rest-state marker stays a tone shift. */
.toc a.is-current,
.toc a.is-current .toc-num {
  color: var(--ink);
  font-weight: 600;
}

.toc a.is-current {
  background: var(--paper-deep);
}

/* ── Mobile TOC drawer (calculator-parity) ─────────────────────────────
   Progressive enhancement: only when JS has flagged <html class="toc-js">
   does the outline become an off-canvas drawer opened from a masthead
   hamburger that is reachable anywhere (the header is sticky). Without JS
   the inline <details> accordion above stays exactly as before. All drawer
   chrome is hidden by default and surfaces only in the mobile drawer state;
   the desktop sidebar block (>=64rem) below is untouched. */
.toc-toggle,
.toc-close,
.toc-backdrop {
  display: none;
}

@media (max-width: 63.999rem) {
  /* Masthead hamburger (lives in the charcoal header). */
  .toc-js .toc-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    margin-left: -0.5rem;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 4px;
    color: var(--on-charcoal);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .toc-js .toc-toggle:hover {
    color: var(--bronze);
  }
  .toc-js .toc-toggle:focus-visible {
    outline: 2px solid var(--bronze);
    outline-offset: 2px;
  }
  /* Group hamburger + logo on the left; the Laskuri CTA stays right. */
  .toc-js .site-header .logo {
    margin-right: auto;
  }

  /* The outline becomes a left off-canvas drawer. visibility:hidden (not just
     the off-canvas transform) takes the closed drawer out of the tab order and
     the accessibility tree, so its links and close button are not reachable
     off-screen; it flips visible on open and is delayed on close so the panel
     stays painted through the slide-out. */
  .toc-js .toc {
    position: fixed;
    top: 0;
    bottom: 0;
    left: 0;
    width: min(20rem, 86vw);
    margin: 0;
    border: 0;
    border-right: 1px solid var(--rule);
    /* Bottom padding insets by the consent banner. The drawer is fixed and
       bottom: 0, and the banner (z-90) paints over its foot, so at a flat 2rem
       the last entries sat under the banner with the drawer already scrolled to
       its end: five links unreachable at 360px, three at 768px, until the
       reader answered the consent request. --consent-banner-h is published by
       the banner script in scripts/lib/render-seo-page.mjs (twin of
       ConsentBanner.jsx) and is absent whenever no banner is up, so this
       resolves back to the plain 2rem. */
    padding: 1rem var(--pad) calc(2rem + var(--consent-banner-h, 0px));
    background: var(--paper);
    z-index: 60;
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform 220ms ease, visibility 0s linear 220ms;
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  .toc-js body.toc-open .toc {
    transform: translateX(0);
    visibility: visible;
    transition: transform 220ms ease;
    box-shadow: 8px 0 28px rgba(0, 0, 0, 0.14);
  }
  /* Keep the list visible inside the drawer regardless of <details> state. */
  .toc-js .toc > .toc-list {
    display: block;
    margin-top: 0.5rem;
  }
  /* Drawer title bar: label + close, no accordion +/- marker. */
  .toc-js .toc-label {
    cursor: default;
    padding: 0.25rem 0 0.9rem;
    margin-bottom: 0.4rem;
    border-bottom: 1px solid var(--rule);
  }
  .toc-js .toc-label::after {
    content: none !important;
  }
  /* Close sits in the drawer header, top-right. It is a sibling of <summary>
     (not nested inside it) so it is not an interactive control inside another
     interactive control; .toc is position:fixed, so it is the containing box. */
  .toc-js .toc-close {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    position: absolute;
    top: 0.35rem;
    right: 0.75rem;
    width: 40px;
    height: 40px;
    padding: 0;
    background: transparent;
    border: 0;
    border-radius: 4px;
    color: var(--ink-muted);
    cursor: pointer;
    -webkit-tap-highlight-color: transparent;
  }
  .toc-js .toc-close:hover {
    color: var(--bronze);
  }
  .toc-js .toc-close:focus-visible {
    outline: 2px solid var(--bronze);
    outline-offset: 2px;
  }

  /* Backdrop, mounted only while the drawer is open. */
  .toc-js body.toc-open .toc-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 55;
    background: rgba(0, 0, 0, 0.42);
  }
}

@media (prefers-reduced-motion: reduce) {
  .toc-js .toc {
    transition: none;
  }
}

/* Outline collapse control: desktop affordance only (mobile has the drawer). */
.toc-collapse { display: none; }

@media (min-width: 64rem) {
  .page-shell--toc {
    display: grid;
    /* Content column is capped at the reading measure (Investopedia-width
       rows); the TOC's left edge still lines up with the wordmark. The
       leftover container width becomes air on the right. */
    grid-template-columns: 16rem minmax(0, var(--measure));
    column-gap: 4rem;
    max-width: var(--container);
    margin: 0 auto;
    padding: 0 var(--pad);
    align-items: start;
  }

  /* Desktop: a plain sticky sidebar, no box. Force the outline open
     regardless of the <details> toggle state; the summary becomes a static
     label (the hairline returns, the +/- affordance is dropped). */
  /* The rail is the ONE sticky element; control + outline live inside it and
     can never separate (owner 2026-07-20: "toc doesn't scroll with the page?";
     2026-07-21: two independent sticky siblings diverged at the grid bottom). */
  .page-shell--toc .toc-rail {
    grid-column: 1;
    grid-row: 1;
    position: sticky;
    top: 5.5rem;
    align-self: start;
    max-height: calc(100vh - 7rem);
    display: flex;
    flex-direction: column;
    min-height: 0;
  }

  .page-shell--toc .toc {
    position: static;
    /* Bound to the rail and let a long outline scroll inside itself. Clean-
       outline pages list every sub-topic as an h3, so a TOC can exceed the
       screen height; without this the lower entries sit below the fold with
       no way to reach them. Short TOCs fit, so no scrollbar appears. */
    flex: 0 1 auto;
    min-height: 0;
    max-height: 100%;
    overflow-y: auto;
    overflow-x: hidden;
    overscroll-behavior: contain;
    margin: 0;
    border: 0;
    padding: 4rem 0 1.75rem;
    /* Soften the bottom edge where a long, internally-scrolling outline meets
       the charcoal footer: a thin, subtle scrollbar (no chunky native arrows)
       and a short fade so the last entries dissolve instead of hard-cutting. */
    scrollbar-width: thin;
    scrollbar-color: var(--rule) transparent;
    /* Edge stops driven by JS (renderTocScript): fade only an edge that has
       hidden content past it. Defaults give the no-JS/initial paint a bottom
       fade; JS clears the bottom at scroll-end (last section reads crisp), adds
       a top fade once scrolled, and drops both when the outline fits. */
    --fade-top: 0px;
    --fade-bottom: 8rem;
    -webkit-mask-image: linear-gradient(to bottom, transparent, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent);
            mask-image: linear-gradient(to bottom, transparent, #000 var(--fade-top), #000 calc(100% - var(--fade-bottom)), transparent);
  }
  .page-shell--toc .toc::-webkit-scrollbar { width: 6px; }
  .page-shell--toc .toc::-webkit-scrollbar-thumb { background: var(--rule); border-radius: 999px; }
  .page-shell--toc .toc::-webkit-scrollbar-track { background: transparent; }

  .page-shell--toc .toc > .toc-list {
    display: block !important;
    margin-top: 0;
  }

  .page-shell--toc .toc-label {
    pointer-events: none;
    cursor: default;
    position: relative;
    /* Clears the collapse control that shares this line (22px glyph + 8px
       gap), so the two read as one header row instead of printing on top of
       each other. The hairline below stays on the column edge with the
       entries, because it is positioned against the padding box. */
    padding: 0 0 0.9rem 1.875rem;
    margin: 0 0 1.3rem;
  }

  .page-shell--toc .toc-label::after {
    content: "";
    position: absolute;
    left: 0;
    bottom: 0;
    width: 40px;
    height: 1px;
    background: var(--rule);
  }

  .page-shell--toc article {
    grid-column: 2;
    max-width: 100%;
    margin: 0;
    /* Gutter comes from the shell + column gap, not the article. */
    padding-left: 0;
    padding-right: 0;
  }

  /* ── Outline collapse control ──────────────────────────────────────────
     Mobile keeps the masthead drawer, so this is a desktop affordance only. */
  .toc-collapse {
    /* Absolutely positioned INSIDE the sticky rail, dropped by the outline's
       own top padding (4rem) so the glyph lands on the "Sisällysluettelo"
       heading line. Because the rail is the only sticky box, the control can
       never drift over the list. The negative left offset cancels the
       button's padding so the glyph itself sits on the column edge. */
    position: absolute;
    top: calc(4rem - 8px);
    left: -6px;
    z-index: 2;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin: 0;
    padding: 6px;
    line-height: 0;
    color: var(--ink-subtle);
    background: var(--paper);
    border: 0;
    cursor: pointer;
    transition: color 160ms ease;
  }
  .toc-collapse:hover { color: var(--ink); }
  .toc-collapse:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
  .toc-collapse svg { width: 22px; height: 22px; display: block; flex-shrink: 0; }

  /* Collapsed: equal side columns centre the reading measure on the page.
     The left one still holds the control that brings the outline back. */
  .page-shell--toc.is-toc-collapsed {
    grid-template-columns: minmax(0, 1fr) minmax(0, var(--measure)) minmax(0, 1fr);
    column-gap: 2.5rem;
  }
  .page-shell--toc.is-toc-collapsed .toc { display: none; }

  /* Expanded: the outline's own summary header already says what it is,
     so the control stays icon-only. Collapsed: the label appears beside
     the icon (owner 2026-07-20: a bare icon does not say what it is). */
  .toc-collapse-text {
    display: none;
    font-family: var(--font-sans);
    font-size: 0.75rem;
    font-weight: 600;
    letter-spacing: 0.14em;
    margin-left: 0.5rem;
    white-space: nowrap;
  }

  .page-shell--toc.is-toc-collapsed .toc-collapse-text {
    display: inline;
  }

  /* Finnish compounds outrun a narrow outline cell on their own and were
     clipped mid-word. Long words break rather than overflow. */
  .page-shell--toc .toc-text {
    overflow-wrap: anywhere;
    hyphens: auto;
  }

  /* Between the sidebar breakpoint and ~71rem the side column cannot hold a
     legible outline: with the reading column centred there is only ~120px of
     air, which clips the labels. Centred text is the rule, so the outline
     stops being a column here and becomes an overlay panel driven by the same
     control. */
  @media (max-width: 70.999rem) {
    /* The panel is out of flow, so the grid keeps the centred form whether it
       is open or not: opening it must not shove the text sideways. */
    .page-shell--toc,
    .page-shell--toc.is-toc-collapsed {
      grid-template-columns: minmax(0, 1fr) minmax(0, var(--measure)) minmax(0, 1fr);
      column-gap: 2.5rem;
    }
    .page-shell--toc .toc {
      position: fixed;
      top: 4.75rem;
      left: 0;
      z-index: 30;
      width: 16rem;
      max-width: 86vw;
      max-height: calc(100vh - 6.5rem);
      overflow-y: auto;
      margin: 0;
      padding: 1.25rem 1.25rem 1.5rem;
      background: var(--paper);
      border-right: 1px solid var(--rule);
      box-shadow: 0 10px 34px rgba(0, 0, 0, 0.14);
      -webkit-mask-image: none;
              mask-image: none;
    }
    /* The panel covers its own toggle, so it dims what is behind it and
       carries a close button, the way the mobile drawer does. */
    .page-shell--toc:not(.is-toc-collapsed) .toc-backdrop {
      display: block;
      position: fixed;
      inset: 4.75rem 0 0;
      z-index: 29;
      background: rgba(20, 19, 16, 0.32);
    }
    .page-shell--toc .toc-close {
      display: inline-flex;
      align-items: center;
      justify-content: center;
      position: absolute;
      top: 0.5rem;
      right: 0.5rem;
      width: 32px;
      height: 32px;
      padding: 0;
      background: transparent;
      border: 0;
      border-radius: 4px;
      color: var(--ink-subtle);
      cursor: pointer;
    }
    .page-shell--toc .toc-close:hover { color: var(--ink); }
    .page-shell--toc .toc-close:focus-visible { outline: 2px solid var(--ink); outline-offset: 2px; }
  }

  .page-shell--toc .toc { transition: opacity 160ms ease; }
}

/* ── Scannable body: section rules + answer-first emphasis ─────────────
   article > h2 = the content section questions (and the FAQ heading). The
   Avaintiedot h2 lives inside <section class="key-takeaways">, the Lue myös /
   Lähteet h2s live in <nav>/<section> wrappers, so none of those are direct
   children of <article> and none pick up the section rule. A 1px hairline above each section chunks the page into
   scannable blocks (ruled, not boxed; flat, per DESIGN.md). */

article > h2 {
  border-top: 1px solid var(--rule);
  padding-top: 2rem;
  margin-top: 3.5rem;
}

/* The intro lead already opened this section with its own hairline; the
   first title follows it seamlessly, no double rule. */
article > .lead + h2 {
  border-top: 0;
  padding-top: 0;
  margin-top: 0;
}

@media (max-width: 40rem) {
  article > h2 {
    padding-top: 1.5rem;
    margin-top: 2.5rem;
  }

  article > .lead + h2 {
    padding-top: 0;
    margin-top: 0;
  }
}

/* Print: drop the sidebar, collapse the grid to a single column. The backdrop
   is listed explicitly because its show rule lives in a bare (media-type: all)
   max-width query that also matches paged media at A4 widths. */
@media print {
  .toc,
  .toc-rail,
  .toc-backdrop,
  .band-motif {
    display: none !important;
  }

  .page-shell--toc {
    display: block;
  }
}

/* ---- vuokratuotto calculator widget (.vt-laskuri) ---- */

.vt-laskuri {
  background: var(--paper-deep);
  border-left: 3px solid var(--charcoal);
  padding: 1.5rem 1.75rem;
  margin: 1.75rem 0 2rem;
}

.vt-laskuri-title {
  font-family: var(--font-sans);
  font-size: 1.05rem;
  font-weight: 650;
  margin: 0 0 0.4rem;
}

.vt-laskuri-help,
.vt-laskuri-note {
  font-family: var(--font-sans);
  font-size: 0.85rem;
  color: var(--ink-muted);
  line-height: 1.5;
  margin: 0 0 1rem;
}

.vt-laskuri-note { margin: 1rem 0 0; }

.vt-laskuri-form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.7rem 1.1rem;
  margin: 0 0 1.1rem;
}

.vt-field label {
  display: block;
  font-family: var(--font-sans);
  font-size: 0.78rem;
  color: var(--ink-muted);
  margin-bottom: 0.2rem;
}

.vt-field input,
.vt-field select {
  width: 100%;
  font-family: var(--font-sans);
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--paper);
  border: 1px solid var(--rule);
  border-radius: 0;
  padding: 0.45rem 0.6rem;
  box-sizing: border-box;
}

.vt-field input:focus-visible,
.vt-field select:focus-visible {
  outline: 2px solid var(--charcoal);
  outline-offset: 1px;
}

.vt-laskuri-results {
  border-top: 1px solid var(--rule);
  padding-top: 0.4rem;
}

.vt-row {
  display: flex;
  justify-content: space-between;
  gap: 1rem;
  font-family: var(--font-sans);
  font-size: 0.9rem;
  padding: 0.32rem 0;
  border-bottom: 1px solid var(--rule);
}

.vt-row span:last-child {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.vt-row-strong {
  font-weight: 650;
  font-size: 0.95rem;
}

@media (max-width: 36rem) {
  .vt-laskuri { padding: 1.1rem 1.1rem; }
  .vt-laskuri-form { grid-template-columns: 1fr; }
}


/* Audit fix (iter1): placeholder at AA for the elderly-phone persona. */
.vastuu-search-input::placeholder {
  color: var(--ink-muted);
  opacity: 1;
}


/* (iter1 static-collapse patch removed 2026-07-20: the outline itself is
   sticky now, so the control and the outline stick together in both states.) */


/* Audit fix (iter1): native webkit search-cancel is off-palette blue and
   absent in Firefox; hide it, clearing happens by editing the field. */
.vastuu-search-input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}

/* ── CTA option C (owner 2026-07-22, lavish-approved): editorial card,
      drawn report plate (bronze story bar), serif standfirst, button-only.
      Same card at both slots; plate hidden on mobile. Short profile
      (owner: "not as tall"). ─────────────────────────────────────────── */
.cta-c {
  padding: 1.125rem 1.5rem;
}

.cta-hook {
  margin: 0.125rem 0 0.25rem;
  font-family: var(--font-serif);
  font-size: 1.1875rem;
  font-weight: 500;
  line-height: 1.3;
  font-variation-settings: 'opsz' 24;
  color: var(--ink);
}

.cta-c .cta-sub {
  margin: 0 0 0.875rem;
  max-width: 46ch;
  font-size: 0.9375rem;
}

.cta-actions {
  display: flex;
  align-items: center;
  gap: 1.25rem;
  flex-wrap: wrap;
}

.cta-card a.cta-btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  background: var(--charcoal);
  color: var(--on-charcoal);
  border: 1px solid var(--charcoal);
  text-decoration: none;
  font-weight: 600;
  font-size: 0.9375rem;
  padding: 0.5rem 1.25rem;
  white-space: nowrap;
  transition: background 150ms ease, border-color 150ms ease;
}

.cta-card a.cta-btn:hover {
  background: var(--bronze);
  border-color: var(--bronze);
  color: var(--on-charcoal);
}

.cta-card a.cta-btn:focus-visible {
  outline: 2px solid var(--bronze);
  outline-offset: 2px;
}

/* Proof link: quiet text link, never a second button (specificity must beat
   the .cta-card a button rule). */
.cta-card a.cta-example {
  display: inline-block;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.cta-card a.cta-example:hover {
  background: none;
  color: var(--bronze);
}

@media (max-width: 44rem) {
  .cta-c {
    padding: 1.125rem 1.25rem;
  }

  .cta-actions {
    align-items: stretch;
    flex-direction: column;
    gap: 0.75rem;
  }

  .cta-card a.cta-btn {
    justify-content: center;
  }

  .cta-card a.cta-example {
    text-align: center;
  }
}

/* ── fig2 chart chrome (ported from kvr-wt-bes-loukku for inline-SVG data
      figures; kit = asuntoanalyysi-infographics) ─────────────────────── */
.fig2 { margin: 2.5rem 0 3rem; }
.fig2-rule { display: flex; align-items: center; gap: 10px; margin-bottom: 0.875rem; }
.fig2-tag { width: 30px; height: 4px; background: oklch(24% 0.012 250); }
.fig2-no { font-size: 0.75rem; letter-spacing: 0.04em; color: oklch(24% 0.012 250); }
.fig2-rule::after { content: ""; flex: 1; border-top: 1px solid oklch(24% 0.012 250 / 0.25); }
.fig2-title { font-family: 'Newsreader', 'Newsreader Fallback', Georgia, serif; font-weight: 500; font-size: 1.25rem; line-height: 1.25; letter-spacing: -0.005em; max-width: 48ch; font-variation-settings: 'opsz' 24; }
.fig2-dek { font-size: 0.9375rem; color: oklch(45% 0.01 250); margin: 0.375rem 0 1.25rem; max-width: 64ch; }
.fig2 svg { display: block; width: 100%; height: auto; }
.fig2 svg text { font-family: 'Inter Tight', 'Inter', system-ui, sans-serif; font-variant-numeric: tabular-nums; }
.fig2-src { font-size: 0.75rem; line-height: 1.5; color: oklch(45% 0.01 250); margin-top: 0.75rem; max-width: 76ch; }
