/* base.css — "sharp" template: precision.
 *
 * A complete, quality-gated design system (hand-rolled BEM, framework-free).
 * The build agent copies this file verbatim into a site's `style.css` and
 * overwrites ONLY the delimited brand-parameter block below — every other rule
 * ships byte-identical, which is how the fixture's Lighthouse/axe pass transfers
 * to every real build. See TEMPLATE.md for the character spec and the
 * brand-parameter contract (which properties to fill, how tints/shades derive).
 *
 * Character: flat, hard-edged, structured — grotesk type, 0-2px radii, hairline
 * borders instead of shadows, high contrast, brisk slide-in motion. Shares the
 * BEM vocabulary of the "soft" template so a site's HTML renders under either
 * stylesheet unchanged. Fonts are self-hosted from the site's own `fonts/`
 * folder — see the generated web-font section below.
 */

/* ── Web fonts (self-hosted, generated) ──────────────────────────────────
 * Regenerate with `node scripts/fetch-template-fonts.mjs`. The files live in
 * the site's own `fonts/` folder, so a page load reaches no third party.
 * Rules for every approved pair are listed; only the pair named in the brand
 * block is ever requested, and a build copies only that pair's files. */

/* archivo-inter */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/archivo-normal-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/archivo-normal-700.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('fonts/archivo-normal-800.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/inter-normal-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/inter-normal-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Inter';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/inter-normal-700.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* barlow */
@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/barlow-normal-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/barlow-normal-500.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Barlow';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/barlow-normal-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/barlow-condensed-normal-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Barlow Condensed';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/barlow-condensed-normal-700.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* spacegrotesk-plex */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-normal-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-normal-500.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/ibm-plex-sans-normal-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/space-grotesk-normal-500.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/space-grotesk-normal-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Space Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/space-grotesk-normal-700.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* schibsted-hanken */
@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/hanken-grotesk-normal-400.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/hanken-grotesk-normal-500.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Hanken Grotesk';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/hanken-grotesk-normal-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/schibsted-grotesk-normal-600.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/schibsted-grotesk-normal-700.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'Schibsted Grotesk';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('fonts/schibsted-grotesk-normal-800.woff2') format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}



/* ── end web fonts ── */

/* ── Font fallbacks (metric-matched) ─────────────────────────────────────────
 * While the self-hosted webfonts load (font-display: swap), the browser lays the page
 * out in a system font. Without these, the hero text is a different height in the
 * fallback than in the webfont, so the framed hero image below it jumps when the
 * webfont arrives — a layout shift Lighthouse scores on every page. Each face below
 * binds Arial (Arial Narrow for the condensed heading) with size-adjust and
 * ascent/descent overrides computed from that webfont's hhea metrics over a Finnish
 * sample text, so the fallback occupies the same lines. One face per approved
 * weight of every approved pair; the brand block's stacks name the matching
 * `<Family> Fallback` right after the webfont. Regenerating the web-font block above
 * does not touch this section. */
@font-face {
  font-family: 'Archivo Fallback';
  font-style: normal;
  font-weight: 600;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 95.41%;
  ascent-override: 92.03%;
  descent-override: 22.01%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Archivo Fallback';
  font-style: normal;
  font-weight: 700;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 98.93%;
  ascent-override: 88.75%;
  descent-override: 21.23%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Archivo Fallback';
  font-style: normal;
  font-weight: 800;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 104.20%;
  ascent-override: 84.26%;
  descent-override: 20.15%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Inter Fallback';
  font-style: normal;
  font-weight: 400;
  src: local('Arial'), local('ArialMT');
  size-adjust: 105.82%;
  ascent-override: 91.55%;
  descent-override: 22.79%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Inter Fallback';
  font-style: normal;
  font-weight: 600;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 100.96%;
  ascent-override: 95.95%;
  descent-override: 23.89%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Inter Fallback';
  font-style: normal;
  font-weight: 700;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 102.20%;
  ascent-override: 94.79%;
  descent-override: 23.60%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Barlow Condensed Fallback';
  font-style: normal;
  font-weight: 600;
  src: local('Arial Narrow Bold'), local('ArialNarrow-Bold');
  size-adjust: 90.68%;
  ascent-override: 110.28%;
  descent-override: 22.06%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Barlow Condensed Fallback';
  font-style: normal;
  font-weight: 700;
  src: local('Arial Narrow Bold'), local('ArialNarrow-Bold');
  size-adjust: 93.03%;
  ascent-override: 107.49%;
  descent-override: 21.50%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Barlow Fallback';
  font-style: normal;
  font-weight: 400;
  src: local('Arial'), local('ArialMT');
  size-adjust: 96.99%;
  ascent-override: 103.11%;
  descent-override: 20.62%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Barlow Fallback';
  font-style: normal;
  font-weight: 500;
  src: local('Arial'), local('ArialMT');
  size-adjust: 97.99%;
  ascent-override: 102.05%;
  descent-override: 20.41%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Barlow Fallback';
  font-style: normal;
  font-weight: 600;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 91.99%;
  ascent-override: 108.71%;
  descent-override: 21.74%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Hanken Grotesk Fallback';
  font-style: normal;
  font-weight: 400;
  src: local('Arial'), local('ArialMT');
  size-adjust: 100.12%;
  ascent-override: 99.88%;
  descent-override: 30.26%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Hanken Grotesk Fallback';
  font-style: normal;
  font-weight: 500;
  src: local('Arial'), local('ArialMT');
  size-adjust: 100.85%;
  ascent-override: 99.15%;
  descent-override: 30.04%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Hanken Grotesk Fallback';
  font-style: normal;
  font-weight: 600;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 94.54%;
  ascent-override: 105.78%;
  descent-override: 32.05%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Schibsted Grotesk Fallback';
  font-style: normal;
  font-weight: 600;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 100.97%;
  ascent-override: 96.72%;
  descent-override: 25.53%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Schibsted Grotesk Fallback';
  font-style: normal;
  font-weight: 700;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 103.18%;
  ascent-override: 94.64%;
  descent-override: 24.99%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Schibsted Grotesk Fallback';
  font-style: normal;
  font-weight: 800;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 105.50%;
  ascent-override: 92.56%;
  descent-override: 24.44%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'IBM Plex Sans Fallback';
  font-style: normal;
  font-weight: 400;
  src: local('Arial'), local('ArialMT');
  size-adjust: 100.94%;
  ascent-override: 101.54%;
  descent-override: 27.24%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'IBM Plex Sans Fallback';
  font-style: normal;
  font-weight: 500;
  src: local('Arial'), local('ArialMT');
  size-adjust: 103.37%;
  ascent-override: 99.15%;
  descent-override: 26.60%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'IBM Plex Sans Fallback';
  font-style: normal;
  font-weight: 600;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 97.66%;
  ascent-override: 104.95%;
  descent-override: 28.16%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Space Grotesk Fallback';
  font-style: normal;
  font-weight: 500;
  src: local('Arial'), local('ArialMT');
  size-adjust: 108.47%;
  ascent-override: 90.72%;
  descent-override: 26.92%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Space Grotesk Fallback';
  font-style: normal;
  font-weight: 600;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 101.03%;
  ascent-override: 97.39%;
  descent-override: 28.90%;
  line-gap-override: 0.00%;
}
@font-face {
  font-family: 'Space Grotesk Fallback';
  font-style: normal;
  font-weight: 700;
  src: local('Arial Bold'), local('Arial-BoldMT');
  size-adjust: 101.15%;
  ascent-override: 97.28%;
  descent-override: 28.87%;
  line-gap-override: 0.00%;
}
/* ── end font fallbacks ── */

/* ── Brand parameters (per-site) ─────────────────────────────────────────────
 * The ONLY block the build agent edits. Fill from the extracted brand (logo
 * colours, screenshot palette, tone). Keep every property; adjust its value.
 * Contrast contract: --color-text and --color-muted must hold >= 4.5:1 on
 * --color-surface and --color-surface-alt; --color-on-primary must hold >= 4.5:1
 * on --color-primary; --color-primary used as link text must hold >= 4.5:1 on
 * --color-surface. Fonts must be one of TEMPLATE.md's approved grotesk pairs. */
:root {
  --color-primary: #0c7591;        /* Tekas teal, darkened for 4.5:1 link contrast — links, primary buttons, flat brand blocks */
  --color-primary-shade: #0a5f76;  /* darker primary for hover/active (derive: primary ~15% darker) */
  --color-primary-tint: #e7f1f4;   /* pale block/fill tint (derive: primary mixed ~90% white) */
  --color-on-primary: #ffffff;     /* text/icons on --color-primary blocks */
  --color-accent: #0090b0;         /* the logo's own teal — underline sweeps, markers, active rules */
  --color-surface: #ffffff;        /* page background */
  --color-surface-alt: #f1f4f6;    /* cool grey background for alternating sections */
  --color-text: #14191d;           /* near-black body text (high contrast) */
  --color-muted: #4a555f;          /* muted cool grey for secondary text (>= 4.5:1 on surfaces) */
  --color-border: #cdd6dc;         /* hairline border colour */

  --font-heading: 'Barlow Condensed', 'Barlow Condensed Fallback', 'Arial Narrow', Arial, sans-serif;
  --font-body: 'Barlow', 'Barlow Fallback', 'Segoe UI', system-ui, -apple-system, sans-serif;
}
/* ── end Brand parameters ──────────────────────────────────────────────────── */

/* ── Fixed tokens (the template character — do not edit per site) ──────────── */
:root {
  /* Type scale 1.333 (perfect fourth), fluid via clamp; body line-height 1.5. */
  --step--1: clamp(0.8rem, 0.77rem + 0.13vw, 0.875rem);
  --step-0: clamp(1rem, 0.96rem + 0.18vw, 1.125rem);
  --step-1: clamp(1.33rem, 1.24rem + 0.42vw, 1.6rem);
  --step-2: clamp(1.78rem, 1.6rem + 0.83vw, 2.37rem);
  --step-3: clamp(2.37rem, 2.05rem + 1.5vw, 3.16rem);
  --step-4: clamp(3.16rem, 2.6rem + 2.6vw, 4.21rem);
  --step-5: clamp(3.8rem, 2.9rem + 4.2vw, 5.61rem);
  --leading-body: 1.5;
  --leading-tight: 1.05;

  /* Spacing — tighter, structured grid; section padding 4-5rem. */
  --space-3xs: 0.375rem;
  --space-2xs: 0.625rem;
  --space-xs: 0.9rem;
  --space-s: 1.25rem;
  --space-m: 2rem;
  --space-l: 3rem;
  --space-xl: 4.5rem;
  --section-pad: clamp(3rem, 2.2rem + 3vw, 5rem);
  --container-max: 74rem;

  /* Radii 0-2px everywhere — the sharp character. */
  --radius-s: 0;
  --radius-m: 2px;
  --radius-l: 2px;
  --radius-pill: 2px;

  /* Flat — no box-shadows; hairline borders carry separation. */
  --border-hair: 1px solid var(--color-border);
  --border-strong: 2px solid var(--color-text);

  /* Brisk motion, 200-250ms. */
  --ease-sharp: cubic-bezier(0.4, 0, 0.2, 1);
  --dur-reveal: 240ms;
  --dur-hover: 180ms;

  --header-h: 4.25rem;
}

/* ── Reset ───────────────────────────────────────────────────────────────── */
*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Reserve the scrollbar's width at all times. The lightbox hides the page's
     overflow while it is open, which would otherwise take the bar away and shift
     the whole page sideways behind the dialog. */
  scrollbar-gutter: stable;
}
body {
  font-family: var(--font-body);
  font-size: var(--step-0);
  line-height: var(--leading-body);
  color: var(--color-text);
  background: var(--color-surface);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img,
picture,
svg,
video {
  display: block;
  max-width: 100%;
  height: auto;
}
input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}
a {
  color: var(--color-primary);
  text-underline-offset: 0.16em;
}
a:hover {
  color: var(--color-primary-shade);
}
h1,
h2,
h3,
h4 {
  font-family: var(--font-heading);
  line-height: var(--leading-tight);
  font-weight: 700;
  color: var(--color-text);
  letter-spacing: -0.02em; /* tight grotesk headings */
}
h1 {
  font-size: var(--step-4);
}
h2 {
  font-size: var(--step-3);
}
h3 {
  font-size: var(--step-2);
}
ul,
ol {
  padding-left: 1.15em;
}

