/*
 * dg-global.css — Davis Group Child Theme
 * Design system: "Granite & Ponderosa"
 * DeadStop Creative · 2026
 *
 * Sections:
 *   1. @font-face
 *   2. Design tokens (:root)
 *   3. Base / reset
 *   4. Skip navigation + focus
 *   5. Typography utility classes
 *   6. Eyebrow component
 *   7. Stat block component
 *   8. Section heading overrides
 *   9. Button styles
 *  10. Community card
 *  11. Card-lift shadow effect
 *  12. Official-link / external link
 *  13. Header (dg-header, dg-scroll-bar, page-template-*)
 *  14. Footer (dg-footer)
 *  15. Forms — Fluent Forms skin
 *  16. VisionBand (vision-band, vision-photo-*, vision-text-col)
 *  17. SHomesites release rows (Stringfield "Now Selling" section)
 *  18. Team cards
 *  19. Image hover
 *  20. Reduced motion
 *  21. Master plan — release strip, land ledger, lightbox (added July 2026)
 */


/* ============================================================
   1. @FONT-FACE
   Download WOFF2 files and place in davis-group-child/fonts/
   Source: https://google-webfonts-helper.herokuapp.com
   ============================================================ */

/* Bodoni Moda — display / editorial */
@font-face {
  font-family: 'Bodoni Moda';
  src: url('../../fonts/bodoni-moda-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Bodoni Moda';
  src: url('../../fonts/bodoni-moda-400-italic.woff2') format('woff2');
  font-weight: 400;
  font-style: italic;
  font-display: swap;
}

/* Hanken Grotesk — body / UI / labels */
@font-face {
  font-family: 'Hanken Grotesk';
  src: url('../../fonts/hanken-grotesk-300.woff2') format('woff2');
  font-weight: 300;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Hanken Grotesk';
  src: url('../../fonts/hanken-grotesk-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Hanken Grotesk';
  src: url('../../fonts/hanken-grotesk-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Hanken Grotesk';
  src: url('../../fonts/hanken-grotesk-600.woff2') format('woff2');
  font-weight: 600;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Hanken Grotesk';
  src: url('../../fonts/hanken-grotesk-700.woff2') format('woff2');
  font-weight: 700;
  font-style: normal;
  font-display: swap;
}


/* ============================================================
   2. DESIGN TOKENS
   Single source of truth. All components reference var() only —
   never hardcoded hex values anywhere else in the theme.
   ============================================================ */

:root {
  /* —— Core palette —— */
  --paper:        #F6F1E7;
  --paper-alt:    #EFE8DA;
  --card:         #FFFDF7;
  --sand:         #E5DBC8;
  --ink-700:      #46433B;
  --ink-900:      #1E1D17;
  /* Darkened from #7E7460 — the original only reached 4.1:1 on --paper and
     3.8:1 on --paper-alt against WCAG AA's 4.5:1 floor for normal text
     (used for muted/caption text at 12-15px sitewide). This hue-preserving
     adjustment clears 4.5:1 against both paper surfaces. */
  --taupe:        #716856;

  /* —— Pine (brand green) —— */
  --pine-900:     #16241A;
  --pine-800:     #1C2E21;
  --pine-700:     #294234;
  --pine-600:     #335041;
  --pine-500:     #436454;
  /* Lightened from #708A78 — the original only reached 4.3:1 against
     --pine-900 (used for footer address/copyright text at 12-13px on the
     dark footer), just under WCAG AA's 4.5:1 floor for normal text. */
  --pine-300:     #748E7C;
  --pine-100:     #C3CFC4;

  /* —— Bronze / clay (accent, CTAs) —— */
  --bronze-600:   #875A35;
  /* #9C6B42 is the reference's exact accent — restored July 2026 after a
     WCAG-motivated darkening to #8B5F3B made the accent CTAs visibly
     off-tone next to the reference (client-flagged on the hero). Note:
     as --accent this is also small eyebrow text, where #9C6B42 reaches
     only ~4.1:1 on --paper vs AA's 4.5:1 — accepted deviation in favor
     of exact reference parity; revisit with the client if AA text
     compliance becomes a requirement. */
  --bronze-500:   #9C6B42;
  --bronze-400:   #B0814F;
  --bronze-200:   #D8BE9C;

  /* —— Sky (dusty blue) —— */
  --sky-600:      #4F6E7C;
  --sky-500:      #6B8896;
  --sky-300:      #A8BEC7;

  /* —— Stone neutrals —— */
  --stone-100:    #DCD2BE;
  --stone-200:    #CABEA6;
  --stone-300:    #B6A98E;

  /* —— Functional —— */
  --success:      #4B6B4E;

  /* —— Semantic surface aliases —— */
  --surface-page:      var(--paper);
  --surface-page-alt:  var(--paper-alt);
  --surface-card:      var(--card);
  --surface-inverse:   var(--pine-900);

  /* —— Semantic text aliases —— */
  --text-heading:       var(--ink-900);
  --text-body:          var(--ink-700);
  --text-muted:         var(--taupe);
  --text-inverse:       var(--paper);
  --text-on-dark-muted: var(--pine-100);

  /* —— Brand / accent aliases —— */
  --brand:         var(--pine-700);
  --brand-strong:  var(--pine-900);
  --accent:        var(--bronze-500);
  --accent-strong: var(--bronze-600);
  --accent-soft:   var(--sky-500);

  /* —— Borders —— */
  --border-hairline: rgba(30, 29, 23, 0.14);
  --border-soft:     rgba(30, 29, 23, 0.08);
  --border-on-dark:  rgba(246, 241, 231, 0.22);
  --rule-accent:     var(--bronze-500);

  /* —— Shadows —— */
  --shadow-xs:  0 1px 2px rgba(30, 29, 23, 0.06);
  --shadow-sm:  0 2px 8px rgba(30, 29, 23, 0.07);
  --shadow-md:  0 10px 30px -12px rgba(30, 29, 23, 0.18);
  --shadow-lg:  0 28px 60px -28px rgba(22, 36, 26, 0.34);

  /* —— Paper opacity variants (for overlays) —— */
  --paper-98: rgba(246, 241, 231, 0.98);
  --paper-96: rgba(246, 241, 231, 0.96);
  --paper-94: rgba(246, 241, 231, 0.94);
  --paper-92: rgba(246, 241, 231, 0.92);
  --paper-90: rgba(246, 241, 231, 0.90);
  --paper-78: rgba(246, 241, 231, 0.78);
  --paper-75: rgba(246, 241, 231, 0.75);
  --paper-72: rgba(246, 241, 231, 0.72);
  --paper-60: rgba(246, 241, 231, 0.60);
  --paper-55: rgba(246, 241, 231, 0.55);
  --paper-50: rgba(246, 241, 231, 0.50);
  --paper-40: rgba(246, 241, 231, 0.40);
  --paper-32: rgba(246, 241, 231, 0.32);
  --paper-22: rgba(246, 241, 231, 0.22);
  --paper-12: rgba(246, 241, 231, 0.12);

  /* —— Typography scale —— */
  --t-title:   28px;
  --t-lead:    21px;
  --t-body:    17px;
  --t-small:   15px;
  --t-caption: 13px;
  --t-eyebrow: 12.5px;

  /* —— Line heights —— */
  --lh-tight:   1.02;
  --lh-snug:    1.12;
  --lh-display: 1.06;
  --lh-body:    1.70;
  --lh-relaxed: 1.75;

  /* —— Letter spacing —— */
  --ls-display: -0.02em;
  --ls-tight:   -0.01em;
  --ls-normal:  0;
  --ls-eyebrow: 0.22em;
  --ls-caps:    0.14em;

  /* —— Font weights —— */
  --w-light:    300;
  --w-regular:  400;
  --w-medium:   500;
  --w-semibold: 600;
  --w-bold:     700;

  /* —— Font families —— */
  --font-display: 'Bodoni Moda', 'Didot', Georgia, serif;
  --font-sans:    'Hanken Grotesk', -apple-system, 'Segoe UI', system-ui, sans-serif;

  /* —— Layout —— */
  --content-max:     1280px;
  --content-text:    680px;
  --gutter:          clamp(20px, 5vw, 80px);
  --section-y:       clamp(80px, 10vw, 128px);
  --section-y-tight: clamp(56px, 7.5vw, 96px);

  /* —— Radius —— */
  --radius-xs:   2px;  /* added July 2026 — used by the master plan ledger/marker (Section 21); matches globals.css */
  --radius-card: 4px;
  --radius-sm:   4px;
  --radius-md:   6px;
  --radius-pill: 9999px;

  /* —— Motion —— */
  /* These three durations mirror the reference site's tokens exactly
     (deadstop-web-projects.vercel.app, app/globals.css). A July 2026 pass
     briefly retimed them to 150/250/450ms; reverted per client — every
     transition must behave exactly like the reference. */
  --ease-out:   cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-inout: cubic-bezier(0.65, 0, 0.35, 1);
  --dur-fast:   180ms;
  --dur-base:   320ms;
  --dur-slow:   560ms;

  /* —— Focus ring —— */
  --focus-ring: 0 0 0 3px var(--bronze-500);

  /* —— Text shadow —— */
  --text-shadow-on-dark: 0 1px 3px rgba(20, 28, 20, 0.35);

  /* —— Overlays —— */
  --overlay-pine: rgba(22, 36, 26, 0.55);
  --img-overlay-bottom: linear-gradient(
    to top, rgba(22,36,26,0.78) 0%, rgba(22,36,26,0.28) 38%, rgba(22,36,26,0) 70%
  );
}


/* ============================================================
   3. BASE / RESET
   ============================================================ */

html {
  scroll-behavior: smooth;
  scroll-padding-top: 96px; /* clears sticky header on anchor jumps */
  color-scheme: light;
}

body {
  background: var(--surface-page);
  color: var(--text-body);
  font-family: var(--font-sans);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

/* Divi resets <a> color globally — re-establish brand link color */
a {
  color: var(--accent-strong);
}

/* Images are block by default (prevents descender gap below inline images) */
img {
  display: block;
  max-width: 100%;
}

/* Divi's own base.css sets `blockquote { border-left: 5px solid;
   padding-left: 20px }` with no border-color of its own, so it inherits
   the browser's default currentColor-ish link-blue — the "blue left
   border" on every quote site-wide. The reference
   (deadstop-web-projects.vercel.app/about) has no border on its quotes
   at all, just italic display type. This is a plain, unscoped reset (no
   class, no !important) so it applies everywhere automatically; sections
   that set their own border inline (e.g. Legacy's bronze accent line)
   are untouched, since an inline style always wins over an external
   stylesheet rule regardless of what this says. */
blockquote {
  border-left: none;
  padding-left: 0;
}


/* ============================================================
   4. SKIP NAVIGATION + FOCUS
   ============================================================ */

.skip-to-content {
  position: absolute;
  top: -100%;
  left: 16px;
  z-index: 99999;
  background: var(--bronze-500);
  color: var(--paper);
  padding: 8px 16px;
  font-family: var(--font-sans);
  font-size: 14px;
  font-weight: var(--w-semibold);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: top var(--dur-fast) var(--ease-out);
}
.skip-to-content:focus {
  top: 16px;
}

/* Global focus ring — overrides Divi's focus reset */
*:focus-visible {
  outline: none !important;
  box-shadow: var(--focus-ring) !important;
}


/* ============================================================
   5. TYPOGRAPHY UTILITY CLASSES
   Divi Presets accept fixed px values only — no clamp() support.
   Apply these classes via Module > Advanced > CSS Class in Divi.
   ============================================================ */

/* Hero H1 — home, Stringfield, Serenity, Legacy heroes */
.hero-headline {
  font-family: var(--font-display) !important;
  font-size: clamp(48px, 7.4vw, 104px) !important;
  font-weight: 400 !important;
  line-height: 0.98 !important;
  letter-spacing: var(--ls-display) !important;
  color: var(--paper) !important;
}
.hero-headline em {
  font-style: italic;
  color: var(--bronze-200);
}

/* Section H1 — LegacyHero editorial headline */
.dg-h1-display {
  font-family: var(--font-display) !important;
  font-size: clamp(44px, 7vw, 96px) !important;
  font-weight: 400 !important;
  line-height: 1.0 !important;
  letter-spacing: var(--ls-display) !important;
}

/* Section H2 — main section headings */
.dg-h2-section {
  font-family: var(--font-display) !important;
  font-size: clamp(30px, 3.8vw, 52px) !important;
  font-weight: 400 !important;
  line-height: 1.06 !important;
  letter-spacing: var(--ls-display) !important;
}

/* Editorial paragraph headings — VEthos, IntroStatement, JeffSection quote */
.dg-h3-editorial {
  font-family: var(--font-display) !important;
  font-size: clamp(26px, 3.4vw, 40px) !important;
  font-weight: 400 !important;
  line-height: 1.32 !important;
  letter-spacing: var(--ls-tight) !important;
}

/* Hero sub-paragraph — large intro text below hero headlines */
.dg-hero-sub {
  font-family: var(--font-sans) !important;
  font-size: clamp(17px, 1.6vw, 22px) !important;
  line-height: 1.6 !important;
}

/* Eyebrow override class for Divi Text modules */
.dg-eyebrow {
  font-family: var(--font-sans) !important;
  font-size: var(--t-eyebrow) !important;
  font-weight: var(--w-semibold) !important;
  letter-spacing: var(--ls-eyebrow) !important;
  text-transform: uppercase !important;
  color: var(--accent) !important;
}


/* ============================================================
   6. EYEBROW COMPONENT
   Used in SectionHeading and stand-alone as Code Module HTML.
   ============================================================ */

.eyebrow-rule {
  display: flex;
  align-items: center;
  gap: 14px;
  font-family: var(--font-sans);
  font-size: var(--t-eyebrow);
  font-weight: var(--w-semibold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--accent);
  margin: 0;
}
.eyebrow-rule::before {
  content: '';
  display: block;
  width: 24px;
  height: 1.5px;
  background: var(--rule-accent);
  flex-shrink: 0;
}

/* Centered variant — IntroStatement, VEthos */
.eyebrow-center {
  justify-content: center;
  text-align: center;
}

/* On-dark variant — hero, VisionBand, VInquiry */
.eyebrow-on-dark {
  color: var(--paper-78);
}
.eyebrow-on-dark::before {
  background: var(--paper-78);
}


/* ============================================================
   7. STAT BLOCK COMPONENT
   HTML lives in Divi Code Modules. counter.js animates .stat-value.
   ============================================================ */

.stat-block {
  padding: 0;
}

.stat-number {
  display: flex;
  align-items: baseline;
  gap: 6px;
  line-height: 1;
}

.stat-value {
  font-family: var(--font-display);
  font-size: clamp(36px, 4.5vw, 60px);
  font-weight: 400;
  letter-spacing: var(--ls-display);
  color: var(--text-heading);
  font-variant-numeric: lining-nums;
}

.stat-unit {
  font-family: var(--font-display);
  font-size: clamp(18px, 2vw, 26px);
  font-weight: 400;
  font-style: italic;
  color: var(--accent);
  letter-spacing: 0;
}

.stat-label {
  font-family: var(--font-sans);
  font-size: var(--t-small);
  font-weight: var(--w-medium);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 10px 0 0;
}

/* Dark-surface variant — used inside inverse sections */
.stat-block.stat-on-dark .stat-value {
  color: var(--paper);
}
.stat-block.stat-on-dark .stat-unit {
  color: var(--bronze-200);
}
.stat-block.stat-on-dark .stat-label {
  color: var(--pine-100);
}

/* Stat grid — 4-col on desktop, 2-col on mobile */
.stat-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 8px;
  border-top: 1px solid var(--border-hairline);
  padding-top: 48px;
  margin-top: 72px;
}
.stat-grid > * + * {
  border-left: 1px solid var(--border-soft);
  padding-left: clamp(16px, 2.5vw, 40px);
}
.stat-grid-3 {
  grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 640px) {
  .stat-grid,
  .stat-grid-3 {
    grid-template-columns: repeat(2, 1fr);
    text-align: center;
  }
  .stat-grid > * + *,
  .stat-grid-3 > * + * {
    border-left: none;
    padding-left: 0;
  }
}


/* ============================================================
   8. SECTION HEADING OVERRIDES
   Target Divi Text modules assigned these CSS classes.
   ============================================================ */

/* SectionHeading wrappers */
.dg-section-heading {
  margin: 0;
}
.dg-section-heading .eyebrow-rule {
  margin-bottom: 20px;
}
.dg-section-heading h2 {
  font-family: var(--font-display);
  font-weight: 400;
  color: var(--text-heading);
  margin: 0 0 20px;
}
.dg-section-heading .intro {
  font-family: var(--font-sans);
  font-size: var(--t-lead);
  line-height: var(--lh-relaxed);
  color: var(--text-body);
  margin: 0;
}

/* Dark tone — VisionBand, hero overlays */
.dg-section-heading.tone-dark h2,
.dg-section-heading.tone-dark .intro {
  color: var(--paper);
}
.dg-section-heading.tone-dark .intro {
  color: var(--pine-100);
}


/* ============================================================
   9. BUTTON STYLES
   NOTE: originally written for native Divi Button Modules (hence the
   `.et_pb_button` co-selector on every rule below), from the pre-pivot
   plan described in SHORTCODE_IMPLEMENTATION.md §1. The shortcode
   partials actually render plain `<a class="btn dg-btn-*">` links —
   they never carry `.et_pb_button` — so every rule here was silently
   matching nothing site-wide. Rewritten to target `.btn` (the class
   every partial actually applies) instead, plus a `.btn` base rule
   for the display/cursor/text-decoration these links no longer
   inherited from Divi's own module CSS either.
   ============================================================ */

.btn,
.btn:active,
.btn:focus {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px; /* reference md gap; .dg-btn-lg widens to 12px below */
  text-align: center;
  text-decoration: none;
  line-height: 1;
  white-space: nowrap;
  cursor: pointer;
  transform: none !important;
}

/* Button icon — arrow nudges on hover/focus for EVERY .btn variant, at
   --dur-base, mirroring the reference's `.btn svg` rules exactly
   (app/globals.css §Button icon): same trigger set (hover AND
   focus-visible), same 3px nudge, same duration, same
   prefers-reduced-motion opt-out. */
.btn .btn-icon,
.btn svg {
  flex-shrink: 0;
  transition: transform var(--dur-base) var(--ease-out);
}
.btn:hover .btn-icon,
.btn:hover svg,
.btn:focus-visible .btn-icon,
.btn:focus-visible svg {
  transform: translateX(3px);
}
/* Back-to-top is not a .btn — its arrow lifts up 2px, per the reference
   BackToTop component. */
.footer-back-to-top:hover .btn-icon,
.footer-back-to-top:focus-visible .btn-icon {
  transform: translateY(-2px);
}
@media (prefers-reduced-motion: reduce) {
  .btn .btn-icon,
  .btn svg,
  .footer-back-to-top .btn-icon {
    transition: none;
  }
  .btn:hover .btn-icon,
  .btn:hover svg,
  .btn:focus-visible .btn-icon,
  .btn:focus-visible svg,
  .footer-back-to-top:hover .btn-icon,
  .footer-back-to-top:focus-visible .btn-icon {
    transform: none;
  }
}

/* — Primary / pine background — */
.dg-btn-primary.btn,
.dg-btn-primary.btn:hover {
  font-family: var(--font-sans) !important;
  font-size: 13px !important;
  font-weight: var(--w-semibold) !important;
  letter-spacing: var(--ls-caps) !important;
  text-transform: uppercase !important;
  background-color: var(--pine-700) !important;
  color: var(--paper) !important;
  /* Reference gives EVERY button a 1px border (transparent on solid
     variants) so solid and outline buttons render identical heights. */
  border: 1px solid transparent !important;
  border-radius: var(--radius-sm) !important;
  padding: 14px 28px !important;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out) !important;
}
.dg-btn-primary.btn:hover {
  background-color: var(--pine-900) !important;
}

/* — Accent / bronze background (primary CTA) — */
.dg-btn-accent.btn,
.dg-btn-accent.btn:hover {
  font-family: var(--font-sans) !important;
  font-size: 13px !important;
  font-weight: var(--w-semibold) !important;
  letter-spacing: var(--ls-caps) !important;
  text-transform: uppercase !important;
  background-color: var(--bronze-500) !important;
  color: var(--paper) !important;
  border: 1px solid transparent !important;
  border-radius: var(--radius-sm) !important;
  padding: 14px 28px !important;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out) !important;
}
.dg-btn-accent.btn:hover {
  background-color: var(--bronze-600) !important;
}

/* — Outline — transparent with pine border — */
.dg-btn-outline.btn,
.dg-btn-outline.btn:hover {
  font-family: var(--font-sans) !important;
  font-size: 13px !important;
  font-weight: var(--w-semibold) !important;
  letter-spacing: var(--ls-caps) !important;
  text-transform: uppercase !important;
  background-color: transparent !important;
  color: var(--pine-700) !important;
  /* 1px like the reference — solid variants carry a transparent 1px
     border, so heights match with identical 14px padding, no
     compensation needed. */
  border: 1px solid var(--pine-700) !important;
  border-radius: var(--radius-sm) !important;
  padding: 14px 28px !important;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out) !important;
}
.dg-btn-outline.btn:hover {
  background-color: var(--pine-700) !important;
  color: var(--paper) !important;
}

