/* ================================================================
   THAMCO360 — Design System & Stylesheet
   Craft-Obsessed Luxury 3D Experience
   ================================================================ */

:root {
  --bg: #faf6ee;
  --bg-subtle: #f2e9d8;
  --surface: rgba(255, 255, 255, 0.7);
  --border: rgba(36, 28, 18, 0.1);
  --primary: #c9962f;
  --primary-glow: rgba(201, 150, 47, 0.4);
  --accent: #4d84b8;
  --accent-glow: rgba(77, 132, 184, 0.35);
  --accent-ink: #2d5a82;
  --text: #241c12;
  --text-muted: #4a3f2c;
  /* Display voice = Cormorant Garamond, a high-contrast old-style serif; it
     carries the headlines and the script accent. UI chrome (nav, buttons,
     labels, form fields) and body copy stay on Instrument Sans, which holds
     up far better at small sizes and in tight controls. */
  --font-display: 'Cormorant Garamond', 'Iowan Old Style', Georgia, serif;
  --font-script: 'Cormorant Garamond', 'Iowan Old Style', Georgia, serif;
  --font-heading: 'Instrument Sans', sans-serif;
  --font-body: 'Instrument Sans', sans-serif;
  /* One rail for the entire page. The header used to sit on 1320 while every
     content section used .inner at 1240, so the header logo hung 40px to the
     left of everything beneath it all the way down. The header has ~370px of
     slack at this width, so it loses nothing by matching. */
  --rail: 1240px;
  --rail-pad: 32px;
  --ease: cubic-bezier(0.16, 1, 0.3, 1);
  --glass: rgba(42, 30, 16, 0.85);
}

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

/* Horizontal overflow is cut on <html> only. Having overflow-x:hidden on BOTH
   html and body made <body> a scroll container of its own (a non-visible
   overflow on one axis forces the other to auto). Chrome then had two nested
   scrollers competing for the wheel, Lenis drove the wrong one, and every
   position:sticky inside body stopped sticking. `clip` hides the overflow
   without creating a scroll container at all; `hidden` stays as the fallback
   for browsers that predate clip (Safari < 16). */
html {
  font-family: var(--font-body);
  background: var(--bg);
  color: var(--text);
  overflow-x: hidden;
}

@supports (overflow: clip) {
  html { overflow-x: clip; }
}

body {
  line-height: 1.6;
  background: var(--bg);
  min-height: 100%;
}

/* Lenis' own required stylesheet (lenis/dist/lenis.css). Without it Lenis
   fights CSS smooth-scroll in Chromium, and a stopped instance (menu open)
   never releases the page on some browsers. */
html.lenis, html.lenis body { height: auto; }
.lenis.lenis-smooth { scroll-behavior: auto !important; }
.lenis.lenis-smooth [data-lenis-prevent] { overscroll-behavior: contain; }
.lenis.lenis-stopped { overflow: hidden; }
.lenis.lenis-smooth iframe { pointer-events: none; }
.lenis.lenis-smooth .embed-live iframe { pointer-events: auto; }

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

/* ── Shader Background ─────────────────────────────────────── */
.shader-canvas {
  position: fixed;
  inset: 0;
  width: 100vw;
  height: 100vh;
  z-index: 0;
  pointer-events: none;
  filter: blur(12px);
  opacity: 0.45;
}

/* ── HEADER ────────────────────────────────────────────────── */
.site-header {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 1000;
  padding: 16px 0;
  background: rgba(250, 246, 238, 0.85);
  -webkit-backdrop-filter: blur(16px);
  backdrop-filter: blur(16px);
  border-bottom: 1px solid var(--border);
  transition: background 0.4s ease;
}

.site-header.scrolled {
  background: rgba(250, 246, 238, 0.96);
  box-shadow: 0 4px 24px rgba(36, 28, 18, 0.12);
}

.header-inner {
  max-width: var(--rail);
  margin: 0 auto;
  padding: 0 var(--rail-pad);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
}

.logo {
  position: relative;
  display: flex;
  align-items: center;
  gap: 10px;
  text-decoration: none;
  color: var(--text);
  font-family: var(--font-heading);
  font-size: 1.3rem;
  font-weight: 700;
  letter-spacing: -0.02em;
}

.logo-mark { display: block; height: 42px; width: auto; }
.footer-brand .logo-mark { height: 38px; }

/* Live Scroll Tag in Header */
.dot-live {
  width: 7px;
  height: 7px;
  background: #22c55e;
  border-radius: 50%;
  box-shadow: 0 0 8px #22c55e;
  animation: live-pulse 1.8s ease infinite;
}

@keyframes live-pulse {
  0%, 100% { transform: scale(1); opacity: 1; }
  50% { transform: scale(0.7); opacity: 0.5; }
}

.main-nav {
  display: flex;
  align-items: center;
  gap: 28px;
}

.nav-a {
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.9rem;
  font-weight: 500;
  transition: color 0.25s ease;
}

.nav-a:hover { color: var(--text); }

.btn-pill {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 10px 22px;
  background: var(--primary);
  color: #241c12;
  border-radius: 100px;
  text-decoration: none;
  font-size: 0.88rem;
  font-weight: 700;
  font-family: var(--font-heading);
  box-shadow: 0 4px 20px var(--primary-glow);
  transition: all 0.25s ease;
}

.btn-pill:hover {
  background: #a9821f;
  transform: translateY(-2px);
  box-shadow: 0 8px 30px var(--primary-glow);
}

/* ── HERO VIRTUAL TOUR SECTION ─────────────────────────────── */
/* 100% rather than 100vw: 100vw counts the scrollbar gutter, which made this
   section ~15px wider than every other block and pushed the hero headline 8px
   right of the rail everything else sits on. It was also a real horizontal
   overflow that only body{overflow-x:hidden} was hiding. */
.hero-tour-section {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100svh;
  overflow: hidden;
  background: #2a2015;
}

.tour-canvas {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  display: block;
  z-index: 1;
  cursor: grab;
  /* Without this, this full-viewport canvas's own pointer-drag "look
     around" handling swallows every touch gesture — including a plain
     vertical swipe meant to scroll the page — since on touch there's
     no separate wheel input to fall back on like there is on desktop.
     pan-y hands vertical drags back to native scroll; horizontal
     look-around dragging still works. */
  touch-action: pan-y;
}
.tour-canvas:active { cursor: grabbing; }

/* These three float directly over the photographic 360 canvas, so they
   keep an explicit light text color independent of the site's base
   theme — the page default flipped to dark warm ink for the light/cream
   chrome, which would otherwise be invisible against a photo backdrop. */
.hero-overlay {
  color: #f5efe0;
}

.hero-overlay {
  position: absolute;
  inset: 0;
  z-index: 10;
  display: flex;
  align-items: center;
  justify-content: flex-start;
  /* Directional scrim rather than a centred radial: the left third is dark
     enough to carry cream text at AA, the right two-thirds stay open so the
     panorama behind the overlay is still legible as an image. */
  background:
    linear-gradient(97deg,
      rgba(26, 16, 7, 0.93) 0%,
      rgba(26, 16, 7, 0.86) 26%,
      rgba(26, 16, 7, 0.60) 50%,
      rgba(26, 16, 7, 0.26) 72%,
      rgba(26, 16, 7, 0.10) 100%),
    linear-gradient(to top, rgba(26, 16, 7, 0.55) 0%, rgba(26, 16, 7, 0) 34%);
  pointer-events: auto;
  transition: opacity 0.6s ease, visibility 0.6s ease;
}

/* Same 1320/32 rail as .header-inner, so the H1's left edge stacks under
   the logo instead of floating in its own centred box. */
.hero-overlay-inner {
  text-align: left;
  width: 100%;
  max-width: var(--rail);
  margin: 0 auto;
  /* The block is vertically centred in the section, so the fixed header
     has to be reserved as top padding or the first headline line slides
     under the nav. The bottom value only balances the column optically —
     the scroll cue it used to make room for is gone. */
  padding: 96px 32px 48px;
  will-change: transform;
}

.hero-h1 {
  font-family: var(--font-display);
  /* Cormorant runs optically smaller than a grotesk at the same px, so the
     clamp sits a step above the old Instrument Sans scale. Tracking goes
     positive-to-neutral rather than -0.03em: a serif this delicate falls
     apart when it is tightened. */
  font-size: clamp(2.55rem, 4.6vw, 4.4rem);
  font-weight: 300;
  line-height: 1.04;
  letter-spacing: -0.012em;
  margin-bottom: 28px;
  /* The four-step ragged stack comes from the hard line breaks in the markup,
     not from this measure — the cap exists purely so no single line wraps a
     second time. 22ch clears the longest of them ("Living a Virtual World"
     set in the larger script size) at every desktop width. */
  max-width: 22ch;
}

