/*
Theme Name: H3K Home Decor
Theme URI: https://example.com/h3k
Author: H3K Home Decor
Description: Premium blinds and curtains theme for H3K Home Decor, Townsville. Every section of the home page is editable through Advanced Custom Fields (PRO) tab groups.
Version: 1.0.0
Requires at least: 6.0
Tested up to: 6.6
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: h3k
Tags: business, one-column, custom-menu, featured-images
*/

/* ==========================================================================
   H3K HOME DECOR
   Palette and identity taken from the H3K standee artwork:
   deep royal navy + rich gold, white display type.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design tokens
   -------------------------------------------------------------------------- */
:root {
  /* H3K premium colour system — royal navy dominant, warm ivory for breathing
     space, gold as a restrained accent. Target balance is roughly
     60% navy / 25% ivory / 10% gold / 5% neutrals. No bright blue anywhere. */

  /* Warm ivory ground. Pure white is the deliberate exception, reserved for
     the two photo-led bands (Services, Gallery) where the images should carry
     the colour and the ground should get out of their way. Everywhere else
     stays on the ivory ramp below. */
  --paper-white: #ffffff;
  --paper-50: #faf7f0;
  --paper-100: #f5f0e6; /* Warm Ivory — primary light background */
  --paper-200: #efe8da;
  --paper-300: #e8ddc8; /* Champagne neutral */
  --paper-400: #dccdb0;

  /* Navy ramp — the primary brand */
  --blue-950: #080a0d; /* Rich Black — supporting only */
  --blue-900: #06172f; /* Deep Navy — dark backgrounds */
  --blue-800: #0b2550; /* Royal Navy — primary brand */
  --blue-700: #113166;
  --blue-600: #17407f;
  --blue-500: #1d4a90;
  --blue-400: #2a5aa4;
  --blue-300: #6f8fc0;

  /* Aliases so the dark bands keep resolving */
  --navy-900: var(--blue-900);
  --navy-800: var(--blue-800);
  --navy-700: var(--blue-700);
  --navy-600: var(--blue-600);
  --navy-500: var(--blue-500);

  /* Gold — accent only */
  --gold-100: #f7edd4;
  --gold-200: #f3d47a;
  --gold-light: #e8c66a; /* Champagne Gold — hover and highlights */
  --gold: #d4a62a; /* Signature Gold — primary accent */
  --gold-deep: #9a6a18; /* Antique Gold — depth and dark details */
  --gold-strong: #9a6a18; /* gold that carries text on ivory */
  --gold-ink: #85590f; /* small gold text on ivory */

  /* Text */
  --white: #ffffff;
  --ink: #0b2550; /* Royal Navy — headings on light */
  --charcoal: #25272a; /* Warm Charcoal — body copy */
  --text: rgba(37, 39, 42, 0.9);
  --text-dim: rgba(37, 39, 42, 0.62);
  --ink-soft: rgba(11, 37, 80, 0.7);

  /* Lines and surfaces */
  --hairline: rgba(11, 37, 80, 0.12);
  --gold-hairline: rgba(212, 166, 42, 0.42);
  --blue-hairline: rgba(11, 37, 80, 0.16);
  --surface: rgba(255, 255, 255, 0.6);

  /* Glass — ivory through champagne, with only a hint of gold */
  --glass: linear-gradient(
    150deg,
    rgba(255, 255, 255, 0.9) 0%,
    rgba(245, 240, 230, 0.78) 46%,
    rgba(232, 198, 106, 0.18) 100%
  );
  --glass-strong: linear-gradient(
    150deg,
    rgba(255, 255, 255, 0.98) 0%,
    rgba(239, 232, 218, 0.9) 46%,
    rgba(232, 198, 106, 0.3) 100%
  );
  --glass-border: rgba(11, 37, 80, 0.14);
  --glass-sheen: inset 0 1px 0 rgba(255, 255, 255, 0.95);
  --blur: saturate(140%) blur(20px);

  /* Smoked navy glass — the counterpart to --glass, for the dark cards that
     sit on the ivory bands. Four layers, painted top to bottom: light landing
     on the top-left corner, a thin glint down the same diagonal, warmth thrown
     back up by the ivory ground, then the navy body. The body runs deep and
     near-opaque (0.93–0.97, navy falling into rich black at the foot) so the
     cards read as smoked glass rather than tinted; the pane shows in the edges
     — the rim, the sheen and the corner highlight — not in what passes
     through it. */
  --glass-navy:
    radial-gradient(
      118% 82% at 2% -14%,
      rgba(255, 255, 255, 0.17),
      transparent 54%
    ),
    linear-gradient(
      150deg,
      rgba(255, 255, 255, 0.07),
      rgba(255, 255, 255, 0) 40%
    ),
    radial-gradient(
      92% 72% at 104% 112%,
      rgba(232, 198, 106, 0.15),
      transparent 58%
    ),
    linear-gradient(
      150deg,
      rgba(13, 42, 88, 0.93) 0%,
      rgba(6, 23, 47, 0.96) 48%,
      rgba(8, 10, 13, 0.97) 100%
    );
  --glass-navy-border: rgba(255, 255, 255, 0.12);
  --glass-navy-sheen:
    inset 0 1px 0 rgba(255, 255, 255, 0.22),
    inset 0 -22px 40px -28px rgba(232, 198, 106, 0.34);

  /* Reserved for small premium details only — never large areas */
  --gold-gradient: linear-gradient(
    135deg,
    #9a6a18 0%,
    #d4a62a 35%,
    #f3d47a 50%,
    #d4a62a 70%,
    #9a6a18 100%
  );

  /* Gradient rim: navy into gold */
  --rim: linear-gradient(
    150deg,
    rgba(11, 37, 80, 0.32) 0%,
    rgba(11, 37, 80, 0.12) 42%,
    rgba(212, 166, 42, 0.5) 100%
  );

  /* Motion — easings matched to the GSAP curves they are named after */
  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --out3: cubic-bezier(0.215, 0.61, 0.355, 1); /* power3.out */
  --expo: cubic-bezier(0.16, 1, 0.3, 1); /* expo.out */
  --inout4: cubic-bezier(0.77, 0, 0.175, 1); /* power4.inOut */
  --dur: 0.7s;

  /* Metrics */
  --section-pad: clamp(60px, 7vw, 104px);
  --nav-h: 72px;
  /* The bar runs full-bleed, so its own inset replaces the container's. Shared
     with the mobile menu panel so the two stay flush with each other. */
  --nav-pad: clamp(0px, 4vw, 48px);
  --radius: 12px;
  --radius-lg: 16px;
  --container: 1240px;
}

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

html {
  scroll-behavior: smooth;
  scroll-padding-top: var(--nav-h);
  -webkit-text-size-adjust: 100%;
  text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper-100);
  color: var(--text);
  font-family:
    "Lato",
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    Helvetica,
    Arial,
    sans-serif;
  font-size: 17px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden; /* belt-and-braces against horizontal scroll */
}

img {
  max-width: 100%;
  display: block;
}

/* Playfair for the headings — high-contrast, regal — with Lato carrying
   every small uppercase label, where a serif at wide tracking reads poorly. */
h1,
h2,
h3 {
  color: var(--ink);
  margin: 0;
  font-family: "Playfair Display", Georgia, "Times New Roman", serif;
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.12;
}
.eyebrow,
.benefits h3,
.info h3,
.footer__wordmark span,
.card__more,
.hscroll-hint,
.hero__eyebrow,
.banner__kicker {
  font-family:
    "Lato",
    -apple-system,
    BlinkMacSystemFont,
    "Segoe UI",
    Roboto,
    Helvetica,
    Arial,
    sans-serif;
}

p {
  margin: 0 0 1em;
}

ul,
ol,
dl {
  margin: 0;
  padding: 0;
  list-style: none;
}

a {
  color: inherit;
  text-decoration: none;
}

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

/* Button-like inputs. The UA stylesheet gives them their own font-family and
   `line-height: normal`, so .btn on an <input> renders about 8px shorter than
   the same class on a <button> or <a> — the gap Contact Form 7's submit showed.
   Only properties .btn leaves alone are listed here on purpose: an attribute
   selector is (0,1,1) and outranks .btn at (0,1,0), so setting font-size,
   color, background or border would override the button styling rather than
   complete it. Text inputs stay out of this entirely. */
input[type="submit"],
input[type="button"],
input[type="reset"] {
  font-family: inherit;
  line-height: inherit;
  cursor: pointer;
}
/* Scoped to .btn so an unstyled submit elsewhere keeps its native appearance */
input[type="submit"].btn,
input[type="button"].btn,
input[type="reset"].btn {
  -webkit-appearance: none;
  appearance: none;
}

svg {
  width: 100%;
  height: 100%;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.6;
  stroke-linecap: round;
  stroke-linejoin: round;
}

/* Visible, high-contrast focus for keyboard users */
:focus-visible {
  outline: 2px solid var(--gold-light);
  outline-offset: 3px;
  border-radius: 4px;
}

