/* ==========================================================================
   Eyes Pixel Photography Studio — Design System
   Pune, Maharashtra
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. Design tokens
   -------------------------------------------------------------------------- */
:root {
  /* Brand — sampled from the Eyes Pixel logo */
  --primary: #ff6903;          /* logo orange — accents, icons, rules */
  --primary-dark: #c24c00;     /* accessible orange for text on light (5.0:1) */
  --primary-soft: #fff2e8;     /* warm tint surface */
  --secondary: #0398cc;        /* logo blue */
  --secondary-dark: #026b91;   /* accessible blue for text on light */
  --accent: #12100e;           /* ink — primary buttons, headings */

  /* Neutrals — warm greys to sit with the orange */
  --ink: #12100e;
  --text: #2f2b27;
  --text-muted: #6d665e;
  --background: #ffffff;
  --surface: #faf8f6;
  --surface-2: #f2eeea;
  --border: #e7e1da;
  --border-strong: #d6cec5;
  --inverse-text: #f7f5f3;
  --inverse-muted: #a9a29a;
  --card: #ffffff;             /* raised panels: cards, inputs, header, menus */
  /* The header is dark in BOTH themes: the Eyes Pixel logo has light-grey
     "Photography" lettering that disappears on a white bar. */
  --header-bg: #14110f;
  --header-blur: rgba(20, 17, 15, 0.86);
  --header-text: #e6e1db;
  --header-strong: #ffffff;
  --header-border: rgba(255, 255, 255, 0.13);
  --header-hover: rgba(255, 255, 255, 0.09);
  --footer-bg: #0d0b0a;
  --hero-overlay-a: rgba(12, 10, 9, 0.92);
  --hero-overlay-b: rgba(12, 10, 9, 0.78);
  --hero-overlay-c: rgba(12, 10, 9, 0.45);
  color-scheme: light;
  /* Typography */
  --font-sans: Inter, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI",
    Roboto, "Helvetica Neue", Arial, sans-serif;
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;

  /* Fluid type scale */
  --fs-xs: 0.8125rem;
  --fs-sm: 0.9375rem;
  --fs-base: 1.0625rem;
  --fs-lg: clamp(1.125rem, 0.5vw + 1rem, 1.25rem);
  --fs-h3: clamp(1.25rem, 0.8vw + 1.05rem, 1.5rem);
  --fs-h2: clamp(1.75rem, 2vw + 1.15rem, 2.75rem);
  --fs-h1: clamp(2.25rem, 4vw + 1.1rem, 4rem);

  /* Spacing */
  --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);

  /* Shape + depth (used sparingly) */
  --radius: 4px;
  --radius-lg: 8px;
  --shadow-sm: 0 1px 2px rgba(18, 16, 14, 0.06);
  --shadow: 0 8px 28px -12px rgba(18, 16, 14, 0.18);

  --container: 1200px;
  --header-h: 72px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
}


/* --------------------------------------------------------------------------
   1b. Dark theme
   Applied by the inline bootstrap script in <head>, which resolves the
   saved preference (or the OS setting) before first paint — so there is no
   flash of the wrong theme. Only surface/text tokens change; the brand
   orange and blue stay exactly the same, shifted only where contrast
   against a dark background requires it.
   -------------------------------------------------------------------------- */
[data-theme="dark"] {
  --primary: #ff7a1f;
  --primary-dark: #ff9c52;     /* lighter, for text on dark (7.1:1) */
  --primary-soft: #2a1a0d;
  --secondary: #35b6e8;
  --secondary-dark: #5cc8f2;   /* lighter, for links on dark (7.6:1) */
  --accent: #f7f5f3;

  --ink: #f6f3f0;              /* headings */
  --text: #ddd6ce;
  --text-muted: #a19a91;
  --background: #100e0d;
  --surface: #171413;
  --surface-2: #221e1c;
  --border: #2f2926;
  --border-strong: #423b36;
  --card: #191615;
  --header-bg: #0e0c0b;
  --header-blur: rgba(14, 12, 11, 0.86);
  --footer-bg: #0a0908;

  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.5);
  --shadow: 0 10px 30px -12px rgba(0, 0, 0, 0.75);
  color-scheme: dark;
}

