@charset "UTF-8";
/* ==========================================================================
   Patio Elite — main stylesheet
   1. Design tokens
   2. Reset & base
   3. Layout primitives
   4. Components
   5. Sections
   6. Utilities
   7. Print
   ========================================================================== */

/* ==========================================================================
   0. Webfonts
   Self-hosted from /assets/fonts/ (SIL Open Font License, see the OFL files
   there): no third-party connection before text renders, and no visitor IP
   sent to Google. These are the Latin subsets Google Fonts serves, which
   cover all of French, and the rules mirror Google's, so text renders exactly
   as it did. Open Sans is one variable file serving both weights.
   ========================================================================== */
@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/open-sans-latin.woff2") format("woff2");
}
@font-face {
  font-family: "Open Sans";
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url("../fonts/open-sans-latin.woff2") format("woff2");
}
@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/poppins-500-latin.woff2") format("woff2");
}
@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/poppins-600-latin.woff2") format("woff2");
}
@font-face {
  font-family: "Poppins";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/poppins-700-latin.woff2") format("woff2");
}

/* ==========================================================================
   1. Design tokens
   ========================================================================== */
:root {
  /* Brand — brown is the accent (eyebrows, step numbers); grey is the button
     colour. Both taken from the original site's palette. */
  --c-brand:        #634435;
  --c-brand-dark:   #4a3227;
  --c-brand-light:  #8a6450;
  --c-brand-tint:   #f4efec;

  --c-btn:          #5c5c5c;
  --c-btn-dark:     #3f3f3f;

  /* Neutrals */
  --c-ink:          #242424;
  --c-ink-soft:     #333333;
  --c-body:         #6f6f6f;
  --c-muted:        #8a8a8a;
  --c-line:         #e3e0dd;
  --c-surface:      #ffffff;
  --c-surface-alt:  #f8f7f5;
  --c-surface-dark: #1f1c1a;

  /* Feedback */
  --c-error:        #b3261e;
  --c-success:      #2e6b3f;

  /* Typography */
  --f-head: "Poppins", "Segoe UI", system-ui, -apple-system, sans-serif;
  --f-body: "Open Sans", "Segoe UI", system-ui, -apple-system, sans-serif;

  --fs-xs:   0.8125rem;
  --fs-sm:   0.9375rem;
  --fs-base: 1rem;
  --fs-md:   1.0625rem;
  --fs-lg:   clamp(1.125rem, 0.5vw + 1rem, 1.25rem);
  --fs-h4:   clamp(1.25rem, 0.7vw + 1.05rem, 1.5rem);
  --fs-h3:   clamp(1.375rem, 1vw + 1.1rem, 1.75rem);
  --fs-h2:   clamp(1.75rem, 2.4vw + 1.05rem, 2.875rem);
  --fs-h1:   clamp(2rem, 3.2vw + 1.2rem, 3.25rem);
  --fs-hero: clamp(2.25rem, 4.5vw + 1rem, 4rem);

  --lh-tight: 1.18;
  --lh-base:  1.75;

  /* Spacing scale */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.5rem;
  --sp-6: 2rem;
  --sp-7: 3rem;
  --sp-8: 4rem;

  --section-y: clamp(3.5rem, 7vw, 6.5rem);

  /* Layout */
  --wrap:       1200px;
  --wrap-text:  68ch;
  --gutter:     clamp(1rem, 4vw, 2.5rem);

  /* Effects */
  --radius-sm: 4px;
  --radius:    8px;
  --radius-lg: 16px;

  --shadow-sm: 0 1px 2px rgb(31 28 26 / 8%);
  --shadow:    0 6px 20px -6px rgb(31 28 26 / 16%);
  --shadow-lg: 0 24px 60px -20px rgb(31 28 26 / 28%);

  --ease: cubic-bezier(0.4, 0, 0.2, 1);
  --dur:  0.28s;

  --header-h: 76px;
}

/* ==========================================================================
   2. Reset & base
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* Mobile Safari and Chrome paint a translucent blue box over whatever is
     tapped or held. Every control here already answers a press with its own
     hover or active styling, so the extra highlight only adds a colour that
     belongs to no part of the palette. Inherited, so it covers every element. */
  -webkit-tap-highlight-color: transparent;
  /* Anchor targets have to clear the sticky header. Uses the measured height
     so a nav that wraps to two lines, or a header that grows when the webfont
     swaps in, still lands the target below it rather than underneath. */
  scroll-padding-top: calc(var(--header-measured, var(--header-h)) + var(--sp-5));
  /* The off-canvas mobile drawer is parked past the right edge. Without this it
     widens the document, which inflates the layout viewport and makes phones
     render the whole page zoomed out. `clip` (not `hidden`) contains it without
     creating a scroll container, so the sticky header keeps working. */
  overflow-x: clip;
}

body {
  margin: 0;
  overflow-x: clip;
  font-family: var(--f-body);
  font-size: var(--fs-md);
  line-height: var(--lh-base);
  color: var(--c-body);
  background: var(--c-surface);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-wrap: break-word;
}

/* Scroll lock for the drawer and the lightbox. On the root, not body: with
   `overflow-x: clip` on html, body's overflow is not passed to the viewport,
   so locking body only made it a scroll box of its own (the page behind kept
   scrolling, and the sticky header scrolled away inside it). */
:root.is-locked { overflow: hidden; }

h1, h2, h3, h4, h5, h6 {
  margin: 0 0 var(--sp-4);
  font-family: var(--f-head);
  font-weight: 600;
  line-height: var(--lh-tight);
  color: var(--c-ink);
  letter-spacing: -0.015em;
  text-wrap: balance;
}

h1 { font-size: var(--fs-h1); }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); }
h4 { font-size: var(--fs-h4); }

p { margin: 0 0 var(--sp-4); }
p:last-child { margin-bottom: 0; }

a {
  color: var(--c-brand);
  text-decoration-thickness: 1px;
  text-underline-offset: 3px;
  transition: color var(--dur) var(--ease);
}
@media (hover: hover) {
  a:hover { color: var(--c-brand-dark); }
}

img, picture, video, svg { display: block; max-width: 100%; height: auto; }

/* Wherever an image is meant to fill a sized box, the <picture> wrapper has to
   fill it too — otherwise `height: 100%` on the <img> resolves against a
   shrink-to-fit parent and collapses to the image's own aspect ratio. */
.hero__media picture,
.page-head__bg picture,
.card__media picture,
.gallery__item picture { display: block; width: 100%; height: 100%; }

ul, ol { margin: 0 0 var(--sp-4); padding-left: 1.25em; }
li + li { margin-top: var(--sp-2); }

strong, b { font-weight: 600; color: var(--c-ink-soft); }

hr { border: 0; border-top: 1px solid var(--c-line); margin: var(--sp-7) 0; }

:focus-visible {
  outline: 3px solid var(--c-brand-light);
  outline-offset: 3px;
  border-radius: var(--radius-sm);
}

::selection { background: var(--c-brand); color: #fff; }

@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;
  }
}

/* ==========================================================================
   3. Layout primitives
   ========================================================================== */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  /* `viewport-fit=cover` lets the page paint under the notch in landscape, so
     the gutter has to clear the safe area as well. */
  padding-left: max(var(--gutter), env(safe-area-inset-left, 0px));
  padding-right: max(var(--gutter), env(safe-area-inset-right, 0px));
}
.wrap--narrow { max-width: 860px; }

.section { padding-block: var(--section-y); }
.section--alt { background: var(--c-surface-alt); }

