/*
	Theme Name: Semplice 7 Child Theme
	Description: Child Theme for Semplice
	Author: Semplicelabs
	Template: semplice7
*/

/* Custom CSS Start */

/* =============================================================
   Lakefront design tokens
   Mapped from Figma variables (file: Lakefront-Brand---web).
   Update here, not inline in module CSS.
   ============================================================= */

:root {
	/* --- Text -------------------------------------------------- */
	--text-primary:           #1a1a1a;                  /* Figma: text/primary, black */
	--text-secondary:         rgba(26, 26, 26, 0.6);    /* Figma: text/secondary (#1a1a1a99) */
	--text-primary-inv:       #fefdf4;                  /* inverted for dark sections */
	--text-secondary-inv:     rgba(254, 253, 244, 0.6);

	/* --- Surfaces / backgrounds ------------------------------- */
	--bg-primary:             #fefdf4;                  /* Figma: bg/primary, off white */
	--border-weak:            rgba(26, 26, 26, 0.1);    /* Figma: border/weak (#1a1a1a1a) */

	/* --- CTAs ------------------------------------------------- */
	--cta-primary-bg:         #2c2c2c;                  /* Figma: cta/primary/bg */
	--cta-primary-text:       #fefdf4;                  /* Figma: cta/primary/text */
	--cta-secondary-bg:       #f5f4eb;                  /* Figma: cta/secondary/bg */
	--cta-secondary-text:     #1a1a1a;                  /* Figma: cta/secondary/text */

	/* --- Named brand colors — full Figma swatch set ------------- */
	--color-burgundy:         #40091e;
	--color-olive:            #6b732c;
	--color-ecru:             #f0f2df;
	--color-yellow:           #f1fb9f;
	--color-peach:            #ffa573;
	--color-light-blue:       #d7e8fa;
	--color-navy:             #0c3154;
	--color-fuchsia:          #ff7eff;                  /* Figma: fuchsia. Also exposed as --color-pink below for legacy marquee callers. */
	--color-pink:             var(--color-fuchsia);     /* alias — keep existing utility classes working */

	/* --- Type families (sizes/lh handled in Semplice Typography panel) --- */
	/* Instrument Serif is uploaded into Semplice as `instrument-serif-regular`
	   (that's the system-name from the woff2 metadata). `"Instrument Serif"`
	   is kept as a second fallback for any other source that loads it under
	   that family name. */
	--font-serif:             'instrument-serif-regular', 'Instrument Serif', Georgia, serif;
	--font-sans:              'Inter', system-ui, -apple-system, sans-serif;
	--lh-display:             1.1;
	--lh-body:                1.3;

	/* --- Layout ----------------------------------------------- */
	/* These mirror Semplice's Customize → Grid settings. Semplice exposes
	   `--smp-grid-outer-desktop` from the Outer Padding field (currently 120px /
	   6.66667rem) but doesn't apply it automatically — we consume it ourselves.
	   Fallbacks here are the Figma design values. */
	--gutter-page:            var(--smp-grid-outer-desktop, 120px);
	--grid-gap:               var(--smp-grid-gap-desktop, 24px);
	--grid-cols:              12;

	/* --- Radii ------------------------------------------------ */
	--r-pill:                 16px;     /* primary buttons, CTA cards */
	--r-input:                8px;      /* form inputs, secondary pills */
	--r-chip:                 32px;     /* event-card chips */
	--r-tag:                  4px;      /* small pill labels (map etc.) */

	/* --- One-off CTA / form surfaces -------------------------- */
	--cta-input-bg:           #333333;  /* email input bg inside the dark CTA card */
	--cta-submit-bg:          #ffffff;  /* "Get in touch" button bg on dark card */

	/* --- Breakpoints ------------------------------------------ */
	/* (Reference; use in media queries directly since CSS vars don't work in @media) */
	/* mobile:   max-width:  767px  */
	/* tablet:   768px – 1023px     */
	/* desktop:  min-width: 1024px  */
}

/* =============================================================
   Background utility classes
   Apply to a Semplice section / row via the "CSS Class" field.
   ============================================================= */

.bg-cream     { background-color: var(--bg-primary); }
.bg-burgundy  { background-color: var(--color-burgundy);   color: var(--text-primary-inv); }
.bg-olive     { background-color: var(--color-olive);      color: var(--text-primary-inv); }
.bg-ecru      { background-color: var(--color-ecru); }
.bg-yellow    { background-color: var(--color-yellow); }
.bg-peach     { background-color: var(--color-peach); }
.bg-sky       { background-color: var(--color-light-blue); }
.bg-dark      { background-color: var(--text-primary);     color: var(--text-primary-inv); }
.bg-pink      { background-color: var(--color-pink); }

/* Vertical gradients seen across pages */
.bg-grad-cream-sky    { background: linear-gradient(180deg, var(--bg-primary), var(--color-light-blue)); }
.bg-grad-cream-yellow { background: linear-gradient(180deg, var(--bg-primary), var(--color-yellow));     }
.bg-grad-cream-peach  { background: linear-gradient(180deg, var(--bg-primary), var(--color-peach));      }

/* =============================================================
   Typography utility classes
   Type sizes/weights/line-heights live in Semplice Typography → Defaults / Custom Styles.
   These utilities handle patterns Semplice's panel doesn't natively express.
   ============================================================= */

/* Uppercase 14px Inter eyebrow above headlines */
.eyebrow {
	font-family: var(--font-sans);
	font-size: 14px;
	font-weight: 400;
	line-height: var(--lh-body);
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--text-primary);
}

/* 32px Instrument Serif lead-paragraph at 60% opacity (About → Emerge Institute) */
.serif-lead {
	font-family: var(--font-serif);
	font-size: 32px;
	font-weight: 400;
	line-height: var(--lh-display);
	color: var(--text-secondary);
}

/* Helpers for dark sections — apply alongside .bg-dark / .bg-burgundy / .bg-olive */
.text-inverted      { color: var(--text-primary-inv); }
.text-inverted-soft { color: var(--text-secondary-inv); }

/* =============================================================
   Buttons — design system primitives
   Source of truth: Figma "Button / Primary" + "Button / Secondary"
   (file qFYua48EMmhEOfH6z0tPec, nodes 18:298 / 524:5145).

   How to use across the site:
   • On any Semplice module (button, link, even text-with-link), set
     the "CSS Class" field to:   btn btn-primary    or   btn btn-secondary
   • For raw HTML inside a Code Module: <a class="btn btn-primary">…</a>
   • For an inline pair (hero CTA segment): wrap two btns in
     <div class="cta-segment">

   Spec: 40px tall · 16px radius · 8/16 padding · Inter Medium 16px.
   ============================================================= */

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 40px;
    padding: 8px 16px;
    border: 0;
    border-radius: var(--r-pill);
    font-family: var(--font-sans);
    font-size: 16px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
    transition: background-color 0.2s ease, color 0.2s ease;
}

.btn-primary {
    background-color: var(--cta-primary-bg);
    color: var(--cta-primary-text);
}
.btn-primary:hover,
.btn-primary:focus-visible {
    background-color: var(--text-primary);     /* slightly darker on hover */
    color: var(--cta-primary-text);
}

.btn-secondary {
    background-color: var(--cta-secondary-bg);
    color: var(--cta-secondary-text);
}
.btn-secondary:hover,
.btn-secondary:focus-visible {
    background-color: #ebe9d8;                 /* Figma's 10% black overlay approx */
    color: var(--cta-secondary-text);
}

/* Hero CTA segment — primary + secondary side-by-side (Figma "cta-segment") */
.cta-segment {
    display: inline-flex;
    gap: 12px;
    align-items: flex-start;
    flex-wrap: wrap;
}

/* -------------------------------------------------------------
   Semplice DEFAULT button override — applies to every `.smp-button`
   on the canvas (page editor "button" module).

   Why !important: Semplice generates per-instance CSS for every
   button at `#content-holder #content_xxx .is-content { … }` with
   the default `#ffd300` bg / `#000` text injected inline whether or
   not the user touched the panel (see semplice7/editor/modules/button.php:298).
   That out-specificity's any non-!important rule we write.

   How to switch to secondary: in the page editor's Module → Advanced,
   set the button module's "CSS Class" to `btn-secondary`. The class
   lands on the outer `.smp-button` div.
   ------------------------------------------------------------- */

/* Primary — default for every Semplice button.
   Hover effect = Figma's 10% white overlay, implemented as a direct
   color shift (`color-mix`) instead of a stacked linear-gradient so
   the transition eases smoothly (linear-gradient ↔ none can't tween).
   Easing: `cubic-bezier(0.16, 1, 0.3, 1)` — quick-out, gentle settle. */
.smp-button .is-content {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    height: 40px !important;
    padding: 0 !important;
    background: var(--cta-primary-bg) !important;
    border-radius: var(--r-pill) !important;
    transition:
        background-color 0.25s cubic-bezier(0.16, 1, 0.3, 1),
        color 0.25s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
.smp-button .is-content a {
    display: inline-flex !important;
    align-items: center !important;
    height: 100% !important;
    padding: 8px 16px !important;
    color: var(--cta-primary-text) !important;
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    font-weight: 500 !important;
    line-height: 1 !important;
    text-decoration: none !important;
    transition:
        color 0.25s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
/* Hover specificity note: Semplice generates `#content-N #content_xxx
   .is-content:hover { background-color: …!important }` per instance,
   which is (2,1,1). We need to beat that. CSS specificity hack:
   chaining the SAME id (#content-holder#content-holder) counts as 2
   IDs, getting us to (2,2,1). It's ugly but it's the cleanest fix
   short of editing every button's per-instance options. */
#content-holder#content-holder .smp-button .is-content:hover {
    background-color: color-mix(in srgb, var(--cta-primary-bg), white 10%) !important;
    background-image: none !important;
}
#content-holder#content-holder .smp-button .is-content:hover a {
    color: var(--cta-primary-text) !important;
}

/* Secondary — set CSS Class `btn-secondary` on the button module.
   Hover = 10% black overlay equivalent via color-mix. */
.smp-button.btn-secondary .is-content {
    background: var(--cta-secondary-bg) !important;
}
.smp-button.btn-secondary .is-content a {
    color: var(--cta-secondary-text) !important;
}
#content-holder#content-holder .smp-button.btn-secondary .is-content:hover {
    background-color: color-mix(in srgb, var(--cta-secondary-bg), black 10%) !important;
    background-image: none !important;
}
#content-holder#content-holder .smp-button.btn-secondary .is-content:hover a {
    color: var(--cta-secondary-text) !important;
}

/* When a Semplice nav `button` module gets one of the .btn-* classes,
   Semplice still injects per-instance CSS for `.nav_X #content_Y button`
   with high specificity. We add a matching selector so the design
   tokens win regardless of what's in the module's option panel. */
[class*="nav_"] button.btn-primary,
[class*="nav_"] a.btn-primary {
    background-color: var(--cta-primary-bg);
    color: var(--cta-primary-text);
    padding: 8px 16px;
    border-radius: var(--r-pill);
}
[class*="nav_"] button.btn-primary span,
[class*="nav_"] a.btn-primary span {
    color: var(--cta-primary-text);
    font-family: var(--font-sans);
    font-size: 16px;
    font-weight: 500;
}
[class*="nav_"] button.btn-secondary,
[class*="nav_"] a.btn-secondary {
    background-color: var(--cta-secondary-bg);
    color: var(--cta-secondary-text);
    padding: 8px 16px;
    border-radius: var(--r-pill);
}
[class*="nav_"] button.btn-secondary span,
[class*="nav_"] a.btn-secondary span {
    color: var(--cta-secondary-text);
    font-family: var(--font-sans);
    font-size: 16px;
    font-weight: 500;
}

/* =============================================================
   Global Header — Lakefront

   Selectors target stable Semplice classes/data attributes
   (.semplice-header, smp-nav-content[data-module=…]) rather than
   the runtime-generated nav/column/content IDs, so this CSS
   survives nav rebuilds, duplications, and renames.

   Layout (left wordmark / right menu+button) is configured in
   Semplice's column options (display: flex, justify-content:
   flex-end, gap), not via CSS. See the nav editor.
   ============================================================= */

/* Wordmark — Instrument Serif 24px uppercase, 0.96px tracking.
   The wordmark is the text-module inside the header; its content is
   wrapped in `<a href="/">…</a>` (set in the navigations ram on
   content_gkjxtxlpk) so the inner anchor handles the click natively. */
.semplice-header smp-nav-content[data-module="text"] .is-content {
    font-family: var(--font-serif);
    font-size: 24px;
    font-weight: 400;
    line-height: 1;
    letter-spacing: 0.96px;
    text-transform: uppercase;
    color: var(--text-primary);
}
.semplice-header smp-nav-content[data-module="text"] .is-content a {
    color: inherit;
    text-decoration: none;
}

/* Menu items — Inter 14px Regular, near-black (per Figma 500:4356).
   Specificity boost via #content-holder: Semplice's per-instance
   `.nav_X #content_Y li a span { color: … }` is (1,2,2). We need
   (1,_,_)+ to beat the color rule.

   Scope to [data-navbar="top"] so the overlay menu (data-navbar="bottom")
   keeps its own ram-driven font/size/colour (large Instrument Serif). */
#content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li a span {
    font-family: var(--font-sans);
    font-size: 14px;
    font-weight: 400;
    line-height: var(--lh-body);
    color: var(--text-primary);
    transition: color 0.15s ease;
}

/* Hover — subtle underline (Figma "hover underline on nav") */
#content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li a:hover span {
    color: var(--text-primary);
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 4px;
}

/* Current page indicator — covers the various WP active-state classes */
#content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li.current-menu-item a span,
#content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li.current_page_item a span,
#content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li.current-menu-parent a span,
#content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li.current-menu-ancestor a span {
    text-decoration: underline;
    text-decoration-thickness: 1px;
    text-underline-offset: 4px;
}

/* Hide menu items that Figma drops:
     • .menu-item-home — clicking the wordmark goes home; this is a
       duplicate
     • .menu-item-210 — Emerge Institute (out of scope per Figma 500:4356)
     • .cta-navbar — replaced by a real Semplice button module in the
       header
   When the WP menu (Appearance → Menus) is cleaned up to remove these,
   the rules become harmless no-ops. */
.semplice-header smp-nav-content[data-module="menu"] nav ul li.menu-item-home,
.semplice-header smp-nav-content[data-module="menu"] nav ul li.menu-item-210,
.semplice-header smp-nav-content[data-module="menu"] nav ul li.cta-navbar {
    display: none;
}

/* Apply button (Semplice nav `button` module). Smaller "nav" variant
   per Figma 500:4356/4364 — 32×auto with 14px text and 12px horizontal
   padding (vs the design-system default 40×auto / 16 / 16). The
   design-system default stays in place for hero/CTA buttons. */
.semplice-header smp-nav-content[data-module="button"] button.smp-nav-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 32px;
    padding: 8px 12px;
    border: 0;
    border-radius: var(--r-pill);
    background-color: var(--cta-primary-bg);
    color: var(--cta-primary-text);
    font-family: var(--font-sans);
    font-size: 14px;
    font-weight: 500;
    line-height: 1;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.semplice-header smp-nav-content[data-module="button"] button.smp-nav-button:hover,
.semplice-header smp-nav-content[data-module="button"] button.smp-nav-button:focus-visible {
    background-color: color-mix(in srgb, var(--cta-primary-bg), white 10%);
}
.semplice-header smp-nav-content[data-module="button"] button.smp-nav-button .text {
    color: var(--cta-primary-text);
    font-family: var(--font-sans);
    font-size: 14px;
    font-weight: 500;
    line-height: 1;
}

/* Mobile — Semplice swaps the menu to a hamburger via its own
   `menu_type_xs/sm/md = hamburger` option (set on the nav). Only
   need overrides here if styling diverges from defaults. */
@media (max-width: 767px) {
    .semplice-header smp-nav-content[data-module="text"] .is-content {
        font-size: 20px;
        letter-spacing: 0.8px;
    }
}

/* Hamburger breakpoint and down — hide the Apply button next to the
   hamburger. Apply also lives inside the overlay menu
   (data-navbar="bottom"), so we'd be showing it twice. Scoping to
   data-navbar="top" leaves the overlay one untouched.

   991px matches Semplice's md breakpoint, which is where this nav
   flips menu_type to "hamburger" (see content_tqemohu7l.menu_type_md
   in the navigations ram). Keep both rules at the same threshold so
   the border only appears when the nav is in its hamburger form. */
@media (max-width: 991.98px) {
    .semplice-header [data-navbar="top"] smp-nav-content[data-module="button"] {
        display: none !important;
    }
    .semplice-header [data-navbar="top"] {
        border-bottom: 1px solid var(--border-weak);
    }
}

/* Top-align the overlay content block. Semplice's base
   `smp-nav-section smp-nav-row` centers items vertically; this
   override lets navbar-overlay's `align-content: start` actually
   render top-aligned content.

   Full-height chain: the overlay is `display: grid` with a
   content-sized row track, which caps how tall the inner chain
   can grow. Force the single row to 1fr so smp-container fills
   the overlay vertically, then propagate `height: 100%` down
   through row → column. That lets `justify-content: space-between`
   on the column push the Apply CTA to the bottom of the viewport. */
.smp-overlay {
    grid-template-rows: 1fr !important;
}
.smp-overlay > smp-container {
    height: 100% !important;
}
.smp-overlay smp-nav-row {
    height: 100% !important;
    align-items: flex-start !important;
}
.smp-overlay smp-nav-column {
    height: 100% !important;
}

/* Overlay Apply CTA — full-width and larger than the navbar variant.
   The desktop nav uses the compact 32x14px pill (see L375). In the
   overlay we want the CTA to fill the column width and read more
   like a primary button (40px tall, 16px text). */
.smp-overlay smp-nav-content[data-module="button"] {
    width: 100%;
}
.smp-overlay smp-nav-content[data-module="button"] button.smp-nav-button {
    width: 100%;
    height: 40px;
    padding: 8px 16px;
    font-size: 16px;
}
.smp-overlay smp-nav-content[data-module="button"] button.smp-nav-button .text {
    font-size: 16px;
}

/* =============================================================
   Dark-hero header variant — Living at Lakefront
   When the page below has a dark/photographic hero (olive #6b732c
   on Living per Figma 500:4348), the header sits transparent on
   top and everything inverts to off-white. Apply button flips to
   cream-on-dark for contrast.

   Activation: add `has-dark-hero` class to <body>. Two options:
   • Page setting: Semplice page editor → Settings → CSS Class
     (adds class to .content-container; selectors below cover that too)
   • PHP filter in child functions.php (auto-applies by page slug):

       add_filter('body_class', function($classes) {
           if (is_page('residency')) $classes[] = 'has-dark-hero';
           return $classes;
       });

   Status: CSS only. Trigger isn't wired yet — gets added when we
   rebuild the Living hero in a later phase.
   ============================================================= */

/* Transparent header background */
body.has-dark-hero .semplice-header,
.content-container.has-dark-hero .semplice-header,
body.has-dark-hero .semplice-header [data-navbar="top"] {
    background-color: transparent !important;
    backdrop-filter: none !important;
}

/* Wordmark → off-white */
body.has-dark-hero .semplice-header smp-nav-content[data-module="text"] .is-content,
.content-container.has-dark-hero .semplice-header smp-nav-content[data-module="text"] .is-content {
    color: var(--text-primary-inv) !important;
}

/* Menu links → off-white. Semplice generates per-instance link CSS
   like `.nav_X #content_Y li a span { color: … }` (1,2,2). We exceed
   it with `body.has-dark-hero + #content-holder + …` = (2,_,_)+.

   Scope to [data-navbar="top"] so the overlay menu doesn't get
   force-inverted on dark-hero pages (would make it invisible on the
   cream overlay bg). */
body.has-dark-hero #content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li a span,
.content-container.has-dark-hero #content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li a span {
    color: var(--text-primary-inv) !important;
}
body.has-dark-hero #content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li a:hover span,
.content-container.has-dark-hero #content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li a:hover span,
body.has-dark-hero #content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li.current-menu-item a span,
body.has-dark-hero #content-holder .semplice-header [data-navbar="top"] smp-nav-content[data-module="menu"] nav ul li.current_page_item a span {
    color: var(--text-primary-inv) !important;
    text-decoration-color: var(--text-primary-inv) !important;
}

/* Apply button — inverts to cream pill with dark text.
   Scoped to [data-navbar="top"] only: the overlay button (in
   data-navbar="bottom") keeps the default dark pill on cream bg. */
body.has-dark-hero .semplice-header [data-navbar="top"] smp-nav-content[data-module="button"] button.smp-nav-button,
.content-container.has-dark-hero .semplice-header [data-navbar="top"] smp-nav-content[data-module="button"] button.smp-nav-button {
    background-color: var(--text-primary-inv) !important;
    color: var(--text-primary) !important;
}
body.has-dark-hero .semplice-header [data-navbar="top"] smp-nav-content[data-module="button"] button.smp-nav-button .text,
.content-container.has-dark-hero .semplice-header [data-navbar="top"] smp-nav-content[data-module="button"] button.smp-nav-button .text {
    color: var(--text-primary) !important;
}
body.has-dark-hero .semplice-header [data-navbar="top"] smp-nav-content[data-module="button"] button.smp-nav-button:hover,
.content-container.has-dark-hero .semplice-header [data-navbar="top"] smp-nav-content[data-module="button"] button.smp-nav-button:hover {
    background-color: color-mix(in srgb, var(--text-primary-inv), black 10%) !important;
}

/* =============================================================
   Global Footer typography (Figma 500:4497)
   Stable selectors — driven by classes on the text content HTML,
   not on per-instance Semplice IDs. Footer text modules emit
   .footer-wordmark / .footer-eyebrow / .footer-nav-link /
   .footer-apply / .footer-utility-link / .footer-copyright.
   ============================================================= */

/* Wordmark — Instrument Serif 24px, UPPERCASE, 0.96px tracking */
.footer-wordmark {
    font-family: var(--font-serif) !important;
    font-size: 1.3333rem !important;            /* 24px @ 18px base */
    line-height: 1 !important;
    letter-spacing: 0.04em !important;          /* ≈0.96px on 24px */
    text-transform: uppercase !important;
    color: var(--text-primary) !important;
    margin: 0 !important;
}

/* Address paragraph — Inter 16px, 1.3 line-height.
   max-width matches Figma's w-[min-content]: the paragraph stays compact
   (~3 lines at the design width) regardless of viewport / column width. */
.footer-address {
    font-family: var(--font-sans) !important;
    font-size: 0.8888rem !important;            /* 16px */
    line-height: 1.3 !important;
    color: var(--text-primary) !important;
    margin: 1.7777rem 0 0 !important;           /* 32px gap (Figma) */
    max-width: 24em !important;                  /* ≈384px @ 16px — matches Figma column width at 1440px design viewport */
}

/* Eyebrow ("Explore", "Connect") — Inter 12px @ 60% opacity */
.footer-eyebrow {
    font-family: var(--font-sans) !important;
    font-size: 0.6666rem !important;            /* 12px */
    line-height: 1.3 !important;
    color: var(--text-primary) !important;
    opacity: 0.6 !important;
    margin: 0 0 0.8888rem !important;            /* 16px gap to next */
}

/* Nav links ("Living at Lakefront" etc.) — Instrument Serif 24px, 0.24px tracking */
.footer-nav-link {
    margin: 0 0 0.6666rem !important;            /* 12px gap */
}
.footer-nav-link:last-child { margin-bottom: 0 !important; }
.footer-nav-link a {
    font-family: var(--font-serif) !important;
    font-size: 1.3333rem !important;            /* 24px */
    line-height: 1.3 !important;
    letter-spacing: 0.01em !important;          /* ≈0.24px */
    color: var(--text-primary) !important;
    text-decoration: none !important;
    transition: opacity 0.2s ease;
}
.footer-nav-link a:hover { opacity: 0.7 !important; }

/* Apply pill (inside text module, rendered as <a>) */
.footer-apply-wrap {
    margin: 0 0 1.3333rem !important;            /* 24px gap */
}
.footer-apply {
    display: inline-flex !important;
    align-items: center !important;
    justify-content: center !important;
    height: 2.2222rem !important;                /* 40px */
    padding: 0.4444rem 0.8888rem !important;     /* 8px / 16px */
    border-radius: 0.8888rem !important;         /* 16px */
    background-color: var(--cta-primary-bg) !important;
    color: var(--cta-primary-text) !important;
    font-family: var(--font-sans) !important;
    font-size: 0.8888rem !important;            /* 16px */
    font-weight: 500 !important;
    line-height: 1 !important;
    text-decoration: none !important;
    white-space: nowrap !important;
    transition: background-color 0.25s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
.footer-apply:hover {
    background-color: color-mix(in srgb, var(--cta-primary-bg), white 10%) !important;
    color: var(--cta-primary-text) !important;
}

/* Utility links (mail, Instagram, Linkedin) — Inter 12px, ↗ prefix via ::before
   (WordPress's emoji filter mangles inline ↗ to an <img>; CSS content escapes that.) */
.footer-utility-link {
    margin: 0 0 0.6666rem !important;            /* 12px gap */
}
.footer-utility-link:last-child { margin-bottom: 0 !important; }
.footer-utility-link a {
    font-family: var(--font-sans) !important;
    font-size: 0.6666rem !important;            /* 12px */
    line-height: 1.3 !important;
    color: var(--text-primary) !important;
    text-decoration: none !important;
    transition: opacity 0.2s ease;
}
.footer-utility-link a::before {
    content: '\2197';                            /* ↗ NORTH EAST ARROW */
    display: inline-block;
    margin-right: 0.35em;
    font-family: 'Segoe UI Symbol', 'Apple Symbols', 'DejaVu Sans', sans-serif;
}
.footer-utility-link a:hover { opacity: 0.7 !important; }

/* Copyright — Inter 16px @ 50% opacity */
.footer-copyright {
    font-family: var(--font-sans) !important;
    font-size: 0.8888rem !important;            /* 16px */
    line-height: 1.3 !important;
    color: var(--text-primary) !important;
    opacity: 0.5 !important;
    margin: 0 !important;
}

/* =============================================================
   Global Footer — responsive (Figma 746:1999 tablet, 746:2027 mobile)

   Desktop (xl/lg ≥ 992): 4 columns side-by-side (4 / 2 / 3 / 3).
   Tablet (md 768–991): 2 visual columns via CSS grid —
     left col = brand (top) + explore (bottom); right col = connect
     (spans both rows). The empty spacer column is hidden.
   Mobile (sm/xs < 768): Semplice's `data-column-mode-sm/xs: "single"`
     section flag stacks all columns vertically. CSS adds: hide the
     "Connect" eyebrow above the Apply pill, make Apply pill full-width.

   Column classes added in ram (post 545 meta): each row-1 column carries
   one of `.lf-footer-col-brand` / `.lf-footer-col-spacer` /
   `.lf-footer-col-explore` / `.lf-footer-col-connect`. Auto-hex column
   IDs aren't stable across Semplice operations, so we target by class.
   ============================================================= */

/* Selectors below use `#content-holder#content-holder` double-ID specificity
   (2,2,0 / 2,3,0) to beat Semplice's per-instance `#content-holder #column_X`
   (2,0,0) rules. See MODULE-PATTERNS §3 "!important strategy". */

/* The footer section has no class on it — Semplice renders global
   footers as just another smp-section in the page's section list.
   To target "the section that holds the footer columns" we use
   `:has(.lf-footer-col-brand)` on smp-section as an anchor.

   Empty spacer column has no job below desktop — hide at all small viewports. */
@media (max-width: 991.98px) {
    #content-holder#content-holder .lf-footer-col-spacer {
        display: none !important;
    }
}

@media (min-width: 768px) and (max-width: 991.98px) {
    /* Tablet (md): 4 columns become a 2x2 visual grid. */
    #content-holder#content-holder .lf-footer-col-brand,
    #content-holder#content-holder .lf-footer-col-explore,
    #content-holder#content-holder .lf-footer-col-connect {
        width: 100% !important;
        max-width: none !important;
    }
    /* Promote the smp-row containing brand to a 2-column CSS grid.
       :has() picks the row that contains the brand column so we don't
       grid-ify the copyright row in the same way. */
    #content-holder#content-holder smp-row:has(> .lf-footer-col-brand) {
        display: grid !important;
        grid-template-columns: 1fr 1fr !important;
        grid-template-rows: auto auto !important;
        column-gap: 32px;
        row-gap: 48px;
    }
    #content-holder#content-holder .lf-footer-col-brand   { grid-column: 1; grid-row: 1; }
    #content-holder#content-holder .lf-footer-col-explore { grid-column: 1; grid-row: 2; }
    #content-holder#content-holder .lf-footer-col-connect { grid-column: 2; grid-row: 1 / span 2; }
    /* Vertical gap between row 1 (4-col grid) and row 2 (copyright). */
    #content-holder#content-holder smp-section:has(.lf-footer-col-brand) > smp-container {
        flex-direction: column !important;
        gap: 64px !important;
    }
}

@media (max-width: 767.98px) {
    /* Mobile (sm + xs): Semplice's data-column-mode-sm/xs="single" makes
       each column take 100% width and wrap to a new row. Add vertical gaps
       between stacked columns and between row 1 and row 2 (copyright). */
    #content-holder#content-holder smp-section:has(.lf-footer-col-brand) > smp-container {
        flex-direction: column !important;
        gap: 40px !important;
    }
    #content-holder#content-holder smp-row:has(> .lf-footer-col-brand) {
        row-gap: 40px !important;
    }
}

@media (max-width: 543.98px) {
    /* xs only: hide "Connect" eyebrow above the Apply pill (Figma mobile
       shows just the pill, no eyebrow). Other eyebrows remain. */
    #content-holder#content-holder .lf-footer-col-connect .footer-eyebrow {
        display: none !important;
    }
    /* Apply pill goes full-width. `.footer-apply` is inline-flex at all
       viewports; promote to flex+100% to fill the column. */
    #content-holder#content-holder .lf-footer-col-connect .footer-apply {
        display: flex !important;
        width: 100% !important;
    }
}

/* =============================================================
   cta+marquee Saved Block (Figma 500:4496)
   Marquee scrolls continuously left; dark card holds heading +
   body + email form + image. Stable .lf-* selectors driven by
   classes in the code/text module HTML, NOT runtime IDs.
   ============================================================= */