.skip-link {
  position: absolute;
  left: 16px;
  top: -100px;
  z-index: 200;
  padding: 12px 20px;
  background: var(--gold);
  color: var(--ink);
  font-weight: 700;
  border-radius: 0 0 10px 10px;
  transition: top 0.2s var(--ease);
}
.skip-link:focus {
  top: 0;
}

/* --------------------------------------------------------------------------
   3. Layout helpers and shared type
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(20px, 5vw, 48px);
}

.section {
  padding-block: var(--section-pad);
  position: relative;
}
/* Trailing margins on a section's last element would break the symmetry */
.section > *:last-child,
.section > *:last-child > *:last-child {
  margin-bottom: 0;
}

.gold {
  color: var(--gold);
}

.eyebrow {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-ink);
  margin-bottom: 18px;
}

/* Big Apple-style statement heading */
.display {
  font-size: clamp(2.3rem, 5.2vw, 4rem);
  letter-spacing: -0.018em;
  font-weight: 700;
  line-height: 1.14;
  margin-bottom: clamp(28px, 3.4vw, 46px);
}

/* The second line of a heading, in brand gold against the navy first line.
   --gold-strong rather than --gold: the brighter gold drops under 3:1 on
   cream, which large display text still has to clear. */
.display .gold {
  color: var(--gold-strong);
}

.lead {
  font-size: clamp(1.1rem, 1.6vw, 1.35rem);
  color: var(--ink);
  line-height: 1.5;
}

.rule {
  display: block;
  width: 64px;
  height: 2px;
  margin-bottom: 28px;
  background: linear-gradient(90deg, var(--gold-deep), rgba(154, 106, 24, 0));
}

.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  color: var(--gold);
  font-weight: 600;
}
.link-arrow svg {
  width: 20px;
  height: 20px;
  transition: transform 0.4s var(--ease);
}
.link-arrow:hover svg {
  transform: translateX(6px);
}

/* --------------------------------------------------------------------------
   3b. Ambient light
   Soft gold and azure blooms sit behind each dark section so the navy reads
   as lit rather than flat. `overflow: clip` rather than `hidden` keeps them off
   the page width without turning the section into a scroll container.
   -------------------------------------------------------------------------- */
.about,
.services,
.process,
.why,
.gallery,
.contact {
  position: relative;
  isolation: isolate;
  overflow: clip;
}

.about::before,
.services::before,
.process::before,
.why::before,
.gallery::before,
.contact::before {
  content: "";
  position: absolute;
  z-index: -1;
  pointer-events: none;
  inset: 0 -25% auto -25%;
  height: 82%;
  /* Fades the bloom before `overflow: clip` reaches it, so the section
     boundary never shows as a hard horizontal edge. */
  -webkit-mask-image: linear-gradient(
    180deg,
    transparent 0%,
    #000 22%,
    #000 62%,
    transparent 100%
  );
  mask-image: linear-gradient(
    180deg,
    transparent 0%,
    #000 22%,
    #000 62%,
    transparent 100%
  );
}

.about::before {
  background:
    radial-gradient(
      42% 58% at 22% 26%,
      rgba(17, 64, 127, 0.16),
      transparent 70%
    ),
    radial-gradient(
      38% 52% at 86% 6%,
      rgba(154, 106, 24, 0.16),
      transparent 70%
    );
}
.services::before {
  background:
    radial-gradient(
      40% 55% at 82% 20%,
      rgba(17, 64, 127, 0.14),
      transparent 72%
    ),
    radial-gradient(
      36% 48% at 14% 4%,
      rgba(212, 166, 42, 0.14),
      transparent 72%
    );
}
.process::before {
  background:
    radial-gradient(
      38% 52% at 50% 24%,
      rgba(212, 166, 42, 0.16),
      transparent 72%
    ),
    radial-gradient(34% 46% at 8% 8%, rgba(17, 64, 127, 0.13), transparent 72%);
}
.why::before {
  background: radial-gradient(
    44% 58% at 30% 18%,
    rgba(212, 166, 42, 0.15),
    transparent 72%
  );
}
.gallery::before {
  background:
    radial-gradient(
      40% 54% at 76% 12%,
      rgba(17, 64, 127, 0.15),
      transparent 72%
    ),
    radial-gradient(
      34% 46% at 18% 30%,
      rgba(212, 166, 42, 0.12),
      transparent 72%
    );
}
.contact::before {
  inset: auto -25% 0 -25%;
  background:
    radial-gradient(
      46% 60% at 50% 78%,
      rgba(212, 166, 42, 0.18),
      transparent 70%
    ),
    radial-gradient(
      40% 50% at 12% 40%,
      rgba(92, 134, 255, 0.16),
      transparent 72%
    );
}

/* --------------------------------------------------------------------------
   3c. Gradient rim
   A 1px gold-to-blue ring painted with a masked pseudo-element. Cheaper and
   crisper than a gradient border-image, and it follows border-radius.
   -------------------------------------------------------------------------- */
.card,
.info,
.benefits li,
.step {
  position: relative;
}

.card::after,
.benefits li::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  padding: 1px;
  background: var(--rim);
  -webkit-mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  mask:
    linear-gradient(#000 0 0) content-box,
    linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask-composite: exclude;
  opacity: 0.75;
  pointer-events: none;
  transition: opacity 0.55s var(--ease);
  z-index: 4;
}
.card:hover::after,
.card:focus-within::after,
.benefits li:hover::after {
  opacity: 1;
}

/* --------------------------------------------------------------------------
   4. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding: 15px 30px;
  border-radius: 999px;
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.01em;
  white-space: nowrap;
  border: 1px solid transparent;
  transition:
    transform 0.45s var(--ease),
    background-color 0.45s var(--ease),
    border-color 0.45s var(--ease),
    color 0.45s var(--ease),
    box-shadow 0.45s var(--ease);
  will-change: transform;
}
.btn--sm {
  padding: 10px 20px;
  font-size: 0.85rem;
}

.btn--gold {
  background: var(--gold);
  color: var(--blue-900);
  box-shadow: 0 10px 30px -14px rgba(154, 106, 24, 0.6);
}
.btn--gold:hover {
  background: var(--gold-light);
  transform: translateY(-2px);
  box-shadow: 0 18px 40px -16px rgba(154, 106, 24, 0.7);
  color: var(--blue-900);
}

.btn--ghost {
  border-color: var(--gold);
  color: var(--gold-strong);
  background: transparent;
  box-shadow: var(--glass-sheen);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
}
.btn--ghost:hover {
  border-color: var(--gold);
  color: var(--blue-900);
  transform: translateY(-2px);
  background: var(--gold);
}

.btn--navy {
  background: var(--navy-800);
  color: var(--white);
}
.btn--navy:hover {
  background: var(--navy-700);
  transform: translateY(-2px);
}

/* Slow, restrained sheen across the banner CTA */
.btn--shine {
  position: relative;
  overflow: hidden;
  isolation: isolate;
}
.btn--shine::after {
  content: "";
  position: absolute;
  inset: 0 auto 0 -60%;
  width: 45%;
  background: linear-gradient(
    100deg,
    transparent,
    rgba(255, 255, 255, 0.22),
    transparent
  );
  transform: skewX(-18deg);
  animation: shine 4.5s ease-in-out 1.2s infinite;
  z-index: -1;
}
@keyframes shine {
  0%,
  62% {
    left: -60%;
  }
  92%,
  100% {
    left: 130%;
  }
}

/* --------------------------------------------------------------------------
   5. Navigation
   -------------------------------------------------------------------------- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  padding: 12px 0;
  z-index: 100;
  /* The bar is light-on-dark at every scroll position, so it overrides the
     page's ink-on-white line colour locally. */
  --hairline: rgba(255, 255, 255, 0.14);
  color: var(--white);
  /* height: var(--nav-h); */
  transition:
    background-color 0.5s var(--ease),
    box-shadow 0.5s var(--ease),
    border-color 0.5s var(--ease),
    backdrop-filter 0.5s var(--ease),
    transform 0.45s var(--ease);
  border-bottom: 1px solid transparent;
}
/* Scrolling down tucks the bar away; scrolling up brings it straight back */
.nav.is-hidden {
  transform: translateY(-100%);
}
/* Before the bar goes frosted it sits straight on hero photography, so a soft
   scrim keeps the navy links legible over any slide. */
.nav::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  /* Taller than the bar itself so the fade finishes below it */
  height: calc(100% + 52px);
  z-index: -1;
  pointer-events: none;
  background: linear-gradient(
    180deg,
    rgba(6, 23, 47, 0.74) 0%,
    rgba(6, 23, 47, 0.42) 56%,
    rgba(6, 23, 47, 0) 100%
  );
  transition: opacity 0.5s var(--ease);
}
.nav.is-scrolled::before {
  opacity: 0;
}
.nav.is-scrolled {
  background: rgba(6, 23, 47, 0.97);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  backdrop-filter: blur(18px) saturate(150%);
}

/* Full-bleed: no container cap, so the brand sits hard left and the CTA hard
   right, with --nav-pad holding them off the viewport edge. */
