/* Wallcovering Pro: cinematic editorial, strict black/white/gray, League Spartan throughout. */

/* Self-hosted variable family from the official Instrument Sans project. */
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url('/assets/fonts/instrument-sans-variable.woff2') format('woff2-variations');
}

@font-face {
  font-family: 'Instrument Sans';
  font-style: italic;
  font-weight: 400 700;
  font-stretch: 75% 100%;
  font-display: swap;
  src: url('/assets/fonts/instrument-sans-italic-variable.woff2') format('woff2-variations');
}

/* Self-hosted League Spartan family used throughout the site. */
@font-face {
  font-family: 'League Spartan';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/assets/fonts/league-spartan-regular.ttf') format('truetype');
}

@font-face {
  font-family: 'League Spartan';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/assets/fonts/league-spartan-medium.ttf') format('truetype');
}

@font-face {
  font-family: 'League Spartan';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/assets/fonts/league-spartan-semibold.ttf') format('truetype');
}

@font-face {
  font-family: 'League Spartan';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/assets/fonts/league-spartan-bold.ttf') format('truetype');
}

:root {
  /* palette — strictly grayscale, no accent color */
  --paper: #FFFFFF;
  --ink: #0A0A0A;
  --ink-2: #1A1A1A;
  --gray-1: #F2F2F0;
  --gray-2: #8C8C8C;
  --gray-3: #D8D8D6;
  --gray-4: #B5B5B5;
  --body-copy-shadow: -22px 50px 92px rgba(138, 43, 226, 0.58);

  /* legacy aliases — keeps any not-yet-restyled page/inline style on the new palette */
  --black: var(--ink);
  --white: var(--paper);
  --green: var(--gray-2);
  --gray: var(--gray-2);
  --gray-light: var(--gray-3);
  --mono: var(--sans);
  --bone: var(--paper);
  --bone-deep: var(--gray-1);
  --brass: var(--gray-2);
  --brass-deep: var(--ink);
  --line: var(--gray-3);

  --border-width: 1px;

  /* One family throughout, with weight supplying hierarchy. */
  --font-display-family: 'League Spartan';
  --font-body-family: 'League Spartan';
  --font-display: var(--font-display-family), -apple-system, BlinkMacSystemFont, sans-serif;
  --font-body: var(--font-body-family), -apple-system, BlinkMacSystemFont, sans-serif;

  /* aliases kept so existing rules and any inline styles keep resolving */
  --sans: var(--font-body);
  --serif: var(--font-display);

  /* ---- Type scale ----
     Fluid by default; mobile-specific overrides live in the 600px block, so mobile
     is tuned deliberately rather than inherited from a shrinking desktop scale. */
  --step-h1: clamp(2.8rem, 6.6vw, 5.8rem);
  --step-h2: clamp(1.9rem, 3.4vw, 3rem);
  --step-h3: 1.3rem;
  --step-body: 1.05rem;
  --step-lede: 1.15rem;
  --step-label: 0.74rem;
  --step-nav: 0.78rem;
  --step-btn: 0.8rem;
  --step-caption: 0.78rem;

  --leading-tight: 1.02;
  --leading-head: 1.1;
  --leading-body: 1.75;
  --tracking-label: 0.16em;

  --max-width: 1280px;
  --space-sm: 16px;
  --space-md: 24px;
  --space-lg: 48px;
  --space-xl: 72px;
  --space-2xl: 120px;

  /* ---- Single horizontal gutter token ----
     Header, footer and every section read from this. Components must not carry
     their own hardcoded horizontal padding. */
  --gutter: 32px;

  /* ---- Breakpoints (documentation only; CSS vars are not valid in @media) ----
     The site uses exactly three, and every media query in this file matches one:
       600px   phone            below this, single column and mobile type scale
       900px   tablet/stack     below this, nav collapses and multi-column grids stack
       1200px  compact desktop  below this, secondary header content is dropped
     Do not introduce a fourth without changing it here first. The old set
     (560/700/768/780/880/900/1400) is what made the tablet range incoherent. */
  --bp-sm: 600px;
  --bp-md: 900px;
  --bp-lg: 1200px;

  --tap-min: 44px;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { scroll-behavior: auto; }

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

body {
  font-family: var(--sans);
  color: var(--ink);
  background: var(--paper);
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

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

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

.skip-link {
  position: fixed;
  top: 10px;
  left: max(var(--gutter), env(safe-area-inset-left, 0px));
  z-index: 200;
  padding: 12px 16px;
  background: var(--paper);
  color: var(--ink);
  font-size: 0.82rem;
  font-weight: 700;
  transform: translateY(-160%);
}

.skip-link:focus { transform: translateY(0); }

:where(a, button, input, textarea):focus-visible {
  outline: 3px solid currentColor;
  outline-offset: 4px;
}

main:focus { outline: none; }

.wrap {
  max-width: var(--max-width);
  margin: 0 auto;
  padding-right: max(var(--gutter), env(safe-area-inset-right, 0px));
  padding-left: max(var(--gutter), env(safe-area-inset-left, 0px));
}

.label {
  font-family: var(--sans);
  font-size: var(--step-label);
  letter-spacing: var(--tracking-label);
  font-weight: 600;
  color: #6E6E6E; /* var(--gray-2) is only 3.36:1 against white/paper, fails WCAG AA for this small text; darkened just enough to clear 4.5:1. Dark-background overrides below (hero, section-alt) use --gray-4 and are unaffected. */
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--serif);
  font-weight: 600;
  font-stretch: 92%;
  line-height: 1.1;
  color: var(--ink);
}

h1 { font-size: var(--step-h1); letter-spacing: -0.01em; line-height: var(--leading-tight); }
h2 { font-size: var(--step-h2); letter-spacing: -0.01em; margin-bottom: 0.55em; line-height: var(--leading-head); }
h3 { font-size: var(--step-h3); margin-bottom: 0.45em; }

p {
  font-size: var(--step-body);
  line-height: var(--leading-body);
  color: #333333;
  text-shadow: var(--body-copy-shadow);
}

main li { text-shadow: var(--body-copy-shadow); }

/* ---------- Buttons — alive, responsive hover feedback ---------- */
.btn, .btn-outline, .btn-green {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--sans);
  font-size: 0.8rem;
  letter-spacing: 0.06em;
  font-weight: 600;
  padding: 16px 30px;
  border: 1.5px solid var(--ink);
  background: transparent;
  color: var(--ink);
  overflow: hidden;
  cursor: pointer;
  z-index: 0;
  transition: color 250ms cubic-bezier(.4,0,.2,1);
}

.btn::before, .btn-outline::before, .btn-green::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--ink);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 250ms cubic-bezier(.4,0,.2,1);
  z-index: -1;
}

.btn:hover, .btn-outline:hover, .btn-green:hover { color: var(--paper); }
.btn:hover::before, .btn-outline:hover::before, .btn-green:hover::before { transform: scaleX(1); }