.grid { display: grid; gap: var(--sp-6); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 280px), 1fr)); }
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 230px), 1fr)); }

.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: -100px;
  z-index: 999;
  padding: var(--sp-3) var(--sp-5);
  background: var(--c-brand);
  color: #fff;
  font-weight: 600;
  border-radius: 0 0 var(--radius) var(--radius);
  transition: top var(--dur) var(--ease);
}
.skip-link:focus { top: 0; color: #fff; }

/* ==========================================================================
   4. Components
   ========================================================================== */

/* --- Section heading ----------------------------------------------------- */
.sec-head { max-width: var(--wrap-text); margin-bottom: var(--sp-7); }
.sec-head--center { margin-inline: auto; text-align: center; }

.eyebrow {
  display: block;
  margin-bottom: var(--sp-3);
  font-family: var(--f-head);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--c-brand);
}

.sec-head__title { margin-bottom: var(--sp-4); }
.sec-head__lead { font-size: var(--fs-md); margin-bottom: 0; }

/* --- Buttons ------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 0.8em 1.6em;
  font-family: var(--f-head);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-decoration: none;
  text-align: center;
  line-height: 1.25;
  border: 2px solid transparent;
  border-radius: 2px;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
@media (hover: hover) {
  .btn:hover { transform: translateY(-2px); }
}
.btn:active { transform: translateY(0); }

.btn--primary { background: var(--c-btn); border-color: var(--c-btn); color: #fff; }
@media (hover: hover) {
  .btn--primary:hover { background: var(--c-btn-dark); border-color: var(--c-btn-dark); color: #fff; }
}

.btn--outline { background: transparent; border-color: var(--c-btn); color: var(--c-ink-soft); }
@media (hover: hover) {
  .btn--outline:hover { background: var(--c-btn); border-color: var(--c-btn); color: #fff; }
}

/* The quote request is the site's primary conversion action, so it carries the
   brand accent and a lift instead of the neutral grey used by everything else —
   it should be the most prominent control on any screen it appears on. */
.btn--cta {
  padding: 0.9em 2em;
  font-weight: 600;
  letter-spacing: 0.05em;
  background: var(--c-brand);
  border-color: var(--c-brand);
  color: #fff;
  box-shadow: 0 8px 20px -8px rgb(99 68 53 / 75%);
}
@media (hover: hover) {
  .btn--cta:hover {
    background: var(--c-brand-dark);
    border-color: var(--c-brand-dark);
    color: #fff;
    box-shadow: 0 14px 28px -10px rgb(99 68 53 / 90%);
  }
}
.btn--cta.btn--sm { padding: 0.72em 1.5em; }

.btn--ghost-light { background: transparent; border-color: rgb(255 255 255 / 65%); color: #fff; }
@media (hover: hover) {
  .btn--ghost-light:hover { background: #fff; border-color: #fff; color: var(--c-brand); }
}

.btn--sm { padding: 0.65em 1.35em; font-size: var(--fs-xs); }
.btn--block { display: flex; width: 100%; }

/* --- Header / navigation ------------------------------------------------- */
.header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: #000;
  border-bottom: 1px solid rgb(255 255 255 / 12%);
  transition: box-shadow var(--dur) var(--ease);
  /* No `backdrop-filter` here on purpose: it would make the header a containing
     block for its `position: fixed` descendants, which collapses the off-canvas
     mobile drawer to the header's own 76px box instead of the full viewport. */
}

/* Safari on iOS leaves a sub-pixel seam above a sticky element while scrolling,
   through which the white page background flashes as a hairline. This strip
   sits just above the bar and covers it. Absolutely positioned, so it adds no
   height and leaves the hero's `100lvh - header` arithmetic untouched. */
.header::before {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: 100%;
  height: 3px;
  background: #000;
}

/* The logo is dark artwork on a transparent ground, so it needs inverting to
   read on the black bar. `brightness(0)` flattens it to black, `invert(1)`
   turns that white; transparent pixels stay transparent. */
.header .brand img { filter: brightness(0) invert(1); }
.header.is-stuck { box-shadow: var(--shadow); }

.header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-5);
  min-height: var(--header-h);
}

.brand { flex: 0 0 auto; display: inline-flex; align-items: center; }
.brand img { width: 132px; height: auto; }

.nav { display: flex; align-items: center; gap: var(--sp-5); }

.nav__list {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
  list-style: none;
}
.nav__list li { margin: 0; }

.nav__link {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  font-family: var(--f-head);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: rgb(255 255 255 / 82%);
  text-decoration: none;
  border-radius: var(--radius-sm);
  white-space: nowrap;
}
/* Brown fill marks the pointer, not the location — the current page is
   indicated by weight alone so the bar stays quiet. */
