/* ---------- tokens.css ---------- */
/**
 * Design tokens.
 *
 * Layout, type scale and section rhythm are matched to the RoofPro reference
 * template (measured at 1440px). The palette is NOT the template's: it is the
 * five brand colours supplied for this project, mapped onto the roles the
 * template uses. Every colour below is one of those five or a tint/shade of one
 * derived to hold a WCAG AA contrast ratio. No sixth hue is introduced.
 *
 *   Graphite      #171A18
 *   Deep Green    #2F5D46
 *   Warm White    #F6F5F1
 *   Concrete Grey #B8BBB6
 *   Pure White    #FFFFFF
 */
:root {
  /* ---- Surfaces -------------------------------------------------- */
  --canvas: #f6f5f1;              /* Warm White: the page ground */
  --canvas-alt: #f6f5f1;
  --surface: #ffffff;             /* Pure White: white sections and cards */
  --surface-sunken: #e4e5e1;

  /* ---- Ink ------------------------------------------------------- */
  --ink: #171a18;                 /* Graphite: headings */
  --ink-soft: #2a2e2b;
  --concrete: #6c706a;            /* Concrete Grey darkened to 4.6:1 on Warm White */
  --concrete-light: #848880;      /* 3.3:1 - LARGE display text only, never body */
  --deep-gray: #6c706a;

  /* ---- Lines ----------------------------------------------------- */
  --line: #dcddd9;                /* Concrete Grey, lightened for hairlines */
  --line-strong: #b8bbb6;         /* Concrete Grey */
  --line-dark: rgba(246, 245, 241, 0.14);
  --line-dark-strong: rgba(246, 245, 241, 0.26);

  /* ---- Accent (single) ------------------------------------------- */
  --accent: #2f5d46;              /* Deep Green - 7.6:1 on white */
  --accent-dark: #264b39;         /* hover */
  --accent-bright: #386f54;
  --accent-soft: #e7eee9;         /* success panel fill */
  --accent-onDark: #74a88c;       /* Deep Green lightened - 6.5:1 on Graphite */

  /* ---- Accent band ------------------------------------------------
     The template runs one full-bleed band in its accent colour. Here that
     band is Deep Green, and text on it is Warm White. */
  --brand: #2f5d46;
  --brand-ink: #f6f5f1;
  --brand-ink-soft: rgba(246, 245, 241, 0.78);
  --brand-card: rgba(246, 245, 241, 0.1);
  --brand-card-line: rgba(246, 245, 241, 0.22);

  /* ---- Dark sections: contact panel and footer --------------------- */
  --dark: #171a18;                /* Graphite */
  --dark-raised: #20241f;
  --dark-ink: #f6f5f1;            /* Warm White */
  --dark-concrete: #b8bbb6;       /* Concrete Grey - 9.0:1 on Graphite */

  /* ---- Feedback --------------------------------------------------- */
  --danger: #a3312a;
  --danger-onDark: #e78d86;
  --success: #2f5d46;

  /* ---- Type ------------------------------------------------------- */
  --font-display: 'Manrope', 'Helvetica Neue', Arial, sans-serif;
  --font-body: 'Manrope', 'Helvetica Neue', Arial, sans-serif;

  /* Template desktop scale: h1 56, h2 52, h3 36, h4 24, body 18 */
  --fs-h1: clamp(2.25rem, 1.5rem + 2.6vw, 3.5rem);
  --fs-h2: clamp(2rem, 1.35rem + 2.2vw, 3.25rem);
  --fs-h3: clamp(1.5rem, 1.26rem + 0.8vw, 2.25rem);
  --fs-h4: clamp(1.25rem, 1.14rem + 0.4vw, 1.5rem);
  --fs-h5: clamp(1.125rem, 1.07rem + 0.2vw, 1.25rem);
  --fs-lead: clamp(1rem, 0.96rem + 0.15vw, 1.125rem);
  --fs-body: 1.125rem;            /* 18px */
  --fs-small: 1rem;               /* 16px */
  --fs-label: 0.875rem;           /* 14px */
  --fs-label-sm: 0.75rem;         /* 12px */
  --fs-stat: clamp(2.75rem, 1.9rem + 2.9vw, 4.5rem);

  --lh-display: 1.2;
  --lh-heading: 1.2;
  --lh-body: 1.5;

  --track-display: -0.03em;
  --track-heading: -0.01em;
  --track-label: 0.04em;

  /* ---- Layout ------------------------------------------------------ */
  /* No max-width cap: the side gutter is a true 90px at every desktop width,
     rather than 90px up to 1600px and then a growing margin beyond it. Text
     blocks carry their own measure (`ch`) limits, so lines stay readable on
     wide displays. */
  --container: none;
  --gutter: 5.625rem;             /* 90px side padding, as specified */
  --section-y: clamp(3.5rem, 2.4rem + 4.4vw, 5rem);      /* 80px */
  --section-y-tight: clamp(3rem, 2.3rem + 2.7vw, 4rem);  /* 64px */
  --header-h: 6.25rem;            /* 100px navigation bar */
  --header-h-compact: 5.625rem;   /* 90px: 45px CTA plus even padding */
  --topbar-h: 0rem;               /* announcement bar removed */

  /* ---- Radius ------------------------------------------------------ */
  --r-xs: 4px;
  --r-sm: 8px;                    /* buttons, inputs */
  --r-md: 12px;
  --r-lg: 16px;                   /* cards, media */

  /* ---- Motion ------------------------------------------------------ */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast: 200ms;
  --dur-btn: 260ms;
  --dur-ui: 360ms;
  --dur-card: 420ms;
  --dur-media: 700ms;
  --dur-reveal: 780ms;

  /* ---- Elevation (restrained: the template leans on fills) ---------- */
  --shadow-sm: 0 1px 2px rgba(19, 27, 51, 0.04);
  --shadow-md: 0 12px 30px -18px rgba(19, 27, 51, 0.22);
  --shadow-lg: 0 30px 70px -40px rgba(19, 27, 51, 0.35);

  --z-header: 60;
  --z-widget: 70;
  --z-menu: 80;
  --z-modal: 90;
}

/* The 90px gutter is a desktop measure. Below that it steps down so narrow
   viewports keep a usable content width. */
@media (max-width: 1180px) {
  :root { --gutter: 3rem; }
}

@media (max-width: 991px) {
  :root {
    --gutter: 2rem;
    --header-h: 6.25rem;
    --header-h-compact: 4.5rem;
  }
}

@media (max-width: 760px) {
  :root {
    --gutter: 1.25rem;
    --header-h: 5.75rem;
    --header-h-compact: 4.25rem;
    --fs-body: 1rem;
  }
}

/* ---------- base.css ---------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1.5rem);
}

body {
  margin: 0;
  overflow-wrap: break-word;
  background: var(--canvas);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
}

body.is-locked { overflow: hidden; }

h1, h2, h3, h4, h5 {
  margin: 0;
  font-family: var(--font-display);
  font-weight: 500;
  letter-spacing: var(--track-heading);
  line-height: var(--lh-heading);
  color: var(--ink);
  text-wrap: balance;
}

p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; list-style: none; }
img, picture, svg, video { display: block; max-width: 100%; }

/* Components below set display on elements that are also toggled with the
   `hidden` attribute, so `hidden` has to win outright. */
[hidden] { display: none !important; }
img { height: auto; }
svg { width: 100%; height: 100%; }

a {
  color: inherit;
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease);
}

button {
  font: inherit;
  color: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

input, textarea, select { font: inherit; color: inherit; }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}

.is-dark :focus-visible,
.quote :focus-visible,
.footer :focus-visible,
.modal :focus-visible,
.lightbox :focus-visible {
  outline-color: var(--accent-onDark);
}

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

.skip-link {
  position: fixed;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 200;
  padding: 0.75rem 1.25rem;
  background: var(--ink);
  color: var(--canvas);
  font-size: var(--fs-small);
  border-radius: var(--r-sm);
  transform: translateY(-160%);
  transition: transform var(--dur-ui) var(--ease);
}
.skip-link:focus-visible { transform: translateY(0); }

::selection { background: var(--accent); color: var(--canvas); }

/* ---- Shared type primitives --------------------------------------- */

/* The template does not use eyebrow labels above section headings. Kept as a
   small inline meta line for the hero and the quote panel only. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  margin-bottom: 1.25rem;
  font-family: var(--font-body);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--accent);
}
.eyebrow span[aria-hidden] { color: var(--concrete); }
.eyebrow--light { color: var(--dark-ink); }
.eyebrow--light span[aria-hidden] { color: var(--brand-ink-soft); }

/**
 * Section header.
 * The template's signature: a two-line heading where the first line carries the
 * title colour and the second drops to grey, with the supporting sentence
 * pushed into a right-hand column and bottom-aligned against the heading.
 */
.sec-head {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 27.5rem);
  align-items: end;
  gap: 2rem 3rem;
  margin-bottom: 3rem;
}

.sec-head__title {
  font-size: var(--fs-h2);
  line-height: var(--lh-heading);
  letter-spacing: var(--track-heading);
  text-wrap: initial;
}
.sec-head__title span {
  display: block;
  color: var(--concrete-light);
}

.sec-head__lead {
  margin: 0;
  padding-bottom: 0.5rem;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--concrete);
  text-wrap: pretty;
}

/* Blue ground */
.sec-head--light .sec-head__title { color: var(--brand-ink); }
.sec-head--light .sec-head__title span { color: var(--brand-ink-soft); }
.sec-head--light .sec-head__lead { color: var(--brand-ink-soft); }

/* A hairline under the header, as used in the template's blue stat band. */
.sec-head--ruled {
  padding-bottom: 2rem;
  border-bottom: 1px solid var(--line);
}
.sec-head--light.sec-head--ruled { border-bottom-color: var(--line-dark-strong); }

/**
 * Single-line variant. The heading and its greyed second half sit on one line,
 * so the type scale is stepped down and the supporting sentence is given a
 * wider column, where it settles on two lines.
 */
.sec-head--oneline {
  grid-template-columns: minmax(0, 1fr) minmax(0, 31rem);
  gap: 2rem 3.5rem;
}
.sec-head--oneline .sec-head__title {
  font-size: clamp(1.75rem, 0.55rem + 2.15vw, 2.625rem);
  text-wrap: nowrap;
}
.sec-head--oneline .sec-head__title span { display: inline; }
.sec-head--oneline .sec-head__lead { font-size: var(--fs-small); }

/* Below this the heading no longer shares the row: it takes the full width and
   the sentence drops underneath it, still on two lines. */
@media (max-width: 1180px) {
  .sec-head--oneline {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: 1.25rem;
  }
  .sec-head--oneline .sec-head__lead { padding-bottom: 0; max-width: 46rem; }
}
@media (max-width: 620px) {
  .sec-head--oneline .sec-head__title { text-wrap: initial; }
}

/* Stacked variant for narrow columns */
.sec-head--stack {
  grid-template-columns: minmax(0, 1fr);
  align-items: start;
}
.sec-head--stack .sec-head__lead { padding-bottom: 0; max-width: 34ch; }

@media (max-width: 860px) {
  .sec-head {
    grid-template-columns: minmax(0, 1fr);
    align-items: start;
    gap: 1.25rem;
    margin-bottom: 2.25rem;
  }
  .sec-head__lead { padding-bottom: 0; max-width: 52ch; }
}

/* Legacy aliases, still used by a few panels */
.section__title {
  font-size: var(--fs-h2);
  letter-spacing: var(--track-heading);
  line-height: var(--lh-heading);
}
.section__title--light { color: var(--dark-ink); }

.section__lead {
  margin-top: 1.25rem;
  max-width: 46ch;
  font-size: var(--fs-body);
  color: var(--concrete);
}

/* ---------- layout.css ---------- */
/**
 * Page rhythm: one Warm White ground for every section between the hero and
 * the footer, a flat 80px vertical rhythm and 90px side gutters held at every
 * desktop width. The section separator is spacing and the occasional hairline,
 * never a colour change.
 */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Full-bleed row that still aligns its inner edge to the gutter. */
.container--flush { padding-inline: 0; }

.section { padding-block: var(--section-y); }
.section--tight { padding-block: var(--section-y-tight); }

.main { display: block; }

/* ---- Ground colours ------------------------------------------------ */
.band-white { background: var(--surface); }
.band-canvas { background: var(--canvas); }
.band-dark { background: var(--dark); color: var(--dark-ink); }

/* ---- Section rhythm ------------------------------------------------
   Every content section sits on the same Warm White ground. */
.main { background: var(--canvas); }

.service,
.credential,
.projects,
.benefits,
.reviews,
.faq { padding-block: var(--section-y); background: var(--canvas); }

.quote { padding-block: var(--section-y); background: var(--canvas); }

/* ---- Media defaults ------------------------------------------------ */

/* `picture` is inline by default, so inside an aspect-ratio frame it leaves a
   strip of the frame's background showing under the image. */
.hero__bg picture,
.credential__media picture,
.service__media-layer picture,
.project__media picture,
.benefits__media picture,
.lightbox__figure picture { display: block; width: 100%; height: 100%; }

.media__img,
.service__media-img,
.project__img,
.benefits__img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---------- buttons.css ---------- */
/**
 * Buttons, matched to the reference template.
 *
 * Hover behaviour is the template's: the fill swaps to the contrasting colour,
 * the whole control scales down to 0.95, and the label rolls up out of a
 * clipped box while a second copy rolls in from below. Transitions are the
 * template's timings too (transform .6s, colour .4s).
 */