/* Each line is its own clipping window; the inner span is what travels, so
   the type rises out of the mask instead of fading in place. The padding /
   negative-margin pair gives descenders and the gold gradient room to live
   inside the clip without being shaved. */
.h1-line {
  display: block;
  overflow: hidden;
  padding-bottom: 0.14em;
  margin-bottom: -0.14em;
}

.h1-line-i {
  display: block;
  will-change: transform;
}

.gradient-text {
  display: inline-block;
  font-family: var(--font-script);
  font-style: italic;
  font-size: clamp(2.75rem, 5.4vw, 5.2rem);
  line-height: 1.08;
  font-weight: 400;
  letter-spacing: -0.005em;
  background: linear-gradient(135deg, #c9962f 0%, #f7e6b6 48%, #c9962f 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  color: transparent;
}

/* Measure tightens as the eye travels down the F — H1 16ch, lead 46ch,
   quote 52ch — which is what produces the stepped left-edge silhouette. */
/* Each sentence is its own block so the break lands where it was written,
   not wherever the measure happens to fall. The measure is widened to fit
   the longer of the two on one line; below that width they wrap normally. */
.hero-p {
  font-size: 1.15rem;
  color: rgba(245, 241, 230, 0.78);
  max-width: 56ch;
  margin: 0 0 14px;
}

.hero-p-line {
  display: block;
}

/* Reads as the second half of the same block, so .hero-p hands its bottom
   margin over to this line. Lifted off --primary because the gold sits on
   the lighter middle of the hero's radial scrim at body size. */
.hero-quote {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 1.3rem;
  line-height: 1.5;
  color: #dcb45c;
  max-width: 52ch;
  margin: 0 0 38px;
  padding-left: 18px;
  border-left: 1px solid rgba(220, 180, 92, 0.42);
}

/* The hero's last element used to be the CTA; now that the block can end on
   the quote, whatever lands last drops its trailing margin so the centred
   column stays optically centred instead of sitting high by ~38px. */
.hero-overlay-inner > :last-child {
  margin-bottom: 0;
}

.btn-enter-tour {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  padding: 15px 32px;
  background: var(--primary);
  color: #241c12;
  border: none;
  border-radius: 100px;
  font-size: 0.95rem;
  font-weight: 700;
  font-family: var(--font-heading);
  cursor: pointer;
  box-shadow: 0 8px 30px rgba(201, 150, 47, 0.5);
  transition: all 0.25s ease;
}

.btn-enter-tour:hover {
  background: #a9821f;
  transform: translateY(-3px) scale(1.02);
}







.hidden { display: none !important; }

/* Room Title Bar */








/* Exit Button */




/* Compass */










/* Drag Hint */


/* Floor Nav */
.floor-nav-title {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 0.72rem;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: rgba(245, 239, 224, 0.65);
  font-weight: 700;
  margin-bottom: 8px;
}







/* Look Controls */
.look-row { display: flex; gap: 4px; }









.popup-close {
  position: absolute;
  top: 10px; right: 10px;
  background: transparent;
  border: none;
  color: rgba(245, 239, 224, 0.7);
  cursor: pointer;
}






/* Formerly a 300vh scroll-jack driver for a pinned room walkthrough —
   removed in favor of the hero's own timer-driven auto-cycle (see
   restartRoomBanner in app.js), which doesn't eat scroll distance.
   Kept at zero height rather than deleting the element/selector in
   case anything still references #tourScrollDriver. */
.tour-scroll-driver { height: 0; margin-top: 0; pointer-events: none; }

/* ── WORK & SEQUENCE CHAPTERS ──────────────────────────────── */
/* 120px top and bottom meant every pair of adjacent sections opened a 240px
   empty band. 84px keeps the page airy while closing roughly a third of that
   dead space. */
.section { padding: 84px 0; position: relative; }
.inner { max-width: var(--rail); margin: 0 auto; padding: 0 var(--rail-pad); }

/* Small, uppercase and widely tracked: Cormorant's thin strokes disappear
   at this size and its caps were never drawn for this much letter-spacing. */
.section-kicker {
  font-family: var(--font-heading);
  font-size: 0.82rem;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  font-weight: 600;
  color: var(--accent-ink);
  margin-bottom: 12px;
}

.section-h2 {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 4vw, 3.4rem);
  font-weight: 400;
  line-height: 1.1;
  letter-spacing: -0.02em;
  margin-bottom: 18px;
}

.section-p {
  font-size: 1.08rem;
  color: var(--text-muted);
  max-width: 540px;
}

.section-header-center { text-align: center; margin-bottom: 64px; }
.section-header-center .section-p { margin: 0 auto; }

.chapter-list { display: flex; flex-direction: column; gap: 32px; }

.chapter-row {
  display: grid;
  grid-template-columns: 1fr 1.5fr;
  gap: 48px;
  padding: 36px 40px;
  background: rgba(255, 255, 255, 0.65);
  border: 1px solid var(--border);
  border-radius: 20px;
  transition: all 0.3s ease;
}

.chapter-row:hover {
  border-color: rgba(201, 150, 47, 0.4);
  transform: translateY(-4px);
  box-shadow: 0 16px 40px rgba(201, 150, 47, 0.12);
}

.ch-eyebrow {
  font-family: var(--font-heading);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  color: var(--accent-ink);
}

.ch-title {
  font-family: var(--font-heading);
  font-size: 1.4rem;
  font-weight: 700;
  margin-top: 6px;
}

.chapter-content p { color: var(--text-muted); font-size: 0.95rem; line-height: 1.7; }

/* ── FLOW STRIP — minimal placeholder process visual ────────── */
.flow-strip {
  display: flex;
  align-items: center;
  justify-content: center;
  flex-wrap: wrap;
  gap: 20px 8px;
}

.flow-step { text-align: center; min-width: 90px; }

.flow-step h3 {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 1.3rem;
}

.flow-arrow {
  color: var(--text-muted);
  opacity: 0.5;
  font-size: 1.2rem;
}

.flow-strip-small .flow-step h3 { font-size: 1.05rem; color: var(--text-muted); }

/* ── THE JOURNEY — five-stage capture-to-experience diagram ─────
   Replaces the old flat "01 Capture → 02 Stitch → …" text row. Each stage
   is an inline stroke SVG so it stays sharp at any density, inherits the
   page colour, and can be drawn on stroke-by-stroke by initJourney().
   Laid out as a grid rather than a flex row so all five columns are equal
   width and the connector rail can be positioned against a predictable
   track. */
.journey {
  position: relative;
  list-style: none;
  margin: 52px 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 28px;
}

/* The rail sits behind the icons, threaded through their centres. Its own
   grid cell spans the full row; `top` matches half the icon height so the
   line passes through the middle of every disc. */
.journey-rail {
  position: absolute;
  left: 0;
  right: 0;
  top: 33px;
  height: 2px;
  /* Stops short of the outer icons so the line reads as joining them
     rather than running off the ends of the row. */
  margin: 0 10%;
  pointer-events: none;
}

.journey-rail-track,
.journey-rail-fill {
  position: absolute;
  inset: 0;
  border-radius: 2px;
}

.journey-rail-track { background: var(--border); }

