/* base.css — "soft" template: warm craft.
 *
 * 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: rounded, warm, airy — humanist type, generous radii, soft two-layer
 * shadows, gentle ease-out motion. 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. */

/* fraunces-nunito */
@font-face {
  font-family: 'Fraunces';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('fonts/fraunces-normal-400-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: 'Nunito Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/nunito-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: 'Nunito Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/nunito-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: 'Nunito Sans';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/nunito-sans-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;
}

/* lora-sourcesans */
@font-face {
  font-family: 'Lora';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/lora-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: 'Lora';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/lora-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: 'Source Sans 3';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/source-sans-3-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: 'Source Sans 3';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/source-sans-3-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: 'Source Sans 3';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/source-sans-3-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;
}

/* bitter-karla */
@font-face {
  font-family: 'Bitter';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('fonts/bitter-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: 'Bitter';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/bitter-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: 'Karla';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/karla-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: 'Karla';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/karla-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: 'Karla';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/karla-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;
}

/* bricolage-figtree */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal;
  font-weight: 400 600;
  font-display: swap;
  src: url('fonts/bricolage-grotesque-normal-400-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: 'Figtree';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('fonts/figtree-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: 'Figtree';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('fonts/figtree-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: 'Figtree';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('fonts/figtree-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;
}



/* ── end web fonts ── */

/* ── 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 humanist pairs. */
:root {
  --color-primary: #586852;        /* lichen sage green — links, primary buttons, on-brand blocks (5.70:1 on surface) */
  --color-primary-shade: #4a5745;  /* darker sage for hover/active */
  --color-primary-tint: #e6ebdd;   /* pale sage tint for soft surfaces */
  --color-on-primary: #fbfcf6;     /* text/icons on --color-primary blocks (5.79:1) */
  --color-accent: #9a5f26;         /* burnt marigold — sparing decorative marks, underlines, hover */
  --color-surface: #fafaf4;        /* warm off-white page background */
  --color-surface-alt: #f1f2e8;    /* slightly deeper, faintly green background for alternating sections */
  --color-text: #242a21;           /* green-tinged near-black body text */
  --color-muted: #5f5a50;          /* warm grey for secondary text (>= 4.5:1 on surfaces) */
  --color-border: #e0e3d5;         /* pale sage line for gentle separation */

  --font-heading: 'Lora', 'Iowan Old Style', 'Palatino Linotype', Palatino, Georgia, serif;
  --font-body: 'Source Sans 3', '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.25 (major third), fluid via clamp; body line-height 1.65. */
  --step--1: clamp(0.82rem, 0.79rem + 0.13vw, 0.9rem);
  --step-0: clamp(1rem, 0.96rem + 0.18vw, 1.125rem);
  --step-1: clamp(1.25rem, 1.18rem + 0.34vw, 1.5rem);
  --step-2: clamp(1.56rem, 1.44rem + 0.6vw, 2rem);
  --step-3: clamp(1.95rem, 1.75rem + 1vw, 2.67rem);
  --step-4: clamp(2.44rem, 2.1rem + 1.7vw, 3.55rem);
  --step-5: clamp(3.05rem, 2.5rem + 2.75vw, 4.74rem);
  --leading-body: 1.65;
  --leading-tight: 1.15;

  /* Spacing rhythm (1.5rem base) + airy section padding. */
  --space-3xs: 0.375rem;
  --space-2xs: 0.75rem;
  --space-xs: 1rem;
  --space-s: 1.5rem;
  --space-m: 2.25rem;
  --space-l: 3.5rem;
  --space-xl: 5rem;
  --section-pad: clamp(3.5rem, 2.4rem + 5.5vw, 7rem);
  --container-max: 72rem;

  /* Generous radii — the soft character. */
  --radius-s: 8px;
  --radius-m: 14px;
  --radius-l: 24px;
  --radius-pill: 999px;

  /* Two-layer soft shadows (low opacity, large blur); no hairline borders. */
  --shadow-s: 0 1px 2px rgba(58, 38, 24, 0.06), 0 4px 12px rgba(58, 38, 24, 0.07);
  --shadow-m: 0 4px 10px rgba(58, 38, 24, 0.07), 0 14px 34px rgba(58, 38, 24, 0.1);
  --shadow-l: 0 10px 24px rgba(58, 38, 24, 0.09), 0 28px 60px rgba(58, 38, 24, 0.13);

  /* Gentle ease-out motion, 450-550ms. */
  --ease-soft: cubic-bezier(0.22, 0.61, 0.36, 1);
  --dur-reveal: 520ms;
  --dur-hover: 260ms;

  --header-h: 4.5rem;
}

/* ── Reset ───────────────────────────────────────────────────────────────── */
*,
*::before,
*::after {
  box-sizing: border-box;
}
* {
  margin: 0;
}
html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}
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.18em;
}
a:hover {
  color: var(--color-primary-shade);
}
h1,
h2,
h3,
h4 {
  font-family: var(--font-heading);
  line-height: var(--leading-tight);
  font-weight: 600;
  color: var(--color-text);
  letter-spacing: -0.005em;
}
h1 {
  font-size: var(--step-4);
}
h2 {
  font-size: var(--step-3);
}
h3 {
  font-size: var(--step-2);
}
ul,
ol {
  padding-left: 1.25em;
}

/* 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-primary);
  outline-offset: 3px;
  border-radius: var(--radius-s);
}

@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-primary);
  color: var(--color-on-primary);
  border-radius: var(--radius-m);
  transition: top var(--dur-hover) var(--ease-soft);
}
.skip-link:focus {
  top: var(--space-2xs);
  color: var(--color-on-primary);
}

/* 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: translateY(24px);
  transition: opacity var(--dur-reveal) var(--ease-soft), transform var(--dur-reveal) var(--ease-soft);
}
.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.85rem 1.75rem;
  border: 2px solid transparent;
  border-radius: var(--radius-pill); /* pill buttons — the soft character */
  font-weight: 700;
  font-size: var(--step-0);
  text-decoration: none;
  cursor: pointer;
  transition: transform var(--dur-hover) var(--ease-soft), box-shadow var(--dur-hover) var(--ease-soft),
    background-color var(--dur-hover) var(--ease-soft), color var(--dur-hover) var(--ease-soft);
}
.button--primary {
  background: var(--color-primary);
  color: var(--color-on-primary);
  box-shadow: var(--shadow-s);
}
.button--primary:hover {
  background: var(--color-primary-shade);
  color: var(--color-on-primary);
  transform: translateY(-2px); /* gentle lift */
  box-shadow: var(--shadow-m); /* shadow deepens on hover */
}
.button--ghost {
  background: transparent;
  color: var(--color-primary);
  border-color: var(--color-border);
}
.button--ghost:hover {
  color: var(--color-primary-shade);
  border-color: var(--color-primary);
  transform: translateY(-2px);
}