/* buttons on dark backgrounds (section-alt panels, the video hero) invert to light-on-dark */
.section-alt .btn, .section-alt .btn-outline, .section-alt .btn-green,
.hero-video .btn, .hero-video .btn-outline, .hero-video .btn-green {
  border-color: var(--paper);
  color: var(--paper);
}

.section-alt .btn::before, .section-alt .btn-outline::before, .section-alt .btn-green::before,
.hero-video .btn::before, .hero-video .btn-outline::before, .hero-video .btn-green::before {
  background: var(--paper);
}

.section-alt .btn:hover, .section-alt .btn-outline:hover, .section-alt .btn-green:hover,
.hero-video .btn:hover, .hero-video .btn-outline:hover, .hero-video .btn-green:hover {
  color: var(--ink);
}

/* ---------- Header ----------
   Reference read: the reference site gives its lockup real vertical air, runs the nav
   as plain wide-tracked caps with no button chrome, and carries no heavy divider. The
   previous header failed on all three: a 30px badge jammed into the corner, a default
   bordered MENU box, and a hard 1px border under everything.

   Default state is transparent over the video hero. Once scrolled past it the bar
   condenses and picks up a paper background with a hairline, so the page gains a
   navigation surface without ever announcing itself. */
:root {
  --header-height: 104px;
  --header-height-condensed: 68px;
}

#site-header {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  z-index: 100;
  color: var(--ink);
  background: transparent;
  border-bottom: 1px solid transparent;
  transition: background 420ms cubic-bezier(.4,0,.2,1),
              border-color 420ms ease,
              backdrop-filter 420ms ease;
  padding-top: env(safe-area-inset-top, 0px);
}

/* Condensed: applied by animate.js once the hero is behind us. */
#site-header.is-condensed {
  background: rgba(255,255,255,0.88);
  backdrop-filter: blur(18px) saturate(140%);
  -webkit-backdrop-filter: blur(18px) saturate(140%);
  border-bottom-color: var(--gray-3);
}

/* Interior pages have no video hero, so they start condensed. */
body:not(.has-hero-video) #site-header { background: rgba(255,255,255,0.88); backdrop-filter: blur(18px) saturate(140%); -webkit-backdrop-filter: blur(18px) saturate(140%); border-bottom-color: var(--gray-3); }

main { padding-top: calc(var(--header-height) + env(safe-area-inset-top, 0px)); }
body.has-hero-video main { padding-top: 0; }

.header-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-lg);
  height: var(--header-height);
  transition: height 420ms cubic-bezier(.4,0,.2,1);
  /* The overlay is a sibling inside #site-header, which is its own stacking context.
     Without an explicit z-index here the overlay (90) paints over the bar and swallows
     taps on the close control, leaving the menu impossible to dismiss. */
  position: relative;
  z-index: 95;
  padding-left: max(var(--gutter), env(safe-area-inset-left, 0px));
  padding-right: max(var(--gutter), env(safe-area-inset-right, 0px));
}

#site-header.is-condensed .header-bar { height: var(--header-height-condensed); }

/* ---- Lockup: badge plus a two-line wordmark, so the mark reads as a brand rather
   than a favicon. The wordmark is set in the display face at small size with wide
   tracking, which is where the editorial character comes from. ---- */
.logo-link {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-shrink: 0;
  transition: opacity 250ms ease;
}

.logo-link:hover, .logo-link:active { opacity: 0.62; }

.logo-mark {
  height: 52px;
  width: 52px;
  transition: height 420ms cubic-bezier(.4,0,.2,1), width 420ms cubic-bezier(.4,0,.2,1), filter 300ms ease;
}

#site-header.is-condensed .logo-mark { height: 40px; width: 40px; }

.logo-word { display: flex; flex-direction: column; line-height: 1; }

.logo-word-1 {
  font-family: var(--serif);
  font-size: 0.94rem;
  letter-spacing: 0.26em;
  font-weight: 600;
}

.logo-word-2 {
  font-family: var(--sans);
  font-size: 0.6rem;
  letter-spacing: 0.52em;
  font-weight: 500;
  color: #6E6E6E;
  margin-top: 6px;
  padding-left: 0.26em; /* optical: balances the trailing letterspace above */
}

/* White-out over the video hero. */
body.has-hero-video #site-header:not(.is-condensed) .logo-mark { filter: invert(1); }
body.has-hero-video #site-header:not(.is-condensed) .logo-word-1 { color: var(--paper); }
body.has-hero-video #site-header:not(.is-condensed) .logo-word-2 { color: rgba(255,255,255,0.72); }

/* ---- Nav: plain tracked caps. The only affordance is a hairline that draws in from
   the left, which is enough at this scale and avoids button chrome. ---- */
nav.primary-nav { display: flex; align-items: center; gap: 26px; flex-shrink: 1; min-width: 0; }

nav.primary-nav a {
  position: relative;
  font-family: var(--sans);
  font-size: 0.85rem;
  letter-spacing: 0.2em;
  font-weight: 500;
  color: var(--ink);
  padding: 8px 0;
  white-space: nowrap;
  transition: color 300ms ease, opacity 250ms ease;
}

body.has-hero-video #site-header:not(.is-condensed) nav.primary-nav a { color: var(--paper); }

nav.primary-nav a::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform 380ms cubic-bezier(.4,0,.2,1);
}

nav.primary-nav a:hover::after,
nav.primary-nav a:active::after,
nav.primary-nav a[aria-current="page"]::after {
  transform: scaleX(1);
  transform-origin: left;
}

.header-actions { display: flex; align-items: center; gap: 28px; flex-shrink: 0; }

/* ---- Primary action: no box. A permanent hairline plus a rule that extends on
   hover reads as deliberate at this tier; a bordered button reads as a template. ---- */
.nav-cta {
  position: relative;
  font-family: var(--sans);
  font-size: 0.85rem;
  letter-spacing: 0.2em;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
  padding: 8px 0 10px;
  transition: color 300ms ease;
}

body.has-hero-video #site-header:not(.is-condensed) .nav-cta { color: var(--paper); }

.nav-cta::after {
  content: "";
  position: absolute;
  left: 0;
  bottom: 2px;
  width: 100%;
  height: 1px;
  background: currentColor;
  transform-origin: left;
  transition: transform 380ms cubic-bezier(.4,0,.2,1);
}

.nav-cta:hover::after, .nav-cta:active::after { transform: scaleX(0); transform-origin: right; }

/* ---- Toggle: two rules and a tracked label, no border. Becomes an X when open. ---- */
.nav-toggle {
  display: none;
  align-items: center;
  gap: 10px;
  background: none;
  border: 0;
  padding: 10px 0;
  min-height: var(--tap-min);
  color: var(--ink);
  cursor: pointer;
}

body.has-hero-video #site-header:not(.is-condensed) .nav-toggle { color: var(--paper); }
html.nav-open .nav-toggle { color: var(--paper); }

.nav-toggle-bars { position: relative; display: block; width: 26px; height: 10px; }

.nav-toggle-bars i {
  position: absolute;
  left: 0;
  width: 100%;
  height: 1.5px;
  background: currentColor;
  transition: transform 380ms cubic-bezier(.4,0,.2,1), opacity 200ms ease;
}

