:root {
	--wd-text-font: "DM Sans", Arial, Helvetica, sans-serif;
	--wd-text-font-weight: 400;
	--wd-text-color: #767676;
	--wd-text-font-size: 16.5px;
	--wd-title-font: "Cormorant Garamond", Arial, Helvetica, sans-serif;
	--wd-title-font-weight: 500;
	--wd-title-color: #2A1F16;
	--wd-entities-title-font: "Cormorant Garamond", Arial, Helvetica, sans-serif;
	--wd-entities-title-font-weight: 500;
	--wd-entities-title-color: rgb(51,51,51);
	--wd-entities-title-color-hover: rgb(51 51 51 / 65%);
	--wd-alternative-font: "IBM Plex Mono", Arial, Helvetica, sans-serif;
	--wd-widget-title-font: "IBM Plex Mono", Arial, Helvetica, sans-serif;
	--wd-widget-title-font-weight: 500;
	--wd-widget-title-transform: uppercase;
	--wd-widget-title-color: #333;
	--wd-widget-title-font-size: 16px;
	--wd-header-el-font: "DM Sans", Arial, Helvetica, sans-serif;
	--wd-header-el-font-weight: 500;
	--wd-header-el-transform: uppercase;
	--wd-header-el-font-size: 15px;
	--wd-otl-style: dotted;
	--wd-otl-width: 2px;
	--wd-primary-color: rgb(184,85,57);
	--wd-alternative-color: rgb(110,126,90);
	--btn-default-bgcolor: rgb(42,31,22);
	--btn-default-bgcolor-hover: rgb(26,19,12);
	--btn-accented-bgcolor: rgb(184,85,57);
	--btn-accented-bgcolor-hover: rgb(142,62,39);
	--wd-form-brd-width: 2px;
	--notices-success-bg: #459647;
	--notices-success-color: #fff;
	--notices-warning-bg: #E0B252;
	--notices-warning-color: #fff;
	--wd-link-color: #333333;
	--wd-link-color-hover: #242424;
}
.wd-age-verify-wrap {
	--wd-popup-width: 500px;
}
.wd-popup.wd-promo-popup {
	background-color: #111111;
	background-image: none;
	background-repeat: no-repeat;
	background-size: contain;
	background-position: left center;
}
.wd-promo-popup-wrap {
	--wd-popup-width: 800px;
}
:is(.woodmart-woocommerce-layered-nav, .wd-product-category-filter) .wd-scroll-content {
	max-height: 223px;
}
.wd-page-title .wd-page-title-bg img {
	object-fit: cover;
	object-position: center center;
}
.wd-footer {
	background-color: rgb(235,221,217);
	background-image: none;
}
html .wd-nav.wd-nav-main > li > a {
	font-weight: 500;
	font-size: 16px;
	text-transform: capitalize;
}
:is(.page, .search-no-results, .error404) :is(.wd-page-content, .whb-header) {
	background-color: rgb(242,235,221);
	background-image: none;
}
.mfp-wrap.wd-popup-quick-view-wrap {
	--wd-popup-width: 920px;
}
:root{
--wd-container-w: 1320px;
--wd-form-brd-radius: 0px;
--btn-default-color: #fff;
--btn-default-color-hover: #fff;
--btn-accented-color: #fff;
--btn-accented-color-hover: #fff;
--btn-default-brd-radius: 35px;
--btn-default-box-shadow: none;
--btn-default-box-shadow-hover: none;
--btn-accented-brd-radius: 35px;
--btn-accented-box-shadow: none;
--btn-accented-box-shadow-hover: none;
--wd-brd-radius: 0px;
}

@media (min-width: 1320px) {
section.elementor-section.wd-section-stretch > .elementor-container {
margin-left: auto;
margin-right: auto;
}
}


.wd-page-title {
background-color: #0a0a0a;
}

















































































































































































































































































































































































































































































































/* ESSELEN-COMPONENT-CSS-START */
/* =========================================================================
   ESSELEN TOKENS — the only part of the prototype's styles.css that belongs
   on the WordPress site.

   WHY THIS FILE REPLACED styles.css:
   styles.css was written for the React prototype's own markup (.nav, .footer,
   .card, .btn, .grid, .subnav, .hero, .news-card, .field, .person …). Elementor
   never renders that DOM, so injecting the whole file put ~21KB into Woodmart's
   Custom CSS of which only a handful of rules could ever match — and three of
   the matches were COLLISIONS with theme markup, not intentional styling:
     .btn        → hit Woodmart / WooCommerce buttons
     .container  → hit Woodmart's own container
     .page       → hit the theme's page wrapper
   Those were silently restyling the theme. They are gone.

   WHAT BELONGS HERE: design tokens, and the few prototype components whose
   visuals Elementor genuinely cannot reproduce (the sawtooth motif band, the
   land-acknowledgement panel). Everything else is built with native Elementor
   controls, or mapped onto Elementor markup in elementor-bridge.css.

   DO NOT re-add prototype component CSS here. If a new page needs a prototype
   component, rebuild it with native controls and, only if Elementor truly
   cannot express something, add a mapped rule to elementor-bridge.css.
   ========================================================================= */

/* ---- Design tokens. Required by elementor-bridge.css and
        esselen-interactions.css — every colour and font reference resolves
        against these. ---- */
:root {
  --bg: #F2EBDD;
  --bg-2: #E8E0CE;
  --bg-3: #DCD2BC;
  --fg: #2A1F16;
  --fg-soft: #5A4A3A;
  --fg-mute: #897962;
  --line: #C9BFA8;
  --line-2: #B8AC92;

  --terracotta: #B85539;
  --terracotta-dark: #8E3E27;
  --sage: #6E7E5A;
  --sage-dark: #4F5B40;
  --ochre: #C9924A;
  --deep: #1A130C;
  --earth-green: #2F7D46;
  --earth-green-dark: #215B33;

  --font-display: "Cormorant Garamond", "Cormorant", Georgia, serif;
  --font-body: "DM Sans", "Söhne", system-ui, sans-serif;
  --font-mono: "IBM Plex Mono", ui-monospace, monospace;

  --maxw: 1320px;
  --gutter: clamp(20px, 4vw, 64px);
}

/* ---- Page surface. Fonts and heading COLOUR are NOT set here — those are
        Woodmart Theme Settings (`text-font` / `primary-font`), and the
        prototype's `body` / `h1-h4` rules were overriding them site-wide.

        `line-height` is the one exception. The prototype's body is 16.5/1.55
        (styles.css); the size is native as of 2026-08-07 (`text-font` →
        font-size 16.5) but the same option declares `'line-height' => false`
        in the theme's own settings file, so there is no control to set — and
        Woodmart's stylesheet ships 1.6. This is the only way to reach it.
        Everything with its own line-height (headings, the four mono
        micro-labels, Elementor widgets with native typography) is unaffected;
        this only catches what actually inherits. ---- */
html, body {
  background: var(--bg);
  color: var(--fg);
  line-height: 1.55;
}

/* ---- Motif band: the sawtooth banner. The conic-gradient mask has no
        Elementor equivalent, so the component stays. Layout (inline-flex,
        padding) is applied to the Elementor container in elementor-bridge.css.
        `.mb-text` is omitted — that element only exists in the React markup;
        the bridge styles the heading widget instead. ---- */
.motif-band {
  position: relative;
  display: inline-block;
  padding: 20px 52px;
  text-align: center;
}
.motif-band::before,
.motif-band::after {
  content: ""; position: absolute; left: 0; right: 0; height: 11px;
  background: var(--motif-color, var(--ochre));
  -webkit-mask: conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / 22px 100% repeat-x;
          mask: conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / 22px 100% repeat-x;
}
.motif-band::before { top: 0; transform: scaleY(-1); }
.motif-band::after  { bottom: 0; }