/* Section bg now lives in ram (`section.styles.xl.background-color` =
   gradient string; Semplice's Background::css emits it as background-image
   per-instance). Edit via section popup → Background → gradient picker. */

/* Horizontal page gutter goes on the smp-container inside the section, NOT on
   the section itself. The section is full-viewport; the container caps at the
   Grid panel's max-width and centers naturally — adding padding to the section
   would double-stack with that centering at wide viewports. Applying inside the
   container gives a consistent 120px gap from the container edge to the dark
   card, matching Figma's p-120 wrapper at any viewport. The marquee escapes
   horizontally via `.lf-marquee { width: 100vw }`.

   We rebind --gutter-page LOCALLY on smp-container because Semplice defines
   `--smp-grid-outer-desktop` only on smp-container (not :root), so the variable
   only resolves correctly here. Inherited downward into the card row's
   margin-top so all spacing tracks the Grid panel's Outer Padding setting. */
.lf-cta-section smp-container {
    --gutter-page: var(--smp-grid-outer-desktop, 120px);
    padding-left: var(--gutter-page) !important;
    padding-right: var(--gutter-page) !important;
}
@media (max-width: 1023px) {
    .lf-cta-section smp-container {
        --gutter-page: 40px;
    }
}
@media (max-width: 767px) {
    .lf-cta-section smp-container {
        --gutter-page: 16px;
    }
}

/* ---- Marquee ----------------------------------------------- */
/* Full-bleed: breaks out of Semplice's container via negative margin so the
   pink strip spans the viewport regardless of container max-width. Track has
   2 copies of items so the loop is seamless. */
.lf-marquee {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    height: 40px;
    overflow: hidden;
    background-color: var(--color-pink);
    display: flex;
    align-items: center;
}
.lf-marquee__track {
    display: flex;
    align-items: center;
    gap: 16px;
    white-space: nowrap;
    will-change: transform;
    animation: lf-marquee-scroll 60s linear infinite;
}
@keyframes lf-marquee-scroll {
    from { transform: translateX(0); }
    to   { transform: translateX(-50%); }
}
.lf-marquee__link {
    display: inline-flex;
    align-items: center;
    gap: 16px;
    color: var(--text-primary);
    text-decoration: none;
}
.lf-marquee__link:hover { color: var(--text-primary); }
.lf-marquee__item {
    display: inline-flex;
    align-items: center;
    gap: 16px;
    padding: 16px 0;
    color: var(--text-primary);
    flex-shrink: 0;
}
.lf-marquee__eyebrow {
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: var(--lh-body);
    text-transform: uppercase;
    color: var(--text-primary);
}
.lf-marquee__label,
.lf-marquee__dot {
    font-family: var(--font-serif);
    font-size: 24px;
    line-height: var(--lh-display);
    color: var(--text-primary);
}

/* ---- Left segment: column wraps two subrows --------------- */
/* Figma has TWO gap sizes inside this column:
     text-field (heading+body) ↔ CTA-segment (form+fineprint) = gap-40
     within each group (heading→body, form→fineprint)         = gap-16
   We use Semplice subrows for the two groups so each container needs
   only a single `gap` value — no per-pair margin overrides. The
   heading and body are now SEPARATE text modules inside the first
   subrow, so each is independently editable in Semplice. */
.lf-cta-card-left > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    gap: 40px !important;
    align-items: flex-start !important;
}
/* First subrow (text-field) — heading + body stacked, gap 16.
   Second subrow (CTA-segment) — form + fineprint stacked, gap 16.
   Semplice's `smp-subrow { display: grid }` site default needs to be
   overridden with !important. */
.lf-cta-card-left smp-subrow {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
    width: 100%;
    align-items: flex-start;
}
.lf-cta-heading {
    font-family: var(--font-serif) !important;
    font-size: 40px !important;
    line-height: var(--lh-display) !important;
    color: var(--text-primary-inv) !important;
    margin: 0 !important;
}
.lf-cta-body {
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    line-height: var(--lh-body) !important;
    color: var(--text-primary-inv) !important;
    max-width: 437px !important;                          /* Figma constraint */
    margin: 0 !important;
}

/* Form module wrapper: grid with an animatable second row. Status sits in
   row 2 with `0fr` height + `gap: 0` while idle, so visually there's no empty
   space below the form. When JS sets data-state on the status, the wrapper
   transitions to `1fr` + `gap: 16px` — the row expands smoothly instead of
   snapping in. (Requires modern browsers — Chrome 125+, Firefox 124+,
   Safari 17.4+. Older browsers fall back to instant resize, no harm done.) */
.lf-form-wrap {
    display: grid !important;
    grid-template-rows: auto 0fr;
    gap: 0;
    transition:
        grid-template-rows 0.6s cubic-bezier(0.22, 1, 0.36, 1),
        gap 0.6s cubic-bezier(0.22, 1, 0.36, 1);
}
.lf-form-wrap:has(> .lf-cta-status[data-state]) {
    grid-template-rows: auto 1fr;
    gap: 16px;
}

/* ---- CTA form (email input + Get in touch pill) ----------- */
/* !important because Semplice/WP default input styles otherwise win the cascade. */
.lf-cta-form {
    display: flex !important;
    gap: 12px !important;                                  /* Figma button-row gap-12 */
    align-items: stretch !important;
    margin: 0 !important;                                  /* gaps come from .lf-form-wrap */
}
.lf-cta-input,
input[type="email"].lf-cta-input {
    box-sizing: border-box !important;
    height: 40px !important;
    width: 320px !important;
    padding: 8px 16px !important;
    border-radius: var(--r-input) !important;             /* 8px */
    background-color: var(--cta-input-bg) !important;
    border: none !important;
    color: var(--text-primary-inv) !important;
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    line-height: 1 !important;
    outline: none !important;
    box-shadow: none !important;
}
.lf-cta-input::placeholder { color: var(--text-primary-inv) !important; opacity: 0.3 !important; }
.lf-cta-input:focus { background-color: color-mix(in srgb, var(--cta-input-bg), white 5%) !important; }
.lf-cta-submit,
button.lf-cta-submit {
    box-sizing: border-box !important;
    height: 40px !important;
    padding: 8px 16px !important;
    border-radius: var(--r-pill) !important;              /* 16px */
    background-color: var(--cta-submit-bg) !important;
    color: var(--text-primary) !important;
    border: none !important;
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    font-weight: 500 !important;
    line-height: 1 !important;
    cursor: pointer;
    white-space: nowrap;
    transition: background-color 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.lf-cta-submit:hover { background-color: color-mix(in srgb, var(--cta-submit-bg), black 10%) !important; }
.lf-cta-submit:disabled { opacity: 0.6; cursor: wait; }

.lf-cta-fineprint {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    line-height: var(--lh-body) !important;
    color: var(--text-primary-inv) !important;
    opacity: 0.5 !important;
    margin: 0 !important;
}
.lf-cta-fineprint a {
    color: var(--text-primary-inv) !important;
    text-decoration: underline;
    text-underline-offset: 0.15em;
}

/* Form status messages (success / error). Sit below the form, only visible
   when [data-state] is set. Brand-token colors that read well on the dark
   card. Small leading icon (CSS-generated) for visual cue. */
/* Status is ALWAYS rendered as an inline-flex grid item; its visibility is
   controlled by opacity + transform. The wrapper's grid-template-rows animates
   its row height (0fr → 1fr), so the slide-down feels smooth instead of the
   element popping into layout. */
.lf-cta-status {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 0;
    overflow: hidden;
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: var(--lh-body);
    color: var(--text-primary-inv);
    margin: 0;
    opacity: 0;
    transform: translateY(-4px);
    transition:
        opacity 0.4s cubic-bezier(0.22, 1, 0.36, 1) 0.15s,
        transform 0.5s cubic-bezier(0.22, 1, 0.36, 1) 0.1s;
}
.lf-cta-status[data-state] {
    opacity: 1;
    transform: translateY(0);
}
/* Honor reduced-motion preference */
@media (prefers-reduced-motion: reduce) {
    .lf-cta-status[data-state] { animation: none; }
}
.lf-cta-status[data-state]::before {
    display: inline-block;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    text-align: center;
    line-height: 18px;
    font-size: 12px;
    font-weight: 600;
    flex-shrink: 0;
}
.lf-cta-status[data-state="ok"] {
    color: var(--color-yellow);                            /* brand: lime/yellow */
}
.lf-cta-status[data-state="ok"]::before {
    content: '✓';
    background-color: var(--color-yellow);
    color: var(--text-primary);
}
.lf-cta-status[data-state="error"] {
    color: var(--color-peach);                             /* brand: warm coral */
}
.lf-cta-status[data-state="error"]::before {
    content: '!';
    background-color: var(--color-peach);
    color: var(--text-primary);
}

/* ---- Dark card: real CSS grid on the row -------------------------------- */
/* The row containing the card columns IS the dark card. It owns the bg, radius,
   padding, and the inner gap. Columns inside become transparent grid items —
   no per-column padding tricks, no asymmetric border-radius hacks.
   Grid 7:3 mirrors Figma's left:right ratio (713/303 ≈ 70/30).
   margin-top is the Figma `p-120` top spacing of the CTA wrapper (replacing
   the marquee's old margin-bottom hack — marquee now sits flush at the top). */
.lf-cta-section smp-row:has(> smp-column.lf-cta-card-left) {
    display: grid !important;
    grid-template-columns: 7fr 3fr;
    gap: var(--grid-gap);                                  /* 24px (Figma) */
    background-color: var(--text-primary);                 /* #1a1a1a */
    border-radius: var(--r-pill);                          /* 16px */
    padding: 80px;                                          /* Figma inner p-80 */
    /* !important beats Semplice's `#content-holder [data-gutter="no"] smp-row { margin-top: 0 }` */
    margin-top: var(--gutter-page) !important;              /* 120px CTA wrapper p-top */
    overflow: hidden;
}

/* Card columns become bare grid items — no own bg, padding, or radius */
.lf-cta-card-left,
.lf-cta-card-right {
    background-color: transparent !important;
    padding: 0 !important;
    border-radius: 0 !important;
    /* Let CSS grid control width — override Semplice's column widths */
    width: auto !important;
    max-width: none !important;
    flex-basis: auto !important;
}

/* Image in right column — fills the grid cell as a 1:1 square */
.lf-cta-card-right smp-content[data-module="image"],
.lf-cta-card-right [data-module="image"] .is-content {
    aspect-ratio: 1 / 1 !important;
    width: 100% !important;
    height: auto !important;
    overflow: hidden;
    /* !important beats Semplice's per-instance CSS (`#content_xxx .is-content`)
       which has a higher specificity ID selector. */
    border-radius: 0 !important;
}
.lf-cta-card-right [data-module="image"] img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    display: block;
}

/* ---- Responsive ------------------------------------------- */

/* Narrow desktop / large tablet (≤1199px): keep grid layout but ease the
   ratio. At Figma's exact 7:3, the heading "The door is open, if you're
   curious." wraps awkwardly when the card narrows. Shift to 3:2 so the left
   segment has more breathing room while the image stays square. */
@media (max-width: 1199px) {
    .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left) {
        grid-template-columns: 3fr 2fr;
        padding: 56px;
        gap: 24px;
    }
    .lf-cta-heading {
        font-size: clamp(28px, 3.5vw, 36px) !important;       /* fluid headline */
    }
}

/* Tablet (≤1023px): stack the columns. A 2-up grid at this width pushes the
   image down to ~30% of the card width — too small to read at a glance.
   Stacking with a 16:9 landscape banner reads as a proper hero card and
   gives both the image and the form room to breathe. Tablet maps to
   Semplice's `md` breakpoint (768-1023). */
@media (max-width: 1023px) {
    .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left) {
        grid-template-columns: 1fr;
        gap: 32px;
        padding: 48px 40px;
        margin-top: 56px !important;
        border-radius: 14px;
    }
    .lf-cta-heading { font-size: clamp(26px, 3.5vw, 32px) !important; }
    .lf-cta-body { max-width: none !important; }
    /* Image goes above text — feels like a hero card. */
    .lf-cta-card-right { order: -1; }
    /* Override the desktop 1:1 — landscape 16:9 stacks more comfortably. */
    .lf-cta-card-right smp-content[data-module="image"],
    .lf-cta-card-right [data-module="image"] .is-content {
        aspect-ratio: 16 / 9 !important;
        max-width: 100% !important;
        margin: 0 !important;
    }
}

/* Phone (≤640px): tightest spacing; full-width form inputs; smaller marquee */
@media (max-width: 640px) {
    .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left) {
        gap: 24px;
        padding: 32px 24px;
        margin-top: 40px !important;
        border-radius: 12px;
    }
    .lf-cta-heading {
        font-size: clamp(24px, 6.5vw, 28px) !important;
        line-height: 1.15 !important;
    }
    .lf-cta-body { font-size: 15px !important; }
    .lf-cta-card-right smp-content[data-module="image"],
    .lf-cta-card-right [data-module="image"] .is-content {
        aspect-ratio: 16 / 9 !important;                        /* landscape hero on phone */
        max-width: 100% !important;
    }
    .lf-cta-form {
        flex-direction: column !important;
        gap: 12px !important;
    }
    .lf-cta-input,
    input[type="email"].lf-cta-input { width: 100% !important; }
    .lf-cta-submit,
    button.lf-cta-submit {
        width: 100% !important;
        height: 44px !important;                                /* bigger tap target */
        font-size: 15px !important;
    }
    .lf-cta-input,
    input[type="email"].lf-cta-input {
        height: 44px !important;
    }
    .lf-marquee {
        height: 36px;
    }
    .lf-marquee__label,
    .lf-marquee__dot { font-size: 18px !important; }
    .lf-marquee__eyebrow { font-size: 11px !important; }
}

/* Extra-narrow (≤380px): reduce side gutter to 12px so content has room */
@media (max-width: 380px) {
    .lf-cta-section smp-container {
        --gutter-page: 16px;
    }
    .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left) {
        padding: 28px 20px;
        border-radius: 10px;
    }
}

/* ---- Editor preview-mode mirrors -----------------------------
   Semplice's editor doesn't reflow the iframe when authors switch
   the preview breakpoint — it sets `data-breakpoint="lg|md|sm|xs"`
   on a wrapper element instead. `@media` rules above never fire in
   editor previews; mirror each one with attribute selectors here
   so the canvas matches what real users will see.

   Mapping (per MODULE-PATTERNS.md §10.11):
     @media (max-width: 1199px) → lg, md, sm, xs (3:2 grid w/ narrower headline)
     @media (max-width: 1023px) → md, sm, xs (STACK with 16:9 banner)
     @media (max-width: 640px)  → sm, xs (tighter phone padding + form stack)
     @media (max-width: 380px)  → xs (extra-narrow gutter)                  */

/* lg (1024-1199): narrower 3:2 grid, fluid headline */
[data-breakpoint="lg"] .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left) {
    grid-template-columns: 3fr 2fr !important;
    padding: 56px !important;
    gap: 24px !important;
}
[data-breakpoint="lg"] .lf-cta-heading {
    font-size: clamp(28px, 3.5vw, 36px) !important;
}

/* md (768-1023): stack with 16:9 banner image on top. THIS is what the
   tablet-preview author was missing — without this mirror the editor at
   md preview shows the cramped desktop grid even though the real frontend
   stacks correctly. */
[data-breakpoint="md"] .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left),
[data-breakpoint="sm"] .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left),
[data-breakpoint="xs"] .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left) {
    grid-template-columns: 1fr !important;
    gap: 32px !important;
    padding: 48px 40px !important;
    margin-top: 56px !important;
    border-radius: 14px !important;
}
[data-breakpoint="md"] .lf-cta-heading,
[data-breakpoint="sm"] .lf-cta-heading,
[data-breakpoint="xs"] .lf-cta-heading {
    font-size: clamp(26px, 3.5vw, 32px) !important;
}
[data-breakpoint="md"] .lf-cta-body,
[data-breakpoint="sm"] .lf-cta-body,
[data-breakpoint="xs"] .lf-cta-body {
    max-width: none !important;
}
[data-breakpoint="md"] .lf-cta-card-right,
[data-breakpoint="sm"] .lf-cta-card-right,
[data-breakpoint="xs"] .lf-cta-card-right {
    order: -1 !important;
}
[data-breakpoint="md"] .lf-cta-card-right smp-content[data-module="image"],
[data-breakpoint="md"] .lf-cta-card-right [data-module="image"] .is-content,
[data-breakpoint="sm"] .lf-cta-card-right smp-content[data-module="image"],
[data-breakpoint="sm"] .lf-cta-card-right [data-module="image"] .is-content,
[data-breakpoint="xs"] .lf-cta-card-right smp-content[data-module="image"],
[data-breakpoint="xs"] .lf-cta-card-right [data-module="image"] .is-content {
    aspect-ratio: 16 / 9 !important;
    max-width: 100% !important;
    margin: 0 !important;
}

/* sm (480-767) + xs (<480): tighter phone padding, full-width form stack,
   smaller marquee. Matches @media (max-width: 640px). */
[data-breakpoint="sm"] .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left),
[data-breakpoint="xs"] .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left) {
    gap: 24px !important;
    padding: 32px 24px !important;
    margin-top: 40px !important;
    border-radius: 12px !important;
}
[data-breakpoint="sm"] .lf-cta-heading,
[data-breakpoint="xs"] .lf-cta-heading {
    font-size: clamp(24px, 6.5vw, 28px) !important;
    line-height: 1.15 !important;
}
[data-breakpoint="sm"] .lf-cta-body,
[data-breakpoint="xs"] .lf-cta-body { font-size: 15px !important; }
[data-breakpoint="sm"] .lf-cta-form,
[data-breakpoint="xs"] .lf-cta-form {
    flex-direction: column !important;
    gap: 12px !important;
}
[data-breakpoint="sm"] .lf-cta-input,
[data-breakpoint="sm"] input[type="email"].lf-cta-input,
[data-breakpoint="xs"] .lf-cta-input,
[data-breakpoint="xs"] input[type="email"].lf-cta-input { width: 100% !important; height: 44px !important; }
[data-breakpoint="sm"] .lf-cta-submit,
[data-breakpoint="sm"] button.lf-cta-submit,
[data-breakpoint="xs"] .lf-cta-submit,
[data-breakpoint="xs"] button.lf-cta-submit {
    width: 100% !important;
    height: 44px !important;
    font-size: 15px !important;
}
[data-breakpoint="sm"] .lf-marquee,
[data-breakpoint="xs"] .lf-marquee { height: 36px; }
[data-breakpoint="sm"] .lf-marquee__label,
[data-breakpoint="sm"] .lf-marquee__dot,
[data-breakpoint="xs"] .lf-marquee__label,
[data-breakpoint="xs"] .lf-marquee__dot { font-size: 18px !important; }
[data-breakpoint="sm"] .lf-marquee__eyebrow,
[data-breakpoint="xs"] .lf-marquee__eyebrow { font-size: 11px !important; }

/* xs (<480): extra-narrow gutter + tighter card padding */
[data-breakpoint="xs"] .lf-cta-section smp-container { --gutter-page: 16px !important; }
[data-breakpoint="xs"] .lf-cta-section smp-row:has(> smp-column.lf-cta-card-left) {
    padding: 28px 20px !important;
    border-radius: 10px !important;
}

/* =============================================================
   Accordion — Figma 500:4486 + item states 151:1672/1673

   These rules apply to ANY Semplice `accordion` module dropped on
   any page. Just drag the module in, leave its popup at defaults;
   this CSS reskins type, color, separators, icon placement, and
   replaces Semplice's gsap-based open/close animation. Section-
   level chrome (cream bg + page gutter + eyebrow gap) is opt-in
   via the `.lf-faq-section` class on the wrapping section, kept
   at the bottom of this block.

   Scoped to `#content-holder` so the rules only fire on Semplice
   frontend / editor canvas markup — won't bleed into the wp-admin
   chrome (which uses some of the same class names elsewhere).
   ============================================================= */

/* Title text: Instrument Serif, --text-primary.
   Semplice defaults to `data-font="inter_bold"` which maps to a
   slug that may not exist in this site's Typography panel — we
   pin the font-family directly so it never falls back. */
#content-holder .accordion-item .title-span span {
    font-family: var(--font-serif) !important;
    font-weight: 400 !important;
    color: var(--text-primary) !important;
}

/* Override Semplice defaults for title size/line-height so a
   freshly-dropped accordion (empty options) renders at Figma spec
   instead of Semplice's 40px/50px default. */
#content-holder .accordion-item .title {
    font-size: 24px !important;
    line-height: 31px !important;
}

/* Cap title and description at 90% of column width so lines don't run
   to the right edge — keeps measure readable on wide viewports.
   !important on title-span: Semplice emits a per-instance rule
   `#content-holder #content_X .title .title-span { max-width: calc(100% - 24px) }`
   with (1,2,2) specificity. */
#content-holder .accordion-item .title-span {
    max-width: 90% !important;
    padding-right: 32px !important;
}
#content-holder .accordion-item .description-inner {
    max-width: 90%;
}

/* Description: Inter Regular, color --text-primary at 50% alpha
   (matches Figma's rgba(26,26,26,0.5)). Semplice's color picker
   doesn't do alpha cleanly, so the override lives here. */
#content-holder .accordion-item .description-inner,
#content-holder .accordion-item .description-inner p {
    font-family: var(--font-sans) !important;
    font-weight: 400 !important;
    font-size: 16px !important;
    line-height: 21px !important;
    color: rgba(26, 26, 26, 0.5) !important;
    margin-top: 16px !important;
}

/* Item padding — 16px vertical, 0 horizontal. Overrides Semplice
   defaults (`padding: 30px 0`) so the accordion sits compact like Figma. */
#content-holder .accordion-item {
    padding: 16px 0 !important;
}

/* Icon — 24px, --text-primary, vertically centered with the title.
   Semplice's accordion positions the icon via `top: <icon_spacing>`,
   which top-aligns it with the title row by default. Pull it down
   (31-24)/2 = 3.5px so the icon's vertical center aligns with the title's. */
#content-holder .accordion-item .title .icon {
    top: 3.5px !important;
    fill: var(--text-primary) !important;
}
#content-holder .accordion-item .title .icon svg {
    width: 24px !important;
    height: auto !important;
    display: block;
}

/* Separator lines: 1px black, including top + bottom of the list. */
#content-holder .accordion-item ~ .seperator,
#content-holder .seperator.top-seperator,
#content-holder .seperator.bottom-seperator,
#content-holder [data-module="accordion"] .seperator {
    height: 1px !important;
    background: var(--text-primary) !important;
}

/* Show top + bottom separators even when Semplice's `seperator_mode`
   defaults to "hidden" (which it does for empty-options accordions).
   `display: block` overrides Semplice's CSS that hides them per the
   seperator_mode attribute on `.is-content`. */
#content-holder [data-module="accordion"] .top-seperator,
#content-holder [data-module="accordion"] .bottom-seperator {
    display: block !important;
}

/* Open/close height transition for our own toggle.
   Why we replace Semplice's gsap-based animation: Semplice's accordion
   sets `semplice.active.accordion = true` while gsap is animating and
   ignores every click for the duration (0.4s). Rapid clicks feel like
   the accordion has frozen. Our JS in `lakefront_faq_inline_js` skips
   that lock and animates height directly via CSS transition with an
   explicit pixel target measured at click time. Interrupted transitions
   pick up smoothly because we always restart from the current value. */
#content-holder .accordion-item .description {
    height: 0;
    overflow: hidden;
    transition: height 0.25s cubic-bezier(0.2, 0.8, 0.2, 1) !important;
}
@media (prefers-reduced-motion: reduce) {
    #content-holder .accordion-item .description {
        transition: none !important;
    }
}

/* Editor canvas: keep every accordion answer visible so authors can
   read, edit, and use the per-item "Text / Image" action buttons.
   `body.wp-admin` is set by WordPress on every admin page, including
   Semplice's editor canvas. We also drop cursor: pointer in the editor
   so clicks land on the contenteditable title-span normally. */
body.wp-admin #content-holder .accordion-item .description {
    height: auto !important;
    overflow: visible !important;
    transition: none !important;
}
body.wp-admin #content-holder .accordion-item,
body.wp-admin #content-holder .accordion-item * {
    cursor: auto !important;
}
body.wp-admin #content-holder .accordion-item .title-span,
body.wp-admin #content-holder .accordion-item .title-span * {
    cursor: text !important;
    user-select: text !important;
    -webkit-user-select: text !important;
}

/* Whole item is clickable. Force cursor: pointer on every descendant —
   Semplice's per-instance CSS sets `cursor: text` on the contenteditable
   title-span, and <svg> defaults to `default`. user-select: none on the
   title prevents the title text from highlighting blue on rapid clicks;
   the description stays selectable so readers can copy answer text. */
#content-holder .accordion-item,
#content-holder .accordion-item * {
    cursor: pointer !important;
}
#content-holder .accordion-item .title,
#content-holder .accordion-item .title * {
    user-select: none;
    -webkit-user-select: none;
}
#content-holder .accordion-item .description,
#content-holder .accordion-item .description * {
    user-select: text;
    -webkit-user-select: text;
    cursor: text !important;
}

/* ---- Section chrome (opt-in via .lf-faq-section) ---------------
   Add the class `lf-faq-section` to a Semplice section that wraps an
   accordion to get: cream bg, page-gutter container, and an Inter
   uppercase eyebrow above the list. */

/* Section bg now in ram (`styles.xl.background-color` = #fefdf4). Edit
   via the FAQ section's popup → Background → color picker. */

.lf-faq-section smp-container {
    --gutter-page: var(--smp-grid-outer-desktop, 120px);
    padding-left: var(--gutter-page) !important;
    padding-right: var(--gutter-page) !important;
}

/* Eyebrow — Inter 14px uppercase. Add `<p class="lf-faq-eyebrow">…</p>`
   as a text module above the accordion. */
.lf-faq-section .lf-faq-eyebrow {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    letter-spacing: 0.04em !important;
    text-transform: uppercase !important;
    color: var(--text-primary) !important;
    margin: 0 !important;
}

/* Gap between eyebrow and accordion list (Figma 40px) — applied to
   the column's content wrapper since Semplice stacks modules inside
   smp-content-wrapper, not on the column directly (gotcha 2.9). */
.lf-faq-section smp-column > smp-content-wrapper {
    display: flex;
    flex-direction: column;
    gap: 40px;
}

/* ---- Responsive ----------------------------------------------- */

@media (max-width: 1023px) {
    .lf-faq-section smp-container {
        --gutter-page: 40px;
    }
    .lf-faq-section smp-column > smp-content-wrapper {
        gap: 32px;
    }
}

@media (max-width: 860px) {
    #content-holder .accordion-item .title {
        font-size: 22px !important;
        line-height: 28px !important;
    }
}

@media (max-width: 640px) {
    .lf-faq-section smp-container {
        --gutter-page: 16px;
    }
    #content-holder .accordion-item .title {
        font-size: 20px !important;
        line-height: 26px !important;
    }
    #content-holder .accordion-item .description-inner {
        font-size: 15px !important;
        line-height: 21px !important;
    }
}

@media (max-width: 380px) {
    .lf-faq-section smp-container {
        --gutter-page: 16px;
    }
}

/* =============================================================
   50/50 Hero — Figma 500:4349 (Living at Lakefront)
   Full-bleed two-column hero. Left half: olive bg with headline,
   body, and CTA segment (bottom-aligned). Right half: hero image
   covering the column.

   Triggers `body.has-dark-hero` for global header inversion — wired
   via body_class filter in functions.php that fires on any page
   containing a master_lf50hero01 instance.

   Saved Block: master_lfhero50_01 (in "New Modules" category).
   ============================================================= */

/* Section — escape Semplice's container max-width so the hero spans
   the full viewport. lf-cta-section keeps its container; this overrides
   only when the section has class lf-hero-50. */
.lf-hero-50 smp-container {
    max-width: none !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
}
.lf-hero-50 smp-row {
    min-height: max(700px, 100vh);
    /* Cap to viewport so a portrait image on the right column can't push
       the row taller than the visible area (which buries the buttons on
       the left below the fold). The image column uses object-fit: cover
       so the photo crops to fit instead of forcing the row taller. The
       narrow-viewport responsive variant below stacks the columns and
       turns off the cap so stacked content can flow naturally. */
    max-height: 100vh;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
}

/* Left column: olive bg, content bottom-aligned. Padding anchors the
   text block to the design system's left content edge.

   Standard Semplice container caps at 1440 with 120 outer padding, so
   the design content area starts at viewport-x = (100vw - 1440px)/2 + 120
   on wide viewports and just 120 on narrow ones. We mirror that here so
   the hero's text sits flush with content on other sections — at 1920
   viewport it indents 360px from the left edge, not 120. */
.lf-hero-50-left {
    background-color: var(--color-olive);
    color: var(--text-primary-inv);
    align-self: stretch;
    /* Without this, a portrait image on the right column would force the
       row's align-items: stretch to make BOTH columns match the image's
       natural height (~1191px for a 4:5 portrait at 953w), pushing the
       text-column buttons below the fold. Capping both columns to viewport
       keeps the buttons visible regardless of image aspect. */
    max-height: 100vh;
    overflow: hidden;
}
/* Layout uses nested Semplice subrows so each container needs only a
   single `gap` value — no per-pair margin overrides, no explicit gap
   tracks. The column wrapper has the gap-40 between groups; each
   subrow has its own internal gap (16 for text, 12 for buttons). */
.lf-hero-50-left > smp-content-wrapper {
    display: flex;
    flex-direction: column;
    justify-content: flex-end;
    /* Default `align-items: stretch` so the subrows fill the column width
       (otherwise they'd shrink to their content and the button subrow's
       flex-row layout would have no horizontal room). Inner subrows cap
       their own max-width where needed. */
    gap: 40px;
    height: 100%;
    width: 100%;
    /* Scale top/bottom padding with viewport height so content fits the
       capped 100vh column on shorter screens (200px each was designed for
       1200+ tall viewports; on a 919-tall viewport it left only ~500px
       for the heading/body/buttons). clamp gives 96px floor for small
       screens, 200px ceiling for tall, ~14vh in between. */
    padding-top: clamp(96px, 14vh, 200px);
    padding-bottom: clamp(96px, 14vh, 200px);
    padding-left: max(120px, calc((100vw - 1440px) / 2 + 120px));
    padding-right: 24px;
}
/* Subrows: Semplice's Subrow::init doesn't emit the ram `classes` field
   so we target the subrows positionally inside .lf-hero-50-left. The
   first subrow is the text stack (heading + body, gap 16, vertical),
   the second is the button row (gap 12, horizontal). Semplice's
   frontend.css declares `smp-subrow { display: grid }` site-wide, so
   !important is needed on display + flex-direction to swap to flex. */