/* — Outline on dark — paper border (transparent header hero) — */
.dg-btn-outline-dark.btn {
  color: var(--paper) !important;
  border-color: var(--paper-55) !important;
}
.dg-btn-outline-dark.btn:hover {
  background-color: var(--paper-12) !important;
  border-color: var(--paper-78) !important;
}

/* — Link / text button — */
.dg-btn-link.btn,
.dg-btn-link.btn:hover {
  font-family: var(--font-sans) !important;
  font-size: 13px !important;
  font-weight: var(--w-semibold) !important;
  letter-spacing: -0.01em !important;
  background: none !important;
  /* Reference link variant underlines with a 1px accent border-bottom
     (transparent on the other edges), animating to pine on hover. */
  border: 1px solid transparent !important;
  border-bottom-color: var(--accent) !important;
  border-radius: 0 !important;
  color: var(--accent-strong) !important;
  padding: 0 !important;
  text-decoration: none !important;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out) !important;
}
.dg-btn-link.btn:hover {
  color: var(--pine-700) !important;
  border-bottom-color: var(--pine-700) !important;
}

/* Large size modifier — hero CTAs. Reference lg spec: 18px 38px padding,
   14px type, 12px icon gap. No outline compensation needed — every
   variant carries a 1px border (transparent on solids), so paddings
   stay uniform.
   The :hover co-selector is load-bearing: the variant rules above declare
   their md-size padding/font-size on `.dg-btn-*.btn:hover` (specificity
   0,3,0), which out-ranks a plain `.dg-btn-lg.btn` (0,2,0) the moment the
   button is hovered — large buttons visibly SHRANK to md size on hover
   (client-reported July 2026). Declaring lg with the same :hover
   co-selector ties the specificity and wins by source order in both
   states. */