.journey-rail-fill {
  background: linear-gradient(90deg, var(--primary) 0%, #e0bd6a 100%);
  transform-origin: left center;
  transform: scaleX(0);
}

.journey-step {
  position: relative;
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.journey-icon {
  position: relative;
  z-index: 1;
  width: 68px;
  height: 68px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  margin-bottom: 18px;
  color: var(--accent-ink);
  background: var(--bg);
  border: 1px solid var(--border);
  box-shadow: 0 6px 22px rgba(36, 28, 18, 0.07);
  transition: color 0.35s var(--ease), border-color 0.35s var(--ease),
              box-shadow 0.35s var(--ease);
}

.journey-icon svg { width: 34px; height: 34px; display: block; }

/* Reached stages take the brand gold; initJourney() adds .is-lit as the
   rail passes each one. */
.journey-step.is-lit .journey-icon {
  color: var(--primary);
  border-color: rgba(201, 150, 47, 0.45);
  box-shadow: 0 8px 26px rgba(201, 150, 47, 0.22);
}

.journey-num {
  font-family: var(--font-heading);
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: var(--primary);
  margin-bottom: 6px;
}

.journey-name {
  font-family: var(--font-display);
  font-size: 1.6rem;
  font-weight: 400;
  line-height: 1.15;
  color: var(--text);
  margin-bottom: 8px;
}

.journey-note {
  font-size: 0.88rem;
  line-height: 1.55;
  color: var(--text-muted);
  max-width: 22ch;
}

@media (max-width: 1024px) {
  .journey { grid-template-columns: repeat(3, 1fr); gap: 40px 24px; }
  /* The rail only reads as a single thread across one unbroken row, so it
     goes as soon as the grid wraps. */
  .journey-rail { display: none; }
}

@media (max-width: 620px) {
  .journey { grid-template-columns: repeat(2, 1fr); gap: 36px 20px; margin-top: 44px; }
  .journey-icon { width: 58px; height: 58px; margin-bottom: 14px; }
  .journey-icon svg { width: 28px; height: 28px; }
  .journey-name { font-size: 1.3rem; }
  .journey-note { font-size: 0.82rem; }
}


@media (max-width: 768px) {
  .flow-strip { flex-direction: column; gap: 16px; }
  .flow-arrow { transform: rotate(90deg); }
}

/* ── TRUST — editorial three-column, dividers not cards ────── */












@media (max-width: 900px) {
  
  }

/* ── PORTFOLIO ─────────────────────────────────────────────── */
/* One tour per row, full rail width, stacked straight down. The old two-up
   grid squeezed each Street View to ~460px wide, where Google's own chrome
   (compass, zoom, level picker, copyright bar) ate a third of the frame. */
.portfolio-grid {
  display: flex;
  flex-direction: column;
  gap: clamp(32px, 5vw, 56px);
  max-width: var(--rail);
  margin: 0 auto;
}

.portfolio-embed {
  width: 100%;
  border-radius: 20px;
  overflow: hidden;
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.25);
  border: 1px solid var(--border);
  background: #17100a;
  /* Keeps the rounded clip on Safari while the iframe composites. */
  isolation: isolate;
}

.embed-frame { position: relative; }

/* 16:9 window capped to the viewport, so a full-width tour never becomes
   taller than the screen it is viewed on. The height attribute in the markup
   stays as the no-CSS fallback. */
.portfolio-embed iframe {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  min-height: 300px;
  max-height: 78vh;
  max-height: 78svh;
  border: 0;
}

.portfolio-name {
  padding: 18px 24px;
  background: var(--surface);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--text);
  border-bottom: 1px solid var(--border);
}

/* Scroll shield (initEmbedShields in app.js): transparent, so the tour is
   fully visible, but it owns the wheel/swipe until someone opts in. */
.embed-shield {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0 0 22px;
  border: 0;
  background: transparent;
  cursor: pointer;
  font: inherit;
  touch-action: pan-y;
}

.embed-shield-pill {
  padding: 9px 18px;
  border-radius: 100px;
  background: rgba(23, 16, 10, 0.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(245, 239, 224, 0.16);
  color: rgba(245, 239, 224, 0.92);
  font-family: var(--font-heading);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  transition: opacity 0.3s var(--ease);
}

.embed-shield:hover .embed-shield-pill,
.embed-shield:focus-visible .embed-shield-pill { opacity: 1; background: rgba(23, 16, 10, 0.88); }

.embed-live .embed-shield { display: none; }

@media (max-width: 768px) {
  .portfolio-embed { border-radius: 14px; }
  /* A phone in portrait is taller than wide; 4:3 shows far more of the room
     than a letterboxed 16:9 strip. */
  .portfolio-embed iframe { aspect-ratio: 4 / 3; min-height: 260px; }
  .portfolio-name { padding: 14px 18px; font-size: 1.02rem; }
  .embed-shield { padding-bottom: 14px; }
}

/* ── LOCATION PAGES (e.g. /360-virtual-tour-indiranagar-bengaluru/) ── */
.location-hero { padding: 160px 0 56px; }

.crumbs {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  margin-bottom: 18px;
  font-size: 0.82rem;
  color: var(--text-muted);
}
.crumbs a { color: var(--accent-ink); text-decoration: none; }
.crumbs a:hover { text-decoration: underline; }

.location-h1 {
  font-family: var(--font-display);
  font-size: clamp(2.3rem, 5vw, 4.2rem);
  font-weight: 300;
  line-height: 1.06;
  letter-spacing: -0.012em;
  max-width: 20ch;
  margin: 4px 0 22px;
}
.location-h1 .gradient-text {
  font-size: inherit;
  display: inline;
  background: linear-gradient(135deg, #a97a1c 0%, #c9962f 50%, #8a6212 100%);
  -webkit-background-clip: text;
  background-clip: text;
}

.location-lede {
  font-size: 1.14rem;
  line-height: 1.7;
  color: var(--text-muted);
  max-width: 62ch;
  margin-bottom: 30px;
}

.location-cta { text-decoration: none; }

.geo-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.7);
  box-shadow: 0 20px 60px rgba(36, 28, 18, 0.1);
}

.geo-table {
  width: 100%;
  min-width: 560px;
  border-collapse: collapse;
  font-size: 0.95rem;
}
.geo-table th,
.geo-table td {
  padding: 18px 22px;
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--border);
}
.geo-table thead th {
  font-family: var(--font-heading);
  font-size: 0.78rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--accent-ink);
  background: rgba(201, 150, 47, 0.08);
}
.geo-table thead th:nth-child(2) { color: #8a6212; }
.geo-table tbody th { font-weight: 700; color: var(--text); }
.geo-table td { color: var(--text-muted); }
.geo-table tbody td:nth-child(2) { color: var(--text); font-weight: 600; }
.geo-table tbody tr:last-child th,
.geo-table tbody tr:last-child td { border-bottom: 0; }

.faq-item p strong { color: var(--text); }

/* Header dropdowns on the location page. <details> so they open with no JS
   and work with keyboard, touch and screen readers out of the box. */
.nav-drop { position: relative; }
.nav-drop > summary { list-style: none; cursor: pointer; display: inline-flex; align-items: center; gap: 6px; }
.nav-drop > summary::-webkit-details-marker { display: none; }
.nav-drop > summary::after { content: '▾'; font-size: 0.7em; opacity: 0.7; }

.nav-drop-menu {
  position: absolute;
  top: calc(100% + 12px);
  left: -14px;
  min-width: 240px;
  display: flex;
  flex-direction: column;
  padding: 8px;
  background: rgba(250, 246, 238, 0.98);
  border: 1px solid var(--border);
  border-radius: 14px;
  box-shadow: 0 18px 40px rgba(36, 28, 18, 0.16);
  z-index: 5;
}
.nav-drop-menu a {
  padding: 10px 12px;
  border-radius: 8px;
  color: var(--text-muted);
  text-decoration: none;
  font-size: 0.9rem;
}
.nav-drop-menu a:hover,
.nav-drop-menu a[aria-current="page"] { background: rgba(201, 150, 47, 0.12); color: var(--text); }

@media (max-width: 768px) {
  .location-hero { padding: 120px 0 36px; }
  .location-lede { font-size: 1.02rem; }
  .nav-drop { border-bottom: 1px solid rgba(36, 28, 18, 0.08); }
  .nav-drop > summary { padding: 15px 0; font-size: 1.02rem; width: 100%; }
  .nav-drop-menu { position: static; min-width: 0; padding: 0 0 10px 12px; background: none; border: 0; box-shadow: none; }
}

/* ── SERVICE TECH TAGS (Services page industry pills) ──────── */


/* ── BEFORE / AFTER ────────────────────────────────────────── */
.ba-wrapper { border-radius: 20px; overflow: hidden; box-shadow: 0 30px 80px rgba(0, 0, 0, 0.5); }
/* 2:1 to match the panoramas exactly. At a fixed 500px the container was
   2.35:1 and object-fit:cover quietly shaved the top and bottom off both
   frames — the worst thing to crop when the whole point is showing a full
   spherical capture. */
.ba-container { position: relative; width: 100%; aspect-ratio: 2 / 1; max-height: 620px; cursor: ew-resize; user-select: none; }
.ba-before, .ba-after { position: absolute; inset: 0; overflow: hidden; }
.ba-before img, .ba-after img { width: 100%; height: 100%; object-fit: cover; }
.ba-after { width: 50%; }

/* Plain labels, not buttons. The gold pill on one side and the dark pill on
   the other gave the two captions completely different visual weight — they
   read as a primary control and a secondary one rather than as two halves of
   the same comparison. Both are now identical in face, size, weight and
   tracking; only the colour separates them. The text-shadow replaces the
   pill's job of holding the label legible over whatever is behind it. */
.ba-badge {
  position: absolute; top: 20px;
  font-family: var(--font-heading);
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85), 0 2px 16px rgba(0, 0, 0, 0.7);
}

/* Each label is pinned to the side its own layer actually occupies, so both
   stay readable at once. Previously both sat at left:18px and the base
   layer's badge spent the whole time hidden underneath the top layer. */
.ba-badge.is-raw {
  left: 20px;
  color: rgba(245, 239, 224, 0.92);
}

.ba-badge.is-stitched {
  right: 20px;
  color: #e8c377;
}

.ba-handle {
  position: absolute; top: 0; bottom: 0; left: 50%;
  transform: translateX(-50%); width: 44px;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  z-index: 10;
}