/* Panels that were "ink on light" need to separate from a dark page */
[data-theme="dark"] .section--ink { background: #070606; }
[data-theme="dark"] .cta-band { background: #070606; }
[data-theme="dark"] .btn--primary { background: var(--primary); color: #150c04; }
[data-theme="dark"] .btn--primary:hover { background: var(--primary-dark); color: #150c04; }
[data-theme="dark"] .btn--outline { color: var(--ink); }
[data-theme="dark"] .btn--outline:hover { border-color: var(--border-strong); }
[data-theme="dark"] .btn--accent { color: #150c04; }
[data-theme="dark"] .btn--accent:hover { color: #150c04; }
[data-theme="dark"] .skip-link { background: var(--primary); color: #150c04; }
[data-theme="dark"] .skip-link:focus { color: #150c04; }
[data-theme="dark"] ::selection { background: var(--primary); color: #150c04; }
[data-theme="dark"] .site-header.is-stuck { box-shadow: 0 1px 0 var(--header-border); }
/* --ink flips to a light tone in dark mode, so anything that used it as a
   BACKGROUND needs restating rather than inheriting an unreadable pairing. */
[data-theme="dark"] .filter[aria-pressed="true"] {
  background: var(--primary);
  border-color: var(--primary);
  color: #150c04;
}
[data-theme="dark"] .card__icon { background: var(--primary-soft); color: var(--primary-dark); }
[data-theme="dark"] .btn--ghost-light:hover { background: #fff; color: #150c04; }
[data-theme="dark"] .hero__media::after {
  background: linear-gradient(100deg,
    rgba(6, 5, 5, 0.94) 0%, rgba(6, 5, 5, 0.82) 42%, rgba(6, 5, 5, 0.5) 100%);
}


/* --------------------------------------------------------------------------
   2. Reset / base
   -------------------------------------------------------------------------- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + 1rem);
}

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: var(--fs-base);
  line-height: 1.65;
  color: var(--text);
  background: var(--background);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* `clip`, not `hidden`: both stop sideways overflow, but `hidden` forces the
     other axis to `auto`, turning <body> into a scroll container — which
     silently breaks `position: sticky` for every descendant. `clip` leaves
     overflow-y visible, so the viewport stays the scrollport.
     `hidden` first as the fallback: a browser without `clip` (Safari < 16)
     drops that declaration and keeps `hidden`, so sideways overflow is still
     contained. Without this pair those browsers get horizontal page scroll. */
  overflow-x: hidden;
  overflow-x: clip;
}

img,
picture,
svg,
video { display: block; max-width: 100%; height: auto; }

h1, h2, h3, h4 {
  margin: 0 0 var(--sp-4);
  color: var(--ink);
  font-weight: 650;
  line-height: 1.15;
  letter-spacing: -0.021em;
  text-wrap: balance;
}

h1 { font-size: var(--fs-h1); letter-spacing: -0.032em; }
h2 { font-size: var(--fs-h2); letter-spacing: -0.026em; }
h3 { font-size: var(--fs-h3); }
h4 { font-size: var(--fs-lg); }

p { margin: 0 0 var(--sp-4); text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

a { color: var(--secondary-dark); text-decoration-thickness: 1px; text-underline-offset: 3px; }
a:hover { color: var(--primary-dark); }

ul, ol { margin: 0 0 var(--sp-4); padding-left: 1.15rem; }

address { font-style: normal; }

hr { border: 0; border-top: 1px solid var(--border); margin: var(--sp-6) 0; }

:focus-visible {
  outline: 2px solid var(--secondary-dark);
  outline-offset: 3px;
  border-radius: 2px;
}

::selection { background: var(--primary); color: #fff; }

/* --------------------------------------------------------------------------
   3. Layout helpers
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--sp-5);
}
.container--narrow { max-width: 780px; }

.section { padding-block: var(--section-y); }
.section--surface { background: var(--surface); }
.section--tint { background: var(--primary-soft); }
.section--ink { background: var(--ink); color: var(--inverse-text); }
.section--ink h2,
.section--ink h3 { color: #fff; }

.skip-link {
  position: absolute;
  left: var(--sp-4);
  top: -100px;
  z-index: 200;
  padding: var(--sp-3) var(--sp-5);
  background: var(--ink);
  color: #fff;
  border-radius: var(--radius);
  text-decoration: none;
  transition: top 0.2s var(--ease);
}
.skip-link:focus { top: var(--sp-4); color: #fff; }

.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* Section heading block */
.section-heading { max-width: 660px; margin-bottom: var(--sp-7); }
.section-heading--center { margin-inline: auto; text-align: center; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  margin-bottom: var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--primary-dark);
}
.eyebrow::before {
  content: "";
  width: 26px;
  height: 2px;
  background: var(--primary);
}
.section-heading--center .eyebrow::before { display: none; }

.section-heading p {
  font-size: var(--fs-lg);
  color: var(--text-muted);
  margin-bottom: 0;
}

.lead { font-size: var(--fs-lg); color: var(--text-muted); }

/* --------------------------------------------------------------------------
   4. Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5em;
  min-height: 48px;
  padding: 0.75rem 1.5rem;
  border: 1px solid transparent;
  border-radius: var(--radius);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: 0.01em;
  text-decoration: none;
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease),
    border-color 0.2s var(--ease), transform 0.2s var(--ease);
}
.btn:active { transform: translateY(1px); }
.btn svg { width: 18px; height: 18px; flex: none; }

.btn--primary { background: var(--ink); color: #fff; }
.btn--primary:hover { background: #2c2723; color: #fff; }

.btn--accent { background: var(--primary); color: #fff; }
.btn--accent:hover { background: var(--primary-dark); color: #fff; }

.btn--outline {
  background: transparent;
  color: var(--ink);
  border-color: var(--border-strong);
}
.btn--outline:hover { background: var(--surface-2); color: var(--ink); border-color: var(--ink); }

.btn--ghost-light {
  background: rgba(255, 255, 255, 0.1);
  color: #fff;
  border-color: rgba(255, 255, 255, 0.45);
  backdrop-filter: blur(6px);
}
.btn--ghost-light:hover { background: rgba(255, 255, 255, 0.95); color: var(--ink); border-color: #fff; }

.btn--wide { width: 100%; }

.btn-row { display: flex; flex-wrap: wrap; gap: var(--sp-3); }

/* Text link with arrow */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--primary-dark);
  text-decoration: none;
}
.link-arrow::after {
  content: "";
  width: 14px; height: 14px;
  background: currentColor;
  -webkit-mask: var(--icon-arrow) center / contain no-repeat;
  mask: var(--icon-arrow) center / contain no-repeat;
  transition: transform 0.2s var(--ease);
}
.link-arrow:hover::after { transform: translateX(3px); }
:root {
  --icon-arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14M13 6l6 6-6 6'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   5. Header
   -------------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: var(--header-bg);
  border-bottom: 1px solid transparent;
  transition: border-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.site-header.is-stuck { border-bottom-color: var(--header-border); }

/* The frosted header is desktop-only on purpose: backdrop-filter creates a
   containing block for descendants, which would trap the fixed mobile nav
   panel inside the header box. */
@media (min-width: 1024px) {
  .site-header {
    background: var(--header-blur);
    backdrop-filter: saturate(180%) blur(14px);
    -webkit-backdrop-filter: saturate(180%) blur(14px);
  }
}
.site-header.is-stuck {
  border-bottom-color: var(--border);
  box-shadow: var(--shadow-sm);
}

.site-header__inner {
  display: flex;
  align-items: center;
  gap: var(--sp-5);
  min-height: var(--header-h);
}

.brand { flex: none; line-height: 0; }
.brand img { width: 168px; height: 39px; }

.nav { margin-left: auto; }
.nav__list {
  display: flex;
  align-items: center;
  gap: var(--sp-1);
  margin: 0;
  padding: 0;
  list-style: none;
}
.nav__link {
  display: block;
  padding: 0.55rem 0.8rem;
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  font-weight: 550;
  color: var(--header-text);
  text-decoration: none;
  white-space: nowrap;
  transition: color 0.18s var(--ease), background-color 0.18s var(--ease);
}
.nav__link:hover { color: var(--header-strong); background: var(--header-hover); }
.nav__link[aria-current="page"] { color: #ff9c52; }

/* Services dropdown */
.nav__item--has-menu { position: relative; }
.nav__toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.35em;
  border: 0;
  background: none;
  font: inherit;
  cursor: pointer;
}
.nav__toggle::after {
  content: "";
  width: 9px; height: 9px;
  border-right: 1.8px solid currentColor;
  border-bottom: 1.8px solid currentColor;
  transform: translateY(-2px) rotate(45deg);
  transition: transform 0.2s var(--ease);
}
.nav__toggle[aria-expanded="true"]::after { transform: translateY(1px) rotate(-135deg); }

.mega {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  width: min(760px, calc(100vw - 3rem));
  padding: var(--sp-5);
  background: var(--header-bg);
  border: 1px solid var(--header-border);
  border-radius: var(--radius-lg);
  box-shadow: 0 18px 44px -20px rgba(0, 0, 0, 0.75);
  opacity: 0;
  visibility: hidden;
  transform: translateY(-6px);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease), visibility 0.18s;
}
.nav__toggle[aria-expanded="true"] + .mega {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.mega__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-1) var(--sp-5);
  margin: 0;
  padding: 0;
  list-style: none;
}
.mega__link {
  display: block;
  padding: 0.45rem 0.55rem;
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  color: var(--text);
  text-decoration: none;
}
.mega__link { color: var(--header-text); }
.mega__link:hover { background: var(--header-hover); color: #ff9c52; }
.mega .eyebrow { color: #ff9c52; }
.mega__foot {
  margin-top: var(--sp-4);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--header-border);
}

.header__cta { display: none; flex: none; }
/* The ink button would vanish against the dark bar, so the header CTA is
   always the brand orange. */
.header__cta .btn--primary,
.nav__cta .btn--accent { background: var(--primary); color: #ffffff; }
.header__cta .btn--primary:hover { background: #ff8a3d; color: #150c04; }
.nav__cta .btn--outline { color: var(--header-text); border-color: var(--header-border); }
.nav__cta .btn--outline:hover { background: var(--header-hover); color: var(--header-strong); }

/* --- Day / night switcher ------------------------------------------------ */
.theme-toggle {
  display: inline-grid;
  place-items: center;
  flex: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--header-border);
  border-radius: var(--radius);
  background: transparent;
  color: var(--header-text);
  cursor: pointer;
  transition: background-color 0.2s var(--ease), color 0.2s var(--ease),
    border-color 0.2s var(--ease);
}
.theme-toggle:hover { background: var(--header-hover); color: var(--header-strong); border-color: rgba(255,255,255,.3); }
.theme-toggle svg { width: 19px; height: 19px; grid-area: 1 / 1; transition: opacity 0.25s var(--ease), transform 0.35s var(--ease); }

/* Show the icon for the theme you would switch TO */
.theme-toggle .icon-moon { opacity: 1; transform: none; }
.theme-toggle .icon-sun { opacity: 0; transform: rotate(-90deg) scale(0.6); }
[data-theme="dark"] .theme-toggle .icon-moon { opacity: 0; transform: rotate(90deg) scale(0.6); }
[data-theme="dark"] .theme-toggle .icon-sun { opacity: 1; transform: none; color: var(--primary); }

/* On mobile the switcher sits next to the hamburger, outside the panel */
.header__tools { display: flex; align-items: center; gap: var(--sp-2); margin-left: auto; }
@media (min-width: 1024px) { .header__tools { margin-left: 0; } }

.hamburger {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  width: 44px; height: 44px;
  padding: 0 10px;
  border: 0;
  background: none;
  cursor: pointer;
}
.hamburger span {
  display: block;
  height: 2px;
  background: var(--header-strong);
  border-radius: 2px;
  transition: transform 0.25s var(--ease), opacity 0.2s var(--ease);
}
.hamburger[aria-expanded="true"] span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.hamburger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.hamburger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Mobile nav panel */
@media (max-width: 1023px) {
  .nav {
    position: fixed;
    inset: var(--header-h) 0 0;
    display: block;
    margin: 0;
    padding: var(--sp-5) var(--sp-5) 6rem;
    background: var(--header-bg);
    overflow-y: auto;
    opacity: 0;
    visibility: hidden;
    transform: translateY(-8px);
    transition: opacity 0.22s var(--ease), transform 0.22s var(--ease), visibility 0.22s;
  }
  .nav.is-open { opacity: 1; visibility: visible; transform: none; }
  .nav__list { display: block; }
  .nav__link,
  .nav__toggle {
    width: 100%;
    padding: 0.85rem 0.25rem;
    border-bottom: 1px solid var(--header-border);
    border-radius: 0;
    font-size: 1.0625rem;
    text-align: left;
  }
  .nav__toggle { justify-content: space-between; }
  .mega {
    position: static;
    width: auto;
    padding: var(--sp-2) 0 var(--sp-4);
    border: 0;
    box-shadow: none;
    border-radius: 0;
    display: none;
    opacity: 1;
    visibility: visible;
    transform: none;
  }
  .nav__toggle[aria-expanded="true"] + .mega { display: block; }
  .mega__grid { grid-template-columns: 1fr 1fr; }
  .mega__link { padding: 0.5rem 0.25rem; }
  .nav__cta { margin-top: var(--sp-5); display: grid; gap: var(--sp-3); }
}

@media (min-width: 1024px) {
  .hamburger { display: none; }
  .header__cta { display: block; }
  .nav__cta { display: none; }
  .nav { margin-left: auto; }
  .site-header__inner { gap: var(--sp-4); }
}

/* --------------------------------------------------------------------------
   6. Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  display: grid;
  align-items: center;
  min-height: min(80vh, 760px);
  /* extra bottom room so the scroll cue and slider dots clear the trust chips */
  padding-block: clamp(3rem, 8vw, 6rem) clamp(5rem, 10vw, 8rem);
  background: var(--ink);
  color: var(--inverse-text);
  overflow: hidden;
}
.hero__media {
  position: absolute;
  inset: 0;
  z-index: 0;
}
.hero__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 35%;
}

/* --- Hero slider (crossfade, 7 slides, vanilla JS) ---------------------- */
.slider__track {
  position: absolute;
  inset: 0;
}
.slider__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 1.1s var(--ease);
  will-change: opacity;
}
.slider__slide.is-active { opacity: 1; }
.slider__slide img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 40%;
}
/* Slow drift on the active slide — the old site's Ken Burns feel, but cheap.
   Duration is tied to the 6s slide interval in main.js (plus the 1.1s
   crossfade): a longer animation gets cut off mid-move and visibly snaps
   back when the next slide takes over. */
.slider__slide.is-active img { animation: ep-drift 7.1s var(--ease) forwards; }
@keyframes ep-drift {
  from { transform: scale(1.005); }
  to   { transform: scale(1.055); }
}

/* Controls sit below the hero copy, above the overlay */
.slider__ui {
  position: absolute;
  right: clamp(1rem, 4vw, 3rem);
  bottom: clamp(1rem, 4vw, 2.5rem);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}
.slider__dots { display: flex; gap: 9px; margin: 0; padding: 0; list-style: none; }
.slider__dot {
  width: 30px;
  height: 4px;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.32);
  cursor: pointer;
  transition: background-color 0.3s var(--ease), transform 0.3s var(--ease);
}
.slider__dot:hover { background: rgba(255, 255, 255, 0.6); }
.slider__dot[aria-current="true"] { background: var(--primary); transform: scaleY(1.6); }

.slider__play {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, 0.32);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.28);
  color: #fff;
  cursor: pointer;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.slider__play:hover { background: rgba(0, 0, 0, 0.55); border-color: #fff; }
.slider__play svg { width: 14px; height: 14px; }
.slider__play .icon-pause { display: block; }
.slider__play .icon-play { display: none; }
.slider__play[aria-pressed="true"] .icon-pause { display: none; }
.slider__play[aria-pressed="true"] .icon-play { display: block; }

@media (max-width: 640px) {
  .slider__ui { left: var(--sp-5); right: auto; }
  .slider__dot { width: 22px; }
}

/* No motion: show the first slide only, no fading, no drift, no autoplay */
@media (prefers-reduced-motion: reduce) {
  .slider__slide { transition: none; }
  .slider__slide.is-active img { animation: none; }
}
.hero__media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(
    100deg,
    rgba(12, 10, 9, 0.92) 0%,
    rgba(12, 10, 9, 0.78) 42%,
    rgba(12, 10, 9, 0.45) 100%
  );
}
.hero__inner { position: relative; z-index: 1; max-width: 720px; }
.hero h1 { color: #fff; margin-bottom: var(--sp-5); }
.hero .eyebrow { color: #ffb27a; }
.hero .eyebrow::before { background: var(--primary); }
.hero__text {
  font-size: var(--fs-lg);
  color: rgba(247, 245, 243, 0.86);
  max-width: 56ch;
  margin-bottom: var(--sp-6);
}
/* Trust chips — discrete pills read faster than a run-on line of text */
.hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-top: var(--sp-6);
  padding: 0;
  font-size: var(--fs-sm);
}
.hero__meta span {
  display: inline-flex;
  align-items: center;
  gap: 0.5em;
  padding: 0.4rem 0.85rem;
  border: 1px solid rgba(255, 255, 255, 0.2);
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.07);
  backdrop-filter: blur(6px);
  color: rgba(247, 245, 243, 0.92);
  font-size: 0.8125rem;
  font-weight: 500;
  line-height: 1.5;
}
.hero__meta svg { width: 15px; height: 15px; color: var(--primary); flex: none; }

/* Compact page hero for interior pages */
.page-hero {
  position: relative;
  padding-block: clamp(2.75rem, 6vw, 4.5rem);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
}
.page-hero h1 { margin-bottom: var(--sp-4); }
.page-hero p { max-width: 62ch; font-size: var(--fs-lg); color: var(--text-muted); margin-bottom: 0; }

.breadcrumb { margin-bottom: var(--sp-4); font-size: var(--fs-xs); color: var(--text-muted); }
.breadcrumb ol { display: flex; flex-wrap: wrap; gap: 0.4em; margin: 0; padding: 0; list-style: none; }
.breadcrumb li:not(:last-child)::after { content: "/"; margin-left: 0.4em; color: var(--border-strong); }
.breadcrumb a { color: var(--text-muted); text-decoration: none; }
.breadcrumb a:hover { color: var(--primary-dark); text-decoration: underline; }

/* --------------------------------------------------------------------------
   7. Grids + cards
   -------------------------------------------------------------------------- */
.grid { display: grid; gap: var(--sp-5); }
.grid--2 { grid-template-columns: 1fr; }
.grid--3 { grid-template-columns: 1fr; }
.grid--4 { grid-template-columns: repeat(2, 1fr); }

@media (min-width: 640px) {
  .grid--2 { grid-template-columns: repeat(2, 1fr); }
  .grid--3 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .grid--3 { grid-template-columns: repeat(3, 1fr); }
  .grid--4 { grid-template-columns: repeat(4, 1fr); }
}

.card {
  display: flex;
  flex-direction: column;
  padding: var(--sp-5);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease),
    box-shadow 0.2s var(--ease);
}
.card:hover { border-color: var(--border-strong); transform: translateY(-2px); box-shadow: var(--shadow); }
.card h3 { margin-bottom: var(--sp-2); font-size: var(--fs-h3); }
.card p { font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: var(--sp-4); }
.card .link-arrow { margin-top: auto; }

.card__icon {
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  margin-bottom: var(--sp-4);
  border-radius: var(--radius);
  background: var(--primary-soft);
  color: var(--primary-dark);
}
.card__icon svg { width: 22px; height: 22px; }

/* Service card with photo */
.service-card {
  position: relative;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  transition: border-color 0.2s var(--ease), transform 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.service-card:hover { transform: translateY(-3px); box-shadow: var(--shadow); border-color: var(--border-strong); }
.service-card__media { aspect-ratio: 4 / 3; overflow: hidden; background: var(--surface-2); }
.service-card__media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease);
}
.service-card:hover .service-card__media img { transform: scale(1.04); }
.service-card__body { display: flex; flex-direction: column; flex: 1; padding: var(--sp-5); }
.service-card__body h3 { font-size: var(--fs-lg); margin-bottom: var(--sp-2); }
.service-card__body p { font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: var(--sp-4); }
.service-card__body .link-arrow { margin-top: auto; }
/* Full-card click target. Uses ::before so it does not collide with the
   arrow glyph that .link-arrow draws in ::after. */
.service-card a.stretched::before { content: ""; position: absolute; inset: 0; }

/* Numbered process steps */
.steps { counter-reset: step; display: grid; gap: var(--sp-5); }
@media (min-width: 640px) { .steps { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .steps { grid-template-columns: repeat(4, 1fr); } }
.step { position: relative; padding-top: var(--sp-5); border-top: 2px solid var(--border); }
.step::before {
  counter-increment: step;
  content: "0" counter(step);
  display: block;
  margin-bottom: var(--sp-3);
  font-size: var(--fs-sm);
  font-weight: 700;
  letter-spacing: 0.08em;
  color: var(--primary);
}
.step h3 { font-size: var(--fs-lg); margin-bottom: var(--sp-2); }
.step p { font-size: var(--fs-sm); color: var(--text-muted); margin: 0; }

/* Feature list with check marks */
.feature-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-4); }
.feature-list li { position: relative; padding-left: 2rem; }
.feature-list li::before {
  content: "";
  position: absolute;
  left: 0; top: 0.42em;
  width: 18px; height: 18px;
  background: var(--primary);
  -webkit-mask: var(--icon-check) center / 12px no-repeat, none;
  mask: var(--icon-check) center / 12px no-repeat;
  border-radius: 50%;
  background-image: none;
}
.feature-list li strong { display: block; color: var(--ink); }