.nav-toggle-bars i:first-child { top: 0; }
.nav-toggle-bars i:last-child { bottom: 0; }

html.nav-open .nav-toggle-bars i:first-child { transform: translateY(4.25px) rotate(45deg); }
html.nav-open .nav-toggle-bars i:last-child { transform: translateY(-4.25px) rotate(-45deg); }

.nav-toggle-label {
  font-family: var(--sans);
  font-size: 0.64rem;
  letter-spacing: 0.24em;
  font-weight: 600;
}

/* ---- Full-screen overlay menu. A dropdown list of small links is the templated
   move; a full-bleed ink panel with the nav set large in the display face is the
   premium one, and it gives mobile a real moment. ---- */
.nav-overlay {
  position: fixed;
  inset: 0;
  z-index: 90;
  background: var(--ink);
  opacity: 0;
  visibility: hidden;
  transition: opacity 460ms cubic-bezier(.4,0,.2,1), visibility 460ms;
  display: flex;
  align-items: stretch;
  overflow-y: auto;
  overscroll-behavior: contain;
  height: 100vh;
  height: 100dvh;
}

html.nav-open,
html.nav-open body {
  overflow: hidden;
  overscroll-behavior: none;
}
html.nav-open .nav-overlay { opacity: 1; visibility: visible; }

.nav-overlay-inner {
  width: 100%;
  min-height: 100%;
  padding-top: calc(var(--header-height) + 24px + env(safe-area-inset-top, 0px));
  padding-right: max(var(--gutter), env(safe-area-inset-right, 0px));
  padding-bottom: max(var(--space-lg), env(safe-area-inset-bottom, 0px));
  padding-left: max(var(--gutter), env(safe-area-inset-left, 0px));
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
}

.nav-overlay a {
  display: flex;
  align-items: baseline;
  gap: 18px;
  padding: 14px 0;
  color: var(--paper);
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 520ms ease, transform 520ms cubic-bezier(.2,.8,.2,1), padding-left 380ms cubic-bezier(.2,.8,.2,1);
  flex-shrink: 0;
}

html.nav-open .nav-overlay a {
  opacity: 1;
  transform: none;
  /* Stagger keyed off --i set per link in render.js. */
  transition-delay: calc(120ms + var(--i) * 55ms);
}

.nav-overlay a:hover, .nav-overlay a:active { padding-left: 14px; }

.overlay-index {
  font-family: var(--sans);
  font-size: 0.62rem;
  letter-spacing: 0.18em;
  color: #6E6E6E;
  flex-shrink: 0;
  width: 2.2em;
}

.overlay-label {
  font-family: var(--serif);
  font-size: clamp(1.7rem, 6.5vw, 2.6rem);
  line-height: 1.1;
  font-weight: 600;
}

.nav-overlay a[aria-current="page"] .overlay-label { font-style: italic; }

.nav-overlay-foot {
  margin-top: var(--space-lg);
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-family: var(--sans);
  font-size: 0.84rem;
  letter-spacing: 0.04em;
  color: var(--gray-4);
}

.nav-overlay-foot a { padding: 6px 0; font-size: 0.84rem; opacity: 1; transform: none; color: var(--gray-4); }

@media (max-width: 1200px) {
  nav.primary-nav { display: none; }
  .header-actions { display: none; }
  .nav-toggle { display: inline-flex; }
}

@media (max-width: 900px) {
  :root { --header-height: 84px; --header-height-condensed: 64px; }
  .logo-mark { height: 44px; width: 44px; }
  #site-header.is-condensed .logo-mark { height: 36px; width: 36px; }
  .logo-word-1 { font-size: 0.82rem; letter-spacing: 0.22em; }
  .logo-word-2 { font-size: 0.55rem; letter-spacing: 0.44em; }
}

@media (max-width: 600px) {
  .logo-link { gap: 11px; }
  .logo-mark { height: 40px; width: 40px; }
  .logo-word-1 { font-size: 0.74rem; letter-spacing: 0.18em; }
  .logo-word-2 { font-size: 0.5rem; letter-spacing: 0.38em; margin-top: 5px; }
  .nav-toggle-label { display: none; } /* the icon carries it; the label crowds at 390 */
}

@media (prefers-reduced-motion: reduce) {
  #site-header, #site-header *, .nav-overlay, .nav-overlay a { transition: none !important; }
}

/* ---------- Hero (homepage) — full-bleed video background ---------- */
.hero-blur-reveal {
  filter: blur(10px);
  animation: hero-blur-in 700ms ease-out forwards;
}

@keyframes hero-blur-in {
  to { filter: blur(0); }
}

@media (prefers-reduced-motion: reduce) {
  .hero-blur-reveal { filter: none; animation: none; }
}

.hero-video {
  position: relative;
  min-height: 88vh;
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  color: var(--paper);
  background: var(--ink);
}

.hero-video-bg-wrap {
  position: absolute;
  inset: 0;
  overflow: hidden;
  transform: scale(1.08);
}

.hero-video-poster,
.hero-video-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.hero-video-poster { z-index: 1; }

.hero-video-bg {
  z-index: 2;
  opacity: 0;
  transition: opacity 700ms ease;
}

.hero-video-bg.is-ready { opacity: 1; }

.hero-video-overlay {
  position: absolute;
  inset: 0;
  z-index: 3;
  background: linear-gradient(to top, rgba(0,0,0,0.88) 0%, rgba(0,0,0,0.62) 45%, rgba(0,0,0,0.38) 100%);
}

.hero-video-content {
  position: relative;
  z-index: 4;
  padding-top: var(--space-xl);
  padding-bottom: var(--space-2xl);
}

.hero-video .label { color: var(--gray-4); display: block; margin-bottom: 20px; }

.hero-video h1 {
  color: var(--paper);
  max-width: 900px;
  margin-bottom: 24px;
  font-family: 'League Spartan', var(--sans);
  font-weight: 700;
  text-shadow: -22px 50px 92px rgba(0, 0, 0, 0.58);
}

.hero-video p.lede { max-width: 560px; font-size: 1.15rem; color: #E5E5E5; margin-bottom: 36px; }

.hero-ctas { display: flex; gap: 18px; flex-wrap: wrap; }

@media (max-width: 600px) {
  .hero-video { min-height: 640px; }
  /* Equal-width stacked CTAs. Previously each button sized to its own label, which
     read as accidental rather than designed. */
  .hero-ctas { flex-direction: column; align-items: stretch; gap: 12px; }
  .hero-ctas .btn { justify-content: center; width: 100%; }
}

/* ===== CRITICAL CSS BOUNDARY =====
   Everything above this line is inlined into index.html at build time by
   scripts/build.js. Do not hand-edit the <style> block in index.html; it is
   generated. Keep above-the-fold rules above this marker, everything else below. */

/* Legacy full-bleed hero (kept for any page still using it) */
.hero {
  position: relative;
  min-height: 640px;
  display: flex;
  align-items: flex-end;
  background-size: cover;
  background-position: center;
  color: var(--paper);
}

.hero::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(0,0,0,0.85) 0%, rgba(0,0,0,0.3) 55%, rgba(0,0,0,0.08) 100%);
}