.dg-btn-lg.btn,
.dg-btn-lg.btn:hover {
  padding: 18px 38px !important;
  font-size: 14px !important;
  gap: 12px;
}


/* ============================================================
   10. COMMUNITY CARD
   Card HTML lives in Divi Code Modules. 3-column grid on desktop.
   ============================================================ */

.community-card {
  position: relative;
  border-radius: var(--radius-card);
  overflow: hidden;
  background: var(--surface-card);
  box-shadow: var(--shadow-sm);
  transition: box-shadow var(--dur-base) var(--ease-out),
              transform var(--dur-base) var(--ease-out);
}
.community-card:hover {
  transform: translateY(-3px);
  /* Client revision (July 2026): was var(--shadow-lg) (0 28px 60px), which
     read much heavier than the team cards further down the page. This is
     the team-card hover shadow from the design system, so both card
     families lift with the same weight. */
  box-shadow: 0 16px 30px -18px rgba(22, 36, 26, 0.28);
}

/* Full-card clickable overlay — stretches over the entire card */
.card-link-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  text-indent: -9999px;
}

/* Prevents the official external link from being covered by overlay */
.card-official-link {
  position: relative;
  z-index: 2;
}

.card-image {
  position: relative;
  overflow: hidden;
  aspect-ratio: 3 / 4;
}
.card-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow) var(--ease-out);
}
.community-card:hover .card-image img {
  transform: scale(1.04);
}

.card-tag {
  position: absolute;
  bottom: 14px;
  left: 14px;
  z-index: 2;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: var(--w-semibold);
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 5px 10px;
  border-radius: var(--radius-pill);
}
.tag-available {
  background: var(--pine-700);
  color: var(--paper);
}
.tag-reserved {
  background: var(--bronze-500);
  color: var(--paper);
}
.tag-sold {
  background: var(--ink-700);
  color: var(--paper);
}

.card-content {
  padding: 22px 24px 28px;
}
.card-content .eyebrow-rule {
  font-size: 11px;
  margin-bottom: 8px;
}
.card-content h3 {
  font-family: var(--font-display);
  font-size: 22px;
  font-weight: 400;
  color: var(--text-heading);
  margin: 0 0 10px;
  line-height: 1.15;
}
.card-excerpt {
  font-family: var(--font-sans);
  font-size: var(--t-small);
  line-height: 1.65;
  color: var(--text-body);
  margin: 0 0 8px;
}
.card-meta {
  font-family: var(--font-sans);
  font-size: 12.5px;
  color: var(--text-muted);
  letter-spacing: 0.04em;
  margin: 0 0 14px;
}

/* Official external link inside the card */
.official-link {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: var(--w-semibold);
  letter-spacing: 0.01em;
  color: var(--accent-strong);
  text-decoration: none;
}
.official-link svg {
  width: 13px;
  height: 13px;
  transition: transform var(--dur-base) var(--ease-out);
}
.official-link:hover svg,
.official-link:focus-visible svg {
  transform: translate(2px, -2px);
}


/* ============================================================
   11. CARD-LIFT SHADOW EFFECT
   Applied to the inquiry form card and any elevated card surface.
   ============================================================ */

.card-lift {
  position: relative;
}
.card-lift::before,
.card-lift::after {
  content: '';
  position: absolute;
  z-index: -1;
  bottom: 26px;
  top: 80%;
  width: 47%;
  max-width: 350px;
  background: rgba(22, 36, 26, 0.5);
  box-shadow: 0 26px 28px rgba(22, 36, 26, 0.5);
}
.card-lift::before {
  left: 14px;
  transform: rotate(-6deg);
}
.card-lift::after {
  right: 14px;
  transform: rotate(6deg);
}


/* ============================================================
   12. OFFICIAL-LINK / EXTERNAL LINK (standalone, outside cards)
   ============================================================ */

.link-external {
  display: inline-flex;
  align-items: center;
  gap: 7px;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: var(--w-semibold);
  letter-spacing: 0.04em;
  color: var(--accent-strong);
  text-decoration: none;
  text-transform: uppercase;
}
.link-external svg {
  transition: transform var(--dur-base) var(--ease-out);
}
.link-external:hover svg,
.link-external:focus-visible svg {
  transform: translate(2px, -2px);
}


/* ============================================================
   13. HEADER (dg-header, dg-scroll-bar, page-template-*)
   .dg-header must be assigned as a CSS Class on the Theme Builder
   header Section (Section > Advanced > CSS Class).
   ============================================================ */

/* Base transition — always present */
.dg-header {
  /* The reference header is pinned via `position: fixed`. Divi's Theme
     Builder header template has its own "Fixed Position" toggle that's
     meant to do this, but if that toggle is ever off (or reset) the header
     silently falls back to static/relative flow and scrolls away with the
     page. Setting it here in CSS makes the pinned header a guarantee of
     the theme rather than a Divi setting someone has to remember to keep
     enabled. */
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  z-index: 500;
  /* Divi's Theme Builder assigns this header section a Custom Margin of
     15px top/bottom by default (its own generated inline rule,
     `.et_pb_section_0_tb_header.et_pb_section { margin: 15px 0 }` — 2
     classes). That beats a plain `.dg-header { margin: 0 }` (1 class) on
     specificity alone even with neither side using !important, which is
     why a first pass at this rule had no effect — confirmed directly by
     inspecting computed styles after deploying it. A fixed-position
     element still respects its own margin box, so that 15px top margin
     was pushing the header down from the viewport's actual top edge — the
     "gap above the header" visible on the public, logged-out site
     (nothing to do with the wp-admin toolbar). !important forces the win
     regardless of Divi's class count. */
  margin: 0 !important;
  transition: background var(--dur-base) var(--ease-out),
              backdrop-filter var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}

/* Logged-in admin-bar offset — public/logged-out visitors must always see
   `top: 0` (the rule above); WordPress's own black toolbar is fixed at
   32px (46px under its own 782px mobile breakpoint) and pushes fixed-
   position elements down to clear it. Scoped strictly to `body.admin-bar`
   so this never affects the real, logged-out site. */
body.admin-bar .dg-header {
  top: 32px;
}
@media (max-width: 782px) {
  body.admin-bar .dg-header {
    top: 46px;
  }
}

/* Header row width/gutter/height — Divi's row default (1080px max-width,
   no horizontal padding, ~70px tall) was never overridden, so the header
   was noticeably more cramped than every other section on the site. The
   rest of the theme already standardizes on --content-max (1280px) and
   --gutter (clamp 20–80px, 72px at typical desktop widths) — reusing them
   here instead of guessing new values matches the reference's own
   computed 1280px / 72px / 104px exactly (checked directly). Scoped to
   Divi's own desktop breakpoint (980px+) so the mobile header (measured
   ~57–60px tall — see "MOBILE NAV PARITY LOCK" below) is untouched. */
@media (min-width: 981px) {
  .dg-header .et_pb_row {
    max-width: var(--content-max) !important;
    padding-left: var(--gutter) !important;
    padding-right: var(--gutter) !important;
    min-height: 104px;
  }

  /* Divi renders each header column as `flex-direction: column` with
     `justify-content: normal` (-> flex-start), which packs the logo/nav/
     button to the TOP of the 104px row instead of centering them —
     confirmed directly: logo sat 5px from the row top instead of the
     22px a centered 60px-tall logo needs, nav sat 12px instead of 36.5px.
     The row itself was never too tall; the leftover space this left at
     the bottom of the row is exactly the "cream band" / "too much
     height" the header appeared to have. Centering the column's main
     axis (column direction = vertical main axis, so this is
     justify-content, not align-items) fixes logo, nav, and the INQUIRE
     button in one rule since all three columns share this layout. */
  .dg-header .et_pb_row > .et_pb_column {
    justify-content: center;
  }
}

/* Divi's own section-level default (`padding: 10px 10px 0`, asymmetric —
   10px top, 0 bottom) is superfluous now that the row above sets its own
   exact height and left/right gutter directly, and its asymmetry was
   compounding the top-packed-content issue above. */
.dg-header {
  padding: 0 !important;
}

/* Scrolled / solid state (JS adds .scrolled after 40px scroll) and
   light-hero pages — About, Inquire (always solid — body class set by
   functions.php's dg-hero-dark/dg-hero-light filter; NOT a home-vs-inner
   split, see that filter's comment).
   Divi auto-generates its own per-instance rule for this exact header
   section's own (blank/none) Background Color setting:
   `.et-l--header > .et_builder_inner_content .et_pb_section.et_pb_section_0_tb_header
   { background-color: rgba(255,255,255,0) !important; }` — 4 classes,
   !important, beating a plain `.dg-header.scrolled`/`.dg-hero-light
   .dg-header` selector (2-3 classes) even with our own !important. This is
   why the header was staying visually transparent on every inner page
   (and once scrolled on the homepage) despite this rule "matching" —
   Divi's rule won specifically on the background-color component (the
   only one that actually needs opacity to render; the dark-hero
   transparent-gradient state below is unaffected because a gradient is a
   background-IMAGE, which Divi's rule never touches). `body
   #page-container` is the same ID-anchored specificity fix used
   elsewhere in this file for the same Divi-per-instance-rule problem. */
