/* ==========================================================================
   EDHN V2 — "Local Advantage"
   A performance system, not an editorial one. Bright, bold, data-forward,
   built to be scanned in seconds and to book meetings.
   One stylesheet on purpose: fewer render-blocking requests.
   ========================================================================== */

:root {
  /* Surfaces */
  --bg:          #F6F4F0;   /* warm light base */
  --card:        #FFFFFF;
  --deep:        #171310;   /* midnight band */
  --deep-2:      #241D18;

  /* Ink */
  --ink:         #191512;
  --ink-2:       #5C5147;
  --ink-on-deep: #F4F1E7;
  --ink-2-deep:  #A89A8E;

  /* ---- Gold. This is El Dorado County: the Gold Rush started here and
     "El Dorado" means the golden one. Gold is local heritage, not luxury polish.
     It stays out of editorial territory by being a SOLID FILL with near-black
     text, set in a bold sans, on a light page.
     Three tokens because one gold cannot be legible everywhere:
       --fill      strike gold, button and highlight fills (dark text on top)
       --accent    deep gold, the only one legible as text on light surfaces
       --accent-hi bright gold, for text and accents on the dark bands        */
  --fill:        #E0A419;
  --fill-hi:     #F0B838;
  --on-fill:     #191512;
  --accent:      #7F5D0E;
  --accent-hi:   #E8B33C;
  --accent-soft: #FBF0D8;
  --pos:         #17795E;

  --line:        #E4DFD7;
  /* Earth accents sampled from the owner's own textures. Same warm family gold sits in.
     --stone is DECORATIVE ONLY: 2.49:1 on parchment, so it must never carry body text. */
  --walnut:      #846B5B;
  --stone:       #A89A8E;
  --espresso:    #2B231F;
  --parchment:   #F4F1E7;
  --line-deep:   #38302A;

  --font: 'Jakarta', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --maxw: 1200px;
  --gutter: clamp(20px, 4.5vw, 48px);
  --r: 14px;
  --r-sm: 8px;

  --dur: 200ms;
  --ease: cubic-bezier(.22,.61,.36,1);
  --shadow: 0 1px 2px rgba(25,21,18,.05), 0 8px 24px rgba(25,21,18,.06);
  --shadow-lg: 0 2px 4px rgba(25,21,18,.06), 0 18px 48px rgba(25,21,18,.12);
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  margin: 0; background: var(--bg); color: var(--ink);
  font-family: var(--font); font-size: 17px; line-height: 1.6;
  font-weight: 400; -webkit-font-smoothing: antialiased; overflow-x: hidden;
}
h1,h2,h3,h4 { margin: 0; line-height: 1.08; letter-spacing: -.02em; font-weight: 800; }
p { margin: 0; }
img, video { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
ul { margin: 0; padding: 0; list-style: none; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }

.wrap { max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
section { padding-block: clamp(56px, 8vw, 104px); }
.skip-link { position: absolute; left: -9999px; }
.skip-link:focus { left: 16px; top: 16px; z-index: 999; background: var(--fill); color: var(--on-fill); padding: 12px 20px; border-radius: var(--r-sm); }

/* ---- Type utilities ---------------------------------------------------- */
.kicker { font-size: 13px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
/* Every dark surface, in one place. .final and .page-hero kept getting missed
   individually, which is how a 3:1 gold label shipped on the closing band. */
.deep .kicker, .band-deep .kicker, .final .kicker, .page-hero .kicker, .hero .kicker { color: var(--accent-hi); }
h2.big { font-size: clamp(2rem, 4.4vw, 3.15rem); margin-top: 14px; text-wrap: balance; }
.lead { font-size: clamp(1.05rem, 1.6vw, 1.2rem); color: var(--ink-2); margin-top: 18px; max-width: 62ch; }
.band-deep .lead, .deep .lead, .final .lead { color: var(--ink-2-deep); }
.center { text-align: center; margin-inline: auto; }
.center .lead { margin-inline: auto; }

/* ---- Buttons ----------------------------------------------------------- */
/* Gold fill, near-black label: ~8:1 contrast, and it reads like a gold bar
   rather than a luxury flourish. */
.btn { display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  background: var(--fill); color: var(--on-fill); font-weight: 800; font-size: 16px;
  padding: 16px 28px; border-radius: var(--r-sm); border: 0; cursor: pointer;
  transition: background var(--dur) var(--ease), transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
  box-shadow: 0 4px 14px rgba(224,164,25,.34); }
.btn:hover { background: var(--fill-hi); transform: translateY(-2px); box-shadow: 0 8px 24px rgba(224,164,25,.42); }
.btn--lg { font-size: 17px; padding: 19px 34px; }
.btn--ghost { background: transparent; color: var(--ink); border: 2px solid var(--line); box-shadow: none; }
.btn--ghost:hover { background: #fff; border-color: var(--ink); color: var(--ink); transform: translateY(-2px); box-shadow: var(--shadow); }
/* Ghost buttons on any dark surface. The hero counts: without .hero here the
   label rendered dark-on-dark and vanished. */
.band-deep .btn--ghost, .deep .btn--ghost, .hero .btn--ghost, .final .btn--ghost {
  color: var(--ink-on-deep); border-color: rgba(255,255,255,.34); }
.band-deep .btn--ghost:hover, .deep .btn--ghost:hover, .hero .btn--ghost:hover, .final .btn--ghost:hover {
  background: rgba(255,255,255,.1); border-color: #fff; color: #fff; }
.cta-row { display: flex; flex-wrap: wrap; gap: 14px; align-items: center; margin-top: 28px; }
/* Both spellings: .center as an ancestor, and .center on the row itself.
   Only the ancestor form existed, so every closing CTA was left-aligned. */
.center .cta-row, .cta-row.center { justify-content: center; }
.micro { font-size: 14px; color: var(--ink-2); margin-top: 14px; }
.band-deep .micro, .deep .micro, .final .micro { color: var(--ink-2-deep); }

/* ---- Header ------------------------------------------------------------ */
.hdr { position: sticky; top: 0; z-index: 60; background: rgba(246,244,240,.92);
  backdrop-filter: blur(10px); border-bottom: 1px solid var(--line); }
.hdr-in { max-width: var(--maxw); margin-inline: auto; padding: 12px var(--gutter);
  display: flex; align-items: center; justify-content: space-between; gap: 24px; }
.logo img { height: 34px; width: auto; }
.nav { display: flex; gap: 26px; }
.nav a { font-size: 15px; font-weight: 600; color: var(--ink-2); transition: color var(--dur) var(--ease); }
.nav a:hover { color: var(--accent); }
.hdr-right { display: flex; align-items: center; gap: 18px; }
.hdr-tel { font-size: 15px; font-weight: 700; color: var(--ink); }
.hdr-tel:hover { color: var(--accent); }
.burger { display: none; background: #fff; border: 2px solid var(--line); border-radius: var(--r-sm);
  padding: 10px 14px; font-weight: 700; font-size: 14px; cursor: pointer; color: var(--ink); }

/* ==========================================================================
   HERO — scale, tenure, local owner, and the ask.
   ========================================================================== */
.hero { position: relative; background: var(--deep); color: var(--ink-on-deep); overflow: hidden;
  padding-block: clamp(56px, 7vw, 96px); }
.hero-media { position: absolute; inset: 0; z-index: 0; }
.hero-media video, .hero-media img { width: 100%; height: 100%; object-fit: cover; }
.hero::after { content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(102deg, rgba(23, 19, 16,.97) 0%, rgba(23, 19, 16,.93) 34%, rgba(23, 19, 16,.72) 56%, rgba(23, 19, 16,.42) 100%); }
.hero-in { position: relative; z-index: 2; max-width: var(--maxw); margin-inline: auto; padding-inline: var(--gutter); }
.hero-col { max-width: 780px; }
/* 780 not 660: the headline runs to 87 characters and at 660 it broke to five
   lines / 271px of display type, which reads as a wall. 780 puts it on three
   lines with no reduction in font size. */
.hero h1 { font-size: clamp(1.95rem, 4.6vw, 3.2rem); color: #fff; }
/* Sized to the headline, not the other way round. At the old 3.9rem cap the
   87-character headline broke to five lines of display type on every desktop
   width and seven on a phone. Measured across ten viewports: this puts it on
   three lines everywhere down to tablet, and five on the narrowest phones. */
.hero h1 .hl { color: var(--accent-hi); }
.hero .lead { color: var(--ink-on-deep); font-size: clamp(1.05rem, 1.7vw, 1.24rem); max-width: 56ch; }
.hero .micro { color: var(--ink-2-deep); }

/* ---- Hero film framing --------------------------------------------------
   The film is 16:9 and the logo reveal spans nearly its full width, but the
   hero box is tall and narrow (the copy, stats and partner row stack), so
   object-fit:cover was cropping 46% of the width on a tablet and 81% on a
   phone. A visitor on mobile saw about a fifth of the logo.

   So while the reveal is playing we CONTAIN the film - the whole title card is
   visible at every size - and only switch to COVER once the copy is in. The
   switch is masked because the film itself hard-cuts to the aerial at the same
   moment. Letterbox is invisible because the reveal is on black and we paint
   the media box black underneath it.

   The scrim is the second half of the fix. It sits ABOVE the video at up to
   97% opacity to make the copy legible, which also dimmed the gold logo it was
   never meant to cover. It now fades in with the copy instead. */
.hero.awaiting .hero-media { background: #000; }
.hero.awaiting .hero-media video,
.hero.awaiting .hero-media img { object-fit: contain; }
.hero.awaiting::after { opacity: 0; }
.hero.revealed::after { opacity: 1; transition: opacity 700ms var(--ease); }
.hero.revealed .hero-media video,
.hero.revealed .hero-media img { object-fit: cover; }

/* ==========================================================================
   HERO REVEAL — the film opens with a ~6s gold logo reveal, so the copy has to
   wait for it and then enter.

   The gate is `html.js .hero.awaiting`, set by JS only once it has decided the
   film will actually play. Default state is VISIBLE, on purpose: no-JS, a
   blocked autoplay, reduced motion, save-data and every AI crawler that does
   not execute JS all get the headline in the raw HTML. Nothing load-bearing is
   ever hidden behind a timer.
   ========================================================================== */
.hero-col > *:not(.hero-media) { opacity: 1; transform: none; }

.hero.awaiting .hero-col > * {
  opacity: 0;
  transform: translateY(16px);
  /* No transition while waiting: entering is animated, hiding is instant. */
  transition: none;
}
.hero.revealed .hero-col > * {
  opacity: 1;
  transform: none;
  transition: opacity 820ms var(--ease), transform 820ms var(--ease);
}
/* Staggered cascade so it reads as a title sequence rather than a flash. */
.hero.revealed .kicker    { transition-delay:   0ms; }
.hero.revealed h1         { transition-delay:  90ms; }
.hero.revealed .lead      { transition-delay: 240ms; }
.hero.revealed .cta-row   { transition-delay: 380ms; }
.hero.revealed .micro     { transition-delay: 470ms; }
.hero.revealed .stats     { transition-delay: 560ms; }
.hero.revealed .partners  { transition-delay: 650ms; }

@media (prefers-reduced-motion: reduce) {
  /* Never hold copy back from someone who asked for less motion. */
  .hero.awaiting .hero-col > *,
  .hero.revealed .hero-col > * { opacity: 1; transform: none; transition: none; }
}

/* stat strip beneath the hero copy */
.stats { display: grid; grid-template-columns: repeat(4, auto); gap: clamp(20px, 4vw, 48px);
  margin-top: 40px; padding-top: 28px; border-top: 1px solid rgba(255,255,255,.16); justify-content: start; }
.stat b { display: block; font-size: clamp(1.5rem, 3vw, 2.1rem); font-weight: 800; color: #fff; letter-spacing: -.03em; line-height: 1; }
.stat span { display: block; font-size: 12.5px; color: var(--ink-2-deep); margin-top: 7px; font-weight: 500; line-height: 1.35; max-width: 17ch; }

/* ==========================================================================
   PILLARS — why owners choose us
   ========================================================================== */
.pillars { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-top: 46px; }
/* A three-up variant. This was an inline style on /services/print/, which beat
   every media query below it and left the page scrolling sideways at 375px. */
.pillars--3 { grid-template-columns: repeat(3, 1fr); }
.pill { background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 30px 26px; box-shadow: var(--shadow);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease); }
.pill:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
.pill-ic { width: 46px; height: 46px; border-radius: 12px; background: var(--accent-soft);
  display: grid; place-items: center; color: var(--accent); margin-bottom: 18px; }
.pill-ic svg { width: 24px; height: 24px; }
.pill h3 { font-size: 1.12rem; font-weight: 800; }
.pill p { font-size: 15px; color: var(--ink-2); margin-top: 10px; }

/* ==========================================================================
   ADVANTAGE — the enterprise-leverage section (dark band)
   ========================================================================== */
.band-deep { background: var(--deep); color: var(--ink-on-deep); }
.band-deep h2 { color: #fff; }
.adv-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 5vw, 68px); align-items: center; }
.adv-list { margin-top: 30px; display: grid; gap: 22px; }
.adv-item { display: grid; grid-template-columns: 40px 1fr; gap: 16px; align-items: start; }
.adv-num { width: 40px; height: 40px; border-radius: 10px; background: rgba(224,164,25,.18);
  color: var(--accent-hi); display: grid; place-items: center; font-weight: 800; font-size: 15px; }
.adv-item h3 { font-size: 1.05rem; color: #fff; font-weight: 700; }
.adv-item p { font-size: 15px; color: var(--ink-2-deep); margin-top: 7px; }
.adv-card { background: var(--deep-2); border: 1px solid var(--line-deep); border-radius: var(--r); padding: 34px 30px; }
.adv-card .big-n { font-size: clamp(2.6rem, 6vw, 3.8rem); font-weight: 800; color: var(--accent-hi); letter-spacing: -.03em; line-height: 1; }
.adv-card .big-l { color: #fff; font-weight: 700; margin-top: 10px; font-size: 1.05rem; }
.adv-card p { color: var(--ink-2-deep); font-size: 15px; margin-top: 12px; }
.adv-split { margin-top: 26px; padding-top: 24px; border-top: 1px solid var(--line-deep); display: grid; gap: 16px; }
.adv-split div { display: flex; gap: 12px; align-items: flex-start; font-size: 15px; color: var(--ink-on-deep); }
.adv-split svg { width: 20px; height: 20px; color: var(--accent-hi); flex: none; margin-top: 2px; }

/* ---- #advantage stat card: two figures, not one -------------------------
   The section argues that print and digital run together, so the card shows
   both. The children set their own size and colour, so the parent .big-n
   clamp never reaches them and every single-figure .big-n elsewhere on the
   site is untouched. Prefixed adv-fig- to stay clear of .ledger .fig below. */
.adv-card .adv-fig { display: block; }
.adv-card .adv-fig + .adv-fig { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line-deep); }
.adv-card .adv-fig-n { display: block; font-size: clamp(2rem, 4vw, 2.7rem); font-weight: 800; line-height: 1;
  letter-spacing: -.03em; color: var(--accent-hi); font-variant-numeric: tabular-nums; }
.adv-card .adv-fig-l { display: block; margin-top: 7px; font-size: 13px; font-weight: 700; line-height: 1.35;
  letter-spacing: .05em; text-transform: uppercase; color: var(--ink-2-deep); }

/* A fourth numbered item makes the left column taller than the card, and
   .adv-grid is align-items:center, which would float the card in dead space.
   .adv-grid is reused by the case splits further down, so scope this. */
#advantage .adv-grid { align-items: start; }
#advantage .adv-card { margin-top: 6px; }
#advantage .adv-card .big-l { margin-top: 20px; }
/* Three .adv-card stats in a row. .adv-grid is a two-column split, so a
   three-card set needs its own track. */
.statrow { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: 44px; }
@media (max-width: 880px) { .statrow { grid-template-columns: 1fr; } }

/* ==========================================================================
   CHANNELS
   ========================================================================== */
.chan { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; margin-top: 46px; }
.ch { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden;
  display: flex; flex-direction: column; box-shadow: var(--shadow);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease); }
.ch:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); }
/* Sources are 4:3. A fixed 210px box cropped them by a different amount at every
   card width - 48% shown on a wide card, 84% on a narrow one - so the same photo
   looked differently framed depending on the viewport. An aspect ratio keeps the
   crop constant everywhere, and 16/10 against a 4:3 source shows 83% of the frame
   instead of roughly half. */
.ch img { width: 100%; aspect-ratio: 16 / 10; height: auto; object-fit: cover; }
.ch-b { padding: 26px 26px 28px; display: flex; flex-direction: column; flex: 1; }
.ch-tag { font-size: 12px; font-weight: 700; letter-spacing: .07em; text-transform: uppercase; color: var(--accent); }
.ch h3 { font-size: 1.3rem; margin-top: 8px; }
.ch p { color: var(--ink-2); font-size: 15.5px; margin-top: 12px; flex: 1; }
.ch .more { margin-top: 18px; font-weight: 700; font-size: 15px; color: var(--accent); }

/* ==========================================================================
   PROOF
   ========================================================================== */
.proof-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 20px; margin-top: 44px; }
/* The card now leads with the campaign creative, so the padding moves off the card
   and onto the body: the image runs flush to the border on three sides. */
.pcard { background: var(--card); border: 1px solid var(--line); border-radius: var(--r); padding: 0;
  box-shadow: var(--shadow); display: flex; flex-direction: column; overflow: hidden; }
.pcard-b { padding: 24px 26px 26px; display: flex; flex-direction: column; flex: 1; }
.pshot { display: block; position: relative; background: var(--ink); line-height: 0; }
/* contain, not cover. These are designed compositions - the magazine, the site, and
   the dashboard are placed deliberately - and the set is not one ratio (Viscuso's is
   16:9, the rest are 3:2). Cropping to a common box clipped ~9% off each side, which
   on Viscuso's is precisely where the listings dashboard sits. Letterboxing against
   the card's own dark ground costs nothing and never cuts the proof off. */
.pshot img { width: 100%; aspect-ratio: 3 / 2; height: auto; object-fit: contain;
  transition: transform 620ms var(--ease); }
.pshot-tag { position: absolute; left: 12px; bottom: 12px; z-index: 1;
  font-size: 10.5px; font-weight: 800; letter-spacing: .1em; text-transform: uppercase;
  color: #fff; background: rgba(23, 19, 16,.74); border: 1px solid rgba(255,255,255,.18);
  padding: 6px 10px; border-radius: 999px; line-height: 1; backdrop-filter: blur(6px); }
a.pshot::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(23, 19, 16,.34), transparent 46%); }
a.pshot:hover img, a.pshot:focus-visible img { transform: scale(1.035); }
@media (prefers-reduced-motion: reduce) { .pshot img { transition: none; }
  a.pshot:hover img, a.pshot:focus-visible img { transform: none; } }
.pquote { font-size: 16.5px; font-weight: 600; color: var(--ink); line-height: 1.5; flex: 1; }
.pmeta { margin-top: 20px; padding-top: 18px; border-top: 1px solid var(--line); }
.pmeta b { display: block; font-size: 15px; font-weight: 700; }
.pmeta span { display: block; font-size: 13.5px; color: var(--ink-2); margin-top: 3px; }
.pnums { margin-top: 14px; display: flex; flex-wrap: wrap; gap: 8px; }
.chip { background: var(--accent-soft); color: var(--accent); font-size: 12.5px; font-weight: 700;
  padding: 6px 11px; border-radius: 999px; }
.gsrc { display: inline-flex; align-items: center; gap: 6px; margin-top: 14px; font-size: 12.5px; color: var(--ink-2); font-weight: 600; }
.gsrc svg { width: 14px; height: 14px; }

/* ==========================================================================
   STEPS
   ========================================================================== */
.steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin-top: 46px; }
.step { position: relative; padding-top: 28px; }
.step::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: var(--fill); border-radius: 2px; opacity: .3; }
.step:first-child::before { opacity: 1; }
.step b { font-size: 13px; font-weight: 800; color: var(--accent); letter-spacing: .06em; text-transform: uppercase; }
.step h3 { font-size: 1.2rem; margin-top: 10px; }
.step p { color: var(--ink-2); font-size: 15.5px; margin-top: 10px; }