.hero-content { position: relative; z-index: 2; padding: 60px 0; }

.hero .label { color: var(--gray-4); display: block; margin-bottom: 14px; }

.hero h1 {
  max-width: 780px;
  margin-bottom: 18px;
  color: var(--paper);
  font-family: 'League Spartan', var(--sans);
  font-weight: 700;
  text-shadow: -22px 50px 92px rgba(0, 0, 0, 0.58);
}

.hero p.lede { max-width: 560px; font-size: 1.1rem; color: #E5E5E5; margin-bottom: 28px; }

/* ---------- Sections ---------- */
section { padding: var(--space-2xl) 0; }

.section-head {
  max-width: 680px;
  margin-bottom: var(--space-lg);
  position: relative;
  padding-bottom: 0;
}

.section-head::after { content: none; }

.section-head .label { display: block; margin-bottom: 12px; }

.section-alt { background: var(--ink); color: var(--paper); }

.section-alt h1, .section-alt h2, .section-alt h3 { color: var(--paper); }

.section-alt p { color: var(--gray-4); }

.section-alt .label { color: var(--gray-4); }

/* ---------- About panel ---------- */
.panel {
  background: var(--gray-1);
  padding: var(--space-lg);
}

.panel-green-border { background: var(--ink); }
.panel-green-border p { color: var(--gray-4); }

.about-panel {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-lg);
  align-items: center;
}

@media (max-width: 900px) {
  .about-panel { grid-template-columns: 1fr; }
}

/* ---------- Services grid → editorial index list ---------- */
.services-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 0;
  background: none;
  border: none;
  position: relative;
}

.services-grid::before { content: none; }

.service-card {
  background: none;
  padding: var(--space-md) 0;
  display: grid;
  grid-template-columns: 72px 1fr;
  gap: var(--space-md);
  align-items: baseline;
  transition: padding-left 300ms cubic-bezier(.2,.8,.2,1);
}

.service-card:hover { padding-left: 14px; }
.service-card:hover h3 { color: var(--ink); }
.service-card:hover .num { color: var(--ink); }

.service-card .num {
  grid-column: 1;
  grid-row: 1 / span 2;
  font-family: var(--serif);
  font-size: 1.6rem;
  color: var(--gray-3);
  font-weight: 500;
  transition: color 300ms ease;
}

.service-card h3 { grid-column: 2; color: var(--ink); margin-bottom: 0.25em; transition: color 200ms ease; }
.service-card p { grid-column: 2; color: #333333; max-width: 640px; }

/* alternating rows sit on section-alt (dark) sections too */
.section-alt .service-card h3 { color: var(--paper); }
.section-alt .service-card p { color: var(--gray-4); }
.section-alt .service-card .num { color: #444444; }
.section-alt .service-card:hover .num { color: var(--paper); }

.service-copy {
  max-width: 760px;
}

.service-copy + .service-copy {
  margin-top: 16px;
}

/* ---------- Steps ---------- */
.steps-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-md);
}

.steps-grid--two { grid-template-columns: repeat(2, 1fr); }
.steps-grid--three { grid-template-columns: repeat(3, 1fr); }

@media (max-width: 900px) {
  .steps-grid, .steps-grid--two, .steps-grid--three { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 600px) {
  .steps-grid, .steps-grid--two, .steps-grid--three { grid-template-columns: 1fr; }
}

.step {
  padding: var(--space-md) 0;
  background: transparent;
  transition: transform 350ms cubic-bezier(.2,.8,.2,1);
}

.step:hover {
  transform: translateY(-6px);
}

.step .step-num {
  font-family: var(--serif);
  font-size: 2.6rem;
  font-weight: 600;
  color: var(--gray-3);
  display: block;
  margin-bottom: 14px;
  transition: color 350ms ease;
}

.step:hover .step-num { color: var(--ink); }

.step h3 { color: var(--ink); margin-bottom: 10px; }

.step p { color: #333333; font-size: 0.95rem; }

.section-alt .step { background: transparent; }
.section-alt .step h3 { color: var(--paper); }
.section-alt .step p { color: var(--gray-4); }

/* ---------- Projects grid — asymmetric, photography-forward, framed hover ---------- */
.projects-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-lg) var(--space-md);
}

.projects-grid .project-card:first-child { grid-column: 1 / -1; }
.projects-grid .project-card:first-child img { aspect-ratio: 21 / 9; }

@media (max-width: 900px) {
  .projects-grid { grid-template-columns: 1fr; }
  .projects-grid .project-card:first-child img { aspect-ratio: 4 / 3; }
}

.project-card {
  border: none;
  overflow: hidden;
}

.project-card .frame { overflow: hidden; position: relative; }

.project-card img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 500ms ease;
}

.project-card:hover img { transform: scale(1.05); }

.project-card-body { padding: 20px 0 0; display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }

.project-card-body h3 { margin: 0; transition: opacity 250ms ease; }

.project-card:hover .project-card-body h3 { opacity: 0.6; }

.project-tags { font-family: var(--sans); font-size: 0.72rem; color: var(--gray-2); letter-spacing: 0.08em; margin-top: 4px; }

.project-card-body a {
  font-family: var(--sans);
  font-size: 0.76rem;
  letter-spacing: 0.04em;
  color: var(--ink);
  font-weight: 600;
  white-space: nowrap;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 2px;
  transition: opacity 200ms ease;
}

.project-card-body a:hover { opacity: 0.55; }

/* ---------- Contact CTA ---------- */
.contact-cta {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-lg);
}

@media (max-width: 900px) {
  .contact-cta { grid-template-columns: 1fr; }
}

.contact-info-list { display: flex; flex-direction: column; gap: 20px; margin-top: 24px; }

.contact-info-item .label { margin-bottom: 8px; display: block; }

.contact-info-item a, .contact-info-item span { font-size: 1.15rem; font-weight: 500; font-family: var(--serif); transition: opacity 200ms ease; }
.contact-info-item a:hover { opacity: 0.6; }

.contact-details-section {
  padding-top: clamp(56px, 6vw, 80px);
  padding-bottom: clamp(56px, 6vw, 80px);
}

.contact-details-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(14px, 2vw, 28px);
  align-items: stretch;
}

.contact-details-grid .step {
  aspect-ratio: 1;
  min-width: 0;
  padding: clamp(24px, 3vw, 42px);
  background: var(--ink);
  color: var(--paper);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  transition: transform 300ms cubic-bezier(.2,.8,.2,1), background-color 300ms ease;
}

.contact-details-grid .step:hover {
  background: #161616;
}

.contact-details-grid .step h3 {
  color: var(--paper);
  margin-bottom: 14px;
}

.contact-details-grid .step p {
  color: var(--gray-4);
  line-height: 1.55;
  overflow-wrap: anywhere;
}

.contact-details-grid .step a {
  color: var(--paper);
  text-underline-offset: 0.2em;
}