body #page-container .dg-header.scrolled,
body.dg-hero-light #page-container .dg-header {
  background: rgba(246, 241, 231, 0.78) !important;
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  box-shadow: 0 10px 30px -18px rgba(22, 36, 26, 0.30);
}

/* Dark-hero pages — Home, Stringfield, Serenity, Legacy — transparent
   gradient before scroll */
.dg-hero-dark .dg-header:not(.scrolled) {
  background: linear-gradient(
    to bottom,
    rgba(22, 36, 26, 0.62) 0%,
    rgba(22, 36, 26, 0.30) 54%,
    rgba(22, 36, 26, 0) 100%
  ) !important;
  box-shadow: none;
}

/* Nav link typography — the Divi Menu module ships its own theme default
   (Abel, 700, 14px, no letter-spacing, 0.4s ease-in-out color transition)
   and nothing here was ever overriding it, only color was. That default
   font is exactly why the header read as "still Divi" rather than the
   reference — values below are the reference's own computed styles
   (Hanken Grotesk / 500 / 15px / 0.6px letter-spacing / 0.18s cubic-bezier),
   not a guess.
   NOTE: the Divi Menu module renders the real nav as .et-menu-nav > ul.et-menu,
   not .et_pb_menu__nav — that class does not exist in the rendered DOM, so
   every rule below targets both to cover Divi's actual markup. */
.dg-header .et_pb_menu__nav > ul > li > a,
.dg-header .et-menu-nav > ul > li > a {
  font-family: var(--font-sans) !important;
  font-size: 15px !important;
  font-weight: var(--w-medium) !important;
  letter-spacing: 0.04em !important;
  transition: color var(--dur-fast) var(--ease-out) !important;
  position: relative;
  padding-bottom: 2px;
}
.dg-header .et_pb_menu__nav > ul,
.dg-header .et-menu-nav > ul {
  gap: 32px;
}
/* Divi's own <li> already carries `padding: 0 11px` as its spacing
   mechanism — adding `gap` on top of that (rather than instead of it)
   stacked both, pushing the effective gap to ~54px and overflowing the
   row width, which is what wrapped "About"/INQUIRE onto a second line.
   Zeroing it out here makes `gap: 32px` the only spacing mechanism,
   matching the reference exactly (a plain flex `gap`, no per-item
   padding). */
.dg-header .et_pb_menu__nav > ul > li,
.dg-header .et-menu-nav > ul > li {
  padding-left: 0 !important;
  padding-right: 0 !important;
}

/* Nav link color — dark-hero pages before scroll (paper text).
   Deliberately NOT using the bare `.et_pb_menu__nav a` / `.et-menu-nav a`
   descendant form here (only the `> ul > li > a` top-level form) — that
   broader selector also matches links inside `ul.sub-menu` (About Jeff,
   Legacy), and at 4 classes it beat the dedicated `.sub-menu a { color:
   ink-700 !important }` rule below (3 classes) on specificity. The
   dropdown panel itself is always the solid paper-98 fill regardless of
   header state, so its links forcing paper-96 text read as
   near-invisible white-on-cream — confirmed directly on a dark-hero page
   before scroll. Scoping to top-level links only lets the submenu rule's
   ink-700 apply the way it already does correctly once scrolled. */
.dg-hero-dark .dg-header:not(.scrolled) .et_pb_menu__nav > ul > li > a,
.dg-hero-dark .dg-header:not(.scrolled) .et-menu-nav > ul > li > a {
  color: var(--paper-96) !important;
  text-shadow: var(--text-shadow-on-dark);
}
.dg-hero-dark .dg-header:not(.scrolled) .et_pb_menu__nav > ul > li > a:hover,
.dg-hero-dark .dg-header:not(.scrolled) .et-menu-nav > ul > li > a:hover {
  color: var(--paper) !important;
}

/* Divi auto-generates its own per-instance rule for the active nav item —
   `.et_pb_menu_0_tb_header.et_pb_menu ul li.current-menu-item > a { color:
   var(--gcid-body-color) !important }` (3 classes, !important) — which beat
   both color rules below (2 classes each, also !important) specifically on
   "The Communities" (the current-page link), leaving it stuck gray in every
   header state instead of following paper/ink like every other link.
   `body #page-container` is the same ID-anchored specificity fix already
   used elsewhere in this file for the same class of Divi-rule conflict. */
body #page-container .dg-hero-dark .dg-header:not(.scrolled) .et-menu-nav > ul > li.current-menu-item > a {
  color: var(--paper-96) !important;
}
body #page-container .dg-header.scrolled .et-menu-nav > ul > li.current-menu-item > a,
body.dg-hero-light #page-container .dg-header .et-menu-nav > ul > li.current-menu-item > a {
  color: var(--ink-700) !important;
}

/* Nav link color — solid header (ink text) */
.dg-header.scrolled .et_pb_menu__nav a,
.dg-hero-light .dg-header .et_pb_menu__nav a,
.dg-header.scrolled .et-menu-nav a,
.dg-hero-light .dg-header .et-menu-nav a {
  color: var(--ink-700) !important;
  text-shadow: none;
}
.dg-header.scrolled .et_pb_menu__nav > ul > li > a:hover,
.dg-hero-light .dg-header .et_pb_menu__nav > ul > li > a:hover,
.dg-header.scrolled .et-menu-nav > ul > li > a:hover,
.dg-hero-light .dg-header .et-menu-nav > ul > li > a:hover {
  color: var(--accent-strong) !important;
}

/* Active-page underline. On the reference this is NOT a hover effect —
   confirmed directly: hovering a non-current link does nothing, only the
   link matching aria-current="page" keeps a permanent underline
   (scaleX(1), transform-origin left, 0.32s reveal on the route that just
   became active). The previous version of this rule also fired on
   `:hover`, which the reference never does — every link would show a
   transient underline that isn't part of the real design. */
.dg-header .et_pb_menu__nav > ul > li:not(.menu-item-has-children) > a::after,
.dg-header .et-menu-nav > ul > li:not(.menu-item-has-children) > a::after {
  content: '';
  position: absolute;
  bottom: -3px;
  left: 0;
  width: 100%;
  height: 1px;
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-base) var(--ease-out);
}
.dg-header.scrolled .et_pb_menu__nav > ul > li:not(.menu-item-has-children) > a::after,
.dg-hero-light .dg-header .et_pb_menu__nav > ul > li:not(.menu-item-has-children) > a::after,
.dg-header.scrolled .et-menu-nav > ul > li:not(.menu-item-has-children) > a::after,
.dg-hero-light .dg-header .et-menu-nav > ul > li:not(.menu-item-has-children) > a::after {
  background: var(--accent);
}
.dg-hero-dark .dg-header:not(.scrolled) .et_pb_menu__nav > ul > li:not(.menu-item-has-children) > a::after,
.dg-hero-dark .dg-header:not(.scrolled) .et-menu-nav > ul > li:not(.menu-item-has-children) > a::after {
  background: var(--paper-75);
}
.dg-header .et_pb_menu__nav > ul > li.current-menu-item:not(.menu-item-has-children) > a::after,
.dg-header .et-menu-nav > ul > li.current-menu-item:not(.menu-item-has-children) > a::after {
  transform: scaleX(1);
}

/* Dropdown caret ("About") — Divi's own ::after icon-font indicator on
   menu-item-has-children. Excluded from the underline rules above (they'd
   otherwise clip its glyph to height:1px, i.e. this exact bug — invisible
   regardless of color). Only recolor it here to follow the same
   paper/ink swap the link text itself uses. */
.dg-hero-dark .dg-header:not(.scrolled) .et_pb_menu__nav > ul > li.menu-item-has-children > a::after,
.dg-hero-dark .dg-header:not(.scrolled) .et-menu-nav > ul > li.menu-item-has-children > a::after {
  color: var(--paper-96) !important;
}
.dg-header.scrolled .et_pb_menu__nav > ul > li.menu-item-has-children > a::after,
.dg-hero-light .dg-header .et_pb_menu__nav > ul > li.menu-item-has-children > a::after,
.dg-header.scrolled .et-menu-nav > ul > li.menu-item-has-children > a::after,
.dg-hero-light .dg-header .et-menu-nav > ul > li.menu-item-has-children > a::after {
  color: var(--ink-700) !important;
}

/* Dropdown menu */
.dg-header .et_pb_menu__nav ul.sub-menu,
.dg-header .et-menu-nav ul.sub-menu {
  background: var(--paper-98) !important;
  border-top: 2px solid var(--accent) !important;
  box-shadow: var(--shadow-md);
  border-radius: 0 0 var(--radius-md) var(--radius-md);
}
.dg-header .et_pb_menu__nav ul.sub-menu a,
.dg-header .et-menu-nav ul.sub-menu a {
  font-family: var(--font-sans) !important;
  font-size: 14px !important;
  font-weight: var(--w-medium) !important;
  letter-spacing: 0.04em !important;
  color: var(--ink-700) !important;
  padding: 11px 22px !important;
  transition: color var(--dur-fast) var(--ease-out),
              background-color var(--dur-fast) var(--ease-out) !important;
}
.dg-header .et_pb_menu__nav ul.sub-menu a:hover,
.dg-header .et-menu-nav ul.sub-menu a:hover {
  color: var(--accent-strong) !important;
  background-color: rgba(156, 107, 66, 0.06) !important;
}

/* Logo sizing — originally matched the reference's own fixed pixel sizes
   exactly (248x60 unscrolled, 210x48 scrolled/inner — read directly from
   its rendered inline styles, not a guess). The unscrolled height was
   bumped from 60px to 68px on client request — the white logo, shown
   before the header goes solid/sticky, reads a touch small at 60px and
   should feel a bit more present. Scrolled/inner height (48px, below)
   deliberately untouched.
   The logo is TWO separate Divi Image modules (dark + light variants,
   see "INQUIRE header CTA" note below on the button for the parallel
   story) — `.et_pb_menu__logo`/`.logo_container` were leftover from
   when this assumed the Divi Menu module's own built-in logo slot.
   Since the dark/light swap moved it to plain Image modules, those
   selectors never matched anything and the logo rendered completely
   unconstrained (auto-sized off the source file's natural dimensions)
   at every viewport, not just mobile — this is why it looked wrong
   everywhere, not only on narrow screens. `.et_pb_image_wrap` is
   Divi's own stable wrapper class for every Image module, not a
   fragile per-instance one. */