/* solid dot + tick */
.feature-list li::before {
  background: var(--primary-soft);
  border: 1px solid var(--primary);
  -webkit-mask: none;
  mask: none;
}
.feature-list li::after {
  content: "";
  position: absolute;
  left: 5px; top: calc(0.42em + 6px);
  width: 8px; height: 4px;
  border-left: 2px solid var(--primary-dark);
  border-bottom: 2px solid var(--primary-dark);
  transform: rotate(-45deg);
}

/* --------------------------------------------------------------------------
   8. Split (image + text)
   -------------------------------------------------------------------------- */
.split {
  display: grid;
  gap: var(--sp-6);
  align-items: center;
}
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; gap: clamp(2.5rem, 5vw, 4.5rem); }
  .split--reverse .split__media { order: 2; }
}
.split__media { position: relative; }
.split__media img {
  width: 100%;
  border-radius: var(--radius-lg);
  aspect-ratio: 4 / 5;
  object-fit: cover;
}
.split__media--wide img { aspect-ratio: 4 / 3; }

.stat-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-6);
  margin-top: var(--sp-6);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--border);
}
.stat__value {
  display: block;
  font-size: 1.75rem;
  font-weight: 700;
  letter-spacing: -0.02em;
  color: var(--ink);
}
.stat__label { font-size: var(--fs-xs); color: var(--text-muted); }

/* --------------------------------------------------------------------------
   9. Portfolio / gallery
   -------------------------------------------------------------------------- */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  margin-bottom: var(--sp-6);
}
.filter {
  min-height: 40px;
  padding: 0.45rem 1rem;
  border: 1px solid var(--border);
  border-radius: 100px;
  background: var(--card);
  font: inherit;
  font-size: var(--fs-sm);
  font-weight: 550;
  color: var(--text-muted);
  cursor: pointer;
  transition: all 0.18s var(--ease);
}
.filter:hover { border-color: var(--border-strong); color: var(--ink); }
.filter[aria-pressed="true"] {
  background: var(--ink);
  border-color: var(--ink);
  color: #fff;
}

.gallery {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--sp-3);
}
@media (min-width: 768px) { .gallery { grid-template-columns: repeat(3, 1fr); gap: var(--sp-4); } }
@media (min-width: 1200px) { .gallery { grid-template-columns: repeat(4, 1fr); } }

.gallery__item {
  margin: 0;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--surface-2);
  aspect-ratio: 3 / 4;
}
.gallery__item[hidden] { display: none; }

/* --- Mosaic portfolio -----------------------------------------------------
   A dense tiled grid: landscape frames take a wide cell, portraits a tall
   one, and a feature frame every so often takes a large square. Dense flow
   backfills the gaps so the wall stays solid at any viewport width.
   -------------------------------------------------------------------------- */
.gallery--mosaic {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 84px;
  grid-auto-flow: dense;
  gap: var(--sp-3);
}
@media (min-width: 560px)  { .gallery--mosaic { grid-auto-rows: 110px; } }
@media (min-width: 768px)  { .gallery--mosaic { grid-template-columns: repeat(6, 1fr); grid-auto-rows: 120px; gap: var(--sp-4); } }
@media (min-width: 1200px) { .gallery--mosaic { grid-template-columns: repeat(8, 1fr); grid-auto-rows: 132px; } }

/* Every tile fills its cell; the cell shape comes from the span classes */
.gallery--mosaic .gallery__item {
  aspect-ratio: auto;
  grid-column: span 2;
  grid-row: span 2;
  margin: 0;
}
/* Scoped to match the specificity of the base rule above, otherwise
   `.gallery--mosaic .gallery__item` (0,2,0) would win and every tile
   would come out the same size. */
.gallery--mosaic .gallery__item--wide { grid-column: span 4; grid-row: span 2; }
.gallery--mosaic .gallery__item--tall { grid-column: span 2; grid-row: span 3; }
.gallery--mosaic .gallery__item--feature { grid-column: span 4; grid-row: span 4; }

/* On the narrowest screens a wide/feature tile would leave slivers, so
   everything settles to a simple two-up rhythm. */
@media (max-width: 559px) {
  .gallery--mosaic { grid-template-columns: repeat(4, 1fr); }
  .gallery--mosaic .gallery__item--wide,
  .gallery--mosaic .gallery__item--feature { grid-column: span 4; grid-row: span 2; }
  .gallery--mosaic .gallery__item--tall { grid-column: span 2; grid-row: span 3; }
}

/* --- Interior mosaic ------------------------------------------------------
   Same mosaic, different cell proportions. Interiors are shot at 3:2 and the
   portfolio's wide cell is 2:1, so reusing it would crop a quarter off the
   ceiling and floor of every room. These spans sit near 4:3, which takes a
   sliver off the sides instead — the harmless direction for a room.
   -------------------------------------------------------------------------- */
.gallery--interiors .gallery__item--wide    { grid-column: span 4; grid-row: span 3; }
.gallery--interiors .gallery__item--feature { grid-column: span 6; grid-row: span 4; }
.gallery--interiors .gallery__item--tall    { grid-column: span 2; grid-row: span 3; }

/* Below 768px the mosaic is four columns wide, so the six-column feature tile
   has to come back to four — spanning six there creates implicit columns and
   squashes every tile in the grid. The row height is then set per band so a
   three-row span still lands near 3:2, because the tile's width changes with
   the breakpoint while grid-auto-rows does not. */
@media (max-width: 767px) {
  .gallery--interiors .gallery__item--wide,
  .gallery--interiors .gallery__item--feature { grid-column: span 4; grid-row: span 3; }
}
@media (max-width: 559px) { .gallery--interiors { grid-auto-rows: 65px; } }
@media (min-width: 560px) and (max-width: 767px) { .gallery--interiors { grid-auto-rows: 114px; } }
/* Filter bar + result count */
.gallery-bar {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  margin-bottom: var(--sp-6);
}
.gallery-bar .filters { margin-bottom: 0; }
.gallery-count {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  white-space: nowrap;
}
.filter__n {
  display: inline-block;
  margin-left: 0.45em;
  padding: 0 0.4em;
  border-radius: 100px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: 0.75rem;
  font-variant-numeric: tabular-nums;
}
.filter[aria-pressed="true"] .filter__n { background: rgba(255, 255, 255, 0.22); color: #fff; }
[data-theme="dark"] .filter[aria-pressed="true"] .filter__n { background: rgba(0, 0, 0, 0.25); color: #150c04; }

.gallery-more { margin-top: var(--sp-6); text-align: center; }
.gallery-empty {
  margin: var(--sp-7) 0;
  text-align: center;
  color: var(--text-muted);
}
.gallery-empty[hidden] { display: none; }

/* The whole tile is a button so the lightbox is keyboard-reachable */
.gallery__btn {
  position: relative;
  display: block;
  width: 100%;
  height: 100%;
  padding: 0;
  border: 0;
  background: none;
  cursor: zoom-in;
  overflow: hidden;
}
.gallery__btn img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease);
}
.gallery__btn:hover img,
.gallery__btn:focus-visible img { transform: scale(1.05); }

/* Category label — always readable on touch, revealed on hover on desktop */
.gallery__tag {
  position: absolute;
  left: 8px;
  bottom: 8px;
  padding: 4px 9px;
  border-radius: 100px;
  background: rgba(10, 9, 8, 0.72);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  line-height: 1.4;
  pointer-events: none;
}
@media (hover: hover) {
  .gallery__tag { opacity: 0; transform: translateY(4px); transition: opacity .25s var(--ease), transform .25s var(--ease); }
  .gallery__btn:hover .gallery__tag,
  .gallery__btn:focus-visible .gallery__tag { opacity: 1; transform: none; }
}