.contact-phone-line a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
}

.contact-map-panel {
  padding: 0;
  overflow: hidden;
}

.contact-map {
  display: block;
  width: 100%;
  max-width: 100%;
  border: 0;
}

.consultation-section {
  scroll-margin-top: calc(var(--header-height-condensed) + env(safe-area-inset-top, 0px) + 16px);
}

@media (max-width: 600px) {
  .contact-details-section {
    padding-top: 52px;
    padding-bottom: 52px;
  }

  .contact-details-grid {
    grid-template-columns: 1fr;
    gap: 14px;
  }
}

form.contact-form { display: flex; flex-direction: column; gap: 14px; }

form.contact-form input,
form.contact-form textarea {
  font-family: var(--sans);
  font-size: 0.95rem;
  padding: 15px 16px;
  border: 1px solid var(--gray-3);
  background: var(--gray-1);
  color: var(--ink);
  transition: border-color 250ms ease, background 250ms ease;
}

form.contact-form textarea { min-height: 140px; resize: vertical; }

form.contact-form input:focus,
form.contact-form textarea:focus { border-color: var(--ink); background: var(--paper); }

/* ---------- Page header (interior pages, photo banner) ---------- */
.page-header {
  position: relative;
  min-height: 380px;
  display: flex;
  align-items: flex-end;
  background-image: var(--page-header-image);
  background-size: cover;
  background-position: var(--page-header-position, center);
  background-repeat: no-repeat;
  color: var(--paper);
  overflow: hidden;
}

.page-header::before {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, var(--page-header-overlay, 0.6));
  z-index: 1;
}

@media (max-width: 600px) {
  .page-header {
    min-height: 340px;
    background-position: var(--page-header-mobile-position, var(--page-header-position, center));
  }
}

.page-header-content {
  position: relative;
  z-index: 2;
  padding-top: var(--space-lg);
  padding-bottom: var(--space-lg);
}

.page-header .label {
  color: var(--paper);
  display: block;
  margin-bottom: 14px;
  font-weight: 650;
}

.page-header h1 {
  margin: 0;
  max-width: 760px;
  color: var(--paper);
  font-family: 'League Spartan', var(--sans);
  font-weight: 700;
  text-shadow: -22px 50px 92px rgba(0, 0, 0, 0.58);
}

.page-header-plain {
  background: var(--paper);
  color: var(--ink);
  padding: var(--space-xl) 0;
}

.page-header-plain .label { display: block; margin-bottom: 14px; }

.page-header-plain h1 { margin: 0; }

/* ---------- Simple listing grid (project-cat / category pages) ---------- */
.simple-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-lg) var(--space-md);
}

@media (max-width: 900px) {
  .simple-grid { grid-template-columns: 1fr; }
}

.empty-note {
  background: var(--gray-1);
  padding: 32px;
  font-family: var(--sans);
  font-size: 0.9rem;
  color: var(--gray-2);
}

/* ---------- Article / prose (blog posts) ---------- */
.prose { max-width: 720px; }

.prose h2 { margin-top: 48px; margin-bottom: 18px; }
.prose h3 { margin-top: 32px; margin-bottom: 12px; }
.prose p { margin-bottom: 18px; }

.prose ul {
  list-style: none;
  margin: 0 0 22px;
  padding: 0;
}

.prose li {
  position: relative;
  margin-bottom: 10px;
  padding-left: 22px;
  color: #333333;
}

.prose li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.78em;
  width: 10px;
  height: 10px;
  background: url('/assets/images/logo-monogram.png') center / contain no-repeat;
  transform: translateY(-50%);
}

.article-meta {
  font-family: var(--sans);
  font-size: 0.78rem;
  color: var(--gray-2);
  letter-spacing: 0.08em;
  margin-bottom: 20px;
  display: block;
}

/* ---------- Project detail ---------- */
.project-detail-block { margin-bottom: var(--space-xl); }

.project-detail-block h2 { margin-bottom: 18px; }

.project-detail-block p { max-width: 720px; margin-bottom: 16px; }

.project-carousel {
  margin-top: var(--space-lg);
  max-width: 1120px;
}

.carousel-viewport {
  position: relative;
  overflow: hidden;
  aspect-ratio: 16 / 10;
  background: #E9E9E9;
  touch-action: pan-y pinch-zoom;
}

.carousel-viewport:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 4px;
}

.carousel-track {
  display: flex;
  height: 100%;
  transition: transform 380ms cubic-bezier(.2,.8,.2,1);
  will-change: transform;
}

.carousel-slide {
  flex: 0 0 100%;
  min-width: 0;
  height: 100%;
  margin: 0;
  display: grid;
  place-items: center;
}

.carousel-slide img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.carousel-toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 16px;
  margin-top: 14px;
}

.carousel-controls {
  display: flex;
  gap: 8px;
}

.carousel-button {
  width: 48px;
  height: 48px;
  padding: 0;
  border: 1px solid var(--ink);
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  cursor: pointer;
  transition: background-color 180ms ease, color 180ms ease;
}

.carousel-button:hover,
.carousel-button:active {
  background: var(--ink);
  color: var(--paper);
}

.carousel-button:focus-visible,
.carousel-thumbnail:focus-visible {
  outline: 2px solid var(--ink);
  outline-offset: 3px;
}

.carousel-status {
  font-family: var(--sans);
  font-size: var(--step-caption);
  letter-spacing: 0.1em;
}

.carousel-thumbnails {
  display: flex;
  gap: 10px;
  margin-top: 14px;
  padding: 3px 3px 8px;
  overflow-x: auto;
  overscroll-behavior-inline: contain;
  scrollbar-width: thin;
}

.carousel-thumbnail {
  flex: 0 0 88px;
  width: 88px;
  height: 66px;
  padding: 0;
  border: 2px solid transparent;
  background: #E9E9E9;
  cursor: pointer;
  opacity: 0.62;
}

.carousel-thumbnail[aria-current="true"] {
  border-color: var(--ink);
  opacity: 1;
}

.carousel-thumbnail img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@media (max-width: 600px) {
  .project-carousel {
    width: 100%;
  }

  .carousel-viewport {
    aspect-ratio: 4 / 5;
  }

  .carousel-thumbnail {
    flex-basis: 72px;
    width: 72px;
    height: 54px;
  }
}

@media (prefers-reduced-motion: reduce) {
  .carousel-track {
    transition: none;
  }
}

/* ---------- Simple project/category card (reused across listing pages) ---------- */
.simple-card {
  border: none;
  overflow: hidden;
}

.simple-card img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 500ms ease;
}

.simple-card:hover img { transform: scale(1.05); }

.simple-card-body { padding: 20px 0 0; display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }

.simple-card-body h3 { margin: 0; }

.simple-card-body a {
  font-family: var(--sans);
  font-size: 0.76rem;
  letter-spacing: 0.04em;
  color: var(--ink);
  font-weight: 600;
  white-space: nowrap;
  border-bottom: 1px solid var(--ink);
  padding-bottom: 2px;
  transition: opacity 200ms ease;
}