.nav__inner {
  height: 100%;
  padding-inline: var(--nav-pad);
  display: flex;
  align-items: center;
  gap: 24px;
}

.nav__brand {
  display: flex;
  align-items: center;
  gap: 12px;
  margin-right: auto;
}
.nav__logo {
  width: 62px;
  height: 62px;
  object-fit: contain;
  flex: none;
  transition:
    width 0.45s var(--ease),
    height 0.45s var(--ease);
}
/* Only the mark shrinks on scroll — the bar height and wordmark hold still */
.nav.is-scrolled .nav__logo {
  width: 40px;
  height: 40px;
}
.nav__brand-text {
  display: flex;
  flex-direction: column;
  line-height: 1.1;
}
.nav__brand-text strong {
  color: var(--white);
  font-weight: 800;
  font-size: 1.05rem;
  letter-spacing: 0.04em;
}
.nav__brand-text span {
  font-size: 0.66rem;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold-light);
}

.nav__list {
  display: flex;
  align-items: center;
  gap: clamp(2px, 0.5vw, 8px);
}
/* Pill treatment rather than an underline: the active item gets a glass chip
   with a gold hairline, which stays distinct from the solid gold CTA. */
.nav__list a {
  display: block;
  font-size: 0.95rem;
  font-weight: 500;
  color: rgba(255, 255, 255, 0.84);
  padding: 5px 15px;
  border-radius: 999px;
  transition:
    color 0.35s var(--ease),
    background-color 0.35s var(--ease),
    box-shadow 0.35s var(--ease);
}
.nav__list a:hover {
  color: var(--white);
  background: rgba(255, 255, 255, 0.1);
}
.nav__list a.is-active {
  color: var(--gold-light);
  background: rgba(255, 255, 255, 0.1);
  box-shadow: inset 0 0 0 1px rgba(212, 166, 42, 0.5);
}

.nav__cta-mobile {
  display: none;
}

/* Hamburger */
.nav__toggle {
  display: none;
  width: 44px;
  height: 44px;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
}
.nav__bar {
  display: block;
  width: 22px;
  height: 2px;
  border-radius: 2px;
  background: var(--white);
  transition:
    transform 0.4s var(--ease),
    opacity 0.3s var(--ease);
}
.nav__toggle[aria-expanded="true"] .nav__bar:nth-child(1) {
  transform: translateY(7px) rotate(45deg);
}
.nav__toggle[aria-expanded="true"] .nav__bar:nth-child(2) {
  opacity: 0;
}
.nav__toggle[aria-expanded="true"] .nav__bar:nth-child(3) {
  transform: translateY(-7px) rotate(-45deg);
}

/* --------------------------------------------------------------------------
   6. Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  min-height: 100svh;
  overflow: hidden;
  isolation: isolate;
}

/* .swiper is declared later in this file at equal specificity, so the hero
   override has to outrank it rather than rely on source order. */
.hero .swiper.hero-swiper {
  width: 100%;
  height: 100svh;
  min-height: 560px;
  padding: 0;
}

.hero__slide {
  position: relative;
  display: flex;
  align-items: center;
  overflow: hidden;
}

/* Ken Burns: the active slide's photograph eases out of a 10% zoom over 7s */
.hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: -2;
  transform: scale(1.1);
  transition: transform 7000ms ease-out;
  will-change: transform;
}
.swiper-slide-active .hero__img {
  transform: scale(1);
}

.hero__scrim {
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Darkened only down the left, where the copy sits. Past ~62% the
     photograph is untouched, so the image carries the section. A dark scrim
     is used rather than a light one because it holds the photo's colour
     instead of bleaching it. */
  background:
    linear-gradient(
      100deg,
      rgba(6, 23, 47, 0.84) 0%,
      rgba(6, 23, 47, 0.66) 26%,
      rgba(6, 23, 47, 0.3) 46%,
      rgba(6, 23, 47, 0) 62%
    ),
    /* Just enough top and bottom weight to seat the nav and the dots */
    linear-gradient(
        180deg,
        rgba(6, 23, 47, 0.34) 0%,
        rgba(6, 23, 47, 0) 22%,
        rgba(6, 23, 47, 0) 76%,
        rgba(6, 23, 47, 0.42) 100%
      );
}

.hero__content {
  position: relative;
  width: 100%;
  text-align: left;
  padding-top: var(--nav-h);
  padding-bottom: 128px;
}
/* .hero__content > * {
  max-width: 30ch;
} */
.hero__content .hero__actions {
  max-width: none;
}

.hero__eyebrow {
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--gold-light);
  margin-bottom: 22px;
}

/* Only the first slide's title is an <h1>; the rest are <p> so the page keeps
   a single top-level heading. Naming the display face here means the serif no
   longer rides on the tag. */
.hero__title {
  font-family: "Playfair Display", Georgia, "Times New Roman", serif;
  font-size: clamp(2.4rem, 6.6vw, 5rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  line-height: 1.06;
  color: var(--white);
  margin: 0 0 24px;
  text-shadow: 0 18px 46px rgba(6, 23, 47, 0.55);
}
/* The bright gold reads correctly here — it is on a dark scrim, not on white */
.hero__title .gold {
  color: var(--gold-light);
}

.hero__sub {
  font-size: clamp(1.02rem, 1.6vw, 1.24rem);
  color: rgba(255, 255, 255, 0.82);
  max-width: 42ch;
  margin: 0 0 34px;
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: flex-start;
}
/* The page-level ghost button is ink-on-white; over the hero it has to flip */
.hero .btn--ghost {
  border-color: rgba(255, 255, 255, 0.42);
  color: var(--white);
  background: rgba(255, 255, 255, 0.08);
}
.hero .btn--ghost:hover {
  border-color: var(--gold-light);
  color: var(--gold-light);
}

/* Copy staggers in, but only once its slide becomes the active one */
.js .hero__slide .hero__eyebrow,
.js .hero__slide .hero__title,
.js .hero__slide .hero__sub,
.js .hero__slide .hero__actions {
  opacity: 0;
}
.js .swiper-slide-active .hero__eyebrow {
  animation: heroReveal 1.2s var(--expo) 0.35s forwards;
}
.js .swiper-slide-active .hero__title {
  animation: heroReveal 1.2s var(--expo) 0.5s forwards;
}
.js .swiper-slide-active .hero__sub {
  animation: heroReveal 1.2s var(--expo) 0.7s forwards;
}
.js .swiper-slide-active .hero__actions {
  animation: heroReveal 1.2s var(--expo) 0.85s forwards;
}
@keyframes heroReveal {
  from {
    opacity: 0;
    transform: translateY(22px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}

/* Pagination — a gold pill for the current slide */
/* Swiper's own `.swiper-horizontal > .swiper-pagination-bullets` sets left,
   width and bottom at (0,2,0), which outranks a bare `.hero__dots`. Scoping to
   `.hero` matches that specificity and, being later in the file, wins — without
   it the dots snap to Swiper's 8px bottom and slide off to the left. */
.hero .hero__dots {
  position: absolute;
  left: 50%;
  right: auto;
  bottom: 50px;
  transform: translateX(-50%);
  z-index: 3;
  /* Same box as .container, so the dots start where the headline does */
  width: 100%;
  max-width: var(--container);
  padding-inline: clamp(20px, 5vw, 48px);
  display: flex;
  justify-content: flex-start;
  gap: 9px;
}
.hero__dot {
  width: 11px;
  height: 11px;
  padding: 0;
  border-radius: 99px;
  border: 1.5px solid var(--gold);
  background: transparent;
  cursor: pointer;
  transition:
    width 0.4s var(--ease),
    background-color 0.4s var(--ease);
}
.hero__dot:hover {
  background: rgba(212, 166, 42, 0.35);
}
.hero__dot--active {
  width: 42px;
  background: var(--gold);
}

/* Hero on small screens: the left rail is the full column, and the scrim
   flips to a vertical wash since there is no side to keep clear. */
@media (max-width: 760px) {
  .hero__content > * {
    max-width: none;
  }
  .hero__scrim {
    background: linear-gradient(
      180deg,
      rgba(6, 23, 47, 0.62) 0%,
      rgba(6, 23, 47, 0.5) 42%,
      rgba(6, 23, 47, 0.72) 100%
    );
  }
}

/* --------------------------------------------------------------------------
   7. About
   -------------------------------------------------------------------------- */
.about {
  background: linear-gradient(180deg, var(--paper-100), var(--paper-50));
}

/* Full-bleed image that eases from slightly zoomed to true scale */
.about__stage {
  margin: 0 0 clamp(36px, 4.5vw, 64px);
  padding-inline: clamp(0px, 4vw, 48px);
  overflow: hidden;
}
.about__stage img {
  width: 100%;
  height: clamp(280px, 56vw, 620px);
  object-fit: cover;
  border-radius: clamp(0px, 1.2vw, var(--radius-lg));
  transform: scale(var(--scale, 1.12));
  will-change: transform;
  transition: transform 0.2s linear;
}

.about__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(36px, 5vw, 72px);
  align-items: center;
}

.about__copy p:last-of-type {
  margin-bottom: 26px;
}

/* Playfair italic set against a gold bar — gives the left column something
   to hold the eye, opposite the block of gold on the right. */
.about__pull {
  position: relative;
  margin: 28px 0;
  padding-left: clamp(20px, 2.4vw, 30px);
  font-family: "Playfair Display", Georgia, serif;
  font-style: italic;
  font-weight: 500;
  font-size: clamp(1.3rem, 2.1vw, 1.8rem);
  line-height: 1.34;
  letter-spacing: -0.01em;
  color: var(--blue-700);
}
.about__pull::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.18em;
  bottom: 0.18em;
  width: 3px;
  border-radius: 99px;
  background: linear-gradient(180deg, var(--gold-light), var(--gold-deep));
}

.about__stats {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(12px, 1.2vw, 18px);
}
/* Navy glass on the ivory band — see --glass-navy */
.about__stats > div {
  padding: 20px 20px 22px;
  border: 1px solid var(--glass-navy-border);
  border-radius: var(--radius);
  background: var(--glass-navy);
  /* No backdrop-filter here on purpose: both bands behind these cards are flat
     paper gradients, so there is nothing for a blur to pick up — the glass has
     to come from the layers above, not from the backdrop. */
  /* Flat at rest — the cast shadow is a hover-only cue, so the row of cards
     sits clean on the band. The inset sheen stays: that is the pane edge,
     not a drop shadow. */
  box-shadow: var(--glass-navy-sheen);
  transition:
    transform 0.45s var(--ease),
    box-shadow 0.45s var(--ease),
    border-color 0.45s var(--ease);
}
/* Hover tips the pane towards the light: brighter rim, deeper cast shadow */
.about__stats > div:hover {
  transform: translateY(-4px);
  border-color: rgba(255, 255, 255, 0.24);
  box-shadow:
    0 30px 58px -24px rgba(6, 23, 47, 0.92),
    inset 0 1px 0 rgba(255, 255, 255, 0.34),
    inset 0 -22px 40px -26px rgba(232, 198, 106, 0.48);
}
.about__stats dt {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 14px;
  font-size: clamp(1.2rem, 1.6vw, 1.42rem);
  font-weight: 700;
  color: var(--white);
  letter-spacing: -0.02em;
  line-height: 1.15;
}

.stat__icon {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--gold);
  color: var(--blue-900);
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.45);
}
.stat__icon svg {
  width: 18px;
  height: 18px;
}
.about__stats dd {
  margin: 6px 0 0;
  font-size: 0.86rem;
  line-height: 1.4;
  color: rgba(255, 255, 255, 0.72);
}