.lf-hero-50-left smp-subrow:nth-of-type(1) {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
    max-width: 600px;
}
.lf-hero-50-left smp-subrow:nth-of-type(2) {
    display: flex !important;
    flex-direction: row !important;
    gap: 12px;
    flex-wrap: wrap;
}
/* Semplice forces smp-content children to width: 100% so column stacks
   normally — undo that inside the button subrow so each button sizes to
   its content and they sit side-by-side. */
.lf-hero-50-left smp-subrow:nth-of-type(2) > smp-content {
    width: auto !important;
    flex: 0 0 auto;
}

/* Headline — Instrument Serif, fluid 48→72px, cream */
.lf-hero-headline {
    font-family: var(--font-serif) !important;
    font-size: clamp(48px, 5vw, 72px) !important;
    line-height: 1.1 !important;
    font-weight: 400 !important;
    color: var(--text-primary-inv) !important;
    margin: 0 !important;
}

/* Body — Inter Regular 16/21, cream, max ~480px so it doesn't run wide */
.lf-hero-body {
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    line-height: 1.3 !important;
    font-weight: 400 !important;
    color: var(--text-primary-inv) !important;
    margin: 0 !important;
    max-width: 480px;
}

/* CTA group buttons — rendered by the `lf-cta-group` custom module.
   Base styles match the project's `.btn-primary` / `.btn-secondary`
   token treatment (designed for LIGHT surfaces). The hero context
   inverts them below since the olive bg makes "primary" want a cream
   button instead of a dark one. */
.lf-cta-group {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
}
.lf-cta-group__btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    height: 40px;
    padding: 8px 16px;
    border: 0;
    border-radius: var(--r-pill);
    font-family: var(--font-sans);
    font-size: 16px;
    font-weight: 500;
    line-height: 1;
    text-decoration: none;
    white-space: nowrap;
    cursor: pointer;
    transition: background-color 0.25s cubic-bezier(0.16, 1, 0.3, 1),
                color 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
/* Light-surface defaults — primary = dark/cream, secondary = cream/dark.
   These mirror the design system buttons in lf-cta-section. */
.lf-cta-group__btn--primary {
    background-color: var(--cta-primary-bg);
    color: var(--cta-primary-text);
}
.lf-cta-group__btn--primary:hover,
.lf-cta-group__btn--primary:focus-visible {
    background-color: color-mix(in srgb, var(--cta-primary-bg), white 10%);
    color: var(--cta-primary-text);
}
.lf-cta-group__btn--secondary {
    background-color: var(--cta-secondary-bg);
    color: var(--cta-secondary-text);
}
.lf-cta-group__btn--secondary:hover,
.lf-cta-group__btn--secondary:focus-visible {
    background-color: color-mix(in srgb, var(--cta-secondary-bg), black 10%);
    color: var(--cta-secondary-text);
}

/* Hero-on-olive inversion — Figma 500:4349 shows primary as cream/dark
   (the bright button) and secondary as #2c2c2c/cream (the darker pill).
   Override the light-surface base treatment within the hero scope. */
.lf-hero-50 .lf-cta-group__btn--primary {
    background-color: var(--text-primary-inv);
    color: var(--text-primary);
}
.lf-hero-50 .lf-cta-group__btn--primary:hover,
.lf-hero-50 .lf-cta-group__btn--primary:focus-visible {
    background-color: color-mix(in srgb, var(--text-primary-inv), black 10%);
    color: var(--text-primary);
}
.lf-hero-50 .lf-cta-group__btn--secondary {
    background-color: #2c2c2c;
    color: var(--text-primary-inv);
}
.lf-hero-50 .lf-cta-group__btn--secondary:hover,
.lf-hero-50 .lf-cta-group__btn--secondary:focus-visible {
    background-color: color-mix(in srgb, #2c2c2c, white 10%);
    color: var(--text-primary-inv);
}

/* ---- Semplice `button` modules in the hero -------------------
   The hero uses two real Semplice button modules (data-module="button")
   so authors get the standard popup for editing label, link, target,
   and so on. The site-wide override at `.smp-button .is-content` (line
   ~209) makes every Semplice button render as the project's primary
   dark-on-light pill — here we override that for the hero context.

   Primary vs. secondary is distinguished by a CSS Class set on the
   button module: `lf-hero-btn--primary` or `lf-hero-btn--secondary`.
   That class lands on the outer `.smp-button` div (same as how
   `.smp-button.btn-secondary` is selected elsewhere). The Semplice
   per-instance CSS for each button still wins on its own selector,
   so we use !important to override the popup-injected hex colors. */

.lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content,
.lf-hero-50 .smp-button.lf-hero-btn--secondary .is-content {
    height: 40px !important;
    padding: 0 !important;
    border-radius: var(--r-pill) !important;
    background-image: none !important;
    transition:
        background-color 0.25s cubic-bezier(0.16, 1, 0.3, 1),
        color 0.25s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
.lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content a,
.lf-hero-50 .smp-button.lf-hero-btn--secondary .is-content a {
    padding: 8px 16px !important;
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    font-weight: 500 !important;
    line-height: 1 !important;
    text-decoration: none !important;
}

/* Primary — cream pill on olive */
.lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content {
    background-color: var(--text-primary-inv) !important;
}
.lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content a {
    color: var(--text-primary) !important;
}
#content-holder#content-holder .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content:hover {
    background-color: color-mix(in srgb, var(--text-primary-inv), black 10%) !important;
    background-image: none !important;
}
#content-holder#content-holder .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content:hover a {
    color: var(--text-primary) !important;
}

/* Secondary — darker pill on olive */
.lf-hero-50 .smp-button.lf-hero-btn--secondary .is-content {
    background-color: #2c2c2c !important;
}
.lf-hero-50 .smp-button.lf-hero-btn--secondary .is-content a {
    color: var(--text-primary-inv) !important;
}
#content-holder#content-holder .lf-hero-50 .smp-button.lf-hero-btn--secondary .is-content:hover {
    background-color: color-mix(in srgb, #2c2c2c, white 10%) !important;
    background-image: none !important;
}
#content-holder#content-holder .lf-hero-50 .smp-button.lf-hero-btn--secondary .is-content:hover a {
    color: var(--text-primary-inv) !important;
}

/* Right column: image fill. Semplice's image module nests
   smp-content > .smp-image > .is-content > img — each level needs
   explicit height: 100% or the chain breaks and the image collapses
   to 0 height at narrower viewports. Semplice's frontend.css sets
   `.smp-image .is-content img { height: auto }` and `.smp-image` to
   display: flex — we override down to the img with object-fit: cover. */
.lf-hero-50-right {
    align-self: stretch;
    background-color: var(--text-primary); /* fallback if image missing */
    overflow: hidden;
    /* See .lf-hero-50-left comment — both columns capped so a portrait
       image can't push the row taller than the viewport. */
    max-height: 100vh;
}
.lf-hero-50-right > smp-content-wrapper {
    height: 100%;
    width: 100%;
    display: flex;
}
.lf-hero-50-right smp-content[data-module="image"],
.lf-hero-50-right smp-content[data-module="image"] .smp-image,
.lf-hero-50-right smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
    flex: 1 1 auto;
}
.lf-hero-50-right smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    object-fit: cover !important;
    display: block;
    border-radius: 0 !important;
}

/* ---- Responsive ----------------------------------------------- */

@media (max-width: 1199px) {
    .lf-hero-50-left > smp-content-wrapper {
        padding-top: 160px;
        padding-bottom: 160px;
        padding-left: 80px;
        padding-right: 24px;
    }
}

@media (max-width: 1023px) {
    .lf-hero-50-left > smp-content-wrapper {
        padding-top: 140px;
        padding-bottom: 140px;
        padding-left: 56px;
        padding-right: 24px;
    }
}

/* Stack columns at 860px — image on top, text below.
   In flex-direction: column the main-axis becomes vertical, so a
   `flex-basis: 100%` on the columns would override the explicit
   `height: clamp(...)` on the right column (basis controls main-axis
   size). Use `flex: 0 0 auto` so explicit height/min-height win. */
@media (max-width: 860px) {
    .lf-hero-50 smp-row {
        flex-direction: column !important;
        min-height: auto;
        /* Stacked layout — height = text content + image clamp; turn off the
           desktop viewport cap so stacked content can flow naturally. */
        max-height: none;
    }
    .lf-hero-50-left,
    .lf-hero-50-right {
        width: 100% !important;
        flex: 0 0 auto !important;
        max-width: 100% !important;
    }
    .lf-hero-50-right {
        order: -1;
        height: clamp(320px, 50vh, 480px) !important;
    }
    .lf-hero-50-left > smp-content-wrapper {
        padding-top: 80px;
        padding-bottom: 80px;
        padding-left: 40px;
        padding-right: 40px;
        height: auto;
        justify-content: flex-start;
    }
    .lf-hero-headline {
        font-size: clamp(40px, 6vw, 56px) !important;
    }
}

@media (max-width: 640px) {
    .lf-hero-50-left > smp-content-wrapper {
        padding-top: 56px;
        padding-bottom: 56px;
        padding-left: 24px;
        padding-right: 24px;
    }
    .lf-hero-headline {
        font-size: clamp(32px, 8vw, 44px) !important;
    }
    /* Stack the buttons inside the second subrow — direction column, full width */
    .lf-hero-50-left smp-subrow:nth-of-type(2) {
        flex-direction: column;
        width: 100%;
        gap: 10px;
    }
    .lf-hero-50 smp-content.lf-hero-btn--primary,
    .lf-hero-50 smp-content.lf-hero-btn--secondary,
    .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button,
    .lf-hero-50 smp-content.lf-hero-btn--secondary .smp-button {
        width: 100%;
    }
    .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content,
    .lf-hero-50 smp-content.lf-hero-btn--secondary .smp-button .is-content {
        height: 44px !important;
        width: 100% !important;
    }
    .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content a,
    .lf-hero-50 smp-content.lf-hero-btn--secondary .smp-button .is-content a {
        font-size: 15px !important;
        width: 100%;
        justify-content: center;
    }
}

@media (max-width: 380px) {
    .lf-hero-50-left > smp-content-wrapper {
        padding-top: 48px;
        padding-bottom: 48px;
        padding-left: 20px;
        padding-right: 20px;
    }
}

/* ---- Semplice editor preview-mode mirrors --------------------
   Semplice's editor switches preview modes (xl/lg/md/sm/xs) by
   flipping a `data-breakpoint` attribute on a canvas wrapper —
   without actually resizing the iframe viewport. That means our
   @media rules don't fire when authors switch modes in the editor.
   Mirror each @media rule with a `[data-breakpoint="..."]` selector
   so the layout updates in the editor preview too.

   Mapping (xl ≥1200, lg 1024-1199, md 768-1023, sm 480-767, xs <480):
     @media (max-width: 1199px) → lg, md, sm, xs
     @media (max-width: 1023px) → md, sm, xs
     @media (max-width: 860px)  → sm, xs (stack columns)
     @media (max-width: 640px)  → sm, xs (button stack — same as 860 since md is 1024+)
     @media (max-width: 380px)  → xs                                 */

[data-breakpoint="lg"] .lf-hero-50-left > smp-content-wrapper,
[data-breakpoint="md"] .lf-hero-50-left > smp-content-wrapper,
[data-breakpoint="sm"] .lf-hero-50-left > smp-content-wrapper,
[data-breakpoint="xs"] .lf-hero-50-left > smp-content-wrapper {
    padding-top: 160px;
    padding-bottom: 160px;
    padding-left: 80px;
    padding-right: 24px;
}

[data-breakpoint="md"] .lf-hero-50-left > smp-content-wrapper,
[data-breakpoint="sm"] .lf-hero-50-left > smp-content-wrapper,
[data-breakpoint="xs"] .lf-hero-50-left > smp-content-wrapper {
    padding-top: 140px;
    padding-bottom: 140px;
    padding-left: 56px;
    padding-right: 24px;
}

/* Stack columns from sm down (matches @media max-width: 860px) */
[data-breakpoint="sm"] .lf-hero-50 smp-row,
[data-breakpoint="xs"] .lf-hero-50 smp-row {
    flex-direction: column !important;
    min-height: auto;
    max-height: none;
}
[data-breakpoint="sm"] .lf-hero-50-left,
[data-breakpoint="sm"] .lf-hero-50-right,
[data-breakpoint="xs"] .lf-hero-50-left,
[data-breakpoint="xs"] .lf-hero-50-right {
    width: 100% !important;
    flex: 0 0 auto !important;
    max-width: 100% !important;
}
[data-breakpoint="sm"] .lf-hero-50-right,
[data-breakpoint="xs"] .lf-hero-50-right {
    order: -1;
    height: clamp(320px, 50vh, 480px) !important;
}
[data-breakpoint="sm"] .lf-hero-50-left > smp-content-wrapper,
[data-breakpoint="xs"] .lf-hero-50-left > smp-content-wrapper {
    padding-top: 80px;
    padding-bottom: 80px;
    padding-left: 40px;
    padding-right: 40px;
    height: auto;
    justify-content: flex-start;
}
[data-breakpoint="sm"] .lf-hero-headline,
[data-breakpoint="xs"] .lf-hero-headline {
    font-size: clamp(40px, 6vw, 56px) !important;
}

/* Button stacking + tighter padding from sm down (matches @media max-width: 640px) */
[data-breakpoint="sm"] .lf-hero-50-left > smp-content-wrapper,
[data-breakpoint="xs"] .lf-hero-50-left > smp-content-wrapper {
    padding-top: 56px;
    padding-bottom: 56px;
    padding-left: 24px;
    padding-right: 24px;
}
[data-breakpoint="sm"] .lf-hero-headline,
[data-breakpoint="xs"] .lf-hero-headline {
    font-size: clamp(32px, 8vw, 44px) !important;
}
[data-breakpoint="sm"] .lf-hero-50-left smp-subrow:nth-of-type(2),
[data-breakpoint="xs"] .lf-hero-50-left smp-subrow:nth-of-type(2) {
    flex-direction: column;
    width: 100%;
    gap: 10px;
}
[data-breakpoint="sm"] .lf-hero-50 smp-content.lf-hero-btn--primary,
[data-breakpoint="sm"] .lf-hero-50 smp-content.lf-hero-btn--secondary,
[data-breakpoint="sm"] .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button,
[data-breakpoint="sm"] .lf-hero-50 smp-content.lf-hero-btn--secondary .smp-button,
[data-breakpoint="xs"] .lf-hero-50 smp-content.lf-hero-btn--primary,
[data-breakpoint="xs"] .lf-hero-50 smp-content.lf-hero-btn--secondary,
[data-breakpoint="xs"] .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button,
[data-breakpoint="xs"] .lf-hero-50 smp-content.lf-hero-btn--secondary .smp-button {
    width: 100%;
}
[data-breakpoint="sm"] .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content,
[data-breakpoint="sm"] .lf-hero-50 smp-content.lf-hero-btn--secondary .smp-button .is-content,
[data-breakpoint="xs"] .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content,
[data-breakpoint="xs"] .lf-hero-50 smp-content.lf-hero-btn--secondary .smp-button .is-content {
    height: 44px !important;
    width: 100% !important;
}
[data-breakpoint="sm"] .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content a,
[data-breakpoint="sm"] .lf-hero-50 smp-content.lf-hero-btn--secondary .smp-button .is-content a,
[data-breakpoint="xs"] .lf-hero-50 smp-content.lf-hero-btn--primary .smp-button .is-content a,
[data-breakpoint="xs"] .lf-hero-50 smp-content.lf-hero-btn--secondary .smp-button .is-content a {
    font-size: 15px !important;
    width: 100%;
    justify-content: center;
}

/* Extra-narrow (matches @media max-width: 380px) — xs only */
[data-breakpoint="xs"] .lf-hero-50-left > smp-content-wrapper {
    padding-top: 48px;
    padding-bottom: 48px;
    padding-left: 20px;
    padding-right: 20px;
}

/* =============================================================
   Tier Cards (3-up) — Figma 500:4434 (Living at Lakefront, "Three
   ways to live here").
   Ecru section. Left-anchored header (heading + body, max 588px)
   over a 3-column card grid. Each card: 3:2 image, cream content
   panel below with title / body / price stacked.

   Saved Block: master_lftiercards01 (in "New Modules" category).
   Composed entirely from Semplice's stock text + image modules
   so every piece is native-popup-editable — no custom module.

   Structure — each card is a Semplice COLUMN (not a subrow), so
   authors get a clickable column popup per card for editing bg,
   padding, alignment, hover, etc. The tradeoff vs the previous
   column-wrap layout: section bg can't be edited via a single
   wrapping-column popup (that would force cards into subrows).
   Section bg is set in CSS instead, overridable by the section
   popup if the author finds it (popup positioning is finicky).

     section.lf-tier-cards         (ecru bg via CSS, 96 padding)
       smp-container                (120px page gutter)
         row 1
           column.lf-tier-cards-header   ← clickable: header column popup
             heading
             lede
         row 2 (cards row, flex with 24px gap)
           column.lf-tier-cards-card     ← clickable: card 1 popup
             image, title, body, price   (direct contents, no nested row)
           column.lf-tier-cards-card     ← clickable: card 2 popup
             image, title, body, price
           column.lf-tier-cards-card     ← clickable: card 3 popup
             image, title, body, price
   ============================================================= */

/* ---- Section chrome ---------------------------------------- */
/* Section bg + vertical padding live in the section ram's `styles.xl`
   (background-color, padding-top, padding-bottom) so they're fully
   popup-editable. Once `customHeight.xl.height` is set on the ram
   (required for the section popup to render at all), Semplice's
   picker pre-fills from styles.xl correctly and the safe-override
   pattern works: author picks a color → per-instance CSS → frontend
   updates; save without touching → preserved.

   This file only handles horizontal gutter (which goes on smp-container
   to avoid double-stacking with Semplice's centered container) and
   the inter-row gap, which sits on smp-container as a flex `gap` —
   never as `margin-top` between sibling rows. */
.lf-tier-cards smp-container {
    --gutter-page: var(--smp-grid-outer-desktop, 120px);
    padding-left: var(--gutter-page) !important;
    padding-right: var(--gutter-page) !important;
    /* smp-container is `display: flex; flex-direction: row` by default.
       Switch to column so rows stack vertically with `gap` between
       them (replaces the prior `smp-row + smp-row { margin-top }`
       antipattern). */
    flex-direction: column !important;
    gap: 48px;
}

/* ---- Header row (1 column, contents inside) ----------------- */
/* The header column is clickable for a column popup (padding,
   alignment, etc.). The content wrapper stacks heading + lede
   with 16px gap, capped at 588px to match Figma's left-anchored
   header block. */
.lf-tier-cards-header > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
    max-width: 588px;
}
.lf-tier-cards__heading {
    font-family: var(--font-serif) !important;
    font-size: 40px !important;
    font-weight: 400 !important;
    line-height: var(--lh-display) !important;
    color: var(--text-primary) !important;
    margin: 0 !important;
}
.lf-tier-cards__lede {
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    color: var(--text-primary) !important;
    margin: 0 !important;
}

/* ---- Cards row (3 columns, 24px gap) ----------------------- */
/* Semplice emits `data-gutter="no"` row CSS that uses flex with
   no gap, AND each column gets a per-instance `flex: 0 0 33.3333%`
   for width:4-of-12 — leaving zero room for any gap. Override:
   gap on the row, and flex-basis 0 on columns so they grow
   equally and the gap subtracts from the total. */
.lf-tier-cards smp-row:nth-of-type(2) {
    gap: 24px;
    flex-wrap: wrap;
}
.lf-tier-cards smp-row:nth-of-type(2) > smp-column {
    flex: 1 1 0% !important;
    min-width: 0;
}

/* ---- Card columns (each card is a column, clickable) -------- */
/* Card styling scoped to any column in the cards row. The author
   can duplicate a card column or drop a new one in via Semplice's
   UI and it auto-picks up cream bg + the image+texts layout — no
   CSS Class field required. Each card column has its OWN popup
   for editing bg, padding, alignment, motions. Contents inside
   the column are direct children (no nested row, no subrow). */
.lf-tier-cards smp-row:nth-of-type(2) > smp-column {
    /* Card bg now lives in each column's `styles.xl.background-color`
       in the ram (popup-editable per breakpoint, matches the section
       pattern). Only structural-only properties remain here — they
       aren't exposed by Semplice's column popup so they have to stay
       in CSS regardless. */
    align-self: stretch;
    overflow: hidden;
}
.lf-tier-cards smp-row:nth-of-type(2) > smp-column > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    height: 100%;
    width: 100%;
}

/* Card image — 3:2 aspect, full-bleed to card edges.
   Image module's deep nesting (smp-content > .smp-image >
   .is-content > img) each needs explicit sizing or the image
   collapses to 0 at narrow viewports (Recipe D / gotcha #5). */
.lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="image"] {
    width: 100% !important;
    aspect-ratio: 3 / 2;
    overflow: hidden;
    flex: 0 0 auto;
    margin: 0 !important;
}
.lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="image"] .smp-image,
.lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
}
.lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    object-fit: cover !important;
    display: block;
    border-radius: 0 !important;
    opacity: 0.85;       /* permanent dim — no hover differential per Figma */
}

/* Card text contents — padded on sides; first text below image
   picks up the cream "panel" top padding; subsequent texts gap 16;
   last text closes with 24 bottom padding. */
.lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="text"] {
    padding-left: 24px;
    padding-right: 24px;
    margin: 0 !important;
}
.lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="image"] + smp-content[data-module="text"] {
    padding-top: 24px;
}
.lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="text"] + smp-content[data-module="text"] {
    margin-top: 16px !important;
}
.lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="text"]:last-child {
    padding-bottom: 24px;
}

.lf-tier-cards__title {
    font-family: var(--font-serif) !important;
    font-size: 24px !important;
    font-weight: 400 !important;
    line-height: var(--lh-display) !important;
    color: var(--text-primary) !important;
}
.lf-tier-cards__body {
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    color: var(--text-primary) !important;
    /* Body grows so the price line sticks to the bottom of the
       card panel, keeping price baselines aligned across cards
       with different body lengths. */
    flex: 1 0 auto;
}
.lf-tier-cards__price {
    font-family: var(--font-sans) !important;
    font-size: 20px !important;
    font-weight: 500 !important;
    line-height: var(--lh-body) !important;
    color: var(--text-primary) !important;
}

/* ---- Responsive ------------------------------------------- */
/* ≤1023: keep 3-up, tighten gutters + section padding.
   ≤860: collapse cards row to single-column stack.
   ≤640: tighter card-panel padding + smaller heading.
   ≤380: smallest gutter. */

@media (max-width: 1023px) {
    .lf-tier-cards smp-container {
        --gutter-page: 40px;
        gap: 40px;                              /* tighter inter-row gap */
    }
    .lf-tier-cards__heading {
        font-size: 36px !important;
    }
}

@media (max-width: 860px) {
    /* Stack cards via flex-direction: column on the cards row. */
    .lf-tier-cards smp-row:nth-of-type(2) {
        flex-direction: column;
        gap: 24px;
    }
    .lf-tier-cards smp-row:nth-of-type(2) > smp-column {
        flex: 0 0 auto !important;
        width: 100% !important;
        max-width: 100% !important;
    }
    .lf-tier-cards__heading {
        font-size: 32px !important;
    }
}

@media (max-width: 640px) {
    .lf-tier-cards smp-container {
        --gutter-page: 16px;
        gap: 32px;
    }
    .lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="text"] {
        padding-left: 20px;
        padding-right: 20px;
    }
    .lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="image"] + smp-content[data-module="text"] {
        padding-top: 20px;
    }
    .lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="text"]:last-child {
        padding-bottom: 20px;
    }
    .lf-tier-cards__heading {
        font-size: 28px !important;
    }
    .lf-tier-cards__title {
        font-size: 22px !important;
    }
    .lf-tier-cards__price {
        font-size: 18px !important;
    }
}

@media (max-width: 380px) {
    .lf-tier-cards smp-container {
        --gutter-page: 16px;
    }
    .lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="text"] {
        padding-left: 16px;
        padding-right: 16px;
    }
    .lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="image"] + smp-content[data-module="text"] {
        padding-top: 16px;
    }
    .lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="text"]:last-child {
        padding-bottom: 16px;
    }
}

/* ---- Editor preview-mode mirrors ---------------------------
   Semplice's xl/lg/md/sm/xs preview buttons flip `data-breakpoint`
   without resizing the iframe, so @media rules don't fire in the
   editor. Mirror each rule by attribute. */

[data-breakpoint="md"] .lf-tier-cards smp-container,
[data-breakpoint="sm"] .lf-tier-cards smp-container,
[data-breakpoint="xs"] .lf-tier-cards smp-container {
    --gutter-page: 40px;
    gap: 40px;
}
[data-breakpoint="md"] .lf-tier-cards__heading,
[data-breakpoint="sm"] .lf-tier-cards__heading,
[data-breakpoint="xs"] .lf-tier-cards__heading {
    font-size: 36px !important;
}

/* Stack cards from sm down */
[data-breakpoint="sm"] .lf-tier-cards smp-row:nth-of-type(2),
[data-breakpoint="xs"] .lf-tier-cards smp-row:nth-of-type(2) {
    flex-direction: column;
    gap: 24px;
}
[data-breakpoint="sm"] .lf-tier-cards smp-row:nth-of-type(2) > smp-column,
[data-breakpoint="xs"] .lf-tier-cards smp-row:nth-of-type(2) > smp-column {
    flex: 0 0 auto !important;
    width: 100% !important;
    max-width: 100% !important;
}
[data-breakpoint="sm"] .lf-tier-cards__heading,
[data-breakpoint="xs"] .lf-tier-cards__heading {
    font-size: 32px !important;
}

/* Tighter inner paddings on xs */
[data-breakpoint="xs"] .lf-tier-cards smp-container {
    --gutter-page: 16px;
    gap: 32px;
}
[data-breakpoint="xs"] .lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="text"] {
    padding-left: 20px;
    padding-right: 20px;
}
[data-breakpoint="xs"] .lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="image"] + smp-content[data-module="text"] {
    padding-top: 20px;
}
[data-breakpoint="xs"] .lf-tier-cards smp-row:nth-of-type(2) > smp-column smp-content[data-module="text"]:last-child {
    padding-bottom: 20px;
}
[data-breakpoint="xs"] .lf-tier-cards__heading {
    font-size: 28px !important;
}
[data-breakpoint="xs"] .lf-tier-cards__title {
    font-size: 22px !important;
}
[data-breakpoint="xs"] .lf-tier-cards__price {
    font-size: 18px !important;
}

/* =============================================================
   Image + Text Split — atomic Saved Block (master_lfimgtextsplit01)
   Asymmetric 6-5 column layout with a 1-column visual offset.
   Section/column/text padding all live in the section's ram so authors
   can edit them through the Semplice section popup. Backgrounds also
   come from ram (the `bg-*` utility classes can be added via the CSS
   class field on the section).

   First used by Living at Lakefront's "Building and the land" composition
   (image = hand-drawn site map, text = heading + paragraph). Reused
   anywhere a designed 6-5 split is wanted.
   ============================================================= */

/* Row: smp-row is display:flex by default (gap: normal = 0). Real flex
   gap on the row produces the 1-col visual offset between map and text —
   no spacer column, no lazy margin. 8.3333% = 1/12 of the row width.
   Shared with `.lf-text-image` (About-story variant) since both use the
   same 6+5 split with 1-col gap. */
.lf-img-text-split smp-row,
.lf-text-image smp-row {
    gap: 8.3333% !important;
}
/* Section container is flex-row by default; keep it that way (one row only).
   Photo Strip section handles its own internal flex column if it has subrows. */

.lf-img-text-split__img {
    background-color: var(--color-ecru);
    align-self: stretch;
    overflow: hidden;
}
.lf-img-text-split__img > smp-content-wrapper {
    display: flex !important;
    width: 100%;
    height: 100%;
    min-height: 560px;       /* Figma h-[560px] floor; image fills */
}
/* Image module fill chain — Recipe D in MODULE-PATTERNS.md §7. */
.lf-img-text-split__img smp-content[data-module="image"],
.lf-img-text-split__img smp-content[data-module="image"] .smp-image,
.lf-img-text-split__img smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
    flex: 1 1 auto;
}
.lf-img-text-split__img smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    object-fit: contain !important;     /* contain — illustrated maps must stay readable */
    object-position: center;
    display: block;
    border-radius: 0 !important;
}

/* Text column: heading + body, vertically centered with one gap. */
.lf-img-text-split__text > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
    gap: 16px;
    width: 100%;
    height: 100%;
}
.lf-h1-48 {
    font-family: var(--font-serif) !important;
    font-size: 48px !important;
    line-height: 1.1 !important;
    color: var(--text-primary) !important;
    margin: 0;
}
.lf-h2-40 {
    font-family: var(--font-serif) !important;
    font-size: 40px !important;
    line-height: 1.1 !important;
    color: var(--text-primary) !important;
    margin: 0;
}
.lf-h2-32 {
    font-family: var(--font-serif) !important;
    font-size: 32px !important;
    line-height: 1.1 !important;
    color: var(--text-primary) !important;
    margin: 0;
}
.lf-body-16 {
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    color: var(--text-primary) !important;
}
.lf-body-16 p { margin: 0 0 1em 0; }
.lf-body-16 p:last-child { margin-bottom: 0; }
.lf-body-16--muted { color: var(--text-secondary) !important; }
.lf-body-16--muted p { color: var(--text-secondary) !important; }
.lf-body-14-muted {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    color: rgba(26, 26, 26, 0.5) !important;
    margin: 0;
}
.lf-h2-32-muted-70 {
    font-family: var(--font-serif) !important;
    font-size: 32px !important;
    line-height: 1.1 !important;
    color: var(--text-primary) !important;
    opacity: 0.7;
    margin: 0;
}
/* 32px Instrument Serif body — full-dark, 1.3 line-height. Distinct
   from .lf-h2-32 (line-height 1.1 for tight headings) and from
   .serif-lead (60% opacity). Used in the Segment + CTA atomic for
   the Figma section-4 body block. The `#content-holder` prefix on
   the `p` rules is mandatory: Semplice's frontend.css sets
   `#content-holder p { font-family/size/color }` at (1,0,1) which
   wins over an unscoped `.lf-serif-32-body p` selector. See §0.5
   principle 7 ("the specificity gauntlet for typography"). */