.simple-card-body a:hover { opacity: 0.55; }

/* ---------- Scroll-in fade (fallback path — see assets/js/animate.js) ----------
   Gated on html.has-fade, set by JS only when animation will actually run,
   so content stays fully visible with no JS / no IntersectionObserver support.
   When GSAP loads successfully, GSAP takes over these same elements directly
   and this CSS-only path is not used. */
html.has-fade .fade-up {
  opacity: 0;
  transform: translateY(24px);
  transition: opacity 400ms ease-out, transform 400ms ease-out;
}

html.has-fade .fade-up.in-view { opacity: 1; transform: translateY(0); }

/* ---------- Footer ---------- */
#site-footer { background: var(--ink); color: var(--paper); padding: 60px 0 24px; }

.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 32px;
  padding-bottom: 40px;
}

@media (max-width: 900px) {
  .footer-grid { grid-template-columns: 1fr; }
}

.footer-logo img { height: 72px; width: 72px; max-width: 100%; margin-bottom: 18px; }

.footer-grid p { color: var(--gray-4); font-size: 0.92rem; max-width: 320px; }

.footer-col .label { color: var(--gray-4); display: block; margin-bottom: 16px; }

.footer-col a { display: block; font-family: var(--sans); font-size: 0.92rem; color: #D8D8D6; margin-bottom: 12px; transition: opacity 200ms ease; }

.footer-col a:hover { opacity: 0.6; }

.footer-contact-list {
  --footer-action-size: 18px;
  --footer-action-gap: 8px;
  --footer-actions-width: 44px;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 12px;
}

.footer-contact-kicker {
  display: block;
  font-family: var(--sans);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  line-height: 1.4;
  color: var(--gray-4);
}

.footer-phone-row {
  min-height: var(--tap-min);
}

.footer-contact-row {
  display: grid;
  grid-template-columns: 44px minmax(0, 1fr);
  column-gap: 12px;
  align-items: center;
  min-width: 0;
  min-height: var(--tap-min);
}

.footer-icon-actions {
  display: inline-flex;
  align-items: center;
  gap: var(--footer-action-gap);
  flex: 0 0 auto;
  width: var(--footer-actions-width);
}

.footer-contact-label {
  display: block;
  font-family: var(--sans);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.08em;
  line-height: 1.4;
  color: var(--gray-4);
}

.footer-contact .footer-icon-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 var(--footer-action-size);
  width: var(--footer-action-size);
  height: var(--tap-min);
  min-height: var(--tap-min);
  margin: 0;
  color: var(--paper);
}

.footer-contact-icon {
  width: 44px;
  height: 44px;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0;
  padding: 0;
  transform: none;
}

.footer-contact-icon .footer-icon-link {
  flex-basis: 44px;
  width: 44px;
}

.footer-single-row {
  grid-template-columns: 22px minmax(0, 1fr);
  column-gap: 10px;
}

.footer-single-row .footer-contact-icon,
.footer-single-row .footer-icon-link {
  width: 22px;
  flex-basis: 22px;
}

.footer-contact-svg {
  width: 20px;
  height: 20px;
  display: block;
  margin: 0;
  transform: none;
}

.footer-contact-svg .icon-fill {
  fill: currentColor;
  stroke: none;
}

.footer-contact .footer-phone-link,
.footer-contact .footer-contact-value {
  display: inline-flex;
  align-items: center;
  width: fit-content;
  min-height: var(--tap-min);
  margin: 0;
  color: #D8D8D6;
  overflow-wrap: anywhere;
}

.footer-contact .footer-phone-link {
  white-space: nowrap;
}

.footer-contact-copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 2px;
  min-width: 0;
  margin: 0;
}

.footer-contact-copy p,
.footer-contact-copy span,
.footer-contact-copy a {
  margin: 0;
}

@media (max-width: 600px) {
  .footer-contact-list { gap: 11px; }
}

.footer-bottom {
  padding-top: 20px;
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  font-family: var(--sans);
  font-size: 0.75rem;
  color: #828282; /* was #6B6B6B (3.72:1 against --ink, fails WCAG AA); this is the one issue axe-core/Lighthouse actually flags sitewide */
}

.footer-service-areas {
  margin-top: 18px;
  font-size: 0.78rem;
  color: #7A7A7A;
  max-width: 320px;
}

.service-area-group { margin-bottom: 6px; }

.service-area-region {
  color: var(--gray-4);
  font-weight: 600;
}

.footer-credit {
  display: inline;
  font-size: 0.68rem;
  letter-spacing: 0.02em;
  color: #828282;
  transition: opacity 200ms ease;
}

.footer-credit:hover { opacity: 0.7; }

/* ============================================================================
   Mobile design layer
   Mobile is tuned here deliberately, not inherited from a shrinking desktop
   scale. Touch feedback, tap targets and the mobile type scale all live here.
   ========================================================================= */

/* ---------- Touch feedback ----------
   The interaction language was built entirely on :hover, which does not exist on
   touch. Every hover affordance gets an :active equivalent so mobile is not silent. */
a, button, .btn, .btn-outline, .btn-green, .nav-toggle, .service-card {
  -webkit-tap-highlight-color: transparent;
}

.btn:active::before, .btn-outline:active::before, .btn-green:active::before { transform: scaleX(1); }
.btn:active, .btn-outline:active, .btn-green:active { color: var(--paper); }
.section-alt .btn:active, .hero-video .btn:active,
.section-alt .btn-outline:active, .hero-video .btn-outline:active { color: var(--ink); }

.nav-toggle:active { background: var(--ink); color: var(--paper); }
.service-card:active { padding-left: 14px; }
.project-card:active img, .simple-card:active img { transform: scale(1.05); }
.project-card-body a:active, .simple-card-body a:active, .footer-col a:active { opacity: 0.55; }

/* ---------- Tap targets ----------
   Hitbox reaches the 44px minimum via padding; negative margin keeps the visual
   edge on the gutter so nothing looks inset. */
.footer-col a {
  min-height: var(--tap-min);
  display: flex;
  align-items: center;
}

.nav-toggle { min-height: var(--tap-min); min-width: var(--tap-min); }

@media (max-width: 900px) {
  :root {
    /* One fluid mobile gutter: never less than 20px, reaching 24px on wider
       phones and tablets. Every .wrap, header and navigation surface consumes
       this same token with safe-area protection. */
    --gutter: clamp(20px, 5.8vw, 24px);
  }

  /* Flex and grid descendants must be allowed to shrink inside the shared
     gutter instead of forcing the document wider than the viewport. */
  .wrap > *,
  .header-bar > *,
  .nav-overlay-inner > *,
  .footer-grid > *,
  .contact-cta > *,
  .cta-split > *,
  .steps-grid > *,
  .team-grid > *,
  .projects-grid > *,
  .simple-grid > *,
  .gallery > * {
    min-width: 0;
  }

  .hero-video-content,
  form.contact-form,
  form.contact-form input,
  form.contact-form textarea,
  form.contact-form .file-input,
  iframe {
    width: 100%;
    max-width: 100%;
    min-width: 0;
  }

  .footer-contact-value,
  .footer-contact-copy,
  .footer-col {
    overflow-wrap: anywhere;
  }
}