/* thin variant for the hero stat line */
.motif-band-sm { padding: 13px 30px; }
.motif-band-sm::before,
.motif-band-sm::after {
  height: 8px;
  -webkit-mask: conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / 15px 100% repeat-x;
          mask: conic-gradient(from -45deg at bottom, #0000, #000 1deg 89deg, #0000 90deg) bottom / 15px 100% repeat-x;
}
@media (max-width: 760px) {
  .motif-band { padding: 16px 26px; }
}

/* ---- Land acknowledgement panel. Background, radius and padding use
        clamp(), and the decorative rings are pseudo-elements — the rings live
        in elementor-bridge.css because Elementor has no `.glyph` child to
        target. `.ack .glyph` is omitted for that reason. ---- */
.ack {
  background: var(--deep);
  color: var(--bg);
  border-radius: 22px;
  padding: clamp(40px, 5vw, 72px);
  position: relative;
  overflow: hidden;
}

/* ESSELEN-COMPONENT-CSS-END */

/* ESSELEN-ELEMENTOR-BRIDGE-START */
/* =========================================================================
   Elementor bridge — maps Esselen design-system classes (styles.css) onto
   the markup Elementor/Woodmart actually render.

   Why this exists: styles.css was written for hand-authored React markup
   (e.g. `.motif-band` is a plain inline-block div). Elementor wraps every
   widget in .elementor-widget > .elementor-widget-container > .elementor-*-title
   and forces containers to display:flex. These rules re-point the original
   design intent at those real elements so sections can be built from native
   widgets instead of raw HTML blobs.
   ========================================================================= */

/* ---- Woodmart page-content padding ----
   Woodmart wraps page content in `<main class="wd-content-layout container">`
   carrying a hard-coded `padding: 40px 15px`. There is no Theme Settings
   option for it and it sits OUTSIDE the Elementor container, so no Advanced
   tab can reach it — this is a genuine "Elementor can't do it" case.

   On an Elementor page every top-level section supplies its own rhythm and
   stretches full-bleed, so the theme's 40px just opens a gap between the
   header and the first section (and above the footer). Zero it.

   Scoped to `.elementor-page` (Elementor-built PAGES) and `.single-post`
   (posts, which render through Woodmart layout 29685 and carry only
   `elementor-default`) — shop, blog and archive templates are still plain
   Woodmart and keep the theme default.

   HISTORY: this gap was invisible until the CSS cleanup, because the
   prototype's `.container { padding: 0 var(--gutter) }` rule was colliding
   with Woodmart's `container` class and zeroing it by accident. Removing that
   collision was right; this replaces the accident with an intentional rule. */
.elementor-page main.wd-content-layout,
.single-post main.wd-content-layout {
  padding-top: 0;
  padding-bottom: 0;
}

/* ---- COMPATIBILITY SHIM — makes Elementor's native padding control work ----
   Woodmart's base.css ships a global reset containing
   `html, body, div, … { padding: 0; padding-top: 0; padding-bottom: 0 }`.
   Elementor applies container padding from its --padding-* custom properties
   via low-specificity rules, so on the BLOCK axis the reset wins and padding
   set on the Advanced tab is silently zeroed. The inline axis is unaffected —
   which is why left/right worked and top/bottom did not, and why a padding
   class appeared to "work" when the native control did not.

   This re-asserts Elementor's OWN variables at a specificity the reset can't
   beat. It is a theme-conflict fix, NOT a styling decision — it sets no values
   of its own, it only lets the native control take effect. Section padding
   lives on each container's Advanced tab and stays editable in the UI.

   Elementor's `custom` unit accepts clamp(), so fluid rhythm is native too:
   padding = clamp(80px, 9vw, 140px) / clamp(20px, 4vw, 64px).

   THIS MUST BE THE FIRST RULE IN THIS FILE. It has the same specificity as
   every `.e-con.<class>` padding rule below (.motif-band, .sec-gutter,
   .pillar), so whichever comes last wins — placing it lower silently zeroed
   their vertical padding. Keep it at the top.

   IT MUST ALSO EXCLUDE `.e-con-boxed`. A boxed container renders an `.e-con-inner`
   child, and Elementor applies the padding THERE — that path already works
   (its rule outranks the reset). Applying the variables to the outer element
   as well made every boxed container's vertical padding DOUBLE: the footer
   read 160px/64px instead of 80px/32px. Full-width containers keep the shim,
   because for those Elementor targets the outer element and the reset wins.

   The exclusion is written `:not(:where(.e-con-boxed))`, NOT `:not(.e-con-boxed)`.
   A bare `:not()` takes its argument's specificity, which would make this rule
   (0,3,0) and let it outrank every `.e-con.<class>` padding rule below — it
   flattened the hero's sawtooth stat band and the pillar cards the moment this
   shim started parsing again. `:where()` contributes ZERO specificity, keeping
   the rule at (0,2,0) so "first in the file, component rules win" holds. */
.e-con.e-parent:not(:where(.e-con-boxed)),
.e-con.e-child:not(:where(.e-con-boxed)) {
  padding-block-start: var(--padding-block-start, 0px);
  padding-block-end: var(--padding-block-end, 0px);
}

/* ---- Motif band (sawtooth banner) as an Elementor container ---- */
.e-con.motif-band,
.e-con.motif-band-sm {
  display: inline-flex;
  width: auto;
  max-width: 100%;
  flex: 0 0 auto;
  align-items: center;
  justify-content: center;
}
.e-con.motif-band { padding: 20px 52px; }
.e-con.motif-band-sm { padding: 13px 30px; }
.motif-band-clay { --motif-color: var(--terracotta); }

/* ---- Hero section built from Elementor containers ---- */
.hero-el {
  position: relative;
  isolation: isolate;
  color: #fff;
  overflow: hidden;
}
/* Gradient scrim over the background image. Elementor's own overlay control
   only supports two colour stops; the design needs four. */
.hero-el::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(26,19,12,.45) 0%,
    rgba(26,19,12,.15) 30%,
    rgba(26,19,12,.05) 55%,
    rgba(26,19,12,.6) 100%);
}
.hero-el > * { position: relative; z-index: 1; }

.hero-el .pre .elementor-heading-title {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(16px, 1.3vw, 20px);
  letter-spacing: 0.02em;
  text-transform: uppercase;
  color: #fff;
  opacity: 0.95;
  line-height: 1.4;
}
.hero-el .h-xxl .elementor-heading-title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(56px, 9vw, 132px);
  line-height: 0.95;
  letter-spacing: -0.025em;
  color: #fff;
  max-width: 14ch;
}
.hero-el .h-xxl em {
  font-style: italic;
  color: #F2EBDD;
  font-weight: 300;
}
.hero-el .motif-band .elementor-heading-title {
  font-family: var(--font-display);
  font-weight: 500;
  line-height: 1.1;
  color: #fff;
  font-size: clamp(22px, 2.6vw, 38px);
}
.hero-el .hero-meta,
.hero-el .hero-meta p {
  font-family: var(--font-body);
  font-weight: 500;
  margin: 0;
  font-size: clamp(15px, 1.1vw, 18px);
  color: rgba(255,255,255,.9);
  line-height: 1.4;
}

/* ---- Buttons ----
   Fully native: colour, border, radius, padding and typography all live on
   each button's Elementor Style tab. No classes, no CSS. The only remaining
   rule is the box-shadow suppression at the bottom of this file, which has
   no Elementor equivalent. */

/* (`.e-con.sec-pad` and `.e-con.sec-pad-tight` lived here. Both DELETED
   2026-08-07 with the Inicio migration — 29032 was their last user, and its
   eight sections now carry the same values as native `padding` on the
   custom unit. Section rhythm is native everywhere on this site now; if you
   find yourself wanting a spacing class again, re-read HANDOFF §3 rule 2.
   `.sec-gutter` survives near the bottom of this file — it is NOT legacy in
   the same way; see the note there.) */

/* ---- Eyebrow: the leading dot is a ::before since Elementor headings
        can't hold an inner <span>. ---- */
/* line-height: the prototype's mono micro-labels (.eyebrow, .idx, .stat-label,
   .quote-attr) set no line-height and inherit the body's 1.55. Elementor
   headings inherit the theme's tight heading line-height instead, which
   rendered every one of them 11px tall instead of 17px and pulled the
   following element ~6px closer. Restated on each of the four classes below. */