.btn {
  --btn-bg: var(--accent);
  --btn-fg: var(--canvas);
  --btn-border: var(--accent);
  --btn-bg-hover: var(--ink);
  --btn-fg-hover: var(--canvas);
  --btn-border-hover: var(--ink);
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.625rem;
  min-height: 3.4375rem;          /* 55px, as measured on the template */
  padding: 0 2.25rem;
  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-border);
  border-radius: var(--r-sm);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  font-weight: 500;
  letter-spacing: 0.5px;
  text-align: center;
  cursor: pointer;
  transition:
    background-color var(--dur-btn) var(--ease),
    border-color var(--dur-btn) var(--ease),
    color var(--dur-btn) var(--ease),
    transform 600ms var(--ease);
}

.btn:hover {
  background: var(--btn-bg-hover);
  color: var(--btn-fg-hover);
  border-color: var(--btn-border-hover);
  transform: scale(0.95);
}
.btn:active { transform: scale(0.93); }

/* ---- Rolling label ------------------------------------------------------ */
.btn__label {
  position: relative;
  display: block;
  overflow: hidden;
  white-space: nowrap;
}
.btn__label-a,
.btn__label-b {
  display: block;
  transition: transform 460ms var(--ease);
}
.btn__label-b {
  position: absolute;
  inset: 0;
  transform: translateY(102%);
}
.btn:hover .btn__label-a { transform: translateY(-102%); }
.btn:hover .btn__label-b { transform: translateY(0); }

.btn__icon {
  display: inline-flex;
  width: 1.125rem;
  height: 1.125rem;
  flex: none;
  transition: transform var(--dur-btn) var(--ease);
}
.btn:hover .btn__icon { transform: translateX(4px); }

/* ---- Variants ----------------------------------------------------------- */
.btn--primary,
.btn--accent {
  --btn-bg: var(--accent);
  --btn-fg: var(--canvas);
  --btn-border: var(--accent);
  --btn-bg-hover: var(--ink);
  --btn-fg-hover: var(--canvas);
  --btn-border-hover: var(--ink);
}

/* Outline, as used beside the hero's primary action. */
.btn--secondary {
  --btn-bg: transparent;
  --btn-fg: var(--accent);
  --btn-border: var(--accent);
  --btn-bg-hover: var(--accent);
  --btn-fg-hover: var(--canvas);
  --btn-border-hover: var(--accent);
}
.btn--secondary .btn__icon { width: 1rem; height: 1rem; }
.btn--secondary:hover .btn__icon { transform: none; }

/* On a Deep Green ground the outline inverts to Warm White. */
.btn--onBrand {
  --btn-bg: var(--canvas);
  --btn-fg: var(--accent);
  --btn-border: var(--canvas);
  --btn-bg-hover: var(--ink);
  --btn-fg-hover: var(--canvas);
  --btn-border-hover: var(--ink);
}

/* Outline on a dark ground or over photography. The faint Graphite fill and
   the blur keep the label legible wherever the image behind it is bright. */
.btn--outlineLight {
  --btn-bg: rgba(23, 26, 24, 0.34);
  --btn-fg: var(--dark-ink);
  --btn-border: rgba(246, 245, 241, 0.45);
  --btn-bg-hover: var(--canvas);
  --btn-fg-hover: var(--ink);
  --btn-border-hover: var(--canvas);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.btn--outlineLight .btn__icon { width: 1rem; height: 1rem; }
.btn--outlineLight:hover .btn__icon { transform: none; }

@media (prefers-reduced-transparency: reduce) {
  .btn--outlineLight { --btn-bg: rgba(23, 26, 24, 0.86); backdrop-filter: none; -webkit-backdrop-filter: none; }
}

/* Uppercase label, as the template sets its in-row actions. */
.btn--caps {
  font-size: var(--fs-label);
  font-weight: 600;
  text-transform: uppercase;
}

/* Compact control used in the header bar (14px / 600 / 45px tall). */
.btn--sm {
  min-height: 2.8125rem;
  padding: 0 1.5rem;
  font-size: var(--fs-label);
  font-weight: 600;
}

/* Text link. No fill, so no scale: the roll alone carries the hover. */
.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--accent);
  --btn-border: transparent;
  --btn-bg-hover: transparent;
  --btn-fg-hover: var(--ink);
  --btn-border-hover: transparent;
  min-height: 2.75rem;
  padding: 0;
  gap: 0.625rem;
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
}
.btn--ghost:hover { transform: none; }
.btn--ghost .btn__icon { width: 1rem; height: 1rem; }
.btn--ghost:hover .btn__icon { transform: none; }

/* Submit button with inline loading + disabled states */
.form__submit { width: 100%; }
.form__submit .btn__spinner {
  position: absolute;
  width: 1.125rem;
  height: 1.125rem;
  border: 2px solid currentColor;
  border-top-color: transparent;
  border-radius: 50%;
  opacity: 0;
}
.form__submit[data-state='loading'] { pointer-events: none; }
.form__submit[data-state='loading'] .btn__label,
.form__submit[data-state='loading'] .btn__icon { opacity: 0; }
.form__submit[data-state='loading'] .btn__spinner {
  opacity: 1;
  animation: spin 720ms linear infinite;
}
.form__submit[disabled] { opacity: 0.55; pointer-events: none; }

@keyframes spin { to { transform: rotate(360deg); } }

/* The roll and the scale are decoration; under reduced motion the colour
   swap alone carries the hover. */
@media (prefers-reduced-motion: reduce) {
  .btn:hover { transform: none; }
  .btn:hover .btn__label-a,
  .btn:hover .btn__label-b { transform: none; }
  .btn__label-b { display: none; }
}

/* ---------- header.css ---------- */
/**
 * Header: a solid white navbar, wordmark left, uppercase links centred, one
 * green action right.
 *
 * The bar has two states, driven entirely by the `is-scrolled` class that
 * src/scripts/header.js already toggles at 24px:
 *
 *   at the top   - the navbar floats over the hero photograph as an inset
 *                  dark glass panel;
 *   once scrolled - the solid white navbar returns.
 *
 * Both states read from the same custom properties below, so every child rule
 * is written once. The mobile menu forces the solid state, because the panel
 * behind it is Warm White.
 */
.header {
  /* Solid state (default, and whenever the mobile menu is open). */
  /* Graphite rather than white: the logo artwork is yellow and would not
     read on a white bar. */
  --hdr-bar: var(--dark);
  --hdr-panel: transparent;
  --hdr-panel-line: transparent;
  --hdr-blur: none;
  --hdr-shadow: none;
  --hdr-inset: 0px;
  --hdr-top: 0px;
  --hdr-pad: var(--gutter);
  --hdr-radius: 0px;
  --hdr-ink: var(--dark-ink);
  --hdr-accent: var(--accent-onDark);
  --hdr-muted: var(--dark-concrete);
  --hdr-line: rgba(246, 245, 241, 0.42);

  position: fixed;
  inset: 0 0 auto 0;
  z-index: var(--z-header);
  transition: transform var(--dur-ui) var(--ease);
}

/* Floating glass state over the hero photograph. */
.header:not(.is-scrolled):not(.is-menu-open) {
  --hdr-bar: transparent;
  --hdr-panel: rgba(23, 26, 24, 0.5);
  --hdr-panel-line: rgba(246, 245, 241, 0.16);
  --hdr-blur: blur(18px) saturate(140%);
  --hdr-shadow: inset 0 1px 0 rgba(246, 245, 241, 0.1);
  --hdr-inset: var(--gutter);
  --hdr-top: clamp(0.875rem, 1.2vw, 1.375rem);
  --hdr-pad: clamp(1rem, 1.4vw, 1.75rem);
  --hdr-radius: var(--r-lg);
  --hdr-ink: var(--dark-ink);
  --hdr-accent: var(--accent-onDark);
  --hdr-muted: var(--dark-concrete);
  --hdr-line: rgba(246, 245, 241, 0.42);
}

/* Where the blur is unavailable or unwanted the panel falls back to a solid
   Graphite fill rather than losing its contrast floor. */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .header:not(.is-scrolled):not(.is-menu-open) { --hdr-panel: rgba(23, 26, 24, 0.84); }
}
@media (prefers-reduced-transparency: reduce) {
  .header:not(.is-scrolled):not(.is-menu-open) {
    --hdr-panel: rgba(23, 26, 24, 0.92);
    --hdr-blur: none;
  }
}

/* ---- Navbar ---------------------------------------------------------- */
.navbar {
  background: var(--hdr-bar);
  padding-top: var(--hdr-top);
  padding-inline: var(--hdr-inset);
  transition: background-color var(--dur-ui) var(--ease), padding var(--dur-ui) var(--ease);
}

.header__inner {
  display: flex;
  align-items: center;
  /* space-between only bites once the nav is hidden: while it is visible its
     auto side margins absorb the free space first and keep it centred. */
  justify-content: space-between;
  gap: clamp(1rem, 2vw, 2.5rem);
  /* min-height, not height: the compact scrolled bar must never clip the CTA
     or the menu button at the breakpoints where those controls are tallest. */
  min-height: calc(var(--header-h) - var(--topbar-h));
  padding-inline: var(--hdr-pad);
  /* Transparent by default so switching states never changes the box height. */
  border: 1px solid var(--hdr-panel-line);
  border-radius: var(--hdr-radius);
  background: var(--hdr-panel);
  backdrop-filter: var(--hdr-blur);
  -webkit-backdrop-filter: var(--hdr-blur);
  box-shadow: var(--hdr-shadow);
  transition:
    min-height var(--dur-ui) var(--ease),
    padding var(--dur-ui) var(--ease),
    background-color var(--dur-ui) var(--ease),
    border-color var(--dur-ui) var(--ease),
    border-radius var(--dur-ui) var(--ease);
}

.header.is-scrolled .header__inner { min-height: calc(var(--header-h-compact) - var(--topbar-h)); }
.header.is-scrolled .navbar { box-shadow: 0 1px 0 var(--line-dark); }

/* Hidden while scrolling down, returns on scroll up */
.header.is-hidden { transform: translateY(-102%); }
.header.is-menu-open { transform: none; }

/* ---- Logo ---------------------------------------------------------- */
.wordmark {
  display: inline-flex;
  align-items: center;
  flex: none;
}
.wordmark__logo,
.wordmark__logo img {
  display: block;
  height: 3.5rem;
  width: auto;
}
.header.is-scrolled .wordmark__logo,
.header.is-scrolled .wordmark__logo img { height: 3.125rem; }

/* ---- Desktop nav ---------------------------------------------------- */
.nav {
  margin-inline: auto;
}
.nav__list { display: flex; align-items: center; gap: clamp(0.75rem, 1.8vw, 1.875rem); }

.nav__link {
  position: relative;
  display: inline-block;
  padding: 0.25rem 0;
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.5px;
  text-transform: uppercase;
  color: var(--hdr-ink);
  white-space: nowrap;
  transition: color var(--dur-ui) var(--ease);
}
.nav__link::after {
  content: '';
  position: absolute;
  left: 0;
  bottom: -2px;
  width: 100%;
  height: 2px;
  background: var(--hdr-accent);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-ui) var(--ease);
}
.nav__link:hover { color: var(--hdr-accent); }
.nav__link:hover::after,
.nav__link.is-current::after { transform: scaleX(1); }
.nav__link.is-current { color: var(--hdr-accent); }

/* ---- Actions --------------------------------------------------------- */
.header__actions { display: flex; align-items: center; gap: clamp(0.75rem, 1.4vw, 1.25rem); flex: none; }

.header__phone {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--fs-label);
  font-weight: 600;
  color: var(--hdr-ink);
  white-space: nowrap;
  transition: color var(--dur-ui) var(--ease), border-color var(--dur-ui) var(--ease);
}
.header__phone-icon { width: 1rem; height: 1rem; color: var(--hdr-accent); flex: none; transition: color var(--dur-ui) var(--ease); }
.header__phone:hover { color: var(--hdr-accent); }

.header__cta { min-height: 2.8125rem; padding-inline: 1.5rem; font-size: var(--fs-label); font-weight: 600; }
/* The default hover fill is Graphite, which would vanish into the bar. */
.header__cta {
  --btn-bg-hover: var(--accent-bright);
  --btn-border-hover: var(--accent-bright);
}

@media (max-width: 1180px) {
  .header__phone { display: none; }
}

.menu-toggle {
  display: none;
  width: 2.875rem;
  height: 2.875rem;
  border: 1px solid var(--hdr-line);
  border-radius: var(--r-sm);
  align-items: center;
  justify-content: center;
  transition: border-color var(--dur-ui) var(--ease), background-color var(--dur-fast) var(--ease);
}
.menu-toggle:hover { border-color: var(--hdr-ink); }

.menu-toggle__bars {
  position: relative;
  display: block;
  width: 1.125rem;
  height: 0.625rem;
}
.menu-toggle__bars span {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: var(--hdr-ink);
  border-radius: 2px;
  transition: transform var(--dur-ui) var(--ease), opacity var(--dur-fast) var(--ease);
}
.menu-toggle__bars span:first-child { top: 0; }
.menu-toggle__bars span:last-child { bottom: 0; }