.lf-serif-32-body {
    font-family: var(--font-serif) !important;
    font-size: 32px !important;
    font-weight: 400 !important;
    line-height: 1.3 !important;
    color: var(--text-primary) !important;
    opacity: 0.6;
}
#content-holder .lf-serif-32-body p {
    font-family: var(--font-serif) !important;
    font-size: 32px !important;
    font-weight: 400 !important;
    line-height: 1.3 !important;
    color: var(--text-primary) !important;
    margin: 0 0 1em 0 !important;
}
#content-holder .lf-serif-32-body p:last-child { margin-bottom: 0 !important; }

/* =============================================================
   Photo Strip — atomic Saved Block (master_lfphotostrip01)
   Single 12-wide column holding a native Semplice `gallery` module.
   The gallery's image list is popup-editable (just like FAQ uses the
   native accordion). Author flow: click the gallery on the canvas →
   the gallery popup opens → add/remove/reorder photos via the media
   picker. CSS below skins Flickity's emitted HTML into the Figma-spec
   horizontal strip with bottom-centered dots.

   Wrapper section padding lives in ram (admin-editable). The strip
   itself breaks out to 100vw so it spans viewport edges regardless of
   the parent column's width.
   ============================================================= */

.lf-photo-strip-section { overflow: hidden; }

/* Photo Strip = a column with class `lf-photo-strip-track` containing N
   standard Semplice `image` modules. Each photo is individually popup-
   editable (click the image in canvas → image popup). Add photos via the
   "+ Add Module → Image" menu inside the column. Drag image modules to
   reorder. Delete to remove.

   Frontend renders as a CSS-keyframes marquee (lf-marquee pattern). JS
   clones the N slides once so the wrapper holds 2N images; the keyframes
   animation translates the wrapper from 0 to -50% and loops infinitely —
   visually seamless because slide N+i is a clone of slide i. JS sets the
   animation-duration inline based on measured wrapper width so the speed
   stays constant across viewports. No drag; dot pagination still works.

   Full-bleed is achieved by zeroing the section's smp-container padding +
   100vw + negative-margin on the track. */

/* JS sets `--lf-wrap-start` and `--lf-wrap-end` to the exact pixel values so
   the loop point lands on a clone-equivalent of the start frame. Using -50%
   is NOT seamless here: scrollWidth/2 ≠ originalCount × (slideWidth+gap)
   because of the wrapper's horizontal padding and the gap math (N gaps
   inside one set, 2N-1 gaps total). Mismatch == visible jump at wrap. */
@keyframes lf-photo-strip-scroll {
    from { transform: translate3d(var(--lf-wrap-start, 0px), 0, 0); }
    to   { transform: translate3d(var(--lf-wrap-end, -50%), 0, 0); }
}

.lf-photo-strip-section smp-container { padding-left: 0 !important; padding-right: 0 !important; }
.lf-photo-strip-section smp-row { width: 100% !important; max-width: none !important; }

/* Embla viewport. The column itself acts as the viewport: overflow:hidden so
   slides moved by Embla's translateX don't escape. Width 100vw + negative
   margins escape parent column-width constraints. */
#content-holder .lf-photo-strip-track {
    width: 100vw !important;
    max-width: 100vw !important;
    flex: 1 1 100vw !important;
    position: relative;
    left: 50%;
    margin-left: -50vw !important;
    margin-right: -50vw !important;
    overflow: hidden;
    height: 480px;          /* matches the wrapper inside — keeps centered
                                slides from getting clipped at the bottom */
}

/* Marquee container. JS sets animation-duration inline (computed from
   measured halfWidth ÷ target px/s so speed stays constant across viewports).
   flex-row + max-content so slides sit side by side. will-change: transform
   promotes the layer to GPU so the long animation stays smooth.

   align-items: center keeps slides of different natural aspect ratios
   vertically centered on a shared axis — taller portraits extend up
   AND down equally while shorter landscapes/squares sit centered in
   the strip for an editorial, varied feel (Figma 500:4411). */
#content-holder .lf-photo-strip-track > smp-content-wrapper {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: center;
    gap: 80px;
    padding: 0 120px;
    width: max-content !important;
    height: 480px !important;       /* enough headroom for the tallest portrait */
    will-change: transform;
    backface-visibility: hidden;
    animation-name: lf-photo-strip-scroll;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    /* animation-duration set inline by JS once wrapper width is known */
}

/* Each image module slide — fixed width, height follows natural aspect.
   This is the inverse of the previous "fixed height / auto width" setup;
   it produces variable per-slide heights so portraits/landscapes/squares
   read as distinctly different sizes in the strip. The max-height cap
   keeps very tall portraits from breaking the track height. */
.lf-photo-strip-track > smp-content-wrapper > smp-content[data-module="image"] {
    flex: 0 0 320px !important;
    width: 320px !important;
    height: auto !important;
    max-width: 320px !important;
    margin: 0 !important;                /* gap on parent does the spacing */
    pointer-events: auto;                 /* keep image clickable for editor popup */
    user-select: none;
    -webkit-user-drag: none;
}
/* Image-fill chain — Recipe D in MODULE-PATTERNS.md §7.
   Width = slide width; height auto preserves the natural aspect. */
.lf-photo-strip-track smp-content[data-module="image"] .smp-image,
.lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content {
    width: 320px !important;
    height: auto !important;
}
.lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content img {
    width: 320px !important;
    height: auto !important;
    max-width: 320px !important;
    max-height: 480px !important;
    object-fit: cover;
    display: block;
    border-radius: 0 !important;
}

/* Dot pagination row — JS appends a `<div class="lf-photo-strip-dots">`
   sibling of the track element. One dot per image module, click to scroll. */
.lf-photo-strip-dots {
    display: flex;
    gap: 8px;
    justify-content: center;
    align-items: center;
    width: 100vw;
    margin-top: 80px;
}
.lf-photo-strip-dot {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background-color: rgba(26, 26, 26, 0.2);
    border: 0;
    padding: 0;
    margin: 0;
    cursor: pointer;
    transition: background-color 0.2s ease;
}
.lf-photo-strip-dot.is-active { background-color: var(--text-primary); }
.lf-photo-strip-dot:focus-visible { outline: 2px solid var(--text-primary); outline-offset: 2px; }

/* Editor canvas: Embla JS is gated out by is_admin(). Render the strip as
   a 4-col grid of thumbnails so the author can see every photo and click
   any one to open the image popup (swap source, edit alt, etc.).

   The 100vw + -50vw full-bleed dance is also undone in admin so the strip
   sits inside the normal column boundary — keeps the editor's selection
   outlines and add-module affordances aligned with the rest of the canvas. */
body.wp-admin .lf-photo-strip-section { overflow: visible !important; }
body.wp-admin #content-holder .lf-photo-strip-track {
    position: static !important;
    left: auto !important;
    right: auto !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    overflow: visible !important;
    height: auto !important;
    cursor: default !important;
}
body.wp-admin #content-holder .lf-photo-strip-track > smp-content-wrapper {
    display: grid !important;
    grid-template-columns: repeat(4, minmax(0, 1fr)) !important;
    grid-auto-rows: 200px !important;
    gap: 16px !important;
    padding: 0 !important;
    width: 100% !important;
    height: auto !important;
    transform: none !important;
    animation: none !important;       /* no marquee in the editor canvas */
}
/* Override the frontend's "natural aspect width" with a uniform cell box
   so the grid stays tidy regardless of which photos the author has loaded. */
body.wp-admin .lf-photo-strip-track > smp-content-wrapper > smp-content[data-module="image"] {
    width: 100% !important;
    height: 200px !important;
}
body.wp-admin .lf-photo-strip-track smp-content[data-module="image"] .smp-image,
body.wp-admin .lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    height: 200px !important;
}
body.wp-admin .lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: 200px !important;
    object-fit: cover;
}
body.wp-admin .lf-photo-strip-dots { display: none !important; }

/* ---- Responsive ---- */

@media (max-width: 860px) {
    /* Stack the image+text-split columns on small screens. The
       max-width / flex-basis overrides are needed to beat Semplice's
       `[data-xl-width="N"]` per-instance CSS, which caps both. */
    .lf-img-text-split smp-row { gap: 24px !important; flex-direction: column !important; }
    .lf-img-text-split__img,
    .lf-img-text-split__text {
        width: 100% !important;
        max-width: 100% !important;
        flex-basis: 100% !important;
        flex: 0 0 auto !important;
    }
    .lf-img-text-split__img > smp-content-wrapper { min-height: 360px; }
    .lf-h2-32 { font-size: 28px !important; }
    .lf-serif-32-body,
    #content-holder .lf-serif-32-body p { font-size: 24px !important; }

    /* Photo strip row: needs display:block so the row collapses to its
       content height. By default smp-row is `display: flex` AND the row
       is `flex: 1 1 auto` inside `smp-container { display: flex;
       flex-direction: column }`, so the row grows to fill the container's
       distributed height — then `align-items: stretch` stretches the
       photo-strip column past its explicit 260px. Switching the row to
       block layout takes both effects out of play. Scoped via `:has()`
       so only the row containing the strip is affected (the text+image
       row above it stays flex). */
    .lf-photo-strip-section smp-row:has(> smp-column.lf-photo-strip-track) {
        display: block !important;
    }
    #content-holder .lf-photo-strip-track {
        height: 360px !important;
    }
    #content-holder .lf-photo-strip-track > smp-content-wrapper {
        gap: 24px !important;
        padding: 0 32px !important;
        height: 360px !important;
    }
    /* Mobile: narrower slide width, shorter max-height — same variable
       heights pattern as desktop. */
    .lf-photo-strip-track > smp-content-wrapper > smp-content[data-module="image"] {
        flex: 0 0 220px !important;
        width: 220px !important;
        max-width: 220px !important;
        height: auto !important;
    }
    .lf-photo-strip-track smp-content[data-module="image"] .smp-image,
    .lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content {
        width: 220px !important;
        height: auto !important;
    }
    .lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content img {
        width: 220px !important;
        height: auto !important;
        max-width: 220px !important;
        max-height: 360px !important;
    }
    .lf-photo-strip-dots { margin-top: 48px; }
}

/* Editor preview-mode mirrors — Semplice's iframe doesn't reflow on
   breakpoint switch, so @media never fires there. */
[data-breakpoint="sm"] .lf-img-text-split smp-row,
[data-breakpoint="xs"] .lf-img-text-split smp-row {
    gap: 24px !important;
    flex-direction: column !important;
}
[data-breakpoint="sm"] .lf-img-text-split__img,
[data-breakpoint="xs"] .lf-img-text-split__img,
[data-breakpoint="sm"] .lf-img-text-split__text,
[data-breakpoint="xs"] .lf-img-text-split__text {
    width: 100% !important;
    flex: 0 0 auto !important;
}
[data-breakpoint="sm"] .lf-img-text-split__img > smp-content-wrapper,
[data-breakpoint="xs"] .lf-img-text-split__img > smp-content-wrapper {
    min-height: 360px;
}
[data-breakpoint="sm"] .lf-h2-32,
[data-breakpoint="xs"] .lf-h2-32 {
    font-size: 28px !important;
}
[data-breakpoint="sm"] .lf-serif-32-body,
[data-breakpoint="xs"] .lf-serif-32-body,
[data-breakpoint="sm"] #content-holder .lf-serif-32-body p,
[data-breakpoint="xs"] #content-holder .lf-serif-32-body p {
    font-size: 24px !important;
}
[data-breakpoint="sm"] .lf-photo-strip-section smp-row:has(> smp-column.lf-photo-strip-track),
[data-breakpoint="xs"] .lf-photo-strip-section smp-row:has(> smp-column.lf-photo-strip-track) {
    display: block !important;
}
[data-breakpoint="sm"] #content-holder .lf-photo-strip-track,
[data-breakpoint="xs"] #content-holder .lf-photo-strip-track {
    height: 360px !important;
}
[data-breakpoint="sm"] #content-holder .lf-photo-strip-track > smp-content-wrapper,
[data-breakpoint="xs"] #content-holder .lf-photo-strip-track > smp-content-wrapper {
    gap: 24px !important;
    padding: 0 32px !important;
    height: 360px !important;
}
[data-breakpoint="sm"] .lf-photo-strip-track > smp-content-wrapper > smp-content[data-module="image"],
[data-breakpoint="xs"] .lf-photo-strip-track > smp-content-wrapper > smp-content[data-module="image"] {
    flex: 0 0 220px !important;
    width: 220px !important;
    max-width: 220px !important;
    height: auto !important;
}
[data-breakpoint="sm"] .lf-photo-strip-track smp-content[data-module="image"] .smp-image,
[data-breakpoint="xs"] .lf-photo-strip-track smp-content[data-module="image"] .smp-image,
[data-breakpoint="sm"] .lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content,
[data-breakpoint="xs"] .lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content {
    width: 220px !important;
    height: auto !important;
}
[data-breakpoint="sm"] .lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content img,
[data-breakpoint="xs"] .lf-photo-strip-track smp-content[data-module="image"] .smp-image .is-content img {
    width: 220px !important;
    height: auto !important;
    max-width: 220px !important;
    max-height: 360px !important;
}
[data-breakpoint="sm"] .lf-photo-strip-dots,
[data-breakpoint="xs"] .lf-photo-strip-dots { margin-top: 48px; }

/* =============================================================
   Captioned Photo Carousel — atomic Saved Block (master_lfcaptionedstrip01)

   Like Photo Strip (#47) but each slide is a Semplice subrow containing
   [image module, text module] so the author can edit the photo AND the
   caption under it via Semplice's native popups. Slide height is fixed
   to 640; width follows the image's natural aspect (matches Figma's
   variable-width slide design — 480/512/853 wide in the reference).

   The wrapper is a CSS-keyframes marquee identical to Photo Strip; dot
   pagination is appended by the same JS (lakefront_photo_strip_inline_js,
   extended to also match .lf-captioned-strip-track).

   Section layer: overflow:hidden + zero smp-container padding so the
   track can escape to 100vw. Composite usage (Three Ways) gives the
   wrapping section the same overflow:hidden so the bg keeps painting
   behind the full-bleed strip.
   ============================================================= */

.lf-captioned-strip-section { overflow: hidden; }
.lf-captioned-strip-section smp-container { padding-left: 0 !important; padding-right: 0 !important; }
.lf-captioned-strip-section smp-row { width: 100% !important; max-width: none !important; }

/* Track = the column. 100vw escape so the strip spans viewport edges
   regardless of the parent column's width — same pattern as Photo Strip. */
#content-holder .lf-captioned-strip-track {
    width: 100vw !important;
    max-width: 100vw !important;
    flex: 1 1 100vw !important;
    position: relative;
    left: 50%;
    margin-left: -50vw !important;
    margin-right: -50vw !important;
    overflow: hidden;
    height: 720px;          /* 640 image + 16 gap + caption headroom */
}

/* Marquee container. animation-duration set inline by JS once wrapper width
   is known. align-items: flex-start anchors all slides to the same top edge
   so the image-row stays level regardless of caption line count. */
#content-holder .lf-captioned-strip-track > smp-content-wrapper {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: nowrap !important;
    align-items: flex-start;
    gap: 126px;             /* matches Figma gap-[126px] */
    padding: 0 120px;
    width: max-content !important;
    height: 720px !important;
    will-change: transform;
    backface-visibility: hidden;
    animation-name: lf-photo-strip-scroll;
    animation-timing-function: linear;
    animation-iteration-count: infinite;
    /* animation-duration set inline by JS */
}

/* Slide = subrow with [image, text]. Vertical stack, 16 gap.
   Slides are FIXED 512×640 (4:5 portrait) per Figma node 128:1586 — every
   slide same size regardless of source aspect ratio. Images crop to fit
   via object-fit:cover. Earlier "variable width by natural aspect" caused
   the wide Pod source (853×640) to render 853 wide on desktop and overflow
   narrow viewports on mobile, breaking the strip's visual rhythm. */
#content-holder .lf-captioned-strip-track > smp-content-wrapper > smp-subrow {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start;
    gap: 16px;
    flex: 0 0 512px !important;
    width: 512px !important;
    height: auto !important;
    margin: 0 !important;
}

/* Recipe D image-fill chain — fixed 512×640 box, object-fit: cover crops
   any non-4:5 source to the box without distorting aspect. */
.lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] {
    width: 512px !important;
    height: 640px !important;
    flex: 0 0 auto !important;
    margin: 0 !important;
    pointer-events: auto;
    user-select: none;
    -webkit-user-drag: none;
}
.lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image,
.lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content {
    width: 512px !important;
    height: 640px !important;
}
.lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content img {
    width: 512px !important;
    height: 640px !important;
    max-width: 512px !important;
    max-height: 640px !important;
    object-fit: cover;
    display: block;
    border-radius: 0 !important;
}

/* Caption under the image — Inter 16 / 1.3 / text-secondary.
   #content-holder prefix beats Semplice's frontend.css `#content-holder p`
   which would otherwise impose margin-bottom: 1.3em (gotcha §11 +
   core principle 7). */
#content-holder .lf-captioned-strip-track smp-subrow > smp-content[data-module="text"] {
    width: auto !important;
    max-width: 100%;
    margin: 0 !important;
}
#content-holder .lf-captioned-strip__caption,
#content-holder .lf-captioned-strip-track smp-subrow > smp-content[data-module="text"] p {
    font-family: 'Inter', sans-serif !important;
    font-size: 16px !important;
    font-weight: 400 !important;
    line-height: 1.3 !important;
    color: var(--text-secondary) !important;
    margin: 0 !important;
}

/* Editor canvas: drop the marquee + full-bleed dance, lay slides out
   as a 3-col grid so authors can click each image / caption to edit. */
body.wp-admin .lf-captioned-strip-section { overflow: visible !important; }
body.wp-admin #content-holder .lf-captioned-strip-track {
    position: static !important;
    left: auto !important;
    right: auto !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
    overflow: visible !important;
    height: auto !important;
    cursor: default !important;
}
body.wp-admin #content-holder .lf-captioned-strip-track > smp-content-wrapper {
    display: grid !important;
    grid-template-columns: repeat(3, minmax(0, 1fr)) !important;
    gap: 24px !important;
    padding: 0 !important;
    width: 100% !important;
    height: auto !important;
    transform: none !important;
    animation: none !important;
}
body.wp-admin .lf-captioned-strip-track > smp-content-wrapper > smp-subrow {
    width: 100% !important;
    height: auto !important;
    align-items: stretch;
}
body.wp-admin .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] {
    width: 100% !important;
    height: 280px !important;
}
body.wp-admin .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image,
body.wp-admin .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    height: 280px !important;
}
body.wp-admin .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: 280px !important;
    object-fit: cover;
}

/* The .lf-photo-strip-dots element is appended by JS to the
   .lf-captioned-strip-section as well — reuses the same styles already
   defined for Photo Strip above. */

/* ---- Responsive ---- */

@media (max-width: 1199px) {
    #content-holder .lf-captioned-strip-track,
    #content-holder .lf-captioned-strip-track > smp-content-wrapper {
        height: 600px !important;
    }
    /* Slide box scales proportionally to keep 4:5 aspect: 416 × 520 */
    #content-holder .lf-captioned-strip-track > smp-content-wrapper > smp-subrow {
        flex: 0 0 416px !important;
        width: 416px !important;
    }
    .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"],
    .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image,
    .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content,
    .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content img {
        width: 416px !important;
        max-width: 416px !important;
        height: 520px !important;
        max-height: 520px !important;
    }
    #content-holder .lf-captioned-strip-track > smp-content-wrapper {
        gap: 80px;
        padding: 0 40px;
    }
}

@media (max-width: 860px) {
    /* Row collapse — same :has() trick as Photo Strip so only this
       carousel's row collapses, not other rows in a composite section. */
    .lf-captioned-strip-section smp-row:has(> smp-column.lf-captioned-strip-track) {
        display: block !important;
    }
    #content-holder .lf-captioned-strip-track,
    #content-holder .lf-captioned-strip-track > smp-content-wrapper {
        height: 480px !important;
    }
    /* Slide box at mobile: 320 × 400 (still 4:5) */
    #content-holder .lf-captioned-strip-track > smp-content-wrapper > smp-subrow {
        flex: 0 0 320px !important;
        width: 320px !important;
    }
    .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"],
    .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image,
    .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content,
    .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content img {
        width: 320px !important;
        max-width: 320px !important;
        height: 400px !important;
        max-height: 400px !important;
    }
    #content-holder .lf-captioned-strip-track > smp-content-wrapper {
        gap: 56px;
        padding: 0 24px;
    }
}