.eyebrow .elementor-heading-title {
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.55;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-mute);
  font-weight: 500;
}
.eyebrow .elementor-heading-title::before {
  content: "";
  display: inline-block;
  width: 6px; height: 6px;
  border-radius: 999px;
  background: var(--terracotta);
  margin-right: 10px;
  vertical-align: middle;
  transform: translateY(-1px);
}
.eyebrow-light .elementor-heading-title { color: rgba(255,255,255,.75); }
.eyebrow-light .elementor-heading-title::before { background: #fff; }
.eyebrow-ack .elementor-heading-title { color: rgba(242,235,221,.6); }

/* ---- Heading size classes applied to the widget wrapper ---- */
/* Page-head h1 is its own size, larger than .h-xl (styles.css:307). */
.h-page .elementor-heading-title { font-family: var(--font-display); font-weight: 500; font-size: clamp(48px, 7vw, 96px); line-height: 1.05; letter-spacing: -0.01em; }
.h-xl .elementor-heading-title  { font-family: var(--font-display); font-weight: 500; font-size: clamp(44px, 6vw, 84px); line-height: 1.05; letter-spacing: -0.01em; }
.h-l .elementor-heading-title   { font-family: var(--font-display); font-weight: 500; font-size: clamp(34px, 4.2vw, 58px); line-height: 1.05; letter-spacing: -0.01em; }
.h-m .elementor-heading-title   { font-family: var(--font-display); font-weight: 500; font-size: clamp(26px, 2.6vw, 36px); line-height: 1.05; letter-spacing: -0.01em; }
.h-s .elementor-heading-title   { font-family: var(--font-display); font-weight: 500; font-size: clamp(20px, 1.8vw, 24px); line-height: 1.05; letter-spacing: -0.01em; }
/* `letter-spacing: -0.01em` comes from the prototype's shared `h1,h2,h3,h4`
   rule (styles.css:63) and belongs on EVERY display heading. It was omitted
   from .h-m/.h-s only — the two smallest scales, which are also the card
   titles, so the miss was invisible until a title wrapped where the
   prototype's did not: "Research & agency partners" on the Conservation page
   measured 389.8px of text in 386.3px of card, and 380.4px with the tracking
   restored. Added 2026-08-07. */
.title-light .elementor-heading-title { color: #fff; }
.title-light em { font-style: italic; color: var(--ochre); }
em.italic-display, .elementor-heading-title em { font-style: italic; font-family: var(--font-display); }

/* ---- Lede / prose text ---- */
.lede-el, .lede-el .elementor-widget-container { font-size: clamp(18px, 1.4vw, 21px); line-height: 1.55; color: var(--fg-soft); max-width: 62ch; }
.prose-el, .prose-el .elementor-widget-container { max-width: 64ch; color: var(--fg-soft); }

/* Paragraph rhythm (prototype `.body-prose p { margin: 0 0 1.1em }`, styles.css:78).
   The class is TRIPLED to raise specificity to (0,3,1). Elementor ships
   `.elementor-widget-text-editor > :last-child { margin-bottom: 0 }` at (0,2,1),
   which beat the plain `.prose-el p` rule — and because every text-editor widget
   on this site holds exactly ONE <p>, that <p> is always :last-child, so the
   rhythm was silently stripped from every paragraph on every page. Symptom:
   paragraphs butt directly against each other with only line-height between them.
   Same harmless specificity-bump technique as `:hover:hover` in the fx library. */
.lede-el.lede-el.lede-el p,
.prose-el.prose-el.prose-el p { margin: 0 0 1.1em; }
.text-light, .text-light .elementor-widget-container,
.text-light p { color: rgba(255,255,255,.88); }

/* ---- Marquee wrapper (borders/padding are native on the container) ---- */
.marquee-rule .wd-marquee { font-family: var(--font-display); font-size: 26px; color: var(--fg-soft); }

/* ---- Section sub-nav pill track (About / Departments / … subpages).
        Background, border, radius, padding and gap are all native; only the
        shrink-wrap needs CSS, because Elementor containers are block-level
        flex and would stretch the track to full width. Same reason as
        .motif-band above.

        THE TRACK SCROLLS, IT DOES NOT WRAP. The prototype's `.subnav`
        (styles.css:367-371) is `overflow-x: auto` with `white-space: nowrap`
        on the buttons — a single-row tab bar you swipe. `overflow-x` was here
        from the start but `flex-wrap` was not, and Elementor containers
        default to `wrap`, so the track never scrolled: it stacked. At 375px
        the five About pills wrapped onto THREE rows inside a 999px stadium
        radius, which rendered as a 127px blob. Both properties are required —
        `overflow-x` alone does nothing while wrapping is allowed.
        Franco caught this on mobile; it was wrong at every width. ---- */
.e-con.subnav-el {
  display: inline-flex;
  width: auto;
  max-width: 100%;
  flex: 0 0 auto;
  flex-wrap: nowrap;
  overflow-x: auto;
  /* Hide the scrollbar — the prototype shows none, and a visible one inside a
     999px-radius pill looks like a rendering fault. */
  scrollbar-width: none;
  -ms-overflow-style: none;
}
.e-con.subnav-el::-webkit-scrollbar { display: none; }

/* Pills keep their intrinsic width instead of being squeezed by the flex row. */
.subnav-el > .elementor-widget-button { flex: 0 0 auto; }
.subnav-el .elementor-button { white-space: nowrap; }

/* ---- Feature panel (Reclaim). Background + radius are native. ---- */
.e-con.panel-clay { color: #fff; }
.panel-clay .elementor-heading-title { color: #fff; }
.stat-num-el .elementor-heading-title,
.panel-clay .wd-counter .wd-counter-value {
  font-family: var(--font-display);
  font-size: 56px;
  line-height: 1;
  color: #fff;
}
.stat-label-el .elementor-heading-title {
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.55;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: rgba(255,255,255,.7);
  font-weight: 500;
}

/* ---- Pillar cards. Background + min-height are native; padding stays here
        because it uses clamp(). ---- */
.e-con.pillar { padding: clamp(32px, 3vw, 48px); }
.idx-el .elementor-heading-title {
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.55;
  letter-spacing: 0.18em;
  color: var(--fg-mute);
  font-weight: 500;
}
/* ---- Card image well (doorway cards, and any future card with a photo).
        The card itself — background, border, radius, padding, gap, min-height —
        is entirely native on its container. Only these two properties have no
        Elementor control: `aspect-ratio` (same reason as .partner-card below)
        and the image's `object-fit` — the Image widget ships an object_fit
        control that emits no CSS at all (verified while building the footer
        logo). Prototype: styles.css:268-269. Hover zoom is `fx-zoom` on the
        CARD container, not here. ---- */
.card-img-el {
  aspect-ratio: 16 / 11;
  width: 100%;
  border-radius: 12px;
  overflow: hidden;
  background: var(--bg-2);
}
.card-img-el img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- Person portrait placeholder (C2 people grids). Exactly two properties
        here have no Elementor control: `aspect-ratio` (same reason as
        .partner-card below) and the 45° hatch, which is a
        repeating-linear-gradient — Elementor's background-gradient control
        emits only two-stop linear/radial. Border, radius, centring and the
        label's typography are all native on the container and the heading
        inside it. Prototype: styles.css:340 (.person-img) + 417-428 (.ph).

        When real headshots arrive: set the container's background to the
        photo and delete the label widget. The ratio rule still applies, so
        the grid keeps its rhythm. ---- */
.person-ph,
.ph-map,
.ph-doc {
  background:
    repeating-linear-gradient(45deg, transparent 0 8px, rgba(42, 31, 22, .04) 8px 9px),
    var(--bg-2);
}
.person-ph { aspect-ratio: 4 / 5; }
/* Same `.ph` hatch at the map tile's ratio (C3 event detail, styles.css:417-428). */
.ph-map    { aspect-ratio: 4 / 3; }
/* And at a fixed size: the 56x70 "PDF" chip on the C4 form tiles
   (page-membership.jsx:183). No ratio — width/height are native there, so this
   class contributes the hatch and nothing else. */

/* Card image that sits flush against the card's top edge — the card carries
   padding 0 + overflow hidden, so its own radius does the clipping and the
   image must NOT round its own corners. C3 Projects-landing cards
   (`page-projects.jsx:29`). Only the ratio and object-fit need CSS; see
   `.card-img-el` above for why. */
.card-img-top {
  aspect-ratio: 16 / 10;
  width: 100%;
  border-radius: 0;
  overflow: hidden;
  background: var(--bg-2);
}
.card-img-top img {
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---- Land acknowledgement. Background, radius and padding are native;
        only the decorative glyph rings live here (no Elementor equivalent). ---- */
.e-con.ack {
  color: var(--bg);
  position: relative;
  overflow: hidden;
}
.e-con.ack::before,
.e-con.ack::after {
  content: "";
  position: absolute;
  border-radius: 999px;
  pointer-events: none;
}
.e-con.ack::before { right: -40px; bottom: -40px; width: 320px; height: 320px; border: 1px solid rgba(242,235,221,0.12); }
.e-con.ack::after  { right: 20px;  bottom: 20px;  width: 200px; height: 200px; border: 1px solid rgba(242,235,221,0.18); }
.ack > *, .ack .elementor-widget-container { position: relative; z-index: 1; }

/* ---- Pull quote ---- */
.quote-el, .quote-el .elementor-widget-container {
  font-family: var(--font-display);
  font-style: italic;
  font-size: clamp(26px, 3vw, 42px);
  line-height: 1.2;
  color: var(--fg);
}
.quote-el p { margin: 0; }
.quote-el .qmark { color: var(--terracotta); }
.quote-attr-el .elementor-heading-title {
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.55;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--fg-mute);
  font-weight: 500;
}

/* ---- Partner tiles. Background, border, radius and padding are native;
        aspect-ratio has no Elementor control so it stays here. ---- */
.e-con.partner-card {
  aspect-ratio: 16/9;
  text-align: center;
}
.partner-card .elementor-heading-title {
  font-family: var(--font-display);
  font-size: 18px;
  color: var(--fg-soft);
  font-weight: 500;
}

/* ---- CTA cards. Background, radius and padding are native. ---- */
.e-con.cta-sage { color: #fff; min-height: 320px; }
.e-con.cta-deep { color: var(--bg); min-height: 320px; }
.cta-sage .elementor-heading-title,
.cta-deep .elementor-heading-title { color: #fff; }

/* ---- Blog cards (wd_blog) nudged toward the prototype's news-card look.
        Classes are TRIPLED for specificity (0,3,0): Woodmart's own
        `.wd-post .wd-post-title { font-size: 22px }` in blog-loop-base.css ties
        the plain one-class form at (0,2,0) and loads AFTER this file, so it won
        on source order and the titles shipped at 22px instead of 26px. Same
        failure mode as the `.prose-el` paragraph rule above. ---- */
.blog-el.blog-el.blog-el .wd-post-title,
.blog-el.blog-el.blog-el .entry-title {
  font-family: var(--font-display);
  font-size: 26px;
  line-height: 1.15;
}
/* Category line: Woodmart renders it as a SOLID terracotta pill with white
   text; the prototype's `.nc-cat` is plain terracotta mono text
   (styles.css:396). The widget's own controls cannot express that — the
   `wd-style-with-bg` variant is baked into the markup — so it is unpainted
   here. */
.blog-el.blog-el.blog-el .wd-post-cat a,
.blog-el.blog-el.blog-el .wd-post-cat {
  font-family: var(--font-mono);
  font-size: 10.5px;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--terracotta);
  background: none;
  padding: 0;
  border-radius: 0;
}
/* The `wd-style-with-bg` variant pulls the pill UP over the image with a
   negative margin so it overlaps the corner. Once the pill background is
   gone that just leaves the label sitting on the photo — drop the margin and
   let the column's own gap (below) place it. */
.blog-el.blog-el.blog-el .wd-post-cat {
  margin: 0;
}
/* Woodmart centres the card body. `text-align` alone does NOT fix it:
   `.wd-post-content` is a FLEX COLUMN with `align-items: center`, so the
   category and title shrink-wrap and centre themselves as flex items no
   matter what the text alignment says. Both properties are needed. The
   prototype's `.news-card` is a plain left-aligned column. */
.blog-el.blog-el.blog-el .wd-post-content {
  align-items: flex-start;
}
.blog-el.blog-el.blog-el .wd-post-content,
.blog-el.blog-el.blog-el .wd-post-cat,
.blog-el.blog-el.blog-el .wd-post-title,
.blog-el.blog-el.blog-el .wd-post-excerpt {
  text-align: left;
}

/* Strip the salon-theme card chrome `wd_blog` has no control to remove.
   The prototype's `.news-card` (styles.css:392-397) is a bare flex column —
   image, category line, title, excerpt. Woodmart adds an author avatar,
   a modified date, share icons, a comment-reply count and a date badge
   overlaid on the image; its `parts_meta` toggle removes the whole meta row
   INCLUDING the category, which is the one part we want, so the parts can
   only be separated here. */
.blog-el.blog-el.blog-el .wd-post-meta,
.blog-el.blog-el.blog-el .wd-post-date.wd-style-with-bg {
  display: none;
}
/* Column rhythm. The prototype's `.news-card` is a flex column with ONE
   14px gap everywhere (styles.css:392); Woodmart's masonry design offsets
   the body 25px from the image and spaces its children 10px.

   The white panel, the resting shadow and the hover shadow that used to be
   unpainted here are gone NATIVELY as of 2026-08-07: Theme Settings → Blog →
   Style is now `flat` (`blog_style` in xts-woodmart-options), which stops
   Woodmart emitting `blog-style-bg` + `wd-add-shadow` on the card in the
   first place. Their unpaint rules were deleted rather than left dead.
   If a card ever reappears with a white body and a hover shadow, check that
   option before adding CSS back. */
.blog-el.blog-el.blog-el .wd-post-content {
  padding-top: 14px;
  gap: 14px;
}
.blog-el.blog-el.blog-el .wd-post-excerpt {
  color: var(--fg-soft);
}

/* Hover zoom: 1.05x over .6s (styles.css:394-395). Woodmart's own
   `.wd-post:hover .wd-post-img` does 1.1x over .5s, so this retunes the
   theme's rule rather than stacking a second transform on the inner <img> —
   an earlier `fx-zoom-news` class did exactly that and the two multiplied
   to 1.155x. The class is gone; this is the only zoom. */
.blog-el.blog-el.blog-el .wd-post-img {
  transition: transform .6s ease;
}
.blog-el.blog-el.blog-el .wd-post:hover .wd-post-img {
  transform: scale(1.05);
}
/* Image well: 16/10 at radius 14 (styles.css:393). `aspect-ratio` and the
   radius on the inner <img> have no widget control. */
.blog-el.blog-el.blog-el .wd-post-thumb,
.blog-el.blog-el.blog-el .wd-post-img {
  border-radius: 14px;
  overflow: hidden;
}
.blog-el.blog-el.blog-el .wd-post-img img {
  aspect-ratio: 16 / 10;
  width: 100%;
  height: auto;
  object-fit: cover;
  object-position: center top;
}

/* ---- Section-head column: Elementor centres any container given an explicit
        width, so cap it with max-width and pin it left instead. ---- */
.e-con.sec-head-col {
  max-width: 740px;
  width: 100%;
  margin-left: 0;
  margin-right: auto;
  align-self: flex-start;
}

/* ---- The theme centres bare h1–h6; our design-system headings are left-aligned.
        (Partner tiles opt out by using a plain heading with align=center.) ---- */
.h-xxl .elementor-heading-title,
.h-page .elementor-heading-title,
.h-xl .elementor-heading-title,
.h-l .elementor-heading-title,
.h-m .elementor-heading-title,
.h-s .elementor-heading-title,
.eyebrow .elementor-heading-title,
.idx-el .elementor-heading-title,
.stat-num-el .elementor-heading-title,
.stat-label-el .elementor-heading-title,
.quote-attr-el .elementor-heading-title,
.lede-el, .prose-el, .quote-el, .text-light { text-align: left; }

/* (`.e-con.sec-gutter` lived here and was DELETED 2026-08-07, the last of the
   three legacy spacing classes. Its 20 users — the sub-nav section of every
   C2/C3/C4 page plus the three sub-nav templates — now carry
   `clamp(20px, 4vw, 64px)` as native left/right padding on the `custom` unit.
   Its original justification, "Elementor drops a padding object that has any
   empty side", was true but avoidable: give all four sides and use the
   vertical values you already have. **There are now ZERO spacing classes on
   this site.** Section rhythm and gutters are native everywhere; if you find
   yourself reaching for a spacing class, re-read HANDOFF §3 rule 2.) */

/* ---- C5 shortcode components (`.login-el`, `.donate-el`) ----------------
   These two are the ONLY places on the site where markup is produced outside
   Elementor, and therefore the only places its Style tab cannot reach. Free
   Elementor has no form-input widgets at all, so the real WordPress login form
   and the donate amount-picker render from the mu-plugin
   `esselen-shortcodes.php` and are dropped onto the page with Elementor's
   native Shortcode widget (which is why the zero-html-widget rule still holds).

   Everything AROUND them — the card, its background, radius, padding, the
   headings — is native on the surrounding containers. Only the innards below
   are styled here. Values are the prototype's `.field` (styles.css:346-354)
   and `.auth-card` (styles.css:380). ---- */

/* -- shared field styling (login form + any future form) -- */
.login-el label,
.form-el label,
.donate-el label {
  display: block;
  font-family: var(--font-mono);
  font-size: 11px;
  line-height: 1.55;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--fg-mute);
  margin-bottom: 8px;
}
.login-el input[type="text"],
.login-el input[type="password"],
.login-el input[type="email"],
.form-el input[type="text"],
.form-el input[type="email"],
.form-el textarea,
.form-el select {
  font: inherit;
  width: 100%;
  padding: 14px 16px;
  border: 1px solid var(--line-2);
  border-radius: 12px;
  background: #F6F1E7;               /* color-mix(--bg, white 20%) resolved */
  color: var(--fg);
}
.login-el input:focus,
.form-el input:focus,
.form-el textarea:focus,
.form-el select:focus { outline: none; border-color: var(--fg); }
.login-el p { margin: 0 0 16px; }
.login-el .login-remember,
.form-el .login-remember { font-size: 13px; color: var(--fg-soft); }
/* A checkbox caption is a sentence, not a field label — undo the mono/uppercase
   treatment the shared `label` rule applies. */
.login-el .login-remember label,
.form-el .login-remember label {
  display: inline; font-family: var(--font-body); font-size: 13px;
  letter-spacing: 0; text-transform: none; color: var(--fg-soft);
}
.form-el .login-remember input[type="checkbox"] { margin-right: 8px; }
/* The submit button is core WP markup, not an Elementor button — restate the
   prototype's `.btn.btn-clay` (styles.css:151-162) on it. */
.login-el .button-primary,
.login-el input[type="submit"],
.form-el button[type="submit"] {
  display: inline-flex; align-items: center; justify-content: center;
  width: 100%; padding: 14px 22px; border-radius: 999px;
  font: 500 14.5px/1 var(--font-body);
  /* Woodmart uppercases all buttons via --btn-transform; the prototype's
     `.btn` is sentence case (styles.css:151-155). */
  text-transform: none;
  background: var(--terracotta); color: #fff;
  border: 1px solid var(--terracotta); cursor: pointer;
  transition: background-color var(--fx-fast, .15s) ease, border-color var(--fx-fast, .15s) ease;
}
.login-el .button-primary:hover,
.login-el input[type="submit"]:hover,
.form-el button[type="submit"]:hover {
  background: var(--terracotta-dark); border-color: var(--terracotta-dark);
}
.login-el-lost { margin: 16px 0 0; text-align: center; font-size: 13px; }
.login-el-lost a { color: var(--terracotta); text-decoration: none; }

/* -- [esselen_contact] / [esselen_newsletter] -----------------------------
   Same justification as the login form: shortcode markup, so Elementor's
   Style tab cannot reach it. The grid mirrors the prototype's contact form
   (page-membership.jsx:363) — two columns, with the reason, message and
   submit spanning both. The newsletter is the same component collapsed to
   one column so it inherits every field style above rather than restating
   them. -- */
.form-el { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form-el .field-wide { grid-column: 1 / -1; }
.form-el textarea { min-height: 150px; resize: vertical; }
.form-el select { height: 51px; }        /* match the 14px+font+14px input box */

/* The homepage newsletter is a different shape from the contact form: the
   prototype (page-home.jsx:233-236) puts a pill input beside a --deep button on
   the sage CTA card, with no visible label. It therefore overrides the shared
   field styling rather than inheriting it — a mono uppercase label in --fg-mute
   is unreadable on sage, and the grid made both controls shrink-wrap. */
.newsletter-el.form-el {
  display: flex; flex-wrap: wrap; align-items: center; gap: 8px; margin-top: 28px;
}
.newsletter-el p { margin: 0; flex: 1 1 auto; }
.newsletter-el p:last-of-type { flex: 0 0 auto; }
/* Kept for screen readers; the placeholder carries it visually. */
.newsletter-el label {
  position: absolute !important; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.newsletter-el input[type="email"] {
  border: none; border-radius: 999px; padding: 14px 18px; background: #fff;
}
.newsletter-el button[type="submit"] {
  width: auto; padding: 14px 22px;
  background: var(--deep); border-color: var(--deep);
}
.newsletter-el button[type="submit"]:hover { background: #000; border-color: #000; }
.newsletter-el .form-el-msg { flex: 1 1 100%; }

/* Honeypot: a real person never sees it, so anything typed here is a bot.
   Off-screen rather than display:none — some bots skip hidden fields. */
.form-el-hp { position: absolute !important; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.form-el-msg {
  grid-column: 1 / -1;
  margin: 0; padding: 14px 16px; border-radius: 12px;
  font-size: 14px; line-height: 1.5;
}
.form-el-msg.is-ok   { background: color-mix(in oklab, var(--sage), transparent 82%); color: var(--sage-dark); }
.form-el-msg.is-err  { background: color-mix(in oklab, var(--terracotta), transparent 86%); color: var(--terracotta-dark); }

@media (max-width: 640px) {
  .form-el { grid-template-columns: 1fr; }
}

/* -- donate panel. It sits on the --deep card, so everything is light-on-dark. --
   NOTE: the widget used to resize as you toggled frequency (367px with the
   monthly note hidden, 456px with it shown) because the deep panel container
   carried `align-items: flex-start`, which makes every child shrink to its own
   content. The fix is NATIVE — `flex_align_items: stretch` on container
   c0c1e8c of page 30744 — not CSS. A `width: 100%` here would have been a
   no-op: `.donate-el` is a plain block div and is already 100% of a parent
   that had itself already shrunk. */
.donate-el-freq {
  display: flex; gap: 4px; padding: 4px; margin-bottom: 16px;
  background: rgba(255, 255, 255, .08); border-radius: 999px;
}
.donate-el-fbtn {
  flex: 1; padding: 10px 14px; border: none; border-radius: 999px; cursor: pointer;
  font: 500 13px/1 var(--font-body);
  background: transparent; color: rgba(255, 255, 255, .85);
  transition: background-color .15s ease, color .15s ease;
}
.donate-el-fbtn.is-active { background: #fff; color: var(--deep); }

.donate-el-amts { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.donate-el-abtn {
  padding: 14px 0; border-radius: 12px; cursor: pointer;
  font-family: var(--font-display); font-size: 22px;
  background: transparent; color: var(--bg);
  border: 1px solid rgba(255, 255, 255, .18);
  transition: background-color .15s ease, border-color .15s ease, color .15s ease;
}
.donate-el-abtn.is-active {
  background: var(--terracotta); border-color: var(--terracotta); color: #fff;
}
.donate-el-custom {
  grid-column: 1 / -1;
  font: inherit; width: 100%; padding: 14px 16px;
  border: 1px solid rgba(255, 255, 255, .18); border-radius: 12px;
  background: rgba(255, 255, 255, .08); color: #fff;
}
.donate-el-custom::placeholder { color: rgba(242, 235, 221, .5); }
.donate-el-custom:focus { outline: none; border-color: rgba(255, 255, 255, .5); }

.donate-el-note {
  margin: 12px 0 0; font-size: 12px; color: rgba(242, 235, 221, .6);
}
.donate-el-go {
  display: flex; align-items: center; justify-content: center;
  margin-top: 22px; padding: 14px 22px; border-radius: 999px;
  font: 500 14.5px/1 var(--font-body);
  background: var(--terracotta); color: #fff; text-decoration: none;
  border: 1px solid var(--terracotta);
  transition: background-color .15s ease, border-color .15s ease;
}
.donate-el-go:hover {
  background: var(--terracotta-dark); border-color: var(--terracotta-dark); color: #fff;
}
.donate-el-secure {
  margin: 16px 0 0; text-align: center;
  font-size: 12px; line-height: 1.5; color: rgba(242, 235, 221, .6);
}

/* ---- Footer (cms_block assigned via Theme Settings → Footer). All colours,
        typography and layout are native per widget; ONLY the link lists live
        here, because they are <a> tags inside text-editor content and
        individual anchors have no Elementor state controls.
        Values: styles.css:316-317. ---- */
.footer-el .elementor-widget-text-editor a {
  display: block;
  padding: 6px 0;
  font-size: 14px;
  color: rgba(255, 255, 255, .7);
  text-decoration: none;
  transition: color .15s ease;
}
.footer-el .elementor-widget-text-editor a:hover { color: #fff; }
/* The links live one per <p>; default paragraph margins ballooned the
   columns to ~30px gaps vs the prototype's tight 6px rhythm. */
.footer-el .elementor-widget-text-editor p { margin: 0; }

/* Brand logo circular mask (prototype styles.css:322 + components.jsx:120-122:
   a 64px overflow-hidden circle with the image cover-filling and scaled 1.22
   to centre the eagle). Elementor's Image widget cannot express this: its
   figure shrink-wraps to the image's natural size, so `max-width:100%` clamps
   the native width back down (64 → 50), its `object_fit` control emits no CSS
   at all, and it has no overflow/transform control for the wrapper. The
   widget's own border-radius was cleared to keep ONE source of truth. */
/* Optimized markup: no <figure>, no .elementor-widget-container — the <img>
   is a direct child of the widget div, so the widget IS the mask. */
.footer-el .elementor-widget-image {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  overflow: hidden;
  flex-shrink: 0;
}
.footer-el .elementor-widget-image img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  transform: scale(1.22) translateX(1px);
}

/* ---- Single post — rendered by the Woodmart LAYOUT (woodmart_layout 29685),
        which replaced the theme's default article template. Everything the
        layout's widgets expose is set natively; these two rules cover the
        two widgets whose schemas have NO such controls (verified):
        - wd_single_post_content: no typography controls at all
        - wd_single_post_image: no height/object-fit, and its radius is
          overridden by the theme's --wd-brd-radius on the <img> itself.
        Prototype values: body 18px/1.65 --fg-soft; hero 64vh cover, r18. ---- */
.elementor-widget-wd_single_post_content {
  font-size: 18px;
  line-height: 1.65;
  color: var(--fg-soft);
}
/* The inner figure shrink-wraps to the image's natural ratio at the fixed
   64vh height (fig width auto → 862px); force it full-bleed. */
.elementor-widget-wd_single_post_image .wd-post-image,
.elementor-widget-wd_single_post_image figure { width: 100%; }
/* Two classes deep: the theme's own `.wd-post-image img { border-radius:
   var(--wd-brd-radius) }` (0) loads after this file at equal specificity. */
.elementor-widget-wd_single_post_image .wd-post-image img,
.elementor-widget-wd_single_post_image img {
  width: 100%;
  height: 64vh;
  object-fit: cover;
  object-position: center top;
}
.elementor-widget-wd_single_post_image .wd-post-image img {
  border-radius: 18px;
}

/* Source chip's leading dot — prototype `.tag .tdot` (styles.css:175) is a
   child <span>; wd_post_meta_value renders only the value, so it's a
   pseudo-element. Everything else about the chip is native. */
.tag-el .wd-post-meta-value,
.tag-el > div {
  display: inline-flex;
  align-items: center;
  gap: 8px;
}
.tag-el .wd-post-meta-value::before,
.tag-el > div::before {
  content: "";
  width: 6px;
  height: 6px;
  border-radius: 999px;
  background: var(--terracotta);
  flex: 0 0 auto;
}

/* The source block import-news.php appends to press-post CONTENT (classic
   post HTML — cannot carry Elementor controls). */
.single-post .news-source {
  margin-top: 2em;
  padding-top: 1.2em;
  border-top: 1px solid var(--line);
  font-size: 14px;
  color: var(--fg-mute);
}
.single-post .news-source a { color: var(--terracotta); font-weight: 600; }

/* ---- Button shadow suppression --------------------------------------
   The ONLY button rule that still needs !important: Woodmart paints a
   rectangular hover box-shadow from a global variable that Elementor's
   own Box Shadow control cannot switch off. Everything else about these
   buttons (colour, border, radius, padding, typography) is set natively
   on each widget's Style tab and is editable in the UI. */
.elementor-widget-button .elementor-button,
.elementor-widget-button .elementor-button:hover,
.elementor-widget-button .elementor-button:focus,
.elementor-widget-button .elementor-button:active {
  box-shadow: none !important;
  text-shadow: none !important;
}
/* Keep the "→" glyph the same colour as its label in every state. */
.elementor-widget-button .elementor-button * { color: inherit; }

/* Marquee star inherits the icon colour rather than rendering black. */
.wd-marquee svg { fill: currentColor; }

/* ESSELEN-ELEMENTOR-BRIDGE-END */

/* ESSELEN-HEADER-START */
/* =========================================================================
   ESSELEN HEADER — navigation styling to match the prototype.

   WHY CSS HERE IS THE RIGHT TOOL (sanctioned):
   The header is built with Woodmart's Header Builder, and Franco has already
   set what that UI exposes — the dropdown panel's background (#F2EBDD) and its
   drop shadow are already correct and are NOT restated here. What remains has
   no control in the builder: the panel's corner radius and border, its
   min-width, the terracotta item colour, per-item pill radius, and the
   terracotta "you are here" state on the top-level item.

   TYPOGRAPHY BELONGS IN THEME SETTINGS, NOT HERE.
   Woodmart Theme Settings → Typography → `navigation-font` controls the
   top-level nav (currently DM Sans / 500 / 15px). Change font family, size or
   transform there. Only the dropdown ITEM size/weight is set below, because
   `navigation-font` does not reach the submenu.

   Source of truth: styles.css:104-134 (.nav-link, .nav-dropdown, .nav-dd-item).
   ========================================================================= */

/* ---- Top-level: the active "you are here" pill.
        Prototype: `.nav-link.active { background: var(--terracotta); color: #fff }`
        (styles.css:113). WordPress already applies these classes correctly —
        current-menu-item on the page itself, current-menu-parent/ancestor on
        the section it belongs to — Woodmart just paints them transparent.
        NOTE: a `?v=` query string breaks WordPress's URL match for custom-link
        menu items, so test this on a clean URL. ---- */
.wd-nav-main > li.current-menu-item > a,
.wd-nav-main > li.current-menu-parent > a,
.wd-nav-main > li.current-menu-ancestor > a,
.wd-nav-main > li.current-menu-item > a:hover,
.wd-nav-main > li.current-menu-parent > a:hover,
.wd-nav-main > li.current-menu-ancestor > a:hover {
  background-color: var(--terracotta);
  color: #fff;
}

/* Keep the caret legible on the terracotta pill. */
.wd-nav-main > li.current-menu-item > a .wd-nav-arrow,
.wd-nav-main > li.current-menu-parent > a .wd-nav-arrow,
.wd-nav-main > li.current-menu-ancestor > a .wd-nav-arrow {
  color: #fff;
}

/* ---- Kill the phantom dropdown caret.
        Woodmart renders the "has children" arrow as `a::after` using a glyph
        from `woodmart-font`. This install has `icons_font_display: disable`
        and `font_awesome_css: not_use` in Theme Settings, so the glyph resolves
        to nothing — leaving an INVISIBLE 7.5px box plus a 4px margin. The
        result: every item with a dropdown was 11.5px wider than its padding,
        pushing the label off-centre inside the pill ("Home", which has no
        dropdown, was correctly centred — that's what gave it away).

        Removing it centres the label. NOTE: the prototype does draw a small
        chevron here (`.nav-link .caret`, styles.css:114 — a CSS border
        triangle, not an icon font). If you want it back, delete this rule and
        build the caret from borders instead of relying on the icon font. ---- */
.wd-nav-main > li > a::after {
  display: none;
}

/* ---- Dropdown panel.
        Background and box-shadow are already set in the Header Builder and
        match the prototype — deliberately not repeated. Only the shape and
        width are missing (styles.css:116-124).
        min-width stops "Non-Profit Board of Directors" wrapping to two lines. */
.wd-dropdown-menu.wd-design-default {
  border: 1px solid var(--line);
  border-radius: 16px;
  padding: 10px;
  min-width: 300px;
}

/* ---- Dropdown items.
        Prototype `.nav-dd-item` (styles.css:128-133): terracotta, 15.5px/600,
        11px 13px padding, 10px radius, tinted hover. Woodmart ships them grey
        (#838383) at 14px/400 with no radius. ---- */
.wd-dropdown-menu .wd-sub-menu > li > a {
  color: var(--terracotta);
  font-size: 15.5px;
  font-weight: 600;
  padding: 11px 13px;
  border-radius: 10px;
  transition: background-color .15s ease, color .15s ease;
}
.wd-dropdown-menu .wd-sub-menu > li > a:hover,
.wd-dropdown-menu .wd-sub-menu > li > a:focus-visible {
  background-color: color-mix(in oklab, var(--terracotta), transparent 88%);
  color: var(--terracotta-dark);
}

/* Woodmart draws an underline/marker on submenu links in some schemes;
   the prototype uses a filled pill instead. */
.wd-dropdown-menu .wd-sub-menu > li > a::before,
.wd-dropdown-menu .wd-sub-menu > li > a::after {
  display: none;
}

/* =========================================================================
   MOBILE MENU — match the desktop nav.

   The Header Builder's `mainmenu` element exposes item colour, hover tint and
   the active pill (Franco set those: #2A1F16 items, 6% tint on hover,
   terracotta active, #F2EBDD dropdown). The BURGER element exposes none of
   them, so the slide-out panel shipped with Woodmart's defaults — #333 items
   at 13px UPPERCASE, no hover, no "you are here" state at all. These rules
   restate the desktop values on the mobile nav. Added 2026-08-07.

   Values are copied from the desktop mainmenu element's own params, not
   invented, so the two stay in step: change them in the Header Builder and
   mirror the change here.
   THE ROW IS A PILL, AND THE PILL IS ON THE TWO CELLS — NOT THE `li`.
   Woodmart splits each row into TWO cells: the `<a>` (flex: 1) and a separate
   50px `.wd-nav-opener` holding the chevron. Painting only the `<a>` leaves the
   chevron cell stranded on the panel background (first attempt). But painting
   the `li` is worse: the `li` ALSO contains the nested `.wd-sub-menu`, so an
   open submenu inherits the fill and the whole expanded panel turns terracotta
   (second attempt — caught on sight). Paint both cells and leave the `li`
   transparent.

   Woodmart also draws three things that have to go, each from a different
   rule in `header-el-mobile-nav.css`: a `border-bottom` on EVERY `<a>` (the
   divider lines), a `border-inline-start` + `border-bottom` boxing the opener
   cell, and a `--wd-primary-color` fill on the opener once a submenu is open.

   EVERY SELECTOR BELOW DOUBLES `.mobile-nav`. Woodmart's own rules are
   `.mobile-nav .wd-nav-opener` and `.wd-side-hidden` — (0,2,0) and (0,1,0) —
   and `header-el-mobile-nav.css` / `base.css` both load AFTER our injected
   Custom CSS, so a matching-specificity rule silently loses on source order.
   Same failure mode, and same fix, as the tripled `.blog-el` selectors in
   elementor-bridge.css. Do not "simplify" the repetition.
   ========================================================================= */

/* Panel surface. The panel is `.mobile-nav.wd-side-hidden.wd-right` — NOT
   `.wd-left-side`, which is a different Woodmart drawer and was the reason an
   earlier version of this rule silently missed and the panel stayed white. */
.mobile-nav.mobile-nav.wd-side-hidden,
.mobile-nav.mobile-nav .wd-heading {
  background-color: var(--bg);
}

/* Inset the list so the pills float inside the panel, like the desktop
   dropdown's 10px padding (see `.wd-dropdown-menu` above). */
.mobile-nav.mobile-nav .wd-nav-mobile {
  padding: 10px;
}

/* Strip the salon dividers and the boxed chevron cell. */
.mobile-nav.mobile-nav .wd-nav-mobile > li > a,
.mobile-nav.mobile-nav .wd-nav-mobile > li > ul li > a,
.mobile-nav.mobile-nav .wd-nav-opener {
  border: none;
}

/* The row. The two cells carry the pill between them: the link rounds its left
   corners, the chevron cell its right. An item with no submenu has no opener,
   so its link rounds all four. */
.mobile-nav .wd-nav-mobile > li {
  margin-bottom: 2px;
}
.mobile-nav .wd-nav-mobile > li > a {
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: var(--fg);
  background-color: transparent;
  padding: 12px 14px;
  min-height: 0;
  border-radius: 10px 0 0 10px;
  transition: background-color .15s ease, color .15s ease;
}
.mobile-nav .wd-nav-mobile > li:not(:has(> .wd-nav-opener)) > a {
  border-radius: 10px;
}
.mobile-nav .wd-nav-opener,
.mobile-nav .wd-nav-opener.wd-active {
  background-color: transparent;
  color: var(--fg-mute);
  border-radius: 0 10px 10px 0;
  transition: background-color .15s ease, color .15s ease;
}

/* Hover tints both cells together. */
.mobile-nav .wd-nav-mobile > li:hover > a,
.mobile-nav .wd-nav-mobile > li:hover > .wd-nav-opener {
  background-color: color-mix(in oklab, var(--fg), transparent 94%);
}

/* The "you are here" pill — the same terracotta state the desktop nav gets.
   WordPress applies current-menu-item on the page and
   current-menu-parent/ancestor on its section; Woodmart paints neither. */
.mobile-nav .wd-nav-mobile > li.current-menu-item > a,
.mobile-nav .wd-nav-mobile > li.current-menu-parent > a,
.mobile-nav .wd-nav-mobile > li.current-menu-ancestor > a,
.mobile-nav .wd-nav-mobile > li.current-menu-item > .wd-nav-opener,
.mobile-nav .wd-nav-mobile > li.current-menu-parent > .wd-nav-opener,
.mobile-nav .wd-nav-mobile > li.current-menu-ancestor > .wd-nav-opener,
.mobile-nav .wd-nav-mobile > li.current-menu-item:hover > a,
.mobile-nav .wd-nav-mobile > li.current-menu-parent:hover > a,
.mobile-nav .wd-nav-mobile > li.current-menu-ancestor:hover > a,
.mobile-nav .wd-nav-mobile > li.current-menu-item:hover > .wd-nav-opener,
.mobile-nav .wd-nav-mobile > li.current-menu-parent:hover > .wd-nav-opener,
.mobile-nav .wd-nav-mobile > li.current-menu-ancestor:hover > .wd-nav-opener {
  background-color: var(--terracotta);
  color: #fff;
}

/* Submenu items mirror the desktop dropdown: terracotta, pill hover.
   Slightly smaller than the desktop 15.5px — the mobile panel is narrower. */
.mobile-nav .wd-nav-mobile .wd-sub-menu {
  padding-bottom: 4px;
}
.mobile-nav .wd-nav-mobile .wd-sub-menu > li > a {
  font-family: var(--font-body);
  font-size: 14.5px;
  font-weight: 500;
  letter-spacing: normal;
  text-transform: none;
  color: var(--terracotta);
  padding: 10px 14px;
  min-height: 0;
  border-radius: 10px;
  transition: background-color .15s ease, color .15s ease;
}
.mobile-nav .wd-nav-mobile .wd-sub-menu > li > a:hover,
.mobile-nav .wd-nav-mobile .wd-sub-menu > li > a:focus-visible {
  background-color: color-mix(in oklab, var(--terracotta), transparent 88%);
  color: var(--terracotta-dark);
}
.mobile-nav .wd-nav-mobile .wd-sub-menu > li.current-menu-item > a {
  background-color: var(--terracotta);
  color: #fff;
}

/* ESSELEN-HEADER-END */

/* ESSELEN-INTERACTIONS-START */
/* =========================================================================
   ESSELEN INTERACTION LIBRARY
   The motion layer: transitions, transforms and hover behaviour.

   WHY THIS FILE EXISTS (and why it isn't native Elementor):
   Elementor's Style tab covers hover *colours* (Background/Text/Border →
   Hover), and those stay native — see ANIMATIONS.md. What it cannot express
   is motion: a transition duration paired with a transform, an arrow that
   slides on hover, an image that scales inside its card. Elementor's canned
   "Hover Animation" list (grow / shrink / pulse / …) is not the prototype's
   vocabulary, so those effects live here as reusable `fx-*` classes.

   HOW TO USE: add the class in Elementor → Advanced → CSS Classes.
   Containers use `css_classes`, widgets use `_css_classes`.
   ANIMATIONS.md is the element→class mapping. Keep the two in sync.

   Every value below is taken from the prototype's styles.css; the source
   line is cited on each block. Do not invent new timings — add a class here
   and record it in ANIMATIONS.md instead.
   ========================================================================= */

:root {
  --fx-fast: .15s;   /* buttons, pills, colour changes  (styles.css:154) */
  --fx-arrow: .2s;   /* the trailing arrow glyph        (styles.css:157) */
  --fx-slow: .6s;    /* image zoom inside cards         (styles.css:269) */
}

/* ---- fx-btn — base button motion. -------------------------------------
   Prototype: `transition: transform .15s ease, background .15s ease`
   (styles.css:154). Colour values themselves are set natively on each
   button's Style → Hover tab; this only makes the change animate. */
.fx-btn .elementor-button {
  transition:
    transform var(--fx-fast) ease,
    background-color var(--fx-fast) ease,
    border-color var(--fx-fast) ease,
    color var(--fx-fast) ease;
}

/* ---- fx-arrow — the trailing "→", as a pseudo-element so it can move.
   Prototype: `.btn { gap: 10px }` + `.btn .arrow { transition: transform
   .2s }` + `.btn:hover .arrow { translateX(4px) }` (styles.css:151,157-158).

   The glyph MUST NOT be typed into the button label — a character inside a
   text node cannot be transformed. Remove it from the text and add this
   class; the 10px margin reproduces the prototype's flex gap exactly. */
/* The button must be inline-flex, exactly as the prototype's .btn is
   (styles.css:151). Elementor ships `.elementor-button` as inline-block,
   which lets the ::after arrow wrap onto its own line like a word — it
   visibly broke "Become a member" before this rule existed. */
.fx-arrow .elementor-button {
  display: inline-flex;
  align-items: center;
}
.fx-arrow .elementor-button::after {
  content: "\2192";
  display: inline-block;
  margin-left: 10px;
  transition: transform var(--fx-arrow) ease;
}
.fx-arrow .elementor-button:hover::after {
  transform: translateX(4px);
}

/* ---- fx-lift — the 1px rise. Prototype applies this ONLY to the header
   Donate CTA, not to ordinary buttons (styles.css:146). Don't spread it. */
.fx-lift .elementor-button:hover {
  transform: translateY(-1px);
}

/* ---- fx-pill — sub-nav pill hover.
   DERIVED, not copied: the prototype's `.subnav button` defines no :hover.
   This reuses `.nav-link:hover`, the top-nav pill of the same component
   family (styles.css:112). Apply to INACTIVE pills only — the active pill
   already carries a solid --fg fill and must not be tinted.

   SPECIFICITY NOTE: Elementor writes a per-widget scoped rule for every
   button's base background/text colour — e.g.
   `.elementor-{page} .elementor-element.elementor-element-{id} .elementor-button`
   — at 4 classes deep, with NO :hover needed since it's the resting state.
   That rule always applies and outranks a plain 2-class hover selector
   (.fx-pill .elementor-button:hover = 3), so the tint silently never showed.
   The repeated :hover is a standard, harmless way to add specificity
   without changing behaviour — it pushes this rule to 5, clear of
   Elementor's 4, independent of stylesheet load order. Same reasoning
   applies to fx-link below. This does NOT affect fx-btn/fx-arrow/fx-lift,
   since Elementor sets no base transition/transform/::after to fight. */
.fx-pill .elementor-button {
  transition: background-color var(--fx-fast) ease, color var(--fx-fast) ease;
}
.fx-pill .elementor-button:hover:hover {
  background-color: color-mix(in oklab, var(--fg), transparent 94%);
}

/* ---- fx-link — inline arrow links (pillar "Explore →" and similar).
   Text-only buttons: colour deepens, arrow still slides via fx-arrow. */
.fx-link .elementor-button {
  transition: color var(--fx-fast) ease;
}
.fx-link .elementor-button:hover:hover {
  color: var(--terracotta-dark);
}

/* ---- fx-zoom — image scale inside a card. Put on the CARD container, not
   the image, so hovering anywhere in the card triggers it.
   Prototype: `.card-img img { transition: transform .6s ease }` +
   `.card:hover .card-img img { scale(1.04) }` (styles.css:269-270). */
.fx-zoom img {
  transition: transform var(--fx-slow) ease;
}
.fx-zoom:hover img {
  transform: scale(1.04);
}
/* The container must clip the overflow or the image escapes its radius. */
.fx-zoom {
  overflow: hidden;
}
/* (A `fx-zoom-news` variant lived here for the wd_blog cards. It was removed
   2026-08-07: Woodmart already zooms `.wd-post-img` on card hover, and the two
   transforms multiplied to 1.155x. The theme's own rule is retuned to the
   prototype's 1.05x/.6s in elementor-bridge.css instead.) */

/* ---- Focus ring. Not in the prototype (it styles no :focus at all), but
   the pills and buttons are keyboard targets and were shipping with no
   visible focus state. Uses the design system's own accent. */
.fx-btn .elementor-button:focus-visible:focus-visible,
.fx-pill .elementor-button:focus-visible:focus-visible,
.fx-link .elementor-button:focus-visible:focus-visible {
  outline: 2px solid var(--terracotta);
  outline-offset: 2px;
}

/* ---- fx-tilt — EXPERIMENTAL 3D card tilt + cursor spotlight -------------
   Requested as an experiment for the homepage pillar cards. NOT part of the
   prototype — remove by deleting this section, the fx-tilt classes on the
   three pillar containers, and wp-content/mu-plugins/esselen-fx.php.

   How it works: the mu-plugin (scripts/esselen-fx.php) sets --px/--py
   (0–1 cursor position) on the card via pointermove. Everything visual is
   CSS: the card tilts toward the cursor, lifts, gains a terracotta-tinted
   ambient shadow and an ochre "candlelight" spotlight that follows the
   pointer, and the card's layers pop forward at different depths
   (headings 20px, text 10px, the arrow link 26px).
   (A lens-flare variant of the spotlight was tried 2026-08-06 and rejected
   by Franco — don't re-propose it.)

   Colours are the design system's own: ochre #C9924A spotlight on the cream
   card, terracotta #B85539 in the shadow — warm light on parchment, not a
   generic neon glow.

   The light is opt-OUT per card, via `fx-unlit` below. Off on 30118 only. ---- */
.fx-tilt {
  --px: .5;                    /* cursor position, 0–1; .5 = rest */
  --py: .5;
  position: relative;
  transform-style: preserve-3d;
  transition: transform .18s ease-out, box-shadow .35s ease;
  will-change: transform;
}
/* Nested Elementor containers must not flatten the 3D space. */
.fx-tilt .e-con { transform-style: preserve-3d; }

.fx-tilt:hover {
  transform:
    perspective(900px)
    rotateX(calc((.5 - var(--py)) * 7deg))
    rotateY(calc((var(--px) - .5) * 9deg))
    translateY(-6px)
    scale(1.02);
  box-shadow:
    0 34px 70px -24px rgba(184, 85, 57, .35),
    0 12px 28px -12px rgba(26, 19, 12, .20),
    inset 0 0 0 1px rgba(201, 146, 74, .40);
  z-index: 3;                  /* ride above the 4px-gap siblings */
}

/* The spotlight. Sits at translateZ(2px) — above the card surface but under
   the popped content, so text stays crisp while the surface glows. */
.fx-tilt::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s ease;
  background: radial-gradient(
    360px circle at calc(var(--px) * 100%) calc(var(--py) * 100%),
    rgba(201, 146, 74, .28),
    rgba(201, 146, 74, .10) 45%,
    transparent 72%);
  transform: translateZ(2px);
}
.fx-tilt:hover::after { opacity: 1; }

/* fx-unlit — opt ONE card out of the light, keeping the tilt, the lift and
   the depth pop. Add it alongside `fx-tilt`.

   Why it exists: the light is right on the flat cream/dark cards it was
   designed for, and wrong on the Projects & News doorway cards (30118),
   which are photo-led — there the ochre wash read as glare across the
   photograph and the warm shadow muddied it. Franco asked for it off there
   and ONLY there; a first pass removed the spotlight globally, which was
   wrong. Specificity (0,3,0) beats the base (0,2,0) rules above. */
.fx-tilt.fx-unlit::after { display: none; }
.fx-tilt.fx-unlit:hover {
  box-shadow:
    0 34px 70px -24px rgba(26, 19, 12, .30),
    0 12px 28px -12px rgba(26, 19, 12, .18);
}

/* Layered depth: children rise off the surface while hovered. */
.fx-tilt .elementor-widget { transition: transform .25s ease; }
.fx-tilt:hover .elementor-widget-heading     { transform: translateZ(20px); }
.fx-tilt:hover .elementor-widget-text-editor { transform: translateZ(10px); }
.fx-tilt:hover .elementor-widget-button      { transform: translateZ(26px); }

/* fx-flat — opt a COMPOUND element out of the depth pop. Put it on any
   container whose parts must stay coplanar with their own background.
   Why it exists: the tag chip is a pill (background + border + radius) holding
   an icon dot and a label heading. The heading matched the rule above and rose
   20px while the pill and the dot stayed at 0, so the label visibly floated off
   its own chip. Anything self-contained on a tilt card wants this.
   Specificity (0,4,0) beats the (0,3,0) depth rules above. */
.fx-tilt:hover .fx-flat,
.fx-tilt:hover .fx-flat .elementor-widget { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .fx-tilt, .fx-tilt:hover {
    transform: none;
    transition: none;
  }
  .fx-tilt .elementor-widget,
  .fx-tilt:hover .elementor-widget-heading,
  .fx-tilt:hover .elementor-widget-text-editor,
  .fx-tilt:hover .elementor-widget-button {
    transform: none;
    transition: none;
  }
  /* Keep a gentle non-moving acknowledgement of the hover. */
  .fx-tilt:hover {
    box-shadow: 0 12px 28px -12px rgba(26, 19, 12, .20),
                inset 0 0 0 1px rgba(201, 146, 74, .40);
  }
  .fx-tilt.fx-unlit:hover {
    box-shadow: 0 12px 28px -12px rgba(26, 19, 12, .20);
  }
}

/* ---- fx-pat-* — hover-revealed background patterns (pair with fx-tilt) --
   Part of the fx-tilt experiment. Abstract geometry drawn from the site's
   OWN motif vocabulary — the sawtooth band, the basketry named in the card
   copy, the ceremony rings on the ack panel — NOT claimed authentic Esselen
   iconography; swap the gradients for real artwork if the tribe provides it.

   Pure CSS gradients, no images. The layer sits at translateZ(1px): above
   the card surface, beneath the ::after spotlight (2px) and the popped
   content, so the cursor light appears to reveal the pattern. */
.fx-pat-mountains, .fx-pat-frieze, .fx-pat-rings { position: relative; }

/* Shared plumbing: the pattern tiles the WHOLE card but is clipped by a soft
   circle that follows the cursor (same --px/--py the spotlight uses) — the
   light reveals the pattern wherever it passes, never a fixed corner. */
.fx-pat-mountains::before,
.fx-pat-frieze::before,
.fx-pat-rings::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  opacity: 0;
  transition: opacity .35s ease;
  transform: translateZ(1px);
  -webkit-mask-image: radial-gradient(
    320px circle at calc(var(--px, .5) * 100%) calc(var(--py, .5) * 100%),
    #000 0%, rgba(0, 0, 0, .55) 45%, transparent 78%);
          mask-image: radial-gradient(
    320px circle at calc(var(--px, .5) * 100%) calc(var(--py, .5) * 100%),
    #000 0%, rgba(0, 0, 0, .55) 45%, transparent 78%);
}
.fx-pat-mountains:hover::before,
.fx-pat-frieze:hover::before,
.fx-pat-rings:hover::before { opacity: 1; }

/* 01 LAND — ridgelines: the motif band's triangle tiled across the whole
   card in two offset terracotta layers; the cursor uncovers them. */
.fx-pat-mountains::before {
  background:
    conic-gradient(from -45deg at 50% 100%, transparent 0deg,
      rgba(184, 85, 57, .10) 1deg 89deg, transparent 90deg)
      0 0 / 56px 28px repeat,
    conic-gradient(from -45deg at 50% 100%, transparent 0deg,
      rgba(184, 85, 57, .05) 1deg 89deg, transparent 90deg)
      28px 14px / 56px 28px repeat;
}

/* 02 CULTURE — basket frieze: horizontal bands in the manner of Californian
   basketry — a zigzag line, then a row of open diamonds — drawn as ochre
   STROKES (woven linework, vs Land's solid triangles). One SVG tile, 40×88,
   repeated; the cursor uncovers the banding. */
.fx-pat-frieze::before {
  background:
    url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 88'%3E%3Cpolyline points='0,22 10,8 20,22 30,8 40,22' fill='none' stroke='%23C9924A' stroke-opacity='.34' stroke-width='2'/%3E%3Cpath d='M20 50L31 63L20 76L9 63Z' fill='none' stroke='%23C9924A' stroke-opacity='.22' stroke-width='2'/%3E%3C/svg%3E")
      0 0 / 40px 88px repeat;
}

/* 03 COMMUNITY — the gathering circle: sage rings anchored at the card's
   lower-right (the ack panel's glyph placement). The rings stay put; only
   the cursor's reveal circle moves — find them as the light passes. */
.fx-pat-rings::before {
  background: repeating-radial-gradient(circle at 88% 94%,
    rgba(110, 126, 90, .22) 0 1.5px, transparent 1.5px 26px);
}

/* ---- Respect reduced-motion preferences. Colour changes still apply;
   only movement is suppressed. */
@media (prefers-reduced-motion: reduce) {
  .fx-btn .elementor-button,
  .fx-pill .elementor-button,
  .fx-link .elementor-button,
  .fx-arrow .elementor-button::after,
  .fx-zoom img {
    transition: none;
  }
  .fx-lift .elementor-button:hover,
  .fx-arrow .elementor-button:hover::after,
  .fx-zoom:hover img,
  .fx-zoom-news:hover img {
    transform: none;
  }
}

/* ESSELEN-INTERACTIONS-END */