/* Visible, high-contrast focus ring for keyboard users on every interactive
   element — never remove the outline without an equal-or-better replacement. */
:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
}

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

/* ── Utilities ───────────────────────────────────────────────────────────── */
.container {
  width: 100%;
  max-width: var(--container-max);
  margin-inline: auto;
  padding-inline: var(--space-s);
}
/* Accessible visually-hidden text (labels for icon-only controls, etc.). */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}
/* Skip link: off-screen until focused, then pinned top-left for keyboard users. */
.skip-link {
  position: absolute;
  left: var(--space-s);
  top: -4rem;
  z-index: 100; /* above the sticky header */
  padding: var(--space-2xs) var(--space-xs);
  background: var(--color-text);
  color: var(--color-surface);
  transition: top var(--dur-hover) var(--ease-sharp);
}
.skip-link:focus {
  top: var(--space-2xs);
  color: var(--color-surface);
}

/* Scroll-reveal: only hidden when JS is active (root .js), so no-JS keeps all
   content visible. main.js adds .is-visible as elements enter the viewport. */
.js [data-reveal] {
  opacity: 0;
  transform: translateX(-22px); /* brisk slide-in from the left */
  transition: opacity var(--dur-reveal) var(--ease-sharp), transform var(--dur-reveal) var(--ease-sharp);
}
.js [data-reveal].is-visible {
  opacity: 1;
  transform: none;
}