/* Editor preview-mode mirrors */
[data-breakpoint="lg"] #content-holder .lf-captioned-strip-track,
[data-breakpoint="lg"] #content-holder .lf-captioned-strip-track > smp-content-wrapper {
    height: 600px !important;
}
[data-breakpoint="lg"] #content-holder .lf-captioned-strip-track > smp-content-wrapper > smp-subrow {
    flex: 0 0 416px !important;
    width: 416px !important;
}
[data-breakpoint="lg"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"],
[data-breakpoint="lg"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image,
[data-breakpoint="lg"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content,
[data-breakpoint="lg"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content img {
    width: 416px !important;
    max-width: 416px !important;
    height: 520px !important;
    max-height: 520px !important;
}
[data-breakpoint="lg"] #content-holder .lf-captioned-strip-track > smp-content-wrapper {
    gap: 80px;
    padding: 0 40px;
}
[data-breakpoint="md"] #content-holder .lf-captioned-strip-track,
[data-breakpoint="md"] #content-holder .lf-captioned-strip-track > smp-content-wrapper {
    height: 560px !important;
}
[data-breakpoint="md"] #content-holder .lf-captioned-strip-track > smp-content-wrapper > smp-subrow {
    flex: 0 0 384px !important;
    width: 384px !important;
}
[data-breakpoint="md"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"],
[data-breakpoint="md"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image,
[data-breakpoint="md"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content,
[data-breakpoint="md"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content img {
    width: 384px !important;
    max-width: 384px !important;
    height: 480px !important;
    max-height: 480px !important;
}
[data-breakpoint="md"] #content-holder .lf-captioned-strip-track > smp-content-wrapper {
    gap: 64px;
    padding: 0 32px;
}
[data-breakpoint="sm"] .lf-captioned-strip-section smp-row:has(> smp-column.lf-captioned-strip-track),
[data-breakpoint="xs"] .lf-captioned-strip-section smp-row:has(> smp-column.lf-captioned-strip-track) {
    display: block !important;
}
[data-breakpoint="sm"] #content-holder .lf-captioned-strip-track,
[data-breakpoint="sm"] #content-holder .lf-captioned-strip-track > smp-content-wrapper,
[data-breakpoint="xs"] #content-holder .lf-captioned-strip-track,
[data-breakpoint="xs"] #content-holder .lf-captioned-strip-track > smp-content-wrapper {
    height: 480px !important;
}
[data-breakpoint="sm"] #content-holder .lf-captioned-strip-track > smp-content-wrapper > smp-subrow,
[data-breakpoint="xs"] #content-holder .lf-captioned-strip-track > smp-content-wrapper > smp-subrow {
    flex: 0 0 320px !important;
    width: 320px !important;
}
[data-breakpoint="sm"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"],
[data-breakpoint="sm"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image,
[data-breakpoint="sm"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content,
[data-breakpoint="sm"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content img,
[data-breakpoint="xs"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"],
[data-breakpoint="xs"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image,
[data-breakpoint="xs"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content,
[data-breakpoint="xs"] .lf-captioned-strip-track smp-subrow > smp-content[data-module="image"] .smp-image .is-content img {
    width: 320px !important;
    max-width: 320px !important;
    height: 400px !important;
    max-height: 400px !important;
}
[data-breakpoint="sm"] #content-holder .lf-captioned-strip-track > smp-content-wrapper,
[data-breakpoint="xs"] #content-holder .lf-captioned-strip-track > smp-content-wrapper {
    gap: 56px;
    padding: 0 24px;
}

/* =============================================================
   Three Ways to Live + Carousel — composite Saved Block
   (master_lfthreewayscomp01)

   Single section with three rows:
     row 1 — header (column.lf-tier-cards-header)        heading + lede
     row 2 — cards  (column.lf-tier-cards-card × 3)       3-up pricing cards
     row 3 — carousel (column.lf-captioned-strip-track)   captioned photo strip

   Section composes `.lf-tier-cards` (so header + card element CSS
   continues to apply) with `.lf-three-ways-composite` (which
   overrides smp-container to a grid for asymmetric inter-row gaps:
   48px between header and cards, 120px between cards and carousel).

   grid-template-rows with explicit gap tracks is the right primitive
   here because the cards row uses 3 side-by-side columns — restructuring
   into nested subrows would lose Tier Cards' existing card CSS, while
   keeping the rows flat costs an asymmetric gap problem that flex+gap
   can't solve in one container.
   ============================================================= */

.lf-three-ways-composite {
    overflow: hidden;          /* carousel row escapes to 100vw; clip inside section */
}
.lf-three-ways-composite smp-container {
    /* Override .lf-tier-cards' flex column + uniform 48px gap with a
       grid that gives each inter-row track its own value. */
    display: grid !important;
    grid-template-columns: 1fr;
    grid-template-rows: auto 48px auto 120px auto;
    row-gap: 0 !important;
}
.lf-three-ways-composite > smp-container > smp-row:nth-of-type(1) { grid-row: 1; }
.lf-three-ways-composite > smp-container > smp-row:nth-of-type(2) { grid-row: 3; }
.lf-three-ways-composite > smp-container > smp-row:nth-of-type(3) { grid-row: 5; }

/* Carousel row needs unconstrained width so the track's 100vw escape
   works (the track sits inside the row's column; row clipping the
   column width would defeat the escape). */
.lf-three-ways-composite > smp-container > smp-row:nth-of-type(3) {
    width: 100% !important;
    max-width: none !important;
}

/* Responsive — same scale as the section's own padding ramp. */
@media (max-width: 1199px) {
    .lf-three-ways-composite smp-container {
        grid-template-rows: auto 40px auto 96px auto;
    }
}
@media (max-width: 860px) {
    .lf-three-ways-composite smp-container {
        grid-template-rows: auto 32px auto 72px auto;
    }
}

/* Editor preview-mode mirrors */
[data-breakpoint="lg"] .lf-three-ways-composite smp-container,
[data-breakpoint="md"] .lf-three-ways-composite smp-container {
    grid-template-rows: auto 40px auto 96px auto;
}
[data-breakpoint="sm"] .lf-three-ways-composite smp-container,
[data-breakpoint="xs"] .lf-three-ways-composite smp-container {
    grid-template-rows: auto 32px auto 72px auto;
}

/* =============================================================
   Building and the land — composite Saved Block (master_lfbuildingland01)
   Combines the Image + Text Split atomic (row 1) with the Photo Strip
   atomic (row 2) inside a single section. The section's CSS class
   should compose `lf-img-text-split` (for row 1 column-gap behaviour) +
   `lf-building-and-land` (for the overflow clip + inter-row gap) +
   `bg-grad-cream-peach-soft` (the gradient).

   Inter-row gap is handled by smp-container's column-flex + gap. Section
   top/bottom padding lives in the section's ram per breakpoint so authors
   can tune it via the Semplice section popup.
   ============================================================= */

.lf-building-and-land {
    overflow: hidden;          /* photo strip is full-bleed; clip overflow inside section */
}
.lf-building-and-land smp-container {
    flex-direction: column !important;
    gap: 200px;                 /* between rows — matches Figma gap-[200px] */
}

@media (max-width: 860px) {
    .lf-building-and-land smp-container { gap: 96px; }
}
[data-breakpoint="sm"] .lf-building-and-land smp-container,
[data-breakpoint="xs"] .lf-building-and-land smp-container {
    gap: 96px;
}

/* The map SVG is intrinsically square (560×560 viewBox). With the default
   img-text-split img column using a fixed min-height + object-fit: contain,
   the SVG letterboxes against the column's ecru background at any aspect
   ratio that isn't 1:1 — visible as horizontal/vertical "background tile"
   gaps around the SVG, especially when the column reflows narrower or
   taller than square. Lock the column wrapper to the SVG's aspect-ratio
   so the container resizes to the SVG and no letterbox exists. Scoped to
   .lf-building-and-land so other img-text-split usages (with rectangular
   photos) keep their existing fixed-height behaviour. */
.lf-building-and-land .lf-img-text-split__img > smp-content-wrapper {
    aspect-ratio: 1 / 1;
    min-height: 0 !important;
}
/* Map SVG has internal transparency in its viewBox (the lower portion of
   the 588×560 illustration is empty). The atomic .lf-img-text-split__img
   carries `background-color: var(--color-ecru)` as a missing-image
   fallback, but here it leaks through the SVG's transparent regions and
   reads as a grey rectangle against the section's cream/peach gradient.
   Drop the fallback for this composite so the gradient shows through. */
.lf-building-and-land .lf-img-text-split__img {
    background-color: transparent !important;
}

/* =============================================================
   Shared horizontal page-gutter — Tier Cards pattern.
   Padding lives on smp-container (not the section) so the visual
   inset is identical to Tier Cards at every viewport. Section
   bg / vertical padding still live in ram (per-instance editable).
   --gutter-page rebound locally on smp-container because Semplice
   defines --smp-grid-outer-desktop only there, not on :root.
   ============================================================= */
.lf-img-text-split smp-container,
.lf-text-cta-split smp-container,
.lf-intro-split smp-container,
.lf-image-banner smp-container,
.lf-process-section smp-container,
.lf-about-hero smp-container,
.lf-events-hero smp-container,
.lf-events-section smp-container,
.lf-text-image smp-container,
.lf-about-story smp-container,
.lf-partners-section smp-container,
.lf-larger-ecosystem smp-container,
.lf-pullquote smp-container,
.lf-people-category smp-container {
    --gutter-page: var(--smp-grid-outer-desktop, 120px);
    padding-left: var(--gutter-page) !important;
    padding-right: var(--gutter-page) !important;
}
@media (max-width: 1023px) {
    .lf-img-text-split smp-container,
    .lf-text-cta-split smp-container,
    .lf-intro-split smp-container,
    .lf-image-banner smp-container,
    .lf-process-section smp-container,
    .lf-about-hero smp-container,
    .lf-events-hero smp-container,
    .lf-events-section smp-container,
    .lf-text-image smp-container,
    .lf-about-story smp-container,
    .lf-partners-section smp-container,
    .lf-larger-ecosystem smp-container,
    .lf-pullquote smp-container,
    .lf-people-category smp-container { --gutter-page: 40px; }
}
@media (max-width: 640px) {
    .lf-img-text-split smp-container,
    .lf-text-cta-split smp-container,
    .lf-intro-split smp-container,
    .lf-image-banner smp-container,
    .lf-process-section smp-container,
    .lf-about-hero smp-container,
    .lf-events-hero smp-container,
    .lf-events-section smp-container,
    .lf-text-image smp-container,
    .lf-about-story smp-container,
    .lf-partners-section smp-container,
    .lf-larger-ecosystem smp-container,
    .lf-pullquote smp-container,
    .lf-people-category smp-container { --gutter-page: 16px; }
}
@media (max-width: 380px) {
    .lf-img-text-split smp-container,
    .lf-text-cta-split smp-container,
    .lf-intro-split smp-container,
    .lf-image-banner smp-container,
    .lf-process-section smp-container,
    .lf-about-hero smp-container,
    .lf-events-hero smp-container,
    .lf-events-section smp-container,
    .lf-text-image smp-container,
    .lf-about-story smp-container,
    .lf-partners-section smp-container,
    .lf-larger-ecosystem smp-container,
    .lf-pullquote smp-container,
    .lf-people-category smp-container { --gutter-page: 16px; }
}
/* Editor preview mirrors — Semplice flips data-breakpoint without
   resizing the iframe, so @media rules don't fire in the editor. */
[data-breakpoint="md"] .lf-img-text-split smp-container,
[data-breakpoint="md"] .lf-text-cta-split smp-container,
[data-breakpoint="md"] .lf-intro-split smp-container,
[data-breakpoint="md"] .lf-image-banner smp-container,
[data-breakpoint="md"] .lf-process-section smp-container,
[data-breakpoint="md"] .lf-about-hero smp-container,
[data-breakpoint="md"] .lf-events-hero smp-container,
[data-breakpoint="md"] .lf-events-section smp-container,
[data-breakpoint="md"] .lf-text-image smp-container,
[data-breakpoint="md"] .lf-about-story smp-container,
[data-breakpoint="md"] .lf-partners-section smp-container,
[data-breakpoint="md"] .lf-larger-ecosystem smp-container,
[data-breakpoint="md"] .lf-pullquote smp-container,
[data-breakpoint="md"] .lf-people-category smp-container,
[data-breakpoint="sm"] .lf-img-text-split smp-container,
[data-breakpoint="sm"] .lf-text-cta-split smp-container,
[data-breakpoint="sm"] .lf-intro-split smp-container,
[data-breakpoint="sm"] .lf-image-banner smp-container,
[data-breakpoint="sm"] .lf-process-section smp-container,
[data-breakpoint="sm"] .lf-about-hero smp-container,
[data-breakpoint="sm"] .lf-events-hero smp-container,
[data-breakpoint="sm"] .lf-events-section smp-container,
[data-breakpoint="sm"] .lf-text-image smp-container,
[data-breakpoint="sm"] .lf-about-story smp-container,
[data-breakpoint="sm"] .lf-partners-section smp-container,
[data-breakpoint="sm"] .lf-larger-ecosystem smp-container,
[data-breakpoint="sm"] .lf-pullquote smp-container,
[data-breakpoint="sm"] .lf-people-category smp-container,
[data-breakpoint="xs"] .lf-img-text-split smp-container,
[data-breakpoint="xs"] .lf-text-cta-split smp-container,
[data-breakpoint="xs"] .lf-intro-split smp-container,
[data-breakpoint="xs"] .lf-image-banner smp-container,
[data-breakpoint="xs"] .lf-process-section smp-container,
[data-breakpoint="xs"] .lf-about-hero smp-container,
[data-breakpoint="xs"] .lf-events-hero smp-container,
[data-breakpoint="xs"] .lf-events-section smp-container,
[data-breakpoint="xs"] .lf-text-image smp-container,
[data-breakpoint="xs"] .lf-about-story smp-container,
[data-breakpoint="xs"] .lf-partners-section smp-container,
[data-breakpoint="xs"] .lf-larger-ecosystem smp-container,
[data-breakpoint="xs"] .lf-pullquote smp-container,
[data-breakpoint="xs"] .lf-people-category smp-container { --gutter-page: 40px; }
[data-breakpoint="xs"] .lf-img-text-split smp-container,
[data-breakpoint="xs"] .lf-text-cta-split smp-container,
[data-breakpoint="xs"] .lf-intro-split smp-container,
[data-breakpoint="xs"] .lf-image-banner smp-container,
[data-breakpoint="xs"] .lf-process-section smp-container,
[data-breakpoint="xs"] .lf-about-hero smp-container,
[data-breakpoint="xs"] .lf-events-hero smp-container,
[data-breakpoint="xs"] .lf-events-section smp-container,
[data-breakpoint="xs"] .lf-text-image smp-container,
[data-breakpoint="xs"] .lf-about-story smp-container,
[data-breakpoint="xs"] .lf-partners-section smp-container,
[data-breakpoint="xs"] .lf-larger-ecosystem smp-container,
[data-breakpoint="xs"] .lf-pullquote smp-container,
[data-breakpoint="xs"] .lf-people-category smp-container { --gutter-page: 16px; }

/* =============================================================
   Text + CTA Split — atomic Saved Block (master_lftextctasplit01)
   Two-column 5/7 split: left column is a heading, right column is a
   body stack (serif paragraph + Inter paragraph) followed by a CTA
   button. Real `gap` on the row produces the 24px column gap — no
   `data-gutter="yes"` padding-as-gap hack (which would leave an
   unwanted 12px inset on the row edges). Stacks to a single column
   at sm/xs.

   Horizontal padding lives on smp-container via the shared rule
   above (Tier Cards pattern). Vertical padding + bg still in ram.
   Section's ram has `data-gutter: "no"`. The row's gap is the only
   source of inter-column spacing.

   First used by Living at Lakefront's "Life between the apartments"
   composition. Reused anywhere a designed 5-7 heading+body+CTA split
   is wanted.
   ============================================================= */

/* Real CSS-grid layout for the 5+7 split with a single 24px gap.
   `:has()` keeps this scoped to the text-cta-split row only — when the
   composite section also carries `.lf-image-banner`, the single-col
   image-banner row (no `__heading` child) is unaffected. */
.lf-text-cta-split smp-row:has(> smp-column.lf-text-cta-split__heading) {
    display: grid !important;
    grid-template-columns: 5fr 7fr;
    gap: 24px;
}
/* Semplice emits per-instance `width: 41.667%` on each column from the
   `width` ram field — that constrains the grid item below its track size.
   Force columns to fill their grid track. */
.lf-text-cta-split smp-row:has(> smp-column.lf-text-cta-split__heading) > smp-column {
    width: 100% !important;
    max-width: none !important;
}

/* Left heading column — top-aligned single text module. */
.lf-text-cta-split__heading > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    width: 100%;
}

/* Right body column — two-subrow stack:
   subrow 1 = text paragraphs (gap 16 internally),
   then a CTA button below at 40px.
   Mirrors Recipe B (50/50 hero) for the button-after-text pattern. */
.lf-text-cta-split__body > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    gap: 40px !important;
    align-items: flex-start !important;
    width: 100%;
}
.lf-text-cta-split__body smp-subrow:nth-of-type(1) {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
    width: 100%;
}
/* Button sizes to its content (Semplice forces smp-content to 100% width
   for column-stacking; override so the pill stays compact). */
.lf-text-cta-split__body > smp-content-wrapper > smp-content[data-module="button"] {
    width: auto !important;
    flex: 0 0 auto;
}

/* =============================================================
   Image Banner — atomic Saved Block (master_lfimagebanner01)
   Single 12-wide column with one popup-editable Semplice image module.
   Image fills the column at 480px height with object-fit: cover.

   First used as the photo row in "Life between the apartments". Reused
   anywhere a full-bleed-within-grid 480px image banner is wanted.
   ============================================================= */

.lf-image-banner__img {
    align-self: stretch;
    overflow: hidden;
}
.lf-image-banner__img > smp-content-wrapper {
    display: flex !important;
    width: 100%;
    height: 480px;
}
/* Recipe D image-fill chain — img stretches to fill the 480px column. */
.lf-image-banner__img smp-content[data-module="image"],
.lf-image-banner__img smp-content[data-module="image"] .smp-image,
.lf-image-banner__img smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
    flex: 1 1 auto;
}
.lf-image-banner__img smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    object-fit: cover !important;
    object-position: center;
    display: block;
    border-radius: 0 !important;
}

/* =============================================================
   Text + CTA Split + Image Banner — responsive rules
   Stack to single column under 860px; reduce image height.
   Mirror @media with [data-breakpoint] for the editor preview.
   ============================================================= */

@media (max-width: 860px) {
    /* Collapse the 5+7 grid to a single column; gap remains the row's. */
    .lf-text-cta-split smp-row:has(> smp-column.lf-text-cta-split__heading) {
        grid-template-columns: 1fr;
    }
    .lf-image-banner__img > smp-content-wrapper { height: 320px; }
}
[data-breakpoint="sm"] .lf-text-cta-split smp-row:has(> smp-column.lf-text-cta-split__heading),
[data-breakpoint="xs"] .lf-text-cta-split smp-row:has(> smp-column.lf-text-cta-split__heading) {
    grid-template-columns: 1fr;
}
[data-breakpoint="sm"] .lf-image-banner__img > smp-content-wrapper,
[data-breakpoint="xs"] .lf-image-banner__img > smp-content-wrapper {
    height: 320px;
}

/* =============================================================
   Life between the apartments — composite Saved Block (master_lflifebetween01)
   Combines the Text + CTA Split atomic (row 1) with the Image Banner
   atomic (row 2) inside a single section. The composite section
   stacks both atomic class names plus its own `lf-life-between`
   for the inter-row gap + overflow clip.

   Section gradient bg + top/bottom padding live in the section's ram
   per breakpoint so authors can tune them via the Semplice section
   popup. Gradient is `linear-gradient(180deg,#fefdf4 0%,#fefdf4 30%,#f1fb9f 100%)`
   stored in `styles.xl.background-color` — Semplice's Background::css
   detects the gradient substring and emits as background-image.
   ============================================================= */

.lf-life-between {
    overflow: hidden;
}
.lf-life-between smp-container {
    flex-direction: column !important;
    gap: 120px;                 /* between rows — matches Figma gap-[120px] */
}

@media (max-width: 860px) {
    .lf-life-between smp-container { gap: 72px; }
}
[data-breakpoint="sm"] .lf-life-between smp-container,
[data-breakpoint="xs"] .lf-life-between smp-container {
    gap: 72px;
}

/* =============================================================
   Intro Split — atomic Saved Block (master_lfintrosplit01)
   Two-column 5/7 split: left column is a short section heading, right
   column is a body stack (serif lead paragraph + Inter paragraphs).
   Same shape as `.lf-text-cta-split` but without a CTA button — use
   when the section needs intro copy, not an action. Real `gap` on the
   row produces the 24px column gap (no `data-gutter="yes"` padding
   hack). Stacks to a single column at sm/xs.

   Horizontal padding lives on smp-container via the shared
   --gutter-page rule. Vertical padding + bg still in ram.
   Section's ram has `data-gutter: "no"`. The row's gap is the only
   source of inter-column spacing.

   First used by the About page's "Emerge Institute" composite.
   ============================================================= */

/* Real CSS-grid 5+7 split with a single 24px gap. `:has()` keeps this
   scoped to the intro-split row only — when the composite section
   also carries `.lf-image-banner`, the single-col image-banner row
   (no `__heading` child) is unaffected. */
.lf-intro-split smp-row:has(> smp-column.lf-intro-split__heading) {
    display: grid !important;
    grid-template-columns: 5fr 7fr;
    gap: 24px;
}
/* Semplice emits per-instance `width: 41.667%` on each column from the
   `width` ram field — that constrains the grid item below its track
   size. Force columns to fill their grid track. */
.lf-intro-split smp-row:has(> smp-column.lf-intro-split__heading) > smp-column {
    width: 100% !important;
    max-width: none !important;
}

/* Left heading column — top-aligned single text module. */
.lf-intro-split__heading > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    width: 100%;
}

/* Right body column — single subrow stack: serif lead + Inter body.
   No CTA button in this variant (that's what differentiates it from
   `.lf-text-cta-split`). Subrow gap of 16px matches Figma's gap-[16px]
   between text fields inside the segment. */
.lf-intro-split__body > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    width: 100%;
}
.lf-intro-split__body smp-subrow:nth-of-type(1) {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
    width: 100%;
}

/* Stack to single column under 860px — mirror @media with
   [data-breakpoint] for the editor preview. */
@media (max-width: 860px) {
    .lf-intro-split smp-row:has(> smp-column.lf-intro-split__heading) {
        grid-template-columns: 1fr;
    }
}
[data-breakpoint="sm"] .lf-intro-split smp-row:has(> smp-column.lf-intro-split__heading),
[data-breakpoint="xs"] .lf-intro-split smp-row:has(> smp-column.lf-intro-split__heading) {
    grid-template-columns: 1fr;
}

/* =============================================================
   Emerge Institute — composite Saved Block (master_lfemergeinst01)
   Combines the Intro Split atomic (row 1) with the Image Banner
   atomic (row 2) inside a single section. The composite section
   stacks both atomic class names plus its own `lf-emerge-institute`
   for the inter-row gap + overflow clip.

   Section solid bg `#f1fb9f` (Sun accent) + top/bottom padding
   live in the section's ram per breakpoint so authors can tune
   them via the Semplice section popup.

   First used on the About page.
   ============================================================= */

.lf-emerge-institute {
    overflow: hidden;
}
.lf-emerge-institute smp-container {
    flex-direction: column !important;
    gap: 120px;                 /* between rows — matches Figma gap-[120px] */
}

@media (max-width: 860px) {
    .lf-emerge-institute smp-container { gap: 72px; }
}
[data-breakpoint="sm"] .lf-emerge-institute smp-container,
[data-breakpoint="xs"] .lf-emerge-institute smp-container {
    gap: 72px;
}

/* =============================================================
   From curious to moved in — composite Saved Block
   (master_lfprocess01)
   Three rows in a single section:
     row 1 — eyebrow (full-width text)
     row 2 — 4 numbered process steps in a 7-col list + 5-col image
     row 3 — fineprint + CTA pill (max-width 554)
   Each step row is a Semplice subrow inside the steps column,
   structured as [number-text-module, content-text-module]. The
   border-top + 32 top/bottom padding per subrow gives the divider
   line pattern from the Figma.

   Horizontal page-gutter handled by the shared --gutter-page rule.
   Vertical padding (top 120, bottom 200) lives in section ram.
   Section's ram has `data-gutter: "no"` so the explicit row gap is
   the only spacing source. Section bg yellow lives in section ram
   (popup-editable).
   ============================================================= */

.lf-process-section smp-container {
    flex-direction: column !important;
    gap: 32px;                              /* eyebrow → steps → footer */
}

/* Row 2 (steps + image): cols 7+5=12 fit the full row width with NO
   explicit gap. The visual "right inset" the Figma shows comes from
   padding-right on the image column (see below), not a column gap. */

/* Steps column — 4 subrows stacked, each with internal flex row. */
.lf-process-steps > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    width: 100%;
}
/* Each step row: number on the left (78px), content fills the rest.
   Border-top + 32 top/bottom padding gives the divider pattern. */
.lf-process-steps smp-subrow {
    display: flex !important;
    flex-direction: row !important;
    align-items: flex-start !important;
    gap: 24px;
    padding-top: 32px;
    padding-bottom: 32px;
    border-top: 1px solid var(--border-weak);
    width: 100%;
}
.lf-process-steps smp-subrow > smp-content:first-child {
    flex: 0 0 78px;
    width: 78px !important;
}
.lf-process-steps smp-subrow > smp-content:last-child {
    flex: 1 1 auto;
    min-width: 0;
}
/* Step content text wraps at Figma's ~384px so the right half of the
   row stays visually empty for the floating image. */
.lf-process-steps smp-subrow > smp-content:last-child .lf-h2-32 {
    max-width: 384px;
}

/* Image column — centered vertically within the steps row. */
.lf-process-image {
    align-self: center !important;
}
.lf-process-image > smp-content-wrapper {
    display: flex !important;
    width: 100%;
    aspect-ratio: 447 / 308;                /* matches Figma image */
}
/* Recipe D image-fill chain. */
.lf-process-image smp-content[data-module="image"],
.lf-process-image smp-content[data-module="image"] .smp-image,
.lf-process-image smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
    flex: 1 1 auto;
}
.lf-process-image smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    object-fit: cover !important;
    object-position: center;
    display: block;
    border-radius: 0 !important;
}

/* Footer column — fineprint + CTA pill, max-width 554, gap 32 between. */
.lf-process-footer > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    gap: 32px !important;
    align-items: flex-start !important;
    max-width: 554px;
    width: 100%;
}
.lf-process-footer > smp-content-wrapper > smp-content[data-module="button"] {
    width: auto !important;
    flex: 0 0 auto;
}

/* Responsive: stack steps + image at narrow viewports, drop the
   max-width cap on step content so it uses full width. At sm/xs the
   number→text gap also tightens (24 → 16) so the narrow column
   doesn't waste space on the gutter.

   The max-width / flex-basis overrides on the columns are needed to
   beat Semplice's `[data-xl-width="N"]` per-instance CSS (xl=7/5
   here), which caps both — same pattern as lf-img-text-split. */
@media (max-width: 860px) {
    .lf-process-section smp-row:has(> smp-column.lf-process-steps) {
        flex-direction: column !important;
        gap: 48px;
    }
    .lf-process-steps,
    .lf-process-image {
        width: 100% !important;
        max-width: 100% !important;
        flex-basis: 100% !important;
        flex: 0 0 auto !important;
    }
    .lf-process-steps smp-subrow > smp-content:last-child .lf-h2-32 {
        max-width: none;
    }
}
@media (max-width: 640px) {
    .lf-process-steps smp-subrow { gap: 16px; }
    /* Number column shrinks to fit its content (just the "01" digits)
       instead of holding a fixed 78px gutter — gives the text more room
       on narrow screens. */
    .lf-process-steps smp-subrow > smp-content:first-child {
        flex: 0 0 auto !important;
        width: auto !important;
    }
}
[data-breakpoint="sm"] .lf-process-section smp-row:has(> smp-column.lf-process-steps),
[data-breakpoint="xs"] .lf-process-section smp-row:has(> smp-column.lf-process-steps) {
    flex-direction: column !important;
    gap: 48px;
}
[data-breakpoint="sm"] .lf-process-steps,
[data-breakpoint="sm"] .lf-process-image,
[data-breakpoint="xs"] .lf-process-steps,
[data-breakpoint="xs"] .lf-process-image {
    width: 100% !important;
    max-width: 100% !important;
    flex-basis: 100% !important;
    flex: 0 0 auto !important;
}
[data-breakpoint="sm"] .lf-process-steps smp-subrow > smp-content:last-child .lf-h2-32,
[data-breakpoint="xs"] .lf-process-steps smp-subrow > smp-content:last-child .lf-h2-32 {
    max-width: none;
}
[data-breakpoint="sm"] .lf-process-steps smp-subrow,
[data-breakpoint="xs"] .lf-process-steps smp-subrow {
    gap: 16px;
}
[data-breakpoint="sm"] .lf-process-steps smp-subrow > smp-content:first-child,
[data-breakpoint="xs"] .lf-process-steps smp-subrow > smp-content:first-child {
    flex: 0 0 auto !important;
    width: auto !important;
}

/* =============================================================
   About Hero — composite Saved Block (master_lfabouthero01)
   Two rows in a single section:
     row 1 — centered heading + body subgroup
              (heading max-width 792, body max-width 588)
     row 2 — full-width image, 720px tall

   Section bg is a vertical gradient (cream at top → sky blue at bottom,
   transparent until 30%); lives in section ram so the popup picker
   pre-fills correctly. Vertical padding (top 160, bottom 120) also in
   ram. Horizontal page-gutter handled by the shared --gutter-page rule.
   ============================================================= */

.lf-about-hero smp-container {
    flex-direction: column !important;
    gap: 64px;                              /* between header and image */
}

/* Header column — centered heading + body stack. Heading and body have
   different max-widths per the Figma spec, both centered.
   Shared with `.lf-events-hero__header` — same centered-hero pattern. */
.lf-about-hero__header > smp-content-wrapper,
.lf-events-hero__header > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    gap: 24px;
    width: 100%;
}
/* Heading: max 792 wide, centered, text-align center */
.lf-about-hero__header smp-content[data-module="text"]:nth-of-type(1),
.lf-events-hero__header smp-content[data-module="text"]:nth-of-type(1) {
    width: 100%;
    max-width: 792px;
}
.lf-about-hero__header smp-content[data-module="text"]:nth-of-type(1) .lf-h1-48,
.lf-events-hero__header smp-content[data-module="text"]:nth-of-type(1) .lf-h1-48 {
    text-align: center;
}
/* Body paragraph: max 588 wide, centered */
.lf-about-hero__header smp-content[data-module="text"]:nth-of-type(2),
.lf-events-hero__header smp-content[data-module="text"]:nth-of-type(2) {
    width: 100%;
    max-width: 588px;
}
.lf-about-hero__header smp-content[data-module="text"]:nth-of-type(2) .lf-body-16,
.lf-about-hero__header smp-content[data-module="text"]:nth-of-type(2) .lf-body-16--muted,
.lf-about-hero__header smp-content[data-module="text"]:nth-of-type(2) .lf-body-16--muted p,
.lf-events-hero__header smp-content[data-module="text"]:nth-of-type(2) .lf-body-16,
.lf-events-hero__header smp-content[data-module="text"]:nth-of-type(2) .lf-body-16--muted,
.lf-events-hero__header smp-content[data-module="text"]:nth-of-type(2) .lf-body-16--muted p {
    text-align: center;
}

/* Image column — 720px tall, white bg as load placeholder. */
.lf-about-hero__image {
    align-self: stretch;
    background-color: #ffffff;
    overflow: hidden;
}
.lf-about-hero__image > smp-content-wrapper {
    display: flex !important;
    width: 100%;
    height: 720px;
}
/* Recipe D image-fill chain. */
.lf-about-hero__image smp-content[data-module="image"],
.lf-about-hero__image smp-content[data-module="image"] .smp-image,
.lf-about-hero__image smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
    flex: 1 1 auto;
}
.lf-about-hero__image smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    object-fit: cover !important;
    object-position: center;
    display: block;
    border-radius: 0 !important;
}

/* Responsive — shrink image height + heading size at narrow viewports. */
@media (max-width: 860px) {
    .lf-about-hero smp-container { gap: 48px; }
    .lf-about-hero__image > smp-content-wrapper { height: 480px; }
    .lf-h1-48 { font-size: 36px !important; }
}
@media (max-width: 640px) {
    .lf-about-hero__image > smp-content-wrapper { height: 360px; }
    .lf-h1-48 { font-size: 32px !important; }
}
[data-breakpoint="sm"] .lf-about-hero smp-container,
[data-breakpoint="xs"] .lf-about-hero smp-container {
    gap: 48px;
}
[data-breakpoint="sm"] .lf-about-hero__image > smp-content-wrapper {
    height: 480px;
}
[data-breakpoint="xs"] .lf-about-hero__image > smp-content-wrapper {
    height: 360px;
}
[data-breakpoint="sm"] .lf-h1-48 { font-size: 36px !important; }
[data-breakpoint="xs"] .lf-h1-48 { font-size: 32px !important; }

/* =============================================================
   Events hero — composite Saved Block (master_lfeventshero01)
   Single-row centered hero: serif headline + Inter muted body,
   both center-aligned. Shares the centered-header CSS pattern with
   `.lf-about-hero__header` (see selector unions above) — heading
   capped at 792px, body capped at 588px, 24px gap between them.

   Section pink-to-cream gradient bg + vertical padding (top 160,
   bottom 120) live in the section's ram so the Semplice section
   popup pre-fills correctly. Gradient stored in
   `styles.xl.background-color` as the gradient string — Semplice's
   Background::css detects the substring and emits as background-image.
   Horizontal page-gutter handled by the shared --gutter-page rule.

   First used at the top of the Events page.
   ============================================================= */

/* No section-level overrides needed — the centered-header pattern
   shared with `.lf-about-hero` covers content layout. Heading and
   body responsive font-size shrinkage are global on `.lf-h1-48` and
   `.lf-body-16`, so they apply automatically. */

/* =============================================================
   Upcoming Events — composite Saved Block (master_lfevents01)
   Section heading + dynamic event card list. Cards are rendered by
   the lf-events-list custom module which fetches from
   dandelion.events/o/lakefront/events.json (cached 1h, see
   lakefront_fetch_dandelion_events_raw in functions.php).

   Each card is a 50/50 split:
     LEFT — title, tag chips, meta rows (facilitator/date/location),
            "With X & Y" subtitle. Lives on the section bg.
     RIGHT — clickable <a> wrapping a 50/50 split:
            inner-left = colored "ticket" (cycled palette per card)
            inner-right = full-bleed event image
     Clicking the right half opens the dandelion event detail page.

   Horizontal page-gutter handled by the shared --gutter-page rule.
   Section bg + vertical padding live in section ram (popup-editable).
   ============================================================= */

/* Column wrapper — stack header subrow + cards with 48px gap. */
.lf-events-section__col > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    gap: 48px;
    width: 100%;
    align-items: stretch !important;
}
/* Header subrow — two text modules (title + subtitle) with 16px gap and
   max-width 588 per Figma. The first subrow in the column carries this. */
.lf-events-section smp-subrow:first-of-type {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
    width: 100%;
    max-width: 588px;
}
/* Section subtitle uses text-primary (not muted) per design feedback —
   readable charcoal rather than the soft secondary tone used in card
   meta. Scoped to the section header subrow so card subtitles still
   use their own --text-secondary rule. */
#content-holder .lf-events-section smp-subrow:first-of-type .lf-body-16,
#content-holder .lf-events-section smp-subrow:first-of-type .lf-body-16--muted,
#content-holder .lf-events-section smp-subrow:first-of-type .lf-body-16--muted p {
    color: var(--text-primary) !important;
}

/* Card list — vertical stack with 48px gap matching Figma. */
.lf-events-list {
    display: flex;
    flex-direction: column;
    gap: 48px;
    width: 100%;
}

.lf-events-empty {
    font-family: var(--font-sans);
    font-size: 16px;
    color: var(--text-secondary);
    margin: 0;
}

/* Semplice's frontend.css applies aggressive content-level resets inside
   `#content-holder` that bulldoze our card typography:
     - `.is-content h*`, `.is-content p` → margin-bottom 1.66667rem (~30px)
     - `#content-holder h3` → font-size 1.77778rem / line-height 1.94444rem
     - `#content-holder p`, `#content-holder smp-content li`
                          → font-size 0.888889rem / line-height 1.16667
   Our class selectors (0,1,0) lose to Semplice's `#content-holder X` (1,0,1),
   so this block re-declares the Figma values with `#content-holder` in the
   selector. Specificity becomes (1,2,0) — wins without `!important`. */
#content-holder .lf-events-list .lf-event-card__title,
#content-holder .lf-events-list .lf-event-card__ticket-title,
#content-holder .lf-events-list .lf-event-card__subtitle,
#content-holder .lf-events-list .lf-event-card__with,
#content-holder .lf-events-list .lf-event-card__chips,
#content-holder .lf-events-list .lf-event-card__chip,
#content-holder .lf-events-list .lf-event-card__meta,
#content-holder .lf-events-list .lf-event-card__meta-row {
    margin: 0;
}
#content-holder .lf-events-list .lf-event-card__title {
    font-size: 24px;
    line-height: 1.1;
    color: var(--text-primary);
}
#content-holder .lf-events-list .lf-event-card__ticket-title {
    font-size: 24px;
    line-height: 1.1;
    color: inherit;                                 /* picks up palette text colour */
}
#content-holder .lf-events-list .lf-event-card__subtitle {
    font-size: 14px;
    line-height: 1.3;
    color: var(--text-secondary);
}
#content-holder .lf-events-list .lf-event-card__with {
    font-size: 10px;
    line-height: 1.3;
    color: inherit;
}
#content-holder .lf-events-list .lf-event-card__chip {
    font-size: 12px;
    line-height: 1.3;
    letter-spacing: 0;
    color: var(--text-primary);
}
#content-holder .lf-events-list .lf-event-card__meta-row {
    font-size: 14px;
    line-height: 1.3;
    letter-spacing: 0;
    color: var(--text-primary);
}

/* Single card — 50/50 outer split, min-height matches Figma 314.
   No card-level bg — the left half carries a translucent tint that
   composes against the section bg, and the right half's ticket + image
   fill their grid cells with their own colours/content.

   `position: relative` is the stretched-link anchor — the right half's
   `<a>` gets a `::after` overlay (below) that absolutely positions to
   fill the entire card, making the whole card clickable. */
.lf-event-card {
    display: grid;
    grid-template-columns: 1fr 1fr;
    min-height: 314px;
    align-items: stretch;
    position: relative;
}
.lf-event-card__right::after {
    content: '';
    position: absolute;
    inset: 0;
    z-index: 1;
    /* No background — purely an invisible click target overlaying the card. */
}

/* LEFT half — meta column.
   Single flex column with uniform 16px gap between all four children
   (title, chips, meta, subtitle) and the whole stack vertically centered
   in the card. Matches Figma node 500:3478 (p-[32px] gap-[16px]
   justify-center). 32px padding on every side. */
