  * { box-sizing: border-box; }
  html, body { margin: 0; padding: 0; }
  body { background: var(--surface-page); color: var(--text-primary); font-family: var(--font-body); -webkit-font-smoothing: antialiased; padding-bottom: 0.5rem; }
  a { color: var(--ink); text-decoration: none; }
  ::selection { background: var(--gold); color: var(--cream); }
  img { max-width: 100%; }

  /* ---- motion ----
     Scroll reveal + hover polish. Everything is progressive enhancement: elements are
     fully visible by default and JS only opts them into the hidden start state, so a
     script failure can never leave content invisible. All of it is disabled under
     prefers-reduced-motion. */
  /* Desktop only: no scroll reveal or hover motion on tablet/mobile. */
  @media (min-width: 1025px) {
    .reveal, .reveal-clip { opacity: 1; }

    /* text + block reveal. --i is set per element by JS, so the stagger scales to any
       number of children instead of stopping at nth-child(5). */
    .js-motion .reveal { opacity: 0; transform: translateY(2.25rem); filter: blur(0.375rem); }
    .js-motion .reveal.in { opacity: 1; transform: none; filter: blur(0);
      transition: opacity .8s cubic-bezier(.22,.61,.36,1), transform .8s cubic-bezier(.22,.61,.36,1), filter .8s cubic-bezier(.22,.61,.36,1);
      transition-delay: calc(var(--i, 0) * .1s); }

    .js-motion .reveal-group > * { opacity: 0; transform: translateY(2rem); filter: blur(0.3125rem); }
    .js-motion .reveal-group.in > * { opacity: 1; transform: none; filter: blur(0);
      transition: opacity .75s cubic-bezier(.22,.61,.36,1), transform .75s cubic-bezier(.22,.61,.36,1), filter .75s cubic-bezier(.22,.61,.36,1);
      transition-delay: calc(var(--i, 0) * .1s); }

    /* Image wipe. Deliberately applied to the image WRAPPER, never the image itself,
       so it cannot fight the hover zoom transforms further down. */
    .js-motion .reveal-clip { clip-path: inset(0 100% 0 0); }
    .js-motion .reveal-clip.in { clip-path: inset(0 0 0 0);
      transition: clip-path 1.05s cubic-bezier(.65,0,.35,1); transition-delay: calc(var(--i, 0) * .1s); }

    /* Hero opening timeline. The hero is above the fold, so it plays on load rather
       than on scroll: copy staggers up while the photo wipes in and settles out of a
       slow push in. */
    .js-motion .hero-el { opacity: 0; transform: translateY(1.75rem); filter: blur(0.3125rem); }
    .js-motion .hero-ready .hero-el { opacity: 1; transform: none; filter: blur(0);
      transition: opacity .8s cubic-bezier(.22,.61,.36,1), transform .8s cubic-bezier(.22,.61,.36,1), filter .8s cubic-bezier(.22,.61,.36,1);
      transition-delay: calc(0.1s + var(--i, 0) * .11s); }
    .js-motion .hero-scene { clip-path: inset(0 100% 0 0); }
    .js-motion .hero-ready .hero-scene { clip-path: inset(0 0 0 0);
      transition: clip-path 1.15s cubic-bezier(.65,0,.35,1); transition-delay: .18s; }
    .js-motion .hero-scene image-slot { transform: scale(1.14); transform-origin: 50% 55%; }
    .js-motion .hero-ready .hero-scene image-slot { transform: scale(1);
      transition: transform 1.9s cubic-bezier(.22,.61,.36,1); transition-delay: .18s; }
    .js-motion .hero-tag { opacity: 0; transform: translateY(0.75rem) scale(.94); }
    .js-motion .hero-ready .hero-tag { opacity: 1; transform: none;
      transition: opacity .6s ease, transform .6s cubic-bezier(.34,1.56,.64,1); transition-delay: 1.25s; }

    /* card + image hover polish */
    .work-shot img, .ba-shot img { transition: transform .6s cubic-bezier(.22,.61,.36,1); }
    .work-slide:hover .work-shot img { transform: scale(1.04); }
    .grid-services4 article { transition: transform .35s ease, box-shadow .35s ease; }
    .grid-services4 article:hover { transform: translateY(-0.375rem); box-shadow: 0 1.75rem 3rem -1.5rem rgba(35,40,45,0.5); }
    .grid-services4 article img, .grid-services4 article image-slot { transition: transform .6s cubic-bezier(.22,.61,.36,1); }
    .grid-services4 article:hover image-slot { transform: scale(1.05); }
    .grid-pillars4 > div, .grid-cards3 > div { transition: transform .3s ease, box-shadow .3s ease; }
    .grid-pillars4 > div:hover, .grid-cards3 > div:hover { transform: translateY(-0.25rem); box-shadow: var(--shadow-card); }
    /* nav + buttons */
    .btn-gold { transition: background .2s ease, transform .2s ease, box-shadow .2s ease; }
    .btn-gold:hover { transform: translateY(-0.125rem); box-shadow: 0 0.75rem 1.5rem -0.5rem rgba(35,40,45,0.35); }
    .social-btn { transition: background .2s ease, transform .2s ease; }
    .social-btn:hover { transform: translateY(-0.125rem); }
    .hero-play-ring { transition: transform .35s cubic-bezier(.22,.61,.36,1), background .25s ease; }
    .hero-play:hover .hero-play-ring { transform: scale(1.09); background: var(--cream); }
    /* Lucide swaps each <i> for an <svg>, so both selectors are required here. */
    .btn-gold i, .btn-gold svg, .secondary-link i, .secondary-link svg { transition: transform .3s cubic-bezier(.22,.61,.36,1); }
    .btn-gold:hover i, .btn-gold:hover svg, .secondary-link:hover i, .secondary-link:hover svg { transform: translateX(0.1875rem); }

    @media (prefers-reduced-motion: reduce) {
      .js-motion .reveal, .js-motion .reveal-group > *, .js-motion .hero-el,
      .js-motion .hero-tag { opacity: 1 !important; transform: none !important; filter: none !important; transition: none !important; }
      .js-motion .reveal-clip, .js-motion .hero-scene { clip-path: none !important; transition: none !important; }
      .js-motion .hero-scene image-slot { transform: none !important; transition: none !important; }
      .work-shot img, .ba-shot img, .grid-services4 article, .btn-gold, .social-btn, .hero-play-ring,
      .btn-gold i, .btn-gold svg, .secondary-link i, .secondary-link svg { transition: none !important; }
      .hero-play:hover .hero-play-ring { transform: none !important; }
      .work-slide:hover .work-shot img, .grid-services4 article:hover, .grid-services4 article:hover image-slot,
      .grid-pillars4 > div:hover, .grid-cards3 > div:hover, .btn-gold:hover, .social-btn:hover,
      .btn-gold:hover i, .btn-gold:hover svg, .secondary-link:hover i, .secondary-link:hover svg { transform: none !important; }
    }
  }

  /* ---- shared interactive states ---- */
  .navlink[aria-current="page"] { color: var(--gold-on-dark); }
  .navlink { color: var(--on-dark-dim); font-size: var(--text-nav); font-weight: var(--fw-medium); background-image: linear-gradient(var(--gold-soft),var(--gold-soft)); background-repeat: no-repeat; background-position: 0 100%; background-size: 0% 0.125rem; padding-bottom: 0.1875rem; transition: background-size .3s ease, color .2s ease; }
  .navlink:hover { background-size: 100% 0.125rem; color: var(--cream); }
  .btn-gold { transition: background .2s ease; }
  .btn-gold:hover { background: var(--gold-hover) !important; }
  .secondary-link { border-bottom: 0.125rem solid var(--divider-line); transition: border-color .2s; }
  .secondary-link:hover { border-bottom-color: var(--gold); }

  /* ---- hero video trigger + modal ----
     The trigger is an <a> pointing straight at the mp4, so with no JS the video still
     plays. JS upgrades it into the modal below. */
  .hero-play { position: absolute; inset: 0; z-index: 3; display: flex; flex-direction: column;
    align-items: center; justify-content: center; gap: 0.875rem; text-decoration: none;
    background: linear-gradient(to bottom, rgba(20,22,24,0) 35%, rgba(20,22,24,0.42) 100%); }
  .hero-play-ring { width: 5rem; height: 5rem; border-radius: var(--radius-pill); background: rgba(252,250,246,0.94);
    display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0;
    box-shadow: 0 1.25rem 2.5rem -0.75rem rgba(20,22,24,0.6); }
  /* Lucide replaces the <i> with an <svg>, so both selectors are needed. */
  .hero-play-ring i, .hero-play-ring svg { width: 1.75rem; height: 1.75rem; color: var(--ink);
    fill: var(--ink); margin-left: 0.1875rem; }
  .hero-play-text { color: var(--cream); font-size: 0.875rem; font-weight: var(--fw-bold);
    letter-spacing: 0.04em; text-transform: uppercase; text-align: center; padding: 0 1rem;
    text-shadow: 0 0.0625rem 0.5rem rgba(20,22,24,0.55); }
  @media (max-width: 560px) {
    .hero-play-ring { width: 4rem; height: 4rem; }
    .hero-play-ring i, .hero-play-ring svg { width: 1.375rem; height: 1.375rem; }
    .hero-play-text { font-size: 0.75rem; }
  }

  .vmodal { position: fixed; inset: 0; z-index: 200; display: none; align-items: center; justify-content: center;
    padding: 1.25rem; background: rgba(12,14,16,0.9); }
  .vmodal.open { display: flex; }
  .vmodal-inner { position: relative; width: min(75rem, 100%); }
  .vmodal video { display: block; width: 100%; height: auto; max-height: 80vh; background: #000;
    border-radius: var(--radius-lg); box-shadow: 0 2rem 4rem -1rem rgba(0,0,0,0.7); }
  .vmodal-close { position: absolute; top: 1rem; right: 1rem; width: 2.75rem; height: 2.75rem; padding: 0;
    border: 0; border-radius: var(--radius-pill); background: rgba(252,250,246,0.16); color: var(--cream);
    display: inline-flex; align-items: center; justify-content: center; cursor: pointer; }
  .vmodal-close:hover { background: rgba(252,250,246,0.3); }
  .vmodal-close i, .vmodal-close svg { width: 1.375rem; height: 1.375rem; }
  /* Scroll lock while the modal is open. Removed on close so the sticky header keeps working. */
  .modal-open { overflow: hidden; }
  @media (max-width: 560px) { .vmodal { padding: 0.75rem; } .vmodal video { max-height: 72vh; } }

  /* ---- fluid display type (moved out of inline styles so mobile can override) ---- */
  /* max-width in em keeps the headline clear of the overhanging hero house at every
     size (it scales with the fluid font size) and stops over-long display lines. */
  /* 8.6em was tight enough to force three ragged lines and strand "Trusted" on its own.
     A slightly wider measure lets text-wrap:balance do its job on the statement, and the
     date sits under it as its own deliberate line rather than as leftover wrap. */
  .hero-h1 { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--text-h1); line-height: var(--lh-display); letter-spacing: var(--tracking-tight); color: var(--ink); text-wrap: balance; margin: 1rem 0 0; max-width: 10.5em; }
  .hero-h1-date { display: block; color: var(--gold); }
  .hero-sub { max-width: 23.5em; margin-top: 1rem !important; }
  /* Tighter vertical rhythm in the copy column. It is the copy, not the image, that
     dictates the hero's height, so trimming it here is what stops the photo panel
     from being stretched into an over-tall sliver. */
  .hero-copy { gap: 1.375rem; }
  .hero-copy .grid-stats3 { margin-top: 1.375rem; gap: 0.75rem; }
  .hero-copy .grid-stats3 > div { padding: 0.875rem 0.875rem; }
  /* "2nd Generation" is the longest of the three stat labels and was wrapping to two
     lines. Size it off the card itself so it stays as large as it can while always
     sitting on one line, capped at the sibling size so it never looks bigger. */
  .grid-stats3 > div { container-type: inline-size; }
  /* All three stat titles share this, so they always resolve to the same size: the
     cards are equal width, so equal cqi in, equal size out. The longest label
     ("2nd Generation") is what the ceiling has to clear. */
  .stat-fit { white-space: nowrap; font-size: clamp(0.75rem, 13cqi, 1.6875rem) !important; }
  /* Narrow desktop is where the three cards are tightest, so buy back some width
     from the padding rather than shrinking the type further. */
  @media (min-width: 1025px) and (max-width: 1200px) {
    .hero-copy .grid-stats3 > div { padding: 0.875rem 0.625rem; }
  }
  /* Eyebrow labels: plain styled text, NOT a pill. A pill background reads as a
     button/tag and invites clicks these are not; it also floated on the tan page
     background and got lost. A short gold rule anchors it visually instead. */
  .eyebrow { display: block; color: var(--gold-deep); font-size: var(--text-eyebrow-size); font-weight: var(--fw-bold); letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; }
  .eyebrow-center { text-align: center; }
  .eyebrow-on-dark { color: var(--gold-on-dark); }
  /* Section intros span the full content width (same as the card grids below). The
     heading keeps a tighter measure so it still breaks into balanced lines instead of
     one very long one. */
  .section-h2 { max-width: 20em; font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--text-h2); line-height: 1.04; letter-spacing: var(--tracking-tight); color: var(--ink); text-wrap: balance; margin: 1.25rem auto 0; }
  @media (max-width: 380px) {
    .hero-h1 { font-size: 2rem; }
    .section-h2 { font-size: 1.6875rem; }
  }

  /* ---- responsive grids (base = desktop; overridden below) ---- */
  /* Hero. The backdrop stays clipped inside the rounded panel; the house is a
     transparent cutout layered on top so it can spill past the panel's LEFT edge
     only (never past the top, bottom or right). */
  .grid-hero { display: grid; grid-template-columns: 1fr 0.85fr; min-height: 37.5rem; overflow: hidden; }
  /* ---- inner pages ----
     Same fold construction as the homepage so the pages read as one site: the hero is the
     same two column card, just shorter because there are no stat cards or video to hold. */
  .grid-hero.page-hero { min-height: 26rem; }
  /* The homepage hero caps the h1 at 10.5em and the sub at 23.5em because that column also
     carries the stat cards and the copy has to sit above them. Inner-page heroes have no
     stat row, so those caps just leave the right half of the column empty. */
  .page-hero .hero-h1 { max-width: none; }
  .page-hero .hero-sub { max-width: none; }
  .grid-hero.page-hero .hero-photo { min-height: 23rem; }
  /* Full gallery: the homepage shows a carousel, a listing page shows everything at once.
     Reuses .work-shot / .work-cap so the tiles are identical to the homepage slides. */
  .work-grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 1.25rem; }
  .work-grid .work-slide { flex: none; }
  /* FAQ accordion. <details> so it works with no JS at all. */
  .faq-group { max-width: 52rem; margin: 0 auto; background: var(--surface-card);
    border: 0.0625rem solid var(--card-border); border-radius: var(--radius-lg);
    padding: 0.5rem 2.25rem; box-shadow: var(--shadow-card); }
  .faq-item:last-child { border-bottom: none; }
  @media (max-width: 560px) { .faq-group { padding: 0.5rem 1.25rem; } }
  .faq-item { border-bottom: 0.0625rem solid var(--card-border); }
  .faq-item summary { cursor: pointer; list-style: none; display: flex; align-items: flex-start; justify-content: space-between; gap: 1.25rem;
    padding: 1.375rem 0; font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 1.0625rem; color: var(--ink); line-height: 1.35; }
  .faq-item summary::-webkit-details-marker { display: none; }
  .faq-item summary::after { content: ""; flex-shrink: 0; width: 0.75rem; height: 0.75rem; margin-top: 0.3125rem;
    border-right: 0.125rem solid var(--gold-deep); border-bottom: 0.125rem solid var(--gold-deep);
    transform: rotate(45deg); transition: transform .25s ease; }
  .faq-item[open] summary::after { transform: rotate(-135deg); }
  .faq-item summary:hover { color: var(--gold-deep); }
  .faq-item .faq-a { padding: 0 0 1.375rem; color: var(--text-body); font-size: var(--text-card); line-height: var(--lh-body); max-width: 46rem; }
  .faq-item .faq-a p { margin: 0 0 0.75rem; color: var(--text-body); font-size: var(--text-card); line-height: var(--lh-body); }
  .faq-item .faq-a p:last-child { margin-bottom: 0; }
  /* The live caption sits on the pine band on the listing page, where the default
     body colour disappears. */
  .ba-on-dark .ba-caption-live { color: var(--on-dark-dim); }
  /* Resource / article cards */
  .res-grid { display: grid; grid-template-columns: repeat(3, minmax(0,1fr)); gap: 1.25rem; }
  .res-card { display: flex; flex-direction: column; background: var(--surface-card); border: 0.0625rem solid var(--card-border);
    border-radius: var(--radius-lg); padding: 1.625rem 1.5rem; box-shadow: var(--shadow-card); }
  /* Photo across the top of an icon card, edge to edge. Negative margins cancel the
     card padding so it meets the rounded corners cleanly. */
  .card-media { display: block; max-width: none; width: calc(100% + 3rem); margin: -1.75rem -1.5rem 1.25rem;
    aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
  .res-media { display: block; max-width: none; width: calc(100% + 3rem); margin: -1.625rem -1.5rem 1.25rem;
    aspect-ratio: 3 / 2; object-fit: cover;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0; }
  .res-card .res-kicker { display: block; color: var(--gold-deep); font-size: 0.8125rem; font-weight: var(--fw-bold);
    letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; }
  .res-card h3 { margin: 0.625rem 0 0; font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 1.125rem; color: var(--ink); line-height: 1.25; }
  .res-card p { margin: 0.75rem 0 0; color: var(--text-body); font-size: var(--text-card); line-height: 1.6; }
  .res-card .res-link { display: inline-flex; align-items: center; gap: 0.5rem; align-self: flex-start; margin-top: auto;
    padding: 1.25rem 0 0.1875rem; color: var(--ink); font-weight: var(--fw-bold); font-size: var(--text-card); border-bottom: 0.125rem solid var(--gold); }
  .res-card .res-link:hover { border-bottom-color: var(--ink); }
  @media (max-width: 1024px) { .work-grid, .res-grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }
  @media (max-width: 640px)  { .work-grid, .res-grid { grid-template-columns: 1fr; } }
  .hero-section { padding: 0.625rem 0 0; }
  /* ---- section rhythm ----
     One rule, whole site. The gap lives on the margin BETWEEN two sections, so it is the
     same value everywhere and can never double the way padding on both sides does.
     Coloured bands add their own internal padding on top; plain sections need none. */
  section + section,
  section + footer { margin-top: var(--section-gap); }
  .band { padding-block: var(--band-pad); }
  /* Two coloured bands in a row meet directly: a cream strip between them reads as a
     mistake, and each band already has its own internal padding. */
  .band + .band,
  .band + footer { margin-top: 0; }   /* both dark, so they meet flush */
  @media (max-width: 640px) {
    :root { --section-gap: 2.5rem; --band-pad: 3rem; }
  }
  .hero-photo { position: relative; min-height: 33.75rem; min-width: 0; }
  .hero-scene { position: absolute; inset: 0; overflow: hidden; }
  .hero-tag {
    position: absolute; left: 1.375rem; bottom: 1.375rem; z-index: 2; pointer-events: none;
    display: inline-flex; align-items: center; gap: 0.5625rem;
    background: rgba(35,40,45,0.78); backdrop-filter: blur(0.1875rem);
    color: var(--on-dark); padding: 0.5625rem 1rem; border-radius: var(--radius-pill);
    font-size: 0.8125rem; font-weight: var(--fw-semibold); letter-spacing: 0.02em;
  }
  .hero-tag span { width: 0.375rem; height: 0.375rem; border-radius: var(--radius-pill); background: var(--gold-soft); flex-shrink: 0; }
  /* Mobile: keep the house fully inside the panel so nothing can cause overflow. */
  .grid-stats3 { display: grid; grid-template-columns: repeat(3,1fr); gap: 0.875rem; margin-top: 2rem; }
  .grid-credibility { display: grid; grid-template-columns: repeat(4,1fr); gap: 1.375rem; }
  .grid-cards3 { display: grid; grid-template-columns: repeat(3,1fr); gap: 1.5rem; }
  /* Who We Help cards lead with a photo. The card clips it, so the image needs no
     radius of its own, and .who-body carries the padding the card used to have. */
  .who-shot { position: relative; aspect-ratio: 3 / 2; overflow: hidden; }
  .who-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .who-body { padding: 1.5rem 1.75rem 1.875rem; }
  .who-body h3 { margin-top: 0 !important; }
  .grid-services4 { display: grid; grid-template-columns: repeat(4,1fr); gap: 1.25rem; }
  .grid-reviews3 { display: grid; grid-template-columns: repeat(3,1fr); gap: 1.25rem; align-items: start; }
  @media (max-width: 1100px) { .grid-services4 { grid-template-columns: repeat(2,1fr); } }
  @media (max-width: 560px)  { .grid-services4 { grid-template-columns: 1fr; } }
  .grid-pillars4 { display: grid; grid-template-columns: repeat(4,1fr); gap: 1.25rem; }
  .grid-process5 { display: grid; grid-template-columns: repeat(5,1fr); gap: 1.25rem; }
  .grid-footer { display: grid; grid-template-columns: 1.3fr 1fr 1fr; gap: 2.5rem; }
  /* Flex columns default to align-items:stretch, which was stretching each .navlink
     to the full column width - so its hover underline (background-size:100%) drew
     under the whole column instead of just the link text. flex-start lets each
     link shrink to its own text width. */
  .footer-col-links, .footer-col-contact { align-items: flex-start; }
  .grid-story { display: grid; grid-template-columns: 1fr; }
  .story-chip { display: inline-flex; align-items: center; background: var(--sand); border: 0.0625rem solid var(--border-sand); color: var(--text-body-soft); padding: 0.4375rem 0.875rem; border-radius: var(--radius-pill); font-size: 0.8125rem; font-weight: var(--fw-medium); }
  /* One line on screens wide enough to fit it; wraps normally below that so it can
     never force horizontal overflow on narrow phones. */
  @media (min-width: 30rem) { .final-cta-sub { max-width: none; white-space: nowrap; } }

  /* ---- contact panel ---- */
  .contact-panel { display: grid; grid-template-columns: 1fr 1fr; gap: 0; background: var(--ink); border-radius: var(--radius-xl); overflow: hidden; }
  .contact-info { padding: clamp(2rem,4vw,3.25rem); }
  .contact-lines { display: flex; flex-direction: column; gap: 1rem; margin-top: 2rem; }
  .contact-line { display: flex; align-items: flex-start; gap: 0.875rem; color: var(--on-dark); }
  .contact-ico { width: 2.5rem; height: 2.5rem; flex-shrink: 0; border-radius: var(--radius-pill); background: rgba(201,170,121,0.16); display: inline-flex; align-items: center; justify-content: center; }
  .contact-ico i, .contact-ico svg { width: 1.125rem; height: 1.125rem; color: var(--gold-on-dark); }
  .contact-line strong { display: block; font-size: 1rem; font-weight: var(--fw-semibold); }
  .contact-line em { display: block; font-style: normal; color: var(--on-dark-dim); font-size: 0.875rem; margin-top: 0.125rem; }
  .contact-map { margin-top: 2rem; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 16 / 9; background: rgba(247,244,239,0.06); }
  .contact-map iframe { width: 100%; height: 100%; border: 0; display: block; filter: grayscale(0.25); }

  .contact-form-card { background: var(--surface-card); padding: clamp(2rem,4vw,3.25rem); }
  .contact-form { display: flex; flex-direction: column; gap: 1rem; }
  .contact-form label { display: block; font-size: 0.875rem; font-weight: var(--fw-semibold); color: var(--ink); }
  .contact-form input, .contact-form select, .contact-form textarea {
    width: 100%; margin-top: 0.4375rem; padding: 0.75rem 0.875rem; font-family: var(--font-body); font-size: 1rem;
    color: var(--ink); background: var(--cream); border: 0.0625rem solid var(--border-sand);
    border-radius: var(--radius-sm); transition: border-color .15s ease, box-shadow .15s ease;
  }
  .contact-form textarea { resize: vertical; }
  .contact-form input:focus, .contact-form select:focus, .contact-form textarea:focus {
    outline: none; border-color: var(--gold); box-shadow: 0 0 0 0.1875rem rgba(184,153,106,0.22);
  }
  .field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
  .contact-submit { display: inline-flex; align-items: center; justify-content: center; gap: 0.75rem; margin-top: 0.25rem; background: var(--gold); color: var(--ink); border: none; cursor: pointer; font-family: var(--font-body); font-size: 1rem; font-weight: var(--fw-bold); padding: 0.875rem 1.5rem; border-radius: var(--radius-pill); }
  .contact-submit-ico { color: var(--cream); width: 1.875rem; height: 1.875rem; border-radius: var(--radius-pill); background: var(--ink); display: inline-flex; align-items: center; justify-content: center; flex-shrink: 0; }
  .contact-submit-ico i, .contact-submit-ico svg { width: 0.9375rem; height: 0.9375rem; color: var(--cream); }
  .form-note { margin: 0.25rem 0 0; font-size: 0.875rem; color: var(--text-muted); }
  @media (max-width: 1024px) { .form-note { text-align: center; } }
  .form-note a { color: var(--ink); font-weight: var(--fw-semibold); text-decoration: underline; text-underline-offset: 0.125rem; }
  /* Honeypot: off-screen rather than display:none, which some bots skip. */
  .hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
  .form-status { margin: 0.75rem 0 0; font-size: var(--text-card); line-height: 1.55; padding: 0.75rem 0.9375rem; border-radius: var(--radius-md, 0.5rem); }
  .form-status.is-ok { background: var(--chip-bg); color: var(--ink); }
  .form-status.is-error { background: #FBECEC; color: #8A2020; }
  .contact-submit[disabled] { opacity: 0.65; pointer-events: none; }
  @media (max-width: 900px) {
    .contact-panel { grid-template-columns: 1fr; }
  }
  @media (max-width: 480px) { .field-row { grid-template-columns: 1fr; } }

  /* ---- Our Work slider ---- */
  /* No-JS fallback: a horizontally scrollable row so every project is still reachable.
     JS upgrades it to an infinite autoplaying track. */
  .work-carousel { position: relative; }
  /* No border-radius here. The viewport clips with overflow:hidden, so a radius on it
     rounds the CLIP, and the tile shadows get cut along that curve -- which reads as a
     rounded panel behind the captions at the outer edges. Each photo is rounded on its
     own via .work-shot, so the container does not need it. */
  .work-viewport { overflow-x: auto; overflow-y: hidden; -webkit-overflow-scrolling: touch; scrollbar-width: none; }
  .work-viewport::-webkit-scrollbar { display: none; }
  .work-carousel.is-armed .work-viewport { overflow-x: hidden; }
  .work-track { display: flex; gap: 1.25rem; }
  .work-slide { flex: 0 0 calc((100% - 2.5rem) / 3); min-width: 0; }
  /* Deliberately NOT --shadow-photo here: that shadow is offset 1.5rem down with a large
     blur, which spills below the tile and reads as a rounded card sitting behind the
     caption. The rounding should belong to the photo only. */
  .work-shot { position: relative; border-radius: var(--radius-lg); overflow: hidden; aspect-ratio: 4 / 3; box-shadow: 0 0.5rem 1rem -0.6875rem rgba(35,40,45,0.32); }
  .work-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .work-cap { margin-top: 0.875rem; }
  .work-cap strong { display: block; font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 1.0625rem; color: var(--ink); }
  .work-cap span { color: var(--text-muted); font-size: 0.875rem; }
  /* Arrows sit on the IMAGE row. `top` is set from JS to half the photo height, because
     centring on the whole card would drop them below the midpoint once the caption is
     counted. Half the circle hangs outside the panel edge. */
  .work-arrow { display: none; }
  .work-arrow.is-armed { position: absolute; top: 50%; transform: translateY(-50%); z-index: 4; display: inline-flex; align-items: center; justify-content: center; width: 2.75rem; height: 2.75rem; border-radius: var(--radius-pill); background: var(--ink); border: 0.125rem solid var(--cream); color: var(--cream); cursor: pointer; box-shadow: var(--shadow-nav); transition: background .18s ease, border-color .18s ease; }
  .work-arrow.work-prev { left: -1.375rem; }
  .work-arrow.work-next { right: -1.375rem; }
  .work-arrow.is-armed:hover { background: var(--gold); border-color: var(--gold); color: var(--ink); }
  .work-arrow i, .work-arrow svg { width: 1.375rem; height: 1.375rem; }
  @media (max-width: 900px) { .work-slide { flex-basis: calc((100% - 1.25rem) / 2); } .work-arrow.is-armed { display: none; } }
  @media (max-width: 620px) { .work-slide { flex-basis: 85%; } }

  /* ---- before / after pairs ---- */
  /* No-JS fallback: pairs stack one per row (three across made each shot ~186px, too
     small to read). JS then turns this into a sliding one-at-a-time carousel, keeping
     the photos full size while cutting the section to a single pair's height. */
  .ba-list { display: grid; gap: 2.75rem; max-width: 70rem; margin: 0 auto; }
  .ba-tabs, .ba-arrow { display: none; }

  /* ---- armed carousel ---- */
  /* Arrows overlay the viewport edges (not beside it) so the photos keep full width. */
  .ba-carousel { position: relative; max-width: 70rem; margin: 0 auto; }
  .ba-viewport { overflow: hidden; min-width: 0; }   /* radius removed: see .work-viewport */
  .ba-list.ba-sliding { display: flex; gap: 0; grid-auto-flow: column; max-width: none; margin: 0; transition: transform .5s cubic-bezier(.4,0,.2,1); will-change: transform; }
  .ba-list.ba-sliding .ba-pair { flex: 0 0 100%; min-width: 0; }
  /* Fully hidden (not just the strong title) once armed: a visible caption inside the
     sliding item added height to .ba-viewport, which pushed the arrows' 50% vertical
     centre down below the middle of the PHOTOS - the caption text was being counted
     in the box the arrows centre against. The single .ba-caption-live element below
     replaces it, sitting outside .ba-carousel so it cannot affect arrow centring. */
  .ba-list.ba-sliding figcaption { display: none; }
  .ba-count { display: none; text-align: center; margin: 0.875rem 0 0; font-size: 0.8125rem;
    font-weight: var(--fw-bold); letter-spacing: var(--tracking-eyebrow); text-transform: uppercase;
    color: var(--text-muted); }
  .ba-count.is-armed { display: block; }
  .ba-on-dark .ba-count { color: var(--gold-on-dark); }
  .ba-caption-live { display: none; margin: 1.125rem 0 0; text-align: center; color: var(--text-body); font-size: var(--text-card); line-height: var(--lh-body); }
  .ba-caption-live.is-armed { display: block; }

  /* One scrollable row, never a wrapping block. With twelve transformations the wrapped
     version ran to two rows on desktop and (with the old mobile rule) twelve stacked
     full-width pills on phones, which is what made the section feel endless. */
  .ba-tabs.is-armed { display: flex; flex-wrap: nowrap; justify-content: flex-start; gap: 0.625rem;
    max-width: 70rem; margin: 0 auto 2rem; overflow-x: auto; scrollbar-width: none;
    -webkit-overflow-scrolling: touch; scroll-snap-type: x proximity; padding-bottom: 0.25rem; }
  .ba-tabs.is-armed::-webkit-scrollbar { display: none; }
  /* With twelve tabs the strip always overflows, and a hard clip mid-pill reads as broken.
     A mask fades both ends instead, which says "there is more this way" and works on any
     background colour (a gradient overlay would have to match pine vs cream per section). */
  .ba-tabs.is-armed { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 2rem, #000 calc(100% - 2rem), transparent 100%);
    mask-image: linear-gradient(to right, transparent 0, #000 2rem, #000 calc(100% - 2rem), transparent 100%);
    scroll-padding-inline: 2rem; padding-inline: 0.25rem; }

  /* In a nowrap strip the flex items shrink by default, which wrapped each label onto
     two or three lines; a pill radius on a tall box then renders as a circle. Lock the
     tabs to their content width and keep every label on one line. */
  .ba-tab { scroll-snap-align: center; flex: 0 0 auto; white-space: nowrap; }
  /* Centre the row when the tabs happen to fit, left-align when they overflow. */
  @media (min-width: 1200px) { .ba-tabs.is-armed { justify-content: safe center; } }
  .ba-tab { font-family: var(--font-body); font-size: 0.9375rem; font-weight: var(--fw-semibold); color: var(--text-body); background: var(--surface-card); border: 0.0625rem solid var(--card-border); padding: 0.6875rem 1.25rem; border-radius: var(--radius-pill); cursor: pointer; transition: background .18s ease, color .18s ease, border-color .18s ease; }
  .ba-tab:hover { border-color: var(--gold); }
  .ba-tab[aria-selected="true"] { background: var(--ink); border-color: var(--ink); color: var(--on-dark); }

  /* Straddles the photo edge: offset is exactly half the circle's own width/height,
     so half sits on the image and half sits outside it. Ink fill (not a light chip)
     so it reads clearly against any photo, bright or dark, underneath it. */
  .ba-arrow.is-armed { position: absolute; top: 50%; left: auto; right: auto; transform: translateY(-50%); z-index: 4; display: inline-flex; align-items: center; justify-content: center; width: 2.75rem; height: 2.75rem; border-radius: var(--radius-pill); background: var(--ink); border: 0.125rem solid var(--cream); color: var(--cream); cursor: pointer; box-shadow: var(--shadow-nav); transition: background .18s ease, border-color .18s ease, transform .18s ease; }
  .ba-arrow.ba-prev { left: -1.375rem; }
  .ba-arrow.ba-next { right: -1.375rem; }
  .ba-arrow.is-armed:hover { background: var(--gold); border-color: var(--gold); color: var(--ink); transform: translateY(-50%) scale(1.06); }
  .ba-arrow i, .ba-arrow svg { width: 1.375rem; height: 1.375rem; color: currentColor; }
  @media (max-width: 760px) { .ba-arrow.is-armed { display: none; } }  /* swipe instead */
  .ba-pair { margin: 0; }
  .ba-shots { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem; }
  .ba-shot { position: relative; border-radius: var(--radius-lg); overflow: hidden; box-shadow: 0 0.5rem 1rem -0.6875rem rgba(35,40,45,0.32); aspect-ratio: 3 / 2; }
  .ba-shot img { width: 100%; height: 100%; object-fit: cover; display: block; }
  .ba-tag { position: absolute; top: 0.875rem; left: 0.875rem; padding: 0.3125rem 0.75rem; border-radius: var(--radius-pill); font-size: 0.75rem; font-weight: var(--fw-bold); letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; }
  .ba-tag-before { background: rgba(35,40,45,0.82); color: var(--on-dark); backdrop-filter: blur(0.1875rem); }
  .ba-tag-after { background: var(--gold); color: var(--ink); }
  .ba-pair figcaption { margin-top: 1rem; color: var(--text-body); font-size: var(--text-card); line-height: var(--lh-body); }
  .ba-pair figcaption strong { display: block; font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 1.0625rem; color: var(--ink); margin-bottom: 0.25rem; }
  @media (min-width: 861px) { .ba-shots { gap: 1rem; } .ba-pair figcaption { margin-top: 1.125rem; } }
  /* Below ~640px a side by side pair leaves each shot ~126px wide, too small to read,
     so stack before above after and let each run full width. */
  /* Keep before and after SIDE BY SIDE on phones. Stacking them doubled the height of
     every pair, which is what made this section an endless scroll on mobile. A squarer
     tile keeps each image readable at half width, and the comparison is the whole point
     of the section, so side by side is also the better read. */
  @media (max-width: 640px) {
    .ba-shots { grid-template-columns: 1fr 1fr; gap: 0.5rem; }
    .ba-shot { aspect-ratio: 1 / 1; }
    .ba-tag { font-size: 0.625rem; padding: 0.25rem 0.5rem; }
    .ba-pair figcaption { margin-top: 0.75rem; }
  }

  @media (max-width: 900px) {
    .grid-reviews3 { grid-template-columns: repeat(2,1fr); }
    .grid-credibility { grid-template-columns: repeat(2,1fr); }
    .grid-pillars4 { grid-template-columns: repeat(2,1fr); }
  }
  @media (max-width: 1024px) {
    .grid-hero { grid-template-columns: 1fr; min-height: auto; }
    /* text first, photo after (no order flip) */
    .grid-hero .hero-photo { order: 0; min-height: 22rem; }
    .grid-story { grid-template-columns: 1fr; }
    /* text first, photo after */
    .grid-story .story-photo { order: 0; min-height: 18rem; }
  }
  @media (max-width: 760px) {
    .grid-footer { grid-template-columns: 1fr; text-align: center; }
    .footer-col-links { align-items: center !important; }
    .footer-col-contact { align-items: center !important; }
    /* The address is the only footer line long enough to wrap. Centred, it used to leave
       the pin stranded at the far left while the text centred itself on two lines. Cap the
       measure and left-align the text so the icon sits against the first line it labels. */
    .footer-address { justify-content: center; align-items: flex-start; text-align: left; max-width: 15rem; }
    .footer-address i, .footer-address svg { margin-top: 0.15rem; }
  }
  @media (max-width: 640px) {
    .grid-process5 { grid-template-columns: 1fr; }
  }
  @media (max-width: 560px) {
    .grid-reviews3 { grid-template-columns: 1fr; }
    .grid-stats3 { grid-template-columns: 1fr; }
    .grid-cards3 { grid-template-columns: 1fr; }
  }
  @media (max-width: 480px) {
    .grid-credibility { grid-template-columns: 1fr; }
    .grid-pillars4 { grid-template-columns: 1fr; }
  }

  /* ---- small screens (<=560px down to 320px) ----
     Tighter gutters and padding so content is not squeezed into a narrow column,
     a stripped-back header, and full width controls. */
  @media (max-width: 560px) {
    :root { --page-gutter: 0.875rem; --card-pad: 1.375rem; }
    /* header: logo left, hamburger right, nothing else */
    .header-cta { display: none !important; }  /* beats the inline display on the button */
    header > div > div { gap: 0.625rem; padding: 0.5rem 0.5rem 0.5rem 0.875rem; }
    .nav-hamburger { margin-left: auto; }
    /* slider: one full width slide, no sliver of the next */
    .work-slide { flex-basis: 100%; }
    .work-track { gap: 0.75rem; }
    /* every button goes full width */
    .btn-gold, .contact-submit { width: 100%; justify-content: center; }
    /* .ba-tab deliberately NOT full width here: it stays a horizontally scrollable strip. */
    /* tighter cards */
    .contact-info, .contact-form-card { padding: 1.5rem 1.125rem; }
    .bt-callout { padding: 1.25rem 1.125rem; }
    .process-step { padding: 1.5rem 1rem 1.25rem; }
    /* footer contact rows: left align the text but centre the block, so the icons
       line up instead of drifting when the address wraps to two lines */
  }

  /* ---- nav: floating pill collapses to hamburger + mobile panel ---- */
  .nav-links, .nav-phone { display: flex; }
  .nav-hamburger { display: none; align-items: center; justify-content: center; width: 2.625rem; height: 2.625rem; border-radius: var(--radius-pill); background: var(--pine); border: 0.0625rem solid rgba(216,188,139,0.35); cursor: pointer; flex-shrink: 0; transition: background .2s ease; }
  .nav-hamburger:hover { background: var(--gold); }
  .nav-hamburger:hover i, .nav-hamburger:hover svg { color: var(--ink); }
  /* Animated open/close. display:none cannot transition, so the panel is always
     flex and collapses via max-height/opacity instead. */
  .mobile-nav-panel { display: flex; flex-direction: column; gap: 0.125rem; overflow: hidden;
    max-height: 0; opacity: 0; padding: 0 1.375rem; margin: 0.5rem 0 0;
    background: var(--pine); border-radius: 1.25rem; box-shadow: var(--shadow-nav);
    transition: max-height .38s ease, opacity .28s ease, padding .38s ease; }
  /* The reworded labels are ~61 characters against the old ~40, so the pill runs out
     of room before the hamburger breakpoint. Buy the width back from the phone number
     (duplicated in the footer, and the CTA covers the same intent) rather than
     shortening the labels the client chose. */
  @media (min-width: 1025px) and (max-width: 1400px) {
    .nav-phone { display: none; }
    .nav-links { gap: 1rem; }
  }
  @media (max-width: 1024px) {
    .grid-cards3 { grid-template-columns: 1fr; }
    .grid-process5 { grid-template-columns: 1fr; }
    .nav-links, .nav-phone { display: none; }
    .nav-hamburger { display: inline-flex; }
    /* the divider only made sense next to the nav links, which are hidden here */
    .nav-divider { display: none; }
    header > div > div { gap: 0.75rem; padding: 0.625rem 0.625rem 0.625rem 1.125rem; }
    /* push the CTA + hamburger to the right edge of the pill */
    .header-cta { margin-left: auto; }
  }
  @media (max-width: 560px) {
    .header-cta-label { display: none; }
    .header-cta { padding: 0.5rem !important; }
    .header-cta span[style*="width:1.625rem"] { width: 1.875rem !important; height: 1.875rem !important; }
  }
  .mobile-nav-panel.open { max-height: 34rem; opacity: 1; padding: 0.625rem 1.375rem 1.125rem; }
  .mobile-nav-panel a { color: var(--on-dark-dim); padding: 0.75rem 0.125rem; font-size: 0.9375rem; font-weight: var(--fw-medium); border-bottom: 0.0625rem solid rgba(247,244,239,0.1); }
  .mobile-nav-panel a:last-of-type { border-bottom: none; }
  .mobile-nav-panel .mobile-phone { color: var(--cream); font-weight: var(--fw-semibold); display: flex; align-items: center; gap: 0.5rem; padding-top: 0.875rem; }


  /* ---- full width photo bands ----
     Breaks up the long run of cream sections. A dark gradient sits over the photo so
     text and the white cards stay legible regardless of what the picture is doing. */
  .photo-band { position: relative; background-size: cover; background-position: center; background-repeat: no-repeat; }
  .photo-band::before { content: ""; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(24,28,32,0.90) 0%, rgba(24,28,32,0.82) 55%, rgba(24,28,32,0.90) 100%); }
  .photo-band > * { position: relative; z-index: 1; }

  /* ---- reviews marquee (endless horizontal scroll) ---- */
  .marquee { position: relative; width: 100%; overflow: hidden; padding: 0.375rem 0; -webkit-mask-image: linear-gradient(to right, transparent 0, #000 5.625rem, #000 calc(100% - 5.625rem), transparent 100%); mask-image: linear-gradient(to right, transparent 0, #000 5.625rem, #000 calc(100% - 5.625rem), transparent 100%); }
  .marquee-track { display: flex; width: max-content; animation: marquee-scroll 46s linear infinite; }
  .marquee-group { display: flex; flex-shrink: 0; }
  .marquee:hover .marquee-track, .marquee:focus-within .marquee-track { animation-play-state: paused; }
  @keyframes marquee-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }

  .review-card { flex: 0 0 auto; width: 22.5rem; margin-right: 1.25rem; background: var(--surface-card); border: 0.0625rem solid var(--card-border); border-radius: var(--radius-lg); padding: 1.625rem; }
  .review-card p { margin: 0.875rem 0 1.125rem; color: var(--text-body); font-size: var(--text-card); line-height: var(--lh-body); }
  /* Reviewer attribution. These two reviewers use Google's default initial avatars
     rather than real profile photos, so the initial is rendered on brand here instead
     of serving Google's grey placeholder. */
  .review-by { display: flex; align-items: center; gap: 0.75rem; margin-top: 1.125rem;
    padding-top: 1rem; border-top: 0.0625rem solid var(--card-border); }
  .review-avatar { width: 2.5rem; height: 2.5rem; border-radius: var(--radius-pill); flex-shrink: 0;
    background: var(--pine); color: var(--cream); display: inline-flex; align-items: center;
    justify-content: center; font-family: var(--font-display); font-weight: var(--fw-bold);
    font-size: 1.0625rem; line-height: 1; }
  .review-meta { display: flex; flex-direction: column; gap: 0.1875rem; min-width: 0; }
  .review-name { font-weight: var(--fw-bold); font-size: 0.9375rem; color: var(--ink);
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
  .review-stars { color: var(--star); font-size: 0.8125rem; letter-spacing: 0.0625rem; }
  .review-stars { display: flex; align-items: center; gap: 0.5rem; color: var(--star); font-size: 0.8125rem; letter-spacing: 0.0625rem; }
  .review-attr { display: block; margin-top: 0.5rem; color: var(--text-muted); font-size: 0.8125rem; font-weight: var(--fw-medium); }

  @media (max-width: 560px) {
    .review-card { width: 18.75rem; margin-right: 1rem; padding: 1.375rem; }
    .marquee { -webkit-mask-image: linear-gradient(to right, transparent 0, #000 2.5rem, #000 calc(100% - 2.5rem), transparent 100%); mask-image: linear-gradient(to right, transparent 0, #000 2.5rem, #000 calc(100% - 2.5rem), transparent 100%); }
  }
  @media (max-width: 380px) {
    .review-card { width: 15.75rem; }
  }
  @media (prefers-reduced-motion: reduce) {
    .marquee { overflow-x: auto; -webkit-overflow-scrolling: touch; }
    .marquee-track { animation: none; }
    .marquee-group[aria-hidden="true"] { display: none; }
  }

  /* ---- process steps: each step is a card; connector line threads the gaps ---- */
  .process-steps { position: relative; --step-pad-top: 1.875rem; }
  /* Connector runs behind the cards, so it only shows in the gaps between them.
     Aligned to the badge's vertical centre: card padding-top + half the 3.625rem badge. */
  .process-steps::before { content: ''; position: absolute; top: calc(var(--step-pad-top) + 1.8125rem); left: 8%; right: 8%; height: 0.125rem; background: linear-gradient(to right, transparent, var(--border-sand) 10%, var(--border-sand) 90%, transparent); z-index: 0; }
  @media (max-width: 960px) { .process-steps::before { display: none; } }

  .process-step {
    position: relative; z-index: 1; text-align: center;
    padding: var(--step-pad-top) 1.25rem 1.75rem;
    background: var(--surface-card);
    border: 0.0625rem solid var(--card-border);
    border-radius: var(--radius-lg);
    box-shadow: var(--shadow-card);
    transition: box-shadow .25s ease;
  }
  .process-step h3 { margin: 1.125rem 0 0; font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 1rem; color: var(--ink); }
  .process-step p { margin: 0.5rem 0 0; color: var(--text-body); font-size: 0.875rem; line-height: 1.5; }

  .step-num {
    width: 3.625rem; height: 3.625rem; margin: 0 auto;
    border-radius: var(--radius-pill);
    background: var(--pine);
    border: 0.125rem solid var(--gold);
    box-shadow: 0 0 0 0.375rem rgba(201,170,121,0.13);
    color: var(--gold-on-dark);
    font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 1.3125rem; line-height: 1;
    display: flex; align-items: center; justify-content: center;
    transition: box-shadow .25s ease;
  }
  .process-step:hover { box-shadow: var(--shadow-photo); }
  .process-step:hover .step-num { box-shadow: 0 0 0 0.5625rem rgba(201,170,121,0.2); }

  /* Staggered reveal. Progressive enhancement: steps are visible by default and only
     hidden once JS arms the animation, so they can never be stranded invisible. */
  .process-steps.reveal-armed .process-step { opacity: 0; transform: translateY(0.875rem); transition: opacity .55s ease, transform .55s ease; }
  .process-steps.reveal-armed.in-view .process-step { opacity: 1; transform: none; }
  .process-steps.reveal-armed.in-view .process-step:nth-child(1) { transition-delay: 0ms; }
  .process-steps.reveal-armed.in-view .process-step:nth-child(2) { transition-delay: 110ms; }
  .process-steps.reveal-armed.in-view .process-step:nth-child(3) { transition-delay: 220ms; }
  .process-steps.reveal-armed.in-view .process-step:nth-child(4) { transition-delay: 330ms; }
  .process-steps.reveal-armed.in-view .process-step:nth-child(5) { transition-delay: 440ms; }

  @media (prefers-reduced-motion: reduce) {
    .process-steps.reveal-armed .process-step { opacity: 1; transform: none; transition: none; }
    .process-step:hover .step-num { transform: none; }
    .step-num { transition: none; }
  }

  /* ---- footer logo (flex column would otherwise stretch it) ---- */
  .footer-logo { height: 2.875rem; width: auto; align-self: flex-start; flex-shrink: 0; }
  @media (max-width: 760px) { .footer-logo { align-self: center; } }

  /* ---- family bios ---- */
  /* Five people do not divide evenly into a 3-up grid, so the last row is centred
     rather than left-hanging. auto-fit would collapse to 2-up and leave a lone card. */
  .bio-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 1.25rem; margin-top: 1.25rem; justify-content: center; }
  .bio-card { background: var(--surface-card); border: 0.0625rem solid var(--card-border); border-radius: var(--radius-lg); padding: 1.625rem 1.5rem; box-shadow: var(--shadow-card); }
  /* Circular avatars keep the four missing headshots from reading as broken images:
     a monogram is a deliberate looking placeholder, and swapping in a photo later is a
     one line change per card. */
  .bio-avatar { width: 8.5rem; height: 8.5rem; border-radius: var(--radius-pill); object-fit: cover; display: block; margin-bottom: 1rem; }
  .bio-monogram { background: var(--sand); border: 0.0625rem solid var(--border-sand); color: var(--gold-deep); font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 1.5rem; letter-spacing: 0.02em; display: flex; align-items: center; justify-content: center; }
  .bio-card h3 { margin: 0; font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 1.1875rem; color: var(--ink); line-height: 1.15; }
  .bio-card .bio-role { display: block; margin-top: 0.3125rem; color: var(--gold-deep); font-size: 0.8125rem; font-weight: var(--fw-bold); letter-spacing: var(--tracking-eyebrow); text-transform: uppercase; }
  .bio-card p { margin: 0.875rem 0 0; color: var(--text-body); font-size: var(--text-card); line-height: 1.6; }
  /* Sixth card closes the grid at two rows of three. Sand rather than white so it reads as
     an action, not a sixth person. flex + margin-top:auto pins the link to the bottom so it
     lines up with the baseline of the bios beside it. */
  /* Sixth tile in the family grid: a dark CTA box in --ink so it reads as an action, not
     a sixth person. It is an <a>, so the whole box is clickable. */
  .bio-card-cta-dark { background: #23282D; border-color: #23282D; display: flex; flex-direction: column;
    text-decoration: none; transition: transform .25s ease, box-shadow .25s ease; }
  .bio-card-cta-dark:hover { transform: translateY(-0.25rem); box-shadow: 0 1rem 2rem -1rem rgba(35,40,45,0.55); }
  .bio-card-cta-dark h3 { color: var(--on-dark); }
  .bio-card-cta-dark .bio-role { color: var(--gold-on-dark); }
  .bio-card-cta-dark p { color: var(--on-dark-dim); }
  .bio-cta-dark-mark { width: 3.5rem; height: 3.5rem; border-radius: var(--radius-pill); background: var(--gold);
    color: var(--ink); display: inline-flex; align-items: center; justify-content: center; margin-bottom: 1.125rem; }
  .bio-cta-dark-mark i, .bio-cta-dark-mark svg { width: 1.375rem; height: 1.375rem; }
  .bio-cta-dark-link { display: inline-flex; align-items: center; gap: 0.5rem; align-self: flex-start;
    margin-top: auto; padding: 1.25rem 0 0.1875rem; color: var(--on-dark); font-weight: var(--fw-bold);
    font-size: var(--text-card); border-bottom: 0.125rem solid var(--gold); }
  .bio-card-cta-dark:hover .bio-cta-dark-link { border-bottom-color: var(--on-dark); }
  .bio-card-cta { background: var(--sand); border-color: var(--border-sand); display: flex; flex-direction: column; }
  .bio-cta-mark { width: 3.5rem; height: 3.5rem; border-radius: var(--radius-pill); background: var(--gold); color: var(--ink); display: inline-flex; align-items: center; justify-content: center; margin-bottom: 1.125rem; }
  .bio-cta-mark i, .bio-cta-mark svg { width: 1.375rem; height: 1.375rem; }
  .bio-cta-link { display: inline-flex; align-items: center; gap: 0.5rem; align-self: flex-start; margin-top: auto; padding: 1.25rem 0 0.1875rem; color: var(--ink); font-weight: var(--fw-bold); font-size: 0.9375rem; border-bottom: 0.125rem solid var(--gold); }
  .bio-cta-link:hover { border-bottom-color: var(--ink); }
  @media (max-width: 1024px) {
    .bio-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  @media (max-width: 640px) {
    .bio-grid { grid-template-columns: 1fr; }
  }
  .social-btn { width: 2.375rem; height: 2.375rem; border-radius: var(--radius-pill); background: rgba(247,244,239,0.08); display: inline-flex; align-items: center; justify-content: center; transition: background .2s ease; }
  .social-btn:hover { background: rgba(201,170,121,0.22); }
  .social-btn svg { width: 1.0625rem; height: 1.0625rem; fill: var(--cream); display: block; }

/* =========================================================================
   Theme additions (WordPress only). Everything above is the static site's
   shared <style> block, unmodified.
   ========================================================================= */

body { margin: 0; min-height: 100%; background: var(--surface-page); }
.ch-container { max-width: var(--page-max); margin: 0 auto; padding: 0 var(--page-gutter); }

/* Spacing controls. A block only writes a --ch-* variable when the editor set it, so
   every fallback below is the site's own rhythm: section + section gaps, .band padding,
   flush band-to-band. Setting a value in the editor overrides exactly that one edge. */
section.ch-section + section.ch-section { margin-top: var(--ch-mt, var(--section-gap)); }
.band.ch-section + .band.ch-section      { margin-top: var(--ch-mt, 0rem); }
.ch-section:first-child                  { margin-top: var(--ch-mt, 0rem); }
.ch-section                              { margin-bottom: var(--ch-mb, 0rem); }
.ch-section:not(.band)                   { padding-top: var(--ch-pt, 0rem); padding-bottom: var(--ch-pb, 0rem); }
.band.ch-section                         { padding-top: var(--ch-pt, var(--band-pad)); padding-bottom: var(--ch-pb, var(--band-pad)); }
@media (max-width: 40rem) {
  section.ch-section + section.ch-section { margin-top: var(--ch-mt-m, var(--ch-mt, var(--section-gap))); }
  .band.ch-section + .band.ch-section      { margin-top: var(--ch-mt-m, var(--ch-mt, 0rem)); }
  .ch-section:first-child                  { margin-top: var(--ch-mt-m, var(--ch-mt, 0rem)); }
  .ch-section                              { margin-bottom: var(--ch-mb-m, var(--ch-mb, 0rem)); }
  .ch-section:not(.band)                   { padding-top: var(--ch-pt-m, var(--ch-pt, 0rem)); padding-bottom: var(--ch-pb-m, var(--ch-pb, 0rem)); }
  .band.ch-section                         { padding-top: var(--ch-pt-m, var(--ch-pt, var(--band-pad))); padding-bottom: var(--ch-pb-m, var(--ch-pb, var(--band-pad))); }
}
/* Page content sits in <main>; the footer part follows it. The static site's
   `section + footer` rule cannot see across that boundary, so restate it. */
.ch-main + .ch-footer-part { margin-top: var(--section-gap); }
.ch-main:has(.wp-block-post-content > .band:last-child) + .ch-footer-part { margin-top: 0; }
.wp-block-post-content > section:first-child { margin-top: 0; }

/* Hero photo: the static site used a design-tool <image-slot>; here it is a real <img>. */
.hero-scene > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; display: block; }

/* ---- Gravity Forms, styled as the hand-built form it replaced -------------------
   GF's own CSS is disabled (Forms > Settings), so every rule the form needs is here.
   Same values as .contact-form above; only the selectors changed. */
.ch-gform_wrapper { margin: 0; }
.ch-gform .gform_fields { display: grid; grid-template-columns: repeat(12, minmax(0, 1fr)); gap: 1rem; margin: 0; padding: 0; list-style: none; }
.ch-gform .gfield { grid-column: span 12; margin: 0; }
.ch-gform .gfield--width-half { grid-column: span 6; }
@media (max-width: 30rem) { .ch-gform .gfield--width-half { grid-column: span 12; } }
.ch-gform .gfield_label { display: block; font-size: 0.875rem; font-weight: var(--fw-semibold); color: var(--ink); margin: 0; }
.ch-gform .ginput_container { margin: 0; }
.ch-gform input:not([type="submit"]):not([type="hidden"]), .ch-gform select, .ch-gform textarea {
  width: 100%; margin-top: 0.4375rem; padding: 0.75rem 0.875rem; font-family: var(--font-body); font-size: 1rem;
  color: var(--ink); background: var(--cream); border: 0.0625rem solid var(--border-sand);
  border-radius: var(--radius-sm); transition: border-color .15s ease, box-shadow .15s ease; box-sizing: border-box;
}
.ch-gform textarea { resize: vertical; min-height: 7.5rem; }
.ch-gform input:focus, .ch-gform select:focus, .ch-gform textarea:focus {
  outline: none; border-color: var(--gold); box-shadow: 0 0 0 0.1875rem rgba(184,153,106,0.22);
}
.ch-gform .gform-footer { margin-top: 1rem; padding: 0; display: flex; flex-direction: column; align-items: stretch; }
.ch-gform .gform_ajax_spinner, .ch-gform .ginput_counter, .ch-gform .charleft { display: none !important; }
/* GF's honeypot field: hidden by GF's stylesheet normally, so hide it here. */
.ch-gform .gform_validation_container, .ch-gform .gfield--type-honeypot { position: absolute !important; left: -9999px !important; width: 1px; height: 1px; overflow: hidden; }
.ch-gform .gform_hidden, .ch-gform input[type="hidden"] { display: none; }
/* Validation: red text under the field, form-level summary as the old status box. */
.ch-gform .gfield_validation_message { margin: 0.375rem 0 0; font-size: 0.8125rem; color: #8A2020; }
.ch-gform .gfield_error input, .ch-gform .gfield_error select, .ch-gform .gfield_error textarea { border-color: #C0504D; }
.ch-gform .gform_validation_errors { margin: 0 0 1rem; font-size: var(--text-card); line-height: 1.55; padding: 0.75rem 0.9375rem; border-radius: var(--radius-md, 0.5rem); background: #FBECEC; color: #8A2020; }
.ch-gform .gform_validation_errors h2 { margin: 0; font: inherit; font-weight: var(--fw-semibold); }
.ch-gform .gform_validation_errors ol { display: none; }
.ch-gform .gform_submission_error { display: none; }
/* Confirmation message = the old success box. */
.gform_confirmation_wrapper .gform_confirmation_message { margin: 0.75rem 0 0; font-size: var(--text-card); line-height: 1.55; padding: 0.75rem 0.9375rem; border-radius: var(--radius-md, 0.5rem); background: var(--chip-bg); color: var(--ink); }
.ch-gform .gfield_description { font-size: 0.8125rem; color: var(--text-muted); margin: 0.375rem 0 0; }
.ch-gform legend.gfield_label, .ch-gform .gfield_required, .ch-gform .gform_required_legend { display: none; }

/* Editor canvas: give blocks the page ground so previews look like the site. */
.editor-styles-wrapper { background: var(--surface-page); }
.editor-styles-wrapper .ch-section { margin-top: var(--section-gap); }