.ba-line { flex: 1; width: 2px; background: #fff; }
.ba-grip {
  width: 40px; height: 40px; border-radius: 50%;
  background: var(--primary); border: 3px solid #fff;
  display: flex; align-items: center; justify-content: center; color: #fff;
}

.btn-card {
  display: block; text-align: center; padding: 12px;
  border-radius: 12px; background: rgba(36, 28, 18, 0.05);
  border: 1px solid rgba(36, 28, 18, 0.16); color: var(--text);
  text-decoration: none; font-size: 0.9rem; font-weight: 700;
  font-family: var(--font-heading); transition: all 0.25s ease;
}

.btn-card.primary { background: var(--primary); border-color: var(--primary); color: #241c12; }

/* ── HOOK SECTION — pinned scroll reveal into Services ──────
   Taller than the viewport on purpose: GSAP pins it at `top top` for
   the full scroll distance so each word gets its own slice of scroll
   before the section releases and Contact scrolls in underneath. */
/* Scroll distance is section height minus the 100vh pin, so this leaves
   ~90vh of scrub — enough for three beats now that body copy follows the two
   display lines. It was cut to 150vh when the frame held nothing but a single
   sentence and the surrounding dark read as empty; with real content in it
   the extra dwell is doing work rather than stalling. */
.hook-section {
  position: relative;
  height: 190vh;
  background: #241c12;
}

.hook-pin {
  position: sticky;
  top: 0;
  height: 100vh;
  height: 100svh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  text-align: center;
  padding: 0 24px;
}

/* The whole statement is one unbroken line, so the type is sized in vw and
   the row is nowrap. `gap` resolves against THIS element's font-size, not
   each word's — leaving it unset here collapsed the word spacing to a few
   pixels while the words themselves rendered at ~90px. */
.hook-words {
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  align-items: baseline;
  /* The line was only filling ~56% of the viewport, which is what made the
     margins around it read as dead space. It has 640px of headroom at
     1440px wide, so the type goes up rather than the frame coming down —
     nowrap means this can never exceed roughly 75% fill. */
  font-size: clamp(1rem, 5.8vw, 5.8rem);
  gap: 0.28em;
  max-width: 100%;
}

.hook-word {
  font-family: var(--font-display);
  font-size: inherit;
  font-weight: 400;
  color: #f5efe0;
  line-height: 1.15;
  white-space: nowrap;
  will-change: transform, opacity, color;
}

.hook-word.script {
  font-family: var(--font-script);
  font-style: italic;
  color: #f5efe0;
}

/* .gradient-text carries its own clamp() font-size for the hero; inside the
   hook it has to track the line so the single line stays measurable. */
.hook-words .gradient-text {
  font-size: inherit;
  line-height: 1.15;
}



.hook-tagline {
  display: flex;
  flex-wrap: nowrap;
  justify-content: center;
  margin-top: 0.7em;
  font-family: var(--font-script);
  font-style: italic;
  font-size: clamp(1rem, 3.2vw, 2.6rem);
  gap: 0.3em;
  color: var(--primary);
}

/* Body copy inside the pinned frame. Sized and measured for reading rather
   than for display: the two lines above it are set in vw and run nowrap, but
   this has to wrap, so it takes a ch-based measure and steps down on smaller
   viewports like any other paragraph. */
.hook-body {
  margin-top: 2em;
  /* Measure is in ch, so it tracks the larger type automatically and the line
     length stays readable instead of widening with the font. */
  max-width: 56ch;
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 0 8px;
}

.hook-para {
  font-family: var(--font-body);
  font-size: 1.34rem;
  line-height: 1.62;
  color: rgba(245, 239, 224, 0.78);
}

/* The closing line hands off to the industry sections below, so it sits a
   step back from the paragraph it follows rather than competing with it. */
.hook-bridge {
  font-size: 1.16rem;
  color: rgba(245, 239, 224, 0.56);
}

@media (max-width: 768px) {
  .hook-body { margin-top: 1.6em; gap: 14px; }
  .hook-para { font-size: 1.06rem; line-height: 1.58; }
  .hook-bridge { font-size: 0.98rem; }
}

.hook-tagline-word {
  font-size: inherit;
  line-height: 1.2;
  white-space: nowrap;
  will-change: transform, opacity;
}

/* Below this width a single line would drop the statement to ~16px, so let
   it break across two lines and take the type back up instead. */
@media (max-width: 700px) {
  .hook-words { flex-wrap: wrap; font-size: clamp(1.9rem, 8.4vw, 3rem); }
  .hook-tagline { flex-wrap: wrap; font-size: clamp(1.3rem, 5.4vw, 2rem); }
}

/* ── FAQ ───────────────────────────────────────────────────── */
.faq-list {
  max-width: 780px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.faq-item {
  padding: 24px 0;
  border-bottom: 1px solid var(--border);
}

.faq-item h3 {
  font-family: var(--font-heading);
  font-size: 1.05rem;
  font-weight: 700;
  margin-bottom: 8px;
}

.faq-item p {
  color: var(--text-muted);
  font-size: 0.92rem;
  line-height: 1.7;
}

/* ── CONTACT & FLOATING WHATSAPP ───────────────────────────── */
.contact-grid { display: grid; grid-template-columns: 1fr 1.2fr; gap: 64px; }
.contact-details { display: flex; flex-direction: column; gap: 14px; margin-top: 24px; }
.cd-item { display: flex; align-items: center; gap: 12px; color: var(--text-muted); font-size: 0.92rem; }
.cd-item svg { color: var(--primary); }
.cd-item a { color: inherit; text-decoration: none; }
.cd-item a:hover { color: var(--accent-ink); text-decoration: underline; }

.phone-cta {
  display: inline-flex;
  align-items: center;
  gap: 12px;
  margin: 8px 0 28px;
  font-family: var(--font-heading);
  font-size: clamp(1.6rem, 3vw, 2.2rem);
  font-weight: 400;
  color: var(--text);
  text-decoration: none;
  border-bottom: 2px solid var(--primary);
  padding-bottom: 4px;
  transition: color 0.25s ease;
}
.phone-cta svg { color: var(--primary); flex-shrink: 0; }
.phone-cta:hover { color: var(--primary); }

.contact-form {
  background: rgba(255, 255, 255, 0.7);
  border: 1px solid var(--border);
  border-radius: 20px; padding: 32px;
}

/* Eleven fields stacked at 16px read as one dense block — the eye has no
   handhold between rows and the form looks longer than it is. The column gap
   grows with it so the two halves of each row stay visibly separate. */
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 26px; }
.fg { display: flex; flex-direction: column; gap: 9px; margin-bottom: 26px; }
.fg label { font-size: 0.8rem; font-weight: 700; color: var(--text-muted); text-transform: uppercase; letter-spacing: 0.04em; }

/* Name and phone are enforced by the browser's required attribute and again
   by /api/contact, which rejects a submission missing either. This is just
   the visible half of that contract — aria-hidden because the input's own
   required state is what a screen reader should be told, not a stray
   asterisk read mid-label. */
.fg label .req { color: var(--primary); font-weight: 700; }

/* Two columns inside a 375px viewport leaves ~110px per input — too narrow
   for a phone number, and labels like "Number of Rooms / Spaces" wrap to
   three lines above them. The row collapses instead; .fg already carries the
   vertical rhythm, so the row gap goes to zero to avoid doubling it. */
@media (max-width: 620px) {
  .form-row { grid-template-columns: 1fr; gap: 0; }
}
.fg input, .fg select, .fg textarea {
  width: 100%; padding: 12px 16px;
  background: rgba(36, 28, 18, 0.03);
  border: 1px solid rgba(36, 28, 18, 0.15);
  border-radius: 12px; color: var(--text); font-family: var(--font-body);
  font-size: 0.92rem; outline: none;
}

.btn-submit {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%; padding: 14px; margin-top: 16px;
  background: #25D366; border: none; border-radius: 12px;
  color: #fff; font-family: var(--font-heading); font-size: 1rem;
  font-weight: 700; cursor: pointer;
  box-shadow: 0 4px 20px rgba(37, 211, 102, 0.35);
  transition: all 0.25s ease;
}

.btn-submit:hover { background: #20ba5a; transform: translateY(-2px); }
.btn-submit:disabled { opacity: 0.6; cursor: wait; transform: none; }

/* Honeypot — off-screen, not display:none, so most bot form-fillers
   that check computed visibility still populate it. */
.hp-field {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.form-status {
  min-height: 1.2em;
  margin-top: 12px;
  text-align: center;
  font-size: 0.85rem;
  font-weight: 600;
}
.form-status.success { color: #1f9d55; }
.form-status.error { color: #c0392b; }

.form-alt-hint {
  margin-top: 12px;
  text-align: center;
  font-size: 0.82rem;
  color: var(--text-muted);
}
.form-alt-hint a { color: var(--accent-ink); text-decoration: none; }
.form-alt-hint a:hover { text-decoration: underline; }

/* ── FINAL CTA — strong close before the footer ─────────────── */
.final-cta-section {
  padding: 120px 0;
  text-align: center;
  background: #241c12;
}

.final-cta {
  display: inline-flex;
  align-items: center;
  gap: 14px;
  font-family: var(--font-display);
  font-size: clamp(1.8rem, 4vw, 3rem);
  font-weight: 400;
  color: #f5efe0;
  text-decoration: none;
  border-bottom: 1px solid rgba(245, 239, 224, 0.3);
  padding-bottom: 10px;
  transition: border-color 0.25s ease, color 0.25s ease;
}
.final-cta:hover { color: var(--primary); border-color: var(--primary); }
.final-cta svg { flex-shrink: 0; }

/* Floating WhatsApp */
.floating-wa {
  position: fixed; bottom: 28px; right: 28px;
  width: 56px; height: 56px; border-radius: 50%;
  background: #25D366; display: flex; align-items: center; justify-content: center;
  box-shadow: 0 8px 30px rgba(37, 211, 102, 0.45);
  z-index: 999; transition: transform 0.25s ease;
}

.floating-wa:hover { transform: scale(1.1); }

/* FOOTER */
.site-footer { background: var(--bg-subtle); border-top: 1px solid var(--border); padding-top: 64px; }
/* Was a nested grid — a 1.5fr/2fr outer split with its own 3-column grid
   inside — so the link columns were spaced against a different track to the
   brand beside them and the whole block read as two unrelated halves.
   .footer-links now uses display:contents, which dissolves the wrapper and
   lets all four columns sit on one shared track with one consistent gap. */
.footer-inner { display: grid; grid-template-columns: 1.6fr 1fr 1fr 1fr; gap: 40px; padding-bottom: 56px; }
.footer-brand p { font-size: 0.88rem; color: var(--text-muted); margin-top: 12px; max-width: 34ch; }
.footer-links { display: contents; }
.fl-col h5,
.fl-col .fl-heading { font-size: 0.78rem; font-weight: 700; text-transform: uppercase; color: rgba(36, 28, 18, 0.8); margin-bottom: 14px; }
.fl-col a { display: block; color: var(--text-muted); text-decoration: none; font-size: 0.88rem; margin-bottom: 8px; line-height: 1.45; }
.fl-col a:hover { color: var(--primary); }
/* These three are sibling services in the JSON-LD, not a parent and a child,
   so the old 14px indent was making one link hang off the column's left edge
   for no reason. */
.fl-col a.fl-sub { padding-left: 0; font-size: 0.88rem; opacity: 1; }
.footer-bottom { border-top: 1px solid var(--border); padding: 20px 0; }
.footer-bottom .inner { display: flex; justify-content: space-between; font-size: 0.8rem; color: rgba(36, 28, 18, 0.8); }

/* REVEALS */
.reveal-up {
  opacity: 0; transform: translateY(30px);
  transition: opacity 0.8s var(--ease), transform 0.8s var(--ease);
}
.reveal-up.visible { opacity: 1; transform: translateY(0); }

/* ── SERVICES PAGE ───────────────────────────────────────────── */
.services-hero {
  padding: 180px 0 80px;
  text-align: center;
}
.services-hero .section-p { max-width: 640px; margin: 18px auto 0; }

.service-block {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 56px;
  align-items: center;
  padding: 72px 0;
  border-bottom: 1px solid var(--border);
}
.service-block:last-child { border-bottom: none; }
.service-block.reverse .service-media { order: -1; }

.service-badge {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 5px 14px;
  border-radius: 100px;
  background: rgba(201, 150, 47, 0.12);
  border: 1px solid rgba(201, 150, 47, 0.3);
  color: var(--accent-ink);
  font-size: 0.72rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin-bottom: 16px;
}

.service-content h2 { margin-bottom: 16px; }
.service-content p { color: var(--text-muted); font-size: 1rem; line-height: 1.7; margin-bottom: 20px; }

.service-tour-wrap {
  position: relative;
  width: 100%;
  height: 420px;
  border-radius: 20px;
  overflow: hidden;
  background: radial-gradient(circle at center, rgba(201, 150, 47, 0.15), rgba(42, 30, 16, 0.95));
  border: 1px solid var(--border);
}

.service-tour-canvas { width: 100%; height: 100%; display: block; cursor: grab; touch-action: pan-y; }
.service-tour-canvas:active { cursor: grabbing; }

.service-drag-hint {
  position: absolute;
  bottom: 14px; left: 50%;
  transform: translateX(-50%);
  font-size: 0.78rem;
  color: rgba(255, 255, 255, 0.85);
  padding: 5px 14px;
  background: rgba(0, 0, 0, 0.6);
  border-radius: 100px;
  pointer-events: none;
}

@media (max-width: 1024px) {
  .service-block { grid-template-columns: 1fr; gap: 24px; }
  .service-block.reverse .service-media { order: 0; }
  .service-tour-wrap { height: 320px; }
}

/* ── INDUSTRIES GRID — compact tiles, label always visible ──── */
.industries-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 16px;
}

/* Presentational only — these were anchors pointing at #contact, which made
   twelve photographs look clickable and then jumped the visitor somewhere
   they had not asked to go. They are labels for the industries served. */
.industry-tile {
  position: relative;
  display: block;
  aspect-ratio: 4 / 5;
  border-radius: 14px;
  overflow: hidden;
}

/* Overhangs its frame by 6% top and bottom so the parallax travel never
   drags an empty edge into view. Hover uses the independent `scale`
   property rather than a transform: GSAP owns `transform` on these images
   for the scrub, and the two compose instead of overwriting each other. */
.industry-tile img {
  position: absolute;
  inset: -6% 0;
  width: 100%;
  height: 112%;
  object-fit: cover;
  transition: scale 0.4s ease;
}
.industry-tile:hover img { scale: 1.06; }

/* The 6% overhang is always needed now: initParallax() scrubs these images on
   every device, including touch and reduced-motion setups. */

.industry-tile::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(20, 14, 6, 0.85) 0%, rgba(20, 14, 6, 0.05) 55%);
}

.industry-tile span {
  position: absolute;
  left: 16px;
  bottom: 14px;
  right: 16px;
  z-index: 1;
  font-family: var(--font-heading);
  font-weight: 700;
  font-size: 0.92rem;
  color: #f5efe0;
  line-height: 1.25;
}

@media (max-width: 1024px) {
  .industries-grid { grid-template-columns: repeat(3, 1fr); }
}

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

/* ── CURSOR RETICLE ─────────────────────────────────────
   HUD-style dot + reticle ring that trails the pointer. Deliberately
   layered on TOP of the native cursor rather than replacing it (no
   `cursor: none` on body) — the tour canvas, before/after handle and
   FOV slider all depend on native grab/resize cursors for their drag
   affordance, and hiding those would read as broken, not premium. */
.cursor-dot {
  position: fixed;
  top: 0; left: 0;
  width: 5px; height: 5px;
  background: var(--accent);
  border-radius: 50%;
  pointer-events: none;
  z-index: 10000;
  transform: translate(-50%, -50%);
  box-shadow: 0 0 10px var(--accent-glow);
}

.cursor-ring {
  position: fixed;
  top: 0; left: 0;
  width: 32px; height: 32px;
  border: 1px solid rgba(201, 150, 47, 0.45);
  border-radius: 50%;
  pointer-events: none;
  z-index: 10000;
  transform: translate(-50%, -50%);
  transition: width 0.3s var(--ease), height 0.3s var(--ease), border-color 0.3s var(--ease);
}

.cursor-ring::before,
.cursor-ring::after {
  content: '';
  position: absolute;
  background: var(--primary);
}
.cursor-ring::before { top: -1px; left: 50%; width: 1px; height: 6px; transform: translateX(-50%); }
.cursor-ring::after { left: -1px; top: 50%; width: 6px; height: 1px; transform: translateY(-50%); }

.cursor-ring.hover {
  width: 54px; height: 54px;
  border-color: var(--accent);
}

.cursor-ripple {
  position: fixed;
  top: 0; left: 0;
  width: 12px; height: 12px;
  border: 1px solid var(--accent);
  border-radius: 50%;
  pointer-events: none;
  z-index: 9999;
  transform: translate(-50%, -50%) scale(1);
  animation: cursor-ripple-out 0.6s var(--ease) forwards;
}

@keyframes cursor-ripple-out {
  to { transform: translate(-50%, -50%) scale(4.5); opacity: 0; }
}

@media (pointer: coarse), (max-width: 768px) {
  .cursor-dot, .cursor-ring { display: none; }
}

/* ── MAGNETIC BUTTONS ────────────────────────────────────────── */
.magnetic { will-change: transform; }

/* RESPONSIVE */
@media (max-width: 1024px) {
  .chapter-row { grid-template-columns: 1fr; gap: 16px; }
  .contact-grid { grid-template-columns: 1fr; }
  .footer-inner { grid-template-columns: 1fr 1fr; gap: 36px; }
  .footer-brand { grid-column: 1 / -1; }
}

@media (max-width: 768px) {
  /* The nav becomes a panel rather than disappearing. It is kept in the DOM
     and moved off-canvas instead of display:none so it stays focusable in
     order and the slide can be animated. */
  .main-nav {
    position: fixed;
    inset: 0 0 auto 0;
    top: 71px;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding: 12px 24px 26px;
    background: rgba(250, 246, 238, 0.98);
    -webkit-backdrop-filter: blur(18px);
    backdrop-filter: blur(18px);
    border-bottom: 1px solid var(--border);
    box-shadow: 0 18px 40px rgba(36, 28, 18, 0.16);
    transform: translateY(-12px);
    opacity: 0;
    visibility: hidden;
    pointer-events: none;
    transition: opacity 0.28s var(--ease), transform 0.28s var(--ease), visibility 0.28s;
  }

  .main-nav.is-open {
    transform: translateY(0);
    opacity: 1;
    visibility: visible;
    pointer-events: auto;
  }

  .main-nav .nav-a {
    padding: 15px 0;
    font-size: 1.02rem;
    border-bottom: 1px solid rgba(36, 28, 18, 0.08);
  }

  .main-nav .nav-a:last-child { border-bottom: none; }
    .hero-h1 { font-size: 2.6rem; }
  
  }

/* ================================================================
   MOTION LAYER — hero intro, scroll cue, parallax, reduced motion
   ================================================================ */

/* Hero intro elements start hidden and are handed to GSAP. `.motion-ready`
   is set by app.js only once GSAP is confirmed present, so with scripting
   off — or if the CDN fails — the hero renders fully visible instead of
   being stranded at opacity 0. */
/* Hero intro in pure CSS. The H1 is this page's Largest Contentful Paint;
   when its reveal waited for GSAP, LCP waited for every deferred script to
   download and execute (~8s on a mid-range phone). Keyframes start on first
   paint instead, with the same rise-out-of-mask motion and stagger.
   fill-mode "both" holds the start state during each delay. */
@keyframes hero-line-in {
  from { opacity: 0; transform: translateY(108%); }
  to { opacity: 1; transform: none; }
}
@keyframes hero-fade-up {
  from { opacity: 0; transform: translateY(22px); }
  to { opacity: 1; transform: none; }
}
.h1-line-i { animation: hero-line-in 1.25s cubic-bezier(0.16, 1, 0.3, 1) 0.28s both; }
.h1-line:nth-child(2) .h1-line-i { animation-delay: 0.37s; }
.h1-line:nth-child(3) .h1-line-i { animation-delay: 0.46s; }
.h1-line:nth-child(4) .h1-line-i { animation-delay: 0.55s; }
.hero-p.hero-anim { animation: hero-fade-up 1s cubic-bezier(0.16, 1, 0.3, 1) 0.66s both; }
.hero-quote.hero-anim { animation: hero-fade-up 1s cubic-bezier(0.16, 1, 0.3, 1) 0.78s both; }

/* ── Parallax ───────────────────────────────────────────────── */
/* Elements carrying [data-parallax] are driven by GSAP in app.js. The
   promotion hint lives here so the compositor layer exists before the
   first scrub frame rather than being created mid-scroll. */
[data-parallax] {
  will-change: transform;
}

/* Media that parallaxes has to be taller than its frame, otherwise the
   travel exposes the edge of the image. */


/* ── Paint / layout cost below the fold ─────────────────────── */
/* The industries grid and FAQ are long, image-heavy and always off-screen
   at load; skipping their layout+paint until they approach the viewport
   takes real work off the main thread during the hero intro. The
   contain-intrinsic-size keeps the scrollbar honest so ScrollTrigger's
   cached ranges do not jump when they are finally rendered. */
/* Sizes are the measured rendered heights at desktop width, not a round
   guess — a placeholder that is 600px short makes the scrollbar lie until
   the section is first painted, and every ScrollTrigger range below it has
   to be re-measured when it corrects itself. The `auto` keyword means the
   browser remembers the real height after the first render and stops using
   the estimate at all. */
.industries-grid-section {
  content-visibility: auto;
  contain-intrinsic-size: auto 1486px;
}

.faq-section {
  content-visibility: auto;
  contain-intrinsic-size: auto 1081px;
}

/* ── Responsive: the F collapses to a single column ─────────── */
@media (max-width: 900px) {
  .hero-h1 { max-width: 100%; }
  .hero-p { max-width: 100%; }
  .hero-quote { max-width: 100%; font-size: 1.12rem; }
  .hero-overlay {
    /* Copy now spans the full width, so the scrim has to as well. */
    background:
      linear-gradient(180deg,
        rgba(26, 16, 7, 0.82) 0%,
        rgba(26, 16, 7, 0.88) 55%,
        rgba(26, 16, 7, 0.94) 100%);
  }
}

@media (max-width: 768px) {
  .hero-h1 { font-size: 2.55rem; margin-bottom: 20px; }
  .gradient-text { font-size: 2.8rem; }
  .hero-p { font-size: 1.02rem; }
  .hero-quote { font-size: 1rem; margin-bottom: 28px; }
  .hero-overlay-inner { padding: 88px 24px 40px; }
}

/* No reduced-motion override here: scroll choreography runs for every visitor
   (see PREFERS_REDUCED in app.js). The hero can still never be stranded
   invisible — app.js drops .motion-ready if GSAP fails, plus a 4s failsafe. */

/* ── LIVE PANORAMA — drag-to-look 360 viewer ────────────────────
   Shares the three.js sphere viewer with the service blocks. The frame is
   16:9 rather than the source's 2:1 because the camera only ever shows a
   ~75deg slice of the sphere; the frame's shape is a window onto the room,
   not a container for the equirectangular image. */
.pano-frame {
  position: relative;
  /* Sits directly under the before/after slider inside the same section now,
     so it needs the gap that used to come from being its own section. */
  margin-top: 56px;
  border-radius: 20px;
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: 0 30px 80px rgba(36, 28, 18, 0.28);
  background: #17100a;
  aspect-ratio: 16 / 9;
  max-height: 660px;
}

.pano-canvas {
  display: block;
  width: 100%;
  height: 100%;
  cursor: grab;
  /* First line of defence for touch: the browser keeps vertical gestures for
     scrolling and only hands sideways ones to the viewer, so looking around
     never steals a scroll. app.js enforces the same split a second time. */
  touch-action: pan-y;
}

.pano-canvas:active { cursor: grabbing; }

.pano-hint {
  position: absolute;
  left: 50%;
  bottom: 22px;
  translate: -50% 0;
  display: flex;
  align-items: center;
  gap: 9px;
  padding: 9px 18px;
  border-radius: 100px;
  background: rgba(23, 16, 10, 0.72);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  border: 1px solid rgba(245, 239, 224, 0.16);
  color: rgba(245, 239, 224, 0.9);
  font-family: var(--font-heading);
  font-size: 0.74rem;
  font-weight: 600;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  pointer-events: none;
  transition: opacity 0.5s var(--ease);
}

/* The prompt has done its job the moment someone takes hold of the room. */
.pano-frame.is-explored .pano-hint { opacity: 0; }

@media (max-width: 768px) {
  .pano-frame { aspect-ratio: 4 / 3; margin-top: 32px; border-radius: 14px; }
  .pano-hint { bottom: 16px; font-size: 0.68rem; padding: 8px 14px; }
}

/* ================================================================
   MOBILE & TOUCH HARDENING
   Behaviours that only bite on real phones, so they are easy to miss
   on a desktop browser window narrowed to phone width.
   ================================================================ */

@media (max-width: 768px) {
  /* iOS Safari zooms the whole page in whenever a form control smaller than
     16px receives focus, and does not zoom back out afterwards. The fields
     were 14.72px, so every visitor tapping "Full Name" got thrown into a
     zoomed viewport for the rest of the form. 16px is the exact threshold. */
  .fg input,
  .fg select,
  .fg textarea {
    font-size: 16px;
  }

  /* Comfortable touch targets. Footer links were 20px tall against Apple's
     44px guidance and WCAG's 24px floor — small enough to mis-tap on the
     move, which is where this page is read. */
  .fl-col a {
    padding: 9px 0;
    margin-bottom: 0;
  }

  .footer-bottom .inner a,
  .cd-item a,
  .phone-cta {
    display: inline-flex;
    align-items: center;
    min-height: 44px;
  }

  .nav-a {
    padding: 10px 0;
  }

  /* Inline link inside a sentence, so it cannot take block padding without
     breaking the line box — inline-block plus a min-height gives it a real
     target while leaving the surrounding text flowing normally. */
  .form-alt-hint a {
    display: inline-block;
    min-height: 32px;
    line-height: 32px;
  }
}

/* Stops a grey flash on tap in iOS/Android Chrome — the elements here already
   have their own hover and active treatments. */
a, button, .industry-tile, .room-node {
  -webkit-tap-highlight-color: transparent;
}

/* Keeps a rubber-band overscroll at the top of the page from dragging the
   fixed header with it on iOS. */
html, body {
  overscroll-behavior-y: none;
}

/* ── Mobile nav toggle ──────────────────────────────────────── */
/* Hidden on desktop, where the full nav is already visible. */
.nav-toggle {
  display: none;
  width: 44px;
  height: 44px;
  padding: 0;
  border: 1px solid var(--border);
  border-radius: 10px;
  background: rgba(255, 255, 255, 0.6);
  cursor: pointer;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  order: 3;
}

.nav-toggle-bar {
  display: block;
  width: 18px;
  height: 1.5px;
  border-radius: 2px;
  background: var(--text);
  transition: transform 0.28s var(--ease), opacity 0.2s var(--ease);
}

/* Bars fold into an X while the panel is open. */
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

@media (max-width: 768px) {
  .nav-toggle { display: flex; }
  /* The full label does not fit beside a toggle at 375px, so the CTA shortens
     to "Book". order:-1 puts the pseudo-element ahead of the arrow SVG, which
     sits after the (now hidden) span in the markup — without it the button
     reads as an arrow followed by its label. */
  .header-actions .btn-pill span { display: none; }
  .header-actions .btn-pill::after { content: 'Book'; order: -1; }
}

@media (prefers-reduced-motion: reduce) {
  .main-nav, .nav-toggle-bar { transition: none; }
}

/* ── LEGAL PAGE (privacy / terms) ───────────────────────────── */
.legal-page { padding-top: 150px; }

.legal-head { max-width: 760px; margin-bottom: 44px; }

.legal-h1 {
  font-family: var(--font-display);
  font-size: clamp(2.2rem, 4.6vw, 3.6rem);
  font-weight: 300;
  line-height: 1.08;
  letter-spacing: -0.012em;
  color: var(--text);
  margin: 6px 0 14px;
}

.legal-meta {
  font-size: 0.86rem;
  color: var(--text-muted);
}

/* A measure sized for sustained reading rather than for display — this is the
   one page on the site someone reads top to bottom. */
.legal-body { max-width: 68ch; }

.legal-lede {
  font-size: 1.14rem;
  line-height: 1.7;
  color: var(--text);
  padding-bottom: 26px;
  margin-bottom: 30px;
  border-bottom: 1px solid var(--border);
}

.legal-body h2 {
  font-family: var(--font-display);
  font-size: 1.62rem;
  font-weight: 400;
  color: var(--text);
  margin: 40px 0 12px;
  /* Anchored headings (#terms) must clear the fixed header when jumped to. */
  scroll-margin-top: 100px;
}

.legal-body p,
.legal-body li {
  font-size: 1rem;
  line-height: 1.72;
  color: var(--text-muted);
}

.legal-body p { margin-bottom: 14px; }

.legal-body ul {
  margin: 0 0 18px;
  padding-left: 22px;
}

.legal-body li { margin-bottom: 9px; }

.legal-body strong { color: var(--text); font-weight: 700; }

.legal-body a {
  color: var(--accent-ink);
  text-decoration: underline;
  text-underline-offset: 3px;
}

.legal-body a:hover { color: var(--primary); }

.legal-body code {
  font-size: 0.88em;
  padding: 2px 6px;
  border-radius: 5px;
  background: rgba(36, 28, 18, 0.07);
  color: var(--text);
}

/* The footer's legal links were plain text; now they are real links they need
   to look like the muted chrome around them rather than body links. */
.footer-bottom a {
  color: inherit;
  text-decoration: none;
}

.footer-bottom a:hover { color: var(--primary); }

@media (max-width: 768px) {
  .legal-page { padding-top: 118px; }
  .legal-body h2 { font-size: 1.4rem; margin-top: 32px; }
}

/* ── BLOG (generated by scripts/build-blog.mjs) ─────────────────── */
.blog-index { padding-top: 12px; }

.blog-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 28px;
}
.blog-grid-compact { gap: 22px; }

.blog-card {
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.72);
  color: var(--text);
  text-decoration: none;
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.blog-card:hover {
  transform: translateY(-4px);
  border-color: rgba(201, 150, 47, 0.4);
  box-shadow: 0 18px 44px rgba(201, 150, 47, 0.14);
}
.blog-card-media { display: block; aspect-ratio: 3 / 2; overflow: hidden; background: var(--bg-subtle); }
.blog-card-media img { width: 100%; height: 100%; object-fit: cover; display: block; transition: scale 0.5s var(--ease); }
.blog-card:hover .blog-card-media img { scale: 1.05; }
.blog-card-body { display: flex; flex-direction: column; gap: 10px; padding: 22px 22px 24px; flex: 1; }
.blog-card-cat {
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-ink);
}
.blog-card-title {
  font-family: var(--font-display);
  font-size: 1.45rem;
  font-weight: 400;
  line-height: 1.18;
  color: var(--text);
}
.blog-card-excerpt { font-size: 0.9rem; line-height: 1.6; color: var(--text-muted); }
.blog-card-meta { margin-top: auto; font-size: 0.8rem; font-weight: 600; color: #8a6212; }

.post-hero { padding: 150px 0 28px; }
.post-inner { max-width: 880px; }
.post-h1 { max-width: 24ch; }
.post-meta { font-size: 0.86rem; color: var(--text-muted); }

.post-figure { margin: 8px 0 36px; }
.post-figure img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  border-radius: 20px;
  border: 1px solid var(--border);
  box-shadow: 0 24px 60px rgba(36, 28, 18, 0.14);
  display: block;
}
.post-figure figcaption { margin-top: 10px; font-size: 0.8rem; color: var(--text-muted); }

.post-summary { display: grid; grid-template-columns: 1.15fr 1fr; gap: 20px; margin-bottom: 44px; }
.post-takeaways,
.post-toc {
  padding: 24px 26px;
  border-radius: 18px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.72);
}
.post-takeaways { border-color: rgba(201, 150, 47, 0.35); background: rgba(201, 150, 47, 0.07); }
.post-takeaways h2,
.post-toc h2 {
  font-family: var(--font-heading);
  font-size: 0.78rem;
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent-ink);
  margin-bottom: 12px;
}
.post-takeaways ul,
.post-toc ol { padding-left: 20px; display: flex; flex-direction: column; gap: 8px; }
.post-takeaways li { font-size: 0.94rem; line-height: 1.55; color: var(--text); }
.post-toc li { font-size: 0.9rem; line-height: 1.45; color: var(--text-muted); }
.post-toc a { color: var(--accent-ink); text-decoration: none; }
.post-toc a:hover { text-decoration: underline; }