.menu-toggle[aria-expanded='true'] .menu-toggle__bars span:first-child {
  transform: translateY(4.25px) rotate(45deg);
}
.menu-toggle[aria-expanded='true'] .menu-toggle__bars span:last-child {
  transform: translateY(-4.25px) rotate(-45deg);
}

/* ---- Mobile panel ----------------------------------------------------- */
.mobile-nav {
  position: fixed;
  inset: var(--header-h) 0 0 0;
  z-index: var(--z-menu);
  background: var(--canvas);
  overflow-y: auto;
  overscroll-behavior: contain;
  opacity: 0;
  transition: opacity var(--dur-ui) var(--ease);
}
.mobile-nav[hidden] { display: none; }
.mobile-nav.is-open { opacity: 1; }

/* The panel is sized against the viewport height, not a fixed scale, so the
   whole menu - six links, both contacts and the quote button - lands on one
   screen on a short phone instead of scrolling. */
.mobile-nav__inner {
  display: flex;
  flex-direction: column;
  justify-content: space-between;
  /* Each dvh rule is preceded by a static fallback, so a browser without dvh
     support keeps a sane fixed scale instead of dropping the declaration. */
  gap: 1.5rem;
  gap: clamp(1rem, 2.6dvh, 2.25rem);
  min-height: 100%;
  padding: 1.25rem var(--gutter) calc(1.5rem + env(safe-area-inset-bottom));
  padding:
    clamp(0.875rem, 2.2dvh, 2rem)
    var(--gutter)
    calc(clamp(1rem, 2.6dvh, 2.25rem) + env(safe-area-inset-bottom));
}

.mobile-nav__list { display: flex; flex-direction: column; border-top: 1px solid var(--line); }
.mobile-nav__list li { border-bottom: 1px solid var(--line); }

.mobile-nav__link {
  display: block;
  padding-block: 0.75rem;
  padding-block: clamp(0.5rem, 1.4dvh, 1rem);
  font-family: var(--font-display);
  font-size: 1.375rem;
  font-size: clamp(1.125rem, 3.3dvh, 1.625rem);
  line-height: 1.15;
  font-weight: 600;
  letter-spacing: -0.02em;
  color: var(--ink);
  opacity: 0;
  transform: translateY(14px);
}
.mobile-nav.is-open .mobile-nav__link {
  opacity: 1;
  transform: none;
  transition:
    opacity 420ms var(--ease) calc(90ms + var(--i) * 55ms),
    transform 420ms var(--ease) calc(90ms + var(--i) * 55ms);
}

.mobile-nav__foot { display: flex; flex-direction: column; gap: 0.5rem; }
.mobile-nav__foot { gap: clamp(0.25rem, 0.8dvh, 0.75rem); }

.mobile-nav__contact {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  font-size: 0.9375rem;
  font-weight: 500;
  color: var(--ink-soft);
  min-height: 2.75rem;
}
.mobile-nav__contact span[aria-hidden] { width: 1.0625rem; height: 1.0625rem; color: var(--accent); flex: none; }

.mobile-nav__cta { margin-top: 0.25rem; width: 100%; }
.mobile-nav__cta { margin-top: clamp(0.125rem, 0.8dvh, 0.5rem); }

.mobile-nav__social { margin-top: 0.5rem; display: flex; align-items: baseline; gap: 1rem; }
.mobile-nav__social { margin-top: clamp(0.25rem, 1dvh, 0.75rem); }
.mobile-nav__social-label {
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--concrete);
}
.mobile-nav__social-list { display: flex; gap: 1rem; }
.mobile-nav__social-list a { font-size: var(--fs-small); color: var(--ink-soft); }
.mobile-nav__social-list a:hover { color: var(--accent); }

@media (max-width: 1080px) {
  .nav { display: none; }
  .header__phone-number { display: none; }
  .header__phone {
    width: 2.875rem;
    height: 2.875rem;
    justify-content: center;
    border: 1px solid var(--hdr-line);
    border-radius: var(--r-sm);
  }
  .menu-toggle { display: inline-flex; }
}

@media (max-width: 600px) {
  .header__cta { display: none; }
  .wordmark__logo,
  .wordmark__logo img,
  .header.is-scrolled .wordmark__logo img { height: 2.875rem; }
}

/* ---------- hero.css ---------- */
/**
 * Hero: one full-bleed photograph carrying the whole first viewport, with the
 * headline block anchored bottom-left and the proof card bottom-right. The
 * header floats over it as a dark glass bar (see header.css) and returns to the
 * solid white navbar as soon as the page scrolls.
 *
 * Every colour here is one of the five brand colours or a tint of one: the
 * ground is Graphite, the type is Warm White, the muted type is Concrete Grey,
 * and the accent is Deep Green lightened for dark grounds (--accent-onDark).
 */
.hero {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: flex-end;
  /* Fills the first viewport exactly. dvh, not vh, so the iOS Safari address
     bar cannot make the section taller than the screen. */
  min-height: 100dvh;
  padding-top: calc(var(--header-h) + 2rem);
  padding-bottom: clamp(2.5rem, 4.5vw, 4.5rem);
  background: var(--dark);
  color: var(--dark-ink);
  overflow: hidden;
}

/* ---- Background photograph ------------------------------------------- */
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
}

.hero__picture,
.hero__picture .media__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* The source frame is 16:9, so a desktop viewport crops almost nothing and
     the frame reads as shot. */
  object-position: 50% 50%;
}

/* The narrower the viewport, the more of the 16:9 frame is cropped away, so the
   crop is pulled right in two steps to keep the installer and the mesh he is
   working in shot rather than clipped at the frame edge. A phone sees roughly
   a quarter of the frame's width, which is why it needs the harder shift. */
@media (max-width: 1080px) {
  .hero__picture,
  .hero__picture .media__img { object-position: 82% 50%; }
}
@media (max-width: 760px) {
  .hero__picture,
  .hero__picture .media__img { object-position: 88% 50%; }
}

/**
 * Three stacked gradients rather than one flat overlay: the bottom wash carries
 * the headline block, the left wash covers the bright rendered wall behind the
 * copy, and the short top wash keeps the announcement bar and the navigation
 * legible against the sky. Measured for WCAG AA on Warm White and Concrete Grey.
 */
.hero__scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(
      to top,
      rgba(23, 26, 24, 0.94) 0%,
      rgba(23, 26, 24, 0.8) 22%,
      rgba(23, 26, 24, 0.46) 46%,
      rgba(23, 26, 24, 0.12) 70%,
      rgba(23, 26, 24, 0) 84%
    ),
    linear-gradient(
      to right,
      rgba(23, 26, 24, 0.78) 0%,
      rgba(23, 26, 24, 0.46) 38%,
      rgba(23, 26, 24, 0) 64%
    ),
    linear-gradient(
      to bottom,
      rgba(23, 26, 24, 0.6) 0%,
      rgba(23, 26, 24, 0.18) 16%,
      rgba(23, 26, 24, 0) 32%
    );
}

/* ---- Content ----------------------------------------------------------- */
.hero__inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  align-items: end;
  gap: clamp(2rem, 4vw, 3.5rem);
  width: 100%;
}

.hero__title {
  /* Sized so both authored lines stay on one line each next to the proof card. */
  font-size: clamp(2.25rem, 0.9rem + 3.1vw, 3.5rem);
  font-weight: 500;
  line-height: 1.12;
  letter-spacing: var(--track-display);
  color: var(--dark-ink);
  text-wrap: initial;
}
.hero__title .line { display: block; overflow: hidden; padding-bottom: 0.08em; }
.hero__title .line > span { display: block; }
.hero__title em { font-style: normal; color: var(--accent-onDark); }

.hero__lead {
  margin-top: clamp(1rem, 1.6vw, 1.5rem);
  max-width: 34rem;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--dark-concrete);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 1rem;
  margin-top: clamp(1.75rem, 3vw, 2.5rem);
}

/* ---- Grant messaging ---------------------------------------------------- */
.hero__badge {
  display: inline-flex;
  align-items: center;
  margin-bottom: clamp(1rem, 1.6vw, 1.5rem);
  padding: 0.5rem 0.9375rem;
  border-radius: 999px;
  background: var(--accent);
  color: var(--dark-ink);
  font-size: var(--fs-label);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.hero__grants {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem 2rem;
  margin-top: clamp(1.25rem, 2vw, 1.75rem);
}
.hero__grants li {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  font-size: var(--fs-body);
  font-weight: 600;
  line-height: 1.35;
  color: var(--dark-ink);
}
.hero__grants-icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 1.625rem;
  height: 1.625rem;
  padding: 0.3125rem;
  border-radius: 50%;
  background: rgba(116, 168, 140, 0.18);
  color: var(--accent-onDark);
}

/* ---- Proof card -------------------------------------------------------- */
.hero__proof {
  align-self: end;
  width: 100%;
  max-width: 22rem;
  padding: clamp(1.25rem, 1.8vw, 1.75rem);
  border: 1px solid rgba(246, 245, 241, 0.18);
  border-radius: var(--r-lg);
  background: rgba(23, 26, 24, 0.44);
  backdrop-filter: blur(18px) saturate(135%);
  -webkit-backdrop-filter: blur(18px) saturate(135%);
  box-shadow: inset 0 1px 0 rgba(246, 245, 241, 0.12);
}

/* Solid fill wherever the blur is unavailable or unwanted, so the card never
   loses its contrast floor. */
@supports not ((backdrop-filter: blur(2px)) or (-webkit-backdrop-filter: blur(2px))) {
  .hero__proof { background: rgba(23, 26, 24, 0.82); }
}
@media (prefers-reduced-transparency: reduce) {
  .hero__proof {
    background: rgba(23, 26, 24, 0.92);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

.hero__proof-label {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--dark-concrete);
}

.hero__proof-figure {
  display: flex;
  align-items: baseline;
  gap: 0.125rem;
  margin-top: 0.75rem;
  font-family: var(--font-display);
  font-size: clamp(2.75rem, 1.9rem + 2.2vw, 3.75rem);
  font-weight: 700;
  line-height: 1;
  letter-spacing: var(--track-display);
  color: var(--dark-ink);
}
.hero__proof-figure span {
  font-size: 0.36em;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--dark-concrete);
}

.hero__proof-stars { display: flex; align-items: center; gap: 0.3125rem; margin-top: 0.875rem; }
.proof__star { display: block; width: 1.0625rem; height: 1.0625rem; color: var(--accent-onDark); }
.proof__star.is-empty { color: rgba(246, 245, 241, 0.28); }

.hero__proof-caption {
  margin-top: 0.625rem;
  font-size: var(--fs-small);
  line-height: 1.45;
  color: var(--dark-concrete);
}

/* Certification variant, shown while no verified rating exists. */
.hero__proof-title {
  margin-top: 0.75rem;
  font-family: var(--font-display);
  font-size: var(--fs-h5);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: var(--track-heading);
  color: var(--dark-ink);
}
.hero__proof-title + .hero__proof-caption { margin-top: 0.5rem; }

/* ---- Responsive --------------------------------------------------------- */

/* Two columns only once the headline column is wide enough to hold both
   authored lines without wrapping. */
@media (min-width: 1200px) {
  .hero__inner {
    grid-template-columns: minmax(0, 1fr) minmax(17rem, 20rem);
    gap: 3rem;
  }
  .hero__proof { justify-self: end; }
}

@media (max-width: 860px) {
  .hero {
    padding-top: calc(var(--header-h) + 2.5rem);
  }
  /* The copy now runs the full width, so the side wash is replaced by an even
     wash across the whole frame. */
  .hero__scrim {
    background:
      linear-gradient(
        to top,
        rgba(23, 26, 24, 0.94) 0%,
        rgba(23, 26, 24, 0.84) 32%,
        rgba(23, 26, 24, 0.64) 60%,
        rgba(23, 26, 24, 0.46) 84%,
        rgba(23, 26, 24, 0.36) 100%
      ),
      linear-gradient(to bottom, rgba(23, 26, 24, 0.5) 0%, rgba(23, 26, 24, 0) 24%);
  }
  .hero__lead { max-width: 32rem; }
  .hero__proof { max-width: 24rem; }
}

@media (max-width: 640px) {
  .hero__inner { gap: 1.75rem; }
  .hero__actions { gap: 0.75rem; }
  .hero__grants { flex-direction: column; gap: 0.625rem; }
  .hero__actions .btn { flex: 1 1 14rem; }
  .hero__proof { max-width: none; padding: 1.125rem 1.25rem; }
  .hero__proof-figure { margin-top: 0.5rem; font-size: 2.5rem; }
  .hero__proof-stars { margin-top: 0.625rem; }
}

/* ---------- service.css ---------- */
/**
 * Service stages, matched to the reference template's expertise row.
 *
 * Row layout:
 *
 *   [01] Title ............................................ [ photograph ]
 *        Description                                        [ photograph ]
 *        [ Action ]                                         [ photograph ]
 *
 * The photograph column is a fixed width so the arrow mark on a closed row
 * sits exactly where the photograph will appear, and its top edge lines up
 * with the top of the title. Both the description and the photograph animate
 * through grid-template-rows, so nothing is measured in JavaScript.
 */
/* No rule above the first row: the space under the section lead separates the
   list, and each row already carries its own bottom hairline. */