@media (max-width: 600px) {
  :root {
    /* Mobile type scale: tighter display sizes, looser body leading for reading
       comfort on a narrow measure. */
    --step-h1: clamp(2.3rem, 10.5vw, 3.1rem);
    --step-h2: clamp(1.65rem, 7vw, 2.1rem);
    --step-h3: 1.16rem;
    --step-body: 1rem;
    --step-lede: 1.04rem;
    --leading-tight: 1.06;
    --leading-body: 1.7;
    --space-2xl: 76px;
    --space-xl: 52px;
  }

  h1 { text-wrap: balance; }
  h2 { text-wrap: balance; }
  p.lede { text-wrap: pretty; }

  .hero-video p.lede { font-size: var(--step-lede); }
  .hero-video-content {
    padding-top: var(--space-lg);
    padding-bottom: var(--space-xl);
  }

  /* Buttons reach full tap height without becoming chunky. */
  .btn, .btn-outline, .btn-green { padding: 15px 24px; min-height: var(--tap-min); }
}

/* ============================================================================
   Final photography slots
   Stable, honest holding space for approved staff portraits. Replace each slot
   with a dimensioned image when the final portrait library is delivered.
   ========================================================================= */
.media-slot {
  position: relative;
  width: 100%;
  aspect-ratio: 4 / 3;
  background: var(--gray-1);
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: var(--space-md);
}

.media-slot[data-ratio="portrait"] { aspect-ratio: 4 / 5; }
.media-slot[data-ratio="wide"] { aspect-ratio: 21 / 9; }
.media-slot[data-ratio="square"] { aspect-ratio: 1 / 1; }

.section-alt .media-slot { background: var(--ink-2); }

/* The message is absolutely positioned so its line count cannot shift layout. */
.media-slot-msg {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--space-md);
  margin: 0;
  font-family: var(--serif);
  font-size: clamp(0.98rem, 1.7vw, 1.2rem);
  line-height: 1.45;
  color: #5E5E5E;
  max-width: 30ch;
  margin-inline: auto;
  opacity: 1;
}

.section-alt .media-slot-msg { color: var(--gray-4); }

/* ============================================================================
   Team / Meet the Staff
   ========================================================================= */
.team-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-md);
}

@media (max-width: 900px) {
  .team-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 600px) {
  .team-grid { grid-template-columns: 1fr; gap: var(--space-lg); }
}

.team-member .media-slot { margin-bottom: 18px; }

.team-member h3 { margin-bottom: 4px; }

.team-role {
  font-family: var(--sans);
  font-size: var(--step-caption);
  letter-spacing: 0.08em;
  color: #6E6E6E;
}

.section-alt .team-role { color: var(--gray-4); }

/* ============================================================================
   Page transition
   Slow cinematic cross-fade on navigation. Purely additive: if JS never runs the
   page simply renders, and reduced-motion disables it entirely.
   ========================================================================= */
@media (prefers-reduced-motion: no-preference) {
  html.page-fade body { animation: page-fade-in 520ms ease-out both; }
  html.page-fade-out body { opacity: 0; transition: opacity 260ms ease-in; }
}

@keyframes page-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

/* ============================================================================
   Simple prose pages (Submit Your Project / Become an Installer)
   ========================================================================= */
.form-note {
  font-family: var(--sans);
  font-size: var(--step-caption);
  color: #6E6E6E;
  margin-top: 10px;
}

.cta-split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2xl) var(--space-lg);
  align-items: start;
}

@media (max-width: 900px) {
  .cta-split { grid-template-columns: 1fr; gap: var(--space-lg); }
}

.checklist { list-style: none; margin: var(--space-md) 0 0; padding: 0; }

.checklist li {
  position: relative;
  padding-left: 26px;
  margin-bottom: 14px;
  color: #333333;
  font-size: var(--step-body);
  line-height: 1.6;
}

.checklist li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.8em;
  width: 11px;
  height: 11px;
  background: url('/assets/images/logo-monogram.png') center / contain no-repeat;
  transform: translateY(-50%);
}

.section-alt .checklist li { color: var(--gray-4); }
.section-alt .checklist li::before {
  background-image: url('/assets/images/logo-monogram-white.png');
}

/* Form labels: the existing contact form relied on placeholders alone, which vanish
   on focus and are not reliably announced. New forms use real labels. */
form.contact-form .label { margin-bottom: -6px; }

.required-marker {
  margin-left: 0.2em;
}

.field-help {
  display: block;
  margin-top: -4px;
  color: #5E5E5E;
  font-size: 0.82rem;
  line-height: 1.5;
}

.section-alt .field-help {
  color: var(--gray-4);
}

form.contact-form .file-input {
  min-height: 52px;
  padding: 6px 12px 6px 6px;
  cursor: pointer;
  font-family: var(--sans);
  font-size: 0.88rem;
}

form.contact-form .file-input::file-selector-button {
  min-height: 40px;
  margin: 0 12px 0 0;
  padding: 10px 14px;
  border: 0;
  background: var(--ink);
  color: var(--paper);
  font: inherit;
  font-weight: 600;
  cursor: pointer;
}

form.contact-form button { align-self: flex-start; margin-top: 8px; }

.form-privacy {
  max-width: 58ch;
  font-size: 0.78rem;
  line-height: 1.55;
  color: inherit;
  opacity: 0.78;
}

.form-privacy a {
  display: inline;
  min-height: 0;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.honeypot {
  position: absolute;
  left: -10000px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.article-hero {
  width: 100%;
  margin-bottom: 32px;
}

/* ============================================================================
   Utility pages
   ========================================================================= */
.error-page {
  min-height: calc(100vh - var(--header-height));
  display: flex;
  align-items: center;
}

.error-page-copy {
  max-width: 760px;
}

.error-page-copy p {
  max-width: 54ch;
}

.error-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  margin-top: 30px;
}

@media (max-width: 600px) {
  .error-page { min-height: auto; }
  .error-actions { flex-direction: column; }
  .error-actions .btn { width: 100%; justify-content: center; }
}

@media (max-width: 600px) {
  form.contact-form button { align-self: stretch; justify-content: center; }
}

/* ============================================================================
   Editorial gallery
   The homepage centrepiece. A 12-column field that items span asymmetrically, so
   the page reads as a curated spread rather than a uniform card grid. Every tile
   accepts either a real <picture> or a .media-slot placeholder with no structural
   difference, which is what lets final photography drop in later without a rebuild.
   ========================================================================= */
.gallery {
  display: grid;
  grid-template-columns: repeat(12, 1fr);
  gap: var(--space-lg) var(--space-md);
  max-width: 1240px;
  margin-inline: auto;
}

.gallery-item { position: relative; min-width: 0; }

.gallery-item--full    { grid-column: span 6; }
.gallery-item--wide    { grid-column: span 6; }
.gallery-item--narrow  { grid-column: span 6; }
.gallery-item--half    { grid-column: span 6; }
.gallery-item--offset  { grid-column: span 6; }
.gallery-item--tall    { grid-column: span 5; }

.gallery-item--drop { margin-top: 0; }

.gallery-media {
  position: relative;
  overflow: hidden;
  background: var(--gray-1);
}

.gallery-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 900ms cubic-bezier(.2,.8,.2,1), filter 900ms ease;
}