.post-body { max-width: 70ch; }
.post-body h2 {
  font-family: var(--font-display);
  font-size: clamp(1.7rem, 3vw, 2.2rem);
  font-weight: 400;
  line-height: 1.15;
  color: var(--text);
  margin: 48px 0 14px;
  scroll-margin-top: 100px;
}
.post-body h2:first-child { margin-top: 0; }
.post-body h3 {
  font-family: var(--font-heading);
  font-size: 1.08rem;
  font-weight: 700;
  color: var(--text);
  margin: 26px 0 8px;
}
.post-body p,
.post-body li { font-size: 1.04rem; line-height: 1.78; color: var(--text-muted); }
.post-body p { margin-bottom: 16px; }
.post-body ul,
.post-body ol { margin: 0 0 20px; padding-left: 22px; display: flex; flex-direction: column; gap: 8px; }
.post-body strong { color: var(--text); }
.post-body a { color: var(--accent-ink); text-decoration: underline; text-underline-offset: 3px; }
.post-body a:hover { color: var(--primary); }
.post-body .geo-table-wrap { margin: 8px 0 18px; }
.post-body .geo-table { min-width: 640px; font-size: 0.9rem; }

.post-cta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 24px;
  margin: 56px 0;
  padding: 30px 34px;
  border-radius: 22px;
  background: #241c12;
  color: #f5efe0;
}
.post-cta h2 { font-family: var(--font-display); font-size: 1.8rem; font-weight: 400; line-height: 1.15; margin-bottom: 6px; }
.post-cta p { color: rgba(245, 239, 224, 0.75); font-size: 0.96rem; }
.post-cta .btn-enter-tour { flex-shrink: 0; text-decoration: none; }