/* ==========================================================================
   PRICING
   ========================================================================== */
.tiers { display: grid; grid-template-columns: repeat(3, 1fr); gap: 22px; margin-top: 46px; align-items: stretch; }
.tier { background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 32px 28px; display: flex; flex-direction: column; box-shadow: var(--shadow); }
.tier--best { background: var(--deep); border-color: var(--deep); color: var(--ink-on-deep);
  box-shadow: var(--shadow-lg); position: relative; }
.tier-flag { position: absolute; top: -13px; left: 28px; background: var(--fill); color: var(--on-fill);
  font-size: 12px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; padding: 6px 14px; border-radius: 999px; }
.tier-name { font-size: 13px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; color: var(--accent); }
.tier--best .tier-name { color: var(--accent-hi); }
.tier-amt { font-size: clamp(1.9rem, 3.4vw, 2.5rem); font-weight: 800; letter-spacing: -.03em; margin-top: 14px; line-height: 1.05; }
.tier--best .tier-amt { color: #fff; }
.tier-amt small { font-size: 15px; font-weight: 600; color: var(--ink-2); letter-spacing: 0; }
.tier--best .tier-amt small { color: var(--ink-2-deep); }
.tier p { font-size: 15px; color: var(--ink-2); margin-top: 14px; flex: 1; }
.tier--best p { color: var(--ink-2-deep); }
.tier .btn { margin-top: 24px; width: 100%; }

/* ==========================================================================
   SEATS / FAQ / FINAL
   ========================================================================== */
.seat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: clamp(32px, 5vw, 64px); align-items: start; }
.seats { border-top: 1px solid var(--line); margin-top: 26px; }
.seats li { display: flex; justify-content: space-between; align-items: center; gap: 16px;
  padding: 15px 0; border-bottom: 1px solid var(--line); }