.lf-event-card__left {
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: flex-start;
    gap: 16px;
    padding: 32px;
    background: rgba(0, 0, 0, 0.04);
}
.lf-event-card__title {
    font-family: var(--font-serif);
    font-size: 24px;
    line-height: 1.1;
    color: var(--text-primary);
    margin: 0;
}
.lf-event-card__chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    list-style: none;
    padding: 0;
    margin: 0;
}
.lf-event-card__chip {
    font-family: var(--font-sans);
    font-size: 12px;
    line-height: 1.3;
    padding: 4px 8px;
    border-radius: 32px;
    background: rgba(0, 0, 0, 0.04);
    color: var(--text-primary);
    opacity: 0.8;
    white-space: nowrap;
}
.lf-event-card__meta {
    display: flex;
    flex-direction: column;
    gap: 8px;
    list-style: none;
    padding: 0;
    margin: 0;
}
.lf-event-card__meta-row {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: 1.3;
    color: var(--text-primary);
}
.lf-event-card__icon {
    width: 20px;
    height: 20px;
    flex: 0 0 20px;
    color: var(--text-primary);
}
.lf-event-card__subtitle {
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: 1.3;
    color: var(--text-secondary);
    margin: 0;
}

/* RIGHT half — clickable <a> with flex row layout (Figma 500:3503).
   16px gap between ticket and image; palette bg lives HERE so the gap
   visually fills with the palette colour. Items align to top so the
   ticket and image rows start flush at the card's top edge. */
.lf-event-card__right {
    display: flex;
    align-items: stretch;
    gap: 16px;
    text-decoration: none;
    color: inherit;
}

/* Ticket — flex column with uniform 40px gap between brand, body and
   credits. The body group's `flex: 1 0 0` lets it grow to fill the
   remaining vertical space, pushing credits to the bottom naturally
   — no `justify-content: space-between` hack. Transparent bg: the
   palette colour shows through from `.lf-event-card__right`. */
.lf-event-card__ticket {
    flex: 1 1 0;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 40px;
    padding: 16px;
    position: relative;
    overflow: hidden;
}
.lf-event-card__brand {
    font-family: var(--font-serif);
    font-size: 16px;
    letter-spacing: 0.64px;
    text-transform: uppercase;
    line-height: 1;
    white-space: nowrap;
}
.lf-event-card__ticket-body {
    flex: 1 1 0;
    min-height: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;                  /* headline-group -> date */
}
.lf-event-card__ticket-headline {
    display: flex;
    flex-direction: column;
    gap: 4px;                   /* eyebrow -> title */
}
.lf-event-card__eyebrow {
    font-family: var(--font-sans);
    font-size: 10px;
    line-height: 1.3;
    letter-spacing: 0.2px;
    text-transform: uppercase;
    opacity: 0.7;
}
.lf-event-card__ticket-title {
    font-family: var(--font-serif);
    font-size: 24px;
    line-height: 1.1;
    margin: 0;
}
.lf-event-card__ticket-date {
    font-family: var(--font-sans);
    font-size: 12px;
    line-height: 1.3;
    white-space: nowrap;
}
.lf-event-card__credits {
    display: flex;
    flex-direction: column;
    gap: 8px;                   /* avatars -> with */
}
.lf-event-card__avatars {
    display: flex;
    align-items: flex-start;
    isolation: isolate;          /* matches Figma `isolate` — scoped stacking
                                    so z-index on avatars works regardless of
                                    ancestor stacking contexts. */
}
.lf-event-card__avatar {
    width: 24px;
    height: 24px;
    border-radius: 24px;
    border: 0.6px solid var(--off-white, #FEFDF4);
    background: #D9D9D9;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-sans);
    font-size: 11px;
    font-weight: 600;
    line-height: 1;
    color: #1a1a1a;
    box-sizing: border-box;
}
.lf-event-card__avatar[data-i="0"] {
    /* Leftmost avatar paints on top of any following ones — z-index works
       on flex items without needing position. Stacking order: left to right. */
    z-index: 2;
}
.lf-event-card__avatar[data-i="1"] {
    /* The avatars container has no gap because the overlap is by design.
       This is the only legit "negative margin" in the file — it produces
       the deliberate Figma overlap effect (24px circles with 18px stride),
       not a sibling-spacing hack. */
    margin-left: -6px;
    z-index: 1;
}
.lf-event-card__with {
    font-family: var(--font-sans);
    font-size: 10px;
    line-height: 1.3;
    margin: 0;
    overflow-wrap: anywhere;      /* long facilitator lists wrap inside ticket */
    word-break: break-word;
}

/* Image — flexes 1:1 with the ticket so they always split the right
   half 50/50 (matches Figma's 292/292 at the 1200 design width and
   scales proportionally at narrower viewports). #d9d9d9 placeholder
   matches Figma's image-loading fallback. */
.lf-event-card__image {
    flex: 1 1 0;
    min-width: 0;
    overflow: hidden;
    background: #d9d9d9;
}
.lf-event-card__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
}
.lf-event-card__image[data-empty="1"] {
    background: #d9d9d9;
}

/* Palette cycle — 5 colors taken from the brand. Avatars on dark
   tickets keep their cream background; on light tickets we tint
   slightly darker so the initial letter stays readable. */
/* Ticket palette — pulls from the Figma brand tokens defined in :root.
   Cycles every 8 cards via the `data-palette` attribute (i % 8 in PHP).
   Palette bg lives on `.lf-event-card__right` (the flex parent) so the
   16px gap between ticket and image fills with the same palette colour
   — matches Figma 500:3503 etc. Text color flips per swatch lightness
   so the LAKEFRONT brand line and ticket title always read clearly. */
.lf-event-card[data-palette="0"] .lf-event-card__right { background: var(--color-light-blue); color: var(--text-primary); }
.lf-event-card[data-palette="1"] .lf-event-card__right { background: var(--color-navy);       color: var(--color-ecru); }
.lf-event-card[data-palette="2"] .lf-event-card__right { background: var(--color-peach);      color: var(--text-primary); }
.lf-event-card[data-palette="3"] .lf-event-card__right { background: var(--color-burgundy);   color: var(--color-ecru); }
.lf-event-card[data-palette="4"] .lf-event-card__right { background: var(--color-yellow);     color: var(--text-primary); }
.lf-event-card[data-palette="5"] .lf-event-card__right { background: var(--color-olive);      color: var(--color-ecru); }
.lf-event-card[data-palette="6"] .lf-event-card__right { background: var(--color-fuchsia);    color: var(--text-primary); }
.lf-event-card[data-palette="7"] .lf-event-card__right { background: var(--color-ecru);       color: var(--text-primary); }
/* Avatars are a single neutral grey with an off-white hairline border —
   reads clearly on every palette so no per-palette overrides needed. */

/* Pagination — visible only when the module emits the nav (per_page > 0
   and more than 1 page). The list hides cards whose data-page doesn't
   match the active page; the JS toggles `is-active` on the nav button. */
/* Pagination — only show cards whose `data-page` matches the list's
   `data-current-page`. PHP renders `data-current-page="1"` so page 1
   is visible immediately without JS (important for the Semplice admin
   canvas where the wp_footer JS doesn't fire). JS swaps the attribute
   on button click. */
.lf-events-list[data-per-page]:not([data-per-page="0"]) .lf-event-card { display: none; }
.lf-events-list[data-current-page="1"] .lf-event-card[data-page="1"],
.lf-events-list[data-current-page="2"] .lf-event-card[data-page="2"],
.lf-events-list[data-current-page="3"] .lf-event-card[data-page="3"],
.lf-events-list[data-current-page="4"] .lf-event-card[data-page="4"],
.lf-events-list[data-current-page="5"] .lf-event-card[data-page="5"],
.lf-events-list[data-current-page="6"] .lf-event-card[data-page="6"],
.lf-events-list[data-current-page="7"] .lf-event-card[data-page="7"],
.lf-events-list[data-current-page="8"] .lf-event-card[data-page="8"] { display: grid; }
/* Pagination — prev/next chevron buttons flanking a row of numbered
   page buttons. Numbered buttons are flat with a circular active
   state; nav buttons are subtle until hovered. */
.lf-events-pagination {
    display: flex;
    justify-content: center;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
    padding-top: 24px;
}
.lf-events-pagination__pages {
    display: flex;
    align-items: center;
    gap: 4px;
}
.lf-events-pagination__btn,
.lf-events-pagination__nav {
    appearance: none;
    background: transparent;
    border: 0;
    color: var(--text-primary);
    font-family: var(--font-sans);
    font-size: 14px;
    line-height: 1;
    cursor: pointer;
    transition: background-color 0.15s ease, color 0.15s ease, opacity 0.15s ease;
    padding: 0;
    margin: 0;
}
.lf-events-pagination__btn {
    width: 36px;
    height: 36px;
    border-radius: 999px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.lf-events-pagination__btn:hover:not(.is-active) {
    background: rgba(0, 0, 0, 0.04);
}
.lf-events-pagination__btn.is-active {
    background: var(--text-primary);
    color: var(--color-ecru);
    font-weight: 500;
}
.lf-events-pagination__nav {
    width: 36px;
    height: 36px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    border-radius: 999px;
}
.lf-events-pagination__nav:hover:not(:disabled) {
    background: rgba(0, 0, 0, 0.04);
}
.lf-events-pagination__nav:disabled {
    opacity: 0.3;
    cursor: not-allowed;
}
.lf-events-pagination__nav svg {
    display: block;
}

/* ====== Event card responsive ======
   Side-by-side at ≥ 1336px. Below that, the right half (ticket + image
   — the visual hook) moves to the top via grid `order` and the meta
   column drops below.

   Why 1336? The Figma is designed for 1200px content (120px gutters on
   a 1440 viewport). At viewports just below 1336 the ticket would have
   < 240px width with the side-by-side layout — the title wraps to four
   lines and the date stops reading naturally. Stacking is the right
   call below that threshold.

   Small mobile (< 480px): the right half's inner flex-row also stacks
   so the ticket sits above a full-width 200px image.
   Each @media rule is mirrored with [data-breakpoint] for the Semplice
   editor canvas previews. */

/* ≥ 1024 viewport (covered by the base rules above): card grid 1fr 1fr,
   right is a flex row with ticket and image both `flex: 1 1 0`. They
   split the right-half evenly and the card spans the full section width
   at every viewport, scaling proportionally instead of clamping. */

/* < 1024 viewport — stack vertically.
   DOM order is meta → ticket → image. We want image → ticket → meta,
   so:
     - card grid collapses to single column
     - right gets `order: -1` (above meta in the grid)
     - right is flex-direction: column-reverse so image (DOM-second)
       renders above ticket (DOM-first) inside the right
   Image becomes a 240px hero band, ticket goes content-sized below it,
   meta column natural width below that. */
@media (max-width: 1023px) {
    .lf-event-card {
        grid-template-columns: 1fr;
        min-height: 0;
    }
    .lf-event-card__right {
        order: -1;
        flex-direction: column-reverse;
        align-items: stretch;
    }
    .lf-event-card__ticket {
        flex: 0 0 auto;
        min-width: 0;
    }
    .lf-event-card__image {
        flex: 0 0 240px;
        height: 240px;
        width: 100%;
        min-height: 0;
    }
    .lf-event-card__left {
        padding: 32px 16px;
    }
    /* Body content-sized so it doesn't collapse inside the stacked
       ticket (no constrained ticket height in this mode). */
    .lf-event-card__ticket-body { flex: 0 0 auto; }
}
/* < 480 viewport: reduce image height for short phones. */
@media (max-width: 480px) {
    .lf-event-card__image {
        flex: 0 0 200px;
        height: 200px;
    }
}

/* Editor preview mirrors — Semplice flips [data-breakpoint] without
   resizing the iframe. md/sm/xs all stack (analogous to viewport < 1024
   in the @media rules); xs shortens the image. */
[data-breakpoint="md"] .lf-event-card,
[data-breakpoint="sm"] .lf-event-card,
[data-breakpoint="xs"] .lf-event-card {
    grid-template-columns: 1fr;
    min-height: 0;
}
[data-breakpoint="md"] .lf-event-card__right,
[data-breakpoint="sm"] .lf-event-card__right,
[data-breakpoint="xs"] .lf-event-card__right {
    order: -1;
    flex-direction: column-reverse;
    align-items: stretch;
}
[data-breakpoint="md"] .lf-event-card__ticket,
[data-breakpoint="sm"] .lf-event-card__ticket,
[data-breakpoint="xs"] .lf-event-card__ticket {
    flex: 0 0 auto;
    min-width: 0;
}
[data-breakpoint="md"] .lf-event-card__image,
[data-breakpoint="sm"] .lf-event-card__image,
[data-breakpoint="xs"] .lf-event-card__image {
    flex: 0 0 240px;
    height: 240px;
    width: 100%;
    min-height: 0;
}
[data-breakpoint="md"] .lf-event-card__left,
[data-breakpoint="sm"] .lf-event-card__left,
[data-breakpoint="xs"] .lf-event-card__left {
    padding: 32px 16px;
}
[data-breakpoint="md"] .lf-event-card__ticket-body,
[data-breakpoint="sm"] .lf-event-card__ticket-body,
[data-breakpoint="xs"] .lf-event-card__ticket-body {
    flex: 0 0 auto;
}
[data-breakpoint="xs"] .lf-event-card__image {
    flex: 0 0 200px;
    height: 200px;
}

/* =============================================================
   Text + Image Split — atomic Saved Block (master_lftextimage01)
   Mirrors the row layout of `lf-img-text-split` (6+5 columns with
   8.333% flex gap = 1-col visual offset, shared row gap rule above).
   Difference from `lf-img-text-split`:
     - Text column uses Inter eyebrow + Inter body (vs serif h2-32)
     - Image column has fixed aspect-ratio 588/441 (vs full-height fill)
     - Image column can hold an optional caption module beneath
     - Section supports `--flip` modifier for image-left/text-right
       (default = text-left, image-right)

   First used by the About page's lineage + beliefs composite
   (`lf-about-story`). Reused anywhere a designed text/image split
   with a captioned image is wanted.
   ============================================================= */

/* Default order: text col (DOM 1st, visually LEFT) + image col (DOM 2nd, RIGHT).
   `--flip` reverses the visual order without reordering the DOM. */
.lf-text-image.lf-text-image--flip smp-row {
    flex-direction: row-reverse;
}

/* Text column — eyebrow + body stack, vertically centered. */
.lf-text-image__text > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    justify-content: center !important;
    align-items: flex-start !important;
    gap: 16px;
    width: 100%;
    height: 100%;
}

/* Image column — image at fixed aspect with optional caption below. */
.lf-text-image__img > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    align-items: flex-start !important;
    gap: 8px;
    width: 100%;
}
.lf-text-image__img smp-content[data-module="image"] {
    width: 100% !important;
    aspect-ratio: 588 / 441;
    flex: 0 0 auto;
}
.lf-text-image__img smp-content[data-module="image"] .smp-image,
.lf-text-image__img smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    height: 100% !important;
    margin: 0 !important;
}
.lf-text-image__img smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: 100% !important;
    max-width: none !important;
    object-fit: cover !important;
    object-position: center;
    display: block;
    border-radius: 0 !important;
    background-color: #ffffff;
}

/* Responsive: stack columns at narrow viewports. The max-width and
   flex-basis overrides are needed to beat Semplice's
   `[data-xl-width="N"]` per-instance CSS, which caps both. */
@media (max-width: 860px) {
    .lf-text-image smp-row {
        gap: 24px !important;
        flex-direction: column !important;
    }
    .lf-text-image.lf-text-image--flip smp-row {
        flex-direction: column !important;
    }
    .lf-text-image__text,
    .lf-text-image__img {
        width: 100% !important;
        max-width: 100% !important;
        flex-basis: 100% !important;
        flex: 0 0 auto !important;
    }
}
[data-breakpoint="sm"] .lf-text-image smp-row,
[data-breakpoint="xs"] .lf-text-image smp-row {
    gap: 24px !important;
    flex-direction: column !important;
}
[data-breakpoint="sm"] .lf-text-image.lf-text-image--flip smp-row,
[data-breakpoint="xs"] .lf-text-image.lf-text-image--flip smp-row {
    flex-direction: column !important;
}
[data-breakpoint="sm"] .lf-text-image__text,
[data-breakpoint="sm"] .lf-text-image__img,
[data-breakpoint="xs"] .lf-text-image__text,
[data-breakpoint="xs"] .lf-text-image__img {
    width: 100% !important;
    max-width: 100% !important;
    flex-basis: 100% !important;
    flex: 0 0 auto !important;
}

/* =============================================================
   About story — composite Saved Block (master_lfaboutstory01)
   Two stacked `lf-text-image` rows in a single section with sky-blue bg.
   Row 1: text-left + image-right (with caption)
   Row 2: image-left + text-right (no caption) — flipped via
          `flex-direction: row-reverse` on the 2nd row.

   Section bg + vertical padding live in section ram (popup-editable).
   Inter-row gap lives in CSS (smp-container flex-column with gap).
   ============================================================= */

.lf-about-story smp-container {
    flex-direction: column !important;
    gap: 120px;                            /* Figma gap-[120px] */
}
.lf-about-story smp-row:nth-of-type(2) {
    flex-direction: row-reverse;
}

@media (max-width: 860px) {
    .lf-about-story smp-container { gap: 72px; }
    /* row 2 stacks vertically — the smp-row flex-direction is reset
       above by the shared @media rule */
}
[data-breakpoint="sm"] .lf-about-story smp-container,
[data-breakpoint="xs"] .lf-about-story smp-container {
    gap: 72px;
}

/* =============================================================
   Partner Card — atomic Saved Block (master_lfpartnercard01)
   Two-line card: uppercase Inter 14 label + Inter 14 muted description.
   Atomic CSS uses light-bg defaults (text-primary / text-secondary).
   When placed inside a dark section (e.g. lf-partners-section), the
   parent section overrides the colors to the inverted tokens.
   ============================================================= */

.lf-partner-card {
    display: flex;
    flex-direction: column;
    gap: 8px;
}
.lf-partner-card__label {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    text-transform: uppercase;
    color: var(--text-primary) !important;
    margin: 0 !important;
}
.lf-partner-card__desc {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    color: var(--text-secondary) !important;
    margin: 0;
}

/* =============================================================
   Part of something larger — composite Saved Block
   (master_lfpartnerssection01)
   Single section with one row:
     - Text column (width 5): heading + body header + 2x2 partner cards grid
     - Image column (width 6): single image (aspect 588/441)
   Reuses lf-text-image's row layout (6+5 with 8.333% gap via the shared
   rule above). Dark surface (#1a1a1a) with inverted text tokens.
   Composite section carries `lf-text-image lf-partners-section` so it
   picks up the row gap from the atomic + bg/cards layout from itself.
   ============================================================= */

/* Dark surface — invert text colors for all text inside the section. */
.lf-partners-section .lf-h2-40,
.lf-partners-section .lf-body-16,
.lf-partners-section .lf-body-16 p {
    color: var(--text-primary-inv) !important;
}
.lf-partners-section .lf-partner-card__label {
    color: var(--text-primary-inv) !important;
}
.lf-partners-section .lf-partner-card__desc {
    color: var(--text-secondary-inv) !important;
}
/* Inline link in the partner card description — body small, slightly
   brighter than surrounding desc text (0.8 vs 0.6 alpha) so the
   underlined CTA reads as interactive on the dark surface. */
.lf-partners-section .lf-partner-card__desc a,
.lf-partners-section .lf-partner-card__desc a:link,
.lf-partners-section .lf-partner-card__desc a:visited {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    color: rgba(254, 253, 244, 0.8) !important;
    text-decoration: underline solid;
    text-decoration-skip-ink: auto;
    text-underline-offset: auto;
    text-underline-position: from-font;
}
.lf-partners-section .lf-partner-card__desc a:hover,
.lf-partners-section .lf-partner-card__desc a:focus-visible {
    color: var(--text-primary-inv) !important;
}

/* Text column — header subrow stacked above the cards-grid subrow.
   72px gap between header and cards (Figma gap-[72px]). */
.lf-partners-section__text > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    gap: 72px !important;
    width: 100%;
}
/* Header subrow: heading + body with 16px gap. */
.lf-partners-section__text smp-subrow:nth-of-type(1) {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
    width: 100%;
}
/* Cards-grid subrow: 2 columns × 2 rows, 24px gap both axes.
   Each child content is a single text module containing the .lf-partner-card
   HTML (label + description). 4 text modules = 4 cards in the grid.
   `grid-auto-flow: row` overrides Semplice's default `grid-auto-flow: column`
   which would otherwise spill the extra cards into implicit columns (giving
   4 columns of 107px instead of 2x2). */
.lf-partners-section__text smp-subrow:nth-of-type(2) {
    display: grid !important;
    grid-template-columns: repeat(2, 1fr) !important;
    grid-auto-flow: row !important;
    column-gap: 24px !important;
    row-gap: 24px !important;
    width: 100%;
}

/* Responsive: cards collapse to single column at xs; whole row stacks
   image-below at sm/xs (inherits from lf-text-image's stacking rules). */
@media (max-width: 640px) {
    .lf-partners-section__text > smp-content-wrapper { gap: 48px !important; }
    .lf-partners-section__text smp-subrow:nth-of-type(2) {
        grid-template-columns: 1fr;
    }
}
[data-breakpoint="xs"] .lf-partners-section__text > smp-content-wrapper {
    gap: 48px !important;
}
[data-breakpoint="xs"] .lf-partners-section__text smp-subrow:nth-of-type(2) {
    grid-template-columns: 1fr;
}

/* =============================================================
   Logo Tile — atomic Saved Block (master_lflogotile01)
   Single column carrying one image module. Renders as a 1:1 dark
   square with the logo centered via object-fit: contain. Drag
   from "Atomic Components" into any row to add a logo column;
   the parent grid arranges them when used inside the Larger
   Ecosystem section.
   ============================================================= */
.lf-logo-tile {
    aspect-ratio: 1 / 1;
    background-color: #292929;
    box-sizing: border-box;
    /* !important needed: Semplice's #content-holder [data-gutter] reset
       sets padding: 0 on every smp-column at higher specificity. */
    padding: 48px !important;
    display: flex !important;
    align-items: center;
    justify-content: center;
    height: auto !important;
    min-height: 0 !important;
}
.lf-logo-tile > smp-content-wrapper,
.lf-logo-tile smp-content,
.lf-logo-tile .smp-image,
.lf-logo-tile .smp-image .is-content {
    display: flex !important;
    align-items: center;
    justify-content: center;
    width: 100%;
    height: 100%;
    margin: 0 !important;
}
.lf-logo-tile img {
    max-width: 100% !important;
    max-height: 100% !important;
    width: auto !important;
    height: auto !important;
    object-fit: contain !important;
    display: block;
}
/* Scale padding with tile width on larger 2-up/1-up viewports so the
   logo keeps visual presence as the tile grows past desktop's 282px. */
@media (max-width: 1023px) {
    .lf-logo-tile { padding: 14% !important; }
}
@media (max-width: 480px) {
    .lf-logo-tile { padding: 18% !important; }
}
[data-breakpoint="md"] .lf-logo-tile,
[data-breakpoint="sm"] .lf-logo-tile { padding: 14% !important; }
[data-breakpoint="xs"] .lf-logo-tile { padding: 18% !important; }

/* =============================================================
   The Larger Ecosystem — composite Saved Block
   (master_lflargereco01)
   Full-bleed dark section with a centered serif header above a
   4-up grid of logo tiles. Reuses the lf-logo-tile shell for each
   tile; the grid auto-flows when authors add or remove Logo Tile
   atomics in the tiles row. Page-gutter (120/40/16) lives on the
   shared rule above.
   ============================================================= */

/* Stack the two rows vertically with a 120px gap (collapses on smaller
   viewports). smp-container is flex-row by default. */
.lf-larger-ecosystem smp-container {
    flex-direction: column !important;
    gap: 6.667rem;
}
@media (max-width: 1023px) {
    .lf-larger-ecosystem smp-container { gap: 4rem; }
}
@media (max-width: 640px) {
    .lf-larger-ecosystem smp-container { gap: 3rem; }
}
[data-breakpoint="md"] .lf-larger-ecosystem smp-container,
[data-breakpoint="sm"] .lf-larger-ecosystem smp-container { gap: 4rem; }
[data-breakpoint="xs"] .lf-larger-ecosystem smp-container { gap: 3rem; }

/* Header column — centered serif title + Inter body, max-width 588px
   to match Figma (text-field width). */
.lf-larger-ecosystem__header > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    align-items: center;
    width: 100%;
}
.lf-larger-ecosystem__header smp-subrow {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
    width: 100%;
    max-width: 588px;
    margin: 0 auto;
    text-align: center;
}
#content-holder .lf-larger-ecosystem__header .lf-h2-40 {
    color: var(--text-primary-inv) !important;
    text-align: center;
}
#content-holder .lf-larger-ecosystem__header .lf-body-16,
#content-holder .lf-larger-ecosystem__header .lf-body-16 p {
    color: var(--text-secondary-inv) !important;
    text-align: center;
}

/* Tiles row — CSS grid 4-up, regardless of how many lf-logo-tile
   columns are inside. data-gutter:"no" on the section means the row
   has no built-in negative margin, so the grid sizing is honest. */
.lf-larger-ecosystem smp-row:nth-of-type(2) {
    display: grid !important;
    grid-template-columns: repeat(4, 1fr) !important;
    gap: 24px !important;
    width: 100%;
    margin: 0 !important;
}
/* Override Semplice's per-column inline width — let the grid drive
   sizing instead of the column.width.xl ram value. NB: do NOT also
   reset padding-left/right here — that would beat .lf-logo-tile's
   `padding` shorthand by specificity and zero out the tile's
   horizontal padding. data-gutter:"no" on the section already keeps
   Semplice from adding column gutter padding. */
.lf-larger-ecosystem smp-row:nth-of-type(2) > smp-column {
    width: auto !important;
    max-width: 100% !important;
    flex: initial !important;
}

/* Responsive: 4-up → 3-up at md → 2-up at sm → 1-up at xs.
   Switching to 3-up at md keeps each tile in the ~220-300px sweet
   spot (versus 2-up where tiles ballooned past 400px around 900w). */
@media (max-width: 1023px) {
    .lf-larger-ecosystem smp-row:nth-of-type(2) {
        grid-template-columns: repeat(3, 1fr) !important;
    }
}
@media (max-width: 767px) {
    .lf-larger-ecosystem smp-row:nth-of-type(2) {
        grid-template-columns: repeat(2, 1fr) !important;
    }
}
@media (max-width: 479px) {
    .lf-larger-ecosystem smp-row:nth-of-type(2) {
        grid-template-columns: 1fr !important;
        max-width: 320px;
        margin: 0 auto !important;
    }
}
[data-breakpoint="md"] .lf-larger-ecosystem smp-row:nth-of-type(2) {
    grid-template-columns: repeat(3, 1fr) !important;
}
[data-breakpoint="sm"] .lf-larger-ecosystem smp-row:nth-of-type(2) {
    grid-template-columns: repeat(2, 1fr) !important;
}
[data-breakpoint="xs"] .lf-larger-ecosystem smp-row:nth-of-type(2) {
    grid-template-columns: 1fr !important;
    max-width: 320px;
    margin: 0 auto !important;
}

/* =============================================================
   Pull Quote — composite Saved Block (master_lfpullquote01)
   Full-bleed dark section with one centered serif quote at
   max-width 588px. Editable as a single Semplice text module —
   author clicks the quote, native popup opens, type to change.
   Page-gutter (120/40/16) lives on the shared rule above.
   ============================================================= */

/* Center the inner column's content within the row at 588px max-width
   so a long quote wraps tightly instead of stretching the row. */
.lf-pullquote__inner > smp-content-wrapper {
    display: flex !important;
    justify-content: center;
    width: 100%;
}
.lf-pullquote__inner smp-content {
    max-width: 588px;
    width: 100%;
}

/* Quote typography: Instrument Serif 48px, line-height 1.3, inverted
   text. clamp() lets the size shrink gracefully on narrow viewports
   without an explicit @media cascade. text-indent hangs the opening
   quote outside the type block (optical alignment trick from Figma). */
#content-holder .lf-pullquote .lf-pullquote__text {
    font-family: var(--font-serif) !important;
    font-size: clamp(28px, 4.5vw, 48px) !important;
    font-weight: 400 !important;
    line-height: 1.3 !important;
    color: var(--text-primary-inv) !important;
    margin: 0;
    text-indent: -0.45em;
}

/* Mobile + tablet: switch to centered text. At narrow viewports the
   588px wrapper fills the row, so left-aligned text sits hard against
   the gutter and looks "off". Centering reads as balanced regardless of
   wrap point. Drop the hanging-quote indent here too — it only makes
   sense as an optical correction for left-aligned type. */
@media (max-width: 1023px) {
    #content-holder .lf-pullquote .lf-pullquote__text {
        text-align: center !important;
        text-indent: 0;
    }
}
[data-breakpoint="md"] #content-holder .lf-pullquote .lf-pullquote__text,
[data-breakpoint="sm"] #content-holder .lf-pullquote .lf-pullquote__text,
[data-breakpoint="xs"] #content-holder .lf-pullquote .lf-pullquote__text {
    text-align: center !important;
    text-indent: 0;
}

/* =============================================================
   Person Card — atomic Saved Block (master_lfpersoncard01)
   Single column with: portrait image (4:5 aspect) + caption subrow
   (Inter Medium 14 name + Inter Regular 14 secondary role).
   Layout uses `gap` on each container; no margin between siblings.
   Use inside the People Category section (4-up grid auto-arranges
   them); also draggable into any other row as a standalone card.
   ============================================================= */

/* The actual sibling container is smp-content-wrapper inside the column.
   Stack the image module and the caption subrow vertically with one
   real gap value — no margin hacks. */
.lf-person-card > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px !important;
    width: 100%;
}

/* Caption subrow (name + role): own gap value, separate container. */
.lf-person-card smp-subrow {
    display: flex !important;
    flex-direction: column !important;
    gap: 4px !important;
    width: 100%;
}

/* Strip Semplice's framework margins/padding on the inner wrappers that
   live inside every smp-content. Without this, .module-placeholder and
   .is-content each contribute `margin: 30px 0; padding: 130px 0` —
   arbitrary spacing that compounds with the container gap. Containers
   own all spacing; these wrappers just hold content. */