.stage-list { border-top: 0; }

.stage {
  --stage-num: 1.5rem;          /* the "01" column */
  --stage-gap: 1.25rem;         /* number to title */
  --stage-media: 31rem;         /* photograph column */
  --stage-lead: 0.5rem;         /* title line box inset, matched by the aside */

  display: grid;
  grid-template-columns: minmax(0, 1fr) var(--stage-media);
  column-gap: clamp(1.5rem, 3vw, 3rem);
  align-items: start;
  padding-block: clamp(1rem, 1.8vw, 1.5rem);
  border-bottom: 1px solid var(--line);
}

/* ---- Left column -------------------------------------------------------- */
.stage__main {
  display: grid;
  grid-template-columns: var(--stage-num) minmax(0, 1fr);
  column-gap: var(--stage-gap);
}

.stage__head {
  grid-column: 1 / -1;
  display: grid;
  grid-template-columns: var(--stage-num) minmax(0, 1fr);
  column-gap: var(--stage-gap);
  align-items: baseline;
  width: 100%;
  padding-block: var(--stage-lead);
  text-align: left;
}

.stage__index {
  font-family: var(--font-display);
  font-size: 0.8125rem;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
  transition: color var(--dur-card) var(--ease);
}

.stage__title {
  display: block;
  font-family: var(--font-display);
  font-size: clamp(1.375rem, 1.05rem + 0.9vw, 2rem);
  font-weight: 500;
  letter-spacing: var(--track-heading);
  line-height: 1.2;
  color: var(--ink);
  transition: color var(--dur-card) var(--ease);
}

/* Description and action, aligned under the title rather than the number. */
.stage__panel {
  grid-column: 2;
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-card) var(--ease);
}
.stage.is-open .stage__panel { grid-template-rows: 1fr; }

.stage__panel-inner {
  min-height: 0;
  overflow: hidden;
  opacity: 0;
  transition: opacity var(--dur-ui) var(--ease);
}
.stage.is-open .stage__panel-inner { opacity: 1; }

.stage__text {
  max-width: 34rem;
  padding-top: 0.75rem;
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--concrete);
}

.stage__cta { padding-top: clamp(1.5rem, 2.4vw, 2.25rem); }

/* ---- Right column ------------------------------------------------------- */
.stage__aside {
  position: relative;
  /* Holds the arrow's height while the row is closed. */
  min-height: 3.5rem;
  padding-top: var(--stage-lead);
}

.stage__mark {
  position: absolute;
  top: var(--stage-lead);
  right: 0;
  display: grid;
  place-items: center;
  width: 3rem;
  height: 3rem;
  padding: 0.875rem;
  border-radius: 50%;
  background: var(--surface);
  color: var(--ink);
  transition:
    opacity var(--dur-ui) var(--ease),
    background-color var(--dur-card) var(--ease),
    color var(--dur-card) var(--ease),
    transform var(--dur-card) var(--ease);
}
.stage.is-open .stage__mark { opacity: 0; }

.stage__media {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows var(--dur-card) var(--ease);
}
.stage.is-open .stage__media { grid-template-rows: 1fr; }

.stage__media-inner { min-height: 0; overflow: hidden; }
.stage__media picture {
  display: block;
  width: 100%;
  aspect-ratio: 16 / 10;
  overflow: hidden;
  border-radius: var(--r-lg);
  background: var(--surface-sunken);
}
.stage__img { width: 100%; height: 100%; object-fit: cover; }

/* ---- Open and hover states ----------------------------------------------
   No indent shift: in the template every row stays flush to the gutter, so the
   photograph column never moves out of alignment when a row opens. */
.stage.is-open .stage__index,
.stage:hover .stage__index { color: var(--accent); }

.stage.is-open .stage__title,
.stage:hover .stage__title { color: var(--accent); }

.stage:hover .stage__mark {
  background: var(--accent);
  color: var(--canvas);
  transform: translateX(2px);
}

/* ---- Responsive ---------------------------------------------------------- */
@media (max-width: 1180px) {
  .stage { --stage-media: 24rem; }
}

@media (max-width: 900px) {
  .stage { grid-template-columns: minmax(0, 1fr); }
  .stage__aside { min-height: 0; padding-top: 0; }
  .stage__mark { display: none; }
  .stage__media { margin-left: calc(var(--stage-num) + var(--stage-gap)); }
  .stage__media picture { max-width: 26rem; aspect-ratio: 16 / 11; }
  .stage.is-open .stage__media { padding-top: clamp(1.5rem, 3vw, 2rem); }
}

@media (max-width: 600px) {
  .stage { --stage-num: 1.25rem; --stage-gap: 0.875rem; }
  .stage__media picture { max-width: none; }
  .stage__cta .btn { width: 100%; padding-inline: 1.25rem; }
}

/* Without motion the row opens instantly rather than sliding. */
@media (prefers-reduced-motion: reduce) {
  .stage__panel,
  .stage__panel-inner,
  .stage__media { transition: none; }
}

/* ---------- credential.css ---------- */
/**
 * NSAI Agrément block.
 *
 * Left: the certificate in a fixed-ratio frame cropped to its head, which
 * opens full size in the document viewer. Right: the registration set as a
 * hairline record, then the scope, then the holder and the verification line.
 * No boxed fact cards, no panel inside a panel.
 */
.credential__body {
  display: grid;
  grid-template-columns: minmax(0, 0.76fr) minmax(0, 1.24fr);
  gap: clamp(1.75rem, 3.4vw, 3.5rem);
  align-items: start;
}

/* ---- The certificate ---------------------------------------------------- */
.credential__doc { margin: 0; }

.credential__frame {
  position: relative;
  display: block;
  width: 100%;
  aspect-ratio: 4 / 5;
  padding: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  cursor: zoom-in;
  transition: border-color var(--dur-card) var(--ease), box-shadow var(--dur-card) var(--ease);
}
.credential__frame:hover {
  border-color: var(--line-strong);
  box-shadow: var(--shadow-md);
}
.credential__frame:focus-visible { outline: 2px solid var(--accent); outline-offset: 3px; }

.credential__img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: top center;
  transition: transform var(--dur-media) var(--ease);
}
.credential__frame:hover .credential__img { transform: scale(1.02); }

/* The scan runs past the bottom of the frame, so it is faded out rather than
   cut off, and the action sits in the cleared space. */
.credential__frame-fade {
  position: absolute;
  inset: auto 0 0;
  height: 45%;
  background: linear-gradient(to top, var(--surface) 22%, rgba(255, 255, 255, 0) 100%);
  pointer-events: none;
}

.credential__frame-action {
  position: absolute;
  left: 50%;
  bottom: clamp(1.25rem, 2.4vw, 1.75rem);
  transform: translateX(-50%);
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.6875rem 1.25rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: var(--surface);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.02em;
  white-space: nowrap;
  color: var(--ink);
  transition: background-color var(--dur-btn) var(--ease), color var(--dur-btn) var(--ease),
    border-color var(--dur-btn) var(--ease);
}
.credential__frame-icon { display: block; width: 1rem; height: 1rem; }
.credential__frame:hover .credential__frame-action {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--canvas);
}

.credential__caption {
  margin-top: 0.875rem;
  font-size: var(--fs-label);
  color: var(--concrete);
}

/* ---- The registration record -------------------------------------------- */
.credential__record { display: flex; flex-direction: column; }

.credential__rows { display: grid; }

.credential__row {
  display: grid;
  grid-template-columns: minmax(0, 13.5rem) minmax(0, 1fr);
  align-items: baseline;
  gap: 0.75rem 2rem;
  padding-block: clamp(1.25rem, 2vw, 1.75rem);
  border-top: 1px solid var(--line);
  transition: border-color var(--dur-card) var(--ease);
}
.credential__row:first-child { padding-top: 0; border-top: 0; }

.credential__row-label {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--concrete);
}

.credential__row-body { margin: 0; }

.credential__row-value {
  font-family: var(--font-display);
  font-size: clamp(1.5rem, 1.2rem + 0.9vw, 2rem);
  font-weight: 500;
  line-height: 1.15;
  letter-spacing: var(--track-heading);
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.credential__row-value.is-accent { color: var(--accent); }

.credential__row-note {
  margin-top: 0.4375rem;
  max-width: 52ch;
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--concrete);
}

/* ---- Scope -------------------------------------------------------------- */
.credential__scope {
  display: grid;
  grid-template-columns: minmax(0, 13.5rem) minmax(0, 1fr);
  gap: 0.75rem 2rem;
  padding-block: clamp(1.25rem, 2vw, 1.75rem);
  border-top: 1px solid var(--line);
}
.credential__scope-label {
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--concrete);
}
.credential__scope-text {
  max-width: 62ch;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--ink-soft);
  text-wrap: pretty;
}

/* ---- Holder and verification -------------------------------------------- */
.credential__foot {
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  padding-top: clamp(1.25rem, 2vw, 1.75rem);
  border-top: 1px solid var(--line);
}

.credential__holder {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.25rem 0.75rem;
  font-family: var(--font-display);
  font-size: var(--fs-h5);
  font-weight: 600;
  letter-spacing: var(--track-heading);
  color: var(--ink);
}
.credential__address {
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0;
  color: var(--concrete);
}

.credential__verify {
  max-width: 62ch;
  font-size: var(--fs-label);
  line-height: 1.6;
  color: var(--concrete);
}
.credential__link {
  display: inline-flex;
  align-items: center;
  gap: 0.3125rem;
  font-weight: 600;
  color: var(--accent);
  white-space: nowrap;
}
.credential__link span[aria-hidden] { width: 0.9375rem; height: 0.9375rem; transition: transform var(--dur-btn) var(--ease); }
.credential__link:hover span[aria-hidden] { transform: translate(3px, -3px); }

/* ---- Responsive --------------------------------------------------------- */
@media (max-width: 1080px) {
  .credential__body { grid-template-columns: minmax(0, 1fr); gap: clamp(2rem, 5vw, 2.75rem); }
  .credential__doc { max-width: 26rem; }
}

@media (max-width: 620px) {
  .credential__doc { max-width: none; }
  .credential__row,
  .credential__scope { grid-template-columns: minmax(0, 1fr); }
}

/* ---------- projects.css ---------- */
/* ---- Filters ------------------------------------------------------------
   No rule under the row: the spacing separates it from the grid. */
.projects__filters {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-bottom: clamp(1.75rem, 3vw, 2.5rem);
}

.filter {
  min-height: 2.75rem;
  padding: 0 1.125rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  background: transparent;
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--concrete);
  transition:
    background-color var(--dur-btn) var(--ease),
    border-color var(--dur-btn) var(--ease),
    color var(--dur-btn) var(--ease);
}
.filter:hover { border-color: var(--accent); color: var(--accent); }
.filter.is-active {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--canvas);
}

/* ---- Grid --------------------------------------------------------------- */
.projects__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(1.5rem, 2.4vw, 2.25rem) clamp(1.25rem, 2vw, 2rem);
  /* Frames in a row stay the same height even when a title wraps. */
  align-items: stretch;
}

/**
 * Each card sits in its own delicate frame: a white panel with a hairline
 * border and a small inner gutter, so the photograph reads as mounted rather
 * than floating on the section ground.
 */
.project {
  display: flex;
  flex-direction: column;
  padding: 0.625rem;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  transition:
    opacity var(--dur-card) var(--ease),
    transform var(--dur-card) var(--ease),
    border-color var(--dur-card) var(--ease),
    box-shadow var(--dur-card) var(--ease);
}
.project:hover {
  border-color: var(--line-strong);
  box-shadow: 0 5px 20px rgba(23, 26, 24, 0.08);
}
.project.is-filtered-out {
  opacity: 0;
  transform: scale(0.985);
  pointer-events: none;
  position: absolute;
  visibility: hidden;
}

.project__button { display: flex; flex-direction: column; width: 100%; height: 100%; text-align: left; }

.project__media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  /* Concentric with the frame: outer radius minus the inner gutter. */
  border-radius: calc(var(--r-lg) - 0.375rem);
  background: var(--surface-sunken);
}

.project__img {
  transition: transform var(--dur-media) var(--ease), filter var(--dur-media) var(--ease);
}

.project__scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(23, 26, 24, 0) 45%, rgba(23, 26, 24, 0.34) 100%);
  opacity: 0;
  transition: opacity var(--dur-card) var(--ease);
}

.project__expand {
  position: absolute;
  right: 1rem;
  top: 1rem;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0.6875rem;
  border-radius: var(--r-sm);
  background: rgba(246, 245, 241, 0.94);
  color: var(--ink);
  opacity: 0;
  transform: translateY(-6px);
  transition: opacity var(--dur-card) var(--ease), transform var(--dur-card) var(--ease);
}

.project__button:hover .project__img,
.project__button:focus-visible .project__img { transform: scale(1.04); filter: brightness(0.97); }
.project__button:hover .project__scrim,
.project__button:focus-visible .project__scrim { opacity: 1; }
.project__button:hover .project__expand,
.project__button:focus-visible .project__expand { opacity: 1; transform: translateY(0); }