.nav__link:focus-visible { color: #fff; background: var(--c-brand); }
@media (hover: hover) {
  .nav__link:hover { color: #fff; background: var(--c-brand); }
}
.nav__link[aria-current="page"] { color: #fff; font-weight: 600; }

/* Dropdown */
.nav__item--has-menu { position: relative; }

.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  font-family: var(--f-head);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: rgb(255 255 255 / 82%);
  background: none;
  border: 0;
  border-radius: var(--radius-sm);
  cursor: pointer;
  white-space: nowrap;
}
.nav__toggle:focus-visible,
.nav__toggle[aria-expanded="true"] { color: #fff; background: var(--c-brand); }
@media (hover: hover) {
  .nav__toggle:hover { color: #fff; background: var(--c-brand); }
}
.nav__toggle svg { width: 10px; height: 10px; transition: transform var(--dur) var(--ease); }
.nav__toggle[aria-expanded="true"] svg { transform: rotate(180deg); }

.nav__menu {
  position: absolute;
  top: calc(100% + 10px);
  left: 0;
  min-width: 210px;
  margin: 0;
  padding: var(--sp-2);
  list-style: none;
  background: #fff;
  border: 1px solid var(--c-line);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  /* `visibility` is stepped, not eased: flip it instantly when opening (so the
     links are focusable in the same frame) and defer it to the end when
     closing, so the fade-out stays visible. */
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease), visibility 0s linear var(--dur);
}
.nav__toggle[aria-expanded="true"] + .nav__menu {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease), visibility 0s;
}
.nav__menu li { margin: 0; }
.nav__menu a {
  display: block;
  padding: var(--sp-2) var(--sp-3);
  font-family: var(--f-head);
  font-size: var(--fs-sm);
  color: var(--c-ink-soft);
  text-decoration: none;
  border-radius: var(--radius-sm);
}
@media (hover: hover) {
  .nav__menu a:hover { background: var(--c-brand-tint); color: var(--c-brand); }
}

.nav__actions { display: flex; align-items: center; gap: var(--sp-3); }
/* The quote label is two words in both languages; keep it on a single line. */
.nav__actions .btn { white-space: nowrap; }

/* Desktop: the menu sits beside the logo while the quote button, socials and
   language picker stay pinned to the far right. The nav takes the leftover
   width so its list starts next to the brand, and `margin-left: auto` on the
   actions pushes that group to the opposite edge.

   Where that switch happens is a property of the content, not a fixed width:
   the French labels are much wider than the English ones, and the menu will
   keep changing. So the widths below are only a fallback — main.js measures
   what the row actually needs and rewrites both conditions to the real number.
   It finds these two blocks by their --nav-mode declaration, and reads the same
   property back to know which layout is live, so nothing has to be kept in sync
   by hand. Keep --nav-mode first in each block. */
@media (min-width: 1024px) {
  :root { --nav-mode: row; }

  .nav { flex: 1 1 auto; }
  .nav__actions { margin-left: auto; }

  /* Last item in the row. Reordered here rather than moved in the markup,
     because the drawer needs it above the quote button — see below. */
  .lang { order: 1; }
}

.lang {
  display: inline-flex;
  align-items: center;
  padding: var(--sp-2) var(--sp-3);
  font-family: var(--f-head);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: rgb(255 255 255 / 70%);
  text-decoration: none;
  border: 1px solid rgb(255 255 255 / 28%);
  border-radius: var(--radius-sm);
}
@media (hover: hover) {
  .lang:hover { color: #fff; border-color: #fff; }
}

/* Burger — icon plus a "Menu" label, as on the original mobile header */
.burger {
  display: none;
  align-items: center;
  gap: var(--sp-3);
  min-height: 44px;
  padding: var(--sp-2) var(--sp-1);
  background: none;
  border: 0;
  cursor: pointer;
}
.burger__bars { display: flex; flex-direction: column; justify-content: center; gap: 5px; width: 24px; }
.burger__bars span {
  display: block;
  height: 2px;
  background: #fff;
  border-radius: 2px;
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.burger__label {
  font-family: var(--f-head);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #fff;
}
.burger[aria-expanded="true"] .burger__bars span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__bars span:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] .burger__bars span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Drawer close control and the flat-list link — mobile only */
.nav__close { display: none; }
.nav__link--flat { display: none; }

/* Social links sit at the end of the navigation. On the black bar they are
   plain light icons with no chip behind them. Scoped to .nav so they outrank
   the base `.socials a` rule defined later in this file at equal specificity. */
.nav .socials--nav { margin: 0; gap: 0; }
.nav .socials--nav a {
  width: 34px;
  height: 34px;
  color: rgb(255 255 255 / 78%);
  background: transparent;
  border-color: transparent;
}
@media (hover: hover) {
  .nav .socials--nav a:hover { color: #fff; background: transparent; border-color: transparent; }
}
.nav .socials--nav svg { width: 18px; height: 18px; }

/* Mobile keeps its own copy in the header row instead; hidden on desktop.
   Scoped to .header so it outranks the base `.socials { display: flex }`
   defined later in this file. */
.header .socials--header { display: none; }

@media (max-width: 1023px) {
  /* Paired with the row block above — see the note there before editing. */
  :root { --nav-mode: drawer; }

  /* The header row is shorter here, and the hero's height is derived from this
     token, so it has to track the real value. */
  :root { --header-h: 64px; }

  /* Header row: burger left, logo centred, socials top right. */
  .burger { display: flex; gap: var(--sp-2); }
  .burger__bars { width: 22px; }
  .burger__label { font-size: var(--fs-xs); }

  .header__inner { gap: var(--sp-2); min-height: var(--header-h); position: relative; }
  /* Clear of the notch when a phone is turned landscape (viewport-fit=cover). */
  .header .wrap {
    padding-inline: max(var(--sp-4), env(safe-area-inset-left, 0px)) max(var(--sp-4), env(safe-area-inset-right, 0px));
  }
  /* Centred against the viewport rather than the leftover space, so the burger
     and the socials don't push the logo off-centre. */
  .brand { position: absolute; left: 50%; transform: translateX(-50%); }
  .brand img { width: 104px; }

  .header .socials--header {
    display: flex;
    margin: 0 0 0 auto;
    gap: 0;
  }
  .header .socials--header a {
    width: 28px;
    height: 28px;
    color: rgb(255 255 255 / 78%);
    background: transparent;
    border-color: transparent;
  }
  @media (hover: hover) {
    .header .socials--header a:hover { color: #fff; background: transparent; border-color: transparent; }
  }
  .header .socials--header svg { width: 17px; height: 17px; }

  /* The logo is centred on the viewport, so on phones narrower than 368px
     (360px Androids, 320px iPhones) all four icons reach under it. Keep the
     two that start a conversation; Facebook and Instagram stay in the footer. */
  @media (max-width: 367px) {
    .header .socials--header li:nth-child(n+3) { display: none; }
  }

  /* The header row carries them on mobile, so the in-drawer copy would only
     duplicate the same four links. */
  .nav .socials--nav { display: none; }

  /* Off-canvas drawer — slides in from the left, matching the original. */
  .nav {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 100;
    /* Widened by the left inset and padded past it, so the notch in landscape
       and the status bar in portrait cover nothing. */
    width: calc(min(300px, 86vw) + env(safe-area-inset-left, 0px));
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding:
      calc(var(--sp-5) + env(safe-area-inset-top, 0px))
      0
      calc(var(--sp-7) + env(safe-area-inset-bottom, 0px))
      env(safe-area-inset-left, 0px);
    background: #fff;
    border-right: 1px solid var(--c-line);
    box-shadow: var(--shadow-lg);
    overflow-y: auto;
    overscroll-behavior: contain;
    transform: translateX(-100%);
    visibility: hidden;
    transition: transform var(--dur) var(--ease), visibility 0s linear var(--dur);
  }
  .nav.is-open {
    transform: translateX(0);
    visibility: visible;
    transition: transform var(--dur) var(--ease), visibility 0s;
  }

  .nav__close {
    display: inline-flex;
    align-items: center;
    gap: var(--sp-2);
    align-self: flex-end;
    margin: 0 var(--sp-4) var(--sp-4) 0;
    padding: var(--sp-2) var(--sp-3);
    font-family: var(--f-head);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--c-muted);
    background: none;
    border: 0;
    cursor: pointer;
  }
  .nav__close svg { width: 14px; height: 14px; }
  @media (hover: hover) {
    .nav__close:hover { color: var(--c-brand); }
  }

  /* Flat list: the dropdown collapses to a single link, as on the original. */
  .nav__list { flex-direction: column; align-items: stretch; gap: 0; }
  .nav__toggle, .nav__menu { display: none; }
  .nav__link--flat { display: block; }

  .nav__link {
    width: 100%;
    padding: 0.95rem var(--sp-5);
    font-size: var(--fs-xs);
    font-weight: 600;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--c-body);
    border-radius: 0;
  }
  .nav__link[aria-current="page"] { color: var(--c-brand); background: var(--c-brand-tint); }
  @media (hover: hover) {
    .nav__link:hover { color: var(--c-brand); background: var(--c-brand-tint); }
  }

  .nav__actions { flex-direction: column; align-items: stretch; gap: 0; margin-top: var(--sp-4); }

  /* The quote button keeps its desktop treatment — filled brand accent with a
     lift — and sits on its own below the language switch. */
  .nav__actions .btn--cta {
    justify-content: center;
    margin: var(--sp-2) var(--sp-5) var(--sp-3);
    padding: 0.95em 1.4em;
    text-align: center;
  }

  /* The language switch stays a plain row, matching the menu items above it.
     Scoped to .nav, not .nav__actions: it sits alongside that group now, and
     DOM order already places it above the quote button. */
  .nav .lang {
    justify-content: flex-start;
    width: 100%;
    padding: 0.95rem var(--sp-5);
    font-size: var(--fs-xs);
    letter-spacing: 0.06em;
    text-align: left;
    color: var(--c-body);
    border: 0;
    border-radius: 0;
  }
  @media (hover: hover) {
    .nav .lang:hover { color: var(--c-brand); background: var(--c-brand-tint); }
  }

  .nav-scrim {
    position: fixed;
    inset: 0;
    z-index: 99;
    background: rgb(31 28 26 / 45%);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
  }
  .nav-scrim.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--dur) var(--ease), visibility 0s;
  }
}

/* Resizing the window can cross the width where the row becomes the drawer.
   That switch sets the same `transform` and `visibility` the open and close
   animation uses, so the browser animates it and the closed pane slides right
   across the screen — a flash of a menu nobody opened. None of it is a real
   open or close, so the transitions are simply off while a resize is in
   progress. Declared outside both blocks because the switch happens in both
   directions, and prefixed with `:root` to outrank `.nav.is-open`. */
:root.is-resizing .nav,
:root.is-resizing .nav-scrim { transition: none; }

/* --- Hero ---------------------------------------------------------------- */
.hero {
  position: relative;
  display: grid;
  place-items: center;
  /* Fills the screen alongside the header. `min-height` (not height) lets it
     grow if the copy needs more room on a short landscape viewport.

     `svh` is the small viewport — the area Safari on iOS actually leaves
     visible with its address bar shown. Sizing to it fits that area exactly,
     with nothing tucked behind the bar. `lvh` and the fixed-element probe that
     preceded it both aimed to run *behind* the bar and could not land it: no
     unit reports that height, and iOS constrains fixed elements to the visible
     viewport, so measuring one just returns `svh` again.

     `--header-measured` is the header's real height, published by main.js once
     the webfont has settled; `--header-h` is the authored fallback used before
     that runs and if scripting is off. Subtracting it keeps header + hero to a
     single screen. */
  min-height: calc(100vh - var(--header-measured, var(--header-h)));
  min-height: calc(100svh - var(--header-measured, var(--header-h)));

  padding-top: var(--sp-7);
  /* Only the home indicator to clear now — the box stops above the address
     bar rather than running behind it. Enough, too, to keep the copy above
     the 40px pause button: on a short phone the copy fills the hero, and the
     full-width buttons would otherwise run under it. */
  padding-bottom: calc(var(--sp-5) + 40px + var(--sp-3) + env(safe-area-inset-bottom, 0px));
  overflow: hidden;
  background: var(--c-surface-dark);
  isolation: isolate;
}

@media (min-width: 640px) {
  .hero {
    padding-top: var(--sp-8);
    padding-bottom: calc(var(--sp-8) + env(safe-area-inset-bottom, 0px));
  }
}

/* Background reel. The still is the reel's own first frame, so the video can
   fade in over it without a visible change; main.js adds `.is-playing` once
   frames are actually arriving, not merely when play() was asked for. */
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img,
.hero__video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.hero__video {
  opacity: 0;
  transition: opacity 1.2s var(--ease);
}
.hero.is-playing .hero__video { opacity: 1; }

/* Clip playlist: two stacked players. The whole stack fades in over the still
   like the single reel does; inside it, each new clip fades in on top of the
   one playing (`.is-top`), which stays fully visible underneath until the
   fade completes, so the change is a true crossfade with no dip. */
.hero__playlist {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1.2s var(--ease);
}
.hero.is-playing .hero__playlist { opacity: 1; }
.hero__clip {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1s linear;
}
.hero__clip.is-shown { opacity: 1; }
/* The playing clip sits above the idle player, which is being loaded with
   the next file and would otherwise show through as it fades out; the
   incoming clip goes above both for its fade. */
.hero__clip.is-front { z-index: 1; }
.hero__clip.is-top { z-index: 2; }

/* Motion is the whole point of the reel, so with reduced motion it never
   loads (main.js checks the same query) and the still stands in. */
@media (prefers-reduced-motion: reduce) {
  .hero__video,
  .hero__playlist { display: none; }
}

/* Pause control. Anything that moves on its own for longer than a few seconds
   needs a way to stop it; kept small and quiet so it does not compete with
   the calls to action. */
.hero__toggle {
  position: absolute;
  right: max(var(--gutter), env(safe-area-inset-right, 0px));
  bottom: calc(var(--sp-5) + env(safe-area-inset-bottom, 0px));
  z-index: 1;
  display: grid;
  place-items: center;
  width: 40px;
  height: 40px;
  padding: 0;
  color: #fff;
  background: rgb(20 17 15 / 35%);
  border: 1px solid rgb(255 255 255 / 35%);
  border-radius: 50%;
  cursor: pointer;
  -webkit-backdrop-filter: blur(6px);
  backdrop-filter: blur(6px);
  transition: background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.hero__toggle[hidden] { display: none; }
.hero__toggle svg { width: 16px; height: 16px; }
.hero__toggle[data-state="playing"] .hero__toggle-play,
.hero__toggle[data-state="paused"] .hero__toggle-pause { display: none; }
@media (hover: hover) {
  .hero__toggle:hover { background: rgb(20 17 15 / 60%); border-color: #fff; }
}

.hero::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Shade concentrated where the copy sits — a soft pool behind the headline
     and a floor under the buttons — so the photo keeps its colour around the
     edges instead of sitting under one flat grey veil. */
  background:
    radial-gradient(ellipse 72% 60% at 50% 52%, rgb(20 17 15 / 58%) 0%, rgb(20 17 15 / 30%) 55%, rgb(20 17 15 / 0%) 100%),
    linear-gradient(180deg, rgb(20 17 15 / 42%) 0%, rgb(20 17 15 / 24%) 38%, rgb(20 17 15 / 28%) 62%, rgb(20 17 15 / 66%) 100%);
}

.hero__inner { position: relative; text-align: center; max-width: 62rem; }
/* Two shadows: a tight one that edges each letter against bright siding or
   sky, and a wide soft one that lifts the line off busy detail. */
.hero__title { font-size: var(--fs-hero); color: #fff; margin-bottom: var(--sp-5); text-shadow: 0 1px 3px rgb(0 0 0 / 45%), 0 2px 28px rgb(0 0 0 / 50%); }
/* The big slogan is a <p> and the line beneath it is the page's h1, because
   that line names the services and the area. Each takes the other's element
   defaults here, so the swap changes the markup and not the look. */
.hero__title {
  font-family: var(--f-head);
  font-weight: 600;
  line-height: var(--lh-tight);
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.hero__lead {
  font-family: var(--f-body);
  line-height: var(--lh-base);
  letter-spacing: normal;
  text-wrap: wrap;
  max-width: 44rem;
  margin: 0 auto var(--sp-6);
  font-size: var(--fs-lg);
  color: #fff;
  font-weight: 600;
  /* Smaller type than the title, so it needs the firmer edge more. */
  text-shadow: 0 1px 2px rgb(0 0 0 / 60%), 0 1px 16px rgb(0 0 0 / 55%);
}
.hero__actions { display: flex; flex-wrap: wrap; justify-content: center; gap: var(--sp-4); }

/* On a phone the headline wraps to many lines, which would push the hero past
   the fold and defeat the full-screen framing. Tighten the type and spacing so
   the whole block still fits one screen. Placed after the rules above so it
   wins on source order — these share the same specificity. */
@media (max-width: 639px) {
  /* Split rather than using the `padding-block` shorthand, which would drop
     the insets that keep the copy above the address bar and home indicator. */
  .hero {
    padding-top: var(--sp-5);
    padding-bottom: calc(var(--sp-5) + env(safe-area-inset-bottom, 0px));
  }
  .hero__title { font-size: clamp(2rem, 8.4vw, 2.75rem); margin-bottom: var(--sp-4); }
  .hero__lead { font-size: var(--fs-base); line-height: 1.55; margin-bottom: var(--sp-5); }
  .hero__actions { flex-direction: column; align-items: stretch; gap: var(--sp-3); }
}

/* --- Page header (inner pages) ------------------------------------------- */
.page-head {
  position: relative;
  display: grid;
  place-items: center;
  min-height: clamp(280px, 42vh, 420px);
  padding-block: var(--sp-8);
  background: var(--c-surface-dark);
  overflow: hidden;
  isolation: isolate;
}
.page-head__bg { position: absolute; inset: 0; z-index: -2; }
.page-head__bg img { width: 100%; height: 100%; object-fit: cover; }
.page-head::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgb(31 28 26 / 62%), rgb(31 28 26 / 74%));
}
.page-head__inner { position: relative; text-align: center; max-width: 56rem; }
.page-head__title { color: #fff; margin-bottom: var(--sp-3); }
.page-head__lead { color: rgb(255 255 255 / 85%); font-size: var(--fs-lg); margin: 0; }

/* --- Breadcrumb ---------------------------------------------------------- */
.breadcrumb { padding-block: var(--sp-4); border-bottom: 1px solid var(--c-line); }
.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin: 0;
  padding: 0;
  list-style: none;
  font-size: var(--fs-xs);
}
.breadcrumb li { margin: 0; display: flex; align-items: center; gap: var(--sp-2); }
.breadcrumb li + li::before { content: "/"; color: var(--c-muted); }
.breadcrumb a { color: var(--c-muted); text-decoration: none; }
@media (hover: hover) {
  .breadcrumb a:hover { color: var(--c-brand); }
}
.breadcrumb [aria-current="page"] { color: var(--c-ink-soft); }

/* --- Media + text split -------------------------------------------------- */
.split {
  display: grid;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 340px), 1fr));
}
.split__media { position: relative; }
.split__media img { width: 100%; border-radius: var(--radius-lg); box-shadow: var(--shadow); }
.split--reverse .split__media { order: 2; }