.dg-header .et_pb_image_wrap img {
  height: 68px !important;
  width: auto !important;
  /* Divi's own phone-breakpoint per-instance width (e.g.
     `.et_pb_image_1_tb_header { width: 55px }`, generated by the Theme
     Builder's responsive image-module-width setting) squeezes the flex
     item's cross size below the logo's true aspect ratio — confirmed
     directly: with `height: 60px` forced and width unable to keep up, the
     rendered logo came out ~55x60 (nearly square) instead of the correct
     ~107x60 the same SVG renders at on desktop and on the reference at
     any width. `flex-shrink: 0` on the image and its two ancestor wrappers
     stops that per-instance width from compressing it. */
  flex-shrink: 0 !important;
  transition: height var(--dur-base) var(--ease-out);
}
.dg-header .et_pb_image_0_tb_header,
.dg-header .et_pb_image_1_tb_header,
.dg-header .et_pb_image_wrap {
  width: auto !important;
  flex-shrink: 0 !important;
}
.dg-header.scrolled .et_pb_image_wrap img,
.dg-hero-light .dg-header .et_pb_image_wrap img {
  height: 48px !important;
}

/* Dark/light logo swap — two Divi Image modules in the same header row:
   et_pb_image_0_tb_header (dark logo) and et_pb_image_1_tb_header (white
   logo). Divi has its own generated rule for the white-logo module,
   `.et_pb_image_1_tb_header { display: none; }` — a module-level toggle
   set in the Divi builder itself, not anything in this theme's files —
   which hides it unconditionally. That never mattered while
   dg-hero-dark pages were incorrectly forced solid (dark logo on a solid
   header is correct), but now that they correctly go transparent before
   scroll, the white logo needs to actually show there. Divi's rule is a
   single class with no !important, so a plain override here is enough. */
.dg-hero-dark .dg-header:not(.scrolled) .et_pb_image_1_tb_header {
  display: flex !important;
}
.dg-hero-dark .dg-header:not(.scrolled) .et_pb_image_0_tb_header {
  display: none !important;
}

/* INQUIRE header CTA — a Divi Button module in the Theme Builder header,
   not a menu item, so it doesn't inherit any of the nav-link rules above.
   Divi's own module defaults render it as a solid dark-green fill; these
   overrides match the reference's ghost button (values measured off the
   reference's rendered computed styles). `body #page-container` matches
   Divi's own wrapper for specificity.
   Forensic parity fix (July 2026): line-height, display, and white-space
   are set explicitly because Divi's module defaults (1.7em line-height,
   inline-block) otherwise leak through and render the button 40.4px tall
   vs the reference's 32px; the transition carries !important because
   Divi's own `transition: all` outranks it otherwise. Box math:
   12px text + 2x9px padding + 2x1px border = 32px tall. */
body #page-container .dg-header a.et_pb_button {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  line-height: 1 !important;
  white-space: nowrap !important;
  border-radius: var(--radius-sm) !important;
  padding: 9px 18px !important;
  font-family: var(--font-sans) !important;
  font-size: 12px !important;
  font-weight: var(--w-semibold) !important;
  letter-spacing: 0.14em !important;
  text-transform: uppercase !important;
  color: var(--paper) !important;
  background: transparent !important;
  border: 1px solid rgba(246, 241, 231, 0.5) !important;
  transition: background-color var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out) !important;
}
/* Measured directly on the reference: on dark-hero pages the ghost button
   persists in EVERY scroll state. Only light-hero pages (About, Inquire)
   render the solid primary button: pine-700, transparent border, pine-900
   on hover. */
body.dg-hero-light #page-container .dg-header a.et_pb_button {
  background: var(--pine-700) !important;
  border-color: transparent !important;
}
/* Ghost hover (dark-hero pages, any scroll state) — reference outline
   hover fills solid pine-700 and keeps the paper-50 border. */
body #page-container .dg-header a.et_pb_button:hover {
  background: var(--pine-700) !important;
  border-color: rgba(246, 241, 231, 0.5) !important;
}
/* Solid (light-hero) hover — reference primary hover: pine-900. */
body.dg-hero-light #page-container .dg-header a.et_pb_button:hover {
  background: var(--pine-900) !important;
  border-color: transparent !important;
}
/* Client revision (July 2026): once the header goes sticky (.scrolled) the
   ghost button read as lost/washed-out against page content — fill it with
   the solid dark green instead. Intentional divergence from the reference
   (which keeps the ghost in all scroll states on dark-hero pages); client
   preference wins. Declared after the ghost rules so it takes the cascade
   when both apply. */
body #page-container .dg-header.scrolled a.et_pb_button {
  background: var(--pine-700) !important;
  border-color: transparent !important;
}
body #page-container .dg-header.scrolled a.et_pb_button:hover {
  background: var(--pine-900) !important;
  border-color: transparent !important;
}
body #page-container .dg-header a.et_pb_button:active,
body #page-container .dg-header a.et_pb_button:focus {
  transform: none !important;
}
/* Divi's default Button-module arrow icon (::after, ETmodules glyph) —
   fades in on hover by default. The reference's INQUIRE button is plain
   text, no icon in any state. */
body #page-container .dg-header a.et_pb_button::after {
  display: none !important;
  content: none !important;
}

/* Scroll progress bar — created by dg-header.js inside .dg-header.
   Absolute (not fixed) on purpose: .dg-header is position: fixed, so
   bottom: 0 here pins the bar to the underside of the sticky nav — the
   reference site's placement. The old position: fixed put it at the
   bottom of the *viewport* except when the header's backdrop-filter
   happened to capture it as a containing block. */
.dg-scroll-bar {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 3px;
  background: var(--accent);
  width: 0%;
  transition: width 0.1s linear, opacity 0.2s var(--ease-out);
  z-index: 9999;
  opacity: 0;
  pointer-events: none;
}

/* Mobile menu — matches the reference's full-width dropdown flush under
   the header exactly (colors, spacing, dividers, submenu treatment).
   Divi's own `.et_mobile_menu` is `position: absolute` relative to
   whatever positioned ancestor happens to be nearest in the header's
   internal column structure, which caps it to that column's width (a
   right-anchored floating box, not full-width). `position: fixed` here
   bypasses that entirely and anchors to the viewport instead, which is
   also why it doesn't fight Divi's own inline width/positioning styles
   the way another `position: absolute` override would. `top` matches
   `.dg-header`'s own height (68px at the sizes set elsewhere in this
   file — logo/nav padding don't scale with viewport, so this holds
   across mobile widths). */
/* Custom animated hamburger, replacing Divi's static icon-font glyph
   (.mobile_menu_bar::before, ETmodules content:"a") — that's a single
   character, so it can't morph into an "X" on its own. Built instead
   from the span itself (middle bar) plus ::before/::after (top/bottom
   bars), each independently transformable. Divi toggles `.opened` on
   the parent `.mobile_nav` on click — no JS beyond that is needed. */
.dg-header .mobile_menu_bar {
  position: relative;
  display: inline-block;
  width: 24px;
  height: 2px;
  vertical-align: middle;
  background-color: var(--paper-96);
  transition: background-color var(--dur-base) var(--ease-out),
              opacity var(--dur-fast) var(--ease-out);
}
.dg-header .mobile_menu_bar::before {
  font: unset !important;
}
.dg-header .mobile_menu_bar::before,
.dg-header .mobile_menu_bar::after {
  content: '' !important;
  position: absolute;
  left: 0;
  width: 24px;
  height: 2px;
  background-color: var(--paper-96);
  transition: transform 0.32s var(--ease-out), top 0.32s var(--ease-out),
              background-color var(--dur-base) var(--ease-out);
}
.dg-header .mobile_menu_bar::before { top: -7px; }
.dg-header .mobile_menu_bar::after  { top: 7px; }

/* Solid header / light-hero pages — ink instead of paper */
.dg-header.scrolled .mobile_menu_bar,
.dg-header.scrolled .mobile_menu_bar::before,
.dg-header.scrolled .mobile_menu_bar::after,
body.dg-hero-light .dg-header .mobile_menu_bar,
body.dg-hero-light .dg-header .mobile_menu_bar::before,
body.dg-hero-light .dg-header .mobile_menu_bar::after {
  background-color: var(--ink-900);
}

/* Opened — collapse the middle bar, rotate top/bottom into an X.
   Color intentionally NOT overridden here — confirmed directly against
   the reference that the X keeps whatever color the bars already had
   (paper on a dark-hero page, ink once scrolled/light), the same as
   every other header element (logo, nav links). A previous version of
   this rule forced ink-900 unconditionally on the assumption the panel
   behind it was always the solid fill it opens onto, but the header
   itself (where the icon actually sits) stays in its own transparent/
   dark-hero state independent of the panel opening below it — the
   existing `.dg-header.scrolled` / `.dg-hero-light` (ink) and
   `.dg-hero-dark .dg-header:not(.scrolled)` (paper) rules above already
   apply regardless of `.opened`, so removing the override here is enough. */
.dg-header .mobile_nav.opened .mobile_menu_bar {
  background-color: transparent;
}
.dg-header .mobile_nav.opened .mobile_menu_bar::before,
.dg-header .mobile_nav.opened .mobile_menu_bar::after {
  top: 0;
}
.dg-header .mobile_nav.opened .mobile_menu_bar::before {
  transform: rotate(45deg);
}
.dg-header .mobile_nav.opened .mobile_menu_bar::after {
  transform: rotate(-45deg);
}
/* START MOBILE NAV PARITY LOCK
   Divi's own `.et_mobile_menu` dropdown is replaced outright, not patched
   further — it's built by Divi's own JS at runtime rather than server-
   rendered, and on every real page load it simply didn't exist yet at the
   point dg-header.js ran (a timing race, not a selector bug), which is why
   the INQUIRE CTA never actually made it into that panel despite code that
   was supposed to clone it in. The replacement panel (`.dg-mobile-nav`,
   built in dg-header.js from the same `.et-menu-nav` link data and the
   real INQUIRE button) is fully self-contained and doesn't depend on
   Divi's menu JS running at all.
   Scoped to Divi's own 980px breakpoint throughout — none of this reaches
   desktop. */