/* ── Buttons ─────────────────────────────────────────────────────────────── */
.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3xs);
  min-height: 3rem; /* comfortable tap target */
  padding: 0.8rem 1.6rem;
  border: 2px solid transparent;
  border-radius: var(--radius-m); /* square buttons — the sharp character */
  font-weight: 700;
  font-size: var(--step-0);
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color var(--dur-hover) var(--ease-sharp), color var(--dur-hover) var(--ease-sharp),
    border-color var(--dur-hover) var(--ease-sharp);
}
.button--primary {
  background: var(--color-primary);
  color: var(--color-on-primary);
  border-color: var(--color-primary);
}
/* Hover inverts the fill — flat, no lift, no shadow. */
.button--primary:hover {
  background: var(--color-surface);
  color: var(--color-primary);
  border-color: var(--color-primary);
}
.button--ghost {
  background: transparent;
  color: var(--color-primary);
  border-color: var(--color-border);
}
.button--ghost:hover {
  background: var(--color-primary);
  color: var(--color-on-primary);
  border-color: var(--color-primary);
}

/* ── Header / navigation ─────────────────────────────────────────────────── */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50; /* above page content, below the skip link */
  background: var(--color-surface);
  border-bottom: var(--border-hair);
  transition: border-color var(--dur-hover) var(--ease-sharp);
}
/* main.js adds --stuck once scrolled off the top; strengthen the hairline. */
.site-header--stuck {
  border-bottom: var(--border-strong);
}
.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-s);
  min-height: var(--header-h);
}
.site-header__brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2xs);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--step-1);
  letter-spacing: -0.02em;
  color: var(--color-text);
  text-decoration: none;
  text-transform: uppercase;
}
.site-header__logo {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius-m);
}
.nav__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  background: transparent;
  border: var(--border-strong);
  border-radius: var(--radius-m);
  cursor: pointer;
}
.nav__toggle-bars {
  position: relative;
  width: 1.25rem;
  height: 2px;
  background: var(--color-text);
}
.nav__toggle-bars::before,
.nav__toggle-bars::after {
  content: '';
  position: absolute;
  left: 0;
  width: 1.25rem;
  height: 2px;
  background: var(--color-text);
}
.nav__toggle-bars::before {
  top: -6px;
}
.nav__toggle-bars::after {
  top: 6px;
}
.nav__menu {
  list-style: none;
  padding: 0;
  margin: 0;
}
.nav__item {
  margin: 0;
}
.nav__link {
  display: inline-flex;
  align-items: center;
  min-height: 3rem;
  padding: 0 var(--space-2xs);
  color: var(--color-text);
  text-decoration: none;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: var(--step--1);
  border-bottom: 2px solid transparent; /* underline-sweep target */
  transition: border-color var(--dur-hover) var(--ease-sharp), color var(--dur-hover) var(--ease-sharp);
}
.nav__link:hover,
.nav__link--active {
  color: var(--color-primary);
  border-bottom-color: var(--color-accent); /* accent underline sweep */
}