.post-faq { margin-bottom: 64px; scroll-margin-top: 100px; }
.post-faq > h2,
.post-related > h2 {
  font-family: var(--font-display);
  font-size: clamp(1.9rem, 3.4vw, 2.5rem);
  font-weight: 400;
  margin-bottom: 12px;
}
.post-faq .faq-list { max-width: none; margin: 0; }
.post-faq .faq-item p { font-size: 0.98rem; }

.post-related { margin-bottom: 84px; }
.post-related .blog-grid { margin-top: 18px; }
.post-related .blog-card-title { font-size: 1.22rem; }
.post-related .blog-card-excerpt { display: none; }

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

@media (max-width: 768px) {
  .blog-grid { grid-template-columns: 1fr; }
  .post-hero { padding: 116px 0 18px; }
  .post-summary { grid-template-columns: 1fr; }
  .post-cta { flex-direction: column; align-items: flex-start; padding: 26px 22px; }
  .post-figure img { border-radius: 14px; }
  .post-body p,
  .post-body li { font-size: 1rem; }
}

/* ── 3D TEXT & SCROLL EFFECTS (effects.js) ───────────────────────── */
/* Elements waiting to animate sit in tilted 3D start states, and perspective
   projection makes their edges reach past the viewport — enough to let a page
   scroll sideways. <main> clips that horizontally. `clip` (not `hidden`) does
   not create a scroll container, so nothing sticky or pinned inside changes;
   `hidden` is only the fallback for browsers without clip. Only the content
   pages use <main>; the homepage is unaffected. */