.lf-person-card .module-placeholder,
.lf-person-card .is-content {
    margin: 0 !important;
    padding: 0 !important;
}

/* Image module — 4:5 portrait wrapper. Targets both the placeholder
   (empty state) and .smp-image (actual upload). Centers content via
   flex now that padding-based centering is gone. */
.lf-person-card .smp-image,
.lf-person-card .module-placeholder {
    aspect-ratio: 4 / 5;
    width: 100%;
    background-color: #f0f0eb;
    display: flex !important;
    align-items: center;
    justify-content: center;
    overflow: hidden;
}
.lf-person-card .smp-image .is-content,
.lf-person-card .smp-image .is-content > * {
    width: 100%;
    height: 100%;
}
.lf-person-card img {
    width: 100% !important;
    height: 100% !important;
    object-fit: cover !important;
    display: block;
}

/* Reset Semplice's #content-holder p { margin-bottom: 1.5em } cascade
   on the caption text so the subrow's `gap: 4px` is the only spacing
   source. This is a defaults-clear, NOT a lazy-gap. */
#content-holder .lf-person-card .lf-person-card__name,
#content-holder .lf-person-card .lf-person-card__role {
    margin: 0 !important;
}
#content-holder .lf-person-card .lf-person-card__name {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    font-weight: 500 !important;
    line-height: 1.3 !important;
    color: var(--text-primary) !important;
}
#content-holder .lf-person-card .lf-person-card__role {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    font-weight: 400 !important;
    line-height: 1.3 !important;
    color: var(--text-secondary) !important;
}

/* =============================================================
   People Category — composite Saved Block (master_lfpeoplecategory01)
   40px serif label + 16px body description (left-aligned 588 segment),
   then a 4-up grid of person cards. Author drags Person Card atomics
   into the cards row to add more people; CSS grid auto-flows new rows.
   Page-gutter (120/40/16) lives on the shared rule above.
   ============================================================= */

/* Stack header above cards row, with a generous gap. */
.lf-people-category smp-container {
    flex-direction: column !important;
    gap: 4rem;       /* 72px between header and cards */
}
@media (max-width: 640px) {
    .lf-people-category smp-container { gap: 3rem; }
}
[data-breakpoint="sm"] .lf-people-category smp-container,
[data-breakpoint="xs"] .lf-people-category smp-container { gap: 3rem; }

/* Header column — left-aligned 588 segment matching Figma. */
.lf-people-category__header > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    width: 100%;
}
.lf-people-category__header smp-subrow {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
    width: 100%;
    max-width: 588px;
}
#content-holder .lf-people-category__header .lf-h2-40 {
    color: var(--text-primary) !important;
    margin: 0;
}
#content-holder .lf-people-category__header .lf-body-16,
#content-holder .lf-people-category__header .lf-body-16 p {
    color: var(--text-secondary) !important;
    margin: 0;
}

/* Cards row — same responsive grid pattern as Larger Ecosystem
   (4-up → 3-up at md → 2-up at sm → 1-up at xs). Vertical row gap
   is 40px per Figma; horizontal column gap is 24px. */
.lf-people-category smp-row:nth-of-type(2) {
    display: grid !important;
    grid-template-columns: repeat(4, 1fr) !important;
    column-gap: 24px !important;
    row-gap: 40px !important;
    width: 100%;
    margin: 0 !important;
}
.lf-people-category smp-row:nth-of-type(2) > smp-column {
    width: auto !important;
    max-width: 100% !important;
    flex: initial !important;
}

@media (max-width: 1023px) {
    .lf-people-category smp-row:nth-of-type(2) {
        grid-template-columns: repeat(3, 1fr) !important;
    }
}
@media (max-width: 767px) {
    .lf-people-category smp-row:nth-of-type(2) {
        grid-template-columns: repeat(2, 1fr) !important;
    }
}
@media (max-width: 479px) {
    .lf-people-category smp-row:nth-of-type(2) {
        grid-template-columns: 1fr !important;
        max-width: 320px;
        margin: 0 auto !important;
    }
}
[data-breakpoint="md"] .lf-people-category smp-row:nth-of-type(2) {
    grid-template-columns: repeat(3, 1fr) !important;
}
[data-breakpoint="sm"] .lf-people-category smp-row:nth-of-type(2) {
    grid-template-columns: repeat(2, 1fr) !important;
}
[data-breakpoint="xs"] .lf-people-category smp-row:nth-of-type(2) {
    grid-template-columns: 1fr !important;
    max-width: 320px;
    margin: 0 auto !important;
}

/* =============================================================
   lf-people-grid — data-driven render (custom Semplice module)
   Renders the same People Category visual using plain &lt;div&gt;s
   pulled from the lf_person CPT. Sits inside whatever section the
   author drops it in, so no section bg/padding here.
   ============================================================= */

.lf-people-grid {
    display: flex;
    flex-direction: column;
    gap: 4rem;            /* 72px between header and cards */
    width: 100%;
}
@media (max-width: 640px) {
    .lf-people-grid { gap: 3rem; }
}
[data-breakpoint="sm"] .lf-people-grid,
[data-breakpoint="xs"] .lf-people-grid { gap: 3rem; }

/* Header — same shape as the People Category header. */
.lf-people-grid__header {
    display: flex;
    flex-direction: column;
    gap: 16px;
    width: 100%;
    max-width: 588px;
}
#content-holder .lf-people-grid__header .lf-h2-40 {
    color: var(--text-primary) !important;
    margin: 0;
}
#content-holder .lf-people-grid__header .lf-body-16 {
    color: var(--text-secondary) !important;
    margin: 0;
}

/* Cards grid — 4-up → 3-up → 2-up → 1-up cascade. */
.lf-people-grid__cards {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    column-gap: 24px;
    row-gap: 40px;
    width: 100%;
}
@media (max-width: 1023px) {
    .lf-people-grid__cards { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 767px) {
    .lf-people-grid__cards { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 479px) {
    .lf-people-grid__cards {
        grid-template-columns: 1fr;
        max-width: 320px;
        margin: 0 auto;
    }
}
[data-breakpoint="md"] .lf-people-grid__cards {
    grid-template-columns: repeat(3, 1fr);
}
[data-breakpoint="sm"] .lf-people-grid__cards {
    grid-template-columns: repeat(2, 1fr);
}
[data-breakpoint="xs"] .lf-people-grid__cards {
    grid-template-columns: 1fr;
    max-width: 320px;
    margin: 0 auto;
}

/* Person card (plain-div variant — used by lf-people-grid). The
   smp-* selectors above only fire when the card is rendered as a
   Semplice column; here the children are plain &lt;div&gt;s with
   __image / __caption suffix classes. Layout values match the
   Semplice variant exactly so a category looks identical whether
   it's authored via the Saved Block or rendered from the CPT. */
.lf-person-card > .lf-person-card__image,
.lf-person-card > .lf-person-card__caption {
    width: 100%;
}
.lf-person-card:not(:has(> smp-content-wrapper)) {
    display: flex;
    flex-direction: column;
    gap: 16px;
}
.lf-person-card__image {
    aspect-ratio: 4 / 5;
    background-color: #f0f0eb;
    overflow: hidden;
}
.lf-person-card__image img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.lf-person-card__caption {
    display: flex;
    flex-direction: column;
    gap: 4px;
}
/* When a person has a LinkedIn URL, the photo is wrapped in an <a>.
   The link should fill the image area cleanly without underline or
   default link colour bleed. */
.lf-person-card__link {
    display: block;
    text-decoration: none;
    color: inherit;
    width: 100%;
}

/* Empty-state notice (no people in category yet). */
.lf-people-grid__empty {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    color: var(--text-secondary) !important;
    margin: 0;
}
.lf-people-grid__empty em {
    font-style: italic;
}

/* Render-all stack — vertical list of category grids. Gap between
   categories matches the section's standard inter-row spacing scale. */
.lf-people-stack {
    display: flex;
    flex-direction: column;
    gap: 6rem;        /* 108px between categories on desktop */
    width: 100%;
}
@media (max-width: 1023px) {
    .lf-people-stack { gap: 4.5rem; }
}
@media (max-width: 640px) {
    .lf-people-stack { gap: 3.5rem; }
}
[data-breakpoint="md"] .lf-people-stack { gap: 4.5rem; }
[data-breakpoint="sm"] .lf-people-stack,
[data-breakpoint="xs"] .lf-people-stack { gap: 3.5rem; }

/* =============================================================
   Day at Lakefront — composite Saved Block (master_lfdayatlf01)
   Scrollytelling "day in the life" section. Three stacked atomics
   on a burgundy section:
     1. .lf-day-intro    centered serif title + Inter subtitle
     2. .lf-day-timeline timeline list + sticky image (custom module)
     3. .lf-day-outro    centered serif pull-quote + button

   Section vertical padding, bg, and inter-row gap live in the
   composite section's ram per-breakpoint (core principle 12).
   Horizontal page-gutter handled by the shared --gutter-page rule
   appended further down.
   ============================================================= */

/* Composite section — multi-row stack. smp-container becomes a flex column
   with the inter-row gap; horizontal gutter on the same rule. Burgundy bg
   lives in section ram, so this rule only handles layout. */
.lf-day-at-lakefront smp-container {
    flex-direction: column !important;
    gap: 6rem;                                          /* 96px between atomics */
    align-items: stretch;
}

/* Override default centered-row constraint — rows should fill the gutter-
   constrained container. Same pattern as other multi-row composites. */
.lf-day-at-lakefront smp-row {
    width: 100% !important;
    max-width: none !important;
}

/* Composite text colour overrides — burgundy section needs cream text. The
   section's `.text-inverted` utility handles the body fallback; per-class
   overrides below ensure h-classes, body classes, and the timeline rows
   pick up the cream variant without authors touching colour pickers. */
#content-holder .lf-day-at-lakefront .lf-h1-48,
#content-holder .lf-day-at-lakefront .lf-h2-32,
#content-holder .lf-day-at-lakefront .lf-body-16 {
    color: var(--text-primary-inv) !important;
}
#content-holder .lf-day-at-lakefront .lf-body-16--muted,
#content-holder .lf-day-at-lakefront .lf-body-16--muted p {
    color: var(--text-secondary-inv) !important;
}

/* -------------------------------------------------------------
   1. Centered intro atomic — title + subtitle
   Same shape as .lf-about-hero__header / .lf-events-hero__header
   (centered, gap 16, 588px body max-width) but with 16px gap
   between title and subtitle (Figma node 500:2900: gap-16).
   ------------------------------------------------------------- */
.lf-day-intro > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    gap: 16px;
    width: 100%;
}
.lf-day-intro smp-content[data-module="text"] {
    width: 100%;
    max-width: 588px;
}
.lf-day-intro smp-content[data-module="text"] .lf-h1-48,
.lf-day-intro smp-content[data-module="text"] .lf-body-16,
.lf-day-intro smp-content[data-module="text"] .lf-body-16--muted,
.lf-day-intro smp-content[data-module="text"] .lf-body-16--muted p {
    text-align: center;
}

/* -------------------------------------------------------------
   2. Day timeline (custom module render)
   Structure (from lf-day-timeline.php):
     .lf-day-timeline                relative parent
       ol.lf-day-timeline__list      vertical row stack, full row width
         li.lf-day-timeline__row     78px time + 1fr text
       .lf-day-timeline__floater     absolute right column
         .lf-day-timeline__image-frame  position: sticky, viewport centred
           img.lf-day-timeline__image
   ------------------------------------------------------------- */

/* Grid container — two columns at desktop / tablet, flex column at mobile.
   `align-items: stretch` is the grid default; we keep it so the sticky-col
   fills the row height (the column the absolutely-positioned image-frame
   moves within). */
.lf-day-timeline {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 591px;
    gap: 80px;
    width: 100%;
    margin: 0;
    padding: 0;
}

/* Row list — grid column 1. Rows stack vertically via gap on the list. */
.lf-day-timeline__list {
    list-style: none;
    margin: 0;
    padding: 0;
    min-width: 0;                                       /* grid item floor — allow text col to shrink below content min */
}

/* Each row — opacity wrapper for the active state + separator line. Border
   lives on the row (not on the inner button) so when the row goes grid at
   the tablet breakpoint the separator spans both text and image columns. */
.lf-day-timeline__row {
    opacity: 0.5;
    transition: opacity 0.35s ease;
    border-top: 1px solid rgba(255, 255, 255, 0.1);
}
.lf-day-timeline__row[data-active="true"] {
    opacity: 1;
}
/* Hover/focus reveal — bumps inactive rows toward full opacity so the user
   gets a visual hint of "this is the row you're about to scroll to". Uses
   :has() to lift the row opacity from inside the button focus state. */
.lf-day-timeline__row:has(.lf-day-timeline__row-btn:hover),
.lf-day-timeline__row:has(.lf-day-timeline__row-btn:focus-visible) {
    opacity: 0.85;
}
.lf-day-timeline__row[data-active="true"]:has(.lf-day-timeline__row-btn:hover),
.lf-day-timeline__row[data-active="true"]:has(.lf-day-timeline__row-btn:focus-visible) {
    opacity: 1;                                         /* active row stays at 1 — no further bump */
}

/* The clickable button covers the whole row including padding + separator.
   Button reset (border, bg, font, color) so it visually matches the prior
   <li> styling — only the cursor + focus ring betray it's interactive. */
.lf-day-timeline__row-btn {
    display: grid;
    grid-template-columns: 78px minmax(0, 1fr);
    gap: 24px;
    width: 100%;
    padding: 32px 0;
    margin: 0;
    border: 0;                                          /* separator lives on .lf-day-timeline__row */
    background: transparent;
    color: inherit;
    font: inherit;
    text-align: left;
    cursor: pointer;
    align-items: start;
}
.lf-day-timeline__row-btn:focus-visible {
    outline: 2px solid var(--text-primary-inv);
    outline-offset: -2px;                               /* inset so it doesn't push the row down */
}

/* Time label — Inter 16, 70% opacity. The opacity multiplies with the row's
   own opacity so the active state pops correctly. */
#content-holder .lf-day-timeline__time {
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    color: var(--text-primary-inv) !important;
    opacity: 0.7;
    display: block;
}

/* Title + body stack inside the right column — gap-on-parent 8px. */
.lf-day-timeline__text {
    display: flex;
    flex-direction: column;
    gap: 8px;
    min-width: 0;
    max-width: 384px;                                   /* Figma w-[384px] keeps text clear of the sticky image */
}

/* Title — Instrument Serif 32. The general .lf-h2-32 typography class already
   exists but doesn't constrain colour at burgundy. Specific selector here. */
#content-holder .lf-day-timeline__title {
    font-family: var(--font-serif) !important;
    font-size: 32px !important;
    font-weight: 400 !important;
    line-height: var(--lh-display) !important;
    color: var(--text-primary-inv) !important;
    margin: 0;
}

/* Body — Inter 16, secondary-on-dark. */
#content-holder .lf-day-timeline__body {
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    font-weight: 400 !important;
    line-height: var(--lh-body) !important;
    color: var(--text-secondary-inv) !important;
    opacity: 0.7;                                       /* matches Figma per-row opacity-50 on body specifically */
    margin: 0;
}

/* Empty-state notice when admin hasn't populated entries yet. */
.lf-day-timeline__empty {
    font-family: var(--font-sans) !important;
    font-size: 14px !important;
    color: var(--text-secondary-inv) !important;
    margin: 0;
    padding: 32px 0;
}
.lf-day-timeline__empty a { color: var(--text-primary-inv) !important; text-decoration: underline; }

/* Sticky column — grid column 2. Stretched to row height by grid default.
   Provides the positioning context for the image-frame, which JS moves
   within these bounds. On mobile this column is itself transformed via JS
   (transform: translateY) to act as the sticky-top strip. */
.lf-day-timeline__sticky-col {
    position: relative;
    width: 591px;
    pointer-events: none;
    will-change: transform;                             /* mobile transforms this element */
}

/* Image frame — absolute inside the sticky-col on desktop / tablet so JS
   can move it within the column to track viewport centre. On mobile this
   gets reset to a normal flow box that fills the sticky-col 1:1. JS sets
   `transform: translate3d()` on this element each scroll frame; will-change
   promotes it to a dedicated compositor layer so the transform applies
   without layout reflow and the sticky tracking stays smooth at 60fps. */
.lf-day-timeline__image-frame {
    position: absolute;
    top: 0;
    left: 0;
    width: 591px;
    height: 407px;
    pointer-events: auto;
    overflow: hidden;
    will-change: transform;
}

/* Image slots — two stacked <img> elements occupy the same frame. The JS
   handler preloads the next entry's image into the inactive slot, then
   toggles `data-visible` so the opacity transition cross-fades between
   them. Hard `img.src` swaps on a single element flash; this is the
   standard scrollytelling cross-fade pattern.
   `will-change: opacity` promotes each slot to its own compositor layer so
   the fade runs on the GPU without repainting the burgundy section behind
   them — without this the swap can visibly shake on lower-end devices. */
.lf-day-timeline__image,
.lf-day-timeline__image--placeholder {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    opacity: 0;
    transition: opacity 0.5s ease;
    will-change: opacity;
    backface-visibility: hidden;
}
.lf-day-timeline__image[data-visible="true"],
.lf-day-timeline__image--placeholder[data-visible="true"] {
    opacity: 1;
}
.lf-day-timeline__image--placeholder {
    background: rgba(254, 253, 244, 0.08);
}

/* -------- Editor canvas adjustments --------
   The frontend has ONE shared image that swaps based on scroll position.
   That's useless for authoring — JS doesn't run in admin, so the canvas
   would show one image at the top of the right column with a lot of empty
   burgundy below, hiding the other entries' images from view.

   In the editor we collapse the grid to a single column and render every
   row's image inline below its text (same shape as the mobile pattern,
   but with ALL rows expanded so the author sees every entry's content at
   once). This works across every [data-breakpoint] preview too — we
   override per-row image visibility unconditionally with !important. */
body.wp-admin #content-holder .lf-day-timeline {
    display: block !important;
}
body.wp-admin #content-holder .lf-day-timeline__sticky-col {
    display: none !important;
}
body.wp-admin #content-holder .lf-day-timeline__row {
    opacity: 1 !important;                              /* readable for editing — no scroll-driven dim */
}
/* wp-admin's global `button { height: 36px }` rule clamps every button in the
   admin chrome. Our row buttons are content (not chrome) and need to be tall
   enough to hold the title + body text — restore auto height. */
body.wp-admin #content-holder .lf-day-timeline__row-btn {
    height: auto !important;
    min-height: 0 !important;
}
body.wp-admin #content-holder .lf-day-timeline__row-image-wrap {
    display: block !important;                          /* every row's image rendered inline */
    padding-left: 102px;                                /* align with title column (time 78 + gap 24) */
}
body.wp-admin #content-holder .lf-day-timeline__row-image {
    width: 100%;
    max-width: 420px;                                   /* matches frontend cap so editor preview matches output */
    aspect-ratio: 591 / 407;
    object-fit: cover;
    display: block;
    margin-top: 16px;
}

/* -------- Responsive --------
   md (768–1023): scaled side-by-side. Image ~340px wide, text column flexes.
   sm (<768) + xs (<480): sticky-top strip pattern — image becomes a full-width
   horizontal banner at the top of the viewport, list scrolls underneath. */

/* Grid responsive — image column shrinks at each breakpoint so the text
   column keeps a readable floor. The 1fr text column flexes to fill the
   remainder once the image col is set. */
@media (max-width: 1439px) {
    .lf-day-timeline {
        grid-template-columns: minmax(0, 1fr) 480px;
        gap: 64px;
    }
    .lf-day-timeline__sticky-col { width: 480px; }
    .lf-day-timeline__image-frame { width: 480px; height: 330px; }
}
/* Per-row image — hidden on desktop where the shared sticky image takes
   over; shown inline below each row's text at narrower viewports. */
.lf-day-timeline__row-image-wrap { display: none; }

/* Tablet (768–1199) — keep the timeline-level grid but switch to 50/50
   proportions so the sticky image column gets equal space to the list.
   The shared sticky image (scrollytelling pattern) runs at tablet too;
   it just lives in a smaller column. Per-row inline images stay hidden
   here — they only kick in below 768 where the list goes single column. */
@media (max-width: 1199px) {
    .lf-day-timeline {
        grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
        gap: 32px;
    }
    .lf-day-timeline__sticky-col {
        width: 100%;                                    /* fill column 2 */
    }
    .lf-day-timeline__image-frame {
        width: 100%;
        height: auto;
        aspect-ratio: 591 / 407;                        /* preserve ratio at fluid width */
    }
    /* Row-btn collapses to a single column at tablet — time stacks above
       the title/body instead of sitting beside them. The narrower text
       column at 50/50 doesn't have room for a 78px time gutter without
       cramping the title wrap. */
    .lf-day-timeline__row-btn {
        grid-template-columns: 1fr;
        gap: 8px;
    }
    .lf-day-timeline__text {
        max-width: none;                                /* let title use the full row-btn width */
    }
}

/* Phone (<768) — drop the timeline grid entirely. Single column, each row
   shows its own image inline below its text, no shared sticky-col. Time
   stacks above the title (same 1fr row-btn shape as tablet). */
@media (max-width: 767px) {
    .lf-day-timeline {
        display: block;
    }
    .lf-day-timeline__sticky-col {
        display: none;                                  /* per-row inline images take over */
    }
    .lf-day-timeline__list {
        display: flex;
        flex-direction: column;
        gap: 24px;                                      /* breathing room between rows on mobile */
    }
    .lf-day-timeline__row {
        opacity: 1;                                     /* no scroll-driven dim */
    }
    .lf-day-timeline__row-image-wrap {
        display: block;
        padding-left: 0;                                /* no gutter — time stacks above */
    }
    .lf-day-timeline__row-image {
        width: 100%;
        max-width: 420px;
        aspect-ratio: 591 / 407;
        object-fit: cover;
        display: block;
        margin-top: 16px;
    }
    .lf-day-timeline__row-btn {
        grid-template-columns: 1fr;
        gap: 8px;
        padding: 24px 0;
    }
    .lf-day-timeline__text { max-width: none; }
    #content-holder .lf-day-timeline__title { font-size: 24px !important; }
}
@media (max-width: 480px) {
    #content-holder .lf-day-timeline__time  { font-size: 14px !important; }
    #content-holder .lf-day-timeline__title { font-size: 22px !important; }
    #content-holder .lf-day-timeline__body  { font-size: 14px !important; }
}

/* Editor preview mirrors — @media doesn't fire in Semplice's editor iframe.
   lg/md mirror the tablet 50/50 grid (shared sticky image in column 2);
   sm/xs mirror the stacked phone pattern (per-row inline images).
   The `body.wp-admin` prefix is required so these match the specificity of
   the body.wp-admin #content-holder admin-canvas overrides above — without
   it the admin overrides win and force the stacked pattern at every
   breakpoint preview. */

/* lg + md — tablet 50/50: timeline grid 1fr | 1fr, sticky-col visible. */
body.wp-admin [data-breakpoint="lg"] #content-holder .lf-day-timeline,
body.wp-admin [data-breakpoint="md"] #content-holder .lf-day-timeline {
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr) !important;
    gap: 32px !important;
}
body.wp-admin [data-breakpoint="lg"] #content-holder .lf-day-timeline__sticky-col,
body.wp-admin [data-breakpoint="md"] #content-holder .lf-day-timeline__sticky-col {
    display: block !important;
    width: 100% !important;
}
body.wp-admin [data-breakpoint="lg"] #content-holder .lf-day-timeline__image-frame,
body.wp-admin [data-breakpoint="md"] #content-holder .lf-day-timeline__image-frame {
    position: relative !important;
    top: auto !important;
    left: auto !important;
    width: 100% !important;
    height: auto !important;
    aspect-ratio: 591 / 407;
}
body.wp-admin [data-breakpoint="lg"] #content-holder .lf-day-timeline__row-image-wrap,
body.wp-admin [data-breakpoint="md"] #content-holder .lf-day-timeline__row-image-wrap {
    display: none !important;                           /* per-row images stay hidden when sticky-col is visible */
}
body.wp-admin [data-breakpoint="lg"] #content-holder .lf-day-timeline__row-btn,
body.wp-admin [data-breakpoint="md"] #content-holder .lf-day-timeline__row-btn {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
}
body.wp-admin [data-breakpoint="lg"] #content-holder .lf-day-timeline__text,
body.wp-admin [data-breakpoint="md"] #content-holder .lf-day-timeline__text {
    max-width: none !important;
}

/* sm + xs — phone stacked: timeline block, per-row inline images. */
body.wp-admin [data-breakpoint="sm"] #content-holder .lf-day-timeline,
body.wp-admin [data-breakpoint="xs"] #content-holder .lf-day-timeline {
    display: block !important;
}
body.wp-admin [data-breakpoint="sm"] #content-holder .lf-day-timeline__sticky-col,
body.wp-admin [data-breakpoint="xs"] #content-holder .lf-day-timeline__sticky-col {
    display: none !important;
}
body.wp-admin [data-breakpoint="sm"] #content-holder .lf-day-timeline__list,
body.wp-admin [data-breakpoint="xs"] #content-holder .lf-day-timeline__list {
    display: flex !important;
    flex-direction: column !important;
    gap: 24px !important;
}
body.wp-admin [data-breakpoint="sm"] #content-holder .lf-day-timeline__row,
body.wp-admin [data-breakpoint="xs"] #content-holder .lf-day-timeline__row {
    opacity: 1 !important;
}
body.wp-admin [data-breakpoint="sm"] #content-holder .lf-day-timeline__row-image-wrap,
body.wp-admin [data-breakpoint="xs"] #content-holder .lf-day-timeline__row-image-wrap {
    display: block !important;
    padding-left: 0 !important;                         /* no gutter — time stacks above */
}
body.wp-admin [data-breakpoint="sm"] #content-holder .lf-day-timeline__row-image,
body.wp-admin [data-breakpoint="xs"] #content-holder .lf-day-timeline__row-image {
    width: 100% !important;
    max-width: 420px !important;
    aspect-ratio: 591 / 407;
    object-fit: cover;
    display: block;
    margin-top: 16px !important;
}
body.wp-admin [data-breakpoint="sm"] #content-holder .lf-day-timeline__row-btn,
body.wp-admin [data-breakpoint="xs"] #content-holder .lf-day-timeline__row-btn {
    grid-template-columns: 1fr !important;
    gap: 8px !important;
    padding: 24px 0;
}
body.wp-admin [data-breakpoint="sm"] #content-holder .lf-day-timeline__text,
body.wp-admin [data-breakpoint="xs"] #content-holder .lf-day-timeline__text { max-width: none !important; }

/* -------------------------------------------------------------
   3. Centered outro atomic — pull quote + button
   The quote is one Semplice text module containing rich text where
   the "That's the point." span uses inline `color: var(--color-pink)`
   (set in the text editor). The button is a standard Semplice button.
   ------------------------------------------------------------- */
.lf-day-outro > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    gap: 40px;                                          /* Figma 500:2912 gap-40 */
    width: 100%;
}
.lf-day-outro smp-content[data-module="text"] {
    width: 100%;
    max-width: 588px;
}
#content-holder .lf-day-outro smp-content[data-module="text"] .lf-h2-32,
#content-holder .lf-day-outro smp-content[data-module="text"] p {
    text-align: center;
    color: var(--text-primary-inv);
}
/* The "That's the point." accent — authors apply `lf-day-outro__accent` to
   a span in the text editor; the colour comes from --color-fuchsia. */
.lf-day-outro__accent { color: var(--color-fuchsia) !important; }

/* Button — auto width, centered. Semplice's column-default 100% width is the
   wrong behaviour for a single CTA; force auto so the pill keeps its native
   width and centres against the parent's align-items: center. */
.lf-day-outro smp-content[data-module="button"] {
    width: auto !important;
    flex: 0 0 auto !important;
}

/* On-dark button colour override — Semplice's global `.smp-button .is-content`
   rule uses `!important` to set the project-wide dark-on-light primary pill.
   On the burgundy section we need the inverse: cream bg, dark text. Match the
   selector specificity (.smp-button .is-content + ID-scope via #content-holder
   wrapper class) and re-!important the colours. The Figma reference (node
   500:2915) uses --cta/primary/bg with the cream #fefdf4 fallback — that's
   what authors see when the section is on a dark surface. */
#content-holder .lf-day-outro .smp-button .is-content {
    background: var(--bg-primary) !important;
    background-image: none !important;
}
#content-holder .lf-day-outro .smp-button .is-content a {
    color: var(--text-primary) !important;
}
#content-holder#content-holder .lf-day-outro .smp-button .is-content:hover {
    background-color: color-mix(in srgb, var(--bg-primary), black 6%) !important;
}
#content-holder#content-holder .lf-day-outro .smp-button .is-content:hover a {
    color: var(--text-primary) !important;
}

/* -------------------------------------------------------------
   Horizontal page-gutter — append .lf-day-at-lakefront to the
   shared selector list (per MODULE-PATTERNS §3 "Horizontal page-
   gutter — the Lakefront convention"). The composite section uses
   the same 120 / 40 / 16 px gutter scale as the rest of the site.
   ------------------------------------------------------------- */
.lf-day-at-lakefront smp-container {
    --gutter-page: var(--smp-grid-outer-desktop, 120px);
    padding-left: var(--gutter-page) !important;
    padding-right: var(--gutter-page) !important;
}
@media (max-width: 1023px) { .lf-day-at-lakefront smp-container { --gutter-page: 40px; } }
@media (max-width: 640px)  { .lf-day-at-lakefront smp-container { --gutter-page: 16px; } }
[data-breakpoint="md"] .lf-day-at-lakefront smp-container,
[data-breakpoint="sm"] .lf-day-at-lakefront smp-container { --gutter-page: 40px; }
[data-breakpoint="xs"] .lf-day-at-lakefront smp-container { --gutter-page: 16px; }

/* =============================================================
   Resident Card (atomic) + People who live here (composite)
   -----------------------------------------------------------
   Atomic: .lf-resident-card  (type=column Saved Block)
     A single video-thumbnail card — photo with a Play-video pill
     centered + a duration tag in the top-left, name/role caption
     below. Authors edit the photo via the image popup and the
     caption via the text popup. Play pill + duration are CSS-baked
     decorative overlays (no real video link; if needed later the
     image module's link target field carries one).
   Composite: .lf-people-here  (type=section Saved Block)
     Heading + 3-up grid of resident cards + CTA button. Authors
     can drag more Resident Cards into the cards row from the
     Atomic Components panel; the flex+wrap row auto-handles 4-up
     or higher counts.
   ============================================================= */