/* Mobile-first: nav collapses behind the toggle; expands to a row at >= 48rem. */
@media (max-width: 47.99rem) {
  .nav__menu {
    display: none;
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    flex-direction: column;
    gap: 0;
    padding: var(--space-2xs) var(--space-s) var(--space-s);
    background: var(--color-surface);
    border-bottom: var(--border-strong);
  }
  .nav__menu--open {
    display: flex;
  }
  .nav__link {
    width: 100%;
    border-bottom: var(--border-hair);
  }
}
@media (min-width: 48rem) {
  .nav__toggle {
    display: none;
  }
  .nav__menu {
    display: flex;
    align-items: center;
    gap: var(--space-s);
  }
}

/* ── Hero ────────────────────────────────────────────────────────────────── */
.hero {
  padding-block: var(--section-pad);
  border-bottom: var(--border-strong);
  overflow: hidden;
  background: var(--color-surface);
  /* Flat diagonal primary wash — directional, not soft-glow, in keeping with
     the hard-edged character. Derived from brand tokens via color-mix();
     browsers without color-mix() keep the solid surface. */
  background: linear-gradient(135deg, color-mix(in srgb, var(--color-primary) 7%, var(--color-surface)), var(--color-surface) 55%);
}
.hero__inner {
  display: grid;
  gap: var(--space-l);
  align-items: center;
}
.hero__body {
  min-width: 0; /* grid child: keep a long word from blowing out the text column */
}
.hero__kicker {
  display: inline-block;
  margin-bottom: var(--space-2xs);
  padding: var(--space-3xs) var(--space-2xs);
  background: var(--color-primary); /* bold flat block — sharp character */
  color: var(--color-on-primary);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-size: var(--step--1);
}
.hero__title {
  /* Below --step-5: at the full display step a 13-character Finnish word ("painopalvelua")
     is wider than the hero column at 375px and at the narrowest two-column width, and breaks.
     This is the largest size at which it still fits. --step-5 itself is unchanged. */
  font-size: clamp(3.57rem, 2.73rem + 3.95vw, 5.27rem);
  overflow-wrap: break-word;
  /* Finnish compounds routinely run past 20 characters ("ympäristöystävällistä"). One cannot
     fit unbroken in a hero column at display size — it would take body-copy size to fit. Left
     unhyphenated the browser still breaks the word, it just breaks it silently, which reads
     worse than a hyphen. So hyphenate, but only from 16 characters up, leaving at least 5
     letters before and 4 after the break. The 13-14 character words that a Finnish tagline
     is full of ("painopalvelua") are kept whole by the title size instead, so they never get
     the hyphen that made the first live site look broken. A 16+ character business name will
     be hyphenated; a visible hyphen is still the better of the two possible breaks. Safari
     before 17 ignores the 16-character floor and applies only the 5/4 limits. */
  hyphens: auto;
  -webkit-hyphens: auto;
  hyphenate-limit-chars: 16 5 4;
  -webkit-hyphenate-limit-before: 5;
  -webkit-hyphenate-limit-after: 4;
  max-width: 15ch;
  text-transform: uppercase;
}
.hero__text {
  margin-top: var(--space-s);
  font-size: var(--step-1);
  color: var(--color-muted);
  max-width: 46ch;
}
.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-xs);
  margin-top: var(--space-m);
}
.hero__media {
  border: var(--border-strong); /* hard-edged framed hero */
  overflow: hidden;
  animation: hero-slide var(--dur-reveal) var(--ease-sharp) both;
}
.hero__art {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
@media (min-width: 56rem) {
  .hero__inner {
    grid-template-columns: 1.1fr 0.9fr;
  }
}

/* ── Section scaffolding ─────────────────────────────────────────────────── */
.section {
  padding-block: var(--section-pad);
  border-bottom: var(--border-hair); /* visible section rules — structured grid */
}
.section--alt {
  background: var(--color-surface-alt);
}
.section__head {
  max-width: 52ch;
  margin-bottom: var(--space-l);
}
.section__kicker {
  display: inline-block;
  margin-bottom: var(--space-2xs);
  padding-bottom: var(--space-3xs);
  border-bottom: 2px solid var(--color-accent); /* accent underline on the kicker */
  font-weight: 700;
  color: var(--color-primary);
  text-transform: uppercase; /* uppercase kicker labels — sharp character */
  letter-spacing: 0.08em;
  font-size: var(--step--1);
}
.section__title {
  font-size: var(--step-3);
  text-transform: uppercase;
}
.section__lead {
  margin-top: var(--space-s);
  color: var(--color-muted);
  font-size: var(--step-1);
}

/* ── Cards (numbered service grid — the sharp treatment) ─────────────────── */
.card-grid {
  display: grid;
  gap: 0;
  grid-template-columns: 1fr;
  border-top: var(--border-hair);
  border-left: var(--border-hair);
  counter-reset: card; /* drives the numbered ::before on each card */
}
@media (min-width: 40rem) {
  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 60rem) {
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}
.card {
  position: relative; /* positions the numeric counter badge */
  counter-increment: card;
  padding: var(--space-m);
  background: var(--color-surface);
  border-right: var(--border-hair);
  border-bottom: var(--border-hair);
  transition: background-color var(--dur-hover) var(--ease-sharp);
}
.card::before {
  content: counter(card, decimal-leading-zero);
  position: absolute;
  top: var(--space-s);
  right: var(--space-m);
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--step-1);
  color: var(--color-border);
}
.card:hover {
  background: var(--color-surface-alt); /* flat fill shift, no lift */
}
.card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  margin-bottom: var(--space-s);
  background: var(--color-primary-tint);
  color: var(--color-primary);
  border-radius: var(--radius-m);
}
.card__title {
  font-size: var(--step-1);
  margin-bottom: var(--space-2xs);
  text-transform: uppercase;
}
.card__text {
  color: var(--color-muted);
}
/* The reset at the top of this file removes every margin, so a card holding more
   than a title and one paragraph (a photo, a second paragraph, a line of links)
   would stack its pieces flush against each other. This spaces each piece from the
   one above it. The gap equals the title's own bottom margin, and the two overlap
   rather than add up, so the space under a title stays as it was. */