/* --------------------------------------------------------------------------
   8. Services cards
   -------------------------------------------------------------------------- */
/* White ground: the card photography is the colour here — see --paper-white */
.services {
  background: var(--paper-white);
}

.cards {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(18px, 2.2vw, 30px);
}

.card {
  position: relative;
  border-radius: var(--radius-lg);
  display: flex;
  min-height: clamp(330px, 32vw, 440px);
  overflow: hidden;
  /* The photograph is the card surface now, so the navy only shows while
     the image is still loading. */
  background: var(--blue-900);
  border: 0;
  box-shadow: 0 22px 50px -34px rgba(11, 37, 80, 0.6);
  transition:
    transform 0.6s var(--ease),
    border-color 0.6s var(--ease),
    box-shadow 0.6s var(--ease),
    background 0.6s var(--ease);
  /* No will-change here: it pins the card to its own compositor layer for the
     life of the page, and the reveal's rounded clip-path will not re-raster
     smoothly against a promoted layer — the wipe snaps instead of sweeping.
     The hover lift is a single translate and does not need the hint. */
}
.card:hover,
.card:focus-within {
  transform: translateY(-8px);
  border-color: var(--gold-hairline);
  box-shadow:
    0 36px 70px -34px rgba(11, 37, 80, 0.55),
    0 0 44px -20px rgba(212, 166, 42, 0.5);
}

/* The photograph now fills the whole card and sits under the copy */
.card__media {
  position: absolute;
  inset: 0;
  overflow: hidden;
}
/* Same dark scrim as the header — deepens the photograph and gives the
   card a defined foot instead of fading it into the body. */
.card__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(6, 23, 47, 0.3) 0%,
    rgba(6, 23, 47, 0.06) 32%,
    rgba(6, 23, 47, 0.72) 68%,
    rgba(6, 23, 47, 0.92) 100%
  );
  pointer-events: none;
}
.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transform: scale(1.01);
  transition: transform 0.85s var(--ease);
}
.card:hover .card__media img,
.card:focus-within .card__media img {
  transform: scale(1.08);
}

.card__body {
  position: relative;
  z-index: 2;
  margin-top: auto;
  width: 100%;
  padding: 26px 26px 28px;
}

.card__icon {
  position: static;
  width: 46px;
  height: 46px;
  margin-bottom: 16px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: linear-gradient(150deg, var(--navy-500), var(--navy-800));
  border: 1.5px solid var(--gold);
  color: var(--gold-light);
  box-shadow:
    0 10px 26px -14px rgba(6, 23, 47, 0.9),
    inset 0 1px 0 rgba(243, 212, 122, 0.35);
  transition:
    background 0.5s var(--ease),
    color 0.5s var(--ease),
    transform 0.5s var(--ease);
  z-index: 5;
}
.card__icon svg {
  width: 26px;
  height: 26px;
}
.card:hover .card__icon,
.card:focus-within .card__icon {
  background: var(--gold);
  color: var(--ink);
  transform: translateY(-3px);
}

.card__body h3 {
  font-size: 1.42rem;
  color: var(--white);
  margin-bottom: 6px;
}
.card__body p {
  font-size: 0.95rem;
  color: rgba(255, 255, 255, 0.82);
  margin-bottom: 16px;
}

.card__more {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-size: 0.85rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--gold-light);
}
.card__more::after {
  content: "";
  width: 16px;
  height: 1.5px;
  background: currentColor;
  transition: width 0.45s var(--ease);
}
.card:hover .card__more::after,
.card:focus-within .card__more::after {
  width: 30px;
}

/* --------------------------------------------------------------------------
   8b. How it works
   -------------------------------------------------------------------------- */
.process {
  background: linear-gradient(180deg, var(--paper-100), var(--paper-50));
}

.steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(16px, 2vw, 28px);
  padding-top: 38px;
}
/* Timeline rule the step markers sit on */
.steps::before {
  content: "";
  position: absolute;
  top: 5px;
  left: 4%;
  right: 4%;
  height: 1px;
  background: linear-gradient(
    90deg,
    transparent,
    var(--gold-hairline) 10%,
    var(--gold-hairline) 90%,
    transparent
  );
}

/* Same navy glass as the about stats */
.step {
  position: relative;
  padding: 32px 28px 30px;
  border: 1px solid var(--glass-navy-border);
  border-radius: var(--radius-lg);
  background: var(--glass-navy);
  /* Flat at rest — the cast shadow is a hover-only cue, so the row of cards
     sits clean on the band. The inset sheen stays: that is the pane edge,
     not a drop shadow. */
  box-shadow: var(--glass-navy-sheen);
  transition:
    transform 0.55s var(--ease),
    box-shadow 0.55s var(--ease),
    border-color 0.55s var(--ease);
}
.step:hover {
  transform: translateY(-6px);
  border-color: rgba(255, 255, 255, 0.24);
  box-shadow:
    0 32px 62px -24px rgba(6, 23, 47, 0.92),
    inset 0 1px 0 rgba(255, 255, 255, 0.34),
    inset 0 -22px 40px -26px rgba(232, 198, 106, 0.48);
}
.step::before {
  content: "";
  position: absolute;
  top: -38px;
  left: 30px;
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: var(--gold-deep);
  box-shadow: 0 0 0 5px rgba(154, 106, 24, 0.2);
}

.step__num {
  display: block;
  font-size: clamp(2.1rem, 3.4vw, 2.8rem);
  font-weight: 900;
  letter-spacing: -0.05em;
  line-height: 1;
  margin-bottom: 16px;
  color: var(--gold);
}
.step h3 {
  font-size: 1.14rem;
  color: var(--white);
  margin-bottom: 8px;
}
.step p {
  margin: 0;
  font-size: 0.95rem;
  color: rgba(255, 255, 255, 0.72);
}

/* --------------------------------------------------------------------------
   9. Why choose us
   -------------------------------------------------------------------------- */
.why {
  background: var(--paper-white);
}

/* `stretch` is what lets the photograph match the copy column: the row's height
   is set by the benefits list, and the figure fills it. */
.why__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  gap: clamp(36px, 6vw, 70px);
  align-items: stretch;
}