/* --- Lightbox ----------------------------------------------------------- */
.lightbox {
  width: min(96vw, 1400px);
  max-width: none;
  max-height: 94vh;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: visible;
}
.lightbox::backdrop { background: rgba(8, 7, 6, 0.92); }
.lightbox__figure { margin: 0; display: grid; justify-items: center; gap: var(--sp-4); }
.lightbox__img {
  max-width: 100%;
  max-height: 82vh;
  width: auto;
  border-radius: var(--radius);
  background: #191615;
}
.lightbox__cap {
  display: flex;
  gap: var(--sp-4);
  align-items: baseline;
  color: rgba(255, 255, 255, 0.82);
  font-size: var(--fs-sm);
}
.lightbox__cap b { color: #fff; font-weight: 600; }

.lightbox__btn {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  display: grid;
  place-items: center;
  width: 46px; height: 46px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  cursor: pointer;
  transition: background-color .2s var(--ease), border-color .2s var(--ease);
}
.lightbox__btn:hover { background: rgba(0, 0, 0, 0.8); border-color: #fff; }
.lightbox__btn svg { width: 20px; height: 20px; }
.lightbox__prev { left: -6px; }
.lightbox__next { right: -6px; }
.lightbox__prev svg { rotate: 180deg; }
.lightbox__close {
  position: absolute;
  top: -46px;
  right: -4px;
  translate: none;
}
@media (min-width: 900px) {
  .lightbox__prev { left: -58px; }
  .lightbox__next { right: -58px; }
  .lightbox__close { top: -52px; right: -52px; }
}

/* --- Hero scroll cue ---------------------------------------------------- */
.hero__cue {
  position: absolute;
  left: 50%;
  bottom: clamp(1rem, 3vw, 2rem);
  translate: -50% 0;
  z-index: 2;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  color: rgba(255, 255, 255, 0.72);
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-decoration: none;
  transition: color 0.2s var(--ease);
}
.hero__cue:hover { color: #fff; }
.hero__cue span {
  display: block;
  width: 1px;
  height: 34px;
  background: linear-gradient(to bottom, rgba(255,255,255,.65), transparent);
  animation: ep-cue 2.2s var(--ease) infinite;
  transform-origin: top;
}
@keyframes ep-cue {
  0%   { transform: scaleY(0); opacity: 0; }
  35%  { transform: scaleY(1); opacity: 1; }
  100% { transform: scaleY(1); opacity: 0; transform-origin: bottom; }
}
@media (min-width: 900px) { .hero__cue { display: flex; } }
@media (prefers-reduced-motion: reduce) { .hero__cue span { animation: none; opacity: .7; } }

/* --------------------------------------------------------------------------
   10. Testimonials
   -------------------------------------------------------------------------- */
/* --- Testimonials carousel ------------------------------------------------
   A scroll-snap rail: it scrolls natively (touch, trackpad, keyboard) with
   no JS at all. The buttons and dots are progressive enhancement, and hide
   themselves whenever every quote already fits on screen — so the controls
   appear on phones now, and switch on for desktop by themselves once a
   fourth review is added.
   -------------------------------------------------------------------------- */
.quotes { position: relative; }

.quotes__track {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 86%;
  gap: var(--sp-5);
  overflow-x: auto;
  overscroll-behavior-x: contain;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;
  -ms-overflow-style: none;
  padding-bottom: 2px;
}
.quotes__track::-webkit-scrollbar { display: none; }
.quotes__track:focus-visible { outline: 2px solid var(--primary); outline-offset: 6px; border-radius: var(--radius); }
.quotes__track > .quote { scroll-snap-align: start; }

/* Fixed fractions, not 1fr: with 1fr the columns divide the track between
   however many cards exist, so ten quotes would shrink to fit instead of
   overflowing — and a rail that never overflows can never scroll. */
@media (min-width: 640px) {
  .quotes__track { grid-auto-columns: calc((100% - var(--sp-5)) / 2); }
}
@media (min-width: 1024px) {
  .quotes__track { grid-auto-columns: calc((100% - 2 * var(--sp-5)) / 3); }
}

@media (prefers-reduced-motion: reduce) { .quotes__track { scroll-behavior: auto; } }

.quotes__ui {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  margin-top: var(--sp-6);
}
.quotes__ui[hidden] { display: none; }

.quotes__dots { display: flex; gap: 8px; margin: 0; padding: 0; list-style: none; }
.quotes__dot {
  width: 28px; height: 4px;
  padding: 0;
  border: 0;
  border-radius: 2px;
  background: rgba(255, 255, 255, 0.26);
  cursor: pointer;
  transition: background-color .25s var(--ease), transform .25s var(--ease);
}
.quotes__dot:hover { background: rgba(255, 255, 255, 0.5); }
.quotes__dot[aria-current="true"] { background: var(--primary); transform: scaleY(1.6); }

.quotes__arrows { display: flex; gap: var(--sp-2); }
.quotes__btn {
  display: grid;
  place-items: center;
  width: 42px; height: 42px;
  border: 1px solid rgba(255, 255, 255, 0.24);
  border-radius: 50%;
  background: transparent;
  color: #fff;
  cursor: pointer;
  transition: background-color .2s var(--ease), border-color .2s var(--ease), opacity .2s var(--ease);
}
.quotes__btn:hover:not(:disabled) { background: rgba(255, 255, 255, 0.12); border-color: #fff; }
.quotes__btn:disabled { opacity: .35; cursor: default; }
.quotes__btn svg { width: 18px; height: 18px; }
.quotes__btn .icon-prev { rotate: 180deg; }

.quote {
  display: flex;
  flex-direction: column;
  margin: 0;
  padding: var(--sp-6);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
}
.section--ink .quote {
  background: rgba(255, 255, 255, 0.045);
  border-color: rgba(255, 255, 255, 0.13);
}
.quote__mark { width: 26px; height: 26px; margin-bottom: var(--sp-4); color: var(--primary); }
.quote { transition: border-color .25s var(--ease), transform .25s var(--ease); }
.quote:hover { border-color: rgba(255, 255, 255, 0.28); }
.section--ink .quote:hover { background: rgba(255, 255, 255, 0.07); }

/* Avatar-free initial badge: identifies the client without inventing a photo.
   Scoped past `.quote figcaption span`, which would otherwise force
   display:block and knock the letter out of the circle. */
.quote__who { display: flex; align-items: center; gap: var(--sp-3); }
.quote figcaption .quote__initial,
.quote__initial {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  flex: none;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  font-weight: 700;
  font-size: 0.9375rem;
  line-height: 1;
}
.quote blockquote { margin: 0 0 var(--sp-5); font-size: var(--fs-lg); line-height: 1.6; }
.section--ink .quote blockquote { color: rgba(247, 245, 243, 0.9); }
/* Cards share a height across the rail; the quote floats in the middle of
   whatever space that leaves and the attribution stays pinned to the foot,
   so a two-line review reads as composed rather than half-empty. */
.quote blockquote { margin-top: auto; margin-bottom: auto; }

.quote figcaption {
  margin-top: var(--sp-5);
  padding-top: var(--sp-4);
  border-top: 1px solid var(--border);
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink);
}
.section--ink .quote figcaption { border-top-color: rgba(255, 255, 255, 0.13); color: #fff; }
.quote figcaption span { display: block; font-weight: 400; color: var(--text-muted); }
.section--ink .quote figcaption span { color: var(--inverse-muted); }


/* A two-line review looks thin at body size next to a six-line one, so the
   shortest quotes are set larger. Purely typographic — no padding games. */
.quote--short blockquote { font-size: clamp(1.25rem, 1.1vw + 1rem, 1.5rem); line-height: 1.45; }
.quote--long blockquote { font-size: var(--fs-base); }

.quote { transition: border-color .25s var(--ease), transform .25s var(--ease), background-color .25s var(--ease); }
.quote:hover { transform: translateY(-3px); }

/* --- Testimonials band background ----------------------------------------
   Two wide, very low-opacity radial pools — brand orange bleeding in from
   the top left, logo blue from the bottom right — over a gentle vertical
   ramp. Deliberately not a hard two-stop diagonal: the colour should read
   as light falling across a dark room, not as a gradient effect. Pure CSS,
   so it costs nothing to load.
   -------------------------------------------------------------------------- */
.section--quotes {
  position: relative;
  isolation: isolate;
  background:
    radial-gradient(70rem 34rem at 12% -14%, rgba(255, 105, 3, 0.17), transparent 62%),
    radial-gradient(52rem 30rem at 96% 114%, rgba(3, 152, 204, 0.13), transparent 60%),
    linear-gradient(180deg, #17130f 0%, #100d0b 55%, #131010 100%);
}

/* Hairline warm rule top and bottom so the band separates cleanly from the
   white sections either side without a hard edge. */
.section--quotes::before,
.section--quotes::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  height: 1px;
  z-index: -1;
  background: linear-gradient(90deg, transparent, rgba(255, 105, 3, 0.45), transparent);
}
.section--quotes::before { top: 0; }
.section--quotes::after  { bottom: 0; opacity: 0.55; }

[data-theme="dark"] .section--quotes {
  background:
    radial-gradient(70rem 34rem at 12% -14%, rgba(255, 122, 31, 0.15), transparent 62%),
    radial-gradient(52rem 30rem at 96% 114%, rgba(53, 182, 232, 0.11), transparent 60%),
    linear-gradient(180deg, #0d0b0a 0%, #070606 55%, #0a0908 100%);
}

/* Cards float on the gradient rather than sitting on a flat panel */
.section--quotes .quote {
  background: rgba(255, 255, 255, 0.055);
  border-color: rgba(255, 255, 255, 0.11);
  backdrop-filter: blur(2px);
}
.section--quotes .quote:hover {
  background: rgba(255, 255, 255, 0.085);
  border-color: rgba(255, 255, 255, 0.24);
}

/* Star row + source attribution on sourced reviews.
   Stars are presentational only — reviews collected on a third-party site
   are NOT emitted as aggregateRating structured data. */
.quote__stars { display: flex; gap: 3px; margin: 0 0 var(--sp-3); }
.quote__stars svg { width: 15px; height: 15px; color: var(--primary); fill: currentColor; stroke-width: 1; }

.quote__source {
  display: inline-block;
  margin-top: var(--sp-3);
  font-size: var(--fs-xs);
  color: var(--inverse-muted);
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.22);
}
.quote__source:hover { color: #fff; border-bottom-color: #fff; }

.quotes__foot {
  margin: var(--sp-6) auto 0;
  max-width: 640px;
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--inverse-muted);
}
.quotes__foot a { color: #ffb27a; }
.quotes__foot a:hover { color: #fff; }

/* Demo-mode notice + placeholder card marking (see include/testimonials.php).
   Remove alongside the demo block once there are enough genuine reviews. */
.quotes__demo-note {
  max-width: 680px;
  margin: 0 auto var(--sp-6);
  padding: var(--sp-4) var(--sp-5);
  border: 1px dashed rgba(255, 255, 255, 0.32);
  border-radius: var(--radius);
  background: rgba(255, 105, 3, 0.1);
  color: rgba(247, 245, 243, 0.9);
  font-size: var(--fs-sm);
  text-align: center;
}
.quotes__demo-note strong { color: #ffb27a; }
.quote--demo { border-style: dashed; opacity: 0.82; }
.quote--demo .quote__initial { background: var(--text-muted); }

/* --------------------------------------------------------------------------
   11. Location + contact
   -------------------------------------------------------------------------- */
.contact-grid { display: grid; gap: var(--sp-6); }
@media (min-width: 900px) { .contact-grid { grid-template-columns: 1.05fr 1fr; gap: clamp(2.5rem, 5vw, 4rem); } }

.info-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-5); }
.info-list li { display: flex; gap: var(--sp-4); }
.info-list svg { width: 20px; height: 20px; flex: none; margin-top: 4px; color: var(--primary); }
.info-list dt,
.info-list .info-label {
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: 2px;
}
.info-list a { color: var(--ink); text-decoration: none; font-weight: 550; }
.info-list a:hover { color: var(--primary-dark); text-decoration: underline; }

/* Click-to-load map */
.map-embed {
  position: relative;
  aspect-ratio: 16 / 10;
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface-2);
}
.map-embed iframe { width: 100%; height: 100%; border: 0; display: block; }
.map-embed__placeholder {
  position: absolute;
  inset: 0;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: var(--sp-3);
  padding: var(--sp-5);
  border: 0;
  width: 100%;
  text-align: center;
  background:
    radial-gradient(circle at 30% 30%, var(--card) 0, transparent 60%),
    repeating-linear-gradient(45deg, var(--surface) 0 12px, var(--surface-2) 12px 24px);
  cursor: pointer;
  font: inherit;
}
.map-embed__placeholder svg { width: 34px; height: 34px; color: var(--primary); }
.map-embed__placeholder strong { color: var(--ink); }
.map-embed__placeholder span { font-size: var(--fs-sm); color: var(--text-muted); }

/* Form */
.form { display: grid; gap: var(--sp-4); }
.field { display: grid; gap: 6px; }
.field label { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); }
.field .req { color: var(--primary-dark); }
.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 48px;
  padding: 0.7rem 0.85rem;
  font: inherit;
  font-size: var(--fs-base);
  color: var(--text);
  background: var(--card);
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  transition: border-color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.field textarea { min-height: 130px; resize: vertical; }
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--secondary-dark);
  box-shadow: 0 0 0 3px rgba(3, 152, 204, 0.16);
}
.field input:user-invalid,
.field textarea:user-invalid { border-color: #b3261e; }
.field .hint { font-size: var(--fs-xs); color: var(--text-muted); }
.field--half { display: grid; gap: var(--sp-4); }
@media (min-width: 560px) { .field--half { grid-template-columns: 1fr 1fr; } }

.form__note { font-size: var(--fs-xs); color: var(--text-muted); }
.form__status {
  padding: var(--sp-4);
  border-radius: var(--radius);
  background: var(--primary-soft);
  border: 1px solid var(--primary);
  font-size: var(--fs-sm);
}
.form__status[hidden] { display: none; }
.hp { position: absolute; left: -9999px; opacity: 0; height: 0; }

/* --------------------------------------------------------------------------
   12. CTA band
   -------------------------------------------------------------------------- */
.cta-band { background: var(--ink); color: var(--inverse-text); }
.cta-band .container {
  display: grid;
  gap: var(--sp-5);
  align-items: center;
  padding-block: clamp(2.75rem, 5vw, 4rem);
}
@media (min-width: 900px) {
  .cta-band .container { grid-template-columns: 1fr auto; gap: var(--sp-7); }
}
.cta-band h2 { color: #fff; margin-bottom: var(--sp-2); font-size: var(--fs-h2); }
.cta-band p { color: rgba(247, 245, 243, 0.8); margin: 0; max-width: 54ch; }

/* --------------------------------------------------------------------------
   13. Footer
   -------------------------------------------------------------------------- */
.site-footer {
  background: var(--footer-bg);
  color: var(--inverse-muted);
  font-size: var(--fs-sm);
}
.site-footer__grid {
  display: grid;
  gap: var(--sp-6);
  padding-block: clamp(3rem, 6vw, 4.5rem) var(--sp-6);
}
@media (min-width: 700px) { .site-footer__grid { grid-template-columns: repeat(2, 1fr); } }
/* Five columns since the Areas nav was added. The count must match the number
   of children in include/footer.php — with four tracks the fifth column
   dropped onto a second row and left a ragged gap under the brand block. */
@media (min-width: 1024px) { .site-footer__grid { grid-template-columns: 1.5fr 1fr 1fr 1fr 1.3fr; gap: var(--sp-6); } }

.site-footer h3 {
  margin-bottom: var(--sp-4);
  font-size: var(--fs-xs);
  font-weight: 600;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: #fff;
}
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--sp-2); }
.site-footer a { color: var(--inverse-muted); text-decoration: none; }
.site-footer a:hover { color: #fff; text-decoration: underline; }
.site-footer__brand img { width: 168px; height: 39px; margin-bottom: var(--sp-4); }
.site-footer__brand p { max-width: 42ch; margin-bottom: var(--sp-5); }

/* Scoped to beat `.site-footer ul { display: grid }` */
.social,
.site-footer .social {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
  list-style: none;
  margin: 0;
  padding: 0;
}
.social a {
  display: grid;
  place-items: center;
  width: 40px; height: 40px;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius);
  color: var(--inverse-muted);
  transition: all 0.2s var(--ease);
}
.social a:hover { background: var(--primary); border-color: var(--primary); color: #fff; }
.social svg { width: 18px; height: 18px; }

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-5);
  align-items: center;
  justify-content: space-between;
  padding-block: var(--sp-5);
  border-top: 1px solid rgba(255, 255, 255, 0.1);
  font-size: var(--fs-xs);
}
.site-footer__bottom ul { display: flex; flex-wrap: wrap; gap: var(--sp-4); }

/* --------------------------------------------------------------------------
   14. Mobile action bar
   -------------------------------------------------------------------------- */
.action-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 90;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  background: var(--card);
  border-top: 1px solid var(--border);
  box-shadow: 0 -4px 20px -8px rgba(18, 16, 14, 0.16);
  padding-bottom: env(safe-area-inset-bottom);
}
.action-bar a {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: 58px;
  font-size: 0.6875rem;
  font-weight: 600;
  letter-spacing: 0.02em;
  color: var(--text);
  text-decoration: none;
}
.action-bar a + a { border-left: 1px solid var(--border); }
.action-bar svg { width: 19px; height: 19px; color: var(--primary); }
.action-bar a:hover { background: var(--surface); color: var(--ink); }