main { overflow-x: hidden; }
@supports (overflow: clip) { main { overflow-x: clip; } }

/* The page H1 starts hidden so its letters can flip in. If effects.js never
   runs (blocked CDN, script error) this CSS-only animation reveals it anyway
   after 2.8s — the headline can never be stranded invisible. */
.fx-pending { opacity: 0; animation: fx-failsafe 0.01s 2.8s forwards; }
@keyframes fx-failsafe { to { opacity: 1; } }

.fx-hero { perspective: 1100px; }
.fx-tilt { transform-style: preserve-3d; will-change: transform; }
.fx-hero-title,
.post-body h2,
.post-faq > h2,
.post-related > h2,
.fx-heading,
.post-cta h2 { perspective: 700px; }

.fx-word { display: inline-block; transform-style: preserve-3d; }
.fx-char { display: inline-block; transform-style: preserve-3d; backface-visibility: hidden; }

/* Light gold extrusion on the page headline: stacked 1px shadows read as
   depth on the cream ground without hurting legibility. */
.fx-hero-title {
  text-shadow:
    0 1px 0 rgba(201, 150, 47, 0.32),
    0 2px 0 rgba(201, 150, 47, 0.26),
    0 3px 0 rgba(201, 150, 47, 0.2),
    0 4px 0 rgba(201, 150, 47, 0.14),
    0 14px 26px rgba(36, 28, 18, 0.14);
}
.fx-hero-title .gradient-text { text-shadow: none; filter: drop-shadow(0 3px 0 rgba(138, 98, 18, 0.28)); }