@media (max-width: 719px) {
  .split--reverse .split__media { order: 0; }
}

/* --- Cards --------------------------------------------------------------- */
.card {
  display: flex;
  flex-direction: column;
  height: 100%;
  background: #fff;
  border: 1px solid var(--c-line);
  border-radius: var(--radius-lg);
  overflow: hidden;
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
@media (hover: hover) {
  .card:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
}
.card__media { aspect-ratio: 4 / 3; background: var(--c-surface-alt); }
.card__media img { width: 100%; height: 100%; object-fit: cover; }
.card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  gap: var(--sp-3);
  padding: var(--sp-5);
  text-align: center; /* the original centres its shed card titles */
  align-items: center;
}
.card__title { margin: 0; font-size: 1.5rem; }
.card__cta { margin-top: auto; padding-top: var(--sp-2); }

/* Numbered advantage card */
.advantage {
  position: relative;
  padding: var(--sp-6) var(--sp-5);
  background: #fff;
  border: 1px solid var(--c-line);
  border-radius: var(--radius-lg);
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
@media (hover: hover) {
  .advantage:hover { border-color: var(--c-brand); box-shadow: var(--shadow); }
}
.advantage__num {
  display: block;
  margin-bottom: var(--sp-3);
  font-family: var(--f-head);
  font-size: 2.375rem;
  font-weight: 700;
  line-height: 1;
  color: var(--c-brand);
}
.advantage__title { margin-bottom: var(--sp-2); font-size: var(--fs-h4); }
.advantage__text { margin: 0; font-size: var(--fs-sm); }

/* --- Service tiles ------------------------------------------------------- */
/* One photo of a real project per service, the label set over a dark fade at
   the foot of the frame. Phones stack them; a tablet runs two across with the
   odd fifth tile spanning the row; desktop puts the two wide tiles on top and
   the three narrow ones beneath. */
.service-tiles {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--sp-4);
  margin: 0;
  padding: 0;
  list-style: none;
}
.service-tile { margin: 0; }
.service-tile__link {
  position: relative;
  display: block;
  height: 100%;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  isolation: isolate;
  color: #fff;
  text-decoration: none;
  background: var(--c-surface-dark);
  border-radius: var(--radius-lg);
}
.service-tile__link picture { position: absolute; inset: 0; z-index: -2; }
.service-tile__link img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.6s var(--ease);
}
.service-tile__link::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(180deg, rgb(31 28 26 / 0%) 38%, rgb(31 28 26 / 82%) 100%);
}
.service-tile__body {
  position: absolute;
  inset: auto 0 0;
  display: block;
  padding: var(--sp-5);
}
.service-tile__title {
  margin: 0 0 var(--sp-1);
  font-size: var(--fs-h4);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #fff;
}
.service-tile__text {
  display: block;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: rgb(255 255 255 / 85%);
}
@media (hover: hover) {
  .service-tile__link:hover { color: #fff; }
  .service-tile__link:hover img { transform: scale(1.05); }
}

@media (min-width: 600px) {
  .service-tiles { grid-template-columns: repeat(2, 1fr); }
  .service-tile__link { aspect-ratio: 1; }
  .service-tile:last-child { grid-column: 1 / -1; }
  .service-tile:last-child .service-tile__link { aspect-ratio: 2 / 1; }
}

@media (min-width: 900px) {
  .service-tiles { grid-template-columns: repeat(6, 1fr); }
  .service-tile { grid-column: span 2; }
  .service-tile--wide { grid-column: span 3; }
  .service-tile:last-child { grid-column: span 2; }
  .service-tile__link,
  .service-tile:last-child .service-tile__link { aspect-ratio: 4 / 5; }
  .service-tile--wide .service-tile__link { aspect-ratio: 3 / 2; }
}

/* --- Feature (checkmark) list -------------------------------------------- */
.check-list { margin: 0 0 var(--sp-5); padding: 0; list-style: none; }
.check-list li {
  position: relative;
  margin-top: var(--sp-4);
  padding-left: 2rem;
  font-size: var(--fs-sm);
}
.check-list li:first-child { margin-top: 0; }
.check-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.45em;
  width: 1.1rem;
  height: 1.1rem;
  background: var(--c-brand);
  border-radius: 50%;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M9.6 16.2 4.8 11.4l1.4-1.4 3.4 3.4 8-8L19 6.8z'/%3E%3C/svg%3E") center / 155% no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23fff' d='M9.6 16.2 4.8 11.4l1.4-1.4 3.4 3.4 8-8L19 6.8z'/%3E%3C/svg%3E") center / 155% no-repeat;
}