@media (min-width: 1024px) { .action-bar { display: none; } }
@media (max-width: 1023px) { body { padding-bottom: 58px; } }

/* --------------------------------------------------------------------------
   15. Prose (legal pages)
   -------------------------------------------------------------------------- */
.prose { max-width: 72ch; }
.prose h2 { margin-top: var(--sp-7); font-size: var(--fs-h3); }
.prose h2:first-child { margin-top: 0; }
.prose h3 { margin-top: var(--sp-5); font-size: var(--fs-lg); }
.prose ul { display: grid; gap: var(--sp-2); }

/* FAQ
   Rows are exclusive: the markup gives every <details> in a group the same
   `name`, so opening one closes its sibling natively, with no JS. main.js
   carries a fallback for browsers that predate the attribute. */
.faq { display: grid; gap: 0; max-width: 800px; }
.faq details {
  position: relative;
  border-bottom: 1px solid var(--border);
}
.faq summary {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
  /* Negative inline margin lets the hover tint bleed past the text column
     without shifting the rule underneath. */
  padding: var(--sp-5) var(--sp-4);
  margin-inline: calc(var(--sp-4) * -1);
  border-radius: var(--radius);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
  transition: color 0.2s var(--ease), background-color 0.2s var(--ease);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--primary-dark); background: var(--surface); }
.faq summary:focus-visible { outline: 2px solid var(--secondary-dark); outline-offset: -2px; }
.faq details[open] > summary { color: var(--primary-dark); }

/* +/− indicator drawn as one pseudo-element with two gradient bars. Replaces
   the previous ::before/::after pair, whose absolutely positioned vertical bar
   was anchored to the <details> and drifted whenever the summary padding
   changed. Collapsing the vertical bar's height turns the + into a −. */
.faq summary::after {
  content: "";
  flex: none;
  width: 28px; height: 28px;
  border-radius: 50%;
  background:
    linear-gradient(var(--primary), var(--primary)) center / 13px 2px no-repeat,
    linear-gradient(var(--primary), var(--primary)) center / 2px 13px no-repeat;
  transition: transform 0.3s var(--ease), background-size 0.3s var(--ease),
    background-color 0.2s var(--ease);
}
.faq summary:hover::after { background-color: var(--primary-soft); }
.faq details[open] > summary::after {
  transform: rotate(180deg);
  background-size: 13px 2px, 2px 0;
  background-color: var(--primary-soft);
}

.faq details > div {
  padding-bottom: var(--sp-5);
  color: var(--text-muted);
  max-width: 64ch;
}
.faq details > div p:last-child { margin-bottom: 0; }
/* A closed <details> does not render its content, so height cannot transition.
   Fade the answer in on open instead — same perceived smoothness, no JS. */
@media (prefers-reduced-motion: no-preference) {
  .faq details[open] > div { animation: ep-faq-in 0.28s var(--ease) both; }
}
@keyframes ep-faq-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   16. Scroll reveal
   -------------------------------------------------------------------------- */
/* Content is visible by default. The hidden state is only applied once the
   inline bootstrap script has confirmed JS + IntersectionObserver are
   available, so content can never be trapped invisible. */
.js-reveal .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.6s var(--ease), transform 0.6s var(--ease);
  will-change: opacity, transform;
}
.js-reveal .reveal.is-visible { opacity: 1; transform: none; }

@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;
    scroll-behavior: auto !important;
  }
  .js-reveal .reveal { opacity: 1; transform: none; }
}

/* --------------------------------------------------------------------------
   17. Print
   -------------------------------------------------------------------------- */
@media print {
  .site-header, .action-bar, .cta-band, .site-footer, .filters { display: none !important; }
  body { padding: 0; color: #000; }
  a[href^="http"]::after { content: " (" attr(href) ")"; font-size: 0.8em; }
}

/* ==========================================================================
   18. Homepage refinements
   Layered on top of the base system rather than editing it, so the shared
   components keep behaving the same everywhere else. Every colour here is a
   token, so dark mode follows automatically; every animation sits behind a
   reduced-motion guard.
   ========================================================================== */

/* --- Hero: staggered entrance -------------------------------------------
   The hero is above the fold, so it must never depend on JS or on the
   IntersectionObserver reveal. This is a pure CSS entrance with `both` fill,
   and it is skipped entirely when reduced motion is requested. */
@media (prefers-reduced-motion: no-preference) {
  .hero__inner > * { animation: ep-hero-in 0.75s var(--ease) both; }
  .hero__inner > :nth-child(1) { animation-delay: 0.05s; }
  .hero__inner > :nth-child(2) { animation-delay: 0.14s; }
  .hero__inner > :nth-child(3) { animation-delay: 0.23s; }
  .hero__inner > :nth-child(4) { animation-delay: 0.32s; }
  .hero__inner > :nth-child(5) { animation-delay: 0.41s; }
}
@keyframes ep-hero-in {
  from { opacity: 0; transform: translateY(16px); }
  to   { opacity: 1; transform: none; }
}

/* No hero→section fade here on purpose: the slider dots, the play button and
   the scroll cue all sit in the bottom ~140px and are solid white. Fading the
   hero out to --background would leave them near-invisible in light mode. The
   hard edge between the dark hero and the light section stays. */

/* Give the trust chips a touch more presence and a hover state, since the
   first one repeats the studio address that the map section links to. */
.hero__meta span { transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease); }
.hero__meta span:hover { border-color: rgba(255, 255, 255, 0.4); background: rgba(255, 255, 255, 0.12); }

/* --- Centred section headings -------------------------------------------
   The left-aligned eyebrow gets a leading rule; the centred variant simply
   dropped it, which left those headings looking unanchored. Flank it
   symmetrically instead. */
.section-heading--center .eyebrow { justify-content: center; }
.section-heading--center .eyebrow::before,
.section-heading--center .eyebrow::after {
  content: "";
  display: block;
  flex: none;
  width: 22px;
  height: 2px;
  background: var(--primary);
}

/* --- Service cards ------------------------------------------------------- */
/* Accent rule that draws in on hover — a restrained signature that reads as
   "this whole tile is a link" without adding another visible control. */
.service-card::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 0;
  z-index: 1;
  height: 2px;
  background: var(--primary);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.4s var(--ease);
}
.service-card:hover::after,
.service-card:focus-within::after { transform: scaleX(1); }

/* Scrim grounds the photo against the card body on hover */
.service-card__media { position: relative; }
.service-card__media::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 45%;
  background: linear-gradient(to top, rgba(10, 9, 8, 0.3), transparent);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
}
.service-card:hover .service-card__media::after { opacity: 1; }

/* Keyboard parity: the stretched link is the only focusable thing in the
   card, so the card itself has to show the focus state. */
.service-card:focus-within {
  transform: translateY(-3px);
  box-shadow: var(--shadow);
  border-color: var(--border-strong);
}

/* --- Process steps -------------------------------------------------------
   Was a plain top rule with a small number above it, which read as four
   loose paragraphs. A numbered badge plus a connecting line makes the
   sequence legible at a glance. */
.steps { position: relative; }
.step {
  padding-top: 0;
  border-top: 0;
}
.step::before {
  display: grid;
  place-items: center;
  width: 46px;
  height: 46px;
  margin-bottom: var(--sp-4);
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--card);
  color: var(--primary-dark);
  font-size: var(--fs-sm);
  letter-spacing: 0.06em;
}
/* The rail only makes sense once the four steps sit in one row */
@media (min-width: 1024px) {
  .step:not(:last-child)::after {
    content: "";
    position: absolute;
    top: 23px;
    left: 58px;
    right: calc(var(--sp-5) * -1);
    height: 1px;
    background: linear-gradient(to right, var(--border-strong), var(--border));
  }
}

/* --- Homepage gallery ----------------------------------------------------
   The ten frames are deliberately two per category. The shared .gallery grid
   is 3-up then 4-up, which orphaned two tiles on the last row at every
   breakpoint; a 2-up / 5-up rhythm divides ten exactly and lines each
   category up as a column pair. Doubled class to outrank the base .gallery
   breakpoints regardless of source order. */
.gallery.gallery--home { grid-template-columns: repeat(2, 1fr); }
@media (min-width: 900px) {
  .gallery.gallery--home { grid-template-columns: repeat(5, 1fr); }
}

/* --- Buttons: hover lift -------------------------------------------------
   :not(:active) so the existing press-down still wins on click. */
.btn--accent:hover:not(:active),
.btn--primary:hover:not(:active) {
  transform: translateY(-1px);
  box-shadow: var(--shadow);
}

/* --- Stat row inside a split column --------------------------------------
   The base .stat-row is a wrapping flex row with a 2rem gap, which drops the
   third stat onto its own line on a phone and reads as a stray orphan. Three
   equal columns keep the trio together at every width. */
.split .stat-row { margin-top: var(--sp-6); }
.stat-row--3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--sp-4);
}
.stat-row--3 .stat__value { font-size: clamp(1.35rem, 3.2vw, 1.75rem); }
.stat-row--3 .stat__label { display: block; line-height: 1.35; }

/* ==========================================================================
   19. Testimonials — rating badge + carousel polish
   The band is always dark (.section--ink.section--quotes), so light-on-dark
   values are intentional here rather than theme tokens.
   ========================================================================== */

/* --- Verified rating badge -----------------------------------------------
   Real figures from the public Google Business Profile (EP_GOOGLE_* in
   config.php). Presentational only — deliberately not aggregateRating
   structured data, since self-marked ratings breach Google's policy. */
/* flex + fit-content, not inline-flex: `margin-inline: auto` only centres a
   block-level box, and the badge is a direct child of .container. */
.rating-badge {
  display: flex;
  width: fit-content;
  align-items: center;
  gap: var(--sp-3);
  margin: 0 auto var(--sp-7);
  padding: 0.6rem 1.15rem 0.6rem 0.9rem;
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: 100px;
  background: rgba(255, 255, 255, 0.055);
  backdrop-filter: blur(4px);
  color: rgba(247, 245, 243, 0.92);
  text-decoration: none;
  transition: border-color 0.2s var(--ease), background-color 0.2s var(--ease);
}
/* .section-heading carries margin-bottom: var(--sp-7); tighten it so the
   badge reads as part of the heading block rather than a stray control. */
.section--quotes .section-heading { margin-bottom: var(--sp-5); }

.rating-badge:hover {
  border-color: rgba(255, 255, 255, 0.34);
  background: rgba(255, 255, 255, 0.09);
  color: #fff;
}
.rating-badge__score {
  font-size: 1.375rem;
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.02em;
  color: #ffb27a;
}
.rating-badge__stars { display: inline-flex; gap: 2px; }
.rating-badge__stars svg {
  width: 15px; height: 15px;
  color: var(--primary);
  fill: currentColor;
  stroke-width: 1;
}
/* Single line, divided off from the score it no longer repeats. */
.rating-badge__text {
  padding-left: var(--sp-3);
  border-left: 1px solid rgba(255, 255, 255, 0.16);
  font-size: var(--fs-sm);
  line-height: 1.2;
  white-space: nowrap;
}
/* Signals that the pill is a link out to the profile */
.rating-badge__text::after {
  content: "";
  display: inline-block;
  width: 12px; height: 12px;
  margin-left: 0.45em;
  vertical-align: -1px;
  background: currentColor;
  -webkit-mask: var(--icon-arrow) center / contain no-repeat;
  mask: var(--icon-arrow) center / contain no-repeat;
  opacity: 0.7;
  transition: transform 0.2s var(--ease), opacity 0.2s var(--ease);
}
.rating-badge:hover .rating-badge__text::after { transform: translateX(3px); opacity: 1; }

/* Narrow screens: shrink the stars rather than drop them. They are the most
   recognisable part of a rating, and now that the text is just the count
   there is room for them. */
@media (max-width: 430px) {
  .rating-badge { gap: var(--sp-2); padding: 0.5rem 0.85rem; }
  .rating-badge__score { font-size: 1.25rem; }
  .rating-badge__stars { gap: 1px; }
  .rating-badge__stars svg { width: 12px; height: 12px; }
  .rating-badge__text { padding-left: var(--sp-2); font-size: var(--fs-xs); }
}

/* --- Carousel polish ----------------------------------------------------- */
/* Oversized quote glyph behind the text: gives each card a focal point and
   stops a short review reading as an empty box. */