/* ── Header / navigation ─────────────────────────────────────────────────── */
.site-header {
  position: sticky;
  top: 0;
  z-index: 50; /* above page content, below the skip link */
  /* Opaque, not a translucent backdrop-blur: blur() forces a GPU repaint on
     every scroll frame, which spikes rendering cost — an opaque header keeps the
     sticky nav cheap and the paint deterministic. */
  background: var(--color-surface);
  transition: box-shadow var(--dur-hover) var(--ease-soft);
}
/* main.js adds --stuck once scrolled off the top; lift it with a soft shadow. */
.site-header--stuck {
  box-shadow: var(--shadow-s);
}
.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: 600;
  font-size: var(--step-1);
  color: var(--color-text);
  text-decoration: none;
}
.site-header__logo {
  width: 2.25rem;
  height: 2.25rem;
  border-radius: var(--radius-pill);
}
.nav__toggle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3rem;
  height: 3rem;
  background: transparent;
  border: 2px solid var(--color-border);
  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;
  border-radius: var(--radius-m);
}
.nav__link:hover,
.nav__link--active {
  color: var(--color-primary);
}
.nav__link--active {
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-decoration-thickness: 2px;
}

/* 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: var(--space-3xs);
    padding: var(--space-s);
    background: var(--color-surface);
    box-shadow: var(--shadow-m);
    border-bottom-left-radius: var(--radius-l);
    border-bottom-right-radius: var(--radius-l);
  }
  .nav__menu--open {
    display: flex;
  }
  .nav__link {
    width: 100%;
  }
}
@media (min-width: 48rem) {
  .nav__toggle {
    display: none;
  }
  .nav__menu {
    display: flex;
    align-items: center;
    gap: var(--space-3xs);
  }
}

/* ── Hero ────────────────────────────────────────────────────────────────── */
.hero {
  padding-block: var(--section-pad);
  background:
    radial-gradient(120% 90% at 15% 0%, var(--color-primary-tint), transparent 60%),
    var(--color-surface);
  /* Enhanced wash: a faint accent glow in the lower corner answers the primary
     tint above. Derived from brand tokens via color-mix(); browsers without
     color-mix() keep the declaration above. */
  background:
    radial-gradient(120% 90% at 15% 0%, var(--color-primary-tint), transparent 60%),
    radial-gradient(90% 70% at 92% 100%, color-mix(in srgb, var(--color-accent) 9%, transparent), transparent 62%),
    var(--color-surface);
  overflow: hidden; /* contains the rounded media bleed on small screens */
}
.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);
  font-weight: 700;
  color: var(--color-primary);
  letter-spacing: 0.02em;
}
.hero__title {
  font-size: var(--step-5);
  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: 16ch;
}
.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-radius: var(--radius-l); /* rounded image mask — soft character */
  overflow: hidden;
  /* --shadow-m, not --shadow-l: this is the largest above-the-fold element, and a
     60px-blur shadow is costly to paint — the mid shadow keeps the soft lift while
     keeping first paint cheap. */
  box-shadow: var(--shadow-m);
  animation: hero-rise var(--dur-reveal) var(--ease-soft) 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);
}
.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);
  font-weight: 700;
  color: var(--color-primary); /* text slot — primary carries the contrast; accent stays decorative */
  letter-spacing: 0.02em;
}
.section__title {
  font-size: var(--step-3);
}
.section__lead {
  margin-top: var(--space-s);
  color: var(--color-muted);
  font-size: var(--step-1);
}