/* --- Process steps ------------------------------------------------------- */
.step { display: grid; gap: clamp(2rem, 5vw, 4rem); align-items: center; grid-template-columns: 1fr; }
.step + .step { margin-top: clamp(3rem, 6vw, 5rem); }

@media (min-width: 860px) {
  .step { grid-template-columns: 1fr 1fr; }
  .step:nth-child(even) .step__media { order: -1; }
}

.step__media img { width: 100%; border-radius: var(--radius-lg); box-shadow: var(--shadow); }
.step__num {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 2.5rem;
  height: 2.5rem;
  margin-bottom: var(--sp-4);
  font-family: var(--f-head);
  font-size: var(--fs-sm);
  font-weight: 700;
  color: #fff;
  background: var(--c-brand);
  border-radius: 50%;
}
.step__title { margin-bottom: var(--sp-4); }
.step__list { margin: 0; padding: 0; list-style: none; }
.step__list li { margin-top: var(--sp-4); font-size: var(--fs-sm); }
.step__list li:first-child { margin-top: 0; }
.step__list strong { display: block; margin-bottom: var(--sp-1); color: var(--c-ink); }

/* --- Partner logos ------------------------------------------------------- */
/* Full-bleed dark band, as on the original site. */
.partners-band { background: #212121; }
.partners-band .sec-head__title { color: #fff; }
.partners-band .sec-head__lead { color: rgb(255 255 255 / 72%); }
.partners-band .eyebrow { color: var(--c-brand-light); }

.partners {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: var(--sp-6);
  align-items: center;
  /* Sits outside the 1200px container so the row spans the full width. */
  margin: 0;
  padding-inline: max(var(--gutter), env(safe-area-inset-left, 0px));
  list-style: none;
}
.partners li { margin: 0; display: grid; place-items: center; }
.partners a { display: block; border-radius: var(--radius-sm); }

.partners img {
  max-height: 80px;
  width: auto;
  /* The logos are a mix of dark and light artwork — four of the seven would be
     all but invisible on this background in their own colours. Flattening them
     to white silhouettes keeps every one legible and the row consistent. */
  filter: brightness(0) invert(1);
  opacity: 0.72;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.partners a:focus-visible img { opacity: 1; transform: translateY(-2px); }
@media (hover: hover) {
  .partners a:hover img { opacity: 1; transform: translateY(-2px); }
}

/* --- Video --------------------------------------------------------------- */
.video {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  background: var(--c-surface-dark);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}
.video iframe, .video img { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; object-fit: cover; }
.video__btn {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  width: 100%;
  padding: 0;
  background: rgb(31 28 26 / 30%);
  border: 0;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease);
}
@media (hover: hover) {
  .video__btn:hover { background: rgb(31 28 26 / 12%); }
}
.video__btn::after {
  content: "";
  width: 84px;
  height: 84px;
  background: var(--c-brand);
  border-radius: 50%;
  box-shadow: 0 8px 32px rgb(0 0 0 / 35%);
  -webkit-mask: none;
  transition: transform var(--dur) var(--ease);
}
@media (hover: hover) {
  .video__btn:hover::after { transform: scale(1.08); }
}
.video__icon {
  position: absolute;
  /* Above the ::after disc. Without an explicit z-index the disc wins on
     hover: the `transform` it gains there promotes it into the positioned
     paint layer, where — coming later in the DOM at the same z-index — it
     covers the arrow. */
  z-index: 1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: 30px;
  height: 30px;
  color: #fff;
  pointer-events: none;
}

/* Self-hosted walkthrough. Shot upright on a phone, so it is held to the
   screen's height and centred in its column rather than stretched to fill the
   width. The width/height attributes reserve that shape before the poster
   arrives. */
.walkthrough { display: flex; justify-content: center; }
.walkthrough__video {
  width: auto;
  max-width: 100%;
  max-height: min(78vh, 720px);
  max-height: min(78svh, 720px);
  background: var(--c-surface-dark);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-lg);
}

/* --- Legal text (privacy policy) ----------------------------------------- */
.legal h1 { margin-bottom: var(--sp-3); }
.legal h2 { margin-top: var(--sp-7); font-size: var(--fs-h3); }
.legal__updated { margin-bottom: var(--sp-6); font-size: var(--fs-sm); color: var(--c-muted); }
.legal li { margin-bottom: var(--sp-2); }
.legal__contact { padding-left: 0; list-style: none; }

/* --- Before / after pairs ------------------------------------------------ */
/* Two across from tablet width. With an odd count the last pair sits alone,
   centred at the same width as the others rather than stretched. */
.ba-grid {
  display: grid;
  gap: var(--sp-7) var(--sp-6);
}
@media (min-width: 800px) {
  .ba-grid { grid-template-columns: repeat(2, 1fr); }
  .ba-grid > :last-child:nth-child(odd) {
    grid-column: 1 / -1;
    justify-self: center;
    width: calc((100% - var(--sp-6)) / 2);
  }
}

.ba { margin: 0; }

/* The two photos share one frame, split by a hairline seam, so they read as
   a single before-and-after image rather than two separate tiles. */
.ba__pair {
  position: relative;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 3px;
  overflow: hidden;
  background: var(--c-surface);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow);
}
.ba__shot {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  aspect-ratio: 3 / 4;
  overflow: hidden;
  background: var(--c-surface-alt);
  border: 0;
  cursor: zoom-in;
}
.ba__shot picture { display: block; width: 100%; height: 100%; }
.ba__shot img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease);
}
@media (hover: hover) {
  .ba__shot:hover img { transform: scale(1.05); }
}
.ba__shot:focus-visible { outline: 3px solid var(--c-brand); outline-offset: -3px; }