.card > * + * {
  margin-top: var(--space-2xs);
}
/* The icon is an inline box, so its bottom margin does not overlap the next
   piece's top margin. It already sets the space beneath it, so the piece that
   follows adds none. */
.card__icon + * {
  margin-top: 0;
}

/* ── Gallery ─────────────────────────────────────────────────────────────── */
.gallery {
  display: grid;
  gap: var(--space-2xs);
  grid-template-columns: 1fr;
}
@media (min-width: 40rem) {
  .gallery {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 60rem) {
  .gallery {
    grid-template-columns: repeat(3, 1fr);
  }
}
.gallery__item {
  overflow: hidden;
  border: var(--border-hair);
}
/* The link wraps the whole picture, so it has to be a block. An inline link keeps
   the space a text line reserves under its letters, which would make the item
   taller than the photograph inside it. */
.gallery__link {
  display: block;
}
/* Only when the script is running does a click open the picture, so only then
   does the pointer promise it. */
.js .gallery__link {
  cursor: zoom-in;
}
.gallery__caption {
  padding: 0.75rem 1rem;
  font-size: 0.875rem;
  color: var(--color-muted);
}
.gallery__image {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform var(--dur-hover) var(--ease-sharp);
}
.gallery__item:hover .gallery__image {
  transform: scale(1.03);
}
/* A gallery holding one picture runs the full row instead of sitting in a third
   of it. Written as a class rather than read off `:only-child`, so the markup
   says what it is. At 4:3 a full-width photograph would be nearly a screen tall,
   so the single picture takes the wide-panel ratio. */
.gallery--single .gallery__item {
  grid-column: 1 / -1;
}
.gallery--single .gallery__image {
  aspect-ratio: 12 / 5;
}

/* ── Lightbox ────────────────────────────────────────────────────────────── */
/* main.js builds this dialog the first time a visitor opens a gallery picture.
   The dialog carries no frame of its own: the photograph is the content and the
   darkened page behind it is the frame. Every control is a visible word, so the
   template needs no icon font and the labels follow the site's own language. */
.lightbox {
  width: 100vw;
  max-width: 100vw;
  height: 100vh;
  max-height: 100vh;
  padding: 0;
  border: 0;
  /* The dialog paints the dark ground itself rather than leaving it to the
     backdrop alone: it fills the viewport, and a browser that does not paint
     ::backdrop would otherwise show the light page straight under the caption. */
  background: rgba(10, 12, 14, 0.88);
  color: var(--color-on-primary);
  overflow: hidden;
}
.lightbox::backdrop {
  background: rgba(10, 12, 14, 0.88);
}
.lightbox__figure {
  margin: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-2xs);
  /* The picture keeps clear of the chrome around it: the close button above, and
     the counter with the previous/next pair below. */
  padding: 4rem var(--space-s) 7.5rem;
}
.lightbox__image {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  min-height: 0; /* lets the picture shrink so the caption always fits under it */
  object-fit: contain;
}
.lightbox__caption {
  flex: 0 0 auto;
  max-width: 60ch;
  text-align: center;
  font-size: var(--step--1);
  color: var(--color-on-primary);
}
.lightbox__close,
.lightbox__prev,
.lightbox__next {
  position: fixed;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 3rem;
  min-height: 3rem; /* the same comfortable tap target the page's buttons keep */
  padding: var(--space-3xs) var(--space-xs);
  font-family: var(--font-body);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.01em;
  color: var(--color-text);
  background: var(--color-surface);
  border: 2px solid transparent;
  border-radius: var(--radius-m); /* square, like every other button here */
  cursor: pointer;
}
.lightbox__close {
  top: var(--space-s);
  right: var(--space-s);
}
.lightbox__prev,
.lightbox__next {
  top: 50%;
  transform: translateY(-50%);
}
.lightbox__prev {
  left: var(--space-s);
}
.lightbox__next {
  right: var(--space-s);
}
.lightbox__count {
  position: fixed;
  left: 50%;
  bottom: var(--space-s);
  transform: translateX(-50%);
  font-size: var(--step--1);
  color: var(--color-on-primary);
}
/* On a phone there is no room beside the photograph, so the pair moves under it,
   side by side, and the counter rises above them. */