/* A plain grid so the figure inside stretches to the full column height */
.why__media {
  display: grid;
}
.why__figure {
  position: relative;
  margin: 0;
  height: 100%;
  /* Floor, for wide viewports where the copy column runs short */
  min-height: clamp(320px, 48vh, 560px);
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--gold-hairline);
}
/* Absolutely positioned, same reason as .tsl__figure img: this source is
   portrait (1:1.42), and an in-flow image contributes its natural height to
   the grid row — 762px against copy that only needs 576px, which stretched
   the copy column to match instead of the other way round. Out of flow it
   contributes nothing, so the copy sets the row height and the photo covers it. */
.why__figure img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.benefits {
  display: grid;
  gap: 14px;
  margin-top: 8px;
}
/* Tick in the left column, heading and copy stacked in the right. Two rows so
   the check can span both without needing a wrapper round the text. */
.benefits li {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  column-gap: clamp(14px, 1.4vw, 20px);
  align-items: start;
  padding: 26px 28px;
  border: 0;
  border-radius: var(--radius);
  background: var(--paper-white);
  transition:
    transform 0.55s var(--ease),
    background 0.55s var(--ease);
}
/* The gradient rim on .benefits li::after already draws the edge, so the white
   needs no border of its own — hover just warms the ground and slides it. */
.benefits li:hover {
  background: var(--paper-50);
  transform: translateX(6px);
}
.benefits__check {
  grid-row: 1 / 3;
  grid-column: 1;
  display: grid;
  place-items: center;
  width: 42px;
  height: 42px;
  border-radius: 50%;
  border: 0;
  background: var(--gold);
  color: var(--blue-900);
  box-shadow:
    0 10px 22px -14px rgba(154, 106, 24, 0.8),
    inset 0 1px 0 rgba(255, 255, 255, 0.45);
}
.benefits__check svg {
  width: 20px;
  height: 20px;
  stroke-width: 2.2;
}
.benefits h3 {
  grid-column: 2;
  margin-bottom: 5px;
  color: var(--gold-ink);
  text-transform: uppercase;
  font-size: 1rem;
  letter-spacing: 0.08em;
}
.benefits p {
  grid-column: 2;
  margin: 0;
  color: var(--text);
}

/* --------------------------------------------------------------------------
   10. Promotional banner — the dark band that anchors the light page
   -------------------------------------------------------------------------- */
.banner {
  /* Stays as the ground while the photograph loads, and shows through the
     overlay's lighter passages once it has. */
  background: linear-gradient(155deg, var(--blue-800), var(--blue-950));
  color: rgba(255, 255, 255, 0.78);
  padding-block: var(--section-pad);
  border-radius: clamp(12px, 1.4vw, 20px);
  margin-inline: clamp(0px, 3vw, 40px);
  position: relative;
  isolation: isolate;
  overflow: hidden;
}

/* Photograph layer, under the overlay */
.banner__media {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: inherit;
  overflow: hidden;
}
.banner__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 62%;
}

/* Overlay. The navy scrim moved up here from the section background so it sits
   on top of the photograph — the gold blooms keep the brand warmth, and the
   navy holds the white copy at ~6:1 even where the photo is blown out. */
.banner::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    radial-gradient(
      70% 110% at 84% 50%,
      rgba(212, 166, 42, 0.3),
      transparent 62%
    ),
    radial-gradient(
      50% 90% at 8% 20%,
      rgba(232, 198, 106, 0.16),
      transparent 66%
    ),
    linear-gradient(
      155deg,
      rgba(11, 37, 80, 0.82) 0%,
      rgba(6, 23, 47, 0.76) 45%,
      rgba(8, 10, 13, 0.86) 100%
    );
  pointer-events: none;
}

.banner__inner {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: minmax(0, 1.25fr) minmax(0, 0.75fr);
  gap: clamp(30px, 5vw, 70px);
  align-items: center;
}

.banner__kicker {
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 12px;
}
.banner__title {
  color: var(--white);
  font-size: clamp(1.95rem, 4.4vw, 3.2rem);
  font-weight: 700;
  letter-spacing: -0.015em;
  line-height: 1.1;
  margin-bottom: 30px;
}

.banner__aside {
  text-align: right;
  border-left: 1px solid var(--gold-hairline);
  padding-left: clamp(24px, 4vw, 56px);
}
.banner__script {
  display: block;
  font-family: "Playfair Display", Georgia, serif;
  font-size: clamp(2rem, 4.4vw, 3.2rem);
  font-weight: 600;
  line-height: 1.05;
  color: var(--gold-light);
  letter-spacing: -0.01em;
}
.banner__note {
  margin: 10px 0 0;
  font-size: 0.94rem;
  color: rgba(255, 255, 255, 0.66);
}

/* --------------------------------------------------------------------------
   11. Gallery
   -------------------------------------------------------------------------- */
/* White ground, same reasoning as .services — the carousel supplies the colour */
.gallery {
  background: var(--paper-white);
}

/* Swiper drives both strips. The slides are full-bleed, so the container
   pads its own edges and lets Swiper own the overflow. */
.swiper {
  width: 100%;
  padding-inline: clamp(20px, 5vw, 48px);
  padding-block: 4px;
}
.swiper-slide {
  height: auto; /* let flex stretch the testimonial cards to equal height */
}

/* Shared arrows + progress bar under each slider */
.slider-nav {
  display: flex;
  align-items: center;
  gap: 14px;
  margin-top: clamp(24px, 3vw, 38px);
}
.slider-nav__btn {
  flex: none;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur);
  backdrop-filter: var(--blur);
  color: var(--ink);
  box-shadow: var(--glass-sheen);
  transition:
    border-color 0.4s var(--ease),
    color 0.4s var(--ease),
    background 0.4s var(--ease),
    opacity 0.4s var(--ease);
}
.slider-nav__btn svg {
  width: 20px;
  height: 20px;
}
.slider-nav__btn:hover {
  border-color: var(--gold);
  color: var(--gold-ink);
  background: var(--glass-strong);
}
.slider-nav__btn.swiper-button-disabled {
  opacity: 0.35;
  pointer-events: none;
}

/* Swiper's scrollbar module, restyled as a slim gold progress rail */
.slider-nav__bar {
  position: relative;
  flex: 1;
  height: 3px;
  border-radius: 99px;
  background: rgba(11, 37, 80, 0.1);
  cursor: grab;
}
.slider-nav__bar .swiper-scrollbar-drag {
  background: linear-gradient(90deg, var(--gold-light), var(--gold));
  border-radius: 99px;
}

/* One slide per mosaic column: a wide feature, a full-height tile, or two
   stacked tiles. Heights come from a single row token so every column lines up. */
.gallery-swiper {
  --row: clamp(148px, 19vw, 258px);
  --col: clamp(172px, 21vw, 310px);
  --gap: clamp(10px, 1.1vw, 18px);
}
.gallery-swiper .swiper-wrapper {
  align-items: stretch;
}
.g-slide {
  width: var(--col);
  height: calc(var(--row) * 2 + var(--gap));
  margin-right: var(--gap);
}
.g-slide--feature {
  width: calc(var(--col) * 2 + var(--gap));
}
.g-slide--stack {
  display: grid;
  grid-template-rows: 1fr 1fr;
  gap: var(--gap);
}

.tile__btn {
  display: block;
  position: relative;
  width: 100%;
  height: 100%;
  padding: 0;
  overflow: hidden;
  border-radius: var(--radius);
}
.tile__btn img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.85s var(--ease);
}
.tile__btn::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    180deg,
    rgba(6, 23, 47, 0) 40%,
    rgba(6, 23, 47, 0.82)
  );
  opacity: 0;
  transition: opacity 0.55s var(--ease);
}
.tile__btn::before {
  content: "";
  position: absolute;
  inset: 0;
  border: 1.5px solid var(--gold);
  border-radius: inherit;
  opacity: 0;
  transition: opacity 0.55s var(--ease);
  z-index: 3;
  pointer-events: none;
}
.tile__label {
  position: absolute;
  left: 20px;
  bottom: 18px;
  z-index: 2;
  font-size: 0.82rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--gold-light);
  opacity: 0;
  transform: translateY(10px);
  transition:
    opacity 0.55s var(--ease),
    transform 0.55s var(--ease);
}
.tile__btn:hover img,
.tile__btn:focus-visible img {
  transform: scale(1.07);
}
.tile__btn:hover::after,
.tile__btn:focus-visible::after,
.tile__btn:hover::before,
.tile__btn:focus-visible::before {
  opacity: 1;
}
.tile__btn:hover .tile__label,
.tile__btn:focus-visible .tile__label {
  opacity: 1;
  transform: none;
}

/* --------------------------------------------------------------------------
   12. Testimonials — copy panel beside a full-bleed image
   -------------------------------------------------------------------------- */
.testimonials {
  background: linear-gradient(180deg, var(--paper-100), var(--paper-50) 40%);
}