.ba__tag {
  position: absolute;
  top: var(--sp-3);
  left: var(--sp-3);
  padding: 0.3em 0.8em;
  font-family: var(--f-head);
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #fff;
  background: rgb(31 28 26 / 62%);
  border-radius: 999px;
  -webkit-backdrop-filter: blur(4px);
  backdrop-filter: blur(4px);
}
.ba__shot--after .ba__tag { background: var(--c-brand); }

/* Sits on the seam, pointing from the old to the new. */
.ba__arrow {
  position: absolute;
  top: 50%;
  left: 50%;
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  color: var(--c-brand);
  background: #fff;
  border-radius: 50%;
  box-shadow: 0 4px 14px rgb(0 0 0 / 28%);
  transform: translate(-50%, -50%);
  pointer-events: none;
}
.ba__arrow svg { width: 20px; height: 20px; }

.ba__caption { padding: var(--sp-5) var(--sp-2) 0; }
.ba__title { margin-bottom: var(--sp-2); font-size: var(--fs-h4); }
.ba__text { margin-bottom: 0; }

@media (max-width: 499px) {
  .ba__tag { top: var(--sp-2); left: var(--sp-2); font-size: 0.6875rem; }
  .ba__arrow { width: 36px; height: 36px; }
  .ba__arrow svg { width: 17px; height: 17px; }
}

/* --- Gallery ------------------------------------------------------------- */
.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(100%, 280px), 1fr));
  gap: var(--sp-4);
  margin: 0;
  padding: 0;
  list-style: none;
}
.gallery li { margin: 0; }
/* Two across on phones. One column turns an 84-photo gallery into an
   endless scroll of near-identical full-width tiles. */
@media (max-width: 699px) {
  .gallery { grid-template-columns: repeat(2, 1fr); gap: var(--sp-2); }
}
.gallery__item {
  display: block;
  width: 100%;
  padding: 0;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--c-surface-alt);
  border: 0;
  border-radius: var(--radius);
  cursor: zoom-in;
}
.gallery__item img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease);
}
@media (hover: hover) {
  .gallery__item:hover img { transform: scale(1.06); }
}

/* --- Gallery filters ----------------------------------------------------- */
.filters {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-2);
  margin: 0 auto var(--sp-6);
  /* Clears the sticky header when scripted back into view after a filter. */
  scroll-margin-top: calc(var(--header-measured, var(--header-h)) + var(--sp-4));
}
.filters[hidden] { display: none; }
/* All six fit on one line at full width. Below that, a three-column grid
   breaks them three over three in either language, rather than leaving one or
   two alone on a second row; each column takes its widest label. */
@media (min-width: 700px) and (max-width: 1179px) {
  .filters { display: grid; grid-template-columns: repeat(3, auto); justify-content: center; }
}