@media (max-width: 39.99em) {
  .lightbox__prev,
  .lightbox__next {
    top: auto;
    bottom: var(--space-s);
    transform: none;
  }
  .lightbox__prev {
    left: auto;
    right: 50%;
    margin-right: var(--space-2xs); /* two 48px targets closer than 16px read as one control */
  }
  .lightbox__next {
    right: auto;
    left: 50%;
    margin-left: var(--space-2xs);
  }
  .lightbox__count {
    bottom: calc(var(--space-s) + 3.5rem);
  }
}
@media (min-width: 40em) {
  .lightbox__figure {
    /* Previous and next sit at the sides on a wide screen, so the picture leaves
       them a column of their own. */
    padding: 4rem 9rem 5rem;
  }
}
@media (prefers-reduced-motion: no-preference) {
  .lightbox[open] {
    animation: lightbox-in var(--dur-hover) var(--ease-sharp);
  }
  @keyframes lightbox-in {
    from {
      opacity: 0;
    }
    to {
      opacity: 1;
    }
  }
}
/* The only thing holding the page still behind the open dialog — the script
   deliberately scrolls nothing itself. It is paired with the stable scrollbar
   gutter in the reset, so the page does not shift sideways as the bar goes. */
html.lightbox-open {
  overflow: hidden;
}

/* ── Price cards ─────────────────────────────────────────────────────────── */
/* One card per package, for a business that publishes prices; a business that
   does not leaves the section out rather than filling it with vague cards. Each
   card ends with exactly one action pinned to the bottom, so the buttons line up
   across cards whose lists are of different lengths. */
.plan-grid {
  display: grid;
  gap: var(--space-s);
  grid-template-columns: repeat(auto-fit, minmax(min(18rem, 100%), 1fr) /* never wider than the container, so a 320px phone gets one full-width column */);
  margin-top: var(--space-l);
}
.plan {
  display: flex;
  flex-direction: column;
  gap: var(--space-xs);
  padding: var(--space-m);
  background: var(--color-surface);
  border: var(--border-hair);
}
/* This template is flat, so the highlighted card is a filled block rather than a
   lifted one. The badge above its name says the same thing in words. */
.plan--featured {
  background: var(--color-primary);
  color: var(--color-on-primary);
  border-color: transparent;
}
.plan__badge {
  align-self: flex-start;
  padding: var(--space-3xs) var(--space-xs);
  font-size: var(--step--1);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  /* Near-black on the signal orange, not white: white on this orange sits at
     3.3:1, under the floor for a label at this size. */
  color: var(--color-text);
  background: var(--color-accent);
}
.plan__name {
  font-family: var(--font-heading);
  font-size: var(--step-1);
  line-height: var(--leading-tight);
  text-transform: uppercase;
}
.plan__price {
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: var(--step-3);
  line-height: var(--leading-tight);
  /* A price is as often a phrase as a figure ("Sopimuksen mukaan"), and at
     display size one long word in a narrow card would widen the whole page
     instead of wrapping inside the card. */
  overflow-wrap: break-word;
  hyphens: auto;
  -webkit-hyphens: auto;
}
/* The prefix and the period read as one phrase with the figure. Kept from
   breaking inside themselves, so a narrow card wraps "/ kk" as a unit instead of
   stranding the slash at the end of the line above. */