.section--quotes .quote { position: relative; overflow: hidden; }
.section--quotes .quote .quote__mark {
  width: 30px;
  height: 30px;
  opacity: 0.9;
}
.section--quotes .quote::before {
  content: "";
  position: absolute;
  right: -14px;
  top: -10px;
  width: 116px;
  height: 116px;
  background: currentColor;
  color: rgba(255, 255, 255, 0.032);
  -webkit-mask: var(--icon-quote) center / contain no-repeat;
  mask: var(--icon-quote) center / contain no-repeat;
  pointer-events: none;
}
:root {
  --icon-quote: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath fill='%23000' d='M9.5 5.5c-3 1.4-4.8 4-4.8 7.3V18.5h6v-6h-3c0-2.3 1-3.9 3-4.8Zm9.8 0c-3 1.4-4.8 4-4.8 7.3V18.5h6v-6h-3c0-2.3 1-3.9 3-4.8Z'/%3E%3C/svg%3E");
}

/* Excerpted Google reviews end in an ellipsis; the source link is the way to
   the full text, so make it read as the obvious next step. */
.quote__source::after {
  content: "";
  display: inline-block;
  width: 11px; height: 11px;
  margin-left: 0.4em;
  vertical-align: -1px;
  background: currentColor;
  -webkit-mask: var(--icon-arrow) center / contain no-repeat;
  mask: var(--icon-arrow) center / contain no-repeat;
  transition: transform 0.2s var(--ease);
}
.quote__source:hover::after { transform: translateX(2px); }

/* Dots: larger hit area than the 4px bar they paint, so they are usable on
   touch without changing the visual weight. */
.quotes__dot {
  position: relative;
  width: 30px;
}
.quotes__dot::after {
  content: "";
  position: absolute;
  inset: -12px -3px;
}

/* Keep the rail from clipping the card's focus ring */
.quotes__track { padding-block: 3px; }

/* Card hover lift is disabled on touch, where it just sticks after a tap */
@media (hover: none) {
  .quote:hover { transform: none; }
}

/* --- Split with a tall column -------------------------------------------
   .split centres its columns, which left the FAQ heading floating in the
   middle of the row against a much taller list of questions. Top-align, then
   let the short column follow the reader down so the "Ask us something else"
   CTA stays reachable while they work through the answers. */
.split--top { align-items: start; }
@media (min-width: 900px) {
  .split--top > :first-child {
    position: sticky;
    top: calc(var(--header-h) + var(--sp-6));
  }
}

/* ==========================================================================
   20. Closing sections — CTA band, map, info list
   Shared with the service pages and /contact, so everything here is tokenised
   and both themes are declared explicitly.
   ========================================================================== */

/* --- CTA band -------------------------------------------------------------
   Was flat --ink, which read as a slab after the warm gradient of the quotes
   band above it. Same treatment as .section--quotes so the two dark bands
   belong to one family, with the glow anchored right where the buttons sit. */
.cta-band {
  position: relative;
  isolation: isolate;
  background:
    radial-gradient(46rem 26rem at 88% 116%, rgba(255, 105, 3, 0.18), transparent 62%),
    linear-gradient(180deg, #16120f 0%, #100d0b 100%);
}
[data-theme="dark"] .cta-band {
  background:
    radial-gradient(46rem 26rem at 88% 116%, rgba(255, 122, 31, 0.15), transparent 62%),
    linear-gradient(180deg, #0b0a09 0%, #070606 100%);
}
/* Warm hairline, matching the rule that tops the testimonials band */
.cta-band::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  z-index: -1;
  background: linear-gradient(90deg, transparent, rgba(255, 105, 3, 0.45), transparent);
}
.cta-band .btn-row { flex-wrap: nowrap; }
@media (max-width: 520px) { .cta-band .btn-row { flex-wrap: wrap; } }

/* --- Click-to-load map ----------------------------------------------------
   The placeholder was a repeating 45° stripe pattern, which read as a
   "broken image" hatch rather than a map. A soft grid on a warm wash says
   "map" without shipping one. */
.map-embed__placeholder {
  background:
    radial-gradient(28rem 16rem at 32% 26%, rgba(255, 105, 3, 0.09), transparent 68%),
    linear-gradient(var(--border) 1px, transparent 1px) 0 0 / 100% 34px,
    linear-gradient(90deg, var(--border) 1px, transparent 1px) 0 0 / 34px 100%,
    var(--surface);
  transition: background-color 0.25s var(--ease);
}
.map-embed__placeholder:hover { background-color: var(--surface-2); }
.map-embed__placeholder svg {
  transition: transform 0.25s var(--ease);
  filter: drop-shadow(0 2px 6px rgba(18, 16, 14, 0.18));
}
.map-embed__placeholder:hover svg { transform: translateY(-2px) scale(1.04); }
/* Pin the label to a readable plate so it never fights the grid behind it */
.map-embed__placeholder strong,
.map-embed__placeholder span { position: relative; }

/* --- Info list ------------------------------------------------------------
   Icons sat loose against the text. A soft disc matches the step badges and
   the card icons, so the three icon treatments on the page finally agree. */
.info-list li { align-items: flex-start; }
.info-list svg {
  box-sizing: content-box;
  width: 18px; height: 18px;
  margin-top: 0;
  padding: 10px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary-dark);
}

/* ==========================================================================
   21. Section washes
   Extends the two-pool treatment already used by .section--quotes to every
   band on the site: a warm pool bleeding in from one corner, the logo blue
   from the opposite one, over the section's flat colour. Kept far below the
   photography in contrast — this should read as light falling across the
   page, never as a coloured panel.

   Both pools are single tokens, so dark mode is two redefinitions rather
   than a copy of every gradient.
   ========================================================================== */
:root {
  --wash-warm: rgba(255, 105, 3, 0.07);
  --wash-cool: rgba(3, 152, 204, 0.055);
}
/* Dark surfaces swallow a tint, so the pools carry slightly more alpha */
[data-theme="dark"] {
  --wash-warm: rgba(255, 122, 31, 0.10);
  --wash-cool: rgba(53, 182, 232, 0.07);
}

/* The :not() guards matter: .section--quotes and any future ink band set
   their own `background` shorthand earlier in this file, and a later rule of
   equal specificity would silently wipe it out. .section--quotes always
   carries .section--ink in the markup, so one guard covers both. */
.section:not(.section--ink):not(.section--tint) {
  background-color: var(--wash-bg, var(--background));
  background-image:
    radial-gradient(58rem 30rem at var(--wash-ax, 6%) -12%,
                    var(--wash-a, var(--wash-warm)), transparent 62%),
    radial-gradient(46rem 26rem at var(--wash-bx, 98%) 112%,
                    var(--wash-b, var(--wash-cool)), transparent 60%);
}

/* Surface bands mirror the pools rather than repeat them, so two adjacent
   sections never read as the same wash twice. Custom properties only — no
   specificity fight with the rule above. */
.section--surface {
  --wash-bg: var(--surface);
  --wash-ax: 98%;
  --wash-bx: 4%;
  --wash-a: var(--wash-cool);
  --wash-b: var(--wash-warm);
}

/* Interior-page hero gets the same language, weighted to the top where the
   breadcrumb and H1 sit. */
.page-hero {
  background-color: var(--surface);
  background-image:
    radial-gradient(52rem 26rem at 4% -34%, var(--wash-warm), transparent 62%),
    radial-gradient(40rem 22rem at 100% 132%, var(--wash-cool), transparent 60%);
}

/* ==========================================================================
   22. Google Business Profile card (include/map.php)
   Profile details sit ABOVE the map, never over it — Google's terms require
   their logo and attribution stay visible, and an overlay would cover them.
   The map itself is left at its natural colours in both themes: inverting it
   for dark mode mangles the Google logo and the road/water palette.
   ========================================================================== */
.gmb {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}

.gmb__head {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-bottom: 1px solid var(--border);
}
.gmb__id { display: flex; align-items: center; gap: var(--sp-3); min-width: 0; }
.gmb__pin {
  display: grid;
  place-items: center;
  flex: none;
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary-dark);
}
.gmb__pin svg { width: 19px; height: 19px; }
.gmb__id strong {
  display: block;
  color: var(--ink);
  font-size: var(--fs-sm);
  line-height: 1.3;
}
.gmb__id > div > span {
  display: block;
  color: var(--text-muted);
  font-size: var(--fs-xs);
}

.gmb__rating {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  flex: none;
  padding: 0.3rem 0.6rem;
  border-radius: 100px;
  text-decoration: none;
  transition: background-color 0.2s var(--ease);
}
.gmb__rating:hover { background: var(--surface-2); }
.gmb__score { font-weight: 700; color: var(--primary-dark); line-height: 1; }
.gmb__stars { display: inline-flex; gap: 1px; }
.gmb__stars svg {
  width: 13px; height: 13px;
  color: var(--primary);
  fill: currentColor;
  stroke-width: 1;
}
.gmb__count { font-size: var(--fs-xs); color: var(--text-muted); white-space: nowrap; }

/* The map keeps the 16/10 frame the old placeholder used */
.gmb__map {
  position: relative;
  aspect-ratio: 16 / 10;
  background: var(--surface-2);
}
.gmb__map iframe {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  border: 0;
  display: block;
}

.gmb__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  padding: var(--sp-4) var(--sp-5);
  border-top: 1px solid var(--border);
}
.gmb__foot address {
  margin: 0;
  max-width: 40ch;
  color: var(--text-muted);
  font-size: var(--fs-xs);
  line-height: 1.45;
}
.gmb__actions { display: flex; gap: var(--sp-2); flex: none; }
.gmb__action {
  display: inline-flex;
  align-items: center;
  gap: 0.4em;
  min-height: 38px;
  padding: 0 0.9rem;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius);
  color: var(--ink);
  font-size: var(--fs-sm);
  font-weight: 600;
  text-decoration: none;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.gmb__action:hover { background: var(--surface-2); border-color: var(--ink); color: var(--ink); }
.gmb__action svg { width: 16px; height: 16px; color: var(--primary); }

@media (max-width: 560px) {
  .gmb__head, .gmb__foot { padding: var(--sp-3) var(--sp-4); }
  .gmb__foot { flex-direction: column; align-items: stretch; }
  .gmb__actions { display: grid; grid-template-columns: 1fr 1fr; }
  .gmb__action { justify-content: center; }
  .gmb__map { aspect-ratio: 4 / 3; }
}

/* ==========================================================================
   23. Welcome block (homepage, directly under the hero)
   ========================================================================== */
.welcome {
  display: grid;
  gap: var(--sp-6);
  align-items: center;
}
@media (min-width: 900px) {
  /* Mirrors the old site's 4/8 column split */
  .welcome { grid-template-columns: 1fr 2fr; gap: clamp(2.5rem, 5vw, 4.5rem); }
}
.welcome__art { display: grid; place-items: center; }
.welcome__art img {
  width: min(100%, 300px);
  height: auto;
}
/* The artwork is a near-black silhouette on transparency, so it disappears
   against a dark page. Inverting the RGB flips it to off-white; alpha is
   untouched, so the anti-aliased edges stay clean. */
[data-theme="dark"] .welcome__art img {
  filter: invert(1);
  opacity: 0.9;
}

.welcome__body > p + p { margin-top: var(--sp-4); }
.welcome__body .lead { color: var(--text); }
.welcome__body > p:last-child {
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* --- Headings held on a single line --------------------------------------
   These titles wrapped not because the page was narrow but because
   .section-heading caps its block at 660px, while the text needs more —
   "Welcome to Eyes Pixel Photography" wants 727px at the 44px size and
   "Sixteen kinds of shoot, one studio" wants 685px, with 1152px going spare
   in the container either side.

   So: --wide lifts the cap, and --1line sizes the text so it can never
   outrun the room it has. min() takes the normal --fs-h2 whenever that fits
   and derives a size from the viewport when it does not, which means
   `nowrap` can never push the page into horizontal scroll.

   --h1line is the measured width of that specific string per 1px of font
   size, so it belongs on the element rather than in here. Measure with a
   100px off-screen span and add ~5% slack so the line never sits flush
   against the container padding:
     "Welcome to Eyes Pixel Photography"  16.51 -> 17.2
     "Sixteen kinds of shoot, one studio" 15.58 -> 16.3               */
.section-heading--wide { max-width: none; }
/* Lifting the cap would drag any body copy out to the full container width,
   so re-cap that at a readable measure. */
.section-heading--wide > p:not(.eyebrow) { max-width: 62ch; margin-inline: auto; }

.heading--1line {
  white-space: nowrap;
  font-size: min(var(--fs-h2), calc((100vw - 3.2rem) / var(--h1line, 17.2)));
}
/* Below ~350px a single line would render smaller than body copy, which reads
   as broken rather than deliberate. Let it wrap on those few devices. */
@media (max-width: 350px) {
  .heading--1line { white-space: normal; font-size: var(--fs-h2); }
}

/* --- Theme toggle beside the header CTA -----------------------------------
   The toggle sat immediately after the logo, ~770px away from "Book a
   session". Reordered with flex `order` rather than moved in the markup:
   .header__cta is display:none below 1024px, so relocating the button into
   it would make the theme switch vanish on phones. Scoping the reorder to
   the desktop breakpoint leaves the mobile row (toggle + hamburger, pushed
   right by .header__tools' margin-left:auto) exactly as it was. */
@media (min-width: 1024px) {
  /* .brand and .nav keep the default order:0, so these land after both. */
  .header__tools { order: 1; }
  .header__cta   { order: 2; }
}

/* ==========================================================================
   24. Service page hero
   ========================================================================== */

/* CTA row + social proof, sat side by side under the intro. */
.page-hero__actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4) var(--sp-5);
  margin-top: var(--sp-6);
}