.filter {
  display: inline-flex;
  align-items: center;
  gap: 0.45em;
  min-height: 44px;
  padding: 0.5em 1.1em;
  font-family: var(--f-head);
  font-size: var(--fs-sm);
  font-weight: 500;
  line-height: 1.2;
  white-space: nowrap;
  color: var(--c-ink);
  background: var(--c-surface);
  border: 1px solid var(--c-line);
  border-radius: 999px;
  cursor: pointer;
  transition: color var(--dur) var(--ease), background-color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.filter__count { font-size: var(--fs-xs); color: var(--c-muted); transition: color var(--dur) var(--ease); }
.filter[aria-pressed="true"] { color: #fff; background: var(--c-brand); border-color: var(--c-brand); }
.filter[aria-pressed="true"] .filter__count { color: rgb(255 255 255 / 72%); }
.filter:focus-visible { outline: 3px solid var(--c-brand); outline-offset: 2px; }
@media (hover: hover) {
  .filter:hover { border-color: var(--c-brand); }
}
.filter:active { border-color: var(--c-brand); }

/* On a phone, six labels would wrap into a tall block above the photos. One
   row that scrolls sideways keeps them to a single line; it runs to the screen
   edges so it's clear there is more to swipe to. */
@media (max-width: 699px) {
  .filters {
    flex-wrap: nowrap;
    justify-content: flex-start;
    margin-inline: calc(var(--gutter) * -1);
    padding-inline: var(--gutter);
    overflow-x: auto;
    scrollbar-width: none;
    -webkit-overflow-scrolling: touch;
  }
  .filters::-webkit-scrollbar { display: none; }
  .filter { flex: none; }
}

/* --- Lightbox ------------------------------------------------------------ */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: var(--sp-5);
  background: rgb(15 13 12 / 92%);
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
}
.lightbox.is-open {
  opacity: 1;
  visibility: visible;
  transition: opacity var(--dur) var(--ease), visibility 0s;
}
.lightbox__img {
  max-width: min(1100px, 94vw);
  max-height: 84vh;
  /* iOS sizes vh to the screen with its toolbars hidden, so a tall photo ran
     under the counter while they show. */
  max-height: 84svh;
  width: auto;
  border-radius: var(--radius);
}
.lightbox__count {
  position: absolute;
  bottom: calc(var(--sp-5) + env(safe-area-inset-bottom, 0px));
  left: 50%;
  transform: translateX(-50%);
  font-size: var(--fs-sm);
  color: rgb(255 255 255 / 70%);
}
.lightbox__btn {
  position: absolute;
  display: grid;
  place-items: center;
  width: 48px;
  height: 48px;
  color: #fff;
  background: rgb(255 255 255 / 12%);
  border: 0;
  border-radius: 50%;
  cursor: pointer;
  transition: background-color var(--dur) var(--ease);
}
@media (hover: hover) {
  .lightbox__btn:hover { background: var(--c-brand); }
}
.lightbox__btn svg { width: 22px; height: 22px; }
/* Clear of the notch and rounded corners in landscape (viewport-fit=cover). */
.lightbox__close {
  top: calc(var(--sp-5) + env(safe-area-inset-top, 0px));
  right: calc(var(--sp-5) + env(safe-area-inset-right, 0px));
}
.lightbox__prev { left: calc(var(--sp-5) + env(safe-area-inset-left, 0px)); top: 50%; transform: translateY(-50%); }
.lightbox__next { right: calc(var(--sp-5) + env(safe-area-inset-right, 0px)); top: 50%; transform: translateY(-50%); }

@media (max-width: 599px) {
  .lightbox__prev { left: calc(var(--sp-4) + env(safe-area-inset-left, 0px)); }
  .lightbox__next { right: calc(var(--sp-4) + env(safe-area-inset-right, 0px)); }
}

/* --- Shed model swatches ------------------------------------------------- */
.models {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 200px), 1fr));
  gap: var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
}
.models li { margin: 0; text-align: center; }
.models figure { margin: 0; }
.models img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: contain;
  background: var(--c-surface-alt);
  border-radius: var(--radius);
  padding: var(--sp-3);
}
.models figcaption { margin-top: var(--sp-3); }
.models__code {
  display: block;
  font-family: var(--f-head);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  color: var(--c-muted);
}
.models__size {
  display: block;
  font-family: var(--f-head);
  font-size: var(--fs-md);
  font-weight: 600;
  color: var(--c-ink);
}

/* --- Contact ------------------------------------------------------------- */
.contact-grid {
  display: grid;
  gap: clamp(2rem, 5vw, 4rem);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 330px), 1fr));
  align-items: start;
}

.contact-list { margin: var(--sp-5) 0 0; padding: 0; list-style: none; }
.contact-list li { display: flex; gap: var(--sp-4); margin-top: var(--sp-5); }
.contact-list li:first-child { margin-top: 0; }
.contact-list .icon {
  flex: 0 0 auto;
  width: 22px;
  height: 22px;
  margin-top: 0.25em;
  color: var(--c-brand);
}
.contact-list dt,
.contact-list__label {
  /* Both are spans, so they need to be block-level to stack — left inline they
     run onto the same line as the value they label. */
  display: block;
  margin-bottom: var(--sp-1);
  font-family: var(--f-head);
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.4;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--c-muted);
}
.contact-list__value {
  display: block;
  font-size: var(--fs-md);
  line-height: 1.5;
  color: var(--c-ink);
}
.contact-list__value a { color: var(--c-ink); text-decoration: none; font-weight: 600; }
@media (hover: hover) {
  .contact-list__value a:hover { color: var(--c-brand); }
}