.project__meta {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: baseline;
  gap: 0.75rem;
  margin-top: auto;
  padding: 1.125rem 0.625rem 0.5rem;
}
.project__category {
  grid-column: 1 / -1;
  justify-self: start;
  padding: 0.5rem 0.9375rem;
  border-radius: 999px;
  background: var(--canvas);
  border: 1px solid var(--line);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0;
  text-transform: none;
  color: var(--concrete);
}
.project__title {
  margin-top: 0.875rem;
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: 500;
  letter-spacing: var(--track-heading);
  line-height: var(--lh-heading);
  color: var(--ink);
}
.project__arrow {
  width: 1.125rem;
  height: 1.125rem;
  margin-top: 0.3125rem;
  color: var(--concrete-light);
  transition: transform var(--dur-card) var(--ease), color var(--dur-card) var(--ease);
}
.project__button:hover .project__arrow,
.project__button:focus-visible .project__arrow {
  transform: translate(4px, -4px);
  color: var(--accent);
}

.projects__empty {
  padding: clamp(2.5rem, 5vw, 4rem) 0;
  text-align: center;
  color: var(--concrete);
}

/* ---- Section CTA --------------------------------------------------------- */
.projects__cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem;
  margin-top: clamp(2.5rem, 4vw, 3.75rem);
  padding-top: clamp(2rem, 3vw, 2.75rem);
  border-top: 1px solid var(--line);
}
.projects__cta-text {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 500;
  letter-spacing: -0.018em;
  color: var(--ink);
}

@media (max-width: 1100px) {
  .projects__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 760px) {
  /* Every category stays on screen: a two-column tile row instead of a
     horizontal scroller, so nothing is hidden off the right edge. */
  .projects__filters {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 0.5rem;
  }
  .filter {
    min-height: 2.75rem;
    padding: 0.5rem 0.625rem;
    font-size: 0.8125rem;
    line-height: 1.25;
    text-align: center;
  }

  /* Card stack: each frame sticks under the header and the next one rides up
     over it, so the cards physically overlap as the section scrolls. */
  .projects__grid {
    display: block;
    padding-bottom: 0.5rem;
  }
  .project {
    position: sticky;
    top: calc(var(--header-h-compact) + 0.75rem + var(--i, 0) * 0.5rem);
    margin-bottom: 1rem;
    box-shadow: 0 -6px 24px rgba(23, 26, 24, 0.1);
  }
  .project:last-child { margin-bottom: 0; }

  .projects__cta { flex-direction: column; align-items: stretch; }
  .projects__cta .btn { width: 100%; }
}

/* ---------- quote.css ---------- */
/**
 * Contact block: a full-width header, then the contact grid on the left and the
 * form card on the right, both on the page's one Warm White ground. The header
 * spans the container so the supporting sentence settles on a single line, and
 * the form column is the wider of the two, since it carries the work.
 */
.quote { position: relative; }

/* ---- Header ------------------------------------------------------------- */
.quote__head { margin-bottom: clamp(2.25rem, 3.6vw, 3rem); }

.quote__title {
  font-size: var(--fs-h2);
  font-weight: 500;
  line-height: var(--lh-heading);
  letter-spacing: var(--track-heading);
  color: var(--ink);
}

/* No max-width: the sentence is short enough to hold one line across the
   container, which is the point of lifting it out of the left column. */
.quote__lead {
  margin-top: 0.875rem;
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  color: var(--concrete);
}

/* ---- Grid --------------------------------------------------------------- */
.quote__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.88fr) minmax(0, 1.12fr);
  gap: clamp(2rem, 4vw, 4rem);
  align-items: start;
}

/* ---- Left: contact grid -------------------------------------------------
   Shorter than the form card, so it sticks and travels with the fields as
   they scroll past. Released below 1080px, where the section is one column. */
.quote__intro {
  position: sticky;
  top: calc(var(--header-h-compact) + 2rem);
}

/* 2x2 contact grid, hairline-divided, as in the template. */
.quote__facts {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.quote__fact {
  display: grid;
  align-content: start;
  gap: 0.4375rem;
  padding: clamp(1.125rem, 1.8vw, 1.5rem);
  border-bottom: 1px solid var(--line);
  transition: background-color var(--dur-card) var(--ease);
}
.quote__fact:hover { background: var(--surface); }
.quote__fact:nth-child(odd) { border-right: 1px solid var(--line); }
.quote__fact:nth-last-child(-n + 2) { border-bottom: 0; }

.quote__fact-icon {
  width: 1.375rem;
  height: 1.375rem;
  margin-bottom: 0.75rem;
  color: var(--accent);
}
.quote__fact-label {
  font-family: var(--font-display);
  font-size: var(--fs-h5);
  font-weight: 500;
  color: var(--ink);
}
/* `anywhere`, not `break-word`: only this lets the cell shrink below the width
   of the address, so a narrow column wraps it instead of clipping it. */
.quote__fact-value {
  font-size: var(--fs-label);
  line-height: var(--lh-body);
  color: var(--concrete);
  overflow-wrap: anywhere;
}
a.quote__fact-value:hover { color: var(--accent); text-decoration: underline; text-underline-offset: 3px; }

/* ---- Right: form side --------------------------------------------------- */
.quote__side { display: flex; align-items: flex-start; }

.quote__panel-title {
  margin-bottom: 1.5rem;
  font-size: var(--fs-h3);
  font-weight: 500;
  letter-spacing: var(--track-heading);
  color: var(--ink);
}

@media (max-width: 1080px) {
  .quote__grid { grid-template-columns: minmax(0, 1fr); }
  .quote__intro { position: static; }
}

@media (max-width: 560px) {
  .quote__facts { grid-template-columns: minmax(0, 1fr); }
  .quote__fact:nth-child(odd) { border-right: 0; }
  .quote__fact:nth-last-child(-n + 2) { border-bottom: 1px solid var(--line); }
  .quote__fact:last-child { border-bottom: 0; }
}

.quote__panel {
  width: 100%;
  padding: clamp(1.75rem, 3vw, 2.5rem);
  background: var(--surface);
  border-radius: var(--r-lg);
  border: 1px solid var(--line);
  box-shadow: var(--shadow-md);
}

.form__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1rem, 1.6vw, 1.375rem);
}
.form__grid > .field:nth-child(5),
.form__grid > .field--consent { grid-column: 1 / -1; }

.field { display: flex; flex-direction: column; gap: 0.5rem; }

/* Label, then its marker, both on the left. The required asterisk reads as
   part of the field name; the optional tag follows it at a small gap. */
.field__label {
  display: flex;
  align-items: baseline;
  gap: 0.375rem;
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: 0.02em;
  color: var(--ink-soft);
}
.field__name { flex: none; }
.field__req {
  margin-left: -0.1875rem;
  font-size: 1rem;
  line-height: 1;
  color: var(--accent);
}
.field__optional {
  font-size: 0.6875rem;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--concrete);
}

.field__control {
  width: 100%;
  min-height: 3.25rem;
  padding: 0.875rem 1rem;
  background: var(--surface);
  border: 1px solid var(--line-strong);
  border-radius: var(--r-sm);
  color: var(--ink);
  font-size: var(--fs-body);
  transition: border-color var(--dur-fast) var(--ease), box-shadow var(--dur-fast) var(--ease);
}
textarea.field__control { min-height: 7rem; resize: vertical; line-height: 1.55; }

.field__control::placeholder { color: #8d8b83; }

.field__control:hover { border-color: var(--concrete-light); }
.field__control:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px rgba(47, 93, 70, 0.18);
}

.field__help { font-size: 0.8125rem; color: var(--concrete); }

.field__error {
  display: flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.8125rem;
  font-weight: 500;
  color: var(--danger);
}
.field__error::before {
  content: '';
  width: 0.875rem;
  height: 0.875rem;
  flex: none;
  border-radius: 50%;
  border: 1.5px solid currentColor;
  background:
    linear-gradient(currentColor, currentColor) center 2.5px / 1.5px 4.5px no-repeat,
    linear-gradient(currentColor, currentColor) center 9px / 1.5px 1.5px no-repeat;
}

.field.has-error .field__control { border-color: var(--danger); }
.field.has-error .field__control:focus { box-shadow: 0 0 0 3px rgba(163, 49, 42, 0.15); }

/* ---- Consent -------------------------------------------------------------- */
.consent {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: start;
  gap: 0.75rem;
  cursor: pointer;
}
.consent__input { position: absolute; opacity: 0; width: 1px; height: 1px; }
.consent__box {
  display: grid;
  place-items: center;
  width: 1.375rem;
  height: 1.375rem;
  margin-top: 0.0625rem;
  padding: 0.1875rem;
  border: 1px solid var(--line-strong);
  border-radius: var(--r-xs);
  background: var(--surface);
  color: transparent;
  transition: background-color var(--dur-fast) var(--ease), border-color var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.consent__text { font-size: 0.875rem; line-height: 1.5; color: var(--concrete); }
.consent:hover .consent__box { border-color: var(--concrete-light); }
.consent__input:checked + .consent__box {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--dark-ink);
}
.consent__input:focus-visible + .consent__box {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
}
.field--consent.has-error .consent__box { border-color: var(--danger); }

/* ---- Submit + status ------------------------------------------------------- */
.form__submit { margin-top: clamp(1.25rem, 2vw, 1.75rem); }

.form__status:empty { display: none; }

.form__success {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 0.875rem;
  margin-top: 1.25rem;
  padding: 1.125rem 1.25rem;
  background: var(--accent-soft);
  border: 1px solid rgba(47, 93, 70, 0.24);
  border-radius: var(--r-sm);
}
.form__success-icon {
  display: grid;
  place-items: center;
  width: 1.5rem;
  height: 1.5rem;
  padding: 0.25rem;
  border-radius: 50%;
  background: var(--accent);
  color: var(--dark-ink);
}
.form__success-title { font-weight: 600; color: var(--ink); }
.form__success-text { margin-top: 0.25rem; font-size: var(--fs-small); color: var(--concrete); }
.form__success-dev {
  margin-top: 0.625rem;
  padding-top: 0.625rem;
  border-top: 1px dashed rgba(47, 93, 70, 0.32);
  font-size: 0.8125rem;
  color: var(--concrete);
}
.form__success-dev code {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.75rem;
  color: var(--ink-soft);
}

.form__failure {
  margin-top: 1.25rem;
  padding: 1rem 1.125rem;
  background: rgba(163, 49, 42, 0.07);
  border: 1px solid rgba(163, 49, 42, 0.25);
  border-radius: var(--r-sm);
  font-size: var(--fs-small);
  color: var(--danger);
}
.form__failure a { text-decoration: underline; font-weight: 600; }

@media (max-width: 1080px) {
  .quote__grid { gap: clamp(2.25rem, 5vw, 3rem); }
}

@media (max-width: 600px) {
  .form__grid { grid-template-columns: 1fr; }
  .quote__panel { padding: 1.25rem; }
}

/* ---------- benefits.css ---------- */
/**
 * "Why choose" block, matched to the reference template's layout: a framed
 * photograph on the left and a hairline-divided grid of tiles on the right.
 * The template runs this on its accent band; here it sits on the same Warm
 * White ground as the rest of the page, so the tiles lift to Pure White on
 * hover instead of lightening a colour field.
 */
.benefits__body {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: clamp(1.5rem, 2.6vw, 2.5rem);
  align-items: stretch;
}

.benefits__media {
  margin: 0;
  overflow: hidden;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface-sunken);
  min-height: 100%;
}
.benefits__img {
  width: 100%;
  height: 100%;
  min-height: clamp(20rem, 34vw, 30rem);
  object-fit: cover;
}

/* ---- Tile grid --------------------------------------------------------- */
.benefits__cards {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  overflow: hidden;
}

.benefit {
  position: relative;
  display: grid;
  grid-template-rows: auto auto auto 1fr;
  align-content: start;
  padding: clamp(1.25rem, 1.9vw, 1.875rem);
  border-bottom: 1px solid var(--line);
  transition: background-color var(--dur-card) var(--ease);
}
.benefit:nth-child(odd) { border-right: 1px solid var(--line); }
.benefit:nth-last-child(-n + 2) { border-bottom: 0; }

.benefit__icon {
  display: block;
  width: 1.75rem;
  height: 1.75rem;
  margin-bottom: clamp(1.25rem, 2.2vw, 2rem);
  color: var(--ink);
  transition: color var(--dur-card) var(--ease);
}

.benefit__title {
  font-size: var(--fs-h5);
  font-weight: 500;
  letter-spacing: var(--track-heading);
  color: var(--ink);
}

.benefit__text {
  margin-top: 0.5rem;
  max-width: 28ch;
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--concrete);
}

.benefit__mark {
  display: block;
  width: 1.375rem;
  height: 1.375rem;
  margin-top: clamp(1.25rem, 2.2vw, 2rem);
  margin-left: auto;
  align-self: end;
  color: var(--concrete-light);
  transition: transform var(--dur-card) var(--ease), color var(--dur-card) var(--ease);
}

/* Template hover: the tile lifts out of the field and its marks take the
   accent. */
.benefit:hover { background: var(--surface); }
.benefit:hover .benefit__icon { color: var(--accent); }
.benefit:hover .benefit__mark { color: var(--accent); transform: translate(3px, -3px); }

@media (max-width: 1080px) {
  .benefits__body { grid-template-columns: minmax(0, 1fr); }
  .benefits__img { min-height: 0; aspect-ratio: 16 / 9; }
}