/* The base .rating-badge is built for the dark quotes band — translucent
   white borders, #ffb27a numeral, white text. On a light surface that is
   almost invisible, so this variant restates it in tokens and themes with
   the rest of the page. */
.rating-badge--surface {
  margin: 0;
  border-color: var(--border-strong);
  background: var(--card);
  backdrop-filter: none;
  color: var(--text);
}
.rating-badge--surface:hover {
  border-color: var(--ink);
  background: var(--surface-2);
  color: var(--text);
}
.rating-badge--surface .rating-badge__score { color: var(--primary-dark); }
.rating-badge--surface .rating-badge__text strong { color: var(--ink); }

@media (max-width: 560px) {
  .page-hero__actions { gap: var(--sp-4); }
  .page-hero__actions .btn-row { width: 100%; }
  .page-hero__actions .btn { flex: 1 1 auto; }
}

/* ==========================================================================
   25. Interiors mega-menu + hub
   ========================================================================== */
/* Eight categories need more room than the 3-column services menu. The base
   .mega is anchored right:0 to its nav item, which works for a 760px panel
   hanging off an item near the end of the nav — but at 1020px from an item
   mid-nav it ran ~290px off the left edge of the screen. Centre it on the
   item instead and clamp to the viewport. `translate` is a separate property
   from `transform`, so it composes with the open/close animation rather than
   overwriting it. */
/* Everything here is scoped to the desktop breakpoint. Below 1024px the mega
   panels are `position: static` inside the off-canvas drawer, so absolute
   positioning and multi-column grids must not leak into them. */
@media (min-width: 1024px) {
  .mega--wide { width: min(1020px, calc(100vw - 3rem)); }
  .mega--wide .mega__grid { row-gap: var(--sp-5); grid-template-columns: repeat(3, 1fr); }

  /* Applies to BOTH mega menus. The base rule anchors right:0 to the nav item,
     which only stays on screen while that item sits near the end of the nav —
     adding a seventh nav item shifted Services left and pushed its panel ~140px
     off the edge. Centring on the item is stable wherever the item ends up.
     `translate` is a separate property from `transform`, so it composes with
     the open/close animation instead of overwriting it. */
  .mega {
    left: 50%;
    right: auto;
    translate: -50% 0;
  }
}
@media (min-width: 1200px) {
  .mega--wide .mega__grid { grid-template-columns: repeat(4, 1fr); }
}

/* Category headings in the mega menu are links, not plain labels. */
.mega__head {
  color: inherit;
  text-decoration: none;
}
.mega__head:hover { color: #ffd0aa; text-decoration: underline; }

/* Sub-service lists on the hub cards */
.interior-list {
  list-style: none;
  margin: 0 0 var(--sp-4);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.interior-list li {
  padding: 0.25rem 0.6rem;
  border: 1px solid var(--border);
  border-radius: 100px;
  background: var(--surface);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  line-height: 1.5;
}
/* Anchor targets must clear the sticky header */
.interior-list li[id], .card[id] { scroll-margin-top: calc(var(--header-h) + 1.5rem); }

/* The hub reuses .hero__meta for the service-area chips, but that component is
   built for the dark hero — restate it in tokens for a light card. */
.card .hero__meta span {
  border-color: var(--border);
  background: var(--surface);
  backdrop-filter: none;
  color: var(--text-muted);
}


/* Seven nav items, the theme toggle and the CTA button do not fit between the
   1024px desktop breakpoint and roughly 1200px — the header overflowed by
   ~30px at exactly 1024. Tighten the link padding and header gap through that
   band rather than dropping an item from the nav. */
/* Seven nav items including a 120px "Ceremonies" label. Measured at 1024 and
   1200: the CTA clears with these values. Adding an eighth item overflowed the
   button off screen, which is why Careers moved to the footer - if another is
   ever added, move the hamburger breakpoint up rather than shrinking this
   further. */
@media (min-width: 1024px) and (max-width: 1199px) {
  .site-header__inner { gap: var(--sp-3); }
  .nav__list { gap: 2px; }
  .nav__link { padding-inline: 0.5rem; }
  .header__cta .btn { padding-inline: 1rem; }
}

/* ==========================================================================
   26. Interior landing pages
   ========================================================================== */
/* Sticky "how it works" panel beside the detail copy — the second conversion
   point on the page, after the hero and before the closing band. */
.quote-card {
  padding: var(--sp-6);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-sm);
}
.quote-card__steps {
  counter-reset: qstep;
  list-style: none;
  margin: 0 0 var(--sp-5);
  padding: 0;
  display: grid;
  gap: var(--sp-4);
}
.quote-card__steps li { position: relative; padding-left: 2.6rem; font-size: var(--fs-sm); color: var(--text-muted); }
.quote-card__steps li strong { display: block; color: var(--ink); }
.quote-card__steps li::before {
  counter-increment: qstep;
  content: counter(qstep);
  position: absolute;
  left: 0; top: -0.1em;
  display: grid;
  place-items: center;
  width: 28px; height: 28px;
  border: 1px solid var(--border-strong);
  border-radius: 50%;
  background: var(--surface);
  color: var(--primary-dark);
  font-weight: 700;
  font-size: var(--fs-xs);
}
.quote-card__foot { padding-top: var(--sp-5); border-top: 1px solid var(--border); }
.quote-card__foot p { margin: var(--sp-3) 0 0; font-size: var(--fs-xs); color: var(--text-muted); }

/* Interior list items on the hub are links now */
.interior-list li a { color: var(--text-muted); text-decoration: none; }
.interior-list li:hover { border-color: var(--primary); background: var(--primary-soft); }
.interior-list li:hover a { color: var(--primary-dark); }

/* .split--top sticks its FIRST column, which on the FAQ layout is the short
   one. On interior pages the short column is the quote card in second
   position, so swap which side sticks — sticking the taller copy column does
   nothing useful. */
@media (min-width: 900px) {
  .split--top:has(.quote-card) > :first-child { position: static; }
  .quote-card { position: sticky; top: calc(var(--header-h) + var(--sp-6)); }
}


/* ==========================================================================
   27. Hero video facade + lightbox
   ========================================================================== */

/* Two-column hero: copy left, video right. Only on pages that opt in. */
.page-hero--video .page-hero__grid { display: grid; gap: var(--sp-6); align-items: center; }
@media (min-width: 900px) {
  .page-hero--video .page-hero__grid {
    grid-template-columns: 1.15fr 1fr;
    gap: clamp(2rem, 4vw, 3.5rem);
  }
}

/* --- Poster + play button ------------------------------------------------
   A button, not a div: it is the control that opens the player, so it has to
   be reachable and operable from the keyboard for free. */
.video-facade {
  position: relative;
  display: block;
  width: 100%;
  padding: 0;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface-2);
  cursor: pointer;
  transition: border-color 0.2s var(--ease), transform 0.25s var(--ease),
    box-shadow 0.25s var(--ease);
}
.video-facade:hover {
  border-color: var(--border-strong);
  transform: translateY(-2px);
  box-shadow: var(--shadow);
}
/* hqdefault is 4:3 with letterbox bars; cover-crop to the 16:9 frame */
.video-facade__poster {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.5s var(--ease);
}
.video-facade:hover .video-facade__poster { transform: scale(1.04); }

.video-facade__play {
  position: absolute;
  left: 50%; top: 50%;
  translate: -50% -50%;
  display: grid;
  place-items: center;
  width: 68px; height: 68px;
  border-radius: 50%;
  background: var(--primary);
  color: #fff;
  box-shadow: 0 8px 26px -8px rgba(0, 0, 0, 0.6);
  transition: transform 0.25s var(--ease), background-color 0.2s var(--ease);
}
.video-facade__play svg { width: 26px; height: 26px; margin-left: 3px; }
.video-facade:hover .video-facade__play { transform: scale(1.08); }
.video-facade:focus-visible { outline: 2px solid var(--secondary-dark); outline-offset: 3px; }

.video-facade__label {
  position: absolute;
  left: 12px; bottom: 12px;
  padding: 5px 11px;
  border-radius: 100px;
  background: rgba(10, 9, 8, 0.72);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: var(--fs-xs);
  font-weight: 600;
  line-height: 1.5;
}

/* --- Lightbox -------------------------------------------------------------
   Blurred backdrop, video at full width. Built on <dialog>, so Esc, focus
   trapping and the backdrop element all come from the browser. */