/* ── Cards ───────────────────────────────────────────────────────────────── */
.card-grid {
  display: grid;
  gap: var(--space-m);
  grid-template-columns: 1fr;
}
@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 {
  padding: var(--space-m);
  background: var(--color-surface);
  /* A whisper of brand tint fading to the surface adds depth without a heavier
     shadow. Token-derived; browsers without color-mix() keep the solid surface. */
  background: linear-gradient(180deg, color-mix(in srgb, var(--color-primary-tint) 35%, var(--color-surface)), var(--color-surface) 55%);
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-s);
  transition: transform var(--dur-hover) var(--ease-soft), box-shadow var(--dur-hover) var(--ease-soft);
}
.card:hover {
  transform: translateY(-4px); /* hover lift */
  box-shadow: var(--shadow-m); /* shadow deepens */
}
.card__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 3.25rem;
  height: 3.25rem;
  margin-bottom: var(--space-s);
  border-radius: var(--radius-pill);
  background: var(--color-primary-tint);
  color: var(--color-primary);
}
.card__title {
  font-size: var(--step-1);
  margin-bottom: var(--space-2xs);
}
.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-s);
  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 {
  border-radius: var(--radius-l);
  overflow: hidden; /* clips the image to the rounded frame */
  box-shadow: var(--shadow-s);
}
.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-soft);
}
.gallery__item:hover .gallery__image {
  transform: scale(1.04);
}