.dg-mobile-nav {
  /* Unconditional, outside the media query below on purpose: a bare
     appended <div> defaults to `display: block` with no rule to stop it,
     so without this a desktop viewport would render the panel the moment
     dg-header.js appends it. dg-header.js also guards its own
     `panel.style.display = 'block'` behind a matchMedia(980px) check —
     belt and suspenders, since an inline style would otherwise beat this
     rule regardless of viewport. */
  display: none;
}
@media (max-width: 980px) {
  .dg-header .et_mobile_menu {
    display: none !important;
  }

  /* The real header-bar INQUIRE button stays hidden on mobile — the
     `.dg-mobile-nav__cta` link inside the custom panel below is built
     from its href/label in dg-header.js, so leaving the original visible
     too would show INQUIRE twice. */
  .dg-header .et_pb_button_module_wrapper a.et_pb_button {
    display: none !important;
  }

  /* Divi's own phone-breakpoint responsive column widths (its per-
     instance `.et_flex_column_24_24_phone` etc., generated by the Theme
     Builder's row/column width settings for the "Phone" breakpoint) stack
     the header's 3 columns to 100% width each below ~767px — confirmed
     directly: logo, nav/hamburger, and button columns each rendered full-
     width and stacked vertically, which pushed the hamburger to x:535 on
     a 485px-wide viewport, off-screen and untappable. The header row was
     never meant to reflow like a normal content row; forcing it back to a
     single non-wrapping row (content-sized columns) keeps the hamburger
     in place at every width down to the narrowest phones, matching the
     reference (which never stacks its header at any width). */
  .dg-header .et_pb_row {
    flex-wrap: nowrap !important;
    justify-content: space-between !important;
  }
  .dg-header .et_pb_row > .et_pb_column {
    width: auto !important;
    flex: 0 0 auto !important;
  }
  /* Column 3 (the header-bar INQUIRE button) has nothing left to show —
     its button is already hidden above — so drop the column too instead
     of leaving an empty 0-width flex item in the row. */
  .dg-header .et_pb_row > .et_pb_column:nth-child(3) {
    display: none !important;
  }
  /* The hamburger's column still collapses to 0 width even with the
     overrides above (Divi's per-instance phone rule wins on some inner
     dimension we didn't chase further), but `justify-content: space-
     between` above already lands that 0-width column's own box exactly
     on the row's right edge — confirmed directly (column box x matched
     the row's right edge to the pixel). Positioning the hamburger
     absolutely within that correctly-placed column, rather than relying
     on the column's collapsed width to contain it, keeps it pinned to
     the true right edge instead of overflowing off-screen.
     Both wrapper divs between `.mobile_nav` and the column are
     `position: relative` themselves — left alone, `position: absolute`
     below would bind to the nearer of those two (whichever still has an
     intrinsic width, e.g. the menu module's own fixed-width phone rule)
     instead of the correctly-positioned column, landing off-center again.
     Neutralizing them here makes the column the actual containing block. */
  .dg-header .et_pb_menu_inner_container,
  .dg-header .et_pb_menu_0_tb_header {
    position: static !important;
  }
  .dg-header .mobile_nav {
    position: absolute !important;
    right: var(--gutter);
    top: 50%;
    transform: translateY(-50%);
    margin: 0 !important;
  }

  .dg-mobile-nav {
    width: 100%;
    background: var(--paper-98);
    backdrop-filter: saturate(140%) blur(10px);
    -webkit-backdrop-filter: saturate(140%) blur(10px);
    box-shadow: var(--shadow-md);
    border-top: 1px solid var(--border-hairline);
    max-height: calc(100vh - 68px);
    overflow-y: auto;
    opacity: 0;
    transform: translateY(-8px);
    transition: opacity var(--dur-base) var(--ease-out),
                transform var(--dur-base) var(--ease-out);
  }
  .dg-mobile-nav.dg-mobile-nav--open {
    opacity: 1;
    transform: translateY(0);
  }
  .dg-mobile-nav__inner {
    display: grid;
    gap: 8px;
    padding: 24px var(--gutter) 32px;
  }
  .dg-mobile-nav__link,
  .dg-mobile-nav__link:visited {
    font-family: var(--font-sans);
    font-size: 16px;
    font-weight: var(--w-medium);
    color: var(--ink-900);
    text-decoration: none;
    border-bottom: 1px solid var(--border-soft);
    padding: 10px 0;
  }
  .dg-mobile-nav__link--sub {
    font-size: 14px;
    font-weight: var(--w-regular);
    color: var(--taupe);
    padding: 8px 0 8px 16px;
  }
  .dg-mobile-nav__cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    font-family: var(--font-sans);
    font-size: 13px;
    font-weight: var(--w-semibold);
    letter-spacing: var(--ls-caps);
    text-transform: uppercase;
    text-decoration: none;
    line-height: 1;
    color: var(--paper);
    background: var(--bronze-500);
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    padding: 14px 28px;
    margin-top: 16px;
    transition: background-color var(--dur-fast) var(--ease-out),
                color var(--dur-fast) var(--ease-out),
                border-color var(--dur-fast) var(--ease-out);
    /* `.dg-mobile-nav__inner` is a CSS grid, and grid items default to
       `justify-items: stretch` — that silently overrode the button's own
       `display: inline-flex` and stretched it to the full row width.
       The reference's CTA is compact/content-width, not full-bleed. */
    justify-self: start;
  }
  /* Reference accent-variant hover: bronze-600. */
  .dg-mobile-nav__cta:hover,
  .dg-mobile-nav__cta:focus-visible {
    background: var(--bronze-600);
    color: var(--paper);
  }
}
/* END MOBILE NAV PARITY LOCK */


/* ============================================================
   14. FOOTER (dg-footer)
   Rendered by partials/footer/site-footer.php, appended via the
   wp_footer action in functions.php (see the comment there — a
   child-theme footer.php template override was tried first and had no
   effect on this install, and a whole-page output-buffer regex swap
   after that caused a fatal error in production; wp_footer is the
   same core hook every enqueued script on this theme already relies
   on, so it's the most-proven option available).
   Every value below was read directly off the reference's rendered
   computed styles, not estimated: colors map exactly onto existing
   tokens (pine-900 bg, pine-100 links, pine-300 dim text, bronze-400
   accent, the existing --border-on-dark divider), confirming this
   token set was already correct — only the layout rules to actually
   use them were missing. Font sizes (11/14/13/12px) are hardcoded
   rather than reusing --t-eyebrow (12.5px) / --t-small (15px), because
   those tokens measured a half-to-full pixel off the reference's real
   values and this task calls for an exact match.
   ============================================================ */

/* Removing Divi's default footer shell.
   functions.php's widget_block_content filter already strips the actual
   widget CONTENT (the default Archives/Categories blocks) at the data
   level — after that filter runs, `#footer-widgets` genuinely has
   nothing left inside it, so hiding the now-empty wrapper here is
   cleanup of dead space, not content removal. `#footer-bottom` (Divi's
   hardcoded "Designed by Elegant Themes | Powered by WordPress" credit
   line + default social icons) has no equivalent WordPress filter this
   child theme's code has visibility into without server-side access to
   the parent theme's source, so it's suppressed here instead — `display:
   none` genuinely removes an element from the accessibility tree (unlike
   visibility:hidden/opacity:0), so screen-reader users don't encounter
   it either. Scoped to these two specific IDs only, not a general rule. */
#main-footer #footer-widgets,
#main-footer #footer-bottom {
  display: none;
}

.dg-footer {
  background: var(--pine-900) !important;
  color: var(--pine-100);
}

.dg-footer .footer-inner {
  max-width: var(--content-max);
  margin: 0 auto;
  padding: 60px var(--gutter) 40px;
}

/* Back-to-top row — the reference's only footer divider sits here, below
   the button and above the columns. There is no second divider before
   the copyright row (see .footer-copyright-row below) — confirmed
   directly, not a guess, since it would be easy to assume symmetry. */
.footer-top-row {
  display: flex;
  justify-content: flex-end;
  padding-bottom: 44px;
  margin-bottom: 48px;
  border-bottom: 1px solid var(--border-on-dark);
}
.footer-back-to-top {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: var(--w-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--paper) !important;
  background: var(--bronze-400);
  border-radius: var(--radius-pill);
  padding: 11px 24px;
  text-decoration: none !important;
  line-height: 1;
  cursor: pointer;
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.30);
  transition: background-color var(--dur-base) var(--ease-out),
              box-shadow var(--dur-base) var(--ease-out);
}
.footer-back-to-top:hover,
.footer-back-to-top:focus-visible {
  background: var(--bronze-500);
  color: var(--paper) !important;
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45);
}

.footer-columns {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 48px;
}
@media (max-width: 767px) {
  .footer-columns {
    grid-template-columns: 1fr;
  }
}

.footer-logo {
  height: 44px;
  width: auto;
}
.footer-desc {
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.7;
  color: var(--pine-100);
  margin: 22px 0 0;
  max-width: 30ch;
}
.footer-address {
  font-family: var(--font-sans);
  font-style: normal;
  font-size: 13px;
  line-height: 1.8;
  color: var(--pine-300);
  margin-top: 18px;
}
.footer-address a {
  line-height: inherit;
}

.dg-footer .footer-col-eyebrow {
  font-family: var(--font-sans);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--bronze-400);
  margin: 0 0 16px;
}

.dg-footer a {
  font-family: var(--font-sans);
  font-size: 14px;
  color: var(--pine-100) !important;
  text-decoration: none;
  line-height: 2;
  transition: color var(--dur-fast) var(--ease-out);
}
.dg-footer a:hover,
.dg-footer a:focus-visible {
  color: var(--paper) !important;
}

.footer-copyright-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  padding-top: 28px;
}
.footer-copyright-row p {
  font-family: var(--font-sans);
  font-size: 12px;
  color: var(--pine-300);
  margin: 0;
}


/* ============================================================
   15. FORMS — FLUENT FORMS SKIN
   Overrides Fluent Forms' default styles to match the design system.
   Replaces the theme's original Gravity Forms skin — that plugin was
   never actually installed on this site (only an inert Gravity Forms
   Zero Spam add-on was), so these rules never had anything to style.
   Class names below (.ff-el-form-control, .ff-el-group, etc.) are read
   directly off Fluent Forms' own rendered markup, not guessed from docs.
   ============================================================ */

.fluentform .ff-el-form-control {
  font-family: var(--font-sans) !important;
  font-size: var(--t-body) !important;
  color: var(--text-heading) !important;
  background: var(--paper) !important;
  border: 1px solid var(--border-hairline) !important;
  border-radius: var(--radius-sm) !important;
  padding: 14px 16px !important;
  width: 100% !important;
  transition: border-color var(--dur-fast) var(--ease-out),
              box-shadow var(--dur-fast) var(--ease-out) !important;
  box-shadow: none !important;
}
.fluentform .ff-el-form-control:focus {
  outline: none !important;
  border-color: var(--accent) !important;
  box-shadow: var(--focus-ring) !important;
}