@media (max-width: 620px) {
  .benefits__cards { grid-template-columns: minmax(0, 1fr); }
  .benefit:nth-child(odd) { border-right: 0; }
  .benefit:nth-last-child(-n + 2) { border-bottom: 1px solid var(--line); }
  .benefit:last-child { border-bottom: 0; }
  .benefit__icon { margin-bottom: 1rem; }
  .benefit__text { max-width: none; }
  .benefit__mark { margin-top: 1rem; }
}

/* ---------- reviews.css ---------- */
/**
 * Reviews, matched to the reference template's testimonial block: a narrow
 * accent rating card that sticks while a 2x2 grid of quote cards scrolls past
 * it. Palette is ours - Deep Green rating card, Pure White quote cards,
 * Graphite quote marks.
 */
.reviews__body {
  display: grid;
  grid-template-columns: minmax(0, 21.25rem) minmax(0, 1fr);
  gap: clamp(1.25rem, 2vw, 1.875rem);
  align-items: start;
}

/* ---- Accent rating card ------------------------------------------------- */
.review-summary {
  display: flex;
  flex-direction: column;
  padding: clamp(1.75rem, 2.6vw, 2.25rem);
  border-radius: var(--r-lg);
  background: var(--brand);
  color: var(--brand-ink);
  position: sticky;
  top: calc(var(--header-h-compact) + 2rem);
}

.review-summary__label {
  font-size: var(--fs-h5);
  font-weight: 500;
  letter-spacing: var(--track-heading);
  color: var(--brand-ink);
}

.review-summary__score {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  margin-top: clamp(2.5rem, 4.5vw, 3.5rem);
}

.review-summary__figure {
  display: flex;
  align-items: baseline;
  gap: 0.125rem;
  font-family: var(--font-display);
  font-size: var(--fs-stat);
  font-weight: 500;
  line-height: 1;
  letter-spacing: var(--track-display);
  color: var(--brand-ink);
  font-variant-numeric: tabular-nums;
}
.review-summary__scale {
  font-size: var(--fs-h4);
  font-weight: 500;
  letter-spacing: var(--track-heading);
  color: var(--brand-ink-soft);
}

.review-summary__stars { display: flex; gap: 0.3125rem; }
.review-summary__star { display: block; width: 1.25rem; height: 1.25rem; color: var(--brand-ink); }
.review-summary__star.is-empty { color: rgba(246, 245, 241, 0.34); }

.review-summary__note,
.review-summary__text {
  margin-top: 1.25rem;
  font-size: var(--fs-small);
  line-height: var(--lh-body);
  color: var(--brand-ink-soft);
}
.review-summary__text {
  font-family: var(--font-display);
  font-size: var(--fs-h5);
  color: var(--brand-ink);
}

.review-summary__count {
  margin-top: clamp(1.25rem, 2vw, 1.75rem);
  padding-top: clamp(1.25rem, 2vw, 1.75rem);
  border-top: 1px solid var(--brand-card-line);
  font-size: var(--fs-label);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--brand-ink-soft);
}
.review-summary__count span {
  font-weight: 600;
  color: var(--brand-ink);
  font-variant-numeric: tabular-nums;
}

/* ---- Quote cards -------------------------------------------------------- */
.reviews__cards { min-width: 0; }

/* Pagination dots: the mobile scroller's position indicator. Hidden while the
   cards sit in a grid, because there is nothing to page through. */
.reviews__dots { display: none; }

.reviews__grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(1.25rem, 2vw, 1.875rem);
  align-items: stretch;
}

.review-card {
  display: flex;
  flex-direction: column;
  padding: clamp(1.5rem, 2.4vw, 2rem);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
  transition: box-shadow var(--dur-card) var(--ease), border-color var(--dur-card) var(--ease);
}
.review-card:hover {
  border-color: var(--line-strong);
  box-shadow: 0 5px 20px rgba(23, 26, 24, 0.08);
}

.review-card__head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
}
.review-card__mark { display: block; width: 1.875rem; height: auto; flex: none; color: var(--ink); }

/* The footer is pushed to the foot of the card so the rows align across the
   grid; the quote keeps its own bottom margin so the hairline never runs into
   the text when a card is full. */
/* blockquote carries a 40px inline margin from the UA stylesheet, which
   indented every quote away from its own quote mark and cost the card a
   quarter of its measure. */
.review-card__quote {
  margin-inline: 0;
  margin-top: 1.125rem;
  margin-bottom: clamp(1.25rem, 2vw, 1.75rem);
}
.review-card__quote p {
  font-size: var(--fs-lead);
  line-height: 1.5;
  color: var(--ink);
  text-wrap: pretty;
}

/* Footer row: monogram disc and identity. No stock avatar artwork. */
.review-card__author {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: 0.875rem;
  margin-top: auto;
  padding-top: clamp(1.25rem, 2vw, 1.75rem);
  border-top: 1px solid var(--line);
}

.review-card__avatar {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  border-radius: 50%;
  background: var(--accent-soft);
  color: var(--accent);
  font-family: var(--font-display);
  font-size: var(--fs-label);
  font-weight: 600;
  letter-spacing: 0.02em;
}

.review-card__identity { display: flex; flex-direction: column; gap: 0.1875rem; min-width: 0; }
.review-card__name {
  font-family: var(--font-display);
  font-size: var(--fs-small);
  font-weight: 600;
  letter-spacing: var(--track-heading);
  color: var(--ink);
}
.review-card__meta {
  font-size: var(--fs-label);
  color: var(--concrete);
  overflow-wrap: break-word;
}
.review-card__meta span[aria-hidden] { color: var(--line-strong); }

.review-card__stars { display: flex; flex: none; gap: 0.1875rem; }
.review-card__star { display: block; width: 1rem; height: 1rem; color: var(--accent); }
.review-card__star.is-empty { color: var(--line-strong); }

/* ---- Content-ready panel ------------------------------------------------
   Fills the whole card area, so the composition stays intact until real
   testimonials exist. */
.reviews__grid--ready { grid-template-columns: minmax(0, 1fr); }

.review-ready {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  padding: clamp(1.75rem, 3vw, 2.5rem);
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--surface);
}
.review-ready__mark { display: block; width: 2.125rem; height: auto; color: var(--line-strong); }
.review-ready__title {
  font-size: var(--fs-h4);
  font-weight: 500;
  letter-spacing: var(--track-heading);
  color: var(--ink);
}
.review-ready__text { max-width: 62ch; font-size: var(--fs-small); line-height: var(--lh-body); color: var(--concrete); }

.review-ready__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 0.5rem;
  padding-top: clamp(1.25rem, 2vw, 1.75rem);
  border-top: 1px solid var(--line);
}
.review-ready__note { font-size: var(--fs-small); color: var(--concrete); }
.review-ready__link {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: var(--fs-small);
  font-weight: 600;
  color: var(--accent);
}
.review-ready__link span[aria-hidden] { width: 1.0625rem; height: 1.0625rem; transition: transform var(--dur-btn) var(--ease); }
.review-ready__link:hover span[aria-hidden] { transform: translateX(4px); }

/* ---- Responsive ---------------------------------------------------------- */
/* Below this the rating card can no longer hold a column without squeezing the
   quotes into a ragged four-word measure, so it becomes a full-width banner
   above the grid and lays its parts out in a row. */
@media (max-width: 1180px) {
  .reviews__body { grid-template-columns: minmax(0, 1fr); }

  .review-summary {
    position: static;
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    gap: 1rem 2.5rem;
  }
  .review-summary__label { flex: 1 1 100%; }
  .review-summary__score {
    flex-direction: row;
    align-items: center;
    gap: 1rem;
    margin-top: 0;
  }
  .review-summary__note { flex: 1 1 20rem; margin-top: 0; }
  .review-summary__count {
    margin-top: 0;
    padding-top: 0;
    border-top: 0;
  }
}

/* Mobile: a compact rating card, then the quotes as a swipeable row. */
@media (max-width: 760px) {
  .review-summary {
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    padding: 1.5rem;
  }
  .review-summary__label { flex: none; font-size: var(--fs-h5); }
  .review-summary__score {
    flex-direction: column;
    align-items: flex-start;
    gap: 0.75rem;
    margin-top: 1.375rem;
  }
  .review-summary__figure { font-size: 3.25rem; }
  .review-summary__note {
    flex: none;
    margin-top: 1rem;
    font-size: var(--fs-label);
    line-height: 1.5;
  }
  .review-summary__count {
    margin-top: 1rem;
    font-size: var(--fs-label-sm);
  }

  /* The row bleeds into both gutters so a card can sit flush at the edge while
     the next one peeks in, which is what signals that the row scrolls. */
  .reviews__grid {
    display: flex;
    /* Content height, not stretch: one card fills the screen at a time, so
       matching every card to the longest quote only opens a hole between the
       quote and the footer of the short ones. */
    align-items: flex-start;
    gap: 0.875rem;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory;
    scroll-padding-inline: var(--gutter);
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .reviews__grid::-webkit-scrollbar { display: none; }
  .review-card {
    flex: 0 0 min(88%, 22rem);
    scroll-snap-align: start;
    /* One card per swipe: a flick cannot skip past the card it lands on, so
       the dots always describe where the row actually stopped. */
    scroll-snap-stop: always;
  }
  /* The last card cannot reach the start edge - the row runs out of scroll
     before it gets there - so under `mandatory` snapping its start position is
     unreachable and the row can spring back off the end. Snapping the last
     card to the end instead makes every position reachable. */
  .review-card:last-child { scroll-snap-align: end; }
  /* A narrower measure needs a smaller quote, or the longest card sets a
     height the short ones have to fill with empty space. */
  .review-card__quote {
    margin-top: 1rem;
    margin-bottom: 1.125rem;
  }
  .review-card__quote p { font-size: var(--fs-small); line-height: 1.55; }
  .review-card__author { padding-top: 1.125rem; }

  /* The ready state is a single panel, so it keeps the static layout. */
  .reviews__grid--ready {
    display: grid;
    margin-inline: 0;
    padding-inline: 0;
    overflow: visible;
  }

  .reviews__dots {
    display: flex;
    justify-content: center;
    align-items: center;
    margin-top: 0.75rem;
  }
  /* The dot itself is 8px; the button around it carries the tap target. */
  .reviews__dot {
    display: grid;
    place-items: center;
    width: 1.5rem;
    height: 2.25rem;
    padding: 0;
    border: 0;
    background: transparent;
  }
  .reviews__dot::before {
    content: '';
    display: block;
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 999px;
    background: var(--line-strong);
    transition:
      width var(--dur-btn) var(--ease),
      background-color var(--dur-btn) var(--ease);
  }
  .reviews__dot.is-active::before {
    width: 1.25rem;
    background: var(--accent);
  }
}

/* ---------- faq.css ---------- */
/**
 * The heading column travels with the questions, as in the reference template
 * (`position: sticky`). For that to work the column has to be as tall as the
 * list beside it, so this grid must NOT start-align its items.
 */
.faq__grid {
  display: grid;
  grid-template-columns: minmax(0, 0.72fr) minmax(0, 1.28fr);
  gap: clamp(2rem, 4vw, 5.5rem);
  align-items: stretch;
}

.faq__aside { height: 100%; }
.faq__aside-sticky { position: sticky; top: calc(var(--header-h) + 2.5rem); }
.faq__cta { margin-top: clamp(1.75rem, 3vw, 2.25rem); }

/* No rule above the first question: the first hairline sits under it. */
.faq__list { border-top: 0; }
.faq__item { border-bottom: 1px solid var(--line); }
.faq__heading { margin: 0; font-size: inherit; font-weight: inherit; letter-spacing: normal; }

.faq__trigger {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: 1.5rem;
  width: 100%;
  padding: clamp(1.25rem, 2.2vw, 1.875rem) 0;
  text-align: left;
  transition: color var(--dur-ui) var(--ease);
}

.faq__question {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  font-weight: 500;
  letter-spacing: -0.018em;
  line-height: 1.25;
  color: var(--ink);
  transition: color var(--dur-ui) var(--ease);
}
.faq__trigger:hover .faq__question { color: var(--accent); }

.faq__icon {
  display: grid;
  place-items: center;
  width: 2.375rem;
  height: 2.375rem;
  flex: none;
  padding: 0.5625rem;
  border: 1px solid var(--line-strong);
  border-radius: 50%;
  color: var(--ink);
  transition:
    transform var(--dur-ui) var(--ease),
    border-color var(--dur-ui) var(--ease),
    background-color var(--dur-ui) var(--ease),
    color var(--dur-ui) var(--ease);
}
.faq__trigger:hover .faq__icon { border-color: var(--accent); color: var(--accent); }

.faq__trigger[aria-expanded='true'] .faq__icon {
  transform: rotate(135deg);
  background: var(--accent);
  border-color: var(--accent);
  color: var(--canvas);
}
.faq__trigger[aria-expanded='true'] .faq__question { color: var(--accent); }

.faq__panel { overflow: hidden; height: 0; }
.faq__panel.is-animating { transition: height var(--dur-ui) var(--ease); }

.faq__answer { padding: 0 clamp(0, 4vw, 4rem) clamp(1.375rem, 2.2vw, 1.875rem) 0; }
.faq__answer p { max-width: 62ch; color: var(--concrete); }

@media (max-width: 900px) {
  .faq__grid { grid-template-columns: 1fr; gap: 2rem; align-items: start; }
  .faq__aside { height: auto; }
  .faq__aside-sticky { position: static; }
  .faq__cta .btn { width: 100%; }
  .faq__trigger { gap: 1rem; }
  .faq__answer { padding-right: 0; }
}

/* ---------- footer.css ---------- */
.footer { background: var(--dark); color: var(--dark-ink); }

/* ---- Closing CTA band ------------------------------------------------------ */
.footer__cta { border-bottom: 1px solid var(--line-dark); }
.footer__cta-inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(1.75rem, 4vw, 4rem);
  padding-block: clamp(3.5rem, 6vw, 6.5rem);
}
.footer__cta-title {
  font-size: clamp(1.875rem, 1.15rem + 2.6vw, 3.5rem);
  font-weight: 600;
  letter-spacing: var(--track-display);
  line-height: 1.06;
  max-width: 18ch;
  color: var(--dark-ink);
}
.footer__cta-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem; }
.footer__cta-phone {
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  font-size: var(--fs-small);
  font-weight: 500;
  color: var(--dark-concrete);
  white-space: nowrap;
}
.footer__cta-phone span[aria-hidden] { width: 1.0625rem; height: 1.0625rem; color: var(--accent-onDark); flex: none; }
.footer__cta-phone:hover { color: var(--dark-ink); }