.plan__prefix,
.plan__period {
  white-space: nowrap;
  font-family: var(--font-body);
  font-size: var(--step-0);
  font-weight: 400;
  color: var(--color-muted);
}
.plan__list {
  list-style: none;
  padding: 0;
  display: grid;
  gap: var(--space-3xs);
  color: var(--color-muted);
}
.plan__action {
  margin-top: auto;
  padding-top: var(--space-xs);
}
/* The filled card carries its own light text: the muted and accent colours the
   other cards use are meant for a light ground and would not hold on this one.
   Its focus ring and its button switch for the same reason. */
.plan--featured .plan__prefix,
.plan--featured .plan__period,
.plan--featured .plan__list {
  color: var(--color-on-primary);
}
.plan--featured .plan__badge {
  color: var(--color-text);
  background: var(--color-on-primary);
}
.plan--featured .button--primary {
  color: var(--color-primary);
  background: var(--color-on-primary);
}
.plan--featured .button--primary:hover {
  color: var(--color-primary-shade);
  background: var(--color-primary-tint);
}
.plan--featured :focus-visible {
  outline-color: var(--color-on-primary);
}

/* ── Testimonial ─────────────────────────────────────────────────────────── */
.testimonial {
  max-width: 46ch;
  margin-inline: auto;
  padding: var(--space-l);
  text-align: left;
  border-left: 4px solid var(--color-accent); /* hard accent rule */
  background: var(--color-surface-alt);
  /* The accent bleeds a short way in from the rule, then flattens out.
     Token-derived; browsers without color-mix() keep the solid fill. */
  background: linear-gradient(90deg, color-mix(in srgb, var(--color-accent) 7%, var(--color-surface-alt)), var(--color-surface-alt) 45%);
}
.testimonial__quote {
  font-family: var(--font-heading);
  font-size: var(--step-2);
  line-height: 1.25;
  letter-spacing: -0.02em;
}
.testimonial__author {
  display: block;
  margin-top: var(--space-s);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--color-primary);
}

/* ── FAQ ─────────────────────────────────────────────────────────────────── */
.faq {
  max-width: 52rem;
  margin-inline: auto;
  border-top: var(--border-hair);
}
.faq__item {
  padding: var(--space-s) 0;
  border-bottom: var(--border-hair);
}
.faq__question {
  font-size: var(--step-1);
  margin-bottom: var(--space-2xs);
  text-transform: uppercase;
}
.faq__answer {
  color: var(--color-muted);
}
/* An answer longer than one paragraph (two paragraphs, or a paragraph and a list)
   needs the same spacing as a card: with every margin reset, its pieces would run
   together. */
.faq__answer > * + * {
  margin-top: var(--space-2xs);
}

/* ── Contact form (posts via mailto — no runtime dependency) ─────────────── */
.contact-form {
  display: grid;
  gap: var(--space-s);
  max-width: 40rem;
}
.contact-form__field {
  display: grid;
  gap: var(--space-3xs);
}
.contact-form__label {
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  font-size: var(--step--1);
}
.contact-form__input,
.contact-form__textarea {
  width: 100%;
  padding: 0.8rem 0.9rem;
  background: var(--color-surface);
  border: var(--border-hair);
  border-radius: var(--radius-m);
}
.contact-form__input:focus,
.contact-form__textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: inset 0 0 0 1px var(--color-primary);
}
.contact-form__textarea {
  min-height: 8rem;
  resize: vertical;
}

/* ── Footer ──────────────────────────────────────────────────────────────── */
.site-footer {
  padding-block: var(--space-xl) var(--space-l);
  background: var(--color-text);
  /* A steel cast of the primary at the top of the block settles into the
     near-black — both endpoints stay far darker than the light text, so the
     footer's >= 4.5:1 inversion holds. Browsers without color-mix() keep the
     solid block. */
  background: linear-gradient(180deg, color-mix(in srgb, var(--color-primary) 16%, var(--color-text)), var(--color-text) 45%);
  color: var(--color-surface);
}
.site-footer__inner {
  display: grid;
  gap: var(--space-l);
  grid-template-columns: 1fr;
}
@media (min-width: 48rem) {
  .site-footer__inner {
    grid-template-columns: repeat(3, 1fr);
  }
}
/* The footer inverts: a light `color` on the near-black block. The global h1-h4 rule sets
   `color: var(--color-text)`, which is more specific than inheritance and would paint the
   headings the same near-black as the block behind them (a 1:1 contrast — invisible).
   Inherit instead, so any heading added to the footer follows the inversion. */