.tsl {
  position: relative;
}
/* .swiper carries page-level padding; the panel bleeds to its own edges */
.tsl .swiper.tsl__swiper {
  padding: 0;
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.tsl__slide {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
  min-height: clamp(380px, 40vw, 540px);
  height: auto;
}

.tsl__copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 14px;
  padding: clamp(32px, 4vw, 64px);
  padding-bottom: clamp(84px, 8vw, 110px); /* clears the arrows */
  background: var(--paper-white);
}
.tsl__stars {
  margin: 0;
  color: var(--gold);
  letter-spacing: 0.22em;
  font-size: 1rem;
}
.tsl__headline {
  font-size: clamp(1.3rem, 2.2vw, 1.85rem);
  color: var(--ink);
  margin: 0;
}
.tsl__quote {
  margin: 0;
  font-size: clamp(1rem, 1.3vw, 1.1rem);
  line-height: 1.6;
  color: var(--text);
}
.tsl__by {
  display: flex;
  flex-direction: column;
  gap: 2px;
  margin: 6px 0 0;
}
.tsl__by strong {
  color: var(--ink);
  font-weight: 700;
}
.tsl__by span {
  font-size: 0.86rem;
  color: var(--text-dim);
}

/* The photo is absolutely positioned so a portrait source cannot stretch the
   row — the slide's own min-height decides how tall the panel is. */
.tsl__figure {
  position: relative;
  margin: 0;
  overflow: hidden;
  min-height: clamp(260px, 30vw, 420px);
}
.tsl__figure img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* Arrows sit over the foot of the copy panel */
.tsl__controls {
  position: absolute;
  left: clamp(32px, 4vw, 64px);
  bottom: clamp(28px, 3vw, 44px);
  z-index: 3;
  display: flex;
  gap: 10px;
}
.tsl__arrow {
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--blue-hairline);
  background: var(--paper-50);
  color: var(--ink);
  transition:
    background-color 0.35s var(--ease),
    color 0.35s var(--ease),
    border-color 0.35s var(--ease),
    transform 0.35s var(--ease);
}
.tsl__arrow svg {
  width: 20px;
  height: 20px;
}
.tsl__arrow:hover {
  border-color: var(--gold);
  color: var(--gold-ink);
  transform: translateY(-2px);
}
.tsl__arrow.swiper-button-disabled {
  opacity: 0.4;
  pointer-events: none;
}

/* --------------------------------------------------------------------------
   13. Contact
   -------------------------------------------------------------------------- */
.contact {
  background: linear-gradient(180deg, var(--paper-100), var(--paper-200));
  text-align: left;
  padding-bottom: 0;
}
.contact .display {
  margin-bottom: 18px;
}
.contact__lead {
  font-size: clamp(1.05rem, 1.8vw, 1.3rem);
  color: var(--text);
  margin-bottom: 36px;
}
.contact__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  justify-content: center;
  margin-bottom: clamp(38px, 4.6vw, 62px);
}

.contact__grid {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(14px, 1.8vw, 24px);
  text-align: left;
}
/* Solid gold blocks, the same treatment as the about stats */
.info {
  padding: 28px 26px;
  border: 0;
  border-radius: var(--radius);
  background: linear-gradient(
    140deg,
    var(--gold-light),
    var(--gold) 58%,
    #9a6a18
  );
  box-shadow:
    0 16px 36px -20px rgba(212, 166, 42, 0.85),
    inset 0 1px 0 rgba(255, 255, 255, 0.5);
  transition:
    transform 0.45s var(--ease),
    box-shadow 0.45s var(--ease);
}
.info:hover {
  transform: translateY(-4px);
  box-shadow:
    0 24px 46px -20px rgba(212, 166, 42, 0.9),
    inset 0 1px 0 rgba(255, 255, 255, 0.6);
}
.info__icon {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  margin-bottom: 18px;
  border-radius: 50%;
  background: linear-gradient(150deg, var(--blue-700), var(--blue-900));
  color: var(--gold-light);
  box-shadow: inset 0 1px 0 rgba(243, 212, 122, 0.3);
}
.info__icon svg {
  width: 21px;
  height: 21px;
}
.info h3 {
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(11, 37, 80, 0.62);
  margin-bottom: 8px;
}
.info a,
.info p {
  margin: 0;
  color: var(--ink);
  font-weight: 600;
  font-size: 1.02rem;
  line-height: 1.45;
  overflow-wrap: anywhere;
  transition: color 0.35s var(--ease);
}
.info a:hover {
  color: var(--blue-600);
  text-decoration: underline;
  text-underline-offset: 3px;
}

/* --------------------------------------------------------------------------
   14. Footer
   -------------------------------------------------------------------------- */
/* Minimal light footer. It no longer inverts the palette, so the local token
   overrides the dark version needed are gone — it inherits the page's own. */
.footer {
  background: var(--paper-50);
  border-top: 1px solid var(--hairline);
  color: var(--text);
}

/* Brand left, links centre, social right — one row that wraps to centred
   stacking on narrow screens. */
.footer__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: clamp(20px, 3vw, 40px);
  padding-block: clamp(28px, 3.4vw, 44px);
}

.footer__brand {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--ink);
}
.footer__brand img {
  width: 44px;
  height: 44px;
  object-fit: contain;
  flex: none;
}
.footer__wordmark {
  display: flex;
  flex-direction: column;
  line-height: 1.15;
}
.footer__wordmark strong {
  font-weight: 800;
  letter-spacing: 0.02em;
  color: var(--ink);
}
.footer__wordmark span {
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-ink);
}

.footer__nav {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(16px, 2.2vw, 32px);
}
.footer__nav a {
  font-size: 0.92rem;
  font-weight: 600;
  color: var(--ink-soft);
  transition: color 0.35s var(--ease);
}
.footer__nav a:hover {
  color: var(--gold-ink);
}

.social {
  display: flex;
  gap: 10px;
}
.social a {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  /* --gold-ink, not --gold: the signature gold only reaches 2.1:1 on ivory */
  color: var(--gold-ink);
  transition:
    border-color 0.4s var(--ease),
    background-color 0.4s var(--ease),
    transform 0.4s var(--ease);
}
.social a:hover {
  border-color: var(--gold-hairline);
  background: rgba(212, 166, 42, 0.12);
  transform: translateY(-3px);
}
.social a svg {
  width: 17px;
  height: 17px;
}
/* Facebook glyph is a solid shape, Instagram is drawn with strokes */
.social li:first-child svg {
  fill: currentColor;
  stroke: none;
}

.footer__base {
  border-top: 1px solid var(--hairline);
}
.footer__base .container {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 8px 24px;
  padding-block: 18px;
}
.footer__base p {
  margin: 0;
  font-size: 0.82rem;
  /* --text-dim lands at 4.25:1 on this ground, under the 4.5 floor for text
     this small; --ink-soft reads just as quiet and clears it. */
  color: var(--ink-soft);
}

/* --------------------------------------------------------------------------
   15. Lightbox
   -------------------------------------------------------------------------- */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(8px, 2vw, 28px);
  padding: clamp(16px, 4vw, 56px);
  background: rgba(6, 23, 47, 0.94);
  -webkit-backdrop-filter: blur(14px);
  backdrop-filter: blur(14px);
  opacity: 0;
  transition: opacity 0.4s var(--ease);
}
.lightbox[hidden] {
  display: none;
}
.lightbox.is-open {
  opacity: 1;
}

.lightbox__figure {
  margin: 0;
  max-width: min(1100px, 100%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  min-width: 0;
}
.lightbox__figure img {
  max-width: 100%;
  max-height: 78vh;
  width: auto;
  border-radius: var(--radius);
  border: 1px solid var(--gold-hairline);
  transform: scale(0.97);
  opacity: 0;
  transition:
    transform 0.5s var(--ease),
    opacity 0.5s var(--ease);
}
.lightbox.is-open .lightbox__figure img {
  transform: none;
  opacity: 1;
}
.lightbox__figure figcaption {
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--gold);
}

.lightbox__nav,
.lightbox__close {
  flex: none;
  width: 48px;
  height: 48px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  border: 1px solid var(--hairline);
  color: var(--white);
  background: rgba(255, 255, 255, 0.04);
  transition:
    border-color 0.35s var(--ease),
    color 0.35s var(--ease);
}
.lightbox__nav:hover,
.lightbox__close:hover {
  border-color: var(--gold);
  color: var(--gold);
}
.lightbox__nav svg,
.lightbox__close svg {
  width: 22px;
  height: 22px;
}
.lightbox__close {
  position: absolute;
  top: clamp(14px, 3vw, 30px);
  right: clamp(14px, 3vw, 30px);
  z-index: 2;
}

/* --------------------------------------------------------------------------
   16. Motion system
   Every start state is scoped to `html.js`. script.js adds that class, so a
   visitor without JS (or with a blocked script) gets the finished page rather
   than a blank one. `.is-in` is what plays each animation.
   -------------------------------------------------------------------------- */

/* One gesture for everything: the element rises out from behind its own
   bottom edge, exactly like a word rising out of its mask in a headline.
   `--clip-r` keeps rounded components round while they are clipped, and
   script.js adds `.is-done` afterwards so shadows and rims stop being cut. */