/* ── Testimonial ─────────────────────────────────────────────────────────── */
.testimonial {
  max-width: 44ch;
  margin-inline: auto;
  padding: var(--space-l);
  text-align: center;
  background: var(--color-primary-tint);
  /* Soft diagonal blend of the tint toward the surface keeps the quote block
     airy. Token-derived; browsers without color-mix() keep the solid tint. */
  background: linear-gradient(135deg, var(--color-primary-tint), color-mix(in srgb, var(--color-primary-tint) 55%, var(--color-surface)));
  border-radius: var(--radius-l);
  box-shadow: var(--shadow-s);
}
.testimonial__quote {
  font-family: var(--font-heading);
  font-size: var(--step-2);
  line-height: 1.4;
}
.testimonial__author {
  display: block;
  margin-top: var(--space-s);
  font-weight: 700;
  color: var(--color-primary);
}

/* ── FAQ ─────────────────────────────────────────────────────────────────── */
.faq {
  max-width: 52rem;
  margin-inline: auto;
  display: grid;
  gap: var(--space-s);
}
.faq__item {
  padding: var(--space-s) var(--space-m);
  background: var(--color-surface);
  border-radius: var(--radius-m);
  box-shadow: var(--shadow-s);
}
.faq__question {
  font-size: var(--step-1);
  margin-bottom: var(--space-2xs);
}
.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;
}
.contact-form__input,
.contact-form__textarea {
  width: 100%;
  padding: 0.85rem 1rem;
  background: var(--color-surface);
  border: 2px solid var(--color-border);
  border-radius: var(--radius-m);
}
.contact-form__input:focus,
.contact-form__textarea:focus {
  outline: none;
  border-color: var(--color-primary);
  box-shadow: 0 0 0 3px var(--color-primary-tint);
}
.contact-form__textarea {
  min-height: 8rem;
  resize: vertical;
}

/* ── Footer ──────────────────────────────────────────────────────────────── */
.site-footer {
  padding-block: var(--space-xl) var(--space-l);
  background: var(--color-surface-alt);
  border-top: 1px solid var(--color-border);
}
.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);
  }
}
.site-footer__heading {
  font-family: var(--font-heading);
  font-size: var(--step-1);
  margin-bottom: var(--space-s);
}
.site-footer__link {
  display: block;
  padding: var(--space-3xs) 0;
  color: var(--color-text);
  text-decoration: none;
}
.site-footer__link:hover {
  color: var(--color-primary);
}
.site-footer__legal {
  margin-top: var(--space-l);
  padding-top: var(--space-s);
  border-top: 1px solid var(--color-border);
  color: var(--color-muted);
  font-size: var(--step--1);
}

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

/* ── Cookie banner (used only when a site sets cookies; main.js dismisses) ── */
.cookie-banner {
  position: fixed;
  left: var(--space-s);
  right: var(--space-s);
  bottom: var(--space-s);
  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-radius: var(--radius-l);
  box-shadow: var(--shadow-l);
}
.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;
  background: var(--color-primary);
  color: var(--color-on-primary);
  font-weight: 700;
  font-size: var(--step--1);
}

/* The global `a` rule sets the link colour directly, which beats the colour the
   banner merely passes down by inheritance — so without this the CTA renders in
   --color-primary on a --color-primary background at 1:1 and disappears. */
.demo-banner a {
  color: inherit;
}


/* ── 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);
}
.error-page__title {
  font-size: var(--step-3);
}
.error-page__text {
  color: var(--color-muted);
  max-width: 40ch;
  margin-inline: auto;
}

/* ── Motion keyframes ────────────────────────────────────────────────────── */
/* hero-rise: the hero media eases up on load (soft entrance). Transform-only —
   no opacity fade — so the (large) hero media paints immediately and never
   delays Largest Contentful Paint. */
@keyframes hero-rise {
  from {
    transform: translateY(28px);
  }
  to {
    transform: none;
  }
}
/* soft-pulse: a gentle attention pulse for optional accent marks. */
@keyframes soft-pulse {
  0%,
  100% {
    transform: scale(1);
  }
  50% {
    transform: scale(1.05);
  }
}

/* ── 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: 1px solid var(--color-border);
  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;
}