.site-footer :is(h1, h2, h3, h4) {
  color: inherit;
}
.site-footer__heading {
  font-family: var(--font-heading);
  font-size: var(--step-1);
  margin-bottom: var(--space-s);
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.site-footer__link {
  display: block;
  padding: var(--space-3xs) 0;
  color: var(--color-surface);
  text-decoration: none;
}
.site-footer__link:hover {
  color: var(--color-accent);
}
.site-footer__legal {
  margin-top: var(--space-l);
  padding-top: var(--space-s);
  border-top: 1px solid color-mix(in srgb, var(--color-surface) 30%, transparent);
  color: color-mix(in srgb, var(--color-surface) 78%, transparent);
  font-size: var(--step--1);
}

/* ── Legal page ──────────────────────────────────────────────────────────── */
.legal {
  max-width: 62ch;
  margin-inline: auto;
  padding-block: var(--section-pad);
}
.legal__title {
  margin-bottom: var(--space-m);
  text-transform: uppercase;
}
.legal__body > * + * {
  margin-top: var(--space-s);
}
.legal__body h2 {
  font-size: var(--step-2);
  margin-top: var(--space-l);
  text-transform: uppercase;
}

/* ── Cookie banner (used only when a site sets cookies; main.js dismisses) ── */
.cookie-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 80; /* above content, below the skip link */
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-s);
  padding: var(--space-s) var(--space-m);
  background: var(--color-surface);
  border-top: var(--border-strong);
}
.cookie-banner__text {
  flex: 1 1 16rem;
  color: var(--color-muted);
  font-size: var(--step--1);
}
.cookie-banner__actions {
  display: flex;
  gap: var(--space-2xs);
}

/* ── Demo banner (pre-contract preview marker) ───────────────────────────── */
.demo-banner {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 90; /* above the cookie banner */
  padding: var(--space-2xs) var(--space-s);
  text-align: center;
  /* near-black block, not accent: white-on-accent orange fails 4.5:1 at this
     size — the text slot uses --color-text bg so contrast is guaranteed. */
  background: var(--color-text);
  color: var(--color-surface);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: var(--step--1);
}
/* The banner inverts like the footer: a light `color` on the near-black block.
   The global `a { color: var(--color-primary) }` rule would print its link in
   navy on near-black (1.6:1, illegible) — override with the same light surface
   token the banner text already uses. */
.demo-banner a {
  color: var(--color-surface);
}
.demo-banner a:hover {
  color: var(--color-accent);
}

/* ── Error (404) page ────────────────────────────────────────────────────── */
.error-page {
  display: grid;
  place-content: center;
  gap: var(--space-s);
  min-height: 60vh;
  padding: var(--section-pad) var(--space-s);
  text-align: center;
}
.error-page__code {
  font-family: var(--font-heading);
  font-size: var(--step-5);
  color: var(--color-primary);
  letter-spacing: -0.03em;
}
.error-page__title {
  font-size: var(--step-3);
  text-transform: uppercase;
}
.error-page__text {
  color: var(--color-muted);
  max-width: 40ch;
  margin-inline: auto;
}

/* ── Motion keyframes ────────────────────────────────────────────────────── */
/* hero-slide: the hero media slides in briskly from the left on load.
   Transform-only — no opacity fade — so the hero media paints immediately and
   never delays Largest Contentful Paint. */
@keyframes hero-slide {
  from {
    transform: translateX(-28px);
  }
  to {
    transform: none;
  }
}
/* sweep-in: a brisk left-to-right wipe for optional accent underlines. */
@keyframes sweep-in {
  from {
    transform: scaleX(0);
    transform-origin: left;
  }
  to {
    transform: scaleX(1);
    transform-origin: left;
  }
}

/* ── Map, click-to-load (only on a page with a confirmed street address) ──── */
/* The block reserves its space up front and holds only plain markup: nothing is
   requested from Google until the visitor presses the button, at which point
   main.js swaps the placeholder for the map frame. */
.map-embed {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--color-surface-alt);
  border: var(--border-hair);
  border-radius: var(--radius-m);
}
@media (min-width: 45rem) {
  .map-embed {
    aspect-ratio: 16 / 9;
  }
}
.map-embed__placeholder {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--space-xs);
  padding: var(--space-s);
  text-align: center;
}
/* The small print that tells the visitor what pressing the button will load. */
.map-embed__note {
  max-width: 44ch;
  color: var(--color-muted);
  font-size: var(--step--1);
}
/* Hidden without JavaScript, where pressing it could only do nothing; the link
   below it opens the same location in that case. */
.map-embed__load {
  display: none;
}
.js .map-embed__load {
  display: inline-flex;
}
.map-embed__link {
  font-size: var(--step--1);
}
.map-embed__frame {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  border: 0;
}

/* Detect disabled scripting before first paint; a delayed script must not collapse a tall header. */
@media (max-width: 47.99rem) and (scripting: none) {
  html:not(.js) .site-header { position: relative; }
  html:not(.js) .site-header__inner { flex-wrap: wrap; }
  html:not(.js) .site-header nav { width: 100%; }
  html:not(.js) .nav__toggle { display: none; }
  html:not(.js) .nav__menu {
    display: flex;
    position: static;
    flex-direction: column;
    align-items: stretch;
    width: 100%;
    min-width: 0;
    box-shadow: none;
  }
  html:not(.js) .nav__link { white-space: normal; overflow-wrap: anywhere; }
}