.video-lightbox {
  width: min(94vw, 1400px);
  max-width: none;
  padding: 0;
  border: 0;
  background: transparent;
  overflow: visible;
}
.video-lightbox::backdrop {
  background: rgba(8, 7, 6, 0.72);
  backdrop-filter: blur(16px) saturate(0.9);
}
.video-lightbox__stage {
  position: relative;
  aspect-ratio: 16 / 9;
  overflow: hidden;
  border-radius: var(--radius-lg);
  background: #000;
  box-shadow: 0 30px 80px -30px rgba(0, 0, 0, 0.9);
}
.video-lightbox__stage iframe {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  border: 0;
  display: block;
}
.video-lightbox__close {
  position: absolute;
  top: -52px;
  right: 0;
  display: grid;
  place-items: center;
  width: 44px; height: 44px;
  border: 1px solid rgba(255, 255, 255, 0.28);
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.45);
  color: #fff;
  cursor: pointer;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.video-lightbox__close:hover { background: rgba(0, 0, 0, 0.85); border-color: #fff; }
.video-lightbox__close svg { width: 20px; height: 20px; }
@media (max-width: 560px) {
  .video-lightbox { width: 96vw; }
  .video-lightbox__close { top: -46px; }
  .video-facade__play { width: 56px; height: 56px; }
  .video-facade__play svg { width: 22px; height: 22px; }
}

/* --- Video hero: typography and balance ----------------------------------
   The shared --fs-h1 tops out at 4rem, which is right for a full-width hero
   but not for a two-column one: "Interior & Architectural Photography in
   Pune" ran to FOUR lines and 294px in a 589px column, pushing the intro and
   the CTAs down and leaving the video looking like an afterthought beside it.

   Smaller display size, tighter leading and tracking, and even columns so the
   poster carries real weight.

   Note the stack renders as the system UI font: --font-sans names Inter and
   --font-display names Fraunces, but neither is ever loaded. That is a
   reasonable performance choice — it just means the tuning below is done
   against the fallback, which is what visitors actually see. */
.page-hero--video h1 {
  font-size: clamp(1.9rem, 2.6vw + 0.85rem, 2.9rem);
  line-height: 1.06;
  letter-spacing: -0.03em;
  margin-bottom: var(--sp-4);
  /* Prefer a balanced break over a ragged last word */
  text-wrap: balance;
}
.page-hero--video .breadcrumb { margin-bottom: var(--sp-3); }
.page-hero--video .page-hero__grid > :first-child > p {
  max-width: 46ch;
  font-size: var(--fs-lg);
  line-height: 1.55;
}
.page-hero--video .page-hero__actions { margin-top: var(--sp-5); }

@media (min-width: 900px) {
  /* Even columns: the poster was 512px next to a 589px block of type. */
  .page-hero--video .page-hero__grid { grid-template-columns: 1fr 1fr; }
}

/* Scrim under the label so it stays readable over a bright frame */
.video-facade::after {
  content: "";
  position: absolute;
  inset: auto 0 0 0;
  height: 42%;
  background: linear-gradient(to top, rgba(10, 9, 8, 0.55), transparent);
  pointer-events: none;
}
.video-facade__label { z-index: 1; background: rgba(10, 9, 8, 0.55); }

/* --- Interior film grid (portfolio) --------------------------------------- */
.video-grid {
  display: grid;
  gap: var(--sp-5);
  grid-template-columns: 1fr;
}
@media (min-width: 640px)  { .video-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .video-grid { grid-template-columns: repeat(4, 1fr); } }

.video-card { margin: 0; display: flex; flex-direction: column; gap: var(--sp-4); }
.video-card figcaption h3 { font-size: var(--fs-lg); margin-bottom: var(--sp-2); }
.video-card figcaption p { font-size: var(--fs-sm); color: var(--text-muted); margin-bottom: 0; }
.video-card__meta {
  margin-top: var(--sp-3) !important;
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
}
/* The facade sizes itself to the hero column by default; in the grid it just
   fills its cell. */
.video-card .video-facade-wrap { width: 100%; }
@media (min-width: 1100px) {
  /* Four across makes the 68px play button overpower a small poster */
  .video-grid .video-facade__play { width: 52px; height: 52px; }
  .video-grid .video-facade__play svg { width: 20px; height: 20px; }
}

/* --- Legacy fallbacks -----------------------------------------------------
   Features used above that fail hard rather than softly, if unsupported. */

/* The mega menus centre with `left:50%` + the standalone `translate` property,
   chosen so it composes with the open/close `transform` rather than fighting
   it. Without `translate` (Chrome < 104, Safari < 14.1) the panel is left
   offset by half the viewport — a badly misplaced menu, not a lost nicety.
   Fold the centring into `transform` for those browsers. */
@supports not (translate: 0px) {
  @media (min-width: 1024px) {
    .mega { transform: translate(-50%, -6px); }
    .nav__toggle[aria-expanded="true"] + .mega { transform: translate(-50%, 0); }
  }
}

/* Without `aspect-ratio` (Safari < 15) an absolutely-positioned iframe leaves
   its container with no height at all, so the map and the lightbox video
   collapse to nothing. Fall back to the old padding-top ratio box. */
@supports not (aspect-ratio: 16 / 9) {
  .gmb__map, .video-lightbox__stage { height: 0; padding-top: 56.25%; }
  .video-facade { height: 0; padding-top: 56.25%; }
  .video-facade__poster { position: absolute; inset: 0; }
}

/* --- Full service catalogue (/services) ----------------------------------- */
.catalogue { display: grid; gap: var(--sp-6); }
@media (min-width: 700px)  { .catalogue { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px) { .catalogue { grid-template-columns: repeat(3, 1fr); } }

.catalogue__group { scroll-margin-top: calc(var(--header-h) + 1.5rem); }
.catalogue__group h3 {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-bottom: var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid var(--border);
  font-size: var(--fs-lg);
}
.catalogue__icon {
  display: grid;
  place-items: center;
  flex: none;
  width: 34px; height: 34px;
  border-radius: 50%;
  background: var(--primary-soft);
  color: var(--primary-dark);
}
.catalogue__icon svg { width: 17px; height: 17px; }
.catalogue__n {
  margin-left: auto;
  padding: 1px 8px;
  border-radius: 100px;
  background: var(--surface-2);
  color: var(--text-muted);
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  font-weight: 600;
}
.catalogue__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 2px; }
.catalogue__list a {
  display: block;
  padding: 0.3rem 0.5rem;
  margin-inline: -0.5rem;
  border-radius: var(--radius);
  color: var(--text);
  font-size: var(--fs-sm);
  text-decoration: none;
  transition: background-color 0.15s var(--ease), color 0.15s var(--ease);
}
.catalogue__list a:hover { background: var(--surface-2); color: var(--primary-dark); }
/* Entries without a page of their own route to the enquiry form */
.catalogue__list a.catalogue__ask { color: var(--text-muted); }

/* "+N more" in the mega menu */
.mega__more { color: #ffb27a !important; font-weight: 600; }

/* --- Full-width mega menu -------------------------------------------------
   Ten categories at 1020px wide ran three rows deep and past the bottom of
   the viewport, so the last two categories could not be reached at all.
   Full width gives five columns, which fits ten categories in two rows.

   `position: fixed` escapes the nav item's containing block; the inner grid
   is then constrained back to the site container so the content still lines
   up with the rest of the page. */
@media (min-width: 1024px) {
  .mega--wide {
    position: fixed;
    top: var(--header-h);
    left: 0;
    right: 0;
    width: 100%;
    max-width: none;
    translate: none;                 /* undo the centring used by the narrow menu */
    border-left: 0;
    border-right: 0;
    border-radius: 0 0 var(--radius-lg) var(--radius-lg);
    padding: var(--sp-6) 0 var(--sp-5);
    /* Never taller than the space under the header; scroll if it ever is */
    max-height: calc(100vh - var(--header-h) - 1rem);
    overflow-y: auto;
    overscroll-behavior: contain;
  }

  /* Invisible bridge across the gap between the nav link and the panel.
     Without it the pointer leaves the nav item on the way down and the menu
     closes before you reach it. It is a DOM descendant, so hovering it keeps
     the parent hovered. */
  .mega--wide::before {
    content: "";
    position: absolute;
    top: calc(var(--header-h) * -1);
    left: 0;
    right: 0;
    height: var(--header-h);
  }

  .mega--wide .mega__grid {
    max-width: var(--container);
    margin-inline: auto;
    padding-inline: var(--sp-5);
    grid-template-columns: repeat(5, 1fr);
    align-items: start;              /* ragged column heights, not stretched */
    row-gap: var(--sp-6);
  }
  .mega--wide .mega__foot {
    max-width: var(--container);
    margin-inline: auto;
    padding-inline: var(--sp-5);
  }

  /* The leading dash pushed longer category names onto a second line, which
     is what made the header row look broken. Drop it inside the menu. */
  .mega__grid .eyebrow::before,
  .mega__grid .eyebrow::after { display: none; }
  .mega__grid .eyebrow {
    display: block;
    letter-spacing: 0.08em;
    line-height: 1.35;
    min-height: 2.7em;               /* two-line names still align their lists */
  }
}

/* The panel was landing exactly on its max-height, so a scrollbar appeared and
   knocked the centred grid 7.5px out of line with the header container.
   Tighter rows keep it under the limit; `scrollbar-gutter` keeps the alignment
   honest if a longer menu ever does overflow. */
@media (min-width: 1024px) {
  .mega--wide { scrollbar-gutter: stable both-edges; padding-top: var(--sp-5); }
  .mega--wide .mega__grid { row-gap: var(--sp-5); column-gap: var(--sp-4); }
  .mega--wide .mega__link { padding-block: 0.32rem; }
  .mega--wide .mega__grid .eyebrow { min-height: 2.4em; margin-bottom: .35rem !important; }
  .mega--wide .mega__foot { margin-top: var(--sp-3); padding-top: var(--sp-3); }
}

/* --- Long-form service body ----------------------------------------------
   Spans the full container. A single 1150px column would put ~115 characters
   on a line, which is roughly twice a comfortable measure, so the width is
   spent on an editorial split instead: the sub-heading takes the left third
   and the prose the right two thirds. That lands the text at ~70 characters
   a line — about ideal — while nothing is left empty. */
.service-body { display: grid; gap: var(--sp-6); counter-reset: bodysec; }

.body-row { display: grid; gap: var(--sp-3); }
.body-row + .body-row { padding-top: var(--sp-6); border-top: 1px solid var(--border); }
.body-row h2 { margin: 0; font-size: var(--fs-h3); }
.body-row__text > p {
  margin-bottom: var(--sp-4);
  font-size: var(--fs-lg);
  line-height: 1.7;
  color: var(--text);
}
.body-row__text > p:last-child { margin-bottom: 0; }

@media (min-width: 900px) {
  .service-body { gap: var(--sp-7); }
  .body-row {
    grid-template-columns: 1fr 2fr;
    gap: clamp(2rem, 4vw, 4rem);
    align-items: start;
  }
  .body-row + .body-row { padding-top: var(--sp-7); }
  /* The heading follows its own paragraphs down a long section */
  .body-row h2 { position: sticky; top: calc(var(--header-h) + var(--sp-5)); }
}

/* --- Long-form body: numbering, accent and lead ---------------------------
   Gives the section a visual rhythm without touching the measure. The number
   and rule sit in the heading column, which is otherwise mostly whitespace on
   a wide screen. */
.body-row h2 {
  position: relative;
  padding-top: var(--sp-4);
}
.body-row h2::before {
  counter-increment: bodysec;
  content: counter(bodysec, decimal-leading-zero);
  position: absolute;
  top: 0;
  left: 0;
  font-size: var(--fs-xs);
  font-weight: 700;
  letter-spacing: 0.14em;
  color: var(--primary-dark);
}
/* Short accent rule under the number, echoing the .eyebrow treatment */
.body-row h2::after {
  content: "";
  position: absolute;
  top: 0.55em;
  left: 2.1em;
  width: 28px;
  height: 2px;
  background: var(--primary);
  opacity: 0.55;
}

/* The opening paragraph of the section reads as a lead */
.body-row:first-child .body-row__text > p:first-child {
  font-size: clamp(1.2rem, 0.6vw + 1.05rem, 1.5rem);
  line-height: 1.55;
  letter-spacing: -0.01em;
  color: var(--ink);
}

/* Slightly stronger separation between sections than a plain hairline */
.body-row + .body-row {
  border-top: 1px solid var(--border);
}
@media (min-width: 900px) {
  /* Vertical accent beside the sticky heading, so the left column reads as a
     deliberate column rather than leftover space */
  .body-row h2 { padding-left: var(--sp-4); }
  .body-row h2::before { left: var(--sp-4); }
  .body-row h2::after { left: calc(var(--sp-4) + 2.1em); }
  .body-row h2 {
    border-left: 2px solid var(--border);
    margin-left: calc(var(--sp-4) * -1);
  }
}

/* ==========================================================================
   28. Often booked together — curated cross-links
   Text links rather than cards: this block sits directly under a card grid,
   and a second grid reads as more of the same. It is also the only related
   block the interior pages can use, since they have no photographs.
   ========================================================================== */

.section--tight { padding-block: var(--sp-7); }

.xlinks {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: var(--sp-4);
  grid-template-columns: 1fr;
}

@media (min-width: 640px) { .xlinks { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .xlinks { grid-template-columns: repeat(4, 1fr); } }

.xlink {
  position: relative;
  padding: var(--sp-4) var(--sp-4) var(--sp-4) var(--sp-5);
  border-left: 2px solid var(--border);
  transition: border-color .18s ease, background-color .18s ease;
}

.xlink:hover { border-left-color: var(--primary); background: var(--surface-2); }

.xlink__title {
  display: inline-block;
  font-weight: 600;
  color: var(--primary-dark);
  text-decoration: none;
  line-height: 1.3;
}

/* Whole tile clickable, without nesting the blurb inside the anchor. */
.xlink__title::after {
  content: "";
  position: absolute;
  inset: 0;
}

.xlink:hover .xlink__title { text-decoration: underline; text-underline-offset: 3px; }

.xlink__blurb {
  margin: var(--sp-2) 0 0;
  font-size: 0.9375rem;
  line-height: 1.5;
  color: var(--text-muted);
}

@media (prefers-reduced-motion: reduce) {
  .xlink { transition: none; }
}

/* ==========================================================================
   29. Service-area text on /contact and category intros on /portfolio
   Both exist because seo_content.md §4.6 asked for crawlable text where there
   was only a map or only photographs.
   ========================================================================== */

.areas {
  margin-top: var(--sp-6);
  padding: var(--sp-5);
  background: var(--surface-2);
  border-radius: var(--radius-lg);
}

.areas h3 {
  margin: 0 0 var(--sp-3);
  font-size: 1.125rem;
}

.areas p {
  margin: 0 0 var(--sp-3);
  color: var(--text-muted);
  line-height: 1.65;
}

.areas p:last-child { margin-bottom: 0; }
.areas strong { color: var(--text); font-weight: 600; }

.pcat {
  padding: var(--sp-5);
  background: var(--card);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.pcat h3 {
  margin: 0;
  font-size: 1.25rem;
}

.pcat p {
  margin: 0;
  color: var(--text-muted);
  line-height: 1.65;
  flex: 1;
}

/* ==========================================================================
   30. Local-intent "near you" block on the service and interior pages
   Reuses .areas from /contact; --wide centres it and gives it room to breathe
   as a full section rather than a sidebar note.
   ========================================================================== */
.areas--wide {
  max-width: none;
  margin-top: 0;
  padding: clamp(1.5rem, 3vw, 2.75rem) clamp(1.25rem, 3vw, 2.75rem);
  text-align: left;
}

/* Three paragraphs, three columns above 900px. Full width with one 1100px
   line length is unreadable; columns keep each line near 60 characters while
   the panel itself still spans the container. */
.areas__cols {
  display: grid;
  gap: var(--sp-4);
}

@media (min-width: 900px) {
  .areas__cols {
    grid-template-columns: repeat(3, 1fr);
    gap: var(--sp-6);
  }
}

.areas__cols p:last-child { margin-bottom: 0; }
.areas__cta { margin-top: var(--sp-5); }

.areas--wide h2 {
  margin: 0 0 var(--sp-4);
  font-size: clamp(1.5rem, 1.4vw + 1.1rem, 2rem);
}

.areas--wide p {
  font-size: 1.0625rem;
}