/* -- Resident Card (atomic) --------------------------------- */

.lf-resident-card > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    gap: 16px;
}

.lf-resident-card .module-placeholder,
.lf-resident-card .is-content {
    margin: 0 !important;
    padding: 0 !important;
}

/* Video slot — sizes to the video's natural aspect ratio at full card
   width. Each card in the row therefore takes on the shape of its own
   source (portrait videos are tall, landscape are short, no cropping).
   The row aligns cards to the top so caption rows sit just under each
   video — the bottoms are intentionally ragged.

   Empty / broken slots (no <video> element rendered) fall back to a
   4:5 placeholder via the :not(:has(video)) rule below so the card
   doesn't collapse to zero height. */
.lf-resident-card > smp-content-wrapper > smp-content[data-module="video"] {
    position: relative;
    width: 100% !important;
    overflow: hidden;
    flex: 0 0 auto;
    background: color-mix(in srgb, var(--bg-primary), black 6%);
}
.lf-resident-card > smp-content-wrapper > smp-content[data-module="video"]:not(:has(video)) {
    aspect-ratio: 4 / 5;
    min-height: 0;
}

/* Frontend: hide the video module's "click to add video" placeholder so
   it doesn't leak into the live page when a card has no video yet.
   The card stays blank (cream-ish) until the author picks one.
   The editor canvas keeps the placeholder visible so authors can click
   it to open the popup. */
.lf-resident-card .module-placeholder { display: none !important; }
body.wp-admin .lf-resident-card .module-placeholder { display: flex !important; }

/* Overlays (0:30 tag + Play-video pill) only appear when an actual
   <video> element is rendered in the slot (= the author has set a
   video). Empty cards stay blank — no decorative play-button on a card
   that doesn't actually play anything. */
.lf-resident-card > smp-content-wrapper > smp-content[data-module="video"]:not(:has(video)) .lf-resident-card__duration,
.lf-resident-card > smp-content-wrapper > smp-content[data-module="video"]:not(:has(video)) .lf-resident-card__pill {
    display: none !important;
}
/* Let the play pill extend outside the card edges when the cursor is
   near a corner. Slot default is overflow:hidden — the video and thumb
   are inset:0 so they don't overflow anyway, but the absolutely-positioned
   pill would otherwise get clipped. Pill bumps z-index above neighbour
   cards so it draws over siblings when it spills out sideways. */
.lf-resident-card smp-content[data-module="video"] {
    overflow: visible !important;
}
.lf-resident-card smp-content[data-module="video"] .lf-resident-card__pill {
    z-index: 20;
}
.lf-resident-card smp-content[data-module="video"] .smp-video {
    width: 100% !important;
    height: auto !important;
    margin: 0 !important;
    padding: 0 !important;
}
.lf-resident-card smp-content[data-module="video"] .smp-video video {
    width: 100% !important;
    height: auto !important;
    /* No object-fit/position: the video drives the slot's natural
       height at full width, so the box matches the source aspect
       exactly and there is nothing to crop. */
    display: block;
    border-radius: 0 !important;
}

/* Suppress Semplice's hide-controls play-triangle overlay (rendered as
   a ::after on .smp-video.hide-controls with their own play.svg bg).
   We use our own .lf-resident-card__pill on top, so theirs is just
   visual noise. */
.lf-resident-card .smp-video::after {
    display: none !important;
}

/* Video element — opacity-based state machine with crossfade.
   Idle (no .is-playing): 0 (invisible, lets the thumb show)
   Playing: 1 (full visible)
   Paused mid-play: 0.3 (matches idle thumb dim)
   opacity:0 (not visibility:hidden) keeps the browser decoding frames
   so the canvas thumb capture can still succeed. */
.lf-resident-card smp-content[data-module="video"] .smp-video video {
    opacity: 0;
    transition: opacity 0.3s ease;
}
.lf-resident-card.is-playing smp-content[data-module="video"] .smp-video video {
    opacity: 1;
}
.lf-resident-card.is-playing.is-paused smp-content[data-module="video"] .smp-video video {
    opacity: 0.3;
}

/* Thumb overlay — JS injects this div over the video and paints the
   first frame onto it via canvas capture. Covers the video element
   (and therefore Chrome's native overlay-play-button) until the user
   clicks Play. Faded to 30% opacity to match Figma — the muted
   thumbnail keeps the play pill as the focal point. When .is-playing,
   hide it so the full-opacity video shows through. For cross-origin
   videos the capture fails silently and the cream fallback colour
   shows instead of the frame. */
.lf-resident-card__thumb {
    position: absolute;
    inset: 0;
    z-index: 1;
    background: color-mix(in srgb, var(--bg-primary), black 6%) center / cover no-repeat;
    opacity: 0.3;
    pointer-events: none;
    transition: opacity 0.3s ease;
}
.lf-resident-card.is-playing .lf-resident-card__thumb { opacity: 0; }

/* Top-left duration tag (▶ 0:30). Matches Figma — rgba(0,0,0,0.24)
   bg, 24px tall, 4px-left / 12px-right padding, 2px gap between icon
   and label. JS updates the label text once metadata loads. */
.lf-resident-card__duration {
    position: absolute;
    top: 16px;
    left: 16px;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    gap: 2px;
    height: 24px;
    background: rgba(0, 0, 0, 0.24);
    color: #fff;
    font-family: 'Inter', sans-serif;
    font-size: 12px;
    font-weight: 400;
    line-height: 1;
    padding: 0 12px 0 4px;
    border-radius: 16px;
    letter-spacing: 0;
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    pointer-events: none;
    opacity: 1;
    transition: opacity 0.2s ease;
}
.lf-resident-card__duration .lf-resident-card__play-icon {
    width: 16px;
    height: 16px;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.lf-resident-card__duration .lf-resident-card__play-icon svg {
    width: 12px;
    height: 12px;
    display: block;
}
/* Stop WordPress's emoji-substitute from injecting <img class="emoji">
   margin/padding around our inline SVG icons. */
.lf-resident-card__duration img.emoji,
.lf-resident-card__pill img.emoji {
    display: none !important;
}

/* Play-video pill — real DOM element (not a pseudo) so it can carry
   its own click handler that resumes a paused video. Default state on
   touch is centered + always visible; on hover-capable devices it
   hides until the user moves the cursor into the slot, follows the
   cursor, and the native cursor is suppressed so the pill IS the
   cursor. */
.lf-resident-card__pill {
    position: absolute;
    /* Default (no-hover / touch): centered in the slot, always visible.
       The @media (hover: hover) block below overrides this with a
       cursor-follow transform + opacity hide-until-hover. */
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    will-change: transform;
    z-index: 3;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: #fff;
    color: var(--text-primary);
    font-family: 'Inter', sans-serif;
    font-size: 16px;
    font-weight: 500;
    line-height: 1;
    padding: 8px 16px 8px 8px;
    border-radius: 24px;
    box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
    letter-spacing: -0.08px;
    white-space: nowrap;
    cursor: pointer;
}
.lf-resident-card__pill .lf-resident-card__pill-icon {
    width: 24px;
    height: 24px;
    flex: 0 0 auto;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.lf-resident-card__pill .lf-resident-card__pill-icon svg {
    width: 16px;
    height: 16px;
    display: block;
}
@media (hover: hover) {
    .lf-resident-card > smp-content-wrapper > smp-content[data-module="video"] {
        cursor: none;
    }
    .lf-resident-card__pill {
        top: 0;
        left: 0;
        /* Position via transform (GPU-accelerated, no layout per frame).
           First translate to cursor coords, then offset back by 50% of
           the pill's own size to center on the cursor. */
        transform: translate(var(--cursor-x, 50%), var(--cursor-y, 50%)) translate(-50%, -50%);
        opacity: 0;
        transition: opacity 0.18s ease;
        pointer-events: none;
        cursor: none;
    }
    /* Pill visibility is driven by a JS-set data attribute (geometric
       bounds check), NOT :hover — because the pill can extend outside
       the slot visually but is still a DOM descendant of the slot,
       which would keep :hover active when the cursor visually leaves. */
    .lf-resident-card smp-content[data-module="video"][data-cursor-inside="1"] .lf-resident-card__pill {
        opacity: 1;
        pointer-events: auto;
    }
}

/* Editor canvas — hide the play pill so it doesn't sit on top of
   Semplice's placeholder UI. The 0:30 tag stays visible. */
body.wp-admin .lf-resident-card__pill { display: none !important; }
body.wp-admin .lf-resident-card > smp-content-wrapper > smp-content[data-module="video"] {
    cursor: default !important;
}

/* Active playback (NOT paused): fade pill + duration tag out, restore
   default cursor (let native video controls take over). The :not(.is-
   paused) qualifier means paused state automatically falls through to
   default visibility — pill fades back in (or follows hover rules)
   and duration tag returns. All transitions are on the base
   selectors, so play→pause→play crossfades smoothly. */
.lf-resident-card.is-playing:not(.is-paused) .lf-resident-card__pill,
.lf-resident-card.is-playing:not(.is-paused) .lf-resident-card__duration {
    opacity: 0;
    pointer-events: none;
}
.lf-resident-card.is-playing:not(.is-paused) > smp-content-wrapper > smp-content[data-module="video"] {
    cursor: default;
}
@media (hover: hover) {
    .lf-resident-card.is-playing.is-paused > smp-content-wrapper > smp-content[data-module="video"],
    .lf-resident-card.is-playing.is-paused .lf-resident-card__pill {
        cursor: none;
    }
}

/* Caption (name + role) — Inter 14, opacity 60 */
.lf-resident-card smp-subrow {
    display: flex !important;
    flex-direction: column !important;
    gap: 4px;
    width: 100%;
    padding-right: 32px;
}
#content-holder .lf-resident-card smp-content[data-module="text"] p,
#content-holder .lf-resident-card .lf-resident-card__caption {
    font-family: 'Inter', sans-serif !important;
    font-size: 14px !important;
    line-height: 1.3 !important;
    color: var(--text-primary) !important;
    opacity: 0.6;
    margin: 0 !important;
}

/* -- People who live here (composite) ----------------------- */

.lf-people-here smp-container {
    flex-direction: column !important;
    gap: 48px;
}

/* Header row — 588px max width, left-aligned serif title */
.lf-people-here smp-row:nth-of-type(1) smp-column {
    max-width: 588px;
}
#content-holder .lf-people-here__heading {
    font-family: var(--font-serif) !important;
    font-size: 40px !important;
    line-height: 1.1 !important;
    color: var(--text-primary) !important;
    margin: 0 !important;
    font-weight: 400 !important;
}

/* Cards row — flex with wrap + 24px gap, 3-up baseline */
.lf-people-here smp-row:nth-of-type(2) {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap !important;
    gap: 24px !important;
    width: 100%;
}
.lf-people-here smp-row:nth-of-type(2) .lf-resident-card {
    flex: 1 1 calc((100% - 48px) / 3) !important;
    max-width: calc((100% - 48px) / 3);
    min-width: 0;
}

/* CTA row — colors / hover / padding live in the button's popup
   (options), so authors can edit them via the standard Semplice
   button popup. CSS here only handles the rounded-pill shape
   (Semplice's popup has no border-radius field) and font weight. */
#content-holder .lf-people-here smp-row:nth-of-type(3) .smp-button .is-content {
    border-radius: 16px !important;
    height: 40px !important;       /* matches design-system .btn pill (style.css:149) */
    display: inline-flex !important;
    align-items: center !important;
    width: auto !important;
}
#content-holder .lf-people-here smp-row:nth-of-type(3) .smp-button .is-content a {
    font-family: 'Inter', sans-serif !important;
    font-size: 16px !important;
    font-weight: 500 !important;
    line-height: 1 !important;
    text-decoration: none !important;
    letter-spacing: -0.08px !important;
}

/* Responsive — 3-up → 2-up at tablet → 1-up at phone */
@media (max-width: 1023px) {
    .lf-people-here smp-row:nth-of-type(2) .lf-resident-card {
        flex-basis: calc((100% - 24px) / 2) !important;
        max-width: calc((100% - 24px) / 2);
    }
    #content-holder .lf-people-here__heading { font-size: 36px !important; }
}
@media (max-width: 640px) {
    .lf-people-here smp-row:nth-of-type(2) .lf-resident-card {
        flex-basis: 100% !important;
        max-width: 100%;
    }
    #content-holder .lf-people-here__heading { font-size: 32px !important; }
    .lf-people-here smp-container { gap: 32px !important; }
}

/* Editor-canvas mirrors for @media (Semplice's iframe doesn't reflow) */
[data-breakpoint="md"] .lf-people-here smp-row:nth-of-type(2) .lf-resident-card,
[data-breakpoint="sm"] .lf-people-here smp-row:nth-of-type(2) .lf-resident-card {
    flex-basis: calc((100% - 24px) / 2) !important;
    max-width: calc((100% - 24px) / 2);
}
[data-breakpoint="md"] #content-holder .lf-people-here__heading,
[data-breakpoint="sm"] #content-holder .lf-people-here__heading {
    font-size: 36px !important;
}
[data-breakpoint="xs"] .lf-people-here smp-row:nth-of-type(2) .lf-resident-card {
    flex-basis: 100% !important;
    max-width: 100%;
}
[data-breakpoint="xs"] #content-holder .lf-people-here__heading { font-size: 32px !important; }
[data-breakpoint="xs"] .lf-people-here smp-container { gap: 32px !important; }

/* Horizontal page-gutter — same shared scale */
.lf-people-here smp-container {
    --gutter-page: var(--smp-grid-outer-desktop, 120px);
    padding-left: var(--gutter-page) !important;
    padding-right: var(--gutter-page) !important;
}
@media (max-width: 1023px) { .lf-people-here smp-container { --gutter-page: 40px; } }
@media (max-width: 640px)  { .lf-people-here smp-container { --gutter-page: 16px; } }
[data-breakpoint="md"] .lf-people-here smp-container,
[data-breakpoint="sm"] .lf-people-here smp-container { --gutter-page: 40px; }
[data-breakpoint="xs"] .lf-people-here smp-container { --gutter-page: 16px; }

/* =============================================================
   Segment + CTA — atomic Saved Block (master_lfsegmentcta01, #79)

   588px max-width column, horizontally centered, left-aligned
   text + button inside. Distinct from .lf-day-intro (text-align
   center). Used standalone or composed into .lf-when-isolation
   (#80, "Ambition meant isolation" on Homepage).

   Two subrows so each container has one gap value: 16 between
   heading and body inside the text-stack, 40 between text-stack
   and button on the outer column. No margins between siblings.
   ============================================================= */

#content-holder .lf-segment-cta > smp-content-wrapper {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    gap: 40px;
    width: 100%;
}

/* Semplice strips `classes` from subrow ram (Subrow::init ignores it),
   so target by position. Subrow 1 = text-stack (heading + body), subrow
   2 = button row. Reordering subrows breaks both rules — same gotcha
   as .lf-hero-50-left smp-subrow:nth-of-type(2). */
.lf-segment-cta > smp-content-wrapper > smp-subrow {
    width: 100%;
    max-width: 588px;
}
.lf-segment-cta > smp-content-wrapper > smp-subrow:nth-of-type(1) {
    display: flex !important;
    flex-direction: column !important;
    align-items: stretch !important;
    gap: 16px;
}
.lf-segment-cta > smp-content-wrapper > smp-subrow:nth-of-type(2) {
    display: flex !important;
    flex-direction: row !important;
    justify-content: flex-start !important;
    align-items: flex-start !important;
}

/* Button — cream pill, dark text, 40px tall. Colors hardcoded here:
   the site-wide `.smp-button .is-content { background: ... !important }`
   default at line ~211 clobbers Semplice's per-instance popup CSS
   (which is non-!important). Same trade-off as the Hero 50/50
   button pattern. Authors edit label / link / target via popup;
   colors are theme-locked to the design-system secondary token.

   Semplice also emits the popup bg-color onto `smp-content` (the outer
   block-level shell), so a 588px-wide cream rectangle appears behind
   the pill if we don't zero it. Shrink smp-content to inline-flex so
   it sizes to the pill's content width and stops painting its own bg. */
#content-holder .lf-segment-cta smp-content.lf-segment-cta__btn {
    display: inline-flex !important;
    width: auto !important;
    background-color: transparent !important;
    background-image: none !important;
}
#content-holder .lf-segment-cta smp-content.lf-segment-cta__btn .smp-button {
    width: auto !important;
    background-color: transparent !important;
    background-image: none !important;
}
#content-holder .lf-segment-cta smp-content.lf-segment-cta__btn .smp-button .is-content {
    background-color: var(--cta-secondary-bg) !important;
    background-image: none !important;
    border-radius: 16px !important;
    height: 40px !important;
    display: inline-flex !important;
    align-items: center !important;
    width: auto !important;
    transition:
        background-color 0.25s cubic-bezier(0.16, 1, 0.3, 1),
        color 0.25s cubic-bezier(0.16, 1, 0.3, 1) !important;
}
#content-holder .lf-segment-cta smp-content.lf-segment-cta__btn .smp-button .is-content a {
    color: var(--cta-secondary-text) !important;
    font-family: var(--font-sans) !important;
    font-size: 16px !important;
    font-weight: 500 !important;
    line-height: 1 !important;
    text-decoration: none !important;
}
/* Hover — double-ID specificity hack to beat Semplice's (2,1,1)
   per-instance hover rule. See the lf-hero-50 hover pattern. */
#content-holder#content-holder .lf-segment-cta smp-content.lf-segment-cta__btn .smp-button .is-content:hover {
    background-color: color-mix(in srgb, var(--cta-secondary-bg), black 8%) !important;
    background-image: none !important;
}
#content-holder#content-holder .lf-segment-cta smp-content.lf-segment-cta__btn .smp-button .is-content:hover a {
    color: var(--cta-secondary-text) !important;
}

/* Responsive — full-width subrows + tighter outer gap on phone. */
@media (max-width: 640px) {
    .lf-segment-cta > smp-content-wrapper > smp-subrow { max-width: 100%; }
    #content-holder .lf-segment-cta > smp-content-wrapper { gap: 32px; }
}

[data-breakpoint="sm"] .lf-segment-cta > smp-content-wrapper > smp-subrow,
[data-breakpoint="xs"] .lf-segment-cta > smp-content-wrapper > smp-subrow { max-width: 100%; }
[data-breakpoint="sm"] #content-holder .lf-segment-cta > smp-content-wrapper,
[data-breakpoint="xs"] #content-holder .lf-segment-cta > smp-content-wrapper { gap: 32px; }

/* =============================================================
   Ambition meant isolation — composite Saved Block
   (master_lfwhenisol01, #80)

   Single section, yellow #f1fb9f bg, two stacked rows:
     row 1: .lf-segment-cta shape (centered text + CTA)
     row 2: .lf-photo-strip-track shape (full-bleed Embla strip)

   Yellow bg + vertical padding live in section ram per-breakpoint.
   Inter-row gap (120 → 80 → 56 px) is structural and lives in CSS
   so the section popup doesn't expose a knob for it. Horizontal
   page-gutter via the shared --gutter-page selector list below.
   `.lf-photo-strip-section` on the same section provides the
   overflow: hidden that clips the strip's 100vw escape.
   ============================================================= */

.lf-when-isolation smp-container {
    flex-direction: column !important;
    gap: 7.5rem;                                  /* 120px segment ↔ strip */
}
.lf-when-isolation smp-row {
    width: 100% !important;
    max-width: none !important;
}

@media (max-width: 1023px) { .lf-when-isolation smp-container { gap: 5rem; } }
@media (max-width: 640px)  { .lf-when-isolation smp-container { gap: 3.5rem; } }
[data-breakpoint="md"] .lf-when-isolation smp-container,
[data-breakpoint="sm"] .lf-when-isolation smp-container { gap: 5rem; }
[data-breakpoint="xs"] .lf-when-isolation smp-container { gap: 3.5rem; }

/* Horizontal page-gutter — same shared scale as Building et al. */
.lf-when-isolation smp-container {
    --gutter-page: var(--smp-grid-outer-desktop, 120px);
    padding-left: var(--gutter-page) !important;
    padding-right: var(--gutter-page) !important;
}
@media (max-width: 1023px) { .lf-when-isolation smp-container { --gutter-page: 40px; } }
@media (max-width: 640px)  { .lf-when-isolation smp-container { --gutter-page: 16px; } }
[data-breakpoint="md"] .lf-when-isolation smp-container,
[data-breakpoint="sm"] .lf-when-isolation smp-container { --gutter-page: 40px; }
[data-breakpoint="xs"] .lf-when-isolation smp-container { --gutter-page: 16px; }

/* =============================================================
   Landing Hero — composite Saved Block (master_lflandinghero01)
   + Centered Hero Header with CTAs — atomic column Saved Block
   (master_lfheroctas01, class .lf-hero-ctas).

   The composite is a single section with two stacked rows:
     row 1 — .lf-hero-ctas atomic (12-wide column):
              subrow_text:    [heading 792 max-w, body 588 max-w]   gap 24
              subrow_buttons: [primary, secondary]                  gap 12
              column gap 40 between the two subrows
     row 2 — full-bleed collage image (single PNG; aspect 1440/837).

   Section bg is a vertical gradient (cream #fefdf4 at top →
   lime #ecff9f at bottom) stored in `styles.xl.background-color`
   as the gradient string; Semplice's Background::css() detects
   "gradient" and emits as background-image at render time.
   Vertical padding (top 160, bottom 0) also lives in ram so the
   section popup pre-fills correctly.

   The section is FULL-BLEED — smp-container has max-width:none +
   padding:0 so the gradient and image extend to the viewport edges.
   The atomic provides its own horizontal page-gutter (120/40/16)
   at the column level so the heading/body don't crash into the
   viewport edge on narrow viewports. This is the inverse of the
   normal --gutter-page rule; most blocks put gutter on smp-container,
   but full-bleed blocks push it down to the content level.

   First placed at the top of the Landing page.
   ============================================================= */

/* ----- Typography utility: 72px Instrument Serif headline -----
   Sits alongside .lf-h1-48 / .lf-h2-40 / .lf-h2-32. Used by the
   Landing Hero; reusable elsewhere if a 72px serif is needed. */
#content-holder .lf-h1-72 {
    font-family: var(--font-serif) !important;
    font-size: 72px !important;
    font-weight: 400 !important;
    line-height: 1 !important;
    color: var(--text-primary) !important;
    margin: 0 !important;
}

/* ----- Section: full-bleed, vertical row stacking ----- */
.lf-landing-hero { overflow: hidden; }
.lf-landing-hero smp-container {
    max-width: none !important;
    padding-left: 0 !important;
    padding-right: 0 !important;
    flex-direction: column !important;
    gap: 64px;                              /* row 1 → row 2 */
}
.lf-landing-hero smp-row {
    width: 100% !important;
    max-width: none !important;
}

/* ----- Row 1: hero-ctas atomic. Provides its own horizontal
   page-gutter at the column level so the centered text doesn't
   touch viewport edges on narrow widths. The atomic lives in
   "Atomic Components" — when dropped on any page, this padding
   handles the gutter regardless of the parent section's container. */
.lf-hero-ctas {
    padding-left: 120px;
    padding-right: 120px;
    align-self: stretch;
}
/* Column is the flex parent; smp-content-wrapper passes through via
   `display: contents`. This way the inter-subrow gap from
   `column.styles.xl.gap` (ram, popup-editable as 40) applies directly
   between the two subrows. If we put flex on the wrapper instead, the
   column's gap would target ONE child (the wrapper) and never render. */
.lf-hero-ctas {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
}
.lf-hero-ctas > smp-content-wrapper {
    display: contents !important;
}

/* Text subrow: heading + body stacked, each with its own max-width.
   Gap 24 lives in ram on subrow.styles.xl.gap (Nested Row popup field). */
.lf-hero-ctas smp-subrow:nth-of-type(1) {
    display: flex !important;
    flex-direction: column !important;
    align-items: center !important;
    width: 100%;
}
/* Heading: max-width 792, centered */
.lf-hero-ctas smp-subrow:nth-of-type(1) > smp-content[data-module="text"]:nth-of-type(1) {
    width: 100%;
    max-width: 792px;
}
#content-holder .lf-hero-ctas smp-subrow:nth-of-type(1) > smp-content[data-module="text"]:nth-of-type(1) .lf-h1-72 {
    text-align: center;
}
/* Body: max-width 588, centered, muted */
.lf-hero-ctas smp-subrow:nth-of-type(1) > smp-content[data-module="text"]:nth-of-type(2) {
    width: 100%;
    max-width: 588px;
}
#content-holder .lf-hero-ctas smp-subrow:nth-of-type(1) > smp-content[data-module="text"]:nth-of-type(2) .lf-body-16,
#content-holder .lf-hero-ctas smp-subrow:nth-of-type(1) > smp-content[data-module="text"]:nth-of-type(2) .lf-body-16--muted,
#content-holder .lf-hero-ctas smp-subrow:nth-of-type(1) > smp-content[data-module="text"]:nth-of-type(2) .lf-body-16--muted p {
    text-align: center;
}

/* Buttons subrow: two buttons side-by-side. Per Recipe B, smp-content
   children need explicit width:auto so Semplice's 100%-stacking default
   doesn't force them to full-width here. Gap 12 lives in ram on
   subrow.styles.xl.gap (Nested Row popup field). */
.lf-hero-ctas smp-subrow:nth-of-type(2) {
    display: flex !important;
    flex-direction: row !important;
    flex-wrap: wrap !important;
    justify-content: center !important;
    align-items: center !important;
    width: auto;
}
.lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content {
    width: auto !important;
    flex: 0 0 auto;
}

/* Button 1 is primary (dark) — covered by the site-wide .smp-button rule.
   Button 2 is the secondary (cream). Per-instance options on the button ram
   set the right colours, but the site-wide `.smp-button .is-content` !important
   rule wins, so we need to specifically override for the second button. */
.lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content:nth-of-type(2) .smp-button .is-content {
    background: var(--cta-secondary-bg) !important;
}
.lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content:nth-of-type(2) .smp-button .is-content a {
    color: var(--cta-secondary-text) !important;
}
#content-holder#content-holder .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content:nth-of-type(2) .smp-button .is-content:hover {
    background-color: color-mix(in srgb, var(--cta-secondary-bg), black 10%) !important;
    background-image: none !important;
}
#content-holder#content-holder .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content:nth-of-type(2) .smp-button .is-content:hover a {
    color: var(--cta-secondary-text) !important;
}

/* ----- Row 2: full-bleed collage. Image fills the row width. ----- */
.lf-landing-hero__image-col {
    width: 100% !important;
    align-self: stretch;
}
.lf-landing-hero__image-col > smp-content-wrapper {
    display: flex !important;
    width: 100%;
}
/* Recipe D image-fill chain — image stretches to col width;
   aspect-ratio handles height proportionally. */
.lf-landing-hero__image-col smp-content[data-module="image"],
.lf-landing-hero__image-col smp-content[data-module="image"] .smp-image,
.lf-landing-hero__image-col smp-content[data-module="image"] .smp-image .is-content {
    width: 100% !important;
    margin: 0 !important;
    flex: 1 1 auto;
}
.lf-landing-hero__image-col smp-content[data-module="image"] .smp-image .is-content img {
    width: 100% !important;
    height: auto !important;
    max-width: 1440px !important;          /* cap at design width on wide viewports */
    margin-inline: auto !important;        /* centre when capped */
    display: block;
    border-radius: 0 !important;
}

/* ----- Responsive: shrink heading + gutter + gap, stack buttons ----- */
@media (max-width: 1023px) {
    .lf-hero-ctas { padding-left: 40px; padding-right: 40px; }
    #content-holder .lf-h1-72 { font-size: clamp(40px, 8vw, 72px) !important; }
    .lf-landing-hero smp-container { gap: 48px; }
}
@media (max-width: 640px) {
    .lf-hero-ctas { padding-left: 16px; padding-right: 16px; }
    .lf-landing-hero smp-container { gap: 40px; }
    /* Tighter inter-subrow gap on phones — overrides ram's 40 default.
       (Per-breakpoint ram gap would also work, but only xl is set so
       narrow viewports fall through to ram xl unless overridden here.) */
    .lf-hero-ctas { gap: 32px !important; }
    /* Buttons stack vertically + take the available content width. */
    .lf-hero-ctas smp-subrow:nth-of-type(2) {
        flex-direction: column !important;
        width: 100% !important;
        max-width: 320px;
    }
    .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content {
        width: 100% !important;
    }
    .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content .smp-button,
    .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content .smp-button .is-content,
    .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content .smp-button .is-content a {
        width: 100% !important;
    }
}

/* Editor preview mirrors — @media doesn't fire in editor canvas. */
[data-breakpoint="md"] .lf-hero-ctas,
[data-breakpoint="sm"] .lf-hero-ctas { padding-left: 40px; padding-right: 40px; }
[data-breakpoint="xs"] .lf-hero-ctas { padding-left: 16px; padding-right: 16px; }
[data-breakpoint="md"] #content-holder .lf-h1-72,
[data-breakpoint="sm"] #content-holder .lf-h1-72,
[data-breakpoint="xs"] #content-holder .lf-h1-72 {
    font-size: clamp(40px, 8vw, 72px) !important;
}
[data-breakpoint="md"] .lf-landing-hero smp-container,
[data-breakpoint="sm"] .lf-landing-hero smp-container { gap: 48px; }
[data-breakpoint="xs"] .lf-landing-hero smp-container { gap: 40px; }
[data-breakpoint="xs"] .lf-hero-ctas > smp-content-wrapper { gap: 32px !important; }
[data-breakpoint="xs"] .lf-hero-ctas smp-subrow:nth-of-type(2) {
    flex-direction: column !important;
    width: 100% !important;
    max-width: 320px;
}
[data-breakpoint="xs"] .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content,
[data-breakpoint="xs"] .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content .smp-button,
[data-breakpoint="xs"] .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content .smp-button .is-content,
[data-breakpoint="xs"] .lf-hero-ctas smp-subrow:nth-of-type(2) > smp-content .smp-button .is-content a {
    width: 100% !important;
}

/* Custom CSS End */