.seats .c { font-weight: 600; font-size: 15.5px; }
.tag { font-size: 12px; font-weight: 800; letter-spacing: .05em; text-transform: uppercase; padding: 5px 11px; border-radius: 999px; }
.tag--taken { background: #E7E3DB; color: #575F6B; }
.tag--open { background: #E4F3EC; color: var(--pos); }

.faq { max-width: 820px; margin: 42px auto 0; }
.faq details { background: var(--card); border: 1px solid var(--line); border-radius: var(--r-sm); margin-bottom: 12px; }
.faq summary { cursor: pointer; list-style: none; padding: 20px 24px; font-weight: 700; font-size: 17px;
  display: flex; justify-content: space-between; align-items: center; gap: 18px; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--accent); font-size: 24px; font-weight: 700; flex: none; line-height: 1;
  transition: transform var(--dur) var(--ease); }
.faq details[open] summary::after { transform: rotate(45deg); }
.faq .a { padding: 0 24px 22px; color: var(--ink-2); font-size: 16px; }

.final { background: var(--deep); color: var(--ink-on-deep); text-align: center; }
.final h2 { color: #fff; font-size: clamp(2.1rem, 4.8vw, 3.3rem); max-width: 20ch; margin-inline: auto; text-wrap: balance; }

/* ---- Footer ------------------------------------------------------------ */
.ftr { background: var(--deep-2); color: var(--ink-2-deep); padding: 60px 0 28px; }
.ftr-grid { display: grid; grid-template-columns: 1.6fr 1fr 1fr; gap: 40px; }
.ftr img { height: 40px; width: auto; margin-bottom: 18px; }
.ftr h4 { font-size: 12.5px; font-weight: 800; letter-spacing: .08em; text-transform: uppercase; color: var(--accent-hi); margin-bottom: 14px; }
.ftr a, .ftr p { font-size: 14.5px; color: var(--ink-2-deep); display: block; margin-bottom: 8px; }
.ftr a:hover { color: #fff; }
.ftr-btm { margin-top: 44px; padding-top: 22px; border-top: 1px solid var(--line-deep);
  display: flex; flex-wrap: wrap; justify-content: space-between; gap: 12px; font-size: 13px; }
.ftr-legal { font-size: 12px; opacity: .75; margin-top: 16px; max-width: 82ch; line-height: 1.5; }

/* ---- Mobile sticky bar -------------------------------------------------- */
.mbar { display: none; position: fixed; left: 0; right: 0; bottom: 0; z-index: 70;
  box-shadow: 0 -4px 16px rgba(0,0,0,.14); }
.mbar a { flex: 1; text-align: center; padding: 16px 0; font-weight: 800; font-size: 15px; }
.mbar .b1 { background: var(--fill); color: var(--on-fill); }
.mbar .b2 { background: #fff; color: var(--ink); border-top: 1px solid var(--line); }

/* ---- Reveal ------------------------------------------------------------- */
.rv { opacity: 0; transform: translateY(16px); transition: opacity 420ms var(--ease), transform 420ms var(--ease); }
.rv.in { opacity: 1; transform: none; }
html:not(.js) .rv { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: .01ms !important; transition-duration: .01ms !important; scroll-behavior: auto !important; }
  .rv { opacity: 1; transform: none; }
}

/* ==========================================================================
   RESPONSIVE
   ========================================================================== */
@media (max-width: 1040px) {
  .pillars, .pillars--3 { grid-template-columns: repeat(2, 1fr); }
  .adv-grid, .seat-grid { grid-template-columns: 1fr; }
  .proof-grid, .steps, .tiers { grid-template-columns: 1fr; }
  .tier--best { order: -1; }
  .ftr-grid { grid-template-columns: 1fr 1fr; }
}
/* 861-1240px: six nav links plus the phone number and the button don't fit, so the
   nav wrapped and pushed the header from 58px to 107px tall. The burger hasn't
   kicked in yet at these widths, so tighten rather than collapse. */
@media (min-width: 861px) and (max-width: 1240px) {
  .hdr-in { gap: 14px; }
  .nav { gap: 16px; flex-wrap: nowrap; }
  .nav a { font-size: 14px; white-space: nowrap; }
  .hdr-tel { display: none; }
  .hdr-right .btn { padding: 13px 18px; font-size: 14px; white-space: nowrap; }
}
/* ---- Hero film on phones and small tablets -------------------------------
   The hero is ~1058px tall and 375px wide on a phone. A 16:9 film cannot live in
   that box as a background: contained it became a 375x211 strip stranded in 423px
   of black top and bottom, and covered it filled the height while throwing away
   80% of the width.

   So on small screens the film stops being a background and becomes a band. The
   media box gets its own 16:9 ratio at the top of the hero, the copy sits below it
   on the solid dark, and the picture is always exactly the right size - no
   letterbox, no crop, and no jump when the reveal ends. The scrim is switched off
   because there is no longer any copy sitting on top of the film. */
@media (max-width: 1024px) {
  .hero { padding-top: 0; overflow: visible; }
  .hero-media { position: relative; inset: auto; width: 100%; aspect-ratio: 16 / 9; }
  .hero-media video, .hero-media img { height: 100%; }
  /* The box is already 16:9, so cover and contain are identical here. Pinning it to
     cover keeps the reveal-to-footage handoff from changing anything visually. */
  .hero.awaiting .hero-media video, .hero.awaiting .hero-media img,
  .hero.revealed .hero-media video, .hero.revealed .hero-media img { object-fit: cover; }
  .hero.awaiting .hero-media { background: transparent; }
  .hero::after, .hero.awaiting::after, .hero.revealed::after { display: none; }
  .hero-in { padding-top: 32px; }
}

@media (max-width: 860px) {
  .nav { display: none; position: absolute; top: 100%; left: 0; right: 0; background: var(--card);
    flex-direction: column; padding: 20px var(--gutter); gap: 18px; border-bottom: 1px solid var(--line); }
  .nav.open { display: flex; }
  .burger { display: block; }
  .hdr-tel, .hdr-right .btn { display: none; }
  .mbar { display: flex; }
  body { padding-bottom: 54px; }
  .chan { grid-template-columns: 1fr; }
  .stats { grid-template-columns: repeat(2, 1fr); gap: 26px; }
  .stat span { max-width: none; }
}
@media (max-width: 560px) {
  .ftr-grid { grid-template-columns: 1fr; }
  .pillars, .pillars--3 { grid-template-columns: 1fr; }
}

/* ==========================================================================
   BOOKING PAGE: scheduler, two-step form, thank-you
   ========================================================================== */
.page-hero { background: var(--deep); color: var(--ink-on-deep); padding-block: clamp(48px, 6vw, 76px); }
.page-hero h1 { color: #fff; font-size: clamp(2.1rem, 4.4vw, 3.1rem); max-width: 22ch; }
.page-hero .lead { color: var(--ink-2-deep); }
.page-hero .kicker { color: var(--accent-hi); }
.crumb { font-size: 13px; color: var(--ink-2-deep); margin-bottom: 16px; }
.crumb a { color: var(--ink-2-deep); }
.crumb a:hover { color: var(--fill); }

.book-grid { display: grid; grid-template-columns: 1.35fr 1fr; gap: clamp(28px, 4vw, 56px); align-items: start; }
.cal-card { background: #fff; border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; box-shadow: var(--shadow); }
.cal-head { padding: 22px 26px; border-bottom: 1px solid var(--line); }
.cal-head h2 { font-size: 1.3rem; }
.cal-head p { font-size: 14.5px; color: var(--ink-2); margin-top: 6px; }
#cal-mount { min-height: 700px; }
.cal-skel { min-height: 700px; display: grid; place-items: center; color: var(--ink-2); font-size: 15px; padding: 30px; text-align: center; }
.cal-fallback { padding: 40px 26px; text-align: center; color: var(--ink-2); }
.cal-fallback a { color: var(--accent); font-weight: 700; }

.aside-card { background: #fff; border: 1px solid var(--line); border-radius: var(--r); padding: 26px; box-shadow: var(--shadow); }
.aside-card + .aside-card { margin-top: 20px; }
.aside-card h3 { font-size: 1.12rem; }
.aside-card ul { margin-top: 14px; display: grid; gap: 12px; }
.aside-card li { display: grid; grid-template-columns: 22px 1fr; gap: 11px; font-size: 15px; color: var(--ink-2); align-items: start; }
.aside-card li svg { width: 20px; height: 20px; color: var(--accent); margin-top: 2px; }
.owner-mini { display: flex; gap: 14px; align-items: center; }
/* Square headshot: centre it. The old 72% offset existed only to rescue a face
   out of a wide two-person photo. */
.owner-mini img { width: 62px; height: 62px; border-radius: 50%; object-fit: cover;
  object-position: center; flex: none; border: 2px solid var(--accent-soft); }
.owner-mini b { display: block; font-size: 15px; }
.owner-mini span { font-size: 13.5px; color: var(--ink-2); }
.quote-mini { font-size: 15.5px; color: var(--ink); font-weight: 600; line-height: 1.5; }
.quote-mini + .owner-mini { margin-top: 18px; padding-top: 18px; border-top: 1px solid var(--line); }

/* ---- Form -------------------------------------------------------------- */
.form-card { background: #fff; border: 1px solid var(--line); border-radius: var(--r); padding: clamp(24px, 3vw, 34px); box-shadow: var(--shadow); }
.fbar { height: 5px; background: var(--line); border-radius: 3px; overflow: hidden; margin-bottom: 26px; }
.fbar span { display: block; height: 100%; width: 50%; background: var(--fill); transition: width var(--dur) var(--ease); }
.field { margin-bottom: 18px; }
.field label { display: block; font-size: 14px; font-weight: 700; margin-bottom: 7px; }
.field label .opt { font-weight: 500; color: var(--ink-2); }
.field input, .field select, .field textarea {
  width: 100%; font-family: var(--font); font-size: 16px; color: var(--ink);
  padding: 13px 15px; border: 2px solid var(--line); border-radius: var(--r-sm);
  background: #fff; transition: border-color var(--dur) var(--ease); }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--fill); }
.field textarea { min-height: 96px; resize: vertical; }
.field .err { display: none; color: #B3261E; font-size: 13.5px; margin-top: 6px; font-weight: 600; }
.field.bad .err { display: block; }
.field.bad input, .field.bad select, .field.bad textarea { border-color: #B3261E; }
.checks { display: grid; gap: 10px; }
.check { display: grid; grid-template-columns: 22px 1fr; gap: 11px; align-items: start; font-size: 14.5px; color: var(--ink-2); }
.check input { width: 20px; height: 20px; margin: 2px 0 0; accent-color: var(--fill); }
.fnav { display: flex; gap: 12px; align-items: center; margin-top: 24px; flex-wrap: wrap; }
.fnav .btn { flex: none; }
.link-btn { background: none; border: 0; font-family: var(--font); font-size: 15px; font-weight: 700;
  color: var(--ink-2); cursor: pointer; padding: 8px 4px; }
.link-btn:hover { color: var(--ink); }
/* Starts hidden via the [hidden] attribute. V1's version rendered permanently. */
.form-err { background: #FDECEA; border: 1px solid #F3C2BD; color: #8C1D18; padding: 14px 16px;
  border-radius: var(--r-sm); font-size: 15px; margin-top: 18px; }
.form-err a { color: #8C1D18; font-weight: 800; }

/* ---- Thank you ---------------------------------------------------------- */
.ty { min-height: 62vh; display: grid; place-items: center; text-align: center; }
.ty-ic { width: 76px; height: 76px; border-radius: 50%; background: var(--accent-soft);
  color: var(--accent); display: grid; place-items: center; margin: 0 auto 24px; }
.ty-ic svg { width: 38px; height: 38px; }
.ty h1 { font-size: clamp(2rem, 4.4vw, 2.9rem); }
.ty-next { display: grid; grid-template-columns: repeat(3, 1fr); gap: 18px; margin-top: 44px; text-align: left; }
.ty-next div { background: #fff; border: 1px solid var(--line); border-radius: var(--r); padding: 22px; }
.ty-next b { display: block; font-size: 12.5px; font-weight: 800; letter-spacing: .06em; text-transform: uppercase; color: var(--accent); }
.ty-next p { font-size: 15px; color: var(--ink-2); margin-top: 8px; }

@media (max-width: 1000px) {
  .book-grid { grid-template-columns: 1fr; }
  .ty-next { grid-template-columns: 1fr; }
}

/* ==========================================================================
   PROOF PAGE (/proof/) — four components the vocabulary above did not cover.
   Purely additive: nothing before this block is modified or overridden.
     1) .ledger*   the opening six-row table (scrolls sideways on small screens)
     2) .case*     the six case splits (layout itself is reused .adv-grid)
     3) .note      the honest-figures disclosure callout
     4) .wall*     the partner logo grid
   Gold discipline is the same as everywhere else: --fill only ever as a solid
   rule or fill, --accent for gold TEXT on light, --accent-hi for gold text on
   the dark bands. No gold text is ever set in --fill.
   ========================================================================== */

/* ---- 1) The Ledger ------------------------------------------------------ */
/* The table has four columns of real content, so below ~780px it scrolls
   inside its own container rather than crushing the figures column. */
.ledger-wrap { margin-top: 44px; overflow-x: auto; -webkit-overflow-scrolling: touch;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r); box-shadow: var(--shadow); }
.ledger { width: 100%; min-width: 720px; border-collapse: collapse; font-size: 15px; }
.ledger-cap { caption-side: top; text-align: left; padding: 20px 22px 0;
  font-size: 13.5px; line-height: 1.55; color: var(--ink-2); }
.ledger th { text-align: left; padding: 16px 22px; background: var(--bg);
  border-bottom: 2px solid var(--line); font-size: 11.5px; font-weight: 800;
  letter-spacing: .08em; text-transform: uppercase; color: var(--ink-2); white-space: nowrap; }
.ledger td { padding: 17px 22px; border-bottom: 1px solid var(--line); vertical-align: top; color: var(--ink-2); }
.ledger tbody tr:last-child td { border-bottom: 0; }
.ledger tbody tr:hover { background: var(--accent-soft); }
.ledger .biz a { font-weight: 800; color: var(--ink); border-bottom: 2px solid var(--fill); }
.ledger .biz a:hover { color: var(--accent); }
.ledger .fig { color: var(--ink); font-weight: 700; white-space: nowrap; }
.ledger .fig span { display: block; margin-top: 5px; font-weight: 600; font-size: 14px; color: var(--ink-2); }
.ledger-hint { display: none; font-size: 13px; color: var(--ink-2); margin-top: 12px; }
@media (max-width: 780px) { .ledger-hint { display: block; } }

/* ---- 2) Case splits ----------------------------------------------------- */
/* Layout is .adv-grid (already responsive). These rules only handle the
   heading scale, the figure pair, and the image frame. */
.case h2 { font-size: clamp(1.55rem, 2.9vw, 2.15rem); margin-top: 14px; text-wrap: balance; }
.case .lead { margin-top: 16px; }
.case-nums { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 20px 28px; margin-top: 28px; padding-top: 24px; border-top: 1px solid var(--line); }
.case-nums b { display: block; font-size: clamp(1.7rem, 3.4vw, 2.3rem); font-weight: 800;
  letter-spacing: -.03em; line-height: 1; color: var(--ink); }
.case-nums span { display: block; margin-top: 9px; font-size: 13px; font-weight: 600;
  line-height: 1.35; color: var(--ink-2); }
.case-chan { margin-top: 20px; font-size: 11.5px; font-weight: 800; letter-spacing: .08em;
  text-transform: uppercase; color: var(--accent); }
.case-media img { width: 100%; height: auto; border-radius: var(--r);
  border: 1px solid var(--line); box-shadow: var(--shadow-lg); }
/* Alternate which side the artwork sits on, but only once the split is really
   two columns. Stacked, the text must always come first. */
@media (min-width: 1041px) { .case--rev .case-media { order: -1; } }
@media (max-width: 420px) { .case-nums { grid-template-columns: 1fr; } }

/* ---- 3) Honest-figures note --------------------------------------------- */
.note { background: var(--card); border: 1px solid var(--line); border-left: 5px solid var(--fill);
  border-radius: var(--r-sm); padding: 22px 26px; margin: 36px auto 0; max-width: 84ch; }
.note b { display: block; margin-bottom: 9px; font-size: 12px; font-weight: 800;
  letter-spacing: .08em; text-transform: uppercase; color: var(--accent); }
.note p { font-size: 15px; line-height: 1.65; color: var(--ink-2); }

/* ---- 4) Partner wall ---------------------------------------------------- */
/* Every logo gets an identical box so the grid reads as a wall, not a jumble.
   object-fit keeps each mark at its own aspect ratio inside that box. */
.wall { display: grid; grid-template-columns: repeat(auto-fill, minmax(170px, 1fr));
  gap: 16px; margin-top: 46px; }
.wchip { display: flex; flex-direction: column; text-align: center;
  background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 22px 16px 18px; box-shadow: var(--shadow); }
.wchip img { width: 100%; height: 56px; object-fit: contain; margin-bottom: 15px; }
.wname { font-size: 13.5px; font-weight: 700; line-height: 1.3; color: var(--ink); }
.wcat { font-size: 12px; line-height: 1.35; color: var(--ink-2); margin-top: 6px; }
a.wchip { transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease); }
a.wchip .wcat { color: var(--accent); font-weight: 700; }
a.wchip:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); border-color: var(--fill); }
@media (max-width: 560px) {
  .wall { grid-template-columns: repeat(2, 1fr); gap: 12px; }
  .wchip { padding: 18px 12px 14px; }
}

/* ==========================================================================
   SERVICE PAGE IMAGERY  (added for /services/*)
   The split sections on the service pages pair a column of copy with a
   photograph. Nothing above styles a standalone image: .ch img is locked to
   the 210px channel tile and .owner-mini img is a 62px avatar. So this is the
   one addition, and it only borrows what the cards already use, a hairline,
   the shared radius, and the shared shadow. On the dark bands the hairline
   swaps to the dark line token so the edge does not glow.
   ========================================================================== */
.shot { width: 100%; height: auto; border-radius: var(--r);
  border: 1px solid var(--line); box-shadow: var(--shadow); }
.band-deep .shot, .deep .shot, .final .shot { border-color: var(--line-deep); }

/* ==========================================================================
   SEATS ON A DARK BAND — added for /services/print/
   .seats draws its rules with --line, a light hairline meant for the warm
   base. On a .band-deep surface seven of those rules read as bright stripes,
   so the list gets the dark-surface line token instead. Additive only:
   the original .seats rules are untouched and still govern light sections.
   ========================================================================== */
.band-deep .seats, .band-deep .seats li { border-color: var(--line-deep); }

/* ==========================================================================
   DARK-SURFACE GAPS ON .page-hero — added for /services/websites/
   .page-hero is a dark surface, but two rules far above list their dark
   surfaces explicitly (.band-deep, .deep, .hero, .final) and .page-hero is in
   neither list. /book/ never hit this because its hero carries no ghost
   button and no .micro line. Any interior page with a secondary hero CTA drew
   a dark-on-dark, invisible label, and a hero .micro line fell back to the
   light-surface ink at roughly 2:1 on midnight. Both get the same treatment
   the other dark surfaces already get, declared later in the cascade so they
   win without editing either original rule.
   ========================================================================== */
.page-hero .btn--ghost { color: var(--ink-on-deep); border-color: rgba(255,255,255,.34); }
.page-hero .btn--ghost:hover { background: rgba(255,255,255,.1); border-color: #fff; color: #fff; }
.page-hero .micro { color: var(--ink-2-deep); }

/* ==========================================================================
   WIDE CROP FOR .shot — added for /services/websites/
   Extends the .shot image treatment defined above rather than duplicating it.
   The library photography is 4:3, so a .shot running the full 1200px content
   width would stand ~900px tall. .shot--wide crops it to a banner instead.
   ========================================================================== */
.shot--wide { aspect-ratio: 16 / 7; object-fit: cover; }
@media (max-width: 640px) { .shot--wide { aspect-ratio: 16 / 10; } }

/* ==========================================================================
   LEGAL PROSE + ABOUT
   ========================================================================== */
.legal { max-width: 760px; margin-inline: auto; }
.legal h2 { font-size: 1.35rem; margin-top: 38px; }
.legal p, .legal li { color: var(--ink-2); font-size: 16px; margin-top: 14px; }
.legal ul { margin-top: 14px; padding-left: 20px; list-style: disc; }
.legal li { margin-top: 9px; }
.legal a { color: var(--accent); font-weight: 700; }
.legal .updated { font-size: 14px; color: var(--ink-2); margin-top: 10px; }
.legal .fineprint { font-size: 13px; color: var(--ink-2); opacity: .8; margin-top: 32px; }

.team { display: grid; grid-template-columns: repeat(4, 1fr); gap: 20px; margin-top: 44px; }
.tmember { background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 22px; text-align: center; box-shadow: var(--shadow); }
.tmember img { width: 92px; height: 92px; border-radius: 50%; object-fit: cover; margin: 0 auto 14px; }
.tmember b { display: block; font-size: 15.5px; font-weight: 800; }
.tmember span { display: block; font-size: 13px; color: var(--accent); font-weight: 700;
  text-transform: uppercase; letter-spacing: .06em; margin-top: 5px; }
@media (max-width: 900px) { .team { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .team { grid-template-columns: 1fr; } }

/* ==========================================================================
   SIGNATURE TOUCHES
   Premium here means restraint plus precision, not ornament. Five small things:
   a gold sheen across the hero highlight, counting stats, a scroll hairline,
   refined card edges, and a subtle gold grain on the dark bands.
   Every one degrades to a calm static state under prefers-reduced-motion.
   ========================================================================== */

/* 1. Gold sheen. Runs once, 2.4s, then rests as solid gold. Gold Country, lit. */
.hero h1 .hl {
  background-image: linear-gradient(100deg,
    var(--accent-hi) 0%, var(--accent-hi) 42%, #FFF2CF 50%, var(--accent-hi) 58%, var(--accent-hi) 100%);
  background-size: 260% 100%;
  background-position: 130% 0;
  -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: transparent;
  animation: sheen 2400ms var(--ease) 500ms 1 forwards;
}
@keyframes sheen { to { background-position: -30% 0; } }

/* 2. Counting stats. Tabular figures so the width never jumps mid-count. */
.stat b, .big-n { font-variant-numeric: tabular-nums; }

/* 3. Scroll hairline. A thin gold rule that tracks progress. */
.progress { position: fixed; top: 0; left: 0; height: 3px; width: 100%; z-index: 90;
  transform: scaleX(0); transform-origin: 0 50%; pointer-events: none;
  background: linear-gradient(90deg, var(--fill), var(--fill-hi));
  box-shadow: 0 0 12px rgba(224,164,25,.55); }

/* 4. Refined edges. Cards pick up a gold hairline on hover instead of a shadow alone. */
.pill, .ch, .pcard, .tier, .aside-card, .tmember { border-color: var(--line); }
.pill:hover, .ch:hover, .tmember:hover { border-color: rgba(224,164,25,.55); }
.tier:not(.tier--best):hover { border-color: rgba(224,164,25,.55); transform: translateY(-3px);
  box-shadow: var(--shadow-lg); transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease); }

/* 5. Gold grain. A barely-there wash so the dark bands read as depth, not flat black. */
.hero::before, .band-deep::before, .final::before {
  content: ""; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(1100px 460px at 12% -10%, rgba(224,164,25,.10), transparent 62%),
    radial-gradient(900px 420px at 88% 108%, rgba(224,164,25,.07), transparent 60%);
}
.band-deep, .final { position: relative; }
.band-deep > *, .final > * { position: relative; z-index: 1; }

/* ==========================================================================
   DISCOVERY MODAL — the 15 minute booking invitation
   ========================================================================== */
.modal { position: fixed; inset: 0; z-index: 200; display: none;
  align-items: center; justify-content: center; padding: 20px; }
.modal.open { display: flex; }
.modal-bd { position: absolute; inset: 0; background: rgba(8,12,18,.72);
  backdrop-filter: blur(6px); animation: fadeIn 260ms var(--ease) both; }
.modal-card { position: relative; width: 100%; max-width: 560px; max-height: 92vh; overflow: auto;
  background: var(--card); border-radius: 18px; box-shadow: 0 30px 90px rgba(0,0,0,.45);
  animation: popIn 320ms var(--ease) both; }
.modal-card::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px;
  border-radius: 18px 18px 0 0; background: linear-gradient(90deg, var(--fill), var(--fill-hi), var(--fill)); }
.modal-head { padding: 34px 34px 22px; text-align: center; }
.modal-head .kicker { color: var(--accent); }
.modal-head h2 { font-size: clamp(1.5rem, 3.4vw, 2rem); margin-top: 10px; }
.modal-head p { color: var(--ink-2); font-size: 15.5px; margin-top: 12px; }
.modal-body { padding: 0 18px 18px; }
.modal-body iframe { width: 100%; min-height: 620px; border: 0; border-radius: 12px; display: block; }
.modal-foot { padding: 0 34px 26px; text-align: center; }
.modal-foot a { color: var(--accent); font-weight: 700; }
.modal-x { position: absolute; top: 12px; right: 12px; z-index: 3;
  width: 40px; height: 40px; border-radius: 50%; border: 0; cursor: pointer;
  background: rgba(25,21,18,.06); color: var(--ink); font-size: 22px; line-height: 1;
  display: grid; place-items: center; transition: background var(--dur) var(--ease); }
.modal-x:hover { background: rgba(25,21,18,.14); }
.modal-later { display: block; margin: 14px auto 0; background: none; border: 0; cursor: pointer;
  font-family: var(--font); font-size: 14px; color: var(--ink-2); text-decoration: underline; }
@keyframes fadeIn { from { opacity: 0 } to { opacity: 1 } }
@keyframes popIn { from { opacity: 0; transform: translateY(18px) scale(.97) } to { opacity: 1; transform: none } }
body.modal-open { overflow: hidden; }

@media (prefers-reduced-motion: reduce) {
  .hero h1 .hl { animation: none; background: none; -webkit-text-fill-color: var(--accent-hi); color: var(--accent-hi); }
  .modal-bd, .modal-card { animation: none; }
  .progress { display: none; }
}
@media (max-width: 560px) {
  .modal-head { padding: 30px 22px 18px; }
  .modal-foot { padding: 0 22px 22px; }
  .modal-body iframe { min-height: 560px; }
}

/* ==========================================================================
   HERO PLATFORM PARTNERS
   Sits under the stat strip. Brand marks stay in their own colors so they are
   recognized instantly; labels are white so they hold up on the dark hero.
   ========================================================================== */
.partners { margin-top: 26px; padding-top: 22px; border-top: 1px solid rgba(255,255,255,.16); }
.partners-lbl { font-size: 11.5px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-2-deep); margin-bottom: 14px; }
.partner-row { display: flex; flex-wrap: wrap; align-items: center; gap: 12px 26px; }
.partner-row li { display: flex; align-items: center; gap: 9px; }
.partner-row svg { width: 22px; height: 22px; flex: none; display: block; }
.partner-row span { font-size: 14.5px; font-weight: 700; color: #fff; letter-spacing: .01em; }
@media (max-width: 560px) {
  .partner-row { gap: 10px 18px; }
  .partner-row span { font-size: 13.5px; }
  .partner-row svg { width: 19px; height: 19px; }
}

/* ==========================================================================
   WHO THIS WORKS FOR — self-identification. One highlighted "best fit" band
   plus the broader categories underneath.
   ========================================================================== */
.fitgrid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 20px; margin-top: 34px; }
.fit { background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 26px; box-shadow: var(--shadow);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease); }
.fit:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: rgba(224,164,25,.55); }
.fit h3 { font-size: 1.15rem; }
.fit p { font-size: 14.5px; color: var(--ink-2); margin-top: 10px; }
.fit-ic { width: 42px; height: 42px; border-radius: 11px; background: var(--accent-soft);
  color: var(--accent); display: grid; place-items: center; margin-bottom: 16px; }
.fit-ic svg { width: 22px; height: 22px; }
@media (max-width: 900px) { .fitgrid { grid-template-columns: 1fr; } }

/* Closing invitation on the who-this-works-for section */
.fit-cta { margin-top: 44px; text-align: center; background: var(--accent-soft);
  border: 1px solid rgba(224,164,25,.4); border-radius: var(--r); padding: clamp(28px, 3.6vw, 42px); }
.fit-cta h3 { font-size: clamp(1.4rem, 2.6vw, 1.95rem); max-width: 22ch; margin-inline: auto; }
.fit-cta p { color: var(--ink-2); font-size: 16px; margin-top: 12px; max-width: 54ch; margin-inline: auto; }
.fit-cta .cta-row { margin-top: 24px; }
.fit-cta-note { font-size: 14px; color: var(--ink-2); margin-top: 20px; max-width: 58ch; margin-inline: auto; }

/* ==========================================================================
   JOURNAL — article index + article body
   ========================================================================== */
.posts { display: grid; grid-template-columns: repeat(2, 1fr); gap: 22px; margin-top: 44px; }
.post { background: var(--card); border: 1px solid var(--line); border-radius: var(--r);
  padding: 28px 26px; display: flex; flex-direction: column; box-shadow: var(--shadow);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease), border-color var(--dur) var(--ease); }
.post:hover { transform: translateY(-4px); box-shadow: var(--shadow-lg); border-color: rgba(224,164,25,.55); }
.post-tag { font-size: 12px; font-weight: 800; letter-spacing: .07em; text-transform: uppercase; color: var(--accent); }
.post h3 { font-size: 1.3rem; margin-top: 10px; }
.post p { color: var(--ink-2); font-size: 15.5px; margin-top: 12px; flex: 1; }
.post .more { margin-top: 18px; font-weight: 700; font-size: 15px; color: var(--accent); }
.post--soon { background: transparent; box-shadow: none; border-style: dashed; }
.post--soon h3 { color: var(--ink-2); }

@media (max-width: 860px) { .posts { grid-template-columns: 1fr; } }

/* ==========================================================================
   BUILD ORDER — "THE TURN"
   One motif, three placements: a quiet past in grey, a gold rule that draws
   itself, a flat black answer. Gold is spent only on the answer half, never
   on the negative half, so the colour system argues the page's point.

   FIVE-DARK-WRAPPER CHECK: every selector below is scoped to .marq, .brn or
   .pcard. None of them appears inside .hero, .band-deep, .deep, .page-hero
   or .final, and nothing here lightens or darkens text globally. Expected
   visual diff on those five wrappers: none.

   APPEND ONLY. This block must sit at the END of app.css — the wall rules
   deliberately supersede app.css:631-632 by source order, not specificity.
   ========================================================================== */

/* ---- 1) THE WALL OF NAMES -------------------------------------------------
   Thirty partners, bigger, continuous on desktop, thumb-scrollable on a phone.
   gap:0 + margin-right is load-bearing: with a flex `gap` the doubled track is
   exactly one gap narrower than 2x a set, and translate3d(-50%) then jumps half
   a gap on every loop. Measured with margin-right: 60 chips x 206px = 12,360px,
   half-track 6,180px, drift 0.000px.
   -------------------------------------------------------------------------- */
.marq { position: relative; margin-top: 26px; }
.marq .wall--strip { margin-top: 0; }
/* The container rule is load-bearing and was lost in an earlier edit. Without it
   .wall--strip falls back to .wall's `display:grid` with auto-fill 1fr columns, and
   the `width:max-content` below then collapses it to ONE column - 60 chips stacked
   vertically, an 8,367px hero, and a 16:9 film cropped to 9% of its frame. */
.wall--strip { display: flex; flex-wrap: wrap; justify-content: center; gap: 12px; }
@media (max-width: 1040px) {
  .wall--strip { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch;
    justify-content: flex-start; padding-bottom: 6px; }
}

/* 48px was a thumbnail. 72px is a logo you can read. */

/* 1041px, not 1025px: app.css:634 turns the strip into an overflow-x:auto
   scroller at max-width 1040px, and an animated width:max-content track inside
   an auto-scrolling box produces a scrollbar and a broken loop. */
@media (min-width: 1041px) {
  .marq.is-live {
    overflow: hidden;
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 96px, #000 calc(100% - 96px), transparent);
            mask-image: linear-gradient(90deg, transparent, #000 96px, #000 calc(100% - 96px), transparent);
  }
  .marq.is-live .wall--strip {
    flex-wrap: nowrap; justify-content: flex-start;
    width: max-content; gap: 0;
  }
  .marq.is-live .wchip { margin-right: 16px; }
  /* .is-live is layout only. .is-running starts the animation, and JS adds it
     only after the set has been measured and --marq-dur written, so the
     marquee never runs for a frame at the wrong speed. */
  .marq.is-live.is-running .wall--strip {
    animation: marq var(--marq-dur, 90s) linear infinite;
  }
  .marq.is-running:hover .wall--strip,
  .marq.is-running:focus-within .wall--strip,
  .marq.is-running.is-out .wall--strip,
  .marq.is-running.is-stopped .wall--strip { animation-play-state: paused; }
}
@keyframes marq { to { transform: translate3d(-50%, 0, 0); } }

/* The six that publish 90 day figures carry a rule the other twenty-four do
   not. A rule and not a badge: a badge would make six chips taller and break
   the wall. */
.wall--strip a.wchip { position: relative; overflow: hidden; }
.wall--strip a.wchip::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 3px;
  background: var(--fill); transform: scaleX(.28); transform-origin: 0 50%;
  transition: transform var(--dur) var(--ease);
}
.wall--strip a.wchip:hover::after,
.wall--strip a.wchip:focus-visible::after { transform: scaleX(1); }

/* WCAG 2.2.2 Pause, Stop, Hide. Motion past five seconds needs a real control;
   hover-pause is not one. The [hidden] rule is mandatory - the base rule sets
   display:block, which would otherwise override the hidden attribute. */
.marq-toggle {
  display: block; margin: 16px auto 0;
  background: var(--card); border: 1px solid var(--line); border-radius: 999px;
  padding: 7px 16px; font-family: var(--font); font-size: 12.5px; font-weight: 700;
  color: var(--ink-2); cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.marq-toggle:hover { color: var(--ink); border-color: var(--ink); }
.marq-toggle[hidden] { display: none; }

@media (max-width: 1040px) {
  .marq .wchip[data-clone] { display: none; }   /* guards a desktop->mobile resize */
  .marq-toggle { display: none; }
  /* Affordance only: let the row bleed off the right edge so a thumb knows it moves. */
  .marq { -webkit-mask-image: linear-gradient(90deg, #000 calc(100% - 44px), transparent);
                  mask-image: linear-gradient(90deg, #000 calc(100% - 44px), transparent); }
}
@media (prefers-reduced-motion: reduce) {
  .marq .wchip[data-clone] { display: none; }
  .marq-toggle { display: none; }
}

/* ---- 3) PROOF CARDS, PROMOTED --------------------------------------------
   The strongest content on the page was the only card with no hover state
   (verified: .pcard is in the border-colour reset at app.css:744 but omitted
   from the hover list at 745). It now behaves like every other card, the
   figures move above the quote, and the gold chips ignite - the same Turn.
   -------------------------------------------------------------------------- */
.pcard { transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease),
  border-color var(--dur) var(--ease); }
.pcard:hover, .pcard:focus-within { transform: translateY(-4px); box-shadow: var(--shadow-lg);
  border-color: rgba(224,164,25,.55); }

/* Figures first. .pcard-b is already a flex column, so this needs no markup
   change; .pquote keeps its flex:1 and .pmeta still bottom-aligns the row. */
.pcard-b .pnums { order: -1; margin-top: 0; margin-bottom: 16px; }
.pcard-b .chip { font-size: 13px; padding: 7px 12px;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease); }
.pcard:hover .chip, .pcard:focus-within .chip { background: var(--fill); color: var(--on-fill); }

@media (prefers-reduced-motion: reduce) {
  .pcard:hover, .pcard:focus-within { transform: none; }
}

/* ==========================================================================
   V3 — "SHOW THE REACH". Append to the END of css/app.css. Nothing above is
   edited; every rule here wins on cascade order alone.

   Five moves:
     1. The reach story stops being print-only.
     2. Services arrive one flick after the hero (the partner strip folds into
        the hero floor instead of owning a section).
     3. Three claims become photographs.
     4. The light half goes from five white sections to one.
     5. One new dark wrapper, .figband, registered against EVERY dark-surface
        rule that already exists further up this file.
   ========================================================================== */

/* ---- New tokens ---------------------------------------------------------
   --sand is the third light surface the page never had. Relative luminance
   0.800 against --bg's 0.906 — an 11% step, unmistakably a different tone
   rather than a fourth off-white. Measured, not eyeballed:
     --ink    #191512 on #EDE7DD = 14.67:1
     --ink-2  #5C5147 on #EDE7DD =  6.24:1
     --accent #7F5D0E on #EDE7DD =  4.89:1   (5.50:1 on --bg; still clears 4.5)
   --sand-line exists because --line (#E4DFD7) is within 3% of --sand and
   disappears on it.                                                          */
:root {
  --sand:      #EDE7DD;
  --sand-line: #DED5C6;
}

.band-sand      { background: var(--sand); }
/* Hairlines are opt-in per edge. A sand band NEVER draws one against a dark
   neighbour: #DED5C6 on #171310 renders as a bright stripe, which is exactly
   the bug .band-deep .seats (app.css:661) already had to clean up once. */
.band-sand--t   { border-top: 1px solid var(--sand-line); }
.band-sand--b   { border-bottom: 1px solid var(--sand-line); }

/* ==========================================================================
   1) HERO — digital-first stats, and the partner strip folded into the floor
   ========================================================================== */

/* The two range figures are the headline claim, so they carry gold; the two
   counted figures stay white so the strip does not become a gold bar.
   #E8B33C on #171310 = 9.62:1. */
.stat--reach b { color: var(--accent-hi); }
.micro-hi { color: var(--ink-on-deep); font-weight: 800; }

/* THE FLOOR. An opaque plinth inside .hero, below .hero-in. It is opaque so it
   never sits on the aerial at the scrim's transparent end, and z-index:2 puts
   it above both the media (0) and the scrim (1).
   .wchip already carries background:var(--card) + 1px --line (app.css:627-629),
   so thirty white logo plates GAIN contrast on espresso rather than losing it.
   Not part of the hero reveal cascade on purpose — that machinery is documented
   as the most fragile thing on the page and a logo ribbon is not worth a sixth
   state in it. During .awaiting it simply sits under the letterboxed film. */
.hero-strip {
  position: relative; z-index: 2;
  background: var(--espresso);
  border-top: 1px solid var(--line-deep);
  margin-top: clamp(34px, 5vw, 56px);
  padding-block: clamp(22px, 3vw, 30px);
}
.hero-strip-lbl {
  font-size: 11.5px; font-weight: 700; letter-spacing: .13em; text-transform: uppercase;
  color: var(--ink-2-deep); margin-bottom: 4px;      /* #A89A8E on #2B231F = 5.9:1 */
}
.hero-strip .marq { margin-top: 14px; }
.hero-strip-note {
  font-size: 13.5px; line-height: 1.55; color: var(--ink-2-deep);
  margin-top: 16px; max-width: 76ch;
}
.hero-strip-note a { color: var(--accent-hi); font-weight: 700; }  /* 8.0:1 on espresso */
.hero-strip-note a:hover { color: var(--fill-hi); }
/* The pause control was a white pill authored for a white section. On the dark
   floor it becomes a ghost, matching every other dark-surface control. */
.hero-strip .marq-toggle {
  background: transparent; color: var(--ink-2-deep);
  border-color: rgba(255,255,255,.28);
}
.hero-strip .marq-toggle:hover { color: #fff; border-color: #fff; }
/* The 1041px mask gate lives on .marq itself, so it transplants unchanged. */

@media (max-width: 1024px) {
  /* .hero flips to overflow:visible at this width (app.css:451); the strip is
     opaque and in flow, so it needs nothing except tighter padding. */
  .hero-strip { margin-top: 30px; padding-block: 20px; }
}

/* ==========================================================================
   2) .figband — THE SIXTH DARK WRAPPER
   Two variants, and the choice between them is a rule, not a mood:
     .figband--split  the photograph carries INFORMATION → never scrimmed;
                      it bleeds off the viewport edge beside the copy.
     .figband (base)  the photograph carries ATMOSPHERE → scrimmed, copy over.
   Both share the same surface, type scale, gold-figure treatment and edge
   bleed, so they read as one component with two jobs.
   ========================================================================== */
.figband {
  position: relative; isolation: isolate; overflow: hidden;
  background: var(--deep); color: var(--ink-on-deep);
  padding-block: clamp(60px, 8vw, 108px);
}
.figband--espresso { background: var(--espresso); }
.figband > .wrap { position: relative; z-index: 2; }
.figband-media { position: absolute; inset: 0; z-index: 0; }
.figband-media img { width: 100%; height: 100%; object-fit: cover; }

/* Overlay scrim. Copy on the LEFT; the plateau runs to 46% so the copy column
   (max 500px, ending at ~46% of a 1440px viewport) never leaves it, and the
   subjects sitting right of centre stay at ≤.58 alpha and fully readable.
   Composite check at the column's far right edge (.949 over the image's
   brightest golden area, ~#352B25): --ink-2-deep 5.09:1, --ink-on-deep 11.6:1,
   #fff 15.0:1. All pass. Do not lower the .95 stop. */
.figband:not(.figband--split)::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(90deg,
    rgba(23,19,16,.97) 0%,  rgba(23,19,16,.95) 46%, rgba(23,19,16,.58) 58%,
    rgba(23,19,16,.14) 72%, rgba(23,19,16,0)   86%);
}
.figband--espresso:not(.figband--split)::after {
  background: linear-gradient(90deg,
    rgba(43,35,31,.97) 0%,  rgba(43,35,31,.95) 46%, rgba(43,35,31,.58) 58%,
    rgba(43,35,31,.14) 72%, rgba(43,35,31,0)   86%);
}
.figband:not(.figband--split) .figband-col { max-width: 500px; }

/* REGISTERING THE SIXTH DARK WRAPPER. Five rules above this point enumerate
   their dark surfaces by name (.deep/.band-deep/.final/.page-hero/.hero) and
   .figband is in none of them. Every one is re-declared here.
   NOTE the deliberate exception: .lead and .micro get --ink-on-deep, NOT the
   --ink-2-deep those rules use. Composite alpha over a PHOTOGRAPH is not the
   same as over a flat band — #A89A8E over the .76-alpha shoulder of a golden
   image measures 3.18:1. --ink-on-deep measures 7.6:1 at the same point. */
.figband .kicker              { color: var(--accent-hi); }
.figband h2, .figband h3      { color: #fff; }
.figband .lead, .figband p    { color: var(--ink-on-deep); }
.figband .micro               { color: var(--ink-on-deep); }
.figband .shot                { border-color: var(--line-deep); }
.figband .btn--ghost          { color: var(--ink-on-deep); border-color: rgba(255,255,255,.34); }
.figband .btn--ghost:hover    { background: rgba(255,255,255,.1); border-color: #fff; color: #fff; }

/* Figure block. Gold numerals at 9.62:1, muted labels at 6.7:1 inside the
   opaque zone. Tabular numerals so the counted figures do not jitter. */
.figstats { display: grid; grid-template-columns: repeat(2, minmax(0,1fr));
  gap: 22px 26px; margin-top: 32px; padding-top: 26px;
  border-top: 1px solid rgba(255,255,255,.16); }
.figstat b { display: block; font-size: clamp(1.4rem, 2.7vw, 1.9rem); font-weight: 800;
  line-height: 1; letter-spacing: -.03em; color: var(--accent-hi);
  font-variant-numeric: tabular-nums; }
.figstat span { display: block; margin-top: 8px; font-size: 13px; font-weight: 600;
  line-height: 1.35; color: var(--ink-2-deep); }

/* #owner fact list */
.ownerfacts { margin-top: 26px; display: grid; gap: 11px; }
.ownerfacts li { position: relative; padding-left: 26px; font-size: 15px;
  color: var(--ink-on-deep); }
.ownerfacts li::before { content: ""; position: absolute; left: 0; top: .55em;
  width: 12px; height: 2px; border-radius: 2px; background: var(--fill); }

/* ---- .figband--split: the map bleeds off the right edge ------------------
   No absolute positioning and no scrim. The wrap drops its max-width and its
   right padding, and re-creates the 1200px left alignment with a max() so the
   copy still sits on the page grid while the media runs to the viewport edge.
   16/11 keeps every town pin inside the crop: at a 1440px viewport the panel
   is ~691x475, which shows 62% of the 2.36:1 source — Fair Oaks through
   Cameron Park, all seven labels. Full-height would have shown only 35%. */
@media (min-width: 1041px) {
  .figband--split > .wrap {
    max-width: none; padding-right: 0;
    padding-left: max(var(--gutter), calc((100vw - var(--maxw)) / 2 + var(--gutter)));
    display: grid; grid-template-columns: minmax(0, 520px) minmax(0, 1fr);
    gap: clamp(40px, 5vw, 76px); align-items: center;
  }
  .figband--split .figband-media {
    position: relative; inset: auto; z-index: 0;
    aspect-ratio: 16 / 11; overflow: hidden;
    border-radius: var(--r) 0 0 var(--r);
    border: 1px solid var(--line-deep); border-right: 0;
  }
  .figband--split .figband-media img { object-position: 48% 46%; }
}

/* ---- .figband on tablets and phones --------------------------------------
   Same pattern the hero already uses at this breakpoint (app.css:450): the
   photograph stops being a backdrop and becomes a band of its own with an
   explicit ratio, the copy sits below it on the solid surface, and the scrim
   switches off because nothing is on top of the picture any more. Zero CLS —
   the ratio is declared at every width. */
@media (max-width: 1024px) {
  .figband { padding-top: 0; }
  .figband-media { position: relative; inset: auto; width: 100%; aspect-ratio: 16 / 9; }
  .figband:not(.figband--split)::after { display: none; }
  .figband > .wrap { padding-top: clamp(30px, 6vw, 46px); }
  .figband:not(.figband--split) .figband-col,
  .figband--split .figband-col { max-width: none; }
  /* THE MOBILE MAP CROP, for 0 KB. object-fit:cover in a box narrower than the
     2.36:1 source scales to match HEIGHT and crops width — which is a genuine
     zoom, not a trim. A 4:3 box shows 56% of the frame; a 1:1 box shows 42% at
     roughly native label size, centred at 44% so Fair Oaks through Cameron Park
     all survive. This is the fix for the catalogued "labels fall below
     legibility on phones" warning. */
  }
@media (max-width: 560px) {
  .figstats { grid-template-columns: 1fr; gap: 18px; }
}

/* ==========================================================================
   3) .final — the closing band becomes a place
   Flat vertical scrim, floor of .90 alpha, and that floor is a REQUIREMENT.
   Composite over the image's brightest sky (~#E8DCC0):
     at .82  →  #3D3730,  --ink-2-deep = 4.43:1   FAILS
     at .90  →  #2C2722,  --ink-2-deep = 5.47:1,  #fff = 14.78:1   PASSES
   Do not lighten it to "let the photo through". It is atmosphere, not content.
   ========================================================================== */
.final--fig { position: relative; isolation: isolate; overflow: hidden; }
.final--fig .final-media { position: absolute; inset: 0; z-index: 0; }
.final--fig .final-media img { width: 100%; height: 100%; object-fit: cover;
  object-position: 50% 42%; }
.final--fig::after {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(180deg,
    rgba(23,19,16,.93) 0%, rgba(23,19,16,.90) 46%, rgba(23,19,16,.96) 100%);
}
.final--fig > .wrap { position: relative; z-index: 2; }
/* A single gold wash behind the headline. One radial gradient, 0 KB, no blend
   mode — the cheapest possible way to stop the closing band reading as a slab. */
.final--fig::before {
  content: ""; position: absolute; z-index: 1; pointer-events: none;
  left: 50%; top: 0; width: min(1000px, 120%); height: 78%;
  transform: translateX(-50%);
  background: radial-gradient(ellipse at 50% 0%,
    rgba(224,164,25,.16) 0%, rgba(224,164,25,.06) 42%, rgba(224,164,25,0) 72%);
}

/* ==========================================================================
   4) steps — split so a photograph breaks the longest type run on the page
   ========================================================================== */
.stepsplit { display: grid; grid-template-columns: minmax(0, 440px) minmax(0, 1fr);
  gap: clamp(32px, 5vw, 64px); align-items: start; }
.stepsplit-media { position: sticky; top: 88px; }
.stepsplit-media .shot { aspect-ratio: 4 / 3; object-fit: cover; }
.steps--stack { grid-template-columns: 1fr; gap: 16px; margin-top: 32px; }
@media (max-width: 1040px) {
  .stepsplit { grid-template-columns: 1fr; gap: 28px; }
  .stepsplit-media { position: static; }
  .stepsplit-media .shot { aspect-ratio: 16 / 9; }
}
@media (prefers-reduced-motion: reduce) { .stepsplit-media { position: static; } }

/* ==========================================================================
   5) SAND-BAND CORRECTIONS
   Cards keep their #fff and their soft shadow but lose the hairline they no
   longer need: on --sand a 1px #E4DFD7 border is invisible anyway, and the
   shadow alone reads as a raised object. This is the actual answer to "too
   much white" — the cards stop being the same colour as the page.
   ========================================================================== */
.band-sand .pcard,
.band-sand .tier:not(.tier--best),
.band-sand .fit,
.band-sand .note { border-color: rgba(25,21,18,.07); }
.band-sand .faq details { border-color: var(--sand-line); }
/* The gold rule that opens the two commercial sections. A 1px gradient, 0 KB. */
.band-sand--t { position: relative; }
.band-sand--t::before {
  content: ""; position: absolute; left: 0; right: 0; top: -1px; height: 2px;
  background: linear-gradient(90deg,
    rgba(224,164,25,0) 0%, rgba(224,164,25,.55) 30%,
    rgba(224,164,25,.55) 70%, rgba(224,164,25,0) 100%);
}

/* ==========================================================================
   6) MOTION BUDGET
   Everything above animates transform or opacity only. No filters, no blend
   modes, no background-attachment:fixed, no scroll-linked paint. Each .figband
   costs exactly one composited pseudo-element.
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .figband-col.rv, .stepsplit-media.rv { opacity: 1; transform: none; }
}

/* ---- WALL OF NAMES: optical sizing -----------------------------------------
   Equal HEIGHT is the wrong normaliser for a logo wall: at 72px tall, green-hills
   rendered 158x72 and bodie-electric 60x72 - a 2.64x difference in visual weight.
   These heights equalise rendered AREA instead (variance 1.01x). Each logo carries
   its own --lh so the phone breakpoint scales the whole set with one multiplier.
   -------------------------------------------------------------------------- */
.wall--strip .wchip { flex: 0 0 232px; padding: 18px 16px; align-items: center;
  justify-content: center; min-height: 136px; }
.wall--strip .wchip img { height: var(--lh, 88px); width: auto; max-width: 200px;
  object-fit: contain; margin-bottom: 0; }
.wall--strip .wchip img[src$="/4chr.webp"]{--lh:45px}
.wall--strip .wchip img[src$="/age-in-place.webp"]{--lh:92px}
.wall--strip .wchip img[src$="/bodie-electric.webp"]{--lh:101px}
.wall--strip .wchip img[src$="/boyechko.webp"]{--lh:80px}
.wall--strip .wchip img[src$="/cg-plumbing.webp"]{--lh:99px}
.wall--strip .wchip img[src$="/comfortcraft.webp"]{--lh:69px}
.wall--strip .wchip img[src$="/cruise-planners.webp"]{--lh:45px}
.wall--strip .wchip img[src$="/dignity.webp"]{--lh:71px}
.wall--strip .wchip img[src$="/elite-fireplace.webp"]{--lh:53px}
.wall--strip .wchip img[src$="/fair-oaks-villa.webp"]{--lh:45px}
.wall--strip .wchip img[src$="/farrell.webp"]{--lh:93px}
.wall--strip .wchip img[src$="/fci.webp"]{--lh:42px}
.wall--strip .wchip img[src$="/flr.webp"]{--lh:92px}
.wall--strip .wchip img[src$="/folsom-kb.webp"]{--lh:45px}
.wall--strip .wchip img[src$="/folsom-remodel.webp"]{--lh:92px}
.wall--strip .wchip img[src$="/foothill-pool.webp"]{--lh:92px}
.wall--strip .wchip img[src$="/gcpe.webp"]{--lh:92px}
.wall--strip .wchip img[src$="/gift-of-kids.webp"]{--lh:61px}
.wall--strip .wchip img[src$="/green-hills.webp"]{--lh:62px}
.wall--strip .wchip img[src$="/hc-auto.webp"]{--lh:81px}
.wall--strip .wchip img[src$="/homepro.webp"]{--lh:47px}
.wall--strip .wchip img[src$="/knoblauch.webp"]{--lh:60px}
.wall--strip .wchip img[src$="/liberty-roofing.webp"]{--lh:92px}
.wall--strip .wchip img[src$="/livity.webp"]{--lh:92px}
.wall--strip .wchip img[src$="/owen-training.webp"]{--lh:92px}
.wall--strip .wchip img[src$="/pro-show.webp"]{--lh:92px}
.wall--strip .wchip img[src$="/rp-concrete.webp"]{--lh:75px}
.wall--strip .wchip img[src$="/sgg.webp"]{--lh:63px}
.wall--strip .wchip img[src$="/smits.webp"]{--lh:64px}
.wall--strip .wchip img[src$="/viscusos.webp"]{--lh:75px}
@media (max-width: 1040px) {
  .wall--strip .wchip { flex: 0 0 196px; padding: 16px 14px; min-height: 116px; }
  .wall--strip .wchip img { height: calc(var(--lh, 88px) * .82); max-width: 168px; }
}

/* ---- HERO FILM FRAMING ------------------------------------------------------
   .hero-media was position:absolute;inset:0, so the film scaled to cover the WHOLE
   hero - including the ~340px hidden behind the opaque espresso strip. At 1440x900
   that cost 30% of the frame for pixels nobody can see.

   A two-row grid with the backdrop and the copy sharing row 1 and the strip owning
   row 2 means the film covers exactly the area that is actually visible. No JS, no
   measured heights. The <=1024px band layout is unaffected: it overrides .hero-media
   back to static flow with its own 16/9 box.
   -------------------------------------------------------------------------- */
@media (min-width: 1025px) {
  /* The section's own 96px block padding sat ABOVE the film, so on every desktop
     width the band opened with a dark strip before the picture started. The grid
     rows are the layout now, so the padding moves onto the copy where it belongs
     and the film bleeds to the top edge of the section. */
  .hero { display: grid; grid-template-columns: minmax(0, 1fr);
    grid-template-rows: 1fr auto; align-content: start; padding-block: 0; }
  .hero-in { padding-block: clamp(56px, 6vw, 104px); }
  .hero-media  { position: relative; inset: auto; grid-area: 1 / 1; height: 100%; overflow: hidden; }
  /* width:100% is load-bearing. .hero-in carries `margin-inline:auto`, and in grid an
     auto inline margin DISABLES stretch - the item shrank to its max-content width
     (876px) and the auto margins then centred it, which is why the headline sat in
     the middle of the screen instead of on the page gutter. Filling the column first
     lets max-width cap it and the auto margins centre the capped box, which is what
     the block layout did before this section became a grid. */
  .hero-in     { grid-area: 1 / 1; align-self: center; width: 100%; }
  .hero-strip  { grid-area: 2 / 1; margin-top: 0; }
  .hero::after { grid-area: 1 / 1; }
}

/* ==========================================================================
   THE LETTER
   The one section that is not built like the rest of the page. Every other
   section is centred heading + grid of cards; this is a single left-aligned
   column in first person, on parchment, with a rule down its left edge like a
   document rather than a component. That contrast IS the mechanism - it signals
   "this part is me talking to you" before a word is read.

   Type is larger than body copy (18.5px vs 17px) and the measure is held to
   ~64ch, because this is the only block on the page written to be READ rather
   than scanned.
   ========================================================================== */
/* The turn. Same size as the body but in full ink, so the eye lands on it. */

/* At 320-374px the H1's 1.95rem floor wrapped the headline to six lines and shoved the
   whole hero down. The floor only ever applied below ~678px, so lowering it here costs
   nothing at any width that was already fine. */
@media (max-width: 374px) {
  .hero h1 { font-size: 1.68rem; }
  .hero .lead { font-size: 16px; }
}

/* ---- TOUCH TARGETS AND SMALL LABELS ----------------------------------------
   Measured across 320-2560px: the only elements under the 44px touch guideline were
   the "Verbatim Google review" links (20px) and the marquee pause control (32px).
   Both are real targets a thumb has to hit, so they get padded rather than resized -
   the type stays where the design put it, the hit area grows underneath it.
   -------------------------------------------------------------------------- */
.gsrc { padding-block: 11px; margin-top: 6px; }
.marq-toggle { padding: 11px 20px; }
/* 10.5px was below the floor for a label sitting on a photograph. */
.pshot-tag { font-size: 11.5px; padding: 7px 11px; }

/* ---- #reach map -------------------------------------------------------------
   Source is pre-cropped to the map at 1.64:1, so no CSS zoom is needed and none is
   wanted: the outer pins (Roseville, Placerville) sit near the edges and any crop
   tighter than the source loses the two towns that prove the span.
   -------------------------------------------------------------------------- */
#reach .figband-media { aspect-ratio: 16 / 10; }
#reach .figband-media img { object-position: 50% 50%; }
@media (max-width: 1040px) {
  #reach .figband-media { aspect-ratio: 16 / 10; margin-top: 26px;
    border-radius: var(--r); border: 1px solid var(--line-deep); overflow: hidden; }
}

/* ==========================================================================
   THE SIGN
   A deliberate rupture. Its own typeface, its own ground, its own light source.
   The page is warm parchment and composed grids everywhere else; here it goes
   cold, wet and dark for one screen, and the only warm thing left is the gold.

   The conceit: a roadside sign in bad weather. The four things that went wrong
   are the letters that have burnt out - unlit, grey, no glow. The last line is
   the tube that still works. Nothing about that is decoration; it is the
   argument the section is making, drawn instead of written.
   ========================================================================== */
.sign {
  position: relative; isolation: isolate; overflow: hidden;
  background: #070908;
  padding-block: clamp(72px, 11vw, 132px);
}

/* Storm: a cold sky, a slow bloom of gold where the sign hangs, and the weathered
   texture underneath doing the work of rain-soaked brick. Static gradients only -
   no filters, no blend modes, nothing that costs a frame. */
.sign-sky {
  position: absolute; inset: 0; z-index: 0;
  background-image:
    radial-gradient(78% 52% at 50% 30%, rgba(224,164,25,.16), transparent 68%),
    radial-gradient(120% 80% at 50% 120%, rgba(9,17,20,.9), transparent 70%),
    linear-gradient(180deg, rgba(7,9,8,.86) 0%, rgba(7,9,8,.72) 45%, rgba(7,9,8,.95) 100%),
    url('/assets/img/lib/texture/weathered-leather.webp');
  background-size: cover; background-position: center;
}
/* Rain: two sheets of hairline diagonals at different pitches so it does not read
   as a repeating pattern. Purely CSS - no image, no request. */
.sign-rain {
  position: absolute; inset: -20% -10%; z-index: 1; opacity: .28; pointer-events: none;
  background-image:
    repeating-linear-gradient(74deg, rgba(210,225,235,.16) 0 1px, transparent 1px 7px),
    repeating-linear-gradient(78deg, rgba(210,225,235,.10) 0 1px, transparent 1px 13px);
}
.sign > .wrap { position: relative; z-index: 2; max-width: 940px; }

.sign-eyebrow {
  font-family: 'Bebas', 'Jakarta', sans-serif;
  font-size: clamp(13px, 1.5vw, 15px); letter-spacing: .42em; text-transform: uppercase;
  color: rgba(224,164,25,.85); margin-bottom: 18px;
}

/* The lit sign. Layered shadows read as tube glow: a tight white core, a gold
   halo, then two wide amber blooms that fake light spilling onto the wet wall. */
.sign-h {
  font-family: 'Bebas', 'Jakarta', sans-serif; font-weight: 400;
  font-size: clamp(2.9rem, 9.5vw, 6.4rem); line-height: .92; letter-spacing: .012em;
  text-transform: uppercase; color: #FFF7E6;
  margin-bottom: clamp(38px, 5.5vw, 62px);
  text-shadow:
    0 0 2px  rgba(255,248,232,.98),
    0 0 10px rgba(255,206,120,.85),
    0 0 26px rgba(224,164,25,.62),
    0 0 58px rgba(224,164,25,.34),
    0 0 110px rgba(224,164,25,.20);
}

/* The burnt-out letters. Same family, no glow, cold grey - they read as unlit
   tubes next to the line that still works. */
.sign-list { list-style: none; margin: 0 0 clamp(38px, 5.5vw, 62px); padding: 0; }
.sign-list li {
  font-family: 'Bebas', 'Jakarta', sans-serif; font-weight: 400;
  font-size: clamp(1.32rem, 3.4vw, 2.05rem); line-height: 1.16; letter-spacing: .022em;
  text-transform: uppercase; color: #8E9599;
  padding: clamp(13px, 1.7vw, 19px) 0 clamp(13px, 1.7vw, 19px) clamp(30px, 3.6vw, 52px);
  border-top: 1px solid rgba(210,225,235,.13); position: relative;
}
.sign-list li:last-child { border-bottom: 1px solid rgba(210,225,235,.13); }
/* A dead tube: short, dim, and it never lights. */
.sign-list li::before {
  content: ""; position: absolute; left: 0; top: 50%;
  width: clamp(16px, 2.2vw, 30px); height: 3px; border-radius: 2px;
  background: rgba(142,149,153,.5);
  transform-origin: 0 50%; transform: scaleX(0);
  transition: transform 520ms var(--ease);
}
.sign-list li.in::before { transform: scaleX(1); }
html:not(.js) .sign-list li::before { transform: none; }

/* The one that is still on. */
.sign-turn {
  font-family: 'Jakarta', sans-serif;   /* back to the site's voice for the promise */
  font-size: clamp(1.06rem, 1.9vw, 1.3rem); line-height: 1.55; font-weight: 700;
  color: #FFF3DE; max-width: 62ch;
  padding-left: clamp(30px, 3.6vw, 52px);
  border-left: 3px solid var(--fill);
  text-shadow: 0 0 18px rgba(224,164,25,.28);
}

/* The hum. One compositor-thread opacity cycle on the glow layer, nothing else,
   and it stops entirely for anyone who asked for less motion. */
@media (prefers-reduced-motion: no-preference) {
  .sign-sky { animation: signHum 7.5s ease-in-out infinite; }
}
@keyframes signHum { 0%,100% { opacity: 1; } 46% { opacity: .93; } 52% { opacity: 1; } }

@media (max-width: 700px) {
  .sign-turn { padding-left: 20px; border-left-width: 2px; }
  .sign-list li { padding-left: 24px; }
  .sign-rain { opacity: .2; }
}

/* ==========================================================================
   THE VACANCY BOARD
   The second neon moment, and deliberately a different night from .sign. That
   one is a storm because its message is "you got let down". This one is a warm
   resort dusk because its message is "there is a room for you" - same tube, same
   typeface, opposite weather.

   The conceit does the arguing: seven keys are gone, three are on the hook, and
   the lit rows are the ones you can still have. Scarcity you can read in half a
   second without a single word of pressure.
   ========================================================================== */
.vac {
  position: relative; isolation: isolate; overflow: hidden;
  background: #14100D; padding-block: clamp(70px, 10vw, 120px);
}
/* Warm dusk: a low gold horizon, a pool of sign-light overhead, walnut underneath. */
.vac-night {
  position: absolute; inset: 0; z-index: 0;
  background-image:
    radial-gradient(64% 44% at 50% 12%, rgba(224,164,25,.20), transparent 70%),
    radial-gradient(90% 60% at 50% 108%, rgba(132,107,91,.28), transparent 72%),
    linear-gradient(180deg, rgba(20,16,13,.90) 0%, rgba(20,16,13,.74) 40%, rgba(20,16,13,.96) 100%),
    url('/assets/img/lib/texture/dark-walnut.webp');
  background-size: cover; background-position: center;
}
.vac > .wrap { position: relative; z-index: 2; max-width: 1000px; }

.vac-head { text-align: center; margin-bottom: clamp(38px, 5vw, 60px); }
.vac .sign-eyebrow { margin-bottom: 14px; }

/* The sign. "No" sits above and to the left, unlit, because seven of ten are gone -
   but VACANCY is the word that glows, because three are not. */
.vac-h {
  font-family: 'Bebas', 'Jakarta', sans-serif; font-weight: 400;
  font-size: clamp(3.1rem, 11vw, 7rem); line-height: .86; letter-spacing: .02em;
  text-transform: uppercase; color: #FFF7E6; position: relative; display: inline-block;
  text-shadow:
    0 0 2px  rgba(255,248,232,.98),
    0 0 10px rgba(255,206,120,.85),
    0 0 28px rgba(224,164,25,.60),
    0 0 62px rgba(224,164,25,.32),
    0 0 118px rgba(224,164,25,.18);
}
/* The dead half of the sign. Kept in the flow so the board reads "NO VACANCY" at a
   glance and then resolves - the joke is that the No is burnt out. */
.vac-h .vac-no {
  display: block; font-size: .34em; letter-spacing: .3em; line-height: 1;
  margin-bottom: .16em; color: #6E635A; text-shadow: none;
}
.vac-sub {
  margin-top: 20px; font-size: clamp(1rem, 1.8vw, 1.18rem); line-height: 1.5;
  color: var(--parchment); font-weight: 600;
}

/* The board itself: keys on hooks. */
/* The lamp: lit gold for open, dark and recessed for taken. */
.vlamp {
  width: 10px; height: 10px; border-radius: 50%; flex: 0 0 auto;
  background: #3A322C; box-shadow: inset 0 1px 2px rgba(0,0,0,.8);
}


.vac-ask {
  margin-top: 26px; font-size: 15px; line-height: 1.55; color: var(--parchment);
  text-align: center; max-width: 62ch; margin-inline: auto;
}
.vac-ask a { color: var(--accent-hi); font-weight: 700; }
.vac-ask a:hover { color: var(--fill-hi); }

.vac-foot {
  display: grid; grid-template-columns: repeat(2, minmax(0,1fr));
  gap: clamp(26px, 4vw, 48px); align-items: start;
  margin-top: clamp(44px, 6vw, 70px);
  padding-top: clamp(34px, 5vw, 52px); border-top: 1px solid rgba(244,241,231,.13);
}
.note--vac { background: rgba(244,241,231,.055); border-color: rgba(244,241,231,.16); }
.note--vac b { color: var(--accent-hi); }
.note--vac p { color: var(--parchment); }
.vac-lead { font-size: 16.5px; line-height: 1.6; color: var(--parchment); }
.vac-micro { color: var(--stone); margin-top: 14px; }
.vac-micro a { color: var(--accent-hi); font-weight: 700; }

/* The sign warming up. One opacity cycle on the glow ground, nothing per-frame. */
@media (prefers-reduced-motion: no-preference) {
  .vac-night { animation: vacHum 9s ease-in-out infinite; }
}
@keyframes vacHum { 0%,100% { opacity: 1; } 58% { opacity: .95; } 64% { opacity: 1; } }

@media (max-width: 820px) {
  .vboard { grid-template-columns: 1fr; }
  .vac-foot { grid-template-columns: 1fr; }
}

/* The ground: dusk, not storm */
/* ==========================================================================
   THE MARQUEE — #fit as a resort at dusk.
   Same neon language as .sign, opposite weather. .sign is a roadside sign in
   a storm; this is a porte-cochere with the lights already on. Nothing cold
   appears anywhere in this block — no blue, no grey-blue, no rain.
   Ground reuses weathered-leather.webp, which .sign-sky (app.css:1389) has
   already fetched by the time this section paints. 0 new bytes.
   ========================================================================== */
.marquee {
  background: #0E0B08;            /* warmer + deeper than --deep #171310 */
  overflow: hidden;
  padding-block: clamp(76px, 10vw, 128px) clamp(84px, 11vw, 136px);
}

.marquee-ground {
  position: absolute; inset: 0; pointer-events: none;
  background-image:
    /* 1. the last light: low, wide, amber. this is the whole mood in one line */
    radial-gradient(132% 52% at 50% 106%,
      rgba(240,184,56,.34) 0%, rgba(214,116,36,.15) 38%, transparent 74%),
    /* 2. warm dark overhead, so the eye is pulled DOWN to the horizon */
    radial-gradient(84% 42% at 50% -10%, rgba(72,48,32,.55), transparent 66%),
    /* 3. the dusk wash. every stop is warm; nothing here is blue */
    linear-gradient(180deg,
      rgba(12,9,6,.94) 0%, rgba(24,17,12,.80) 40%,
      rgba(30,20,13,.66) 72%, rgba(12,9,6,.86) 100%),
    url('/assets/img/lib/texture/weathered-leather.webp');
  background-size: cover;
  background-position: center 62%;
}

/* The ridge. A single clipped gradient = the foothills at last light.
   Static, no filter, no blend mode, 0 KB, and it is what turns a dark band
   into somewhere you are arriving. */
.marquee-ground::after {
  content: ""; position: absolute; left: -6%; right: -6%; bottom: 0; height: 32%;
  background: linear-gradient(180deg,
    rgba(10,7,5,0) 0%, rgba(10,7,5,.88) 44%, rgba(8,6,4,.97) 100%);
  clip-path: polygon(0 24%, 11% 15%, 24% 21%, 37% 9%, 50% 18%,
                     63% 8%, 76% 17%, 88% 11%, 100% 19%, 100% 100%, 0 100%);
}

/* A line of light between this band and #owner (figband--espresso) below it.
   Two dark bands must not butt into one long slab — index.html:672 already
   flags that risk. Same 2px gold device as .band-sand--t::before (app.css:1239). */
.marquee::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 2px; z-index: 2;
  background: linear-gradient(90deg,
    rgba(224,164,25,0) 0%, rgba(224,164,25,.5) 28%,
    rgba(224,164,25,.5) 72%, rgba(224,164,25,0) 100%);
}

/* The hardware: canopy, eave, arm */
/* Canopy bulbs. One repeating radial + one hairline wire. 0 KB. */
.marquee-bulbs {
  position: absolute; left: 0; right: 0; top: clamp(28px, 5vw, 52px);
  height: 14px; pointer-events: none; opacity: .85;
  background-image:
    radial-gradient(circle 3px at 15px 9px,
      rgba(255,218,152,.95), rgba(255,196,110,.26) 55%, transparent 72%),
    linear-gradient(90deg, transparent 0%, rgba(224,164,25,.28) 8%,
      rgba(224,164,25,.28) 92%, transparent 100%);
  background-size: 30px 100%, 100% 1px;
  background-position: 0 0, 0 4px;
  background-repeat: repeat-x, no-repeat;
}

/* The eave the signs hang off. */
.marquee-eave {
  height: 2px; margin-top: clamp(46px, 6vw, 74px);
  background: linear-gradient(90deg, transparent,
    rgba(224,164,25,.34) 10%, rgba(224,164,25,.48) 50%,
    rgba(224,164,25,.34) 90%, transparent);
  box-shadow: 0 1px 0 rgba(0,0,0,.6), 0 0 18px rgba(224,164,25,.16);
}

/* Two rods and a bracket bar, in one element. */
.msign-arm {
  position: absolute; top: 0; left: 0; right: 0; height: var(--arm);
  pointer-events: none;
  background-image:
    linear-gradient(180deg, rgba(224,164,25,.45), rgba(224,164,25,.14)),
    linear-gradient(180deg, rgba(224,164,25,.45), rgba(224,164,25,.14));
  background-size: 2px 100%, 2px 100%;
  background-position: 27% 0, 73% 0;
  background-repeat: no-repeat;
}
.msign-arm::before {
  content: ""; position: absolute; top: 0; left: 27%; right: 27%;
  height: 2px; border-radius: 2px; background: rgba(224,164,25,.42);
}

/* One sign, constructed */
.msigns {
  display: grid; grid-template-columns: repeat(2, 1fr);
  gap: clamp(30px, 4vw, 52px) clamp(24px, 3.4vw, 46px);
  align-items: start; list-style: none; margin: 0; padding: 0;
}

/* Four tubes, one gold family. Nothing here leaves black / white / gold /
   earth: the coolest is warm ivory, the warmest is copper amber. */
.msign {
  --arm: 40px; --tube: var(--fill-hi); --halo: 240,184,56;
  position: relative; padding-top: var(--arm);
  transition: transform var(--dur) var(--ease);
}
.msign--1 { --arm: 34px; --tube: #F6C24E; --halo: 246,194,78; }   /* brightest: it has open seats */
.msign--2 { --arm: 58px; --tube: #FFE3B4; --halo: 255,227,180; }  /* warm ivory: the calm one */
.msign--3 { --arm: 44px; --tube: #E0A419; --halo: 224,164,25; }   /* --fill, straight */
.msign--4 { --arm: 70px; --tube: #EF9A3F; --halo: 239,154,63; }   /* copper amber */

/* Light spilling off the sign onto the wall. Own layer, opacity-only. */
.msign::before {
  content: ""; position: absolute; left: -8%; right: -8%;
  top: var(--arm); bottom: -10%; pointer-events: none; opacity: .6;
  background: radial-gradient(60% 50% at 50% 34%, rgba(var(--halo), .22), transparent 72%);
  transition: opacity var(--dur) var(--ease);
}

.msign-plate {
  position: relative;
  padding: clamp(24px,3vw,32px) clamp(20px,2.6vw,28px) clamp(22px,2.8vw,30px);
  border-radius: var(--r);
  background:
    linear-gradient(180deg, rgba(48,35,25,.74), rgba(18,13,9,.90)),
    url('/assets/img/lib/texture/weathered-leather.webp');
  background-size: cover; background-position: 50% 30%;
  border: 1px solid rgba(224,164,25,.30);
  box-shadow:
    inset 0 1px 0 rgba(255,214,150,.12),
    0 18px 40px rgba(0,0,0,.52);
}

/* The glass tube tracing the plate. */
.msign-plate::before {
  content: ""; position: absolute; inset: 7px; pointer-events: none;
  border: 1.5px solid var(--tube);
  border-radius: calc(var(--r) - 5px);
  opacity: .78;
  box-shadow:
    0 0 6px rgba(var(--halo), .55),
    0 0 18px rgba(var(--halo), .30),
    inset 0 0 10px rgba(var(--halo), .18);
  transition: opacity var(--dur) var(--ease);
}

.msign-glyph { display: block; width: 44px; height: 44px; margin-bottom: 16px; color: var(--tube); }
.msign-glyph svg {
  width: 100%; height: 100%;
  fill: none; stroke: currentColor; stroke-width: 1.6;
  stroke-linecap: round; stroke-linejoin: round;
  filter:
    drop-shadow(0 0 2px rgba(255,246,228,.9))
    drop-shadow(0 0 8px rgba(var(--halo), .75))
    drop-shadow(0 0 20px rgba(var(--halo), .45));
}

/* Same five-layer tube glow as .sign-h (app.css:1420), re-tinted per sign.
   Overrides the global h1-h4 letter-spacing:-.02em — signage tracks OUT. */
.msign-name {
  font-family: 'Bebas', 'Jakarta', sans-serif; font-weight: 400;
  font-size: clamp(1.55rem, 3.4vw, 2.15rem); line-height: .96;
  letter-spacing: .028em; text-transform: uppercase;
  color: #FFF7E8;
  text-shadow:
    0 0 2px  rgba(255,248,232,.95),
    0 0 9px  rgba(var(--halo), .85),
    0 0 24px rgba(var(--halo), .52),
    0 0 52px rgba(var(--halo), .28);
}

/* The letter board — where the load-bearing copy lives now */
/* The letter board. Every trade its own object, because that is how someone
   finds themselves. The dashed rule is the seam between the neon and the placard. */
.msign-trades {
  display: flex; flex-wrap: wrap; gap: 7px;
  margin: 16px 0 0; padding: 14px 0 0; list-style: none;
  border-top: 1px dashed rgba(224,164,25,.26);
}
.msign-trades li {
  font-size: 13.5px; font-weight: 600; line-height: 1.25;
  color: #EFE7DA;                      /* 12.97:1 on the plate */
  background: rgba(255,242,220,.055);
  border: 1px solid rgba(224,164,25,.20);
  border-radius: 999px; padding: 6px 12px;
}

/* The argument, not the index. Prose is the right shape for it. */
.msign-note {
  margin-top: 16px; font-size: 14.5px; line-height: 1.55;
  color: #C6B9A8;                      /* 8.86:1 on the plate */
}

/* Four signs, four silhouettes */
/* 1 — cap-railed plate. Square shoulders, a lit rail across the top. */
.msign--1 .msign-plate {
  border-radius: 4px 4px var(--r) var(--r);
  box-shadow: inset 0 3px 0 rgba(var(--halo), .55),
              inset 0 1px 0 rgba(255,214,150,.12),
              0 18px 40px rgba(0,0,0,.52);
}
.msign--1 .msign-plate::before { border-radius: 2px 2px calc(var(--r) - 5px) calc(var(--r) - 5px); }

/* 2 — the dome. The only centred sign on the marquee. */
.msign--2 .msign-plate {
  border-radius: 120px 120px var(--r) var(--r);
  padding-top: clamp(40px, 5vw, 58px); text-align: center;
}
.msign--2 .msign-plate::before { border-radius: 116px 116px calc(var(--r) - 5px) calc(var(--r) - 5px); }
.msign--2 .msign-glyph  { margin-inline: auto; }
.msign--2 .msign-trades { justify-content: center; }

/* 3 — the gable. A hollow tube peak: rotated square, two borders.
   clip-path would have been simpler and would have eaten the glow. */
.msign--3 .msign-plate { border-radius: 3px 3px var(--r) var(--r); }
.msign--3 .msign-plate::before { border-radius: 2px 2px calc(var(--r) - 5px) calc(var(--r) - 5px); }
.msign-gable {
  position: absolute; left: 50%; top: calc(var(--arm) - 20px);
  width: 46px; height: 46px; margin-left: -23px; pointer-events: none;
  border-top: 2px solid var(--tube); border-right: 2px solid var(--tube);
  border-radius: 4px 6px 4px 0;
  transform: rotate(-45deg);
  box-shadow: 0 0 8px rgba(var(--halo), .5);
  opacity: .85;
}

/* 4 — the marquee box. Bulbs top and bottom, theatre-style. */
.msign--4 .msign-plate { border-radius: var(--r); padding-bottom: clamp(34px, 4vw, 44px); }
.msign--4 .msign-plate::after {
  content: ""; position: absolute; left: 14px; right: 14px; top: 15px; bottom: 15px;
  pointer-events: none;
  background-image:
    radial-gradient(circle 2.4px at 10px 0,    rgba(255,214,145,.95), transparent 62%),
    radial-gradient(circle 2.4px at 10px 100%, rgba(255,214,145,.95), transparent 62%);
  background-size: 20px 100%, 20px 100%;
  background-position: 0 0, 0 100%;
  background-repeat: repeat-x, repeat-x;
}

/* Hover, focus, and the hum */
@media (hover: hover) {
  .msign:hover { transform: translateY(-5px); }
  .msign:hover::before,
  .msign:hover .msign-plate::before { opacity: 1; }
}
.msign:focus-within { transform: translateY(-5px); }
.msign:focus-within::before,
.msign:focus-within .msign-plate::before { opacity: 1; }

/* --accent (#7F5D0E) is the LIGHT-surface gold. On this ground it is 3.06:1.
   --accent-hi is 10.4:1. Same fix is owed to .band-deep, .final and .hero. */
.marquee :focus-visible { outline-color: var(--accent-hi); }

/* The hum. One composited opacity cycle per sign, four phases, never in sync.
   The dip at 46% is the flicker a real tube has. */
@media (min-width: 900px) and (prefers-reduced-motion: no-preference) {
  .msign::before { animation: msignHum 9s ease-in-out infinite; will-change: opacity; }
  .msign--2::before { animation-duration: 11s;   animation-delay: -3.2s; }
  .msign--3::before { animation-duration: 8.2s;  animation-delay: -5.6s; }
  .msign--4::before { animation-duration: 12.4s; animation-delay: -1.4s; }
}
@keyframes msignHum {
  0%, 100% { opacity: .60; }
  42%      { opacity: .74; }
  46%      { opacity: .55; }
  50%      { opacity: .72; }
}

/* Reduced motion: the global rule at app.css:414 zeroes the duration, which
   would turn the hover lift into a jump. Remove the lift outright. */
@media (prefers-reduced-motion: reduce) {
  .msign, .msign:hover, .msign:focus-within { transform: none; }
}

/* 390px — what survives and what turns off */
@media (max-width: 900px) {
  .msigns { grid-template-columns: 1fr; gap: clamp(28px, 6vw, 40px); }
  .msign--1, .msign--2, .msign--3, .msign--4 { --arm: 24px; }

  .marquee-eave  { display: none; }
  .marquee-bulbs { top: 22px; opacity: .7; }
  .marquee-ground::after { height: 26%; }

  .msign--2 .msign-plate { border-radius: 80px 80px var(--r) var(--r); padding-top: 38px; }
  .msign--2 .msign-plate::before { border-radius: 76px 76px calc(var(--r) - 5px) calc(var(--r) - 5px); }
  .msign-gable { width: 34px; height: 34px; margin-left: -17px; top: calc(var(--arm) - 14px); }
  .msign--4 .msign-plate::after { background-size: 24px 100%, 24px 100%; }

  /* The whole mobile perf story in four lines: no bloom layer, and every
     large blur radius cut. Wide-radius shadows are the cost, not the count. */
  .msign::before { display: none; }
  .msign-name {
    text-shadow: 0 0 2px rgba(255,248,232,.95),
                 0 0 8px rgba(var(--halo), .80),
                 0 0 20px rgba(var(--halo), .40);
  }
  .msign-glyph svg { filter: drop-shadow(0 0 6px rgba(var(--halo), .70)); }
  .msign-plate { box-shadow: inset 0 1px 0 rgba(255,214,150,.12), 0 10px 24px rgba(0,0,0,.45); }

  .vac-plate { flex-wrap: wrap; justify-content: center; }
}

/* ---- the vacancy board, now living inside the marquee ----------------------
   It was its own dark section; folded in here it becomes the resort's front desk
   instead of a second, competing sign a screen later. Same metaphor, one place.
   The board keeps its own type and lamps; it just loses its ground to the marquee. */
.vac-in {
  margin-top: clamp(52px, 7vw, 88px);
  padding-top: clamp(40px, 5.5vw, 64px);
  border-top: 1px solid rgba(244,241,231,.14);
}
.vac-in .vac-head { margin-bottom: clamp(30px, 4vw, 48px); }

/* ---- vacancy board: taken and open are now two separate boards --------------
   One mixed list implied a closed set of ten. Splitting it, and adding the
   "every category not listed" row, makes the real position readable at a glance:
   seven are gone, everything else is available. */
/* The row that carries the correction. Full width, lit, and it closes the board. */

/* ---- HERO GOOGLE RATING -----------------------------------------------------
   Was a clause inside the micro line: true, but nothing a scanning eye stops on.
   As a badge directly under the ask it is the last thing read before the button,
   and it links out to the actual reviews so the claim is checkable in one tap.
   -------------------------------------------------------------------------- */
.grate {
  display: inline-flex; align-items: center; gap: 9px;
  margin-top: 18px; padding: 12px 17px 12px 14px;
  background: rgba(244,241,231,.06); border: 1px solid rgba(244,241,231,.19);
  border-radius: 999px; text-decoration: none; line-height: 1;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.grate:hover, .grate:focus-visible {
  background: rgba(244,241,231,.11); border-color: rgba(224,164,25,.65);
}
.grate-g { width: 17px; height: 17px; flex: 0 0 auto; }
.grate-stars { display: inline-flex; gap: 2px; }
.grate-stars svg { width: 15px; height: 15px; fill: var(--fill); }
.grate-n {
  font-size: 16px; font-weight: 800; color: #fff; letter-spacing: -.01em;
  font-variant-numeric: tabular-nums;
}
.grate-l { font-size: 13.5px; font-weight: 600; color: var(--ink-2-deep); }
.grate-arrow { display: inline-block; transition: transform var(--dur) var(--ease); }
.grate:hover .grate-arrow, .grate:focus-visible .grate-arrow { transform: translateX(3px); }
@media (prefers-reduced-motion: reduce) {
  .grate-arrow, .grate:hover .grate-arrow { transition: none; transform: none; }
}
@media (max-width: 420px) {
  .grate { gap: 7px; padding: 11px 14px 11px 11px; }
  .grate-stars svg { width: 13px; height: 13px; }
  .grate-l { font-size: 12.5px; }
}

/* ---- FOOTER SOCIAL ----------------------------------------------------------
   These three were already in the schema's sameAs, which means search engines
   knew about them and visitors did not. Real marks, 44px hit areas, and they
   inherit the footer's own colour so they read as part of the page rather than
   as pasted-in brand badges.
   -------------------------------------------------------------------------- */
.ftr-social { display: flex; gap: 8px; margin-top: 16px; }
.ftr-social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; margin: 0; padding: 0;
  border: 1px solid rgba(244,241,231,.20); border-radius: 50%;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease),
              transform var(--dur) var(--ease);
}
.ftr-social a:hover, .ftr-social a:focus-visible {
  border-color: var(--fill); background: rgba(224,164,25,.12); transform: translateY(-2px);
}
.ftr-social svg { width: 19px; height: 19px; fill: var(--ink-2-deep); transition: fill var(--dur) var(--ease); }
.ftr-social a:hover svg, .ftr-social a:focus-visible svg { fill: var(--accent-hi); }
@media (prefers-reduced-motion: reduce) {
  .ftr-social a, .ftr-social a:hover { transition: none; transform: none; }
}

/* ---- THE VERIFICATION PLATE -------------------------------------------------
   The only cool metal on an all-gold page. It should read as hardware screwed to
   the bottom of the sign, not as another lit element - that contrast is the whole
   point: the neon is theatre, the plate is the receipt.

   TAP-TARGET NOTE. The obvious way to give the phone link a 44px target is
   `padding:12px 8px; margin:-12px -8px`, and it is wrong here. Negative margins
   grow the hit box without moving the text, so the link silently overlaps the
   words around it and a thumb aimed at "and say so" dials the phone. The link is
   a block-level line of its own instead: real height, no overlap, nothing stolen
   from neighbouring copy.
   -------------------------------------------------------------------------- */
.bp {
  max-width: 62ch; margin: clamp(26px, 3.4vw, 40px) auto 0; padding: 18px 22px 20px;
  background: linear-gradient(157deg, #C9BFA6 0%, #B9AE93 42%, #A79B80 100%);
  border: 1px solid #8E836B; border-radius: 4px;
  box-shadow: inset 0 1px 0 rgba(255,252,240,.55), inset 0 -1px 0 rgba(0,0,0,.22),
              0 6px 18px rgba(0,0,0,.42);
  position: relative;
}
/* Two screws. Pure CSS - a 40-character plate does not justify an image request. */
.bp::before, .bp::after {
  content: ""; position: absolute; top: 9px; width: 6px; height: 6px; border-radius: 50%;
  background: radial-gradient(circle at 34% 30%, #F2EBDA, #8A7F67 70%);
  box-shadow: inset 0 0 0 .5px rgba(0,0,0,.35);
}
.bp::before { left: 9px; }
.bp::after  { right: 9px; }
.bp-eyebrow {
  font-size: 10.5px; font-weight: 800; letter-spacing: .2em; text-transform: uppercase;
  color: #6B6152; margin-bottom: 7px;
}
.bp-who  { font-size: 14.5px; line-height: 1.5; font-weight: 700; color: #241F18; }
.bp-date { font-weight: 800; white-space: nowrap; }
.bp-dare { font-size: 13.5px; line-height: 1.55; color: #4A4234; margin-top: 6px; }
/* Block-level: its own 44px line, so it can never overlap the sentence around it. */
.bp-tel {
  display: block; width: fit-content; min-height: 44px;
  display: flex; align-items: center;
  margin-top: 8px; font-weight: 800; color: #241F18;
  text-decoration: underline; text-underline-offset: 3px; text-decoration-thickness: 1.5px;
}
.bp-tel:hover { text-decoration-thickness: 2.5px; }
/* .marquee recolours :focus-visible to gold, which is ~2:1 on brass. Take it back. */
.marquee .bp :focus-visible { outline: 3px solid #17140E; outline-offset: 2px; }
/* Gone stale: JS adds this rather than letting an old date quietly keep claiming. */
.bp--stale .bp-date { text-decoration: line-through; opacity: .75; }
@media (max-width: 480px) { .bp { padding: 16px 18px 18px; } .bp-who { font-size: 14px; } }

/* ---- AVAILABILITY BOARD -----------------------------------------------------
   Three states, because there are three: wide open, Expert seat gone but standard
   slots free, and full. The old two-state board read TAKEN against six categories
   that can still be bought into, which was turning away business.

   Scanning: the status is stated ONCE per group instead of on every row. Ten
   repeated labels disappear and the eye lands on three headings and a set of names.
   Order is deliberate - opportunity first, the one full category last, where it
   reads as evidence the list is honest rather than as a wall.
   -------------------------------------------------------------------------- */
.vboard-wrap { max-width: 780px; margin: 0 auto; }
.vgroup { padding: 20px 0 22px; border-top: 1px solid rgba(244,241,231,.14); }
.vgroup:first-child { border-top: 0; padding-top: 0; }

.vgroup-h {
  display: flex; align-items: center; flex-wrap: wrap; gap: 0 12px;
  font-family: 'Bebas', 'Jakarta', sans-serif; font-size: clamp(1.15rem, 2.4vw, 1.5rem);
  letter-spacing: .045em; text-transform: uppercase; margin-bottom: 14px;
}
.vgroup--open .vgroup-h { color: #FFF7E6; }
.vgroup--part .vgroup-h { color: #E3D9CA; }
.vgroup--shut .vgroup-h { color: #9C9286; }
/* The qualifier that stops each heading being ambiguous. Sentence case on purpose:
   it is an explanation, not another label. */
.vgroup-note {
  font-family: 'Jakarta', sans-serif; font-size: 13px; font-weight: 600;
  letter-spacing: .01em; text-transform: none; color: #A89A8E;
}

/* The lamp carries the state visually so the heading does not have to be read first. */
.vlamp { width: 11px; height: 11px; border-radius: 50%; flex: 0 0 auto; }
.vlamp--on {
  background: var(--fill);
  box-shadow: 0 0 6px rgba(224,164,25,.95), 0 0 16px rgba(224,164,25,.6);
}
.vlamp--half {
  background: linear-gradient(90deg, var(--fill) 0 50%, #3A322C 50% 100%);
  box-shadow: 0 0 6px rgba(224,164,25,.45);
}
.vlamp--off { background: #3A322C; box-shadow: inset 0 1px 2px rgba(0,0,0,.8); }

.vchips { list-style: none; display: flex; flex-wrap: wrap; gap: 8px; margin: 0; padding: 0; }
.vchip {
  font-family: 'Jakarta', sans-serif; font-size: 14.5px; font-weight: 700;
  line-height: 1.2; padding: 10px 14px; border-radius: 999px;
  border: 1px solid rgba(244,241,231,.2); color: var(--parchment);
}
.vchip--open {
  color: #FFF7E6; border-color: rgba(224,164,25,.6); background: rgba(224,164,25,.13);
}
.vchip--any { border-style: dashed; }
.vchip--part { color: #E3D9CA; }
.vchip--shut { color: #9C9286; border-color: rgba(244,241,231,.14); }

@media (max-width: 560px) {
  .vgroup-h { font-size: 1.1rem; }
  .vgroup-note { flex-basis: 100%; }
  .vchip { font-size: 13.5px; padding: 9px 12px; }
}

/* ---- FOOTER CHAMBER MEMBERSHIPS --------------------------------------------
   Both chamber marks are dark ink on white, so on the near-black footer they get
   their own light plates rather than being knocked out or ghosted. Each links to
   the real member listing, which is what turns a badge into something checkable.
   -------------------------------------------------------------------------- */
.ftr-memb-lbl {
  margin-top: 22px; font-size: 11px; font-weight: 800; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-2-deep);
}
.ftr-memb { display: flex; align-items: stretch; gap: 10px; margin-top: 10px; }
.ftr-memb a {
  display: flex; align-items: center; justify-content: center;
  width: 84px; height: 84px; margin: 0; padding: 10px;
  background: #FFFFFF; border-radius: 8px;
  border: 1px solid rgba(244,241,231,.18);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.ftr-memb a:hover, .ftr-memb a:focus-visible {
  transform: translateY(-2px); box-shadow: 0 6px 18px rgba(0,0,0,.4);
}
.ftr-memb img { max-width: 100%; max-height: 100%; width: auto; height: auto; object-fit: contain; }
@media (prefers-reduced-motion: reduce) {
  .ftr-memb a, .ftr-memb a:hover { transition: none; transform: none; }
}

/* ============================================================================
   FILM BAND
   Click-to-play facade. A live YouTube iframe pulls roughly a megabyte of
   script on every page load whether or not anyone presses play, so the poster
   frame stands in until someone actually asks for the video. Sits directly
   under the hero and shares its --deep background, so the two read as one dark
   opening before the page turns light at THE SYSTEM.
   ========================================================================= */
.filmband { background: var(--deep); color: var(--ink-on-deep);
  border-top: 1px solid var(--line-deep); }
.filmband .wrap { max-width: 980px; }
.filmband-head { max-width: 44ch; margin-inline: auto; text-align: center;
  margin-bottom: 30px; }
.filmband-head .big { margin-bottom: 0; }

/* aspect-ratio, not a padding hack: the box is correct before the player loads,
   so the band never reflows and costs no layout shift. */
.ytf { position: relative; aspect-ratio: 16 / 9; overflow: hidden;
  border-radius: var(--r); border: 1px solid var(--line-deep); background: #0D0B09; }
.ytf > iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

.filmband-note { margin-top: 18px; text-align: center; color: var(--ink-2-deep);
  font-size: .92rem; }

/* ---- Pricing: the uncapped fourth option ---------------------------------
   Not a fourth tier card. A card sits in the comparison grid and implies a
   comparable number; the point of the block is that there is no ceiling to
   compare against, so it runs full width beneath the three. */
.tier-plus { margin-top: 22px; background: var(--deep); color: var(--ink-on-deep);
  border: 1px solid var(--deep); border-radius: var(--r); padding: 30px 34px;
  box-shadow: var(--shadow-lg);
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 28px; align-items: center; }
.tier-plus .tier-name { color: var(--accent-hi); }
.tier-plus h3 { font-size: clamp(1.3rem, 2.2vw, 1.7rem); font-weight: 800;
  letter-spacing: -.02em; margin-top: 8px; }
.tier-plus p { font-size: 15px; line-height: 1.6; color: var(--ink-2-deep);
  margin-top: 12px; max-width: 64ch; }
.tier-plus .btn { white-space: nowrap; }

@media (max-width: 760px) {
  .tier-plus { grid-template-columns: minmax(0, 1fr); gap: 22px; padding: 26px 24px; }
  .tier-plus .btn { width: 100%; }
}