/* ---- Main grid -------------------------------------------------------------- */
.footer__main {
  display: grid;
  grid-template-columns: minmax(0, 0.9fr) minmax(0, 1.6fr);
  gap: clamp(2.5rem, 5vw, 5rem);
  padding-block: clamp(3rem, 5vw, 5rem);
}

.footer__logo,
.footer__logo img {
  display: block;
  height: clamp(4.5rem, 3.6rem + 2.4vw, 6rem);
  width: auto;
}
.footer__description {
  margin-top: 1.5rem;
  font-size: var(--fs-small);
  line-height: 1.7;
  color: var(--dark-concrete);
}

.footer__cols {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(9rem, 1fr));
  gap: clamp(1.75rem, 3vw, 3rem);
}
.footer__col-title {
  margin-bottom: 1.125rem;
  font-family: var(--font-body);
  font-size: var(--fs-label);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--dark-concrete);
}
.footer__links { display: flex; flex-direction: column; gap: 0.75rem; }
.footer__links a {
  font-size: var(--fs-small);
  color: var(--dark-ink);
  overflow-wrap: anywhere;
}
.footer__links a:hover { color: var(--accent-onDark); }
.footer__links--plain li { font-size: var(--fs-small); color: var(--dark-concrete); }

/* ---- Bottom bar --------------------------------------------------------------- */
.footer__bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: 1rem;
  padding-block: 1.75rem;
  /* Clears the floating WhatsApp button at the very bottom of the page. */
  padding-bottom: 5.75rem;
  border-top: 1px solid var(--line-dark);
}
.footer__copy { font-size: 0.8125rem; color: var(--dark-concrete); }
/* No reserved room for the sticky quote widget: the row ends flush with the
   90px gutter, and src/scripts/conversion.js hides the widget while this bar
   is on screen instead. */
.footer__legal { display: flex; flex-wrap: wrap; gap: 1.5rem; }
.footer__legal a { font-size: 0.8125rem; color: var(--dark-concrete); }
.footer__legal a:hover { color: var(--dark-ink); }
.footer__legal-pending {
  font-size: 0.8125rem;
  color: var(--dark-concrete);
  cursor: default;
}

@media (max-width: 900px) {
  .footer__cta-inner { grid-template-columns: 1fr; }
  .footer__cta-title { max-width: none; }
  .footer__main { grid-template-columns: 1fr; }
}

/* Mobile: the footer runs down the middle of the screen. With the columns
   stacked there is no left edge left to align to, so a centred axis reads as
   composed rather than ragged. */
@media (max-width: 600px) {
  .footer__cta-inner { justify-items: center; text-align: center; }
  .footer__cta-actions {
    flex-direction: column;
    align-items: stretch;
    width: 100%;
  }
  .footer__cta-actions .btn { width: 100%; }
  .footer__cta-phone { justify-content: center; }

  .footer__main { justify-items: center; text-align: center; }
  .footer__brand { display: flex; flex-direction: column; align-items: center; }
  .footer__cols {
    grid-template-columns: minmax(0, 1fr);
    justify-items: center;
    width: 100%;
  }
  .footer__col { width: 100%; }
  .footer__col-title { margin-bottom: 0.875rem; }
  .footer__links { align-items: center; gap: 0.625rem; }

  .footer__bar {
    flex-direction: column;
    align-items: center;
    text-align: center;
  }
  .footer__legal { justify-content: center; }
}

/* ---------- overlays.css ---------- */
/* ============ Quote modal ============ */
.modal {
  width: min(34rem, 100%);
  max-width: 100%;
  max-height: 100dvh;
  padding: 0;
  margin: auto;
  border: 0;
  background: transparent;
  color: var(--ink);
  overflow: visible;
}
.modal::backdrop {
  background: rgba(18, 20, 18, 0.58);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
  opacity: 0;
  transition: opacity var(--dur-ui) var(--ease);
}
.modal[open]::backdrop { opacity: 1; }

.modal__panel {
  position: relative;
  padding: clamp(1.5rem, 3vw, 2.5rem);
  background: var(--canvas);
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transform: translateY(14px) scale(0.985);
  transition: opacity var(--dur-ui) var(--ease), transform 420ms var(--ease);
}
.modal[open] .modal__panel { opacity: 1; transform: none; }

.modal__close {
  position: absolute;
  top: 0.875rem;
  right: 0.875rem;
  display: grid;
  place-items: center;
  width: 2.5rem;
  height: 2.5rem;
  padding: 0.6875rem;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--ink);
  background: var(--surface);
  transition: border-color var(--dur-fast) var(--ease), background-color var(--dur-fast) var(--ease);
}
.modal__close:hover { border-color: var(--ink); }

.modal__head { margin-bottom: clamp(1.25rem, 2vw, 1.75rem); padding-right: 3rem; }
.modal__title {
  font-size: clamp(1.5rem, 1.2rem + 1.1vw, 1.875rem);
  font-weight: 500;
  letter-spacing: -0.022em;
}
.modal__lead { margin-top: 0.75rem; font-size: var(--fs-small); color: var(--concrete); max-width: 42ch; }

.form--compact { display: flex; flex-direction: column; gap: 1.125rem; }
.form--compact .form__submit { margin-top: 0.375rem; }

.modal__alt {
  margin-top: 1.25rem;
  padding-top: 1.125rem;
  border-top: 1px solid var(--line);
  font-size: var(--fs-small);
  color: var(--concrete);
  text-align: center;
}
.modal__alt a { font-weight: 600; color: var(--accent); }
.modal__alt a:hover { text-decoration: underline; }

/* Bottom sheet on small screens */
@media (max-width: 600px) {
  .modal {
    width: 100%;
    margin: auto auto 0;
    max-height: 92dvh;
  }
  .modal__panel {
    border-radius: var(--r-lg) var(--r-lg) 0 0;
    padding-bottom: calc(1.5rem + env(safe-area-inset-bottom));
    max-height: 92dvh;
    overflow-y: auto;
    transform: translateY(100%);
  }
  .modal[open] .modal__panel { transform: none; }
}