.js [data-reveal],
.js [data-stagger] > *,
.js [data-rule] {
  clip-path: inset(0 0 100% 0 round var(--clip-r, 0px));
  transform: translateY(12%);
}
[data-reveal].is-in,
[data-stagger].is-in > *,
[data-rule].is-in {
  clip-path: inset(0 0 0 0 round var(--clip-r, 0px));
  transform: none;
  transition:
    clip-path 1.05s var(--expo) var(--d, 0s),
    transform 1.05s var(--expo) var(--d, 0s);
}

/* Once the reveal has played, stop clipping altogether */
.is-done {
  clip-path: none !important;
}

/* Radii the clip has to respect while it is running */
.card,
.step,
.quote,
.why__figure {
  --clip-r: var(--radius-lg);
}
.info,
.benefits li,
.about__stats > div,
.tile {
  --clip-r: var(--radius);
}

/* Word-by-word headline reveal ------------------------------------------- */
.wm {
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
  /* Room for descenders, which the mask would otherwise crop */
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}
.js .wm > .w {
  display: inline-block;
  transform: translateY(112%);
}
.is-in .wm > .w {
  transform: none;
  transition: transform 1.1s var(--expo) var(--d, 0s);
}

/* Same gesture on the big plates, held longer, with the image counter-scaling
   so the frame settles into it rather than sliding with it. */
.js [data-mask] {
  clip-path: inset(0 0 100% 0 round var(--clip-r, 0px));
}
[data-mask].is-in {
  clip-path: inset(0 0 0 0 round var(--clip-r, 0px));
  transition: clip-path 1.35s var(--expo);
}
.js [data-mask] img {
  transform: scale(1.16);
}
[data-mask].is-in img {
  transform: none;
  transition: transform 1.7s var(--expo);
}

/* Plain fade — no clip-path, no travel, no stagger delay. Deliberately its own
   hook rather than data-mask so `[data-mask] img` never reaches the service
   card photographs and fights the hover zoom for the transform. */
.js [data-fade] {
  opacity: 0;
}
[data-fade].is-in {
  opacity: 1;
  transition: opacity 0.7s var(--ease);
}
/* `transition` is one property, so the rule above would replace .card's own
   list wholesale and leave the hover lift with nothing to animate. */
.card[data-fade].is-in {
  transition:
    opacity 0.7s var(--ease),
    transform 0.6s var(--ease),
    border-color 0.6s var(--ease),
    box-shadow 0.6s var(--ease),
    background 0.6s var(--ease);
}
.step[data-fade].is-in {
  transition:
    opacity 0.7s var(--ease),
    transform 0.55s var(--ease),
    box-shadow 0.55s var(--ease),
    border-color 0.55s var(--ease);
}
.about__stats > div[data-fade].is-in {
  transition:
    opacity 0.7s var(--ease),
    transform 0.45s var(--ease),
    box-shadow 0.45s var(--ease),
    border-color 0.45s var(--ease);
}

/* --------------------------------------------------------------------------
   17. Responsive
   -------------------------------------------------------------------------- */

/* Laptop / small desktop */
@media (max-width: 1100px) {
  .cards {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
  .steps {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    row-gap: 46px;
  }
  .contact__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

/* Tablet */
@media (max-width: 900px) {
  :root {
    --nav-h: 64px;
  }

  /* Collapse the primary menu into a slide-down panel */
  .nav__toggle {
    display: flex;
  }
  .nav__cta {
    display: none;
  }
  .nav__cta-mobile {
    display: inline-flex;
    align-self: flex-start;
  }

  .nav__menu {
    position: fixed;
    inset: var(--nav-h) 0 auto 0;
    display: flex;
    flex-direction: column;
    gap: 8px;
    padding: 26px var(--nav-pad) 34px;
    background: rgba(6, 23, 47, 0.96);
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
    border-bottom: 1px solid var(--gold-hairline);
    transform: translateY(-14px);
    opacity: 0;
    visibility: hidden;
    transition:
      opacity 0.4s var(--ease),
      transform 0.4s var(--ease),
      visibility 0.4s;
  }
  .nav__menu.is-open {
    opacity: 1;
    visibility: visible;
    transform: none;
  }
  .nav__list {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    margin-bottom: 18px;
  }
  .nav__list li + li {
    border-top: 1px solid var(--hairline);
  }
  .nav__list a {
    display: block;
    padding: 14px 0;
    font-size: 1.05rem;
  }
  .nav__list a::after {
    display: none;
  }

  /* Stacked content layouts */
  .about__grid,
  .why__grid,
  .banner__inner {
    grid-template-columns: minmax(0, 1fr);
  }
  .why__figure {
    height: clamp(260px, 48vw, 420px);
    min-height: 0;
  }
  .banner__aside {
    text-align: left;
    border-left: 0;
    border-top: 1px solid var(--gold-hairline);
    padding-left: 0;
    padding-top: 26px;
  }

  /* Only the first step keeps a marker once the row wraps */
  .steps::before {
    display: none;
  }
  .step::before {
    display: none;
  }
  .steps {
    padding-top: 0;
  }
}

/* Mobile */
@media (max-width: 640px) {
  body {
    font-size: 16px;
  }

  .cards,
  .steps,
  .about__stats {
    grid-template-columns: minmax(0, 1fr);
  }
  .steps {
    row-gap: 16px;
  }

  .contact__grid {
    grid-template-columns: minmax(0, 1fr);
  }
  .hero__actions .btn,
  .contact__actions .btn {
    flex: 1 1 100%;
  }

  .lightbox__nav {
    position: absolute;
    bottom: 20px;
    z-index: 2;
  }
  .lightbox__nav--prev {
    left: 22%;
  }
  .lightbox__nav--next {
    right: 22%;
  }
  .lightbox__figure img {
    max-height: 66vh;
  }
}

/* --------------------------------------------------------------------------
   18. Reduced motion
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
  }
  /* Reduced motion: render everything in its final state, no exceptions */
  [data-reveal],
  [data-stagger] > *,
  .wm > .w,
  [data-rule],
  [data-mask],
  [data-mask] img,
  [data-fade],
  .hero__eyebrow,
  .hero__title,
  .hero__sub,
  .hero__actions {
    opacity: 1 !important;
    transform: none !important;
    filter: none !important;
    animation: none !important;
  }
  .hero__img {
    transform: none !important;
  }
  [data-mask],
  [data-reveal],
  [data-stagger] > *,
  [data-rule],
  .hero__eyebrow,
  .hero__sub,
  .hero__actions {
    clip-path: none !important;
  }
}

/* --------------------------------------------------------------------------
   22. Contact Form 7 inside the quote modal
   CF7 wraps every control in .wpcf7-form-control-wrap and appends its own
   validation and response elements. These rules fold that extra markup into
   the .modal__form grid the static form used, so the styling above still
   applies unchanged.
   -------------------------------------------------------------------------- */
/* CF7 puts a wrapper between .field and the control, so the control is no
   longer the flex item that used to stretch to full width — hence the explicit
   widths below. min-width:0 lets the wrapper shrink past the input's intrinsic
   `size`, which otherwise pushes it out of the modal. */
.modal__form .wpcf7-form-control-wrap {
  display: block;
  width: 100%;
  min-width: 0;
}
.modal__form input[type="text"],
.modal__form input[type="tel"],
.modal__form input[type="email"],
.modal__form select,
.modal__form textarea {
  width: 100%;
  min-width: 0;
}
/* CF7 emits <p> wrappers when autop is on; the theme disables it for this
   form, so this is only a safety net if that filter is ever removed. */
.modal__form > p {
  margin: 0;
  grid-column: 1 / -1;
}
.modal__form .wpcf7-not-valid-tip {
  margin-top: 4px;
  font-size: 0.78rem;
  font-weight: 600;
  color: #a3271f;
}
.modal__form input.wpcf7-not-valid,
.modal__form select.wpcf7-not-valid,
.modal__form textarea.wpcf7-not-valid {
  border-color: #a3271f;
}
.modal__form .wpcf7-response-output {
  grid-column: 1 / -1;
  margin: 0;
  padding: 12px 16px;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  font-size: 0.9rem;
  line-height: 1.5;
  background: var(--paper-50);
  color: var(--ink);
}
/* CF7 colours these borders itself from .wpcf7 form.sent|invalid|failed, which
   out-specifies a two-class selector — hence the .modal__panel prefix. */
.modal__panel .modal__form.invalid .wpcf7-response-output,
.modal__panel .modal__form.unaccepted .wpcf7-response-output,
.modal__panel .modal__form.payment-required .wpcf7-response-output {
  border-color: rgba(212, 166, 42, 0.55);
  background: rgba(212, 166, 42, 0.08);
}
.modal__panel .modal__form.failed .wpcf7-response-output,
.modal__panel .modal__form.aborted .wpcf7-response-output,
.modal__panel .modal__form.spam .wpcf7-response-output {
  border-color: rgba(163, 39, 31, 0.45);
  background: rgba(163, 39, 31, 0.06);
}
.modal__panel .modal__form.sent .wpcf7-response-output {
  border-color: var(--gold-hairline);
  background: rgba(212, 166, 42, 0.12);
  color: var(--ink);
}
/* The spinner sits beside the submit button rather than pushing it around */
.modal__form .wpcf7-spinner {
  margin: 0 0 0 12px;
  align-self: center;
}
.modal__form .modal__actions {
  align-items: center;
}

/* --------------------------------------------------------------------------
   19. Floating WhatsApp button
   -------------------------------------------------------------------------- */
.wa-fab {
  position: fixed;
  right: clamp(16px, 2.4vw, 28px);
  bottom: clamp(16px, 2.4vw, 28px);
  z-index: 150;
  display: inline-flex;
  align-items: center;
  gap: 0;
  height: 56px;
  padding: 0 16px;
  border-radius: 999px;
  background: #25d366;
  color: #fff;
  box-shadow:
    0 14px 34px -12px rgba(37, 211, 102, 0.7),
    0 4px 12px rgba(6, 23, 47, 0.24);
  transition:
    transform 0.4s var(--ease),
    box-shadow 0.4s var(--ease),
    gap 0.4s var(--ease);
}
.wa-fab svg {
  width: 24px;
  height: 24px;
  flex: none;
  fill: currentColor;
  stroke: none;
}
/* The label is collapsed until hover, so the control stays out of the way */
.wa-fab__label {
  max-width: 0;
  overflow: hidden;
  white-space: nowrap;
  font-size: 0.9rem;
  font-weight: 700;
  opacity: 0;
  transition:
    max-width 0.45s var(--ease),
    opacity 0.35s var(--ease);
}
.wa-fab:hover,
.wa-fab:focus-visible {
  transform: translateY(-3px);
  gap: 10px;
}
.wa-fab:hover .wa-fab__label,
.wa-fab:focus-visible .wa-fab__label {
  max-width: 190px;
  opacity: 1;
}

/* --------------------------------------------------------------------------
   20. Enquiry modal
   -------------------------------------------------------------------------- */
.modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: grid;
  place-items: center;
  padding: clamp(16px, 4vw, 40px);
  background: rgba(6, 23, 47, 0.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
  overflow-y: auto;
}
.modal[hidden] {
  display: none;
}
.modal.is-open {
  opacity: 1;
}

.modal__panel {
  position: relative;
  width: min(600px, 100%);
  max-height: 100%;
  overflow-y: auto;
  padding: clamp(28px, 4vw, 44px);
  border-radius: var(--radius-lg);
  background: var(--paper-50);
  box-shadow: 0 40px 90px -40px rgba(6, 23, 47, 0.8);
  transform: translateY(14px) scale(0.985);
  transition: transform 0.4s var(--ease);
}
.modal.is-open .modal__panel {
  transform: none;
}

.modal__close {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  color: var(--ink);
  transition:
    background-color 0.3s var(--ease),
    color 0.3s var(--ease);
}
.modal__close svg {
  width: 20px;
  height: 20px;
}
.modal__close:hover {
  background: var(--paper-200);
  color: var(--gold-ink);
}

.modal__title {
  font-size: clamp(1.6rem, 3vw, 2.1rem);
  margin-bottom: 10px;
}
.modal__intro {
  color: var(--text);
  margin-bottom: 24px;
}

.modal__form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 16px;
}
.field {
  display: flex;
  flex-direction: column;
  gap: 7px;
  min-width: 0;
}
.field--full,
.modal__error,
.modal__actions,
.modal__note {
  grid-column: 1 / -1;
}
.field label {
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--text-dim);
}
.field label span {
  color: var(--gold-ink);
}
.field input,
.field select,
.field textarea {
  font: inherit;
  color: var(--ink);
  padding: 12px 14px;
  border: 1px solid var(--blue-hairline);
  border-radius: var(--radius);
  background: var(--paper-100);
  transition:
    border-color 0.3s var(--ease),
    background-color 0.3s var(--ease);
}
.field textarea {
  resize: vertical;
  min-height: 88px;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--gold);
  background: var(--white);
}
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--gold);
  outline-offset: 1px;
}
/* Flagged only after a failed submit, never while the visitor is still typing */
.field.is-invalid input {
  border-color: #c0392b;
  background: #fdf3f2;
}