.gallery-item:hover .gallery-media img,
.gallery-item:active .gallery-media img { transform: scale(1.04); }

/* Ratios drive height, so nothing depends on the image's intrinsic size and CLS
   stays at 0 whether the slot holds a photo or a placeholder. */
.gallery-media[data-ratio="wide"]     { aspect-ratio: 4 / 3; }
.gallery-media[data-ratio="landscape"]{ aspect-ratio: 4 / 3; }
.gallery-media[data-ratio="portrait"] { aspect-ratio: 4 / 5; }
.gallery-media[data-ratio="square"]   { aspect-ratio: 1 / 1; }

.gallery-media .media-slot { border: 0; height: 100%; aspect-ratio: auto; }

.gallery-cap {
  display: flex;
  align-items: baseline;
  gap: 16px;
  margin-top: 20px;
  padding-top: 0;
}


.gallery-index {
  font-family: var(--sans);
  font-size: 0.64rem;
  letter-spacing: 0.18em;
  color: #6E6E6E;
  flex-shrink: 0;
  transition: color 300ms ease;
}

.gallery-item:hover .gallery-index { color: var(--ink); }
.section-alt .gallery-item:hover .gallery-index { color: var(--paper); }

.gallery-cap h3 { margin: 0 0 4px; font-size: clamp(1.15rem, 2vw, 1.5rem); }

.gallery-meta {
  font-family: var(--sans);
  font-size: var(--step-caption);
  letter-spacing: 0.14em;
  color: #6E6E6E;
}

.section-alt .gallery-meta { color: var(--gray-4); }

.gallery-cap-body { min-width: 0; }

@media (max-width: 900px) {
  .gallery { gap: var(--space-lg) var(--space-md); }
  .gallery-item--wide, .gallery-item--narrow, .gallery-item--half,
  .gallery-item--tall { grid-column: span 6; }
  .gallery-item--offset { grid-column: 1 / -1; }
  .gallery-item--drop { margin-top: 0; }
}

@media (max-width: 600px) {
  .gallery { gap: var(--space-lg) 0; }
  .gallery-item { grid-column: 1 / -1; }
  /* Every tile becomes portrait on a phone: it is the only ratio that earns the
     vertical space on a narrow screen. */
  .gallery-media[data-ratio] { aspect-ratio: 4 / 5; }
  .gallery-media[data-ratio="wide"] { aspect-ratio: 3 / 2; }
}

/* ---------- Section intro with a right-aligned action ---------- */
.section-lead {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--space-lg);
  margin: 0 auto var(--space-lg);
  max-width: 1240px;
}

.section-lead .section-head { margin-bottom: 0; }

@media (max-width: 900px) {
  .section-lead { flex-direction: column; align-items: flex-start; gap: var(--space-md); }
}

/* ---------- Hero refinements ---------- */
.hero-scroll-cue {
  position: absolute;
  left: 0;
  bottom: 34px;
  z-index: 4;
  font-family: var(--sans);
  font-size: 0.62rem;
  letter-spacing: 0.24em;
  color: rgba(255,255,255,0.72);
}

@media (max-width: 900px) { .hero-scroll-cue { display: none; } }

/* Unified phone treatment: one style everywhere it appears as content, so the same
   number does not read three different ways across header, contact page and footer. */
.contact-info-item a, .contact-info-item span {
  font-family: var(--sans);
  font-size: 1.02rem;
  font-weight: 500;
  letter-spacing: 0.02em;
}

.gallery-link { display: block; color: inherit; }

/* ============================================================================
   Reversible section background media
   The build adds these classes only to major sections without forms, photography,
   video, or embedded media. Colors remain the fallback and the entire experiment
   can be disabled through BACKGROUND_MEDIA.enabled in scaffold-data.js.
   ========================================================================= */
.surface-media-enabled .surface-media {
  --surface-image: none;
  --surface-overlay: 1;
  --surface-position: center center;
  --surface-mobile-position: var(--surface-position);
  position: relative;
  isolation: isolate;
  overflow: clip;
}

.surface-media-enabled .surface-media::before,
.surface-media-enabled .surface-media::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
}

.surface-media-enabled .surface-media::before {
  z-index: 0;
  background-color: inherit;
  background-image: var(--surface-image);
  background-position: var(--surface-position);
  background-repeat: no-repeat;
  background-size: cover;
}

.surface-media-enabled .surface-media::after {
  z-index: 0;
}

.surface-media-enabled .surface-media > * {
  position: relative;
  z-index: 1;
}

.surface-media-enabled .surface-media--dark {
  background-color: var(--ink);
}

.surface-media-enabled .surface-media--dark::after {
  background: rgb(10 10 10 / var(--surface-overlay));
}

.surface-media-enabled .surface-media--light {
  background-color: var(--paper);
}

.surface-media-enabled .surface-media--light::after {
  background: rgb(255 255 255 / var(--surface-overlay));
}

.surface-media-enabled .surface-media--dark-1 {
  --surface-image: var(--surface-dark-1-image);
  --surface-overlay: var(--surface-dark-1-overlay);
  --surface-position: var(--surface-dark-1-position);
  --surface-mobile-position: var(--surface-dark-1-mobile-position);
}

.surface-media-enabled .surface-media--dark-2 {
  --surface-image: var(--surface-dark-2-image);
  --surface-overlay: var(--surface-dark-2-overlay);
  --surface-position: var(--surface-dark-2-position);
  --surface-mobile-position: var(--surface-dark-2-mobile-position);
}

.surface-media-enabled .surface-media--dark-3 {
  --surface-image: var(--surface-dark-3-image);
  --surface-overlay: var(--surface-dark-3-overlay);
  --surface-position: var(--surface-dark-3-position);
  --surface-mobile-position: var(--surface-dark-3-mobile-position);
}

.surface-media-enabled .surface-media--light-1 {
  --surface-image: var(--surface-light-1-image);
  --surface-overlay: var(--surface-light-1-overlay);
  --surface-position: var(--surface-light-1-position);
  --surface-mobile-position: var(--surface-light-1-mobile-position);
}

.surface-media-enabled .surface-media--light-2 {
  --surface-image: var(--surface-light-2-image);
  --surface-overlay: var(--surface-light-2-overlay);
  --surface-position: var(--surface-light-2-position);
  --surface-mobile-position: var(--surface-light-2-mobile-position);
}

@media (max-width: 768px) {
  .surface-media-enabled .surface-media::before {
    background-position: var(--surface-mobile-position);
  }
}

@media (prefers-reduced-data: reduce) {
  .surface-media-enabled .surface-media::before {
    background-image: none;
  }
}