/* ============ Mobile sticky CTA ============ */
.mobile-cta {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: var(--z-widget);
  display: none;
  gap: 0.625rem;
  padding: 0.625rem 0.875rem calc(0.625rem + env(safe-area-inset-bottom));
  background: rgba(246, 245, 241, 0.94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
  transform: translateY(110%);
  transition: transform var(--dur-ui) var(--ease);
}
.mobile-cta[hidden] { display: none; }
.mobile-cta.is-visible { transform: none; }

.mobile-cta__call,
.mobile-cta__quote {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  min-height: 3.125rem;
  border-radius: var(--r-sm);
  font-size: var(--fs-small);
  font-weight: 600;
}
.mobile-cta__call {
  flex: 0 0 6.5rem;
  border: 1px solid var(--line-strong);
  background: var(--surface);
  color: var(--ink);
}
.mobile-cta__call span[aria-hidden] { width: 1.0625rem; height: 1.0625rem; color: var(--accent); }
.mobile-cta__quote { flex: 1; background: var(--accent); color: var(--canvas); }
.mobile-cta__quote:active { transform: translateY(1px); }
.mobile-cta__arrow { width: 1.0625rem; height: 1.0625rem; }

@media (max-width: 760px) {
  .mobile-cta { display: flex; }
  body { padding-bottom: 0; }
}

/* ============ Desktop quote widget ============ */
.quote-widget {
  position: fixed;
  right: clamp(1rem, 2vw, 2rem);
  bottom: clamp(1rem, 2vw, 2rem);
  z-index: var(--z-widget);
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 3rem;
  padding: 0 1.125rem;
  background: var(--ink);
  color: var(--canvas);
  border: 1px solid var(--ink);
  border-radius: var(--r-sm);
  font-size: var(--fs-small);
  font-weight: 500;
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: translateY(12px);
  transition:
    opacity var(--dur-ui) var(--ease),
    transform var(--dur-ui) var(--ease),
    background-color var(--dur-btn) var(--ease);
}
.quote-widget[hidden] { display: none; }
.quote-widget.is-visible { opacity: 1; transform: none; }
.quote-widget:hover { background: #0e100f; }

.quote-widget__dot {
  width: 0.4375rem;
  height: 0.4375rem;
  border-radius: 50%;
  background: var(--accent-onDark);
  flex: none;
}
.quote-widget__icon { width: 1rem; height: 1rem; transition: transform var(--dur-btn) var(--ease); }
.quote-widget:hover .quote-widget__icon { transform: translate(3px, -3px); }

@media (max-width: 760px) { .quote-widget { display: none !important; } }

/* ============ WhatsApp chat button ============
   Always on screen, bottom-right. WhatsApp green is deepened from #25D366 to
   #1E9E4F so the white label (19px bold, large text) holds 3.4:1. */
.wa-widget {
  --wa-edge: clamp(1rem, 2vw, 2rem);
  position: fixed;
  right: var(--wa-edge);
  bottom: calc(var(--wa-edge) + env(safe-area-inset-bottom));
  z-index: var(--z-widget);
  display: inline-flex;
  align-items: center;
  gap: 0.625rem;
  min-height: 3.5rem;
  padding: 0 1.5rem 0 1.125rem;
  border-radius: 999px;
  background: #1e9e4f;
  color: #ffffff;
  font-size: 1.1875rem;
  font-weight: 700;
  line-height: 1;
  white-space: nowrap;
  box-shadow: 0 10px 28px -10px rgba(23, 26, 24, 0.45);
  transition:
    transform var(--dur-ui) var(--ease),
    background-color var(--dur-btn) var(--ease);
}
.wa-widget:hover { background: #178a43; transform: translateY(-2px); }
.wa-widget:active { transform: translateY(1px); }
.wa-widget:focus-visible { outline: 2px solid var(--ink); outline-offset: 3px; }
.wa-widget__icon { display: block; width: 1.75rem; height: 1.75rem; flex: none; }
.wa-widget__icon svg { display: block; width: 100%; height: 100%; }

/* Desktop: the quote control stacks above the WhatsApp button. */
.quote-widget { bottom: calc(clamp(1rem, 2vw, 2rem) + 4.25rem); }

@media (max-width: 760px) {
  .wa-widget {
    min-height: 3.25rem;
    padding: 0 1.25rem 0 1rem;
    gap: 0.5rem;
  }
  .wa-widget__icon { width: 1.625rem; height: 1.625rem; }
  /* Rides above the sticky call/quote bar while that bar is showing. */
  .mobile-cta.is-visible ~ .wa-widget { transform: translateY(-4.5rem); }
  .mobile-cta.is-visible ~ .wa-widget:active { transform: translateY(calc(-4.5rem + 1px)); }
}

@media (prefers-reduced-motion: reduce) {
  .wa-widget { transition: background-color var(--dur-btn) var(--ease); }
  .wa-widget:hover { transform: none; }
}

/* ============ Floating intro video ============
   Bottom-left portrait frame that follows the page from the second screen on. Its width is a step
   change between the compact and enlarged states (never animated); the
   enlarge moment is carried by a short transform-only pop. */
.intro-video {
  --iv-edge: clamp(1rem, 2vw, 2rem);
  --iv-w: 9.5rem;
  --iv-lift: 0px;
  position: fixed;
  left: var(--iv-edge);
  bottom: calc(var(--iv-edge) + env(safe-area-inset-bottom));
  z-index: var(--z-widget);
  width: var(--iv-w);
  transform: translateY(var(--iv-lift));
  transform-origin: bottom left;
  transition:
    transform 520ms var(--ease),
    opacity 520ms var(--ease),
    visibility 0s linear 0s;
}
.intro-video[hidden] { display: none; }
.intro-video.is-away {
  opacity: 0;
  visibility: hidden;
  transform: translateY(calc(var(--iv-lift) + 1.5rem));
  transition:
    transform var(--dur-ui) var(--ease),
    opacity var(--dur-ui) var(--ease),
    visibility 0s linear var(--dur-ui);
}
.intro-video.is-expanded {
  --iv-w: min(18rem, calc((100dvh - 9rem) * 9 / 16));
}
.intro-video.is-expanded .intro-video__frame { animation: intro-video-pop 420ms var(--ease); }

@keyframes intro-video-pop {
  from { transform: scale(0.9); }
}

.intro-video__frame {
  position: relative;
  aspect-ratio: 9 / 16;
  overflow: hidden;
  border: 3px solid var(--surface);
  border-radius: var(--r-lg);
  background: var(--dark);
  box-shadow: 0 18px 40px -16px rgba(23, 26, 24, 0.55);
  transition: transform var(--dur-ui) var(--ease);
}
.intro-video:not(.is-expanded):hover .intro-video__frame { transform: translateY(-3px); }

.intro-video__media {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.intro-video__open {
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(to top, rgba(23, 26, 24, 0.42) 0%, rgba(23, 26, 24, 0) 38%);
  cursor: pointer;
}
.intro-video__open:focus-visible { outline: 2px solid var(--accent-onDark); outline-offset: -5px; }

.intro-video__sound,
.intro-video__close {
  position: absolute;
  display: grid;
  place-items: center;
  width: 1.875rem;
  height: 1.875rem;
  border-radius: 50%;
  background: rgba(23, 26, 24, 0.62);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  color: var(--dark-ink);
}
.intro-video__sound { left: 0.5rem; bottom: 0.5rem; padding: 0.4375rem; }
.intro-video__sound svg,
.intro-video__close svg { display: block; width: 100%; height: 100%; }
.intro-video__sound-on { display: none; }
.intro-video.is-expanded .intro-video__sound-off { display: none; }
.intro-video.is-expanded .intro-video__sound-on { display: block; }

.intro-video__close {
  top: 0.4375rem;
  right: 0.4375rem;
  z-index: 2;
  padding: 0.4375rem;
  transition: background-color var(--dur-fast) var(--ease);
}
.intro-video__close:hover { background: rgba(23, 26, 24, 0.86); }
.intro-video__close:focus-visible { outline: 2px solid var(--accent-onDark); outline-offset: 2px; }

@media (max-width: 760px) {
  .intro-video { --iv-w: 5.75rem; }
  .intro-video.is-expanded { --iv-w: min(15rem, calc((100dvh - 9rem) * 9 / 16)); }
  .intro-video__frame { border-width: 2px; border-radius: var(--r-md); }
  .intro-video__sound,
  .intro-video__close { width: 1.5rem; height: 1.5rem; padding: 0.3125rem; }
  .intro-video__sound { left: 0.375rem; bottom: 0.375rem; }
  .intro-video__close { top: 0.3125rem; right: 0.3125rem; }
  /* Rides above the sticky call/quote bar, like the WhatsApp button. */
  .mobile-cta.is-visible ~ .intro-video { --iv-lift: -4.5rem; }
}

@media (prefers-reduced-motion: reduce) {
  .intro-video.is-expanded .intro-video__frame { animation: none; }
  .intro-video__frame { transition: none; }
  .intro-video:not(.is-expanded):hover .intro-video__frame { transform: none; }
}

/* ============ Lightbox ============ */
.lightbox {
  width: 100%;
  max-width: 100%;
  height: 100%;
  max-height: 100%;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: hidden;
}
.lightbox::backdrop {
  background: rgba(13, 15, 13, 0.94);
  opacity: 0;
  transition: opacity var(--dur-ui) var(--ease);
}
.lightbox[open]::backdrop { opacity: 1; }

.lightbox__inner {
  display: flex;
  flex-direction: column;
  height: 100%;
  padding: clamp(0.75rem, 2vw, 1.5rem);
  opacity: 0;
  transform: scale(0.99);
  transition: opacity var(--dur-ui) var(--ease), transform 420ms var(--ease);
}
.lightbox[open] .lightbox__inner { opacity: 1; transform: none; }

.lightbox__bar {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding-bottom: clamp(0.75rem, 1.5vw, 1.25rem);
  color: var(--dark-ink);
}
.lightbox__meta { display: flex; flex-direction: column; gap: 0.1875rem; margin-right: auto; }
.lightbox__category {
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-onDark);
}
.lightbox__title {
  font-family: var(--font-display);
  font-size: var(--fs-h4);
  font-weight: 500;
  letter-spacing: -0.014em;
}
.lightbox__count { font-size: var(--fs-small); color: var(--dark-concrete); font-variant-numeric: tabular-nums; }

.lightbox__close,
.lightbox__nav {
  display: grid;
  place-items: center;
  width: 2.75rem;
  height: 2.75rem;
  flex: none;
  padding: 0.6875rem;
  border: 1px solid var(--line-dark-strong);
  border-radius: var(--r-sm);
  color: var(--dark-ink);
  background: rgba(255, 255, 255, 0.04);
  transition: background-color var(--dur-btn) var(--ease), border-color var(--dur-btn) var(--ease);
}
.lightbox__close:hover,
.lightbox__nav:hover { background: rgba(255, 255, 255, 0.12); border-color: var(--dark-ink); }

.lightbox__figure {
  position: relative;
  display: flex;
  align-items: center;
  gap: clamp(0.5rem, 1.5vw, 1.25rem);
  flex: 1;
  min-height: 0;
  margin: 0;
}
.lightbox__picture {
  flex: 1;
  min-width: 0;
  height: 100%;
  display: grid;
  place-items: center;
}
.lightbox__img {
  max-width: 100%;
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: var(--r-sm);
}

@media (max-width: 600px) {
  .lightbox__nav {
    position: absolute;
    bottom: 0;
    z-index: 2;
  }
  .lightbox__nav--prev { left: 0; }
  .lightbox__nav--next { right: 0; }
  .lightbox__title { font-size: 0.9375rem; }
}

/* ---------- motion.css ---------- */
/**
 * One motion system for the whole page.
 * Entrances: opacity + small translateY, or a mask reveal for photography.
 * Everything is transform/opacity only, and everything collapses to a static
 * page under prefers-reduced-motion.
 */

/* ---- Scroll reveals ------------------------------------------------------ */
.js [data-reveal] {
  opacity: 0;
  will-change: opacity, transform;
}
.js [data-reveal='up'] { transform: translateY(26px); }
/* The clip lives on the child, never on the observed element itself: Chrome
   factors a target's own clip-path into its intersection rect, so a fully
   clipped element would never be reported as visible. */
.js [data-reveal='mask'] { transform: none; }
.js [data-reveal='mask'] > * { clip-path: inset(0 0 100% 0); }

.js [data-reveal].is-inview {
  opacity: 1;
  transform: none;
  transition:
    opacity var(--dur-reveal) var(--ease) calc(var(--reveal-order, 0) * 85ms),
    transform var(--dur-reveal) var(--ease) calc(var(--reveal-order, 0) * 85ms);
}

.js [data-reveal='mask'].is-inview > * {
  clip-path: inset(0 0 0 0);
  transition: clip-path 1000ms var(--ease) calc(var(--reveal-order, 0) * 85ms);
}
.js [data-reveal].is-inview { will-change: auto; }

/* ---- Hero load sequence --------------------------------------------------- */
.js [data-hero] { opacity: 0; }
.js [data-hero='1'], .js [data-hero='3'], .js [data-hero='4'], .js [data-hero='5'] { transform: translateY(22px); }
.js [data-hero='6'] { clip-path: inset(0 0 100% 0); }

.js .hero__title .line > span { transform: translateY(105%); }

.is-ready [data-hero] {
  opacity: 1;
  transform: none;
  transition:
    opacity 760ms var(--ease) var(--delay),
    transform 900ms var(--ease) var(--delay);
}
.is-ready [data-hero='1'] { --delay: 120ms; }
.is-ready [data-hero='2'] { --delay: 180ms; }
.is-ready [data-hero='3'] { --delay: 460ms; }
.is-ready [data-hero='4'] { --delay: 560ms; }
.is-ready [data-hero='5'] { --delay: 680ms; }

.is-ready [data-hero='6'] {
  --delay: 240ms;
  clip-path: inset(0 0 0 0);
  transition:
    opacity 700ms var(--ease) var(--delay),
    clip-path 1150ms var(--ease) var(--delay);
}
.is-ready .hero__picture img {
  animation: hero-settle 1500ms var(--ease) 240ms both;
}

.is-ready .hero__title .line > span {
  transform: none;
  transition: transform 1000ms var(--ease) var(--line-delay);
}
.is-ready .hero__title .line:nth-child(1) > span { --line-delay: 220ms; }
.is-ready .hero__title .line:nth-child(2) > span { --line-delay: 320ms; }

@keyframes hero-settle {
  from { transform: scale(1.04); }
  to { transform: scale(1); }
}

/* ---- Reduced motion: no transforms, nothing hidden ------------------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }

  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }

  [data-reveal],
  [data-reveal] > *,
  [data-hero],
  .hero__title .line > span {
    opacity: 1 !important;
    transform: none !important;
    clip-path: none !important;
  }

  .service__media-layer { transform: none; }
  .mobile-cta { transform: none; }
  .modal__panel,
  .lightbox__inner { opacity: 1; transform: none; }
}

/* ---------- preloader.css ---------- */
/**
 * Brand preloader.
 *
 * Only shown once the inline head script has set `pl-active` on <html>, so a
 * page without JavaScript never sees it. Every state below is the resting
 * "before" state; src/scripts/preloader.js drives the sequence with GSAP and
 * removes the element from the DOM when the split exit has finished.
 *
 * Gold is the logo artwork's own colour (#FCD628). The ground is Graphite.
 */
.preloader { display: none; }

.pl-active,
.pl-active body { overflow: hidden; }

.pl-active .preloader {
  --pl-gold: #fcd628;
  --pl-w: 15.625rem;       /* 250px on phones */
  --pl-stroke: 5.5;        /* user units: ~1px at every size */
  position: fixed;
  inset: 0;
  z-index: 1000;
  display: block;
  color: var(--dark-ink);
}

@media (min-width: 600px) {
  .pl-active .preloader { --pl-w: 20rem; --pl-stroke: 4.6; }
}
@media (min-width: 1024px) {
  .pl-active .preloader { --pl-w: 25rem; --pl-stroke: 4; }
}

/* ---- Ground: two panels that part on exit ------------------------------- */
.preloader__panel {
  position: absolute;
  left: 0;
  right: 0;
  height: 50.5%;          /* a hairline of overlap, so no seam shows */
  background: var(--dark);
}
.preloader__panel--top { top: 0; }
.preloader__panel--bottom { bottom: 0; }

/* ---- Stage: the logo is centred on the viewport, the indicator hangs below */
.preloader__stage {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  padding: 1.25rem;
}
.preloader__mark {
  position: relative;
  width: min(var(--pl-w), calc((100dvh - 12rem) * 1.5767));
}
.preloader__logo { transform-origin: 50% 50%; }
.preloader__svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

/* ---- Logo layers ---------------------------------------------------------- */
.pl-fill { fill: var(--pl-gold); opacity: 0; }

.pl-outline {
  fill: none;
  stroke: var(--pl-gold);
  stroke-width: var(--pl-stroke);
  stroke-linejoin: miter;
  stroke-linecap: butt;
}
.pl-draw {
  opacity: 0;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
}
.pl-window { opacity: 0; stroke-opacity: 0.9; }

.pl-text { fill: rgba(246, 245, 241, 0.92); }
.preloader:not(.is-armed) .pl-text { visibility: hidden; }

.pl-sweep { opacity: 0; }

/* ---- Loading indicator: a 1px architectural line and a quiet counter ----- */
.preloader__progress {
  position: absolute;
  left: 50%;
  top: calc(100% + clamp(2rem, 6vh, 3.5rem));
  width: 10rem;
  transform: translateX(-50%);
  opacity: 0;
}
.preloader__track {
  position: relative;
  height: 1px;
  overflow: hidden;
  background: rgba(246, 245, 241, 0.12);
}
.preloader__bar,
.preloader__glint {
  position: absolute;
  inset: 0;
}
.preloader__bar {
  background: rgba(252, 214, 40, 0.62);
  transform: scaleX(0);
  transform-origin: 0 50%;
}
/* The warm line that opens the sequence; it settles into the muted track. */
.preloader__glint { background: var(--pl-gold); }

.preloader__count {
  display: block;
  margin-top: 0.875rem;
  font-family: var(--font-body);
  font-size: 0.6875rem;
  font-weight: 500;
  line-height: 1;
  letter-spacing: 0.2em;
  text-align: center;
  font-variant-numeric: tabular-nums;
  color: rgba(246, 245, 241, 0.42);
}

/* ---- Reduced motion: the finished logo, briefly, then gone ---------------- */
.pl-reduced .preloader .pl-fill { opacity: 1; }
.pl-reduced .preloader .pl-outline,
.pl-reduced .preloader .pl-sweep,
.pl-reduced .preloader .preloader__progress { display: none; }
.pl-reduced .preloader .pl-text { visibility: visible; fill: var(--pl-gold); }

/* ---- Hand-off to the hero -------------------------------------------------
   The split panels reveal the photograph itself, so the hero's own clip wipe
   is switched off and the image settles from a slight scale instead. */
.pl-used [data-hero='6'],
.pl-used.is-ready [data-hero='6'] {
  opacity: 1;
  clip-path: none;
  transition: none;
}
.pl-used .hero__picture img { transform: scale(1.04); }
.pl-used.is-ready .hero__picture img {
  animation: hero-settle 1600ms var(--ease) 0ms both;
}