.socials { display: flex; gap: var(--sp-3); margin: var(--sp-6) 0 0; padding: 0; list-style: none; }
.socials li { margin: 0; }
.socials a {
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  color: var(--c-ink-soft);
  background: var(--c-surface-alt);
  border: 1px solid var(--c-line);
  border-radius: 50%;
  transition: background-color var(--dur) var(--ease), color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
@media (hover: hover) {
  .socials a:hover { background: var(--c-brand); border-color: var(--c-brand); color: #fff; }
}
.socials svg { width: 19px; height: 19px; }

/* Scoped so these beat the generic `.footer a` colour. */
.footer .socials { margin-top: var(--sp-5); }
.footer .socials a {
  color: var(--c-ink-soft);
  background: var(--c-surface-alt);
  border-color: var(--c-line);
}
@media (hover: hover) {
  .footer .socials a:hover { background: var(--c-brand); border-color: var(--c-brand); color: #fff; }
}

/* Compact variant for the dark header strip. */

/* --- Forms --------------------------------------------------------------- */
.form {
  padding: clamp(1.5rem, 4vw, 2.5rem);
  background: #fff;
  border: 1px solid var(--c-line);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.form__grid { display: grid; gap: var(--sp-5); grid-template-columns: repeat(auto-fit, minmax(min(100%, 220px), 1fr)); }
.form__row { display: block; }
.form__row--full { grid-column: 1 / -1; }

.label {
  display: block;
  margin-bottom: var(--sp-2);
  font-family: var(--f-head);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--c-ink-soft);
}
.label .req { color: var(--c-error); }

.input, .select, .textarea {
  display: block;
  width: 100%;
  padding: 0.75em 0.9em;
  font-family: inherit;
  font-size: var(--fs-sm);
  color: var(--c-ink);
  background: var(--c-surface-alt);
  border: 1px solid var(--c-line);
  border-radius: var(--radius-sm);
  transition: border-color var(--dur) var(--ease), background-color var(--dur) var(--ease);
}
.input:focus, .select:focus, .textarea:focus {
  /* background-color, not the shorthand, which would drop the select's arrow. */
  background-color: #fff;
  border-color: var(--c-brand);
  outline: 2px solid rgb(99 68 53 / 18%);
  outline-offset: 0;
}
.input[aria-invalid="true"], .select[aria-invalid="true"], .textarea[aria-invalid="true"] { border-color: var(--c-error); }
.textarea { min-height: 130px; resize: vertical; }

/* iOS zooms the page into any field under 16px when it takes focus. */
@media (pointer: coarse) {
  .input, .select, .textarea { font-size: max(16px, var(--fs-sm)); }
}

.select {
  appearance: none;
  padding-right: 2.4em;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 12 8'%3E%3Cpath fill='%236f6f6f' d='M6 8 0 2l1.4-1.4L6 5.2 10.6.6 12 2z'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 0.9em center;
  background-size: 11px;
}

.radio-group { display: flex; flex-wrap: wrap; gap: var(--sp-5); }
.radio { display: inline-flex; align-items: center; gap: var(--sp-2); font-size: var(--fs-sm); cursor: pointer; }
.radio input { width: 1.1em; height: 1.1em; accent-color: var(--c-brand); }

.field-error {
  display: block;
  margin-top: var(--sp-2);
  font-size: var(--fs-xs);
  color: var(--c-error);
}
.field-error:empty { display: none; }

.form__note { margin-top: var(--sp-4); font-size: var(--fs-xs); color: var(--c-muted); }

.form__status {
  margin-top: var(--sp-5);
  padding: var(--sp-4) var(--sp-5);
  font-size: var(--fs-sm);
  border-radius: var(--radius);
}
.form__status:empty { display: none; }
.form__status[data-state="ok"] { background: #eaf3ec; color: var(--c-success); }
.form__status[data-state="error"] { background: #fbecea; color: var(--c-error); }

.hp { position: absolute !important; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; }

/* --- CTA band ------------------------------------------------------------ */
/* Full-bleed black band, as on the original site. */
.cta-band {
  padding-block: clamp(2.25rem, 4.5vw, 3.5rem);
  background: #000;
  color: rgb(255 255 255 / 72%);
}
.cta-band__inner {
  display: grid;
  gap: var(--sp-5);
  align-items: center;
}
@media (min-width: 860px) {
  .cta-band__inner { grid-template-columns: 1fr auto; gap: var(--sp-7); }
}
.cta-band h2 { color: #fff; margin-bottom: var(--sp-3); font-size: var(--fs-h3); }
.cta-band p { margin: 0; }

/* --- Footer -------------------------------------------------------------- */
.footer {
  padding-top: var(--sp-8);
  background: #fff;
  color: var(--c-body);
  border-top: 1px solid var(--c-line);
  font-size: var(--fs-sm);
}
.footer a { color: var(--c-body); text-decoration: none; }
@media (hover: hover) {
  .footer a:hover { color: var(--c-brand); }
}

.footer__grid {
  display: grid;
  gap: var(--sp-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  padding-bottom: var(--sp-7);
}
.footer__brand img { width: 150px; margin-bottom: var(--sp-4); }
.footer__title {
  margin-bottom: var(--sp-4);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--c-ink);
}
.footer__list { margin: 0; padding: 0; list-style: none; }
.footer__list li { margin-top: var(--sp-2); }
.footer__list li:first-child { margin-top: 0; }
/* The original sets its footer navigation in uppercase. */
.footer__list a { text-transform: uppercase; letter-spacing: 0.04em; font-size: var(--fs-xs); }

.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3) var(--sp-5);
  padding-top: var(--sp-5);
  /* Last thing on the page — keep it above the home indicator. */
  padding-bottom: calc(var(--sp-5) + env(safe-area-inset-bottom, 0px));
  border-top: 1px solid var(--c-line);
  font-size: var(--fs-xs);
}
.footer__bottom p { margin: 0; }

/* --- Back to top --------------------------------------------------------- */
.to-top {
  position: fixed;
  /* Clear of the home indicator, and of the notch in landscape. */
  right: calc(var(--sp-5) + env(safe-area-inset-right, 0px));
  bottom: calc(var(--sp-5) + env(safe-area-inset-bottom, 0px));
  z-index: 90;
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  color: #fff;
  background: var(--c-brand);
  border: 0;
  border-radius: 50%;
  box-shadow: var(--shadow);
  cursor: pointer;
  opacity: 0;
  visibility: hidden;
  transform: translateY(10px);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease), visibility var(--dur), background-color var(--dur) var(--ease);
}
.to-top.is-visible { opacity: 1; visibility: visible; transform: translateY(0); }
@media (hover: hover) {
  .to-top:hover { background: var(--c-brand-dark); }
}
.to-top svg { width: 18px; height: 18px; }

/* --- Reveal on scroll ---------------------------------------------------- */
.reveal { opacity: 0; transform: translateY(22px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
.reveal.is-in { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; }
}

/* --- Press feedback on touch --------------------------------------------- */
/* A cursor gets its answer from :hover, which is now gated to pointer devices,
   and the browser's own blue tap flash is off. So touch needs its own: each
   control repeats its hover appearance for as long as the finger is down.
   Ordered to match the hover rules above — the footer's own link colour before
   the social chips, so the chips still win inside the footer.
   :active does not fire on iOS unless the page listens for touches; main.js
   registers the empty listener that turns it on. */
@media (hover: none) {
  .btn--primary:active { background: var(--c-btn-dark); border-color: var(--c-btn-dark); color: #fff; }
  .btn--outline:active { background: var(--c-btn); border-color: var(--c-btn); color: #fff; }
  .btn--cta:active {
    background: var(--c-brand-dark);
    border-color: var(--c-brand-dark);
    color: #fff;
    box-shadow: 0 14px 28px -10px rgb(99 68 53 / 90%);
  }
  .btn--ghost-light:active { background: #fff; border-color: #fff; color: var(--c-brand); }

  .nav__link:active,
  .nav .lang:active { color: var(--c-brand); background: var(--c-brand-tint); }
  .nav__close:active { color: var(--c-brand); }
  .nav__menu a:active { background: var(--c-brand-tint); color: var(--c-brand); }

  .breadcrumb a:active,
  .contact-list__value a:active,
  .footer a:active { color: var(--c-brand); }

  .socials a:active,
  .footer .socials a:active { background: var(--c-brand); border-color: var(--c-brand); color: #fff; }
  /* Flat icons on the black header strip — a filled chip would be wrong there. */
  .header .socials--header a:active { color: #fff; background: transparent; border-color: transparent; }

  .service-tile__link:active img { transform: scale(1.05); }
  .video__btn:active { background: rgb(31 28 26 / 12%); }
  .hero__toggle:active { background: rgb(20 17 15 / 60%); border-color: #fff; }
  .lightbox__btn:active { background: var(--c-brand); }
  .to-top:active { background: var(--c-brand-dark); }
}

/* ==========================================================================
   6. Utilities
   ========================================================================== */
.sr-only {
  position: absolute !important;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}
.text-center { text-align: center; }
.mt-0 { margin-top: 0; }
.mb-0 { margin-bottom: 0; }
.mt-6 { margin-top: var(--sp-6); }
.mt-7 { margin-top: var(--sp-7); }
.lead { font-size: var(--fs-lg); }

/* ==========================================================================
   7. Print
   ========================================================================== */
@media print {
  .header, .footer, .to-top, .cta-band, .form, .nav-scrim { display: none !important; }
  body { color: #000; font-size: 12pt; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
  .section { padding-block: 1rem; }
}