.fx-figure { perspective: 1300px; }
.fx-img { transform-style: preserve-3d; will-change: transform, clip-path; }

/* Cards: GSAP owns transform for the tilt, so the CSS hover lift and its
   transform transition would fight it. */
.blog-card,
.svc-card { position: relative; transform-style: preserve-3d; transition: box-shadow 0.3s var(--ease), border-color 0.3s var(--ease); }
.blog-card:hover { transform: none; }
.blog-card::after,
.svc-card::after {
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 0%), rgba(255, 255, 255, 0.42), transparent 48%);
  opacity: 0;
  transition: opacity 0.35s var(--ease);
}
.blog-card:hover::after,
.svc-card:hover::after { opacity: 1; }

/* Full-bleed band of extruded 3D words. */
.fx-band {
  position: relative;
  overflow: hidden;
  padding: clamp(56px, 10vw, 120px) 0;
  background: #241c12;
  perspective: 1000px;
}
.fx-band-track {
  display: flex;
  gap: 0.45em;
  width: max-content;
  white-space: nowrap;
  font-family: var(--font-display);
  font-size: clamp(3.2rem, 11vw, 9.5rem);
  font-weight: 400;
  line-height: 1;
  transform-style: preserve-3d;
  will-change: transform;
}
.fx-band-word {
  display: inline-block;
  color: #f5efe0;
  transform-style: preserve-3d;
  text-shadow:
    0 1px 0 #d9ad4f, 0 2px 0 #c9962f, 0 3px 0 #b8862a, 0 4px 0 #a97a24,
    0 5px 0 #9a6e1f, 0 6px 0 #8a6219, 0 7px 0 #7a5614, 0 8px 0 #6b4a10,
    0 20px 34px rgba(0, 0, 0, 0.55);
}
.fx-band-word.is-outline {
  color: transparent;
  -webkit-text-stroke: 1.5px #e0bd6a;
  text-shadow: none;
}
.fx-band-word.is-italic { font-style: italic; color: #e0bd6a; }

/* In-article image with caption (gallery images inside the post body). */
.post-body .fx-figure { margin: 30px 0 34px; }
.post-body .fx-figure img {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: cover;
  display: block;
  border-radius: 20px;
  border: 1px solid var(--border);
  box-shadow: 0 26px 60px rgba(36, 28, 18, 0.16);
}
.post-body .fx-figure figcaption { margin-top: 10px; font-size: 0.8rem; color: var(--text-muted); }

@media (max-width: 768px) {
  .fx-band-track { font-size: clamp(2.6rem, 15vw, 4.4rem); }
  .post-body .fx-figure img { border-radius: 14px; }
}

/* ── SERVICE PAGES ─────────────────────────────────────────────────── */
.svc-hero { padding: 150px 0 40px; }
.svc-hero-grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 48px; align-items: center; }
.svc-hero-actions { display: flex; flex-wrap: wrap; gap: 12px; align-items: center; }
.svc-hero-actions .btn-card { display: inline-flex; padding: 14px 24px; }
.svc-hero-media { border-radius: 22px; overflow: hidden; }
.svc-hero-media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; border-radius: 22px; box-shadow: 0 30px 70px rgba(36, 28, 18, 0.2); }

.svc-section { padding: 72px 0; }
.svc-section .section-header-center { margin-bottom: 44px; }

.svc-points { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 22px; }
.svc-point {
  padding: 28px 26px;
  border-radius: 20px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.72);
}
.svc-point h3 { font-family: var(--font-display); font-size: 1.55rem; font-weight: 400; line-height: 1.15; margin-bottom: 8px; }
.svc-point p { font-size: 0.95rem; line-height: 1.65; color: var(--text-muted); }

.svc-steps { list-style: none; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 18px; counter-reset: svc; }
.svc-step {
  counter-increment: svc;
  padding: 26px 22px;
  border-radius: 18px;
  background: #241c12;
  color: #f5efe0;
}
.svc-step::before {
  content: counter(svc, decimal-leading-zero);
  display: block;
  font-family: var(--font-heading);
  font-size: 0.72rem;
  font-weight: 700;
  letter-spacing: 0.18em;
  color: #e0bd6a;
  margin-bottom: 10px;
}
.svc-step h3 { font-family: var(--font-display); font-size: 1.45rem; font-weight: 400; margin-bottom: 6px; }
.svc-step p { font-size: 0.9rem; line-height: 1.6; color: rgba(245, 239, 224, 0.75); }

.svc-gallery { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 18px; }
.svc-gallery figure { margin: 0; }
.svc-gallery img { width: 100%; aspect-ratio: 4 / 5; object-fit: cover; display: block; border-radius: 18px; }
.svc-gallery figcaption { margin-top: 8px; font-size: 0.8rem; color: var(--text-muted); }

.svc-pano { margin-top: 0; }

.svc-card {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 24px;
  border-radius: 18px;
  border: 1px solid var(--border);
  background: rgba(255, 255, 255, 0.72);
  color: var(--text);
  text-decoration: none;
}
.svc-card strong { font-family: var(--font-display); font-size: 1.35rem; font-weight: 400; }
.svc-card span { font-size: 0.88rem; color: var(--text-muted); }

.svc-faq .faq-list { max-width: 820px; }

@media (max-width: 1024px) {
  .svc-hero-grid { grid-template-columns: 1fr; gap: 32px; }
  .svc-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .svc-points { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 640px) {
  .svc-hero { padding: 116px 0 24px; }
  .svc-steps,
  .svc-points,
  .svc-gallery { grid-template-columns: 1fr; }
  .svc-gallery img { aspect-ratio: 4 / 3; }
}