.fluentform textarea.ff-el-form-control {
  min-height: 120px !important;
  resize: vertical !important;
}

.fluentform .ff-el-input--label label {
  font-family: var(--font-sans) !important;
  font-size: var(--t-small) !important;
  font-weight: var(--w-medium) !important;
  color: var(--text-body) !important;
  letter-spacing: 0.02em !important;
  margin-bottom: 8px !important;
  display: inline-block;
}

/* Required asterisk — Fluent renders it as a label::after, not a separate
   element, so recolor it in place rather than styling a nonexistent node. */
.fluentform .ff-el-is-required label::after {
  color: var(--bronze-500) !important;
}

/* Submit button — mirrors the reference's form submit exactly: an accent
   Button at size lg (18px 38px, 14px type, --ls-caps tracking, 12px icon
   gap) with a trailing 16px arrow, and NOT full-width — the reference
   submit hugs its label. Fluent Forms renders a bare <button> with no
   icon slot, so the arrow is a ::after mask painted in the button's own
   text color, nudging on hover/focus at --dur-base like every other
   .btn arrow. */
.fluentform .ff-btn-submit {
  display: inline-flex !important;
  align-items: center !important;
  justify-content: center !important;
  gap: 12px !important;
  font-family: var(--font-sans) !important;
  font-size: 14px !important;
  font-weight: var(--w-semibold) !important;
  letter-spacing: var(--ls-caps) !important;
  text-transform: uppercase !important;
  line-height: 1 !important;
  white-space: nowrap !important;
  background: var(--accent) !important;
  color: var(--paper) !important;
  border: 1px solid transparent !important;
  border-radius: var(--radius-sm) !important;
  padding: 18px 38px !important;
  width: auto !important;
  cursor: pointer !important;
  transition: background var(--dur-fast) var(--ease-out),
              color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out) !important;
}
.fluentform .ff-btn-submit::after {
  content: "";
  width: 16px;
  height: 16px;
  flex-shrink: 0;
  background-color: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m12 5 7 7-7 7'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M5 12h14'/%3E%3Cpath d='m12 5 7 7-7 7'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform var(--dur-base) var(--ease-out);
}
.fluentform .ff-btn-submit:hover {
  background: var(--accent-strong) !important;
}
.fluentform .ff-btn-submit:hover::after,
.fluentform .ff-btn-submit:focus-visible::after {
  transform: translateX(3px);
}
@media (prefers-reduced-motion: reduce) {
  .fluentform .ff-btn-submit::after {
    transition: none;
  }
  .fluentform .ff-btn-submit:hover::after,
  .fluentform .ff-btn-submit:focus-visible::after {
    transform: none;
  }
}

/* Field spacing */
.fluentform .ff-el-group {
  margin-bottom: 20px !important;
}

/* Validation error state */
.fluentform .ff-el-is-error .ff-el-form-control {
  border-color: #8B4A3A !important;
}
.fluentform .error {
  font-family: var(--font-sans) !important;
  font-size: 13px !important;
  color: #8B4A3A !important;
  margin-top: 4px !important;
}

/* Confirmation message */
.ff-message-success {
  font-family: var(--font-sans);
  font-size: var(--t-body);
  color: var(--text-body);
  padding: 32px;
  background: var(--surface-card);
  border-radius: var(--radius-card);
  border-left: 3px solid var(--success);
}


/* ============================================================
   16. VISIONBAND ("Land Stewardship")
   Assign .vision-band as CSS Class on the Divi Section.
   Background gradient and photo-mask values below are read directly off
   the reference (deadstop-web-projects.vercel.app #vision, computed
   styles) for an exact match — not re-derived from design tokens.
   ============================================================ */

.vision-band {
  position: relative;
  overflow: hidden;
  /* 5-stop wash, dark pine fading into the photo's own golden-hour bronze
     tones, so the handoff to the masked image below isn't a hard seam. */
  background: linear-gradient(
    to right,
    rgb(22, 36, 26) 0%,
    rgb(28, 46, 33) 42%,
    rgb(51, 80, 65) 70%,
    rgb(135, 90, 53) 92%,
    rgb(156, 107, 66) 108%
  );
}

/* Photo sits above the gradient, masked so it only reveals itself on the
   right half — a real <img> (see vision-band.php) rather than a CSS
   custom-property background-image: WordPress's content sanitizer strips
   `--custom-prop:url(...)` out of inline style attributes, which is why
   the previous version of this section never actually showed a photo. */
.vision-photo-wrap {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

.vision-photo-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center 38%;
  -webkit-mask-image: linear-gradient(to right, transparent 0%, transparent 50%, #000 90%, #000 100%);
  mask-image: linear-gradient(to right, transparent 0%, transparent 50%, #000 90%, #000 100%);
}

/* Mobile/tablet: reference hides the photo outright (matches its
   "max-md:hidden!" wrapper class) AND drops the gradient for a flat wash —
   confirmed directly against the reference's computed styles at 500px
   (background-image: none, background-color: rgb(22, 36, 26), i.e. plain
   --pine-900), not the gradient's own 0% stop carried through. */
@media (max-width: 768px) {
  .vision-photo-wrap {
    display: none;
  }
  .vision-band {
    background: var(--pine-900);
  }
}

/* Content sits above the pseudo-element */
.vision-band .et_pb_row {
  position: relative;
  z-index: 1;
}

/* Text column — flush with the same left margin every other homepage
   section uses (its containing div is max-width:var(--content-max), see
   vision-band.php), capped to a readable width here. Reference keeps this
   left-aligned on desktop and centers it only at the mobile breakpoint. */
.vision-text-col {
  max-width: 640px;
  text-align: left;
}

@media (max-width: 768px) {
  .vision-text-col {
    margin: 0 auto;
    text-align: center;
  }
  /* .eyebrow-rule is display:flex, so text-align alone won't center its
     dash + label row — needs justify-content directly (same fix as the
     existing .eyebrow-center utility, scoped here instead of applied
     globally). */
  .vision-text-col .eyebrow-rule {
    justify-content: center;
  }
}


/* ============================================================
   17. SHOMESITES RELEASE ROWS ("Now Selling" — Stringfield page)
   HTML lives in a Divi Code Module on the Stringfield page, inside the
   SHomesites section (id="homesites"). Replaces the old invented 8-lot
   grid (Available/Reserved/Sold) — that mock data never matched a real
   release and was removed in the July 2026 master plan overhaul.
   ============================================================ */

.release-row {
  border-top: 1px solid var(--border-hairline);
  padding: 24px 0;
}
.release-row-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 24px;
  flex-wrap: wrap;
}
.release-row-name {
  font-family: var(--font-display);
  font-size: var(--t-title);
  font-weight: 400;
  color: var(--text-heading);
  margin: 0;
}
.release-row-meta {
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  font-weight: var(--w-semibold);
  color: var(--accent-strong);
  white-space: nowrap;
}
.release-row-blurb {
  font-family: var(--font-sans);
  font-size: 15px;
  line-height: 1.65;
  color: var(--text-body);
  margin: 8px 0 0;
  max-width: 52ch;
}
.release-row-link {
  margin-top: 4px;
  color: var(--accent-strong);
}


/* ============================================================
   18. TEAM CARDS
   Homepage only (JeffSection) — a 3D flip card ported from the
   approved Next.js reference (JeffSection.tsx's TeamCard): front
   face is the photo with a name/role caption; hovering/focusing
   flips it to a back face with name/role and a "Read bio" link to
   the matching About-page team row (#slug anchor, see
   about-team.php). A card-stack shadow fan + lift also plays on
   hover, layered on the outer link.
   The About page's own team rows (.about-team-row) are a separate,
   simpler two-column layout — see dg-shortcodes.css.
   ============================================================ */

.dg-team-card {
  display: block;
  position: relative;
  aspect-ratio: 4 / 5;
  border-radius: var(--radius-card);
  perspective: 1400px;
  text-decoration: none;
  /* Was a hardcoded 0.55s — now the shared --dur-slow token, same tier as
     every other large reveal/hover-zoom on the site. The 0.12s stagger
     delay is this component's own intentional timing, kept as-is. */
  transition: transform var(--dur-slow) var(--ease-out) 0.12s;
}
.dg-team-card:hover,
.dg-team-card:focus-within {
  transform: translateY(-6px);
}

/* Card-stack shadow panels — fan out ±6° behind the card on hover */
.dg-team-card::before,
.dg-team-card::after {
  content: '';
  position: absolute;
  z-index: -1;
  opacity: 0;
  width: 46%;
  top: 80%;
  bottom: 22px;
  background: rgba(22, 36, 26, 0.48);
  box-shadow: 0 24px 26px rgba(22, 36, 26, 0.48);
  transition: opacity 60ms var(--ease-out);
}
.dg-team-card::before { left: 14px; transform: rotate(-6deg); }
.dg-team-card::after  { right: 14px; transform: rotate(6deg); }
.dg-team-card:hover::before,
.dg-team-card:hover::after,
.dg-team-card:focus-within::before,
.dg-team-card:focus-within::after {
  opacity: 1;
  transition: opacity 0.3s var(--ease-out) 0.12s;
}

/* The flip itself — a rotator that fills the card, holding both faces */
.dg-team-card-rotator {
  position: relative;
  width: 100%;
  height: 100%;
  transform-style: preserve-3d;
  transition: transform 0.7s var(--ease-out);
}
.dg-team-card:hover .dg-team-card-rotator,
.dg-team-card:focus-within .dg-team-card-rotator {
  transform: rotateY(180deg);
}

.dg-team-card-face {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: var(--radius-card);
  backface-visibility: hidden;
  box-shadow: var(--shadow-sm);
}

/* Front face — photo + gradient name/role caption.
   The source photos are ~1:2 three-quarter-body shots; unzoomed in a 4:5
   card the subjects read small with a lot of office background. The scale
   + matching object-position/transform-origin crop each one to an
   editorial head-and-shoulders framing. Keeping object-position and
   transform-origin at the same focal point means that point stays fixed
   while the image scales, so the face lands at the same card position at
   every breakpoint (the card is 4:5 at all sizes). Per-person values
   below compensate for how far from the camera each subject stood, so
   all four faces render at the same visual size (~40% of card height)
   with the eyes in the upper third. */
.dg-team-card-face--front img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 50% var(--team-focus-y, 30%);
  transform: scale(var(--team-zoom, 1.5));
  transform-origin: var(--team-focus-x, 50%) var(--team-focus-y, 30%);
}
/* Person-specific focal points — Pam stands farthest from camera (most
   zoom), Jim closest (least). X pulls off-center subjects back to the
   middle of the card. */