.modal__error {
  margin: 0;
  font-size: 0.9rem;
  font-weight: 600;
  color: #c0392b;
}
.modal__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 4px;
}
.modal__note {
  margin: 0;
  font-size: 0.82rem;
  color: var(--text-dim);
}

@media (max-width: 560px) {
  .modal__form {
    grid-template-columns: minmax(0, 1fr);
  }
  .wa-fab {
    height: 52px;
    padding: 0 14px;
  }
  /* The WhatsApp button is fixed bottom-right and lands on the footer's last
     line once the page is scrolled to the end. Centre the base row and clear
     the button's height (52px) plus its 16px offset. */
  .footer__base .container {
    justify-content: center;
    text-align: center;
    padding-bottom: 80px;
  }
}

/* --------------------------------------------------------------------------
   21. Contact — service-area map beside a details panel
   -------------------------------------------------------------------------- */
/* Full-bleed band: an even split across the whole viewport, no container */
/* Copy left, map right. The source order matches, so tab order follows the
   layout and the iframe is the last thing focused in the section. */
.reach {
  /* Distance from the viewport edge to where .container's content starts, so
     the panel copy lines up with the heading above it. Below the container's
     max-width the two are the same value, and max() falls back to it. */
  --edge: max(
    clamp(20px, 5vw, 48px),
    calc((100vw - var(--container)) / 2 + clamp(20px, 5vw, 48px))
  );
  display: grid;
  grid-template-columns: 1fr 1fr;
  width: 100%;
}

.reach__map {
  position: relative;
  min-height: clamp(340px, 38vw, 560px);
  background: var(--paper-200);
}
.reach__map iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
  /* Desaturated so the map sits under the brand rather than fighting it */
  filter: grayscale(1) contrast(1.04) brightness(1.02);
}

.reach__card {
  position: absolute;
  top: clamp(18px, 2.4vw, 36px);
  left: clamp(18px, 2.4vw, 36px);
  max-width: 240px;
  padding: 20px 22px 22px;
  border-radius: var(--radius);
  background: var(--paper-50);
  box-shadow: 0 18px 40px -20px rgba(6, 23, 47, 0.5);
}
.reach__card-title {
  margin: 0 0 2px;
  font-size: 0.74rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--gold-ink);
}
.reach__card-sub {
  margin: 0 0 14px;
  font-weight: 700;
  color: var(--ink);
}

.reach__panel {
  display: flex;
  align-items: center;
  padding: clamp(36px, 5vw, 80px) clamp(24px, 5vw, 64px) clamp(36px, 5vw, 80px)
    var(--edge);
  background: linear-gradient(155deg, var(--blue-800), var(--blue-950));
  color: rgba(255, 255, 255, 0.78);
  text-align: left;
}
/* Caps the measure so the copy does not stretch across half of a 1920 screen */
.reach__panel-inner {
  display: flex;
  flex-direction: column;
  gap: 22px;
  width: 100%;
  max-width: 460px;
}
.reach__title {
  margin: 0;
  font-size: clamp(1.7rem, 2.8vw, 2.5rem);
  letter-spacing: 0.06em;

  color: var(--white);
}
.reach__lines {
  font-style: normal;
  display: grid;
  gap: 16px;
}
.reach__lines p {
  margin: 0;
  line-height: 1.6;
}
.reach__lines a {
  transition: color 0.3s var(--ease);
}
.reach__lines a:hover {
  color: var(--gold-light);
}
.reach__abn {
  font-size: 0.86rem;
  color: rgba(255, 255, 255, 0.5);
}

.reach__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
/* The page ghost button is ink-on-white; on the dark panel it has to flip */
.btn--on-dark {
  border-color: rgba(255, 255, 255, 0.34);
  color: var(--white);
  background: rgba(255, 255, 255, 0.06);
}
.btn--on-dark:hover {
  border-color: var(--gold-light);
  color: var(--gold-light);
}

.reach__social {
  display: flex;
  gap: 12px;
}
.reach__social a {
  display: grid;
  place-items: center;
  border-radius: 50%;
  width: 46px;
  height: 46px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  color: var(--gold-light);
  transition:
    border-color 0.35s var(--ease),
    background-color 0.35s var(--ease);
}
.reach__social a:hover {
  border-color: var(--gold);
  background: rgba(212, 166, 42, 0.12);
}
.reach__social svg {
  width: 19px;
  height: 19px;
}
.reach__social li:first-child svg {
  fill: currentColor;
  stroke: none;
}

@media (max-width: 900px) {
  .reach,
  .tsl__slide {
    grid-template-columns: minmax(0, 1fr);
  }
  .reach__panel-inner {
    max-width: none;
  }
  /* Image first on narrow screens, copy beneath it */
  .tsl__figure {
    order: -1;
  }
  .tsl__figure img {
    min-height: clamp(220px, 46vw, 320px);
  }
  .reach__panel {
    text-align: left;
  }
}

.modal__actions {
  position: relative;
}

.wpcf7-spinner {
  position: absolute;
  bottom: -27px;
}