.dg-team-card--pam-berry     { --team-zoom: 1.65; --team-focus-x: 58%; --team-focus-y: 37%; }
.dg-team-card--gianna-minton { --team-zoom: 1.5;  --team-focus-x: 71%; --team-focus-y: 26%; }
.dg-team-card--jim-clark     { --team-zoom: 1.35; --team-focus-x: 85%; --team-focus-y: 23%; }
.dg-team-card--debbie        { --team-zoom: 1.4;  --team-focus-x: 57%; --team-focus-y: 32%; }
.dg-team-caption {
  position: absolute;
  inset: auto 0 0 0;
  padding: 22px 20px;
  background: linear-gradient(to top, rgba(22, 36, 26, 0.82) 8%, rgba(22, 36, 26, 0) 100%);
}
.dg-team-caption-name {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 21px;
  line-height: 1.5;
  color: var(--paper);
  margin: 0;
}
.dg-team-caption-role {
  font-family: var(--font-sans);
  font-size: 11.5px;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: rgba(246, 241, 231, 0.78);
  margin: 6px 0 0;
}

/* Back face — name/role + "Read bio" link, bronze inner frame */
.dg-team-card-face--back {
  transform: rotateY(180deg);
  background: var(--paper-alt);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 28px 24px;
}
.dg-team-card-face--back::after {
  content: '';
  position: absolute;
  inset: 10px;
  border: 4px solid var(--bronze-400);
  pointer-events: none;
}
.dg-team-card-face--back .team-name {
  font-family: var(--font-display);
  font-size: 24px;
  color: var(--text-heading);
  margin: 0;
  font-weight: 400;
}
.dg-team-card-face--back .team-role {
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: var(--w-semibold);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 10px 0 0;
}
.dg-team-divider {
  display: block;
  width: 34px;
  height: 2px;
  background: var(--bronze-400);
  margin: 20px 0;
}
.team-readmore {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-sans);
  font-size: 13px;
  font-weight: var(--w-semibold);
  letter-spacing: 0.02em;
  color: var(--accent-strong);
}


/* ============================================================
   19. IMAGE HOVER
   Apply .img-hover to Divi Image Modules via CSS Class field.
   ============================================================ */

.img-hover {
  transition: transform var(--dur-slow) var(--ease-out);
}
.img-hover:hover {
  transform: scale(1.04);
}

/* Wrap image containers that should clip the scale */
.img-hover-wrap {
  overflow: hidden;
  border-radius: var(--radius-card);
}
.img-hover-wrap .img-hover:hover {
  transform: scale(1.04);
}


/* ============================================================
   20. REDUCED MOTION
   Disables all animations and transitions for users who request it.
   Applies to Divi's scroll reveal animations as well.
   ============================================================ */

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto !important;
  }
  *,
  *::before,
  *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .img-hover:hover,
  .community-card:hover,
  .dg-team-card:hover {
    transform: none !important;
  }
  .dg-team-card::before,
  .dg-team-card::after {
    transition: none !important;
  }
}


/* ============================================================
   21. MASTER PLAN — RELEASE STRIP, LAND LEDGER, LIGHTBOX
   Stringfield page, SMasterPlan section (id="master-plan"), sits between
   SStats and SFeatures. Added July 2026 with the master plan overhaul.
   Full HTML + build notes: WORDPRESS_IMPLEMENTATION.md → DA.2 → Section 3.
   JS behavior (accordion toggle + lightbox open/close): dg-masterplan.js.
   ============================================================ */

/* — Release strip: segment width = homesite share of the 340 total — */
.plan-strip {
  display: flex;
  gap: 3px;
}
.plan-strip-seg {
  height: 10px;
  border-radius: var(--radius-xs);
  flex-basis: 0;
}
.plan-seg-sold {
  background: var(--stone-300);
}
.plan-seg-selling {
  background: var(--bronze-400);
}
.plan-seg-future {
  background: var(--paper-12);
  border: 1px solid var(--paper-22);
}

.plan-legend {
  display: flex;
  gap: 28px;
  flex-wrap: wrap;
  margin-top: 16px;
}
.plan-legend-item {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-sans);
  font-size: 12px;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--pine-100);
}
.plan-legend-swatch {
  display: inline-block;
  width: 18px;
  height: 8px;
  border-radius: var(--radius-xs);
}
.plan-legend-sold    { background: var(--stone-300); }
.plan-legend-selling { background: var(--bronze-400); }
.plan-legend-future  { background: var(--paper-12); border: 1px solid var(--paper-22); }

/* — Land ledger: 7-row accordion of every release — */
.plan-ledger {
  border-bottom: 1px solid var(--border-on-dark);
}
.plan-ledger-row {
  border-top: 1px solid var(--border-on-dark);
}

.plan-ledger-toggle {
  all: unset;
  display: grid;
  grid-template-columns: 44px 1fr auto auto;
  align-items: center;
  gap: 16px;
  padding: 20px 8px;
  width: 100%;
  box-sizing: border-box;
  cursor: pointer;
  transition: background var(--dur-fast) var(--ease-out);
}
.plan-ledger-toggle:hover {
  background: rgba(246, 241, 231, 0.045);
}
.plan-ledger-toggle:focus-visible {
  outline: 2px solid var(--bronze-400);
  outline-offset: 4px;
}

.plan-ledger-phase {
  font-family: var(--font-display);
  font-style: italic;
  font-size: 15px;
  letter-spacing: 0.04em;
  color: var(--bronze-200);
}
.plan-ledger-name {
  font-family: var(--font-display);
  font-size: clamp(20px, 2.2vw, 26px);
  color: var(--paper);
  line-height: 1.15;
}
.plan-ledger-chip {
  font-family: var(--font-sans);
  font-size: 10.5px;
  font-weight: var(--w-semibold);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 6px 12px;
  border-radius: var(--radius-pill);
  border: 1px solid;
  white-space: nowrap;
}
.plan-chip-sold    { color: var(--paper-50); border-color: var(--paper-22); }
.plan-chip-selling { color: var(--bronze-200); border-color: var(--bronze-400); }
.plan-chip-future  { color: var(--pine-100); border-color: var(--paper-22); }

.plan-ledger-marker {
  position: relative;
  width: 12px;
  height: 12px;
  flex-shrink: 0;
}
.plan-ledger-marker::before,
.plan-ledger-marker::after {
  content: '';
  position: absolute;
  background: var(--bronze-200);
  transition: transform var(--dur-base) var(--ease-out),
              opacity var(--dur-base) var(--ease-out);
}
.plan-ledger-marker::before {
  left: 0;
  right: 0;
  top: 5.25px;
  height: 1.5px;
}
.plan-ledger-marker::after {
  top: 0;
  bottom: 0;
  left: 5.25px;
  width: 1.5px;
}
.plan-ledger-toggle[aria-expanded="true"] .plan-ledger-marker::after {
  transform: scaleY(0);
  opacity: 0;
}

.plan-ledger-detail {
  display: none;
  padding: 0 8px 28px 60px;
}
.plan-ledger-detail p {
  font-family: var(--font-sans);
  font-size: 15.5px;
  line-height: 1.7;
  color: var(--pine-100);
  max-width: 52ch;
  margin: 0;
}
.plan-ledger-stats {
  display: flex;
  gap: 36px;
  flex-wrap: wrap;
  margin: 20px 0 0;
}
.plan-ledger-stats dt {
  font-family: var(--font-sans);
  font-size: 10.5px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--paper-50);
}
.plan-ledger-stats dd {
  font-family: var(--font-display);
  font-size: 22px;
  color: var(--paper);
  margin: 4px 0 0;
}

/* — Plan plate: click-to-enlarge affordance — */
.plan-plate {
  display: block;
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  cursor: zoom-in;
}
.plan-plate-frame {
  position: relative;
  background: var(--paper);
  padding: 10px;
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-lg);
  overflow: hidden;
}
.plan-plate-frame img {
  display: block;
  width: 100%;
  border-radius: var(--radius-xs);
}
.plan-plate:focus-visible .plan-plate-frame {
  outline: 2px solid var(--bronze-400);
  outline-offset: 4px;
}
.plan-plate-hint {
  position: absolute;
  inset: 10px;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 26px;
  background: linear-gradient(to top, rgba(22, 36, 26, 0.4), rgba(22, 36, 26, 0) 46%);
  opacity: 0;
  transition: opacity var(--dur-base) var(--ease-out);
}
.plan-plate:hover .plan-plate-hint,
.plan-plate:focus-visible .plan-plate-hint {
  opacity: 1;
}
.plan-plate-badge {
  padding: 10px 18px;
  border-radius: var(--radius-pill);
  background: var(--paper-92);
  color: var(--ink-900);
  font-family: var(--font-sans);
  font-size: 11.5px;
  font-weight: var(--w-semibold);
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  box-shadow: var(--shadow-md);
}
.plan-plate-caption {
  font-family: var(--font-sans);
  font-size: 11px;
  letter-spacing: var(--ls-caps);
  text-transform: uppercase;
  color: var(--paper-50);
  margin-top: 14px;
  text-align: center;
}

/* Sticky on desktop so the plate stays in view while the ledger scrolls */
.plan-sticky {
  position: sticky;
  top: 108px;
  align-self: start;
}
@media (max-width: 768px) {
  .plan-sticky {
    position: static;
  }
}

/* — Lightbox: fade + scale, not a shared-element morph —
   The Next.js version uses Motion's layoutId to make the plate itself grow
   into the full-screen view. That has no practical vanilla-JS equivalent;
   this fade-in overlay reads as equally premium without it. Do not attempt
   to replicate the morph. */
.plan-lightbox {
  position: fixed;
  inset: 0;
  z-index: 9990;
  display: none;
  align-items: center;
  justify-content: center;
  padding: clamp(20px, 6vw, 72px);
  background: rgba(10, 15, 11, 0.88);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.plan-lightbox.is-open {
  display: flex;
}
.plan-lightbox-frame {
  position: relative;
  background: var(--paper);
  padding: 14px;
  border-radius: var(--radius-card);
  box-shadow: 0 48px 120px -24px rgba(0, 0, 0, 0.6);
}
.plan-lightbox-frame img {
  display: block;
  width: min(78vw, calc(80vh * 0.857));
  max-width: 1400px;
  border-radius: var(--radius-xs);
}
.plan-lightbox-close {
  position: absolute;
  top: -18px;
  right: -18px;
  width: 40px;
  height: 40px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: var(--radius-pill);
  background: var(--pine-900);
  color: var(--paper);
  border: 1px solid var(--paper-22);
  box-shadow: var(--shadow-md);
  cursor: pointer;
  font-size: 22px;
  line-height: 1;
}
