/* er-layout.css — section, columns, divider, spacer, navbar, footer, base, accessibility */

/* ============================================================
   Element Renderer — public-facing element component styles
   Uses --site-* theme tokens from ThemeProvider
   ============================================================ */

/* ============================================================
   Universal page-gutter contract
   ============================================================
   `--site-page-gutter` is the horizontal breathing room between the page
   edge and section content at every breakpoint. On desktop it tracks
   `--site-content-gutter` so authors only edit one token. At ≤768px we
   collapse it to 0 — the platform-wide "edge-to-edge on mobile" policy.
   This activates the negative-margin escape math in
   public/css/er-mobile-fullbleed.css (which references this var) and is
   the single switch that drives full-bleed sections on phones.
   ============================================================ */
:root {
  --site-page-gutter: var(--site-content-gutter, clamp(1rem, 4vw, 2rem));
}
@container site style(--site-bp: mobile) {
  :root {
    --site-page-gutter: 0px;
  }
  /* Zero outer section padding for sections that opt into the full-bleed
     contract (default true on Section + CompoundSection). Scoped to
     [data-mobile-full-bleed="true"] so non-section uses of
     .el-site-container (navbar inner, hero, FAQ) are unaffected. The
     .el-section base rule (CriticalCss.tsx) and .el-site-container
     (er-layout.css ~3766) both apply padding-inline at desktop; this
     collapses them to 0 on phones. */
  [data-mobile-full-bleed="true"].el-section,
  [data-mobile-full-bleed="true"] .el-site-container {
    padding-inline: 0 !important;
  }
}
@media (max-width: 768px) {
  :root {
    --site-page-gutter: 0px;
  }
  /* Zero outer section padding for sections that opt into the full-bleed
     contract (default true on Section + CompoundSection). Scoped to
     [data-mobile-full-bleed="true"] so non-section uses of
     .el-site-container (navbar inner, hero, FAQ) are unaffected. The
     .el-section base rule (CriticalCss.tsx) and .el-site-container
     (er-layout.css ~3766) both apply padding-inline at desktop; this
     collapses them to 0 on phones. */
  [data-mobile-full-bleed="true"].el-section,
  [data-mobile-full-bleed="true"] .el-site-container {
    padding-inline: 0 !important;
  }
}

/* ============================================================
   Builder CSS-variable bridge — single source of truth
   ============================================================
   ElementWrapper (div.el) sets --el-* custom properties.
   This rule — specificity [0,1,1], beating any .el-type [0,1,0]
   class — applies them to the renderer's root element.

   Three-layer fallback cascade:
     1. --el-*          builder-set value (user explicitly changed it)
     2. --el-*-default  element-type default  (declared in .el-type below)
     3. hardcoded last  universal safe value  (transparent / inherit / 0)

   Per-type defaults live in the matching .el-* class as --el-*-default
   vars so they are co-located with other type styles.

   RULE FOR RENDERERS: never set background / color / border-radius /
   box-shadow / padding on the root element inline. Those belong here.
   Only renderer-specific --custom-vars and structural layout go inline.
   ============================================================ */
/* Borders are applied to the outer div.el wrapper via inline styles from
   ElementWrapper. Apply the same border-radius to the wrapper itself so
   any configured border follows the element's rounded corners. */
/* Background + text color paint on the OUTER wrapper only.
   The wrapper is full-width by default; the renderer-root child may cap
   itself via `.el-site-container` (`max-width: --site-max-width`). If we
   painted bg on the inner instead, the bg would stop at the cap and the
   page bg would show through on the viewport edges. Painting on the
   wrapper makes "Background Color" in the inspector behave the way users
   expect: a full-width band behind the section's content column.
   `:where(.el .el) { --el-bg: initial }` (below) prevents bleed onto
   nested elements; leaf classes (.el--heading, .el--button, …) reset
   the same vars so text leaves never paint a block. */
.el {
  background:    var(--el-bg,       var(--el-bg-default,       transparent));
  color:         var(--el-color,    var(--el-color-default,    inherit));
  border-radius: var(--el-radius,   var(--el-radius-default,   0px));
}
.el > :not(style) {
  padding:       var(--el-padding,  var(--el-padding-default,  0));
  border-radius: var(--el-radius,   var(--el-radius-default,   0px));
  box-shadow:    var(--el-shadow,   var(--el-shadow-default,   none));
}
/* Per-side padding overrides — emitted by ElementWrapper when the author
   sliders a single side (paddingTop / paddingRight / paddingBottom /
   paddingLeft). Each side wins over the `padding:` shorthand above (higher
   specificity: attr+class+type beats class+type) so the three unset sides
   keep falling through to --el-padding-default (renderer chrome), and the
   set side picks up the slider value. */
.el[style*="--el-padding-top:"]    > :not(style) { padding-top:    var(--el-padding-top); }
.el[style*="--el-padding-right:"]  > :not(style) { padding-right:  var(--el-padding-right); }
.el[style*="--el-padding-bottom:"] > :not(style) { padding-bottom: var(--el-padding-bottom); }
.el[style*="--el-padding-left:"]   > :not(style) { padding-left:   var(--el-padding-left); }

/* Top-level (parentId == null) elements bleed their --el-bg to the viewport
   edges via a pseudo-element. The wrapper itself sits inside <main> which
   caps width on most pages, so painting bg only on the wrapper leaves a
   gutter exposing the page bg. The pseudo is `position: absolute; left: 50%;
   width: 100vw; margin-left: -50vw` so it centers on the wrapper and spans
   the full viewport regardless of any ancestor max-width. z-index: -1 puts
   it behind content; pointer-events: none keeps clicks on the section.
   `:where(.el .el) { --el-bg: initial }` and leaf-class resets ensure the
   pseudo paints transparent on nested / leaf elements that don't carry a
   bg of their own. */
.el--top-level {
  position: relative;
}
.el--top-level::before {
  content: "";
  position: absolute;
  z-index: -1;
  top: 0;
  bottom: 0;
  left: 50%;
  width: 100vw;
  margin-left: -50vw;
  background: var(--el-bg, var(--el-bg-default, transparent));
  pointer-events: none;
}
/* Suppress the bleed for global-chrome elements that own their own bg
   plumbing (navbar uses fixed/sticky inner with opacity slider; footer
   already spans full width via its own renderer; loading screen is fixed). */
.el--top-level.el--navbar::before,
.el--top-level.el--footer::before,
.el--top-level.el--loading::before {
  content: none;
}

/* ── Nested-.el default reset (prevents ancestor chrome bleed) ──
 * CSS custom properties inherit down the DOM by default. Without this
 * block, a parent like `.el-testimonials { --el-padding-default: 6rem
 * 2rem }` (the section's own chrome) cascades into every nested `.el`
 * descendant — headings, rich-text, cards — and the `.el > :not(style)`
 * rule above then paints 6rem of vertical padding around each child,
 * blowing up their bounding boxes.
 *
 * Wrapping in `:where()` gives this rule specificity (0,0,0) so any
 * type-specific declaration — e.g. `.el-page-header { --el-padding-
 * default: clamp(...) }` at specificity (0,1,0) — still wins for
 * elements that legitimately want their own chrome. The declared
 * value on a nested `.el` also beats the inherited value from its
 * ancestor, so this local reset neutralizes the cascade without
 * blocking intentional per-type declarations. */
/* Reset BOTH the user-override (`--el-*`) AND the element-type default
   (`--el-*-default`) custom properties on every nested `.el`. Both sets
   inherit down the DOM by default, so an ancestor that emits
   `style="--el-padding: 24px"` (or a type that declares
   `--el-padding-default: 6rem`) would otherwise bleed that value into
   every descendant's `.el > :not(style)` rule and paint it around
   nested content.
   `initial` makes the custom property behave as if never declared on
   this element, so `var(--el-padding, var(--el-padding-default, 0))`
   walks its whole fallback chain against the CHILD's own declared
   defaults — not the ancestor's override. Inline `style="--el-padding:
   Xpx"` set by ElementWrapper on the child itself still wins (inline
   always beats CSS). */
:where(.el .el) {
  --el-padding: initial;
  --el-padding-top: initial;
  --el-padding-right: initial;
  --el-padding-bottom: initial;
  --el-padding-left: initial;
  --el-padding-default: 0;
  --el-bg: initial;
  --el-bg-default: transparent;
  --el-color: initial;
  --el-color-default: inherit;
  --el-radius: initial;
  --el-radius-default: 0px;
  --el-shadow: initial;
  --el-shadow-default: none;
}

/* Leaf text-content wrappers never carry their own chrome defaults —
   no padding, no background, no radius, no shadow. They're pure text
   and should inherit zero chrome regardless of where they're placed.
   Specificity (0,1,0) beats the :where(...) reset above (0,0,0) and
   beats any ancestor's inheritable --el-*-default. Design panel inline
   styles still win (always), and widget-specific rules declared later
   in the cascade can re-enable chrome for a specific context if
   intentional. */
.el--heading,
.el--rich-text,
.el--eyebrow,
.el--subheading,
.el--rating,
.el--button {
  --el-padding: initial;
  --el-padding-top: initial;
  --el-padding-right: initial;
  --el-padding-bottom: initial;
  --el-padding-left: initial;
  --el-padding-default: 0;
  --el-bg: initial;
  --el-bg-default: transparent;
  --el-color: initial;
  --el-color-default: inherit;
  --el-radius: initial;
  --el-radius-default: 0px;
  --el-shadow: initial;
  --el-shadow-default: none;
}
/* Stretched elements: apply bg to the wrapper itself so it spans full viewport width */
.el.el--stretched {
  background: var(--el-bg, transparent);
  color:      var(--el-color, inherit);
}

/* Flex-wrapper bridge. Container elements (supportsChildren) default to
   display:flex on the wrapper, but each .el has exactly one renderer-root
   as its direct child. In flex-direction: row (the default), a single
   flex item shrinks to its intrinsic content width — which leaves a
   100vw-stretched wrapper with a narrow section inside and empty bands
   beside it. `flex: 1 1 auto` + `min-width: 0` makes the renderer root
   fill the wrapper's main axis no matter the flex-direction; in column
   mode it's already the default stretch, so this is a no-op there. */
.el--flex > :not(style) {
  flex: 1 1 auto;
  min-width: 0;
}

/* Stretched ↔ Site-Container separation of concerns.
   `stretchFullWidth` ONLY drives the outer .el wrapper to 100vw so the
   section background paints edge-to-edge. Inner content width is governed
   exclusively by `siteContainerWidth` (default/narrow/wide/full) — pick
   'full' for edge-to-edge content. Previously a `.el--stretched > .el-site-container
   { max-width: 100% }` rule lived here and forcibly uncapped the inner
   whenever the outer was stretched, silently overriding whatever the user
   picked in the Content Width dropdown. Removed so the dropdown is the
   single source of truth for inner content width. */

/* ── Reset browser defaults ───────────────────────────────── */
html, body { margin: 0; padding: 0; }
/* `clip` (not `hidden`) — `overflow-x: hidden` on body breaks position:sticky
   on body's descendants in mobile Safari/Chrome. `clip` is non-scrolling so
   sticky stays anchored to the viewport. */
body { overflow-x: clip; }

/* Container-query bridge — paired with @container site style() rules
   throughout this file and other er-*.css / site-*.css files. The
   ResizeObserver in SiteContainerBridge keeps --site-bp in sync with
   viewport width. Default desktop so SSR renders the desktop layout
   first paint; the bridge swaps to mobile/tablet on mount.
   See .claude/plans/query/container-query-refactor.md.
   Mirrored in CriticalCss for above-fold paint. */
body {
  container-type: inline-size;
  container-name: site;
  --site-bp: desktop;
}
nextjs-portal,
[data-nextjs-toast],
[data-next-badge-root] {
  display: none !important;
}

/* ── Navbar ───────────────────────────────────────────────── */
.el--navbar {
  width: 100%;
  margin: 0;
  padding: 0;
  position: sticky;
  top: 0;
  z-index: 1000;
  /* The wrapper itself is never painted — the inner `.el-navbar` (or the
     `position:fixed` chrome for transparent-to-solid / floating / transparent
     variants) is the only visible bg layer. Without this, an `.el--stretched`
     navbar with `--el-bg: <site-primary>` (set by the inspector's Background
     Color field) paints a full-width band behind the nav at every breakpoint
     — invisible on desktop because the wrapper collapses to 0 height when
     the inner is fixed, but visible on mobile/tablet where the wrapper
     occupies layout, producing the navy "anchored bg" strip on Momentum. */
  background: transparent !important;
}
/* When the inner uses a floating variant (transparent-to-solid / floating /
   transparent), the inner is already `position:fixed` and removed from flow,
   so the wrapper should occupy zero vertical space — letting the page hero
   start at viewport top with the nav floating over it. Some browsers reserve
   a baseline line-box for the empty wrapper, producing a white strip below
   the pill on mobile. Forcing height: 0 + overflow: visible kills the strip
   while keeping the wrapper a real positioned box (preserving the inner's
   `position: fixed` containing-block behavior — `display: contents` worked
   on plain pages but broke sticky inside the builder iframe). */
.el--navbar:has(> .el-navbar--transparent-to-solid.el-navbar--sticky),
.el--navbar:has(> .el-navbar--floating),
.el--navbar:has(> .el-navbar--transparent) {
  height: 0;
  min-height: 0;
  overflow: visible;
}
.el-navbar {
  width: 100%;
  background: color-mix(in srgb, var(--navbar-header-bar-bg, var(--site-surface)) var(--navbar-header-bar-bg-opacity, 100%), transparent);
  border-bottom: 1px solid var(--navbar-header-bar-border-color, transparent);
  box-shadow: 0 4px 20px rgba(8,14,25, var(--navbar-header-bar-shadow-alpha, 0));
  backdrop-filter: blur(var(--navbar-header-bar-blur, 0px));
  -webkit-backdrop-filter: blur(var(--navbar-header-bar-blur, 0px));
  z-index: 100;
}
/* Universal "Background Opacity" slider bridge — wraps whatever --el-bg the
   user set (via the navbar's Background Color field) in color-mix() so the
   opacity control works on every variant (solid, dark, transparent,
   transparent-to-solid, floating). Specificity (0,2,0) beats `.el > :not(style)`
   (0,1,1) so this overrides ElementWrapper's flat --el-bg for the navbar. When
   no --navbar-bg-opacity is emitted (slider never touched) the default 100%
   keeps the existing fully-opaque behavior. */
.el--navbar > .el-navbar {
  background: color-mix(in srgb, var(--el-bg, var(--site-surface)) var(--navbar-bg-opacity, 100%), transparent);
  background-color: color-mix(in srgb, var(--el-bg, var(--site-surface)) var(--navbar-bg-opacity, 100%), transparent);
}
.el-navbar--sticky {
  position: sticky;
  top: 0;
}
/* When the transparent-to-solid variant is sticky, it pins via `position: fixed`
   (the floating-pill chrome lives on `.el-navbar__inner`). When sticky is
   toggled OFF, this rule is absent so the variant falls back to the static
   in-flow position from the base `.el-navbar` rule — and the wrapper
   height-collapse rule below also stops applying, restoring normal layout. */
.el-navbar--transparent-to-solid.el-navbar--sticky {
  position: fixed;
  top: 0;
  left: 0;
  right: var(--scrollbar-w, 0px);
  z-index: 1000;
}
.el-navbar__inner {
  padding-block: 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: nowrap;
  height: var(--navbar-height, 64px);
  gap: 1.4rem;
  min-width: 0;
}
/* Per-instance navbar pill width override. The contract's .el-site-container
   sets max-width to var(--site-max-width). Authors can break out of the
   site-wide token here with the inspector "Navbar Max Width" field — useful
   when the navbar pill should be wider/narrower than the rest of the site
   (e.g. 1600px navbar over a 1200px content column). Selector specificity
   (0,2,0) beats the contract's :where() (0,0,0). */
.el-navbar__inner.el-site-container {
  max-width: var(--el-navbar-max-width, var(--site-max-width, 1200px));
}
.el-navbar__logo {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  flex-shrink: 0;
  min-width: 0;
  max-width: min(34vw, var(--navbar-brand-max-width, 360px));
  /* Tap-target floor — the brand link wraps the wordmark/logo and is the
     site-home target. Was rendering 89×38 on mobile (one logical pixel
     short of the WCAG 2.5.5 minimum). Floor at 40px so it's always a
     reliable home tap. */
  min-height: 40px;
}
.el-navbar__logo-img {
  height: var(--navbar-logo-max-height, 36px);
  max-height: var(--navbar-logo-max-height, 36px);
  width: auto;
  max-width: var(--navbar-logo-max-width, 160px);
  display: block;
  object-fit: contain;
}
.el-navbar__logo-text {
  font-family: var(--site-font-heading);
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--site-primary);
  text-decoration: none;
}
.el-navbar__logo-placeholder {
  font-family: var(--site-font-heading);
  font-size: 1.125rem;
  font-weight: 700;
  color: var(--site-primary);
}
.el-navbar__links {
  display: flex;
  align-items: center;
  justify-content: center;
  flex: 1 1 auto;
  gap: var(--navbar-link-gap, 1.55rem);
  list-style: none;
  margin: 0;
  padding: 0;
  min-width: 0;
}
.el-navbar__link {
  font-size: var(--navbar-link-font-size, 0.9rem);
  font-weight: var(--navbar-link-font-weight, 600);
  letter-spacing: var(--navbar-link-letter-spacing, 0.035em);
  color: var(--navbar-link-color, var(--navbar-text, var(--site-text)));
  text-decoration: none;
  transition: color 0.15s ease, opacity 0.15s ease;
  /* Keep multi-word labels ("Resident Portal", "Get Started", "About Us") on
   * a single line. Without this, the label wraps inside its flex item and
   * the parent's width stays the same — which defeats the auto-breakpoint
   * detector (it watches scrollWidth on .el-navbar__inner). With nowrap the
   * link's full width contributes to scrollWidth, the detector fires, and
   * the navbar collapses to the hamburger menu when items truly don't fit. */
  white-space: nowrap;
}
/* Defend nav link colors against browser-default :visited / :focus / :active
   styles. Without these overrides, links a user has tapped before render in
   the browser's default visited-purple (or whatever the OS-level link color
   override is) and stop honoring the authored `--navbar-link-color` token.
   The :visited cascade is locked to inherit (CSS spec restricts what
   :visited can change to fg/bg/border-color, so inherit is the strongest
   reset), and :focus / :active fall through to the same token chain as the
   idle state so tabbing or pressing a link doesn't briefly flash a different
   color. Active-page styling keeps its dedicated --navbar-link-active token
   so authors can still emphasize the current page distinctly. */
.el-navbar__link:visited,
.el-navbar__dropdown-item:visited,
.el-navbar__dropdown-trigger:visited,
.er-radix-navmenu__link:visited,
.er-radix-navmenu__trigger:visited {
  color: inherit;
}
.el-navbar__link:focus,
.el-navbar__link:active {
  color: var(--navbar-link-color, var(--navbar-text, var(--site-text)));
}
.el-navbar__link--active,
.el-navbar__link[aria-current="page"] {
  color: var(--navbar-link-active, var(--navbar-link-color, var(--site-primary)));
}
.el-navbar__link:hover {
  color: var(--navbar-link-hover, var(--site-primary));
  background: var(--navbar-link-hover-bg, transparent);
}
.el-navbar__cta {
  flex-shrink: 0;
}
.el-navbar .el-navbar__cta--custom-spacing {
  padding: var(--el-btn-pad-y, 12px) var(--el-btn-pad-x, 24px) !important;
}
.el-navbar__cta:hover { opacity: 1; }
/* Nav CTA hover overrides now flow through the universal button contract:
   NavbarRenderer emits --el-btn-hover-bg / --el-btn-hover-text / --el-btn-hover-border
   on the anchor itself, and the shared .cta-btn--* / .site-btn--* rules in
   site-components.css + er-buttons.css consume them. This guarantees a
   theme-level change to btnPrimaryHoverBg / btnPrimaryHoverText updates every
   nav CTA simultaneously, while per-element overrides still shadow the theme. */

/* ── Navbar search: icon toggle + under-nav drawer ──────────────
   Inherits colour from nav link vars so it flips with scroll state.
   No hardcoded colours — everything flows through navbar CSS vars. */
.el-navbar__search-toggle {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--navbar-search-size, 38px);
  height: var(--navbar-search-size, 38px);
  padding: 0;
  margin: 0;
  background: var(--navbar-search-bg, transparent);
  border: var(--navbar-search-border-width, 1px) solid var(--navbar-search-border, transparent);
  border-radius: var(--navbar-search-radius, 999px);
  color: var(--navbar-search-color, var(--navbar-link-color, var(--navbar-text, var(--site-text))));
  cursor: pointer;
  transition: background 0.18s ease, color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
  -webkit-tap-highlight-color: transparent;
  /* See `.el-navbar__mobile-toggle` below for the rationale — same iOS Safari
     backdrop-filter quirk applies to the search-toggle pill. */
  position: relative;
  z-index: 2;
  touch-action: manipulation;
}
.el-navbar__search-toggle > svg {
  pointer-events: none;
}
.el-navbar__search-toggle:hover {
  background: var(--navbar-search-hover-bg, var(--navbar-link-hover-bg, color-mix(in srgb, var(--navbar-link-color, currentColor) 10%, transparent)));
  color: var(--navbar-search-hover-color, var(--navbar-link-hover, var(--site-primary)));
  border-color: var(--navbar-search-border-hover, color-mix(in srgb, var(--navbar-link-color, currentColor) 20%, transparent));
}
/* Search toggle follows the same scrolled-aware token cascade as nav links —
   --navbar-link-color-scrolled → --navbar-link-color → --navbar-text-scrolled
   → --site-text. !important parallels the .el-navbar--scrolled .el-navbar__link
   rule below so the [aria-expanded="true"] selector can't override the
   scroll-state colour with a stale --site-primary fallback against a white
   shell. */
.el-navbar--scrolled .el-navbar__search-toggle {
  color: var(--navbar-search-color-scrolled, var(--navbar-search-color, var(--navbar-link-color-scrolled, var(--navbar-link-color, var(--navbar-text-scrolled, var(--site-text)))))) !important;
  background: var(--navbar-search-bg-scrolled, var(--navbar-search-bg, transparent));
  border-color: var(--navbar-search-border-scrolled, var(--navbar-search-border, transparent));
}
.el-navbar--scrolled .el-navbar__search-toggle:hover {
  background: var(--navbar-search-hover-bg-scrolled, var(--navbar-search-hover-bg, var(--navbar-link-hover-bg-scrolled, var(--navbar-link-hover-bg, color-mix(in srgb, currentColor 10%, transparent)))));
  color: var(--navbar-search-hover-color-scrolled, var(--navbar-search-hover-color, var(--navbar-link-hover-scrolled, var(--navbar-link-hover, var(--site-primary))))) !important;
}
.el-navbar__search-toggle[aria-expanded="true"] {
  background: var(--navbar-search-open-bg, var(--navbar-search-hover-bg, var(--navbar-link-hover-bg, color-mix(in srgb, currentColor 12%, transparent))));
  color: var(--navbar-search-open-color, var(--navbar-search-hover-color, inherit));
  border-color: var(--navbar-search-open-border, var(--navbar-search-border-hover, transparent));
}
.el-navbar--scrolled .el-navbar__search-toggle[aria-expanded="true"] {
  color: var(--navbar-search-open-color, var(--navbar-search-hover-color-scrolled, var(--navbar-search-hover-color, inherit))) !important;
}
.el-navbar__search-toggle--mobile { display: inline-flex; }
.el-navbar__search-toggle--desktop { display: inline-flex; }

.el-navbar__search-drawer {
  position: relative;
  /* Sits below the navbar bar but BEHIND any open nav dropdown menu
     (.el-navbar__dropdown-menu z-index 520, .el-navbar__flyout-menu 530).
     Without an explicit low z-index here, backdrop-filter's stacking
     context lets the drawer cover dropdown menus that originate from
     siblings inside .el-navbar__inner. */
  z-index: 5;
  max-height: 0;
  overflow: hidden;
  width: 100%;
  /* Always use an opaque surface so the search panel reads as a distinct
     dropdown surface even when the navbar shell is transparent. Mirrors
     the --navbar-dropdown-* vocabulary used elsewhere. */
  background: var(--navbar-search-drawer-bg, var(--navbar-dropdown-bg, var(--site-surface)));
  color: var(--navbar-search-drawer-text, var(--navbar-dropdown-text, var(--site-text)));
  border-top: 1px solid var(--navbar-search-drawer-border, var(--site-border, color-mix(in srgb, currentColor 12%, transparent)));
  backdrop-filter: blur(var(--navbar-search-drawer-blur, var(--navbar-header-bar-blur, 0px)));
  -webkit-backdrop-filter: blur(var(--navbar-search-drawer-blur, var(--navbar-header-bar-blur, 0px)));
  transition: max-height 0.28s ease, opacity 0.2s ease, box-shadow 0.28s ease;
  opacity: 0;
  box-shadow: 0 0 0 rgba(0,0,0,0);
  pointer-events: none;
}
.el-navbar--scrolled .el-navbar__search-drawer {
  background: var(--navbar-search-drawer-bg, var(--navbar-dropdown-bg, var(--site-surface)));
}
.el-navbar__search-drawer--open {
  max-height: min(78vh, 640px);
  opacity: 1;
  pointer-events: auto;
  box-shadow: 0 18px 42px rgba(8, 14, 25, var(--navbar-search-drawer-shadow-alpha, 0)), var(--site-shadow-md);
  overflow-y: auto;
}
/* Custom themed scrollbar for the open drawer — colors flow from --site-accent
   and --site-surface so any builder theme-token edit automatically retints the
   scrollbar without per-element wiring. Scoped tightly to the drawer so it
   doesn't leak to other scrollable surfaces. */
.el-navbar__search-drawer::-webkit-scrollbar {
  width: 10px;
}
.el-navbar__search-drawer::-webkit-scrollbar-track {
  background: var(--site-surface);
}
.el-navbar__search-drawer::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--site-accent) 60%, transparent);
  border-radius: 999px;
  border: 2px solid var(--site-surface);
}
.el-navbar__search-drawer::-webkit-scrollbar-thumb:hover {
  background: var(--site-accent);
}
.el-navbar__search-drawer {
  scrollbar-width: thin;
  scrollbar-color: var(--site-accent) var(--site-surface);
}

/* Site-wide scrollbar — themed cyan-accent thumb on the public render so
   the preview / live tenant site doesn't fall back to the raw OS chrome.
   Gated behind `body:not(.is-builder-canvas)` so the builder iframe (which
   adds the .is-builder-canvas class in PreviewClient when `mode=builder`)
   keeps the browser default and doesn't compete with the canvas chrome's
   own scrollbar styling. Per-element opt-ins (.el-navbar__search-drawer
   above, .el-comparison__scroll-wrapper in er-content.css) keep their
   bespoke treatment by specificity. */
html:not(.is-builder-canvas) {
  scrollbar-width: thin;
  scrollbar-color: color-mix(in srgb, var(--site-accent, deepskyblue) 55%, transparent) transparent;
}
html:not(.is-builder-canvas)::-webkit-scrollbar {
  width: 12px;
  height: 12px;
}
html:not(.is-builder-canvas)::-webkit-scrollbar-track {
  background: transparent;
}
html:not(.is-builder-canvas)::-webkit-scrollbar-thumb {
  background: color-mix(in srgb, var(--site-accent, deepskyblue) 45%, transparent);
  border-radius: 999px;
  border: 3px solid transparent;
  background-clip: padding-box;
}
html:not(.is-builder-canvas)::-webkit-scrollbar-thumb:hover {
  background: color-mix(in srgb, var(--site-accent, deepskyblue) 80%, transparent);
  background-clip: padding-box;
}
html:not(.is-builder-canvas)::-webkit-scrollbar-corner {
  background: transparent;
}

/* Floating-shell variant: drawer sits attached UNDER the floating pill,
   matching the shell's horizontal inset and bottom radius so the two
   surfaces read as one continuous panel. Solid/dark/transparent variants
   keep the default full-width treatment above.
   Width tracks the .el-site-container that constrains .el-navbar__inner so
   the drawer's left/right edges line up flush with the pill above it. */
.el-navbar--floating .el-navbar__search-drawer,
.el-navbar--transparent-to-solid .el-navbar__search-drawer {
  width: 100%;
  /* Track the navbar pill's width so the drawer's left/right edges line up
     flush with the pill above. `.el-navbar__inner.el-site-container` uses the
     same `--el-navbar-max-width` → `--site-max-width` chain — mirroring it
     here keeps a per-instance `navMaxWidth` (e.g. 1200px pill on a 1680px
     site) from leaving the drawer wider than the pill. */
  max-width: var(--el-navbar-max-width, var(--site-max-width, 1280px));
  margin-top: calc(var(--navbar-shell-inset-bottom, 14px) * -1);
  margin-left: auto;
  margin-right: auto;
  padding-inline: var(--site-content-gutter, clamp(1rem, 4vw, 2rem));
  border-top: 0;
  border-radius: 0 0 var(--navbar-shell-radius, 24px) var(--navbar-shell-radius, 24px);
  background-clip: padding-box;
}
/* Drop the inner search-form's own gutter so the field aligns with the
   nav links inside the pill — the drawer itself now owns the gutter. */
.el-navbar--floating .el-navbar__search-drawer .el-navbar__search-form,
.el-navbar--transparent-to-solid .el-navbar__search-drawer .el-navbar__search-form {
  padding-inline: 0;
  max-width: none;
}
.el-navbar--floating .el-navbar__search-drawer--open,
.el-navbar--transparent-to-solid .el-navbar__search-drawer--open {
  border-radius: 0 0 var(--navbar-shell-radius, 24px) var(--navbar-shell-radius, 24px);
}
/* When the search drawer is open under the floating-shell variants, square off
   the bottom of the shell pill so it meets the drawer's flat top flush — without
   this override the shell's rounded bottom corners leave a bowtie-shaped gap on
   either side where the page background shows through. */
.el-navbar--floating:has(.el-navbar__search-drawer--open) .el-navbar__inner,
.el-navbar--transparent-to-solid:has(.el-navbar__search-drawer--open) .el-navbar__inner {
  border-bottom-left-radius: 0;
  border-bottom-right-radius: 0;
}
.el-navbar__search-form {
  max-width: var(--site-max-width, 1200px);
  margin: 0.9rem auto;
  padding: 0 var(--site-content-gutter, 24px);
  display: flex;
  align-items: center;
  gap: 0.65rem;
  color: var(--navbar-dropdown-text, var(--site-text));
}
.el-navbar--scrolled .el-navbar__search-form {
  color: var(--navbar-dropdown-text, var(--site-text));
}
/* Visible field treatment so the input reads as a proper control inside
   the dropdown surface, not as raw text on the page. */
.el-navbar__search-form > .el-navbar__search-icon,
.el-navbar__search-form > .el-navbar__search-input,
.el-navbar__search-form > .el-navbar__search-spinner,
.el-navbar__search-form > .el-navbar__search-kbd {
  /* children sit inside the field wrapper below */
}
/* 2026-modern search field — borderless soft pill, larger type, no focus
   ring at all. The drawer surface already reads as a control; layering a
   border around the input reads as legacy form chrome. */
.el-navbar__search-form {
  background: var(--navbar-search-input-bg, color-mix(in srgb, currentColor 5%, transparent));
  border: 0;
  border-radius: var(--navbar-search-input-radius, 999px);
  padding: 0.85rem 1.4rem;
  gap: 0.9rem;
  max-width: min(var(--site-max-width, 1200px), calc(100% - 2 * var(--site-content-gutter, 24px)));
  transition: background 0.2s ease;
}
.el-navbar__search-form:hover {
  background: var(--navbar-search-input-bg, color-mix(in srgb, currentColor 7%, transparent));
}
.el-navbar__search-form:focus-within {
  background: var(--navbar-search-input-focus-bg, var(--navbar-search-input-bg, color-mix(in srgb, currentColor 8%, transparent)));
  outline: none;
  box-shadow: none;
}
.el-navbar__search-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: currentColor;
  opacity: 0.55;
  flex-shrink: 0;
  margin-left: 1.35rem;
}
.el-navbar__search-form:focus-within .el-navbar__search-icon {
  opacity: 0.85;
}
.el-navbar__search-input {
  flex: 1 1 auto;
  min-width: 0;
  background: transparent;
  border: 0;
  outline: 0;
  padding: 0.35rem 0.15rem;
  font-size: var(--navbar-search-input-font-size, 1.0625rem);
  font-weight: 500;
  letter-spacing: -0.01em;
  color: var(--navbar-search-input-color, inherit);
  font-family: inherit;
}
.el-navbar__search-input:focus {
  outline: 0;
  box-shadow: none;
}
.el-navbar__search-input::placeholder {
  color: var(--navbar-search-input-placeholder, currentColor);
  opacity: var(--navbar-search-input-placeholder-opacity, 0.4);
  font-weight: 500;
}
.el-navbar__search-input::-webkit-search-cancel-button {
  -webkit-appearance: none;
  appearance: none;
}
.el-navbar__search-kbd {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.72rem;
  font-weight: 600;
  min-width: 26px;
  height: 26px;
  padding: 0 8px;
  border-radius: var(--navbar-search-kbd-radius, 8px);
  background: var(--navbar-search-kbd-bg, color-mix(in srgb, currentColor 9%, transparent));
  color: var(--navbar-search-kbd-color, inherit);
  opacity: 0.7;
  flex-shrink: 0;
  letter-spacing: 0;
}
.el-navbar__search-submit {
  flex-shrink: 0;
  padding: 0.55rem 1.15rem;
  border-radius: 999px;
  border: 0;
  background: var(--site-primary);
  color: var(--site-primary-fg);
  font-weight: 600;
  font-size: 0.9rem;
  cursor: pointer;
  transition: background 0.18s ease, transform 0.18s ease;
}
.el-navbar__search-submit:hover {
  background: color-mix(in srgb, var(--site-primary) 88%, var(--site-primary-fg, currentColor));
}
.el-navbar__search-spinner {
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 2px solid color-mix(in srgb, currentColor 25%, transparent);
  border-top-color: currentColor;
  animation: el-navbar-spin 0.7s linear infinite;
  flex-shrink: 0;
  opacity: 0.75;
}
@keyframes el-navbar-spin { to { transform: rotate(360deg); } }
@media (prefers-reduced-motion: reduce) {
  .el-navbar__search-spinner { animation: none; }
}

/* Inline close button — reads as an icon-button anchored INSIDE the search
   input pill (right edge), not a separate floating chip. Default background
   is transparent so the search-form's pill surface shows through; hover/focus
   reveal a soft tint as feedback. Mirrors the search-icon's "in-input" feel
   on the left, so the input row reads as one unified field. */
.el-navbar__search-close {
  flex-shrink: 0;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  /* Tap-target floor — was 28×28, well below WCAG 2.5.5 minimum.
     Bumped to 40×40 with the icon centered inside. */
  width: 40px;
  height: 40px;
  padding: 0;
  margin-left: 0.1rem;
  margin-right: 1.35rem;
  border-radius: 999px;
  border: 0;
  background: var(--navbar-search-close-bg, color-mix(in srgb, currentColor 9%, transparent));
  color: var(--navbar-search-close-color, currentColor);
  opacity: 0.55;
  cursor: pointer;
  transition: background 0.18s ease, opacity 0.18s ease, color 0.18s ease;
  -webkit-tap-highlight-color: transparent;
}
.el-navbar__search-close:hover {
  background: var(--navbar-search-close-hover-bg, color-mix(in srgb, currentColor 10%, transparent));
  opacity: 1;
}
.el-navbar__search-close:focus-visible {
  outline: 0;
  background: color-mix(in srgb, var(--site-accent, currentColor) 14%, transparent);
  opacity: 1;
}

/* ── Search results panel — 2026 bold + clean ─────────────────── */
.el-navbar__search-results {
  max-width: var(--site-max-width, 1200px);
  margin: 0 auto;
  padding: 0.5rem var(--site-content-gutter, 24px) 1.25rem;
  color: var(--navbar-dropdown-text, var(--site-text));
}
.el-navbar--scrolled .el-navbar__search-results {
  color: var(--navbar-dropdown-text, var(--site-text));
}
.el-navbar__search-hint {
  font-size: 0.95rem;
  font-weight: 500;
  letter-spacing: -0.005em;
  line-height: 1.55;
  opacity: 0.55;
  padding: 1rem 0.4rem 0.4rem;
}
.el-navbar__search-hint kbd { margin: 0 2px; }
.el-navbar__search-overview {
  font-size: 0.8125rem;
  font-weight: 600;
  letter-spacing: 0;
  text-transform: none;
  opacity: 0.5;
  padding: 0.6rem 0.4rem 0.85rem;
}
.el-navbar__search-overview strong {
  font-weight: 700;
  opacity: 1;
  color: var(--site-text, currentColor);
}
.el-navbar__search-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 0.35rem;
}
.el-navbar__search-result {
  display: grid;
  gap: 0.4rem;
  width: 100%;
  text-align: left;
  background: transparent;
  border: 0;
  border-radius: 16px;
  padding: 0.95rem 1.05rem;
  color: inherit;
  cursor: pointer;
  font: inherit;
  transition: background 0.18s ease, transform 0.18s ease;
}
.el-navbar__search-result:hover,
.el-navbar__search-result--active {
  background: var(--navbar-search-result-hover-bg, color-mix(in srgb, currentColor 7%, transparent));
  transform: translateX(2px);
}
.el-navbar__search-result-title {
  font-size: 1.0625rem;
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.3;
  word-break: break-word;
  overflow-wrap: break-word;
}
.el-navbar__search-result-meta {
  display: flex;
  align-items: center;
  gap: 0.65rem;
  font-size: 0.8125rem;
  opacity: 0.65;
}
.el-navbar__search-result-path {
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 0.78rem;
  font-weight: 500;
  opacity: 0.85;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  min-width: 0;
  flex: 1 1 auto;
}
.el-navbar__search-result-badge {
  flex-shrink: 0;
  font-size: 0.7rem;
  font-weight: 700;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  padding: 3px 10px;
  border-radius: 999px;
  /* Accent-tinted pill — flows from --site-accent so theme-token edits in
     the builder propagate automatically. No per-instance override needed.
     Borderless flat fill reads cleaner on bold cards than the legacy
     border+tint combo. */
  background: var(--navbar-search-result-badge-bg, color-mix(in srgb, var(--site-accent) 16%, transparent));
  color: var(--navbar-search-result-badge-color, var(--site-accent));
  border: 0;
  opacity: 1;
}
.el-navbar__search-result-snippet {
  font-size: 0.875rem;
  font-weight: 400;
  opacity: 0.7;
  line-height: 1.5;
  overflow-wrap: break-word;
  word-break: break-word;
  display: -webkit-box;
  -webkit-line-clamp: 2;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.el-navbar__search-mark {
  background: var(--navbar-search-mark-bg, color-mix(in srgb, var(--site-accent, var(--site-primary)) 22%, transparent));
  color: inherit;
  padding: 1px 4px;
  border-radius: 5px;
  font-weight: 700;
}
/* was @media(max-width:640px); bucketed to mobile (640 ≤ 768) */
@container site style(--site-bp: mobile) {
  .el-navbar__search-form {
    margin: 0.75rem 1rem;
    padding: 0.7rem 1.05rem;
    gap: 0.65rem;
    max-width: calc(100% - 2rem);
  }
  .el-navbar__search-input {
    font-size: 1rem;
  }
  .el-navbar__search-results {
    padding: 0.5rem 1rem 1.25rem;
  }
  .el-navbar__search-kbd { display: none; }
  .el-navbar__search-result {
    padding: 0.85rem 0.9rem;
    border-radius: 14px;
  }
  .el-navbar__search-result-title { font-size: 1rem; }
  .el-navbar__search-result-path { font-size: 0.72rem; }
}
@media (max-width: 640px) {
  .el-navbar__search-form {
    margin: 0.75rem 1rem;
    padding: 0.7rem 1.05rem;
    gap: 0.65rem;
    max-width: calc(100% - 2rem);
  }
  .el-navbar__search-input {
    font-size: 1rem;
  }
  .el-navbar__search-results {
    padding: 0.5rem 1rem 1.25rem;
  }
  .el-navbar__search-kbd { display: none; }
  .el-navbar__search-result {
    padding: 0.85rem 0.9rem;
    border-radius: 14px;
  }
  .el-navbar__search-result-title { font-size: 1rem; }
  .el-navbar__search-result-path { font-size: 0.72rem; }
}

.el-navbar__mobile-actions {
  display: none;
  align-items: center;
  gap: 0.5rem;
  margin-left: auto;
  flex-shrink: 0;
}
.el-navbar__links .el-navbar__cta--menu {
  display: none !important;
}
.el-navbar__mobile-toggle {
  display: none;
  /* Hamburger inherits the same visual treatment as the search toggle so the
     two mobile actions read as one cluster. Defaults to a transparent pill
     with an accent-colored outline (modern outline style); authors can
     override per-pill via --navbar-mobile-action-*. The search-toggle vars
     stay in the fallback chain for themes (e.g. Momentum's gold accent)
     that already wired the search pill to a brand colour. */
  background: var(--navbar-mobile-action-bg, var(--navbar-search-bg, transparent));
  border: var(--navbar-search-border-width, 1px) solid var(--navbar-mobile-action-border, var(--navbar-search-border, var(--site-accent, var(--site-primary, currentColor))));
  /* Mobile action size + radius unify the hamburger and the search toggle so
     the two pills always read at the same visual weight. Authors can swap
     the size token via the "Mobile Action Size" inspector control; the
     radius can be turned square via "Mobile Action Radius". */
  border-radius: var(--navbar-mobile-action-radius, var(--navbar-search-radius, 999px));
  cursor: pointer;
  width: var(--navbar-mobile-action-size, var(--navbar-search-size, 46px));
  height: var(--navbar-mobile-action-size, var(--navbar-search-size, 46px));
  padding: 0;
  color: var(--navbar-mobile-action-color, var(--navbar-search-color, var(--site-accent, var(--site-primary, currentColor))));
  align-items: center;
  justify-content: center;
  -webkit-tap-highlight-color: transparent;
  box-shadow: none;
  flex-shrink: 0;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
  /* Stacking + touch reliability fix (mobile, scrolled state):
     1. position:relative + z-index ensures the toggle always sits above any
        scrolled-state pseudo-element / sibling overlay inside the inner
        shell. Without an explicit z-index the open drawer's backdrop-filter
        stacking context could float a sibling above the toggle on iOS.
     2. touch-action:manipulation removes the 300ms double-tap-zoom delay AND
        prevents iOS Safari from swallowing the tap when the parent
        .el-navbar__inner has `backdrop-filter` (a known WebKit quirk where
        backdrop-filter ancestors intermittently block synthetic click events
        on interactive descendants). */
  position: relative;
  z-index: 2;
  touch-action: manipulation;
}
/* The hamburger SPAN and its bar SPANs are purely visual. Letting them be
   pointer-event targets means a tap that lands on a bar (the visible part
   the user actually aims at) registers `event.target` as the SPAN, not the
   BUTTON. Normally the click still bubbles to the BUTTON's React handler,
   but on iOS Safari with a `backdrop-filter` ancestor (the scrolled-state
   inner shell uses blur(22px)) the synthetic click on the inner SPAN can be
   dropped while the equivalent tap on the BUTTON's padding succeeds. Making
   these `pointer-events:none` forces every tap to hit the BUTTON directly
   so React's onClick fires reliably in the scrolled state. */
.el-navbar__hamburger,
.el-navbar__hamburger span {
  pointer-events: none;
}

/* Mobile-shell CTA — compact pill rendered inside `.el-navbar__mobile-actions`
   alongside the hamburger. Hidden on desktop (the regular --desktop CTA owns
   that layout). On mobile it inherits the navbar mobile-action sizing tokens
   so it visually matches the hamburger pill height.
   `!important` mirrors the `.el-navbar__cta--desktop` hide rule below — needed
   because `.cta-btn { display: inline-flex }` (in er-content.css /
   site-components.css) ties on specificity AND loads later, so a plain
   `display: none` here is silently overridden and the CTA renders twice
   (once as desktop, once as mobile-shell). */
.el-navbar__cta--mobile-shell,
.el-navbar .el-navbar__cta--mobile-shell { display: none !important; }
@container site style(--site-bp: mobile) {
  .el-navbar__cta--mobile-shell,
  .el-navbar .el-navbar__cta--mobile-shell {
    display: inline-flex !important;
    align-items: center;
    height: var(--navbar-mobile-action-size, 46px);
    padding-inline: 14px;
    border-radius: var(--navbar-mobile-action-radius, 999px);
    font-size: 13px;
    line-height: 1;
    white-space: nowrap;
    flex-shrink: 0;
  }
}
@media (max-width: 768px) {
  .el-navbar__cta--mobile-shell,
  .el-navbar .el-navbar__cta--mobile-shell {
    display: inline-flex !important;
    align-items: center;
    height: var(--navbar-mobile-action-size, 46px);
    padding-inline: 14px;
    border-radius: var(--navbar-mobile-action-radius, 999px);
    font-size: 13px;
    line-height: 1;
    white-space: nowrap;
    flex-shrink: 0;
  }
}
/* Builder-canvas mobile preview / breakpoint-class mode — when the navbar
   forces "mobile mode" via `--bp-640` / `--bp-900` / `--bp-1024` (i.e. the
   author dropped the desktop layout below the viewport-768 cutoff), surface
   the shell CTA in those modes too so it stays visible while the desktop CTA
   is hidden. Without this the shell CTA hides at viewport>768px even when
   the navbar is rendering its mobile cluster, leaving only the hamburger.
   Pairs with `.el-navbar--bp-* .el-navbar__cta--desktop { display: none }`
   already on lines below. */
.el-navbar--bp-640 .el-navbar__cta--mobile-shell,
.el-navbar--bp-900 .el-navbar__cta--mobile-shell,
.el-navbar--bp-1024 .el-navbar__cta--mobile-shell,
.el-navbar--overflow .el-navbar__cta--mobile-shell {
  display: inline-flex !important;
  align-items: center;
  height: var(--navbar-mobile-action-size, 46px);
  padding-inline: 14px;
  border-radius: var(--navbar-mobile-action-radius, 999px);
  font-size: 13px;
  line-height: 1;
  white-space: nowrap;
  flex-shrink: 0;
}
.el-navbar__mobile-toggle:hover {
  background: var(--navbar-mobile-action-hover-bg, var(--navbar-search-hover-bg, color-mix(in srgb, var(--site-primary) 88%, var(--site-primary-fg, transparent))));
  border-color: var(--navbar-mobile-action-hover-border, var(--navbar-search-border-hover, color-mix(in srgb, var(--site-primary) 88%, var(--site-primary-fg, transparent))));
  color: var(--navbar-mobile-action-hover-color, var(--navbar-search-hover-color, var(--site-primary-fg)));
}
.el-navbar__mobile-toggle[aria-expanded="true"] {
  background: var(--navbar-mobile-action-open-bg, var(--navbar-search-open-bg, color-mix(in srgb, var(--site-primary-fg) 18%, var(--site-primary))));
  border-color: var(--navbar-mobile-action-open-border, var(--navbar-search-open-border, color-mix(in srgb, var(--site-primary-fg) 24%, var(--site-primary))));
  color: var(--navbar-mobile-action-open-color, var(--navbar-search-open-color, var(--site-primary-fg)));
}
.el-navbar__hamburger {
  position: relative;
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 4px;
  width: 18px;
  height: 18px;
}
.el-navbar__hamburger span {
  display: block;
  width: 18px;
  height: 2px;
  border-radius: 999px;
  background: currentColor;
  transform-origin: center;
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.el-navbar__hamburger.is-open span:nth-child(1) {
  transform: translateY(6px) rotate(45deg);
}
.el-navbar__hamburger.is-open span:nth-child(2) {
  opacity: 0;
}
.el-navbar__hamburger.is-open span:nth-child(3) {
  transform: translateY(-6px) rotate(-45deg);
}
@container site style(--site-bp: mobile) {
  .el-navbar__inner {
    gap: 0.75rem;
    position: relative;
  }
  .el-navbar__links { display: none; }
  /* !important so the .site-btn { display:inline-flex } base rule can't
     re-show the desktop CTA on mobile. (Previously scoped under
     `.el-navbar__links` when the desktop CTA was a child of it; the CTA
     now renders as a sibling of `__links` so the scope is removed.) */
  .el-navbar__cta--desktop,
  .el-navbar__inner > .el-navbar__cta--desktop,
  .el-navbar .el-navbar__cta--desktop { display: none !important; }
  .el-navbar__search-toggle--desktop,
  .el-navbar .el-navbar__search-toggle--desktop { display: none !important; }
  .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; align-items: center; }
  .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  /* Equalize mobile action buttons — search toggle must match the hamburger
     pill (same width/height/radius/border). Without this the search icon
     reads as a smaller secondary affordance, breaking visual rhythm. Tokens
     fall back to the same defaults the mobile-toggle uses. */
  .el-navbar__mobile-actions .el-navbar__search-toggle {
    width: var(--navbar-mobile-action-size, 46px);
    height: var(--navbar-mobile-action-size, 46px);
    border-radius: var(--navbar-mobile-action-radius, 999px);
  }
  .el-navbar__mobile-actions .el-navbar__search-toggle svg {
    width: 18px;
    height: 18px;
  }
  .el-navbar__logo { min-width: 0; flex-shrink: 1; }
  .el-navbar__brand-name {
    font-size: 0.95rem;
    max-width: min(60vw, 280px);
  }
  /* Mobile default: hide brand text — logo-only header. Opt back in
     by enabling "Show Brand Name on Mobile" in the navbar settings. */
  .el-navbar__brand-name:not(.el-navbar__brand-name--mobile-visible) {
    display: none;
  }
  /* When shown on mobile, never truncate — wrap onto a second line and
     drop the desktop ellipsis cap entirely. Word-break stays normal so
     "Momentum Management" wraps as `Momentum / Management`, never mid-word. */
  .el-navbar__brand-name.el-navbar__brand-name--mobile-visible {
    display: inline-block;
    max-width: none;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: break-word;
    word-break: normal;
    line-height: 1.15;
  }
}
@media (max-width: 768px) {
  .el-navbar__inner {
    gap: 0.75rem;
    position: relative;
  }
  .el-navbar__links { display: none; }
  /* !important so the .site-btn { display:inline-flex } base rule can't
     re-show the desktop CTA on mobile. (Previously scoped under
     `.el-navbar__links` when the desktop CTA was a child of it; the CTA
     now renders as a sibling of `__links` so the scope is removed.) */
  .el-navbar__cta--desktop,
  .el-navbar__inner > .el-navbar__cta--desktop,
  .el-navbar .el-navbar__cta--desktop { display: none !important; }
  .el-navbar__search-toggle--desktop,
  .el-navbar .el-navbar__search-toggle--desktop { display: none !important; }
  .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; align-items: center; }
  .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  /* Equalize mobile action buttons — search toggle must match the hamburger
     pill (same width/height/radius/border). Without this the search icon
     reads as a smaller secondary affordance, breaking visual rhythm. Tokens
     fall back to the same defaults the mobile-toggle uses. */
  .el-navbar__mobile-actions .el-navbar__search-toggle {
    width: var(--navbar-mobile-action-size, 46px);
    height: var(--navbar-mobile-action-size, 46px);
    border-radius: var(--navbar-mobile-action-radius, 999px);
  }
  .el-navbar__mobile-actions .el-navbar__search-toggle svg {
    width: 18px;
    height: 18px;
  }
  .el-navbar__logo { min-width: 0; flex-shrink: 1; }
  .el-navbar__brand-name {
    font-size: 0.95rem;
    max-width: min(60vw, 280px);
  }
  /* Mobile default: hide brand text — logo-only header. Opt back in
     by enabling "Show Brand Name on Mobile" in the navbar settings. */
  .el-navbar__brand-name:not(.el-navbar__brand-name--mobile-visible) {
    display: none;
  }
  /* When shown on mobile, never truncate — wrap onto a second line and
     drop the desktop ellipsis cap entirely. Word-break stays normal so
     "Momentum Management" wraps as `Momentum / Management`, never mid-word. */
  .el-navbar__brand-name.el-navbar__brand-name--mobile-visible {
    display: inline-block;
    max-width: none;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: break-word;
    word-break: normal;
    line-height: 1.15;
  }
}

/* ── Mobile drawer interior styling ─────────────────────────────
   The .el-navbar__links--open class is the trigger — it's only ever
   set when the drawer is open, regardless of viewport. So these
   rules live at file scope (not inside a @media query) so they apply
   correctly at every drawer-active width: 360, 768, 900, 1024+ when
   mobileBreakpoint is set higher OR --overflow class is active.

   Open drawer frame layout (position/inset/zIndex/background/display)
   is applied via inline styles in NavbarRenderer.tsx — see commit
   notes. We intentionally do NOT redeclare those frame properties
   here so there's no cascade fight in scrolled-state on iOS Safari.
   Only the interior layout + typography lives in CSS. */
/* Drawer scroll lives on the inner <nav> so the sticky header + footer CTA
   tray stay pinned. Scrollbar tokens inherit from the site-wide rules at
   the top of this file (--site-accent on --site-surface), so the drawer
   automatically picks up the active theme's scrollbar. */

/* Drawer surface — defaults to the page surface (--site-bg → --site-surface),
   NOT the brand-primary accent. A full-bleed mobile takeover painted in the
   brand accent (typically a saturated cyan/teal/orange) drowns out CTAs and
   reads as broken on dark-SaaS palettes. Sites that genuinely want a brand-
   colored drawer set --navbar-drawer-bg explicitly via the design panel.
   Do NOT chain through --navbar-dropdown-* here: those are desktop-popover
   tokens (often white-on-colored-navbar) and don't apply to the full pane. */
.el-navbar__links--open {
  background: var(--navbar-drawer-bg, var(--site-bg, var(--site-surface, var(--site-primary, currentColor)))) !important;
  color: var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, inherit))) !important;
  /* The drawer Content carries both `.el-navbar__links` (desktop row layout)
     AND `.el-navbar__links--open` (open drawer). The desktop rule sets
     `align-items: center`, which on a flex-column collapses children to
     content width on the cross axis. Force stretch so nav/li/link rows
     fill the full drawer width. */
  align-items: stretch !important;
  justify-content: flex-start !important;
}

/* Drawer header — brand label on the LEFT, X close on the RIGHT.
   Sticky so it remains visible while the link body scrolls. */
.el-navbar__links--open .el-navbar__drawer-header {
  position: sticky;
  top: 0;
  display: flex !important;
  align-items: center;
  justify-content: space-between !important;
  width: 100%;
  padding: 1.1rem 1.25rem;
  margin: 0 0 0.25rem 0;
  background: inherit;
  border-bottom: 1px solid var(--navbar-drawer-divider, color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 12%, transparent));
  z-index: 2;
}
.el-navbar__links--open .el-navbar__drawer-title {
  font-family: var(--site-font-heading, var(--site-font-body, inherit));
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 75%, transparent);
  margin: 0;
}
.el-navbar__links--open .el-navbar__drawer-brand {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  text-decoration: none;
  color: var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor)));
  min-width: 0;
}
.el-navbar__links--open .el-navbar__drawer-brand-img {
  display: block;
  flex-shrink: 0;
}
.el-navbar__links--open .el-navbar__drawer-brand-name {
  font-family: var(--site-font-heading, var(--site-font-body, inherit));
  font-size: 1.05rem;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor)));
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
/* Close button — visible circular chip by default (NOT transparent).
   Fill is a soft tint of the drawer text color so it reads as tappable
   on every theme. Author can override via --navbar-drawer-close-*. */
.el-navbar__links--open .el-navbar__drawer-close {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--navbar-drawer-close-size, 44px);
  height: var(--navbar-drawer-close-size, 44px);
  margin-left: auto;
  border: 0;
  background: var(--navbar-drawer-close-bg, color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 10%, transparent));
  color: var(--navbar-drawer-close-color, currentColor);
  border-radius: var(--navbar-drawer-close-radius, 999px);
  cursor: pointer;
  transition: background 160ms ease, color 160ms ease, transform 160ms ease;
  flex-shrink: 0;
}
.el-navbar__links--open .el-navbar__drawer-close:hover,
.el-navbar__links--open .el-navbar__drawer-close:focus-visible {
  background: var(--navbar-drawer-close-hover-bg, color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 22%, transparent));
  color: var(--site-accent, currentColor);
  outline: none;
  transform: scale(1.04);
}

/* Drawer scroll container is the nav — defer scrollbar styling to the
   site-wide ::-webkit-scrollbar rules at the top of this file so it matches
   the active theme. */

/* Page scroll while the drawer is open is locked by the navbar's
   Headless UI Dialog (it sets inert + scroll-lock on <html> as part of
   its modal behavior). No CSS-only fallback is wired up — if the
   drawer ever switches off Headless UI, restore a body-attribute
   scroll-lock here AND emit the attribute from the renderer. */

/* Top-level link rows: full-width, large, generous tap area, divider. */
.el-navbar__links--open .el-navbar__link,
.el-navbar__links--open .el-navbar__dropdown-trigger {
  width: 100%;
  display: flex !important;
  align-items: center;
  justify-content: space-between !important;
  padding: var(--navbar-drawer-link-padding-y, 18px) var(--navbar-drawer-link-padding-x, 24px) !important;
  border-radius: 0;
  font-family: var(--site-font-heading, var(--site-font-body, inherit));
  font-size: var(--navbar-drawer-link-size, 20px) !important;
  font-weight: 600 !important;
  line-height: 1.25;
  color: var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) !important;
  background: transparent;
  border-bottom: 1px solid var(--navbar-drawer-divider, color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 8%, transparent));
  text-decoration: none;
  transition: background 160ms ease, color 160ms ease;
}
/* Alignment override — drives both label position and chevron behavior. */
.el-navbar__links--open[data-link-align="center"] .el-navbar__link,
.el-navbar__links--open[data-link-align="center"] .el-navbar__dropdown-trigger {
  justify-content: center !important;
  text-align: center;
}
.el-navbar__links--open[data-link-align="center"] .el-navbar__dropdown-trigger > .el-navbar__label {
  flex: 0 1 auto;
}
.el-navbar__links--open .el-navbar__link:hover,
.el-navbar__links--open .el-navbar__dropdown-trigger:hover,
.el-navbar__links--open .el-navbar__dropdown--open > .el-navbar__dropdown-trigger {
  background: color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 8%, transparent);
  color: var(--site-accent, var(--navbar-dropdown-hover-text, currentColor)) !important;
}

/* Drawer footer — pinned tray below the scrolling nav. Full-width filled
   buttons by default. The drawer Content is a flex column with the nav as
   the only scrolling child, so the footer sits naturally at the bottom
   without needing `position: sticky`. */
.el-navbar__links--open .el-navbar__drawer-footer {
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  padding: 1rem 1.25rem max(1rem, env(safe-area-inset-bottom));
  background: inherit;
  border-top: 1px solid var(--navbar-drawer-divider, color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 12%, transparent));
}
.el-navbar__links--open .el-navbar__cta--menu {
  /* Full-width tap target; button styling still flows through cta-btn--*. */
  width: 100%;
  justify-content: center;
}
/* When the author opts to force a variant on the drawer footer (default
   = primary), wire the universal --el-btn-* contract to the site button
   tokens for that variant so the CTA picks up the theme's filled fill
   even if its own variant prop says "outline". */
.el-navbar__links--open[data-cta-variant="primary"] .el-navbar__cta--menu {
  --el-btn-bg: var(--site-btn-primary-bg, var(--site-accent, currentColor));
  --el-btn-text: var(--site-btn-primary-text, var(--site-primary-fg, currentColor));
  --el-btn-border: var(--site-btn-primary-border, var(--site-btn-primary-bg, var(--site-accent, currentColor)));
  --el-btn-hover-bg: var(--site-btn-primary-hover-bg, color-mix(in srgb, var(--site-accent, currentColor) 88%, var(--site-primary-fg, transparent)));
  --el-btn-hover-text: var(--site-btn-primary-hover-text, var(--site-primary-fg, currentColor));
  --el-btn-hover-border: var(--site-btn-primary-hover-border, var(--site-btn-primary-hover-bg, var(--site-accent, currentColor)));
}
.el-navbar__links--open[data-cta-variant="secondary"] .el-navbar__cta--menu {
  --el-btn-bg: var(--site-btn-secondary-bg, var(--site-surface, transparent));
  --el-btn-text: var(--site-btn-secondary-text, var(--site-text, currentColor));
  --el-btn-border: var(--site-btn-secondary-border, var(--site-btn-secondary-bg, var(--site-surface, transparent)));
}
.el-navbar__links--open[data-cta-variant="outline"] .el-navbar__cta--menu {
  --el-btn-bg: transparent;
  --el-btn-text: var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor)));
  --el-btn-border: currentColor;
}
.el-navbar__links--open .el-navbar__link--active,
.el-navbar__links--open .el-navbar__link[aria-current="page"] {
  color: var(--site-accent, var(--navbar-dropdown-active-text, currentColor)) !important;
}
/* Suppress desktop underline-pseudo on active top-level links. */
.el-navbar__links--open .el-navbar__link--active::after {
  display: none;
}

/* Submenu container: indented, lightly shaded so it reads as nested. */
.el-navbar__links--open .el-navbar__dropdown,
.el-navbar__links--open .el-navbar__flyout {
  width: 100%;
}
.el-navbar__links--open .el-navbar__dropdown-menu,
.el-navbar__links--open .el-navbar__flyout-menu {
  background: color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 4%, transparent);
}
.el-navbar__links--open .el-navbar__dropdown-item {
  width: 100%;
  padding: 0.85rem 1.5rem 0.85rem 2.5rem !important;
  border-radius: 0;
  font-family: var(--site-font-body, inherit);
  font-size: 1rem !important;
  font-weight: 500 !important;
  line-height: 1.3;
  color: color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 85%, transparent) !important;
  background: transparent;
  border-bottom: 1px solid color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 5%, transparent);
  white-space: normal;
  text-decoration: none;
  box-shadow: none;
}
.el-navbar__links--open .el-navbar__dropdown-item:hover {
  background: color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 8%, transparent);
  color: var(--site-accent, var(--navbar-dropdown-hover-text, currentColor)) !important;
}
.el-navbar__links--open .el-navbar__dropdown-item[aria-current="page"],
.el-navbar__links--open .el-navbar__dropdown-item--active {
  color: var(--site-accent, var(--navbar-dropdown-active-text, currentColor)) !important;
  background: transparent;
  box-shadow: none;
}

/* Force Radix NavigationMenu list to stack vertically inside the drawer.
   Specificity beats the unscoped `.er-radix-navmenu__list` rule in
   er-radix.css. */
.el-navbar__links--open .el-navbar__menu {
  width: 100%;
  align-items: stretch;
  flex: 1 1 auto;
}
.el-navbar__links--open .er-radix-navmenu__list,
.el-navbar__links--open .el-navbar__menu-list {
  display: flex !important;
  flex-direction: column !important;
  align-items: stretch !important;
  width: 100%;
  gap: 0 !important;
  padding: 0 !important;
  margin: 0 !important;
  list-style: none;
}
.el-navbar__links--open .er-radix-navmenu__list > li,
.el-navbar__links--open .el-navbar__menu-list > li {
  width: 100%;
}
.el-navbar__links--open .er-radix-navmenu__trigger {
  width: 100%;
  justify-content: space-between;
}

/* Footer CTA row — the menu CTAs render at the END of the scrollable
   nav (inside the same scroll container) so on tall menus they reach
   them by scrolling instead of getting clipped behind the system nav
   bar / safe area. Plain margin spacing — no sticky positioning. */
.el-navbar__links--open .el-navbar__cta--menu {
  display: inline-flex !important;
  align-items: center;
  justify-content: center;
  width: calc(100% - 2.5rem);
  min-height: 48px;
  margin: 0.5rem 1.25rem 0;
  padding: 0.95rem 1.25rem;
  border-radius: 999px;
  font-family: var(--site-font-heading, var(--site-font-body, inherit));
  font-size: 0.95rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-align: center;
}
.el-navbar__links--open .el-navbar__cta--menu:last-child {
  margin-bottom: max(1.25rem, env(safe-area-inset-bottom));
}
.el-navbar__links--open .el-navbar__drawer-footer {
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  padding-top: 0.75rem;
  margin-top: 0.5rem;
  border-top: 1px solid var(--navbar-drawer-divider, color-mix(in srgb, var(--navbar-drawer-text, var(--site-text, var(--site-primary-fg, currentColor))) 12%, transparent));
}

/* ── Mobile breakpoint overrides (Cluster A1) ──────────────────
   CSS doesn't support custom properties inside @media queries, so
   the builder's `mobileBreakpoint` setting is implemented via a flag
   class on the navbar root (.el-navbar--bp-640 / --bp-900 / --bp-1024)
   that scopes a sibling media query to the chosen width.
   The default 768px block above is untouched so any site that has
   not set the field keeps today's behavior.
   ============================================================ */
/* was @media(max-width:640px); bucketed to mobile (640 ≤ 768) */
@container site style(--site-bp: mobile) {
  .el-navbar--bp-640 .el-navbar__inner {
    gap: 0.75rem;
    position: relative;
  }
  .el-navbar--bp-640 .el-navbar__links { display: none; }
  .el-navbar--bp-640 .el-navbar__cta--desktop,
  .el-navbar--bp-640 .el-navbar__inner > .el-navbar__cta--desktop,
  .el-navbar.el-navbar--bp-640 .el-navbar__cta--desktop { display: none !important; }
  .el-navbar--bp-640 .el-navbar__search-toggle--desktop,
  .el-navbar.el-navbar--bp-640 .el-navbar__search-toggle--desktop { display: none !important; }
  .el-navbar--bp-640 .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; }
  .el-navbar--bp-640 .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  /* Open drawer frame styles are inline in NavbarRenderer.tsx — no CSS here. */
  .el-navbar--bp-640 .el-navbar__links--open .el-navbar__cta--menu {
    display: inline-flex !important;
  }
}
@media (max-width: 640px) {
  .el-navbar--bp-640 .el-navbar__inner {
    gap: 0.75rem;
    position: relative;
  }
  .el-navbar--bp-640 .el-navbar__links { display: none; }
  .el-navbar--bp-640 .el-navbar__cta--desktop,
  .el-navbar--bp-640 .el-navbar__inner > .el-navbar__cta--desktop,
  .el-navbar.el-navbar--bp-640 .el-navbar__cta--desktop { display: none !important; }
  .el-navbar--bp-640 .el-navbar__search-toggle--desktop,
  .el-navbar.el-navbar--bp-640 .el-navbar__search-toggle--desktop { display: none !important; }
  .el-navbar--bp-640 .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; }
  .el-navbar--bp-640 .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  /* Open drawer frame styles are inline in NavbarRenderer.tsx — no CSS here. */
  .el-navbar--bp-640 .el-navbar__links--open .el-navbar__cta--menu {
    display: inline-flex !important;
  }
}
/* was @media(max-width:900px); bucketed to mobile+tablet (768 < 900 ≤ 1024) */
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-navbar--bp-900 .el-navbar__inner {
    gap: 0.75rem;
    position: relative;
  }
  .el-navbar--bp-900 .el-navbar__links { display: none; }
  .el-navbar--bp-900 .el-navbar__cta--desktop,
  .el-navbar--bp-900 .el-navbar__inner > .el-navbar__cta--desktop,
  .el-navbar.el-navbar--bp-900 .el-navbar__cta--desktop { display: none !important; }
  .el-navbar--bp-900 .el-navbar__search-toggle--desktop,
  .el-navbar.el-navbar--bp-900 .el-navbar__search-toggle--desktop { display: none !important; }
  .el-navbar--bp-900 .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; }
  .el-navbar--bp-900 .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  /* Open drawer frame styles are inline in NavbarRenderer.tsx — no CSS here. */
  .el-navbar--bp-900 .el-navbar__links--open .el-navbar__cta--menu {
    display: inline-flex !important;
  }
}
@media (max-width: 900px) {
  .el-navbar--bp-900 .el-navbar__inner {
    gap: 0.75rem;
    position: relative;
  }
  .el-navbar--bp-900 .el-navbar__links { display: none; }
  .el-navbar--bp-900 .el-navbar__cta--desktop,
  .el-navbar--bp-900 .el-navbar__inner > .el-navbar__cta--desktop,
  .el-navbar.el-navbar--bp-900 .el-navbar__cta--desktop { display: none !important; }
  .el-navbar--bp-900 .el-navbar__search-toggle--desktop,
  .el-navbar.el-navbar--bp-900 .el-navbar__search-toggle--desktop { display: none !important; }
  .el-navbar--bp-900 .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; }
  .el-navbar--bp-900 .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  /* Open drawer frame styles are inline in NavbarRenderer.tsx — no CSS here. */
  .el-navbar--bp-900 .el-navbar__links--open .el-navbar__cta--menu {
    display: inline-flex !important;
  }
}
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-navbar--bp-1024 .el-navbar__inner {
    gap: 0.75rem;
    position: relative;
  }
  .el-navbar--bp-1024 .el-navbar__links { display: none; }
  .el-navbar--bp-1024 .el-navbar__cta--desktop,
  .el-navbar--bp-1024 .el-navbar__inner > .el-navbar__cta--desktop,
  .el-navbar.el-navbar--bp-1024 .el-navbar__cta--desktop { display: none !important; }
  .el-navbar--bp-1024 .el-navbar__search-toggle--desktop,
  .el-navbar.el-navbar--bp-1024 .el-navbar__search-toggle--desktop { display: none !important; }
  .el-navbar--bp-1024 .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; }
  .el-navbar--bp-1024 .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  /* Open drawer frame styles are inline in NavbarRenderer.tsx — no CSS here. */
  .el-navbar--bp-1024 .el-navbar__links--open .el-navbar__cta--menu {
    display: inline-flex !important;
  }
}
@media (max-width: 1024px) {
  .el-navbar--bp-1024 .el-navbar__inner {
    gap: 0.75rem;
    position: relative;
  }
  .el-navbar--bp-1024 .el-navbar__links { display: none; }
  .el-navbar--bp-1024 .el-navbar__cta--desktop,
  .el-navbar--bp-1024 .el-navbar__inner > .el-navbar__cta--desktop,
  .el-navbar.el-navbar--bp-1024 .el-navbar__cta--desktop { display: none !important; }
  .el-navbar--bp-1024 .el-navbar__search-toggle--desktop,
  .el-navbar.el-navbar--bp-1024 .el-navbar__search-toggle--desktop { display: none !important; }
  .el-navbar--bp-1024 .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; }
  .el-navbar--bp-1024 .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  /* Open drawer frame styles are inline in NavbarRenderer.tsx — no CSS here. */
  .el-navbar--bp-1024 .el-navbar__links--open .el-navbar__cta--menu {
    display: inline-flex !important;
  }
}
/* ── Auto mobile breakpoint (mobileBreakpoint='auto') ─────────
   JS-driven: NavbarRenderer measures whether links overflow the
   inner shell and toggles .el-navbar--overflow on the root. No
   media query — the class is the trigger so the swap point follows
   the actual content width regardless of viewport size. */
.el-navbar--overflow .el-navbar__inner {
  gap: 0.75rem;
  position: relative;
}
.el-navbar--overflow.el-navbar--sticky {
  position: sticky;
  top: 0;
}
.el-navbar--overflow .el-navbar__links { display: none; }
.el-navbar--overflow .el-navbar__cta--desktop,
.el-navbar--overflow .el-navbar__inner > .el-navbar__cta--desktop,
.el-navbar.el-navbar--overflow .el-navbar__cta--desktop { display: none !important; }
.el-navbar--overflow .el-navbar__search-toggle--desktop,
.el-navbar.el-navbar--overflow .el-navbar__search-toggle--desktop { display: none !important; }
.el-navbar--overflow .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; align-items: center; }
.el-navbar--overflow .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }

/*
 * Belt-and-suspenders touch-device class. NavbarRenderer applies
 * `.el-navbar--touch-mobile` post-mount when navigator.maxTouchPoints > 0
 * AND viewport ≤ 1024. Fires on Android browsers that lie about the CSS
 * `(hover: none) and (pointer: coarse)` query (older Samsung Internet,
 * a few Chrome custom skins). Mirrors the existing `--overflow` rules.
 */
.el-navbar--touch-mobile .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; align-items: center; }
.el-navbar--touch-mobile .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
.el-navbar--touch-mobile .el-navbar__menu,
.el-navbar.el-navbar--touch-mobile .el-navbar__menu { display: none !important; }
.el-navbar--touch-mobile .el-navbar__cta--desktop,
.el-navbar.el-navbar--touch-mobile .el-navbar__cta--desktop { display: none !important; }
.el-navbar--touch-mobile .el-navbar__search-toggle--desktop,
.el-navbar.el-navbar--touch-mobile .el-navbar__search-toggle--desktop { display: none !important; }

/*
 * Touch-device defensive gate — guarantees the mobile toggle is
 * reachable on ANY touch-primary device (phones, foldables, Android
 * landscape, Samsung S/Note class) regardless of viewport width.
 *
 * Without this rule, devices reporting > 768 CSS px in landscape
 * (Galaxy Fold ~884px unfolded, S24 Ultra ~882px landscape, Pixel 7
 * Pro ~915px landscape) inherit `.el-navbar__mobile-toggle { display:
 * none }` from the base rule and the user can't open the menu — even
 * though the auto-overflow ResizeObserver might also detect overflow,
 * a measurement before fonts/images settle leaves the toggle hidden
 * for the critical first paint.
 *
 * `(hover: none) and (pointer: coarse)` is the canonical CSS touch
 * query, supported in every browser shipped after 2018. The desktop
 * nav links / CTA / search-toggle are forced hidden on touch so the
 * mobile-toggle isn't competing with a half-collapsed inline nav.
 */
/* Container-query bridge for the viewport branch (touch fallback kept below
   as @media for devices reporting hover:none + pointer:coarse — those rely
   on the device characteristics, not viewport width, and can't be expressed
   as @container style()). */
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; align-items: center; }
  .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  .el-navbar__menu,
  .el-navbar .el-navbar__menu { display: none !important; }
  .el-navbar__cta--desktop,
  .el-navbar .el-navbar__cta--desktop { display: none !important; }
  .el-navbar__search-toggle--desktop,
  .el-navbar .el-navbar__search-toggle--desktop { display: none !important; }
}
@media (hover: none) and (pointer: coarse) and (max-width: 1024px) {
  .el-navbar__mobile-actions { display: flex; gap: 0.5rem; margin-left: auto; align-items: center; }
  .el-navbar__mobile-toggle { display: flex; flex-shrink: 0; }
  .el-navbar__menu,
  .el-navbar .el-navbar__menu { display: none !important; }
  .el-navbar__cta--desktop,
  .el-navbar .el-navbar__cta--desktop { display: none !important; }
  .el-navbar__search-toggle--desktop,
  .el-navbar .el-navbar__search-toggle--desktop { display: none !important; }
}
.el-navbar--overflow .el-navbar__logo { min-width: 0; flex-shrink: 1; }
.el-navbar--overflow .el-navbar__brand-name {
  font-size: 0.95rem;
  max-width: min(60vw, 280px);
}
/* Drawer interior styling now lives at file scope above (search for
   "Mobile drawer interior styling") so it applies under every
   trigger — fixed-width media query (--bp-640/900/1024), JS-driven
   --overflow class, AND the default 768px breakpoint. No need for
   --overflow-scoped duplicates here. */

/* was @media(max-width:480px); bucketed to mobile (480 ≤ 768) */
@container site style(--site-bp: mobile) {
  /* Drawer width is now full-viewport via inline style in JSX. */
  .el-navbar__brand-name {
    font-size: 0.85rem;
    letter-spacing: 0.01em;
    max-width: min(55vw, 200px);
  }
  .el-navbar__cta--menu {
    font-size: 0.75rem;
  }
}
@media (max-width: 480px) {
  /* Drawer width is now full-viewport via inline style in JSX. */
  .el-navbar__brand-name {
    font-size: 0.85rem;
    letter-spacing: 0.01em;
    max-width: min(55vw, 200px);
  }
  .el-navbar__cta--menu {
    font-size: 0.75rem;
  }
}
/* ── Mobile open menu: inline dropdown/flyout stacking ─────────
   These rules scope dropdown position changes to the open mobile
   menu ONLY — not at any viewport-width breakpoint — so desktop
   dropdowns stay absolutely positioned on tablets/small laptops. */
.el-navbar__links--open .el-navbar__dropdown-menu,
.el-navbar__links--open .el-navbar__flyout-menu {
  position: static;
  transform: none;
  box-shadow: none;
  border-radius: 0;
  border: 0;
  min-width: 0;
  width: 100%;
  padding: 0.25rem 0 0.15rem 0;
  background: transparent;
  animation: none;
  border-left: 0;
  /* Stack child links vertically — overrides any inherited flex-row. */
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.el-navbar__links--open .el-navbar__dropdown-menu {
  margin-top: 0.15rem;
  gap: 0.15rem;
}
/* The dropdown wrapper is flex on desktop (so its trigger stays
   vertically centered with sibling top-level links). Inside the open
   mobile menu it becomes a stacking column so the trigger sits above
   its open menu instead of beside it (which caused the right-aligned
   look in img_11). Scope kept inside .el-navbar__links--open per
   CLAUDE.md "Dropdown stacking" rule (never inside a media query). */
.el-navbar__links--open .el-navbar__dropdown,
.el-navbar__links--open .el-navbar__flyout {
  display: flex;
  flex-direction: column;
  align-items: stretch;
}
.el-navbar__links--open .el-navbar__flyout-menu {
  padding-left: 1rem;
}
/* Drawer is a full-screen pane and intentionally inherits the same surface
   regardless of navbar variant. Submenu containers stay transparent so the
   drawer's solid bg shows through. */
.el-navbar--transparent-to-solid .el-navbar__links--open .el-navbar__dropdown-menu,
.el-navbar--transparent-to-solid .el-navbar__links--open .el-navbar__flyout-menu {
  background: transparent;
}
/* Dark navbar variant */
.el-navbar--dark {
  background: color-mix(in srgb, var(--navbar-header-bar-bg, var(--site-primary)) var(--navbar-header-bar-bg-opacity, 100%), transparent);
  border-bottom-color: var(--navbar-header-bar-border-color, transparent);
}
.el-navbar--dark .el-navbar__link { color: var(--navbar-link-color, currentColor); }
.el-navbar--dark .el-navbar__link:hover { color: var(--navbar-link-hover, var(--site-accent)); }
.el-navbar--dark .el-navbar__logo-text,
.el-navbar--dark .el-navbar__logo-placeholder { color: var(--site-primary-fg, currentColor); }
.el-navbar--dark .el-navbar__mobile-toggle {
  color: var(--navbar-mobile-action-color, var(--navbar-search-color, var(--site-primary-fg))) !important;
  background: var(--navbar-mobile-action-bg, var(--navbar-search-bg, var(--site-primary)));
  border-color: var(--navbar-mobile-action-border, var(--navbar-search-border, var(--site-primary)));
}
.el-navbar--dark .el-navbar__mobile-toggle:hover {
  background: var(--navbar-mobile-action-hover-bg, var(--navbar-search-hover-bg, color-mix(in srgb, var(--site-primary) 82%, var(--site-primary-fg, transparent))));
  border-color: var(--navbar-mobile-action-hover-border, var(--navbar-search-border-hover, color-mix(in srgb, var(--site-primary) 82%, var(--site-primary-fg, transparent))));
}
.el-navbar--dark .el-navbar__brand-name,
.el-navbar--dark .el-navbar__dropdown-trigger,
.el-navbar--dark .el-navbar__chevron {
  color: var(--navbar-text, var(--site-primary-fg)) !important;
}
.el-navbar--dark .el-navbar__chevron,
.el-navbar--dark .el-navbar__chevron-right {
  opacity: 1;
}
.el-navbar--dark .el-navbar__cta {
  background: rgba(255,255,255,0.15);
  color: var(--site-primary-fg, currentColor);
}
.el-navbar--dark .cta-btn--outline,
.el-navbar--dark .cta-btn--secondary,
.el-navbar--transparent-to-solid .cta-btn--outline,
.el-navbar--transparent-to-solid .cta-btn--secondary {
  background: var(--el-btn-bg, transparent) !important;
  color: var(--el-btn-text, var(--site-primary-fg)) !important;
  border-color: var(--el-btn-border, transparent) !important;
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.12);
}
.el-navbar--dark .cta-btn--outline:hover,
.el-navbar--transparent-to-solid .cta-btn--outline:hover {
  background: var(--el-btn-hover-bg, var(--site-btn-outline-hover-bg, var(--site-btn-outline-text, var(--site-primary)))) !important;
  color: var(--el-btn-hover-text, var(--site-btn-outline-hover-text, var(--site-primary-fg))) !important;
  border-color: var(--el-btn-hover-border, var(--el-btn-border, var(--site-btn-outline-border, var(--site-primary)))) !important;
}
.el-navbar--dark .cta-btn--secondary:hover,
.el-navbar--transparent-to-solid .cta-btn--secondary:hover {
  background: var(--el-btn-hover-bg, var(--site-btn-secondary-hover-bg, var(--site-btn-secondary-bg, var(--site-secondary)))) !important;
  color: var(--el-btn-hover-text, var(--site-btn-secondary-hover-text, var(--site-btn-secondary-text, var(--site-secondary-fg, var(--site-primary))))) !important;
  border-color: var(--el-btn-hover-border, var(--el-btn-border, var(--site-btn-secondary-hover-bg, var(--site-btn-secondary-bg, var(--site-secondary))))) !important;
}
/* Drawer is a full-screen pane: do NOT inherit dark-navbar overrides.
   Surface + text are owned by the base `.el-navbar__links--open` rules
   (which paint --site-primary / --site-primary-fg by default). */

/* Transparent-to-solid variant — starts with builder-configurable wide-bar bg, transitions on scroll.
   The full-width band behind the pill is driven by --navbar-header-bar-* custom properties set by
   NavbarRenderer from the design-panel Wide Header Bar (Initial) controls. Defaults to transparent.
   Fill % blends the chosen color toward transparent via color-mix so users can make the bar opaque
   with a plain color (e.g. #ffffff + 100%) or translucent (e.g. #ffffff + 40%). */
/* Scrollbar-width compensation for fixed-position chrome.
   `calc(100vw - 100%)` evaluates to the vertical scrollbar width WHEN
   computed in body context (where 100% = body width = viewport - scrollbar).
   Without @property, CSS custom properties inherit as token streams — the
   calc would re-evaluate against each consumer's own containing block (where
   for position:fixed elements 100% = 100vw, giving 0). With @property the
   value is computed once at definition site, so descendants inherit the
   actual pixel value and fixed-position bars can shift their right edge
   inward to match the body's effective right edge. */
@property --scrollbar-w {
  syntax: '<length>';
  inherits: true;
  initial-value: 0px;
}
body { --scrollbar-w: calc(100vw - 100%); }

.el-navbar--transparent-to-solid {
  background: color-mix(in srgb, var(--navbar-header-bar-bg, transparent) var(--navbar-header-bar-bg-opacity, 0%), transparent);
  border-bottom: 1px solid var(--navbar-header-bar-border-color, transparent);
  /* position: fixed is now scoped to `.el-navbar--sticky` (see below) so
     toggling Sticky Header off in the inspector lets this variant fall
     back to normal in-flow layout. */
  top: 0;
  left: 0;
  /* Pull right edge inward by the scrollbar width so the nav matches body's
     effective width — pill centers inside the same coordinate system as the
     content beneath it. Falls back to 0 if --scrollbar-w isn't inherited. */
  right: var(--scrollbar-w, 0px);
  /* Horizontal inset for the floating-pill children. Lives on the parent
     (longhand padding) so per-Section Container Contract `.el-navbar__inner`
     does not redeclare width chrome. The pill chrome (bg/border/radius)
     stays on `__inner`, so the visible pill still floats inset from the
     viewport edge. `box-sizing` is global border-box, so padding does not
     extend the fixed parent past `right: var(--scrollbar-w)`. The
     `--navbar-shell-inset-x` value is emitted by the navbar renderer from
     the editable `shellInsetX` prop (with `responsiveProps.tablet.shellInsetX`
     and `responsiveProps.mobile.shellInsetX` overrides) — every site
     controls its own value via the inspector. */
  padding-left: var(--navbar-shell-inset-x, 16px);
  padding-right: var(--navbar-shell-inset-x, 16px);
  z-index: 1000;
  box-shadow: 0 4px 20px rgba(8,14,25, var(--navbar-header-bar-shadow-alpha, 0));
  backdrop-filter: blur(var(--navbar-header-bar-blur, 0px));
  -webkit-backdrop-filter: blur(var(--navbar-header-bar-blur, 0px));
  transition: color 0.3s ease, background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, backdrop-filter 0.3s ease;
}
/* The .el wrapper's --el-bg propagates to direct children via .el > :not(style) (specificity 0,1,1)
   which would otherwise fill the full-width nav band with the element wrapper bg. For variants that
   own their own wide-bar styling, route through the builder-editable --navbar-header-bar-* vars
   instead so the design-panel controls win over --el-bg. Defaults stay transparent. */
.el--navbar > .el-navbar--transparent-to-solid,
.el--navbar > .el-navbar--floating,
.el--navbar > .el-navbar--transparent {
  background: color-mix(in srgb, var(--navbar-header-bar-bg, transparent) var(--navbar-header-bar-bg-opacity, 0%), transparent);
  background-color: color-mix(in srgb, var(--navbar-header-bar-bg, transparent) var(--navbar-header-bar-bg-opacity, 0%), transparent);
  border-bottom-color: var(--navbar-header-bar-border-color, transparent);
  box-shadow: 0 4px 20px rgba(8,14,25, var(--navbar-header-bar-shadow-alpha, 0));
  backdrop-filter: blur(var(--navbar-header-bar-blur, 0px));
  -webkit-backdrop-filter: blur(var(--navbar-header-bar-blur, 0px));
}
.el-navbar--transparent-to-solid .el-navbar__link { color: var(--navbar-link-color, var(--navbar-text, currentColor)); }
.el-navbar--transparent-to-solid .el-navbar__link:hover { color: var(--navbar-link-hover, var(--site-accent)); }
.el-navbar--transparent-to-solid .el-navbar__mobile-toggle {
  color: var(--navbar-mobile-action-color, var(--navbar-search-color, var(--site-accent, var(--site-primary, currentColor))));
  background: var(--navbar-mobile-action-bg, var(--navbar-search-bg, transparent));
  border-color: var(--navbar-mobile-action-border, var(--navbar-search-border, var(--site-accent, currentColor)));
}
.el-navbar--transparent-to-solid .el-navbar__dropdown-trigger { color: var(--navbar-link-color, var(--navbar-text, currentColor)); }
.el-navbar--transparent-to-solid .el-navbar__dropdown-trigger:hover { color: var(--navbar-link-hover, var(--site-accent)); }
/* Wrapper transparency for transparent-to-solid + floating variants —
   the pill/shell IS the navbar; the wrapper band around it must never
   paint a background or border, otherwise authors see a coloured strip
   behind the floating pill. The base `.el-navbar` rule sets a bg from
   `--navbar-header-bar-bg` which defaults to `--site-surface` (white on
   most themes). Force transparent for these two variants at every state
   (top, scrolled, mobile-drawer-open). The shell paints all visible
   chrome from the rules below. */
.el-navbar--transparent-to-solid,
.el-navbar--floating,
.el--navbar > .el-navbar--transparent-to-solid,
.el--navbar > .el-navbar--floating {
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}

.el-navbar--transparent-to-solid .el-navbar__inner,
.el-navbar--floating .el-navbar__inner {
  position: relative;
  /* Re-declare flex alignment explicitly on the variant override — the
     pill shell's min-height is taller than the base .el-navbar__inner
     height, and without repeating align-items here some browsers drift
     children off-center when flex item heights differ (logo image tall,
     dropdown wrapper div short). */
  display: flex;
  align-items: center;
  justify-content: space-between;
  min-height: max(var(--navbar-height, 64px), 70px);
  margin-top: var(--navbar-shell-inset-top, 14px);
  margin-bottom: var(--navbar-shell-inset-bottom, 14px);
  /* Cap the pill width via the site-container contract — `.el-navbar__inner`
     already carries `.el-site-container` (see NavbarRenderer). Setting
     `--el-navbar-max-width` here lets the variant request a tighter pill
     cap without redeclaring `max-width` / `margin-inline` (which would
     violate the section-container width-chrome contract — see
     siteContainerContract.test.tsx). The `.el-navbar__inner.el-site-container`
     rule above picks this up via its existing fallback chain. */
  --el-navbar-max-width: var(--navbar-shell-max-width, var(--site-max-width, 1200px));
  /* Horizontal inset is applied as `padding-left/right` on the parent
     `.el-navbar--transparent-to-solid` so this wrapper does not redeclare
     width chrome — see Section Container Contract test. */
  /* Uniform translucent shell. Single-layer background controlled
   * entirely by inspector props (`--site-nav-initial-bg`,
   * `--navbar-shell-bg-opacity`) plus an optional brand-primary tint
   * through `--navbar-shell-tint-opacity`. Earlier revisions stacked a
   * 135° specular sweep + vertical highlight gradient on top — those
   * layers worked as a "glass" cue on wide pills but landed a bright
   * spot in the upper-left where the logo sits, reading as a halo
   * behind the brand mark. Removed. Glass cue now comes from the
   * backdrop-filter blur + the soft drop shadow alone. */
  background: color-mix(in srgb, var(--site-primary, #2563eb) var(--navbar-shell-tint-opacity, 0%), color-mix(in srgb, var(--site-nav-initial-bg, var(--site-nav-glass-bg, var(--site-bg))) var(--navbar-shell-bg-opacity, 60%), transparent));
  border: 1px solid var(--navbar-shell-border-color, color-mix(in srgb, var(--site-primary, white) 18%, transparent));
  border-radius: var(--navbar-shell-radius, 24px);
  box-shadow:
    0 24px 52px -16px color-mix(in srgb, var(--site-primary, #1a2540) 32%, transparent),
    0 8px 18px -8px rgba(0, 0, 0, 0.16),
    inset 0 0 0 1px color-mix(in srgb, var(--site-primary, white) 6%, transparent);
  backdrop-filter: blur(var(--navbar-shell-blur, 22px)) saturate(160%);
  -webkit-backdrop-filter: blur(var(--navbar-shell-blur, 22px)) saturate(160%);
  transition: background 0.3s ease, border-color 0.3s ease, box-shadow 0.3s ease, transform 0.3s ease, backdrop-filter 0.3s ease;
}

/* Scrolled state — off-white background, dark text */
.el-navbar--scrolled {
  background: transparent !important;
  border-bottom-color: transparent !important;
  box-shadow: none;
  backdrop-filter: none;
}
.el-navbar--transparent-to-solid.el-navbar--scrolled,
.el-navbar--floating.el-navbar--scrolled {
  /* Wide band stays fully transparent at every breakpoint — these variants
     paint chrome on the pill (`.el-navbar__inner`), never on the wide band.
     The previous color-mix on `--navbar-header-glass-bg` was producing a
     visible dark band on mobile/tablet whenever the inspector's bg-opacity
     value was non-zero (and even at 0% on Momentum due to a residual
     paint somewhere in the cascade). Hard-pinning to transparent gives the
     "scroll-and-stick pill only" look the user is asking for. */
  background: transparent !important;
  border-bottom-color: transparent !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
/* Same lock for the initial (un-scrolled) state — the wide band is never the
   visible chrome on these variants. */
.el-navbar--transparent-to-solid,
.el-navbar--floating,
.el-navbar--transparent {
  background: transparent !important;
  border-bottom-color: transparent !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
/* Active link state — refined indicator: thin full-width underline flush
   with the text baseline, subtle scale-in on mount/hover. Token-driven,
   never hardcoded. */
.el-navbar__link--active {
  color: var(--site-nav-active-color, var(--site-accent, var(--site-primary))) !important;
  position: relative;
}
.el-navbar__link--active::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 2px;
  background: currentColor;
  border-radius: 999px;
  transform: scaleX(1);
  transform-origin: center;
  opacity: 0.9;
  transition: transform 0.25s ease, opacity 0.25s ease;
}
.el-navbar__dropdown-trigger .el-navbar__label {
  position: relative;
  display: inline-flex;
  align-items: center;
}
.el-navbar__dropdown-trigger.el-navbar__link--active::after {
  display: none;
}
.el-navbar__dropdown-trigger.el-navbar__link--active .el-navbar__label::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: -4px;
  height: 2px;
  background: currentColor;
  border-radius: 999px;
  opacity: 0.9;
}
/* Scrolled-state link color cascade:
   1. --navbar-link-color-scrolled (new dedicated field)
   2. --navbar-link-color            (base linkColor — lets a user set ONE
                                      color that applies in both states)
   3. --navbar-text-scrolled         (legacy scrolledTextColor fallback)
   4. --site-text                    (theme default) */
/* Scrolled-state link color — when the shell switches from transparent to
   solid (typically white), the transparent-state link color (often a brand
   accent like gold) frequently fails AA against the new solid bg. The chain
   prefers an explicit `--navbar-link-color-scrolled` first, then the
   theme-vetted `--navbar-text-scrolled` / `--site-text` (which authors set
   for body copy → guaranteed AA on the surface), and only falls through to
   the transparent-state `--navbar-link-color` as a last resort. This stops
   gold-on-white (#c9a84c on #fff = 2.29:1) without forcing every theme to
   re-declare the scrolled token. */
.el-navbar--scrolled .el-navbar__link { color: var(--navbar-link-color-scrolled, var(--navbar-text-scrolled, var(--site-text, var(--navbar-link-color)))) !important; }
/* Scrolled-state active link: prefer navy (--site-primary) over accent
   (--site-accent / gold) because gold-on-white scrolled bg fails AA at
   2.29:1. Sites can pin a different scrolled-active color via
   --site-nav-active-color-scrolled. */
.el-navbar--scrolled .el-navbar__link--active { color: var(--site-nav-active-color-scrolled, var(--site-primary, var(--site-accent))) !important; }
.el-navbar--scrolled .el-navbar__link--active::after { background: var(--site-nav-active-color-scrolled, var(--site-primary, var(--site-accent))); }
.el-navbar--scrolled .el-navbar__dropdown-trigger.el-navbar__link--active .el-navbar__label::after { background: var(--site-nav-active-color-scrolled, var(--site-accent, var(--site-primary))); }
.el-navbar--scrolled .el-navbar__link:hover {
  color: var(--navbar-link-hover-scrolled, var(--navbar-link-hover, var(--site-primary))) !important;
  background: var(--navbar-link-hover-bg-scrolled, var(--navbar-link-hover-bg, transparent));
}
.el-navbar--scrolled .el-navbar__dropdown-trigger { color: var(--navbar-link-color-scrolled, var(--navbar-text-scrolled, var(--site-text, var(--navbar-link-color)))) !important; }
.el-navbar--scrolled .el-navbar__dropdown-trigger.el-navbar__link--active { color: var(--site-nav-active-color-scrolled, var(--site-accent, var(--site-primary))) !important; }
.el-navbar--scrolled .el-navbar__dropdown-trigger:hover {
  color: var(--navbar-link-hover-scrolled, var(--navbar-link-hover, var(--site-primary))) !important;
  background: var(--navbar-link-hover-bg-scrolled, var(--navbar-link-hover-bg, transparent));
}
.el-navbar--scrolled .el-navbar__mobile-toggle {
  color: var(--navbar-mobile-action-color-scrolled, var(--navbar-search-color-scrolled, var(--navbar-mobile-action-color, var(--navbar-search-color, var(--site-primary-fg))))) !important;
  background: var(--navbar-mobile-action-bg-scrolled, var(--navbar-search-bg-scrolled, var(--navbar-mobile-action-bg, var(--navbar-search-bg, var(--site-primary))))) !important;
  border-color: var(--navbar-mobile-action-border-scrolled, var(--navbar-search-border-scrolled, var(--navbar-mobile-action-border, var(--navbar-search-border, var(--site-primary))))) !important;
}
/* Active link in transparent-to-solid variant (on top — transparent background) */
.el-navbar--transparent-to-solid .el-navbar__link--active { color: var(--site-nav-active-color, var(--site-primary-fg)) !important; }
.el-navbar--transparent-to-solid .el-navbar__link--active::after { background: var(--site-nav-active-color, var(--site-primary-fg)); }
.el-navbar--transparent-to-solid.el-navbar--scrolled .el-navbar__inner,
.el-navbar--floating.el-navbar--scrolled .el-navbar__inner {
  /* Scrolled pill bg: prefer the dedicated shellScrolledBackgroundColor
     (via --navbar-shell-scrolled-bg) so the pill can diverge from the wide
     band's scrolled background. Falls back to white surface when no
     author override is supplied (was `transparent` before, which left the
     pill invisible on scroll on themes that hadn't set
     site-nav-scrolled-bg). */
  background: color-mix(in srgb, var(--navbar-shell-scrolled-bg, var(--site-nav-scrolled-bg, var(--site-nav-glass-scrolled-bg, var(--site-surface, transparent)))) var(--navbar-shell-scrolled-opacity, 96%), transparent);
  border-color: var(--navbar-shell-scrolled-border-color, transparent);
  box-shadow: 0 18px 38px rgba(8,14,25,var(--navbar-shell-scrolled-shadow-alpha, 0.1));
  backdrop-filter: blur(var(--navbar-shell-scrolled-blur, 22px)) saturate(1.1);
  -webkit-backdrop-filter: blur(var(--navbar-shell-scrolled-blur, 22px)) saturate(1.1);
}
/* Active link in transparent-to-solid scrolled state — must be visible on glass */
.el-navbar--transparent-to-solid.el-navbar--scrolled .el-navbar__link--active { color: var(--site-nav-active-color-scrolled, var(--site-accent, var(--site-primary))) !important; }
.el-navbar--transparent-to-solid.el-navbar--scrolled .el-navbar__link--active::after { background: var(--site-nav-active-color-scrolled, var(--site-accent, var(--site-primary))); }
/* Active state inside the open mobile drawer — top-level links AND
   dropdown leaves both honor the dropdown text color so an active
   "Communities" link doesn't render in white-on-white over the drawer
   surface. The previous "suppress on top-level" scope let the parent
   transparent-to-solid `--site-nav-active-color` (white) leak through to
   the drawer, which paints the active link white over the white drawer
   panel — invisible. */
.el-navbar .el-navbar__links--open .el-navbar__link,
.el-navbar .el-navbar__links--open .el-navbar__dropdown-trigger {
  color: var(--navbar-dropdown-text, var(--site-primary)) !important;
}
.el-navbar .el-navbar__links--open .el-navbar__link--active,
.el-navbar .el-navbar__links--open .el-navbar__dropdown-trigger.el-navbar__link--active,
.el-navbar .el-navbar__links--open .el-navbar__link[aria-current="page"],
.el-navbar .el-navbar__links--open .el-navbar__dropdown-item[aria-current="page"],
.el-navbar .el-navbar__links--open .el-navbar__dropdown-item--active {
  background: var(--navbar-dropdown-active-bg, color-mix(in srgb, var(--site-accent, var(--site-primary)) 14%, transparent));
  color: var(--navbar-dropdown-active-text, var(--site-accent, var(--site-primary))) !important;
  box-shadow: none;
}
.el-navbar .el-navbar__links--open .el-navbar__link--active::after,
.el-navbar .el-navbar__links--open .el-navbar__dropdown-trigger.el-navbar__link--active .el-navbar__label::after {
  display: none;
}
/* Dropdown content reveal inside the open drawer — when a dropdown is
   open (data-state="open" from Radix, or .el-navbar__dropdown--open
   class on the legacy path), force its content surface visible and its
   items laid out vertically. The base .er-radix-navmenu__content rule in
   er-radix.css uses position: absolute + clip-path animation that's
   suited to desktop hover-popovers but leaves the content visually
   absent inside the mobile drawer. Override here so tapping a trigger
   reveals the items beneath it inline. */
.el-navbar__links--open .er-radix-navmenu__content[data-state="open"],
.el-navbar__links--open .el-navbar__dropdown--open > .el-navbar__dropdown-menu,
.el-navbar__links--open .el-navbar__dropdown--open > .el-navbar__flyout-menu {
  position: static !important;
  width: 100% !important;
  display: flex !important;
  flex-direction: column !important;
  gap: 0.25rem !important;
  padding: 0.4rem 0 0.4rem 0.5rem !important;
  margin: 0 !important;
  background: transparent !important;
  border: none !important;
  box-shadow: none !important;
  clip-path: none !important;
  animation: none !important;
  opacity: 1 !important;
  transform: none !important;
}
.el-navbar:not(.el-navbar--transparent-to-solid).el-navbar--scrolled {
  background: var(--site-nav-scrolled-bg, transparent) !important;
  border-bottom-color: rgba(26,39,68,0.08) !important;
  box-shadow: 0 12px 28px rgba(8,14,25,0.08);
  backdrop-filter: blur(22px);
}
.el-navbar:not(.el-navbar--transparent-to-solid).el-navbar--scrolled .el-navbar__cta {
  box-shadow: 0 10px 20px rgba(26,39,68,0.1);
}
.el-navbar:not(.el-navbar--transparent-to-solid).el-navbar--scrolled .cta-btn--outline,
.el-navbar:not(.el-navbar--transparent-to-solid).el-navbar--scrolled .cta-btn--secondary {
  background: rgba(255,255,255,0.58) !important;
  color: var(--site-primary) !important;
  border-color: rgba(26,39,68,0.14) !important;
  box-shadow: none;
}
.el-navbar:not(.el-navbar--transparent-to-solid).el-navbar--scrolled .cta-btn--outline:hover,
.el-navbar:not(.el-navbar--transparent-to-solid).el-navbar--scrolled .cta-btn--secondary:hover {
  background: rgba(201,168,76,0.12) !important;
  color: var(--site-primary) !important;
  border-color: var(--site-accent) !important;
}
.el-navbar--transparent-to-solid.el-navbar--scrolled .el-navbar__cta {
  box-shadow: 0 12px 24px rgba(8,14,25,0.1);
}
/* ── Editorial Marquee / Intent Router shared shell controls ───── */
.el-editorial-marquee {
  --el-bg-default:      var(--site-bg, transparent);
  --el-color-default:   var(--site-fg, currentColor);
  --el-padding-default: 0; /* marquee owns its own internal content padding */
  border-radius: var(--editorial-marquee-radius, 0px);
  overflow: hidden;
  border: 1px solid rgba(255,255,255,0.14);
  position: relative;
}
.el-editorial-marquee > div:last-child > div:last-child > div:first-child {
  border-radius: var(--editorial-marquee-panel-radius, 0px);
}
/* Mobile reset for editorial-marquee root padding. Layout props default
   to `clamp(52px, 7vw, 80px) 24px` (set on the wrapper as `--el-padding`),
   which the `.el > :not(style)` rule paints onto the section root. On a
   375px viewport that 24px horizontal gutter (compounded with the inner
   __grid's own 16px gutter) leaves the headline column ~295px wide and
   forces aggressive mid-word break on long words like "Development" or
   "Preservation". Drop the section's outer side gutter on mobile so the
   inner __grid owns the only horizontal gutter (16px each side) — the
   headline column reclaims ~343px of the 375px viewport.
   Inline `style="padding-x: …"` on the renderer still wins because inline
   styles always beat class selectors, but no live row sets one. The
   vertical scale stays compressed (`clamp(36px, 9vw, 60px)`) so the hero
   isn't taller than the viewport on the smallest screens. */
@container site style(--site-bp: mobile) {
  .el-editorial-marquee {
    --el-padding-default: clamp(36px, 9vw, 60px) 0;
  }
}
@media (max-width: 768px) {
  .el-editorial-marquee {
    --el-padding-default: clamp(36px, 9vw, 60px) 0;
  }
}
.el-intent-router {
  --el-bg-default:    var(--site-bg, transparent);
  --el-color-default: var(--site-fg, currentColor);
  border-radius: var(--intent-router-radius, 0px);
}
/* Intent-card wrapper gets generous internal padding by default. The
   `.el > :not(style)` rule in this file paints padding on the renderer root
   via `var(--el-padding, var(--el-padding-default, 0))` — so declaring
   `--el-padding-default` on the wrapper is how card chrome opts into its
   own default padding. Authors can still override via the design panel's
   Spacing controls (paddingTop / …) or the shorthand `padding` prop. */
.el--intent-card {
  /* Grid equal-height contract: `display:contents` on the card-shell means
     this ElementWrapper IS the actual grid item. `.el-compound-section__cards > *`
     targets the shell and never reaches here, so height:100% must be declared
     explicitly so the nested `.el-intent-router__card { height:100% }` can
     resolve against a definite containing-block height. */
  height: 100%;
  --el-padding-default: var(--ir-card-padding, clamp(1.75rem, 2.5vw, 2.5rem));
  /* Inherit the router's card-radius knob so the `.el > :not(style)` rule
     (specificity 0,1,1) — which otherwise wins over `.el-intent-router__card`
     (0,1,0) — resolves to the author-set radius instead of the `:where(.el .el)`
     reset's 0px default. The fallback chain mirrors `.el-intent-router__card`
     so visuals stay identical whichever rule ultimately paints. */
  --el-radius-default: var(--intent-router-card-radius, var(--site-radius-lg, 16px));
  /* Same pattern for bg and shadow — without these, :where(.el .el) resets
     --el-bg-default to transparent and --el-shadow-default to none, causing
     .el > :not(style) to zero the card background and shadow on light-tone
     sections (dark-tone has a higher-specificity override at (0,2,0)). */
  --el-bg-default: var(--ir-card-bg, color-mix(in srgb, var(--site-surface, transparent) 92%, transparent));
  --el-shadow-default: var(--ir-card-shadow, 0 4px 16px rgba(0, 0, 0, 0.18));
}
/* Eyebrow defaults to the site accent so it reads as a branded tag. The
   design panel's "Eyebrow Color" control emits `--ir-eyebrow-color` from
   the renderer, so per-site overrides still win. Target both the slot's
   direct text and any rich-text paragraph inside it. */
.el-intent-router .el-compound-section__slot--eyebrow,
.el-intent-router .el-compound-section__slot--eyebrow .el-rich-text,
.el-intent-router .el-compound-section__slot--eyebrow .el-rich-text > p {
  color: var(--ir-eyebrow-color, var(--site-accent, currentColor));
  font-weight: var(--site-eyebrow-weight, 700);
  letter-spacing: var(--site-eyebrow-tracking, 0.14em);
  text-transform: var(--site-eyebrow-transform, uppercase);
  font-size: var(--site-eyebrow-size, 0.78rem);
}
.el-intent-router a[data-featured],
.el-intent-router a {
  border-radius: var(--intent-router-card-radius, 0px);
}
/* Card initial styling driven entirely by --ir-card-* vars set inline by the
   renderer. Putting these properties in CSS (not inline) is what allows the
   :hover rule below to actually win. */
.el-intent-router__card {
  text-decoration: none;
  color: inherit;
  display: flex;
  flex-direction: column;
  gap: 0.75rem;
  /* Default internal padding — every side min 28px, scales up on wider
     viewports. Authors override via the design panel (cardPadding → the
     `--ir-card-padding` CSS var). 1.5rem felt cramped and let icons sit
     flush against the card rim. */
  padding: var(--ir-card-padding, clamp(1.75rem, 2.5vw, 2.5rem));
  border-radius: var(--intent-router-card-radius, var(--site-radius-lg, 16px));
  /* Fallbacks keep the card visible when the builder has not explicitly set
     cardBackground/borderColor/shadow on the intent-router — e.g. legacy
     Momentum pages carrying pre-Stage-7C JSON. Without these, an unset
     --ir-card-bg resolves to transparent and the card loses its chrome. */
  background: var(--ir-card-bg, color-mix(in srgb, var(--site-surface, transparent) 92%, transparent));
  /* Uniform border on all sides — the accent bar is painted as an inset
     box-shadow below so the rounded-corner area is automatically clipped
     to the card boundary (no visible gap between bar and card edge that
     a 5px `border-top` produces against a thinner 1px side-border with
     rounded corners). */
  border: 1px solid var(--ir-card-border-color, var(--site-border, transparent));
  /* Accent bar — inset box-shadow guarantees flush bond with the card top
     and respects border-radius. Authors override height via
     `--ir-card-accent-bar-height` (defaults to 5px). Set the height to 0 to
     remove the bar entirely. */
  box-shadow:
    inset 0 var(--ir-card-accent-bar-height, 5px) 0 0 var(--ir-card-accent-bar-color, var(--ir-accent, var(--site-accent, currentColor))),
    var(--ir-card-shadow, 0 4px 16px rgba(0, 0, 0, 0.18));
  backdrop-filter: var(--ir-card-blur, none);
  -webkit-backdrop-filter: var(--ir-card-blur, none);
  transition:
    transform 220ms cubic-bezier(0.4, 0, 0.2, 1),
    box-shadow 220ms cubic-bezier(0.4, 0, 0.2, 1),
    border-color 220ms cubic-bezier(0.4, 0, 0.2, 1),
    background 220ms cubic-bezier(0.4, 0, 0.2, 1);
  will-change: transform, box-shadow;
  height: 100%;
}

.el-intent-router.el-compound-section--grid .el-compound-section__inner {
  gap: var(--ir-section-gap, clamp(1.25rem, 2vw, 2rem));
}
/* Dark-tone default: when the intent-router sits on a $primary/dark band,
   the standard $surface cardBackground often resolves to a near-identical
   dark tone (visible failure: cards blend into the band with only a faint
   border). Promote a glassmorphic treatment as the default so cards lift
   off the band. Authors who want a solid card can set cardBackground to a
   distinct token (e.g. $background) — higher specificity than this rule. */
.el-compound-section--tone-dark .el-intent-router__card {
  /* Glass base tinted with the site accent so cards feel branded, not
     clinical. Reads as a soft accent wash over the dark band; every
     color-mix stop flows through `--ir-accent` (emitted by the renderer
     from the accentColor prop) → `--site-accent` → currentColor, so the
     accent is fully theme-driven and design-panel-editable. */
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 14%, transparent) 0%,
      color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 5%, transparent) 100%
    ),
    linear-gradient(
      180deg,
      rgba(255, 255, 255, 0.08) 0%,
      rgba(255, 255, 255, 0.02) 100%
    );
  border-color: color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 30%, rgba(255, 255, 255, 0.1));
  backdrop-filter: blur(22px) saturate(160%);
  -webkit-backdrop-filter: blur(22px) saturate(160%);
  /* Layer an accent-tinted inner highlight on top of the author-set outer
     shadow (via --ir-card-shadow, emitted by the renderer from cardShadow).
     Keeps the user's shadow control live while adding a proper glass rim. */
  box-shadow:
    /* Preserve accent-bar inset shadow on dark-tone rest state. Layered
       BEFORE the inner highlights so the bar reads as a solid stripe, not
       a tinted wash. */
    inset 0 var(--ir-card-accent-bar-height, 5px) 0 0 var(--ir-card-accent-bar-color, var(--ir-accent, var(--site-accent, currentColor))),
    inset 0 -1px 0 rgba(0, 0, 0, 0.18),
    var(--ir-card-shadow, 0 16px 40px rgba(0, 0, 0, 0.28));
}
/* Icon tile on dark-tone cards — bump accent presence so the icon reads as a
   real affordance instead of a muted grey square. Matches the accent-derived
   hover glow that already exists below. */
.el-compound-section--tone-dark .el-intent-router__card-icon {
  background: color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 22%, transparent);
  box-shadow:
    inset 0 0 0 1px color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 36%, transparent),
    0 4px 12px color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 18%, transparent);
}
/* Dark-tone hover — the glass default above is higher specificity than the
   base `[data-card-hover-shell]:hover .el-intent-router__card` rule and would swallow the accent
   highlight. Re-assert the accent tint at matching specificity so the hover
   state still pops. Routes through the same `--ir-card-hover-*` var chain as
   the base rule so the design panel controls (cardHoverBg, cardHoverBorderColor,
   cardHoverShadow, cardHoverGlowOpacity) stay live. */
.el-compound-section--tone-dark [data-card-hover-shell]:hover .el-intent-router__card,
.el-compound-section--tone-dark .el-intent-router__card:focus-visible {
  /* Stack: author-set hover tint (or accent gradient fallback) on top of an
     accent-washed glass base. Both layers are accent-derived so the hover
     feels like the card "lighting up" with the brand rather than flashing
     to white. */
  background:
    var(--ir-card-hover-bg,
      linear-gradient(180deg,
        color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) calc(28% * var(--ir-card-hover-glow-opacity, 1)), transparent),
        color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) calc(14% * var(--ir-card-hover-glow-opacity, 1)), transparent)
      )),
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 16%, transparent) 0%,
      color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 6%, transparent) 100%
    );
  border-color: var(--ir-card-hover-border-color,
    color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 72%, transparent));
  color: var(--ir-card-hover-color, inherit);
  box-shadow:
    /* Preserve the accent-bar inset shadow on dark-tone hover too. */
    inset 0 var(--ir-card-accent-bar-height, 5px) 0 0 var(--ir-card-accent-bar-color, var(--ir-accent, var(--site-accent, currentColor))),
    0 0 0 1px color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) calc(42% * var(--ir-card-hover-glow-opacity, 1)), transparent),
    var(--ir-card-hover-shadow,
      0 24px 56px color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 26%, rgba(0, 0, 0, 0.32)));
}
/* Intent-card inner slot layout — header (icon + heading/badge) stacks at
   top, body fills middle, CTA pins to bottom. All typography inherits from
   the child elements themselves so theme tokens flow through. */
.el-intent-router__card-header {
  display: flex;
  flex-direction: row;
  gap: 0.75rem;
  align-items: center;
}
.el-intent-router__card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ir-card-icon-size, 44px);
  height: var(--ir-card-icon-size, 44px);
  border-radius: var(--ir-card-icon-radius, 12px);
  background: color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 14%, transparent);
  color: var(--ir-accent, var(--site-accent, currentColor));
  flex-shrink: 0;
}
.el-intent-router__card-icon .inline-icon { background-color: currentColor; }
/* Icon child element wraps in its own `.el.el--icon` → `.el-icon` span, so the
   card-icon container's inline-flex centering lands on the outer wrapper only
   and its intermediates anchored the glyph top-left. Force each layer to flex-
   center and fill the 44px box, and inherit the container's accent color
   (otherwise `.el-icon { color: var(--site-primary) }` in er-content.css wins
   over the `--ir-accent` cascade set on the container). */
.el-intent-router__card-icon > .el,
.el-intent-router__card-icon .el-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  color: inherit;
}
.el-intent-router__card-titles {
  display: flex;
  flex-direction: column;
  gap: 0.25rem;
  flex: 1 1 0;
  min-width: 0;
}
.el-intent-router__card-title-wrap .el-heading {
  margin-bottom: 0;
}
.el-intent-router__card-title-wrap .el-heading__text {
  font-size: clamp(1.1rem, 1.5vw, 1.35rem);
  line-height: 1.2;
  margin: 0;
}
.el-intent-router__card-badge {
  display: inline-block;
  padding: 0.2rem 0.55rem;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 14%, transparent);
  color: var(--ir-accent, var(--site-accent, currentColor));
  font-size: 0.68rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  align-self: flex-start;
}
.el-intent-router__card-body {
  font-size: 0.95rem;
  line-height: 1.6;
  opacity: 0.85;
  flex: 1 1 auto;
}
.el-intent-router__card-body > * { margin: 0; }
.el-intent-router__card-cta {
  margin-top: auto;
  padding-top: 0.25rem;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
}
/* Card hover state — CARD_HOVER_FIELDS contract.
   Each property prefers the builder-set override (--ir-card-hover-*) when
   present, otherwise falls back to an accent-derived default. The accent itself
   is read from --ir-accent (set inline by the renderer from the element's
   accentColor prop) → falls through to the site theme's --site-accent token.
   Documented in src/ai_skills/evara-website-builder/SKILL_REFERENCE.md
   § "Card Hover Contract".

   NOTE: `background` fallback must use COMMA-separated multi-backgrounds —
   space-concatenation (`<image> <color>`) is invalid when the second layer
   is itself a gradient, which causes the whole declaration to be dropped.
   That's why a prior version rendered *no* visible hover background on
   gradient-bg cards (e.g. the hero preset on Momentum). */
[data-card-hover-shell]:hover .el-intent-router__card,
.el-intent-router__card:focus-visible{
  transform: translateY(calc(var(--ir-card-hover-lift, 6px) * -1)) !important;
  border-color: var(--ir-card-hover-border-color,
    color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 65%, transparent));
  background:
    var(--ir-card-hover-bg,
      linear-gradient(180deg,
        color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) calc(14% * var(--ir-card-hover-glow-opacity, 1)), transparent),
        color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) calc(6% * var(--ir-card-hover-glow-opacity, 1)), transparent)
      )),
    var(--ir-card-bg, color-mix(in srgb, var(--site-surface, transparent) 92%, transparent));
  box-shadow:
    /* Preserve the accent-bar inset shadow from the rest state so the bar
       stays flush during hover lift. */
    inset 0 var(--ir-card-accent-bar-height, 5px) 0 0 var(--ir-card-accent-bar-color, var(--ir-accent, var(--site-accent, currentColor))),
    var(--ir-card-hover-shadow, 0 24px 56px rgba(0, 0, 0, 0.32)),
    0 0 0 1px color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) calc(32% * var(--ir-card-hover-glow-opacity, 1)), transparent);
}
/* Focus-visible: keyboard-user parity with hover, plus an offset 3px
   accent-tinted ring. Paired with the :hover rule above so all the
   lift/background/border changes apply too. */
.el-intent-router__card:focus-visible {
  outline: 3px solid color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 35%, transparent);
  outline-offset: 3px;
}
.el-intent-router__card[data-featured='true']:hover,
.el-intent-router__card[data-featured='true']:focus-visible {
  background:
    var(--ir-card-hover-bg,
      linear-gradient(180deg,
        color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) calc(22% * var(--ir-card-hover-glow-opacity, 1)), transparent),
        color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) calc(10% * var(--ir-card-hover-glow-opacity, 1)), transparent)
      )),
    var(--ir-card-bg, color-mix(in srgb, var(--site-surface, transparent) 92%, transparent));
  box-shadow:
    /* Preserve the accent-bar inset shadow on featured-hover too. */
    inset 0 var(--ir-card-accent-bar-height, 5px) 0 0 var(--ir-card-accent-bar-color, var(--ir-accent, var(--site-accent, currentColor))),
    var(--ir-card-hover-shadow,
      0 28px 64px color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) 26%, rgba(0,0,0,0.32))),
    0 0 0 1px color-mix(in srgb, var(--ir-accent, var(--site-accent, currentColor)) calc(40% * var(--ir-card-hover-glow-opacity, 1)), transparent);
}
/* Respect user motion preferences — kill the lift, keep the color/border/
   background shift so the card still responds visibly. */
@media (prefers-reduced-motion: reduce) {
  .el-intent-router__card {
    transition:
      box-shadow 1ms linear,
      border-color 1ms linear,
      background 1ms linear;
    will-change: auto;
  }
  .el-intent-router__card:hover,
  .el-intent-router__card:focus-visible {
    transform: none !important;
  }
}

/* Brand name next to logo */
.el-navbar__brand-name {
  font-family: var(--site-font-heading);
  font-size: var(--navbar-brand-font-size, 18px);
  font-weight: var(--navbar-brand-font-weight, 700);
  color: inherit;
  text-decoration: none;
  letter-spacing: 0.02em;
  max-width: min(24vw, 220px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.el-navbar__logo {
  text-decoration: none;
  display: flex;
  align-items: center;
  gap: 0.65rem;
  flex-shrink: 0;
}
.el-navbar--dark .el-navbar__brand-name,
.el-navbar--dark.el-navbar--scrolled .el-navbar__brand-name { color: rgba(255,255,255,0.95) !important; }
/* Brand-name in scrolled state — same chain as `.el-navbar--scrolled
   .el-navbar__link` so a navy-text site doesn't paint navy brand-on-navy
   when the navbar shell stays dark in its scrolled state (e.g. Momentum
   /turnagain-place @1024 → bg=rgb(26,39,68) brand=rgb(26,39,68) = 1:1).
   Falls through to `--site-text-on-primary` then white as a hard guard. */
.el-navbar--scrolled .el-navbar__brand-name { color: var(--navbar-link-color-scrolled, var(--navbar-text-scrolled, var(--site-text-on-primary, currentColor))) !important; }
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-navbar__brand-name {
    font-size: 0.95rem;
    max-width: min(40vw, 260px);
  }
}
@media (max-width: 1024px) {
  .el-navbar__brand-name {
    font-size: 0.95rem;
    max-width: min(40vw, 260px);
  }
}

/* ── Dropdown menus ──────────────────────────────────────── */
.el-navbar__dropdown {
  position: relative;
  /* Wrapper around the dropdown trigger button — needs to participate in
     flex alignment as a flex item so the trigger sits on the same vertical
     center line as sibling plain links in .el-navbar__links. */
  display: flex;
  align-items: center;
}
.el-navbar__dropdown-trigger {
  display: inline-flex;
  align-items: center;
  gap: 0.35rem;
  background: none;
  border: none;
  cursor: pointer;
  font-size: var(--navbar-link-font-size, 0.9rem);
  font-weight: var(--navbar-link-font-weight, 600);
  letter-spacing: var(--navbar-link-letter-spacing, 0.035em);
  color: var(--site-text);
  padding: 0;
  transition: color 0.15s;
}
.el-navbar__dropdown-trigger:hover { color: var(--navbar-link-hover, var(--site-primary)); }
.el-navbar__chevron {
  color: inherit;
  opacity: 0.72;
  transition: transform 0.2s ease, opacity 0.2s ease, color 0.2s ease;
}
.el-navbar__chevron svg,
.el-navbar__chevron path,
.el-navbar__chevron-right svg,
.el-navbar__chevron-right path {
  fill: currentColor;
  stroke: currentColor;
}
.el-navbar__dropdown--open .el-navbar__chevron {
  transform: rotate(180deg);
}
.el-navbar__dropdown-menu {
  position: absolute;
  top: calc(100% + 8px);
  left: 0;
  transform: none;
  min-width: 200px;
  background: color-mix(in srgb, var(--navbar-dropdown-bg, var(--site-surface)) 92%, rgba(255,255,255,0.55));
  border: 1px solid rgba(26,39,68,0.08);
  border-radius: var(--navbar-dropdown-radius, 16px);
  box-shadow: 0 calc(var(--navbar-dropdown-shadow-alpha, 20px) * 0.6) var(--navbar-dropdown-shadow-alpha, 20px) rgba(15, 23, 42, 0.1);
  padding: 0.35rem;
  /* Sit above the search drawer (z-index 5) so an open nav dropdown is never
     hidden behind a simultaneously-open search panel. */
  z-index: 520;
  animation: el-navbar-fadeIn 0.15s ease;
  backdrop-filter: blur(16px);
}
/* Invisible bridge between trigger and dropdown — prevents hover gap */
.el-navbar__dropdown-menu::before {
  content: '';
  position: absolute;
  bottom: 100%;
  left: 0;
  right: 0;
  height: 12px;
}
@keyframes el-navbar-fadeIn {
  from { opacity: 0; transform: translateY(-4px); }
  to { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .el-navbar__dropdown-menu { animation: none; }
}
.el-navbar__dropdown-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  /* Match the trigger's `0.5rem` horizontal padding so dropdown item text
   * left-aligns with the parent trigger label instead of indenting another
   * 16px to the right. */
  padding: 0.6rem 0.5rem;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--navbar-dropdown-text, var(--site-text));
  text-decoration: none;
  transition:
    background var(--navbar-dropdown-item-transition, 140ms) ease,
    color var(--navbar-dropdown-item-transition, 140ms) ease,
    box-shadow var(--navbar-dropdown-item-transition, 140ms) ease;
  white-space: nowrap;
  cursor: pointer;
  background: none;
  border: none;
  border-radius: 12px;
  width: 100%;
  text-align: left;
}
.el-navbar__dropdown-item:hover,
.el-navbar__dropdown-item:focus-visible {
  background: var(--navbar-dropdown-hover-bg, color-mix(in srgb, var(--site-accent, currentColor) 8%, transparent));
  color: var(--navbar-dropdown-hover-text, var(--navbar-dropdown-text, var(--site-text, currentColor)));
  box-shadow: inset 2px 0 0 var(--site-accent);
}
.el-navbar__dropdown-item[aria-current="page"],
.el-navbar__dropdown-item--active {
  background: var(--navbar-dropdown-active-bg, var(--navbar-dropdown-hover-bg, color-mix(in srgb, var(--site-accent, currentColor) 12%, transparent)));
  color: var(--navbar-dropdown-active-text, var(--navbar-dropdown-text, var(--site-text, currentColor)));
}
.el-navbar__dropdown-item svg,
.el-navbar__dropdown-item .el-navbar__chevron-right {
  color: var(--navbar-dropdown-item-icon-color, currentColor);
}
.el-navbar__dropdown-item a {
  color: inherit;
  text-decoration: none;
  flex: 1;
}

/* ── Flyout (3rd level) ──────────────────────────────────── */
.el-navbar__flyout {
  position: relative;
}
.el-navbar__flyout-trigger {
  display: flex;
  align-items: center;
  justify-content: space-between;
  width: 100%;
}
.el-navbar__chevron-right {
  flex-shrink: 0;
  margin-left: 0.5rem;
  opacity: 0.72;
  transition: transform 0.2s ease, opacity 0.2s ease, color 0.2s ease;
}
.el-navbar__flyout--open .el-navbar__chevron-right {
  transform: rotate(90deg);
}
.el-navbar__flyout-menu {
  position: absolute;
  left: calc(100% + 10px);
  top: -6px;
  min-width: 220px;
  background: color-mix(in srgb, var(--navbar-dropdown-bg, var(--site-surface)) 92%, rgba(255,255,255,0.55));
  border: 1px solid rgba(26,39,68,0.08);
  border-radius: var(--navbar-dropdown-radius, 22px);
  box-shadow: 0 calc(var(--navbar-dropdown-shadow-alpha, 20px) * 0.6) var(--navbar-dropdown-shadow-alpha, 20px) rgba(15, 23, 42, 0.1);
  padding: 0.55rem;
  /* Stays above its parent dropdown-menu (z-index 520). */
  z-index: 530;
  animation: el-navbar-flyIn 0.15s ease;
  backdrop-filter: blur(16px);
}
/* Invisible bridge between parent menu and flyout */
.el-navbar__flyout-menu::before {
  content: '';
  position: absolute;
  top: 0;
  right: 100%;
  width: 12px;
  height: 100%;
}
@keyframes el-navbar-flyIn {
  from { opacity: 0; transform: translateX(-4px); }
  to { opacity: 1; transform: translateX(0); }
}
@media (prefers-reduced-motion: reduce) {
  .el-navbar__flyout-menu { animation: none; }
}

/* Compact link gap on mid-range viewports */
/* was @media(max-width:1320px); bucketed to mobile+tablet (1320 > 1024 — desktop drift accepted) */
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-navbar__inner { gap: 1rem; }
  .el-navbar__logo { max-width: min(30vw, 300px); }
  .el-navbar__brand-name {
    font-size: 1rem;
    max-width: min(24vw, 260px);
  }
  .el-navbar__links { gap: 1.05rem; }
  .el-navbar__link,
  .el-navbar__dropdown-trigger {
    font-size: 0.83rem;
    letter-spacing: 0.028em;
  }
  .el-navbar__cta--desktop {
    font-size: 0.82rem;
    padding-inline: 0.95rem;
  }
  .el-navbar--transparent-to-solid {
    /* Tightened pill inset at <=1100px — Section Container Contract:
       horizontal inset lives on parent padding, not __inner margin. */
    padding-left: max(calc(var(--navbar-shell-inset-x, 16px) - 2px), 8px);
    padding-right: max(calc(var(--navbar-shell-inset-x, 16px) - 2px), 8px);
  }
  .el-navbar--transparent-to-solid .el-navbar__inner {
    margin-top: max(calc(var(--navbar-shell-inset-top, 14px) - 2px), 8px);
    margin-bottom: max(calc(var(--navbar-shell-inset-bottom, 14px) - 2px), 8px);
  }
}
@media (max-width: 1320px) {
  .el-navbar__inner { gap: 1rem; }
  .el-navbar__logo { max-width: min(30vw, 300px); }
  .el-navbar__brand-name {
    font-size: 1rem;
    max-width: min(24vw, 260px);
  }
  .el-navbar__links { gap: 1.05rem; }
  .el-navbar__link,
  .el-navbar__dropdown-trigger {
    font-size: 0.83rem;
    letter-spacing: 0.028em;
  }
  .el-navbar__cta--desktop {
    font-size: 0.82rem;
    padding-inline: 0.95rem;
  }
  .el-navbar--transparent-to-solid {
    /* Tightened pill inset at <=1100px — Section Container Contract:
       horizontal inset lives on parent padding, not __inner margin. */
    padding-left: max(calc(var(--navbar-shell-inset-x, 16px) - 2px), 8px);
    padding-right: max(calc(var(--navbar-shell-inset-x, 16px) - 2px), 8px);
  }
  .el-navbar--transparent-to-solid .el-navbar__inner {
    margin-top: max(calc(var(--navbar-shell-inset-top, 14px) - 2px), 8px);
    margin-bottom: max(calc(var(--navbar-shell-inset-bottom, 14px) - 2px), 8px);
  }
}

/* was @media(max-width:1100px); bucketed to mobile+tablet (1100 > 1024 — desktop drift accepted) */
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-navbar__logo { max-width: min(28vw, 260px); }
  .el-navbar__brand-name {
    font-size: 0.95rem;
    max-width: min(22vw, 240px);
  }
  .el-navbar__links { gap: 0.9rem; }
  .el-navbar__link,
  .el-navbar__dropdown-trigger {
    font-size: 0.8rem;
    letter-spacing: 0.024em;
  }
  .el-navbar__cta--desktop {
    font-size: 0.78rem;
    padding-inline: 0.8rem;
  }
  .el-navbar--transparent-to-solid .el-navbar__inner {
    min-height: 66px;
  }
}
@media (max-width: 1100px) {
  .el-navbar__logo { max-width: min(28vw, 260px); }
  .el-navbar__brand-name {
    font-size: 0.95rem;
    max-width: min(22vw, 240px);
  }
  .el-navbar__links { gap: 0.9rem; }
  .el-navbar__link,
  .el-navbar__dropdown-trigger {
    font-size: 0.8rem;
    letter-spacing: 0.024em;
  }
  .el-navbar__cta--desktop {
    font-size: 0.78rem;
    padding-inline: 0.8rem;
  }
  .el-navbar--transparent-to-solid .el-navbar__inner {
    min-height: 66px;
  }
}

.el-navbar--scrolled .el-navbar__chevron,
.el-navbar--scrolled .el-navbar__chevron-right {
  color: var(--navbar-text-scrolled, var(--site-text)) !important;
  opacity: 0.64;
}

.el-navbar__links--open .el-navbar__chevron,
.el-navbar__links--open .el-navbar__chevron-right {
  color: inherit !important;
  opacity: 0.68;
}

@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  /* Sticky behavior preserved for transparent-to-solid; floating navbars
     keep their own positioning rules elsewhere in this file. */
  .el-navbar--transparent-to-solid {
    position: sticky;
    top: 0;
    left: 0;
    right: auto;
    z-index: 1000;
  }
  /* Universal mobile + tablet policy: floating + transparent-to-solid pill
     navbars drop their side inset and corner radius at ≤1024px so the nav
     matches the rest of the page going edge-to-edge on every non-desktop
     size. !important is required to beat the per-element scoped CSS that
     NavbarRenderer emits for responsiveProps.mobile|tablet.shellInsetX /
     shellRadius (those only set the CSS variable; direct property
     declarations win regardless). */
  .el-navbar--floating,
  .el-navbar--transparent-to-solid {
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  .el-navbar--floating .el-navbar__inner,
  .el-navbar--transparent-to-solid .el-navbar__inner {
    min-height: 62px;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    border-radius: 0 !important;
    /* No border / shadow on the flat full-width shell — any chrome
       looks misplaced flush against the page below desktop. */
    border: 0 !important;
    box-shadow: none !important;
  }
  /* The drop-down search drawer and mobile menu both reference
     --navbar-shell-radius for their bottom corners — when the pill goes
     flat the drawer should match. */
  .el-navbar--floating .el-navbar__search-drawer,
  .el-navbar--transparent-to-solid .el-navbar__search-drawer,
  .el-navbar--floating .el-navbar__search-drawer--open,
  .el-navbar--transparent-to-solid .el-navbar__search-drawer--open {
    border-radius: 0 !important;
  }

  /* Center the CTA cluster between the logo (left) and the hamburger
     (right) on mobile + tablet. Trick: an auto-margin on the FIRST CTA
     and another on the hamburger (mobile-actions) splits the row's
     leftover space equally, so the CTAs land in the middle while the
     hamburger anchors the right edge. order:99 forces the hamburger to
     the end of the flex row regardless of DOM source order — in the
     base DOM `.el-navbar__mobile-actions` sits between the logo and
     the desktop CTAs, but at this breakpoint we want it last.
     The chained selector zeros the auto-margin on every CTA AFTER the
     first so the cluster keeps its native gap between buttons. */
  .el-navbar__inner > .el-navbar__cta--desktop {
    margin-left: auto !important;
  }
  .el-navbar__inner > .el-navbar__cta--desktop ~ .el-navbar__cta--desktop {
    margin-left: 0 !important;
  }
  .el-navbar__inner > .el-navbar__mobile-actions {
    margin-left: auto !important;
    order: 99;
  }
}
@media (max-width: 1024px) {
  /* Sticky behavior preserved for transparent-to-solid; floating navbars
     keep their own positioning rules elsewhere in this file. */
  .el-navbar--transparent-to-solid {
    position: sticky;
    top: 0;
    left: 0;
    right: auto;
    z-index: 1000;
  }
  /* Universal mobile + tablet policy: floating + transparent-to-solid pill
     navbars drop their side inset and corner radius at ≤1024px so the nav
     matches the rest of the page going edge-to-edge on every non-desktop
     size. !important is required to beat the per-element scoped CSS that
     NavbarRenderer emits for responsiveProps.mobile|tablet.shellInsetX /
     shellRadius (those only set the CSS variable; direct property
     declarations win regardless). */
  .el-navbar--floating,
  .el-navbar--transparent-to-solid {
    padding-left: 0 !important;
    padding-right: 0 !important;
  }
  .el-navbar--floating .el-navbar__inner,
  .el-navbar--transparent-to-solid .el-navbar__inner {
    min-height: 62px;
    margin-top: 0 !important;
    margin-bottom: 0 !important;
    border-radius: 0 !important;
    /* No border / shadow on the flat full-width shell — any chrome
       looks misplaced flush against the page below desktop. */
    border: 0 !important;
    box-shadow: none !important;
  }
  /* The drop-down search drawer and mobile menu both reference
     --navbar-shell-radius for their bottom corners — when the pill goes
     flat the drawer should match. */
  .el-navbar--floating .el-navbar__search-drawer,
  .el-navbar--transparent-to-solid .el-navbar__search-drawer,
  .el-navbar--floating .el-navbar__search-drawer--open,
  .el-navbar--transparent-to-solid .el-navbar__search-drawer--open {
    border-radius: 0 !important;
  }

  /* Center the CTA cluster between the logo (left) and the hamburger
     (right) on mobile + tablet. Trick: an auto-margin on the FIRST CTA
     and another on the hamburger (mobile-actions) splits the row's
     leftover space equally, so the CTAs land in the middle while the
     hamburger anchors the right edge. order:99 forces the hamburger to
     the end of the flex row regardless of DOM source order — in the
     base DOM `.el-navbar__mobile-actions` sits between the logo and
     the desktop CTAs, but at this breakpoint we want it last.
     The chained selector zeros the auto-margin on every CTA AFTER the
     first so the cluster keeps its native gap between buttons. */
  .el-navbar__inner > .el-navbar__cta--desktop {
    margin-left: auto !important;
  }
  .el-navbar__inner > .el-navbar__cta--desktop ~ .el-navbar__cta--desktop {
    margin-left: 0 !important;
  }
  .el-navbar__inner > .el-navbar__mobile-actions {
    margin-left: auto !important;
    order: 99;
  }
}

/* ── Base wrapper ─────────────────────────────────────────── */
.el {
  position: relative;
  box-sizing: border-box;
}
/* Navbar must override base .el position for sticky to work */
.el.el--navbar {
  position: sticky;
  top: 0;
  z-index: 1000;
}

/* ── Section Vertical Rhythm Contract ─────────────────────── */
/* Single source of truth for top/bottom padding on every section-level
   element on every public site. Active token `--site-section-pad-y` is
   swapped at the project breakpoints (1024 tablet, 768 mobile). Sites
   override per-tenant via the design panel (`Section Spacing` group);
   templates can override in their ThemeProvider tokens. Horizontal
   gutter stays on `--site-content-gutter` — the site-container contract
   owns the X axis.

   See SKILL.md § Section Vertical Rhythm Contract for the override
   hierarchy and the no-hardcode-padding-y rule for new section elements.

   Mirrors `src/components/public/CriticalCss.tsx` so the rhythm is set
   above-the-fold during SSR before this stylesheet arrives. */
:root { --site-section-pad-y: var(--site-section-pad-y-desktop, 5rem); }
@container site style(--site-bp: mobile) or style(--site-bp: tablet) { :root { --site-section-pad-y: var(--site-section-pad-y-tablet, 4rem); } }
@media (max-width: 1024px) { :root { --site-section-pad-y: var(--site-section-pad-y-tablet, 4rem); } }
@container site style(--site-bp: mobile) { :root { --site-section-pad-y: var(--site-section-pad-y-mobile, 3rem); } }
@media (max-width: 768px)  { :root { --site-section-pad-y: var(--site-section-pad-y-mobile, 3rem); } }

/* ── Root-level element padding ──────────────────────────── */
/* Elements at root level (not inside a section) need their own padding.
   Inside sections, the section provides padding. Vertical padding reads
   from the rhythm token above; horizontal padding stays on the gutter. */
.el--stats:not(.el-section__inner *) { padding: 0; }
.el--gallery:not(.el-section__inner *) {
  padding-block: var(--site-section-pad-y);
}
.el--contact-section:not(.el-section__inner *) {
  padding-block: var(--site-section-pad-y);
}
.el--feature-cards:not(.el-section__inner *) {
  padding-block: var(--site-section-pad-y);
}
.el--team:not(.el-section__inner *) {
  padding-block: var(--site-section-pad-y);
}

/* ── Button wrapper — inline by default, wraps on mobile ──── */
.el--button { display: inline-block; margin: 0.25rem 0.5rem 0.25rem 0; }
/* was @media(max-width:480px); bucketed to mobile (480 ≤ 768) */
@container site style(--site-bp: mobile) { .el--button { display: block; margin: 0.5rem 0; } }
@media (max-width: 480px) { .el--button { display: block; margin: 0.5rem 0; } }

/* ── Visibility ───────────────────────────────────────────── */
/* was @media(max-width:480px); bucketed to mobile (480 ≤ 768) */
@container site style(--site-bp: mobile) {
  .el--hide-mobile { display: none !important; }
}
@media (max-width: 480px) {
  .el--hide-mobile { display: none !important; }
}
/* was @media(min-width:481px) and (max-width:768px); both bounds fall in the
   mobile bucket under the 3-bucket scheme (mobile <768, tablet 768–1023). The
   .el--hide-tablet label is preserved for the legacy @media path; the
   container path fires within the same mobile bucket. */
@container site style(--site-bp: mobile) {
  .el--hide-tablet { display: none !important; }
}
@media (min-width: 481px) and (max-width: 768px) {
  .el--hide-tablet { display: none !important; }
}
/* was @media(min-width:769px); bucketed to tablet+desktop (769 ≥ 768) */
@container site style(--site-bp: tablet) or style(--site-bp: desktop) {
  .el--hide-desktop { display: none !important; }
}
@media (min-width: 769px) {
  .el--hide-desktop { display: none !important; }
}

/* ── Unknown element (dev only) ───────────────────────────── */
.el-unknown {
  padding: 1rem;
  border: 2px dashed var(--site-border);
  border-radius: var(--site-radius, 8px);
  background: var(--site-surface-alt);
  text-align: center;
  font-family: var(--site-font-body);
}
.el-unknown__label {
  color: var(--site-text-muted);
  font-size: 13px;
  font-weight: 500;
}

/* ── Section ──────────────────────────────────────────────── */
/* Section — vertical padding from the rhythm token (single source of
   truth for every section element on every site). Horizontal padding is
   the site gutter so all section types share the same edge-to-content
   distance. See § Section Vertical Rhythm Contract above. */
.el-section {
  width: 100%;
  padding-block: var(--site-section-pad-y);
  box-sizing: border-box;
  position: relative;
}
.el-section__overlay {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.el-section__inner {
  width: 100%;
  position: relative;
  z-index: 1;
}
/* Section scrim — painted by SECTION_OVERLAY_FIELDS. Sits between the section's
   background media and its content; content stays legible because .el-section__inner
   is forced above via z-index: 1. Opacity is 0 by default so this is a no-op
   until the builder sets overlayOpacity > 0 or overlayColor. */
.el-section::before,
.el-editorial-marquee::before,
.el-cta-band::before,
.el-page-header::before,
.el-hero::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: var(--el-overlay-bg, transparent);
  opacity: var(--el-overlay-opacity, 0);
  border-radius: inherit;
}
/* Hero scrim default — when the inspector hasn't set overlayOpacity/overlayColor
   the renderer falls through to these CSS-level defaults so a hero with a
   background image stays legible out of the box. Inspector-set inline-style vars
   (via ElementWrapper) win because element-style is more specific than the rule.
   Color comes from --site-overlay-scrim (or the dark text token) so re-skinning works. */
.el-hero::before {
  background: var(--el-overlay-bg, var(--site-overlay-scrim, var(--site-text)));
  opacity: var(--el-overlay-opacity, 0.5);
}
/* Section backgrounds are set deterministically via template styleProps.
   No CSS nth-child rules — alternation is controlled by the sec() helper
   in pageTemplates.ts which passes backgroundColor: '$surfaceAlt' to even sections.
   Mobile padding-y is now driven by the `--site-section-pad-y` cascade at
   the top of this file — no per-element media query needed. */

/* ── Columns ──────────────────────────────────────────────── */
.el-columns {
  width: 100%;
  grid-template-columns: repeat(var(--el-grid-cols, 2), 1fr);
}
@container site style(--site-bp: mobile) {
  .el-columns {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 768px) {
  .el-columns {
    grid-template-columns: 1fr;
  }
}

/* ── Divider ──────────────────────────────────────────────── */
.el-divider {
  border: none;
  border-top: var(--divider-thickness, 1px) solid var(--divider-color, var(--site-border));
  margin: 1.5rem auto;
  width: var(--divider-max-width, 100%);
  opacity: var(--divider-opacity, 1);
}
.el-divider--dashed {
  border-top-style: dashed;
}
.el-divider--dotted {
  border-top-style: dotted;
}
.el-divider--gradient {
  border: none;
  height: var(--divider-thickness, 2px);
  background: linear-gradient(
    var(--divider-gradient-angle, 90deg),
    var(--divider-gradient-start, var(--site-primary)) 0%,
    var(--divider-gradient-end, var(--site-accent)) 100%
  );
}

/* ── Spacer ───────────────────────────────────────────────── */
.el-spacer {
  width: 100%;
}

/* ── Section variants ────────────────────────────────────── */

.el-section--dark {
  background: var(--site-fg);
  color: var(--site-bg, currentColor);
}
.el-section--dark .el-section__inner {
  color: var(--site-bg, currentColor);
}

.el-section--highlight {
  background: color-mix(in srgb, var(--site-primary) 8%, var(--site-surface, transparent));
}

.el-section--narrow .el-section__inner:not(.el-site-container) {
  max-width: 800px;
  margin-left: auto;
  margin-right: auto;
}

/* ── General layout variants ─────────────────────────────── */

.el-layout--parallax {
  background-attachment: fixed;
}

.el-layout--full-bleed {
  margin-left: calc(-50vw + 50%);
  margin-right: calc(-50vw + 50%);
  width: 100vw;
}

/* ============================================================
   Accessibility — WCAG 2.1 AA compliance
   ============================================================ */

/* ── Skip navigation ─────────────────────────────────────────── */
.skip-nav {
  position: absolute;
  top: -100%;
  left: 16px;
  z-index: 10000;
  padding: 12px 24px;
  background: var(--site-primary);
  color: var(--site-primary-fg, currentColor);
  font-size: 14px;
  font-weight: 600;
  text-decoration: none;
  border-radius: 0 0 8px 8px;
  transition: top 0.15s ease;
}
.skip-nav:focus {
  top: 0;
  outline: 2px solid var(--site-primary);
  outline-offset: 2px;
}

/* ── Reduced motion — disable ALL animations and transitions ── */
@media (prefers-reduced-motion: reduce) {
  .el-animate {
    transition: none !important;
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
  .el-countdown__value {
    transition: none !important;
    animation: none !important;
  }
  .el-before-after__handle {
    transition: none !important;
  }
  .cta-btn:hover,
  .el-back-to-top:hover,
  .el-live-chat:hover {
    transform: none !important;
  }
  .el-modal__overlay,
  .el-modal__backdrop,
  .el-modal__dialog {
    transition: none !important;
    animation: none !important;
  }
  .el-accordion__panel {
    transition: none !important;
  }
  .el-tabs__panel {
    transition: none !important;
  }
  /* Disable carousel/slider auto-play transition effects */
  .el-carousel__track,
  .el-slider__track {
    transition: none !important;
  }
}

/* ── Focus visible — consistent focus ring on ALL interactive elements ── */
:focus-visible {
  outline: 2px solid var(--site-primary);
  outline-offset: 2px;
}

/* ── High contrast mode support ──────────────────────────────── */
@media (forced-colors: active) {
  .cta-btn {
    border: 2px solid ButtonText;
  }
  .el-cookie-consent {
    border: 1px solid CanvasText;
  }
  .el-modal__dialog {
    border: 2px solid CanvasText;
  }
  .el-accordion__trigger {
    border: 1px solid ButtonText;
  }
  .el-tabs__tab {
    border: 1px solid ButtonText;
  }
  .el-tabs__tab--active {
    border-bottom: 3px solid Highlight;
  }
  .el-before-after__handle {
    border: 2px solid ButtonText;
  }
  .skip-nav {
    border: 2px solid ButtonText;
  }
}

/* ── Screen reader only utility ──────────────────────────────── */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}


/* First content section after hero+stats — reduce top gap */
.el--hero + .el--stats + .el--section .el-section { padding-top: 3rem; }

/* Mobile: tighter section spacing.
   `.el-section` and `.el-cta-band` padding-y now flow from the
   `--site-section-pad-y` rhythm cascade — the per-element overrides
   that used to live here were duplicating the rhythm-token mobile
   value and have been removed. */
@container site style(--site-bp: mobile) {
  .property-card__actions a { padding: 0.5rem 1rem; font-size: 0.75rem; }
  .property-detail-module { padding: 16px; }
  .el--button { display: block; margin: 0.375rem 0; }
  .el--button .cta-btn { width: 100%; justify-content: center; }
}
@media (max-width: 768px) {
  .property-card__actions a { padding: 0.5rem 1rem; font-size: 0.75rem; }
  .property-detail-module { padding: 16px; }
  .el--button { display: block; margin: 0.375rem 0; }
  .el--button .cta-btn { width: 100%; justify-content: center; }
}

/* Contact map — hide when empty */
.el-contact-section__map:empty,
.el-contact-section__map-placeholder { display: none; }

/* Cookie banner — reduce visual dominance */
.cookie-consent {
  max-width: 420px !important;
  font-size: 0.8125rem !important;
  box-shadow: 0 -4px 24px rgba(0,0,0,0.08) !important;
}

/* Footer nav list — tighter spacing */
.site-footer__nav li { margin-bottom: 6px; }

/* ── Footer ────────────────────────────────────────────────── */
/* ── Footer ──────────────────────────────────────────────── */
.el-footer {
  background: var(--footer-panel-bg, var(--site-primary));
  color: var(--site-primary-fg);
  padding-block: var(--site-space-section, 4rem) var(--site-space-md, 2rem);
}
.el-footer__brand-name {
  color: var(--site-primary-fg);
}
.el-footer__column-heading {
  color: var(--footer-column-heading-color, var(--site-primary-fg));
}
.el-footer__tagline {
  color: var(--footer-tagline-color, currentColor);
}
.el-footer__link {
  color: var(--footer-link-color, currentColor);
}
.el-footer__social-link {
  color: var(--footer-social-icon-color, currentColor);
}
.el-footer__compliance-label {
  color: var(--footer-compliance-text-color, currentColor);
}
.el-footer__copyright {
  color: var(--footer-copyright-color, currentColor);
}
.el-footer__powered-by,
.el-footer__powered-by a {
  color: var(--footer-powered-by-color, currentColor);
}
.el-footer__link:hover,
.el-footer__link:focus-visible,
.el-footer__powered-by a:hover,
.el-footer__powered-by a:focus-visible {
  color: var(--footer-link-hover-color, var(--site-accent, currentColor));
  background: var(--footer-link-hover-bg, transparent);
}
.el-footer__social-link:hover,
.el-footer__social-link:focus-visible {
  color: var(--footer-social-icon-hover-color, var(--site-accent, currentColor));
}
.el-footer__link:focus-visible,
.el-footer__social-link:focus-visible,
.el-footer__powered-by a:focus-visible {
  outline: 2px solid var(--footer-link-hover-color, var(--site-accent, currentColor));
  outline-offset: 2px;
  border-radius: 2px;
}
/* Active page state — set by FooterRenderer via aria-current="page". CSS vars
   come from builder fields (activeBg/activeTextColor/activeBorderColor/activeFontWeight). */
.el-footer__link[aria-current="page"] {
  color: var(--footer-link-active-color, var(--footer-link-hover-color, var(--site-accent, currentColor)));
  background: var(--footer-link-active-bg, transparent);
  border: 1px solid var(--footer-link-active-border, transparent);
  font-weight: var(--footer-link-active-weight, 600);
}
.el-footer__top-border,
.el-footer__bottom-border {
  border-top: 1px solid rgba(255,255,255,0.25);
  display: block;
  width: 100%;
  min-height: 1px;
  max-width: var(--site-max-width, 1280px);
  margin: 0 auto;
  padding-top: 0;
  box-sizing: border-box;
}
.el-footer__container {
  display: flex;
  flex-direction: column;
}

/* ── Main row: brand + columns ── */
.el-footer__main {
  display: grid;
  align-items: start;
}
.el-footer--brand-left .el-footer__main {
  grid-template-columns: minmax(220px, 1fr) minmax(0, 2fr);
}
.el-footer--stacked .el-footer__main { grid-template-columns: 1fr; justify-items: center; text-align: center; }
.el-footer--columns-first .el-footer__main { grid-template-columns: 1fr; justify-items: center; }
.el-footer--columns-first .el-footer__brand-section { order: 2; }
.el-footer--columns-first .el-footer__columns { order: 1; }
.el-footer--minimal .el-footer__main { grid-template-columns: 1fr; justify-items: center; text-align: center; }

/* ── Brand section ── */
.el-footer__brand-section {
  display: flex;
  flex-direction: column;
  gap: var(--footer-brand-gap, 0.75rem);
  flex-shrink: 0;
  max-width: min(var(--footer-brand-section-max-width, 320px), 100%);
}
.el-footer--brand-left .el-footer__brand-section {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  column-gap: var(--footer-brand-gap, 0.75rem);
  row-gap: 0.875rem;
}
.el-footer--brand-left .el-footer__brand-section .el-footer__tagline,
.el-footer--brand-left .el-footer__brand-section .el-footer__status {
  grid-column: 1 / -1;
}

/* ── Live status card (2026 glassmorphism) ──
   Sits inside the brand-section, below tagline / brandDescription.
   Card with large animated circular gauge on top + summary pill below.
   Fully token-driven so per-site theming is automatic.
*/
.el-footer__status {
  --footer-status-bg: rgba(15,23,42,0.72);
  --footer-status-border: rgba(148,163,184,0.22);
  --footer-status-border-hover: rgba(34,197,94,0.42);
  --footer-status-color: rgba(226,232,240,0.88);
  --footer-status-badge-bg: rgba(15,23,42,0.62);
  --footer-status-badge-border: rgba(148,163,184,0.22);
  --footer-status-badge-color: rgba(203,213,225,0.82);
  --footer-status-live-bg: rgba(16,185,129,0.12);
  --footer-status-live-border: rgba(52,211,153,0.32);
  --footer-status-live-color: rgba(209,250,229,0.94);
  --footer-status-live-dot: #34d399;
  --footer-status-dot-up: #34d399;
  --footer-status-pill-bg: rgba(15,23,42,0.48);
  --footer-status-pill-border: rgba(148,163,184,0.18);
  --footer-status-divider: rgba(148,163,184,0.34);
  --footer-status-rt-color: rgba(226,232,240,0.9);
  --footer-status-gauge-track: rgba(148,163,184,0.18);
  --footer-status-gauge-glow: rgba(34,197,94,0.5);
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 0.85rem;
  padding: 0.95rem 1.125rem 1.05rem;
  border-radius: 20px;
  width: 100%;
  isolation: isolate;
  text-decoration: none;
  background:
    linear-gradient(155deg, rgba(255,255,255,0.10) 0%, rgba(255,255,255,0.02) 60%, rgba(255,255,255,0) 100%),
    var(--footer-status-bg, transparent);
  border: 1px solid var(--footer-status-border, transparent);
  color: var(--footer-status-color, var(--footer-tagline-color, currentColor));
  backdrop-filter: blur(18px) saturate(160%);
  -webkit-backdrop-filter: blur(18px) saturate(160%);
  box-shadow:
    inset 0 1px 0 0 rgba(255,255,255,0.10),
    inset 0 -1px 0 0 rgba(0,0,0,0.20),
    0 12px 36px -14px rgba(0,0,0,0.45);
  overflow: hidden;
  transition: border-color 0.3s ease, transform 0.3s ease, box-shadow 0.3s ease;
}

/* Aurora — soft animated blob behind the gauge. Sits below content via z-index
   on the card-level isolation context. Subtle, premium, never busy. */
.el-footer__status::after {
  /* Ambient corner blobs only — pulled away from the gauge center so they
     stop drowning out the gauge pulse. Lower opacity, cooler hues. */
  content: "";
  position: absolute;
  inset: -30%;
  background:
    radial-gradient(40% 30% at 12% 88%, rgba(56,189,248,0.10) 0%, transparent 65%),
    radial-gradient(40% 30% at 88% 12%, rgba(167,139,250,0.08) 0%, transparent 65%);
  filter: blur(22px);
  opacity: 0;
  transition: opacity 1.2s ease;
  pointer-events: none;
  z-index: 0;
  animation: el-footer-status-aurora 18s ease-in-out infinite alternate;
}
.el-footer__status--visible::after { opacity: 1; }
@keyframes el-footer-status-aurora {
  0%   { transform: translate(0, 0) scale(1);   }
  50%  { transform: translate(4%, -3%) scale(1.05); }
  100% { transform: translate(-3%, 4%) scale(0.97); }
}
.el-footer__status > * { position: relative; z-index: 1; }

/* Subtle gradient seam at the top edge of the card — premium SaaS hairline. */
.el-footer__status::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 1px;
  background: linear-gradient(90deg,
    transparent 0%,
    rgba(255,255,255,0.18) 30%,
    rgba(34,197,94,0.45) 50%,
    rgba(255,255,255,0.18) 70%,
    transparent 100%
  );
  pointer-events: none;
  z-index: 2;
}

/* Header banner — eyebrow row with live indicator + 30-day label. */
.el-footer__status-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.75rem;
  width: 100%;
  padding: 0 0.125rem;
}
/* Unified badge — both LIVE and 30-DAY UPTIME use this base; modifiers
   tint the LIVE one green to signal real-time status. Identical typography. */
.el-footer__status-badge {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  padding: 0.3rem 0.6rem 0.3rem 0.55rem;
  border-radius: 999px;
  background: var(--footer-status-badge-bg, transparent);
  border: 1px solid var(--footer-status-badge-border, transparent);
}
.el-footer__status-badge--live {
  padding-left: 0.45rem;
  background: var(--footer-status-live-bg, transparent);
  border-color: var(--footer-status-live-border, transparent);
}
.el-footer__status-badge-text {
  font-size: 10px;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--footer-status-badge-color, currentColor);
  line-height: 1;
}
.el-footer__status-badge--live .el-footer__status-badge-text {
  color: var(--footer-status-live-color, currentColor);
}
.el-footer__status-live-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--footer-status-live-dot, transparent);
  box-shadow: 0 0 8px rgba(34,197,94,0.7);
  animation: el-footer-status-live-blink 2s ease-in-out infinite;
}
@keyframes el-footer-status-live-blink {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.35; }
}

.el-footer__status:hover {
  border-color: var(--footer-status-border-hover, transparent);
  box-shadow:
    inset 0 1px 0 0 rgba(255,255,255,0.14),
    0 18px 44px -14px rgba(34,197,94,0.28);
}
.el-footer__status--up {
  --footer-status-pulse-core: rgba(52,211,153,0.62);
  --footer-status-pulse-mid: rgba(16,185,129,0.24);
  --footer-status-pulse-color: rgba(52,211,153,0.48);
}
.el-footer__status--degraded {
  --footer-status-pulse-color: rgba(245,158,11,0.58);
  --footer-status-gauge-glow: rgba(245,158,11,0.5);
}
.el-footer__status--down {
  --footer-status-pulse-color: rgba(239,68,68,0.6);
  --footer-status-gauge-glow: rgba(239,68,68,0.55);
}
.el-footer__status--unknown {
  --footer-status-pulse-color: transparent;
  --footer-status-gauge-glow: transparent;
}

/* Soft pulsing glow that lives behind the SVG ring. Always-on once the
   card is visible — gentle, rhythmic, sits below the ring without competing. */
.el-footer__status-gauge-pulse {
  position: absolute;
  inset: 6%;
  border-radius: 50%;
  background: radial-gradient(
    circle,
    var(--footer-status-pulse-core, transparent) 0%,
    var(--footer-status-pulse-mid, transparent) 38%,
    transparent 72%
  );
  box-shadow: 0 0 18px var(--footer-status-pulse-color, transparent);
  filter: blur(8px);
  z-index: 0;
  pointer-events: none;
  animation: el-footer-status-gauge-pulse 1.8s ease-in-out infinite;
  mix-blend-mode: screen;
  will-change: opacity, transform;
}
.el-footer__status-gauge-pulse::after {
  content: "";
  position: absolute;
  inset: 10%;
  border-radius: 50%;
  border: 2px solid var(--footer-status-pulse-color, transparent);
  opacity: 0.5;
  animation: el-footer-status-gauge-pulse-ring 1.8s ease-out infinite;
}
.el-footer__status-gauge-pulse--degraded {
  background: radial-gradient(
    circle,
    rgba(245,158,11,0.85) 0%,
    rgba(245,158,11,0.45) 30%,
    transparent 70%
  );
}
.el-footer__status-gauge-pulse--down {
  background: radial-gradient(
    circle,
    rgba(239,68,68,0.85) 0%,
    rgba(239,68,68,0.45) 30%,
    transparent 70%
  );
}
.el-footer__status-gauge-pulse--unknown {
  background: radial-gradient(circle, rgba(148,163,184,0.4) 0%, transparent 70%);
  animation: none;
}
@keyframes el-footer-status-gauge-pulse {
  0%, 100% { opacity: 0.38; transform: scale(0.92); }
  50%      { opacity: 0.74; transform: scale(1.06); }
}
@keyframes el-footer-status-gauge-pulse-ring {
  0%   { opacity: 0.56; transform: scale(0.86); }
  100% { opacity: 0;    transform: scale(1.16); }
}
@media (prefers-reduced-motion: reduce) {
  .el-footer__status-gauge-pulse,
  .el-footer__status-gauge-pulse::after { animation: none; }
}

/* Large gauge — circle with gradient ring + count-up percentage centered */
.el-footer__status-gauge {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 116px;
  height: 116px;
  flex-shrink: 0;
}
.el-footer__status-gauge-svg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  transform: rotate(-90deg);
  overflow: visible;
  z-index: 2;
}
.el-footer__status-gauge-track {
  fill: none;
  stroke: var(--footer-status-gauge-track, currentColor);
  stroke-width: 6;
}
.el-footer__status-gauge-ring {
  fill: none;
  stroke-width: 6;
  stroke-linecap: round;
  filter: drop-shadow(0 0 10px var(--footer-status-gauge-glow, transparent));
  /* No CSS transition — RAF drives the dash every frame and any CSS interp
     fights it, producing the visible "freeze + jump" the user reported. */
}
.el-footer__status-gauge-ring--degraded { filter: drop-shadow(0 0 10px rgba(245,158,11,0.5)); }
.el-footer__status-gauge-ring--down     { filter: drop-shadow(0 0 10px rgba(239,68,68,0.55)); }
.el-footer__status-gauge-ring--unknown  { filter: none; }

/* "Fresh" ring — full-circle stroke that fades in after the original ring
   blows out at 100%. Initially invisible; the --burst modifier triggers
   the choreographed blow-out + fade-in pair so the gauge cleanly resets
   to a satisfied "filled" state. */
.el-footer__status-gauge-ring--fresh {
  fill: none;
  stroke-width: 6;
  stroke-linecap: round;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  transform: scale(0.85);
  filter: drop-shadow(0 0 12px var(--footer-status-gauge-glow));
}
.el-footer__status-gauge-ring-fresh--up      { filter: drop-shadow(0 0 14px rgba(34,197,94,0.6)); }
.el-footer__status-gauge-ring-fresh--degraded{ filter: drop-shadow(0 0 14px rgba(245,158,11,0.55)); }
.el-footer__status-gauge-ring-fresh--down    { filter: drop-shadow(0 0 14px rgba(239,68,68,0.55)); }

/* Blow-out: the animated ring scales out + fades. Fires once at 100%. */
.el-footer__status--burst .el-footer__status-gauge-ring {
  transform-box: fill-box;
  transform-origin: center;
  animation: el-footer-status-ring-blowout 900ms cubic-bezier(0.22, 0.61, 0.36, 1) forwards;
}
/* Fresh ring fades in shortly after the blow-out begins. */
.el-footer__status--burst .el-footer__status-gauge-ring--fresh {
  animation: el-footer-status-ring-fresh-in 950ms cubic-bezier(0.16, 1, 0.3, 1) 350ms forwards;
}
@keyframes el-footer-status-ring-blowout {
  0%   { opacity: 1; transform: scale(1); }
  55%  { opacity: 0; transform: scale(1.55); }
  100% { opacity: 0; transform: scale(1.6); }
}
@keyframes el-footer-status-ring-fresh-in {
  0%   { opacity: 0;   transform: scale(0.86); }
  55%  { opacity: 1;   transform: scale(1.06); }
  100% { opacity: 1;   transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .el-footer__status--burst .el-footer__status-gauge-ring,
  .el-footer__status--burst .el-footer__status-gauge-ring--fresh { animation: none; }
  .el-footer__status--burst .el-footer__status-gauge-ring { opacity: 0; }
  .el-footer__status--burst .el-footer__status-gauge-ring--fresh { opacity: 1; transform: scale(1); }
}
.el-footer__status-pct {
  position: relative;
  z-index: 3;
  font-weight: 800;
  font-size: 26px;
  line-height: 1;
  letter-spacing: -0.025em;
  font-variant-numeric: tabular-nums;
  background: linear-gradient(135deg, #fff 0%, #d1fae5 50%, #86efac 100%);
  -webkit-background-clip: text;
  background-clip: text;
  -webkit-text-fill-color: transparent;
  filter: drop-shadow(0 0 12px rgba(34,197,94,0.35));
}
.el-footer__status-pct--degraded {
  background: linear-gradient(135deg, #fff 0%, #fef3c7 50%, #fcd34d 100%);
  -webkit-background-clip: text;
  background-clip: text;
  filter: drop-shadow(0 0 12px rgba(245,158,11,0.4));
}
.el-footer__status-pct--down {
  background: linear-gradient(135deg, #fff 0%, #fecaca 50%, #fca5a5 100%);
  -webkit-background-clip: text;
  background-clip: text;
  filter: drop-shadow(0 0 12px rgba(239,68,68,0.4));
}
.el-footer__status-pct--unknown {
  background: linear-gradient(135deg, #fff 0%, #e2e8f0 100%);
  -webkit-background-clip: text;
  background-clip: text;
  filter: none;
}

/* Typewriter caret — blinking vertical bar at the end of the typed label. */
.el-footer__status-caret {
  display: inline-block;
  width: 2px;
  height: 0.95em;
  margin-left: 2px;
  vertical-align: -0.12em;
  background: var(--footer-status-caret-color, currentColor);
  opacity: 0.85;
  animation: el-footer-status-caret-blink 0.9s steps(1) infinite;
}
@keyframes el-footer-status-caret-blink {
  0%, 49%   { opacity: 0.85; }
  50%, 100% { opacity: 0; }
}

/* Completion pulse — fires once when the count-up settles. Expands a soft
   ring outward from the gauge edge, fades, and stops. Triggered by the
   `--complete` modifier added in React state once display reaches target. */
.el-footer__status-gauge::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 50%;
  border: 2px solid var(--footer-status-pulse-color, transparent);
  opacity: 0;
  pointer-events: none;
}
.el-footer__status--complete .el-footer__status-gauge::after {
  animation: el-footer-status-complete-pulse 1.4s ease-out forwards;
}
@keyframes el-footer-status-complete-pulse {
  0%   { opacity: 0.85; transform: scale(1);   }
  100% { opacity: 0;    transform: scale(1.35); }
}

/* Inner core glow that brightens once the ring hits target. */
.el-footer__status-gauge::before {
  content: "";
  position: absolute;
  inset: 18%;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(34,197,94,0.18) 0%, transparent 70%);
  opacity: 0;
  transition: opacity 0.6s ease 0.2s;
  pointer-events: none;
  z-index: 1;
}
.el-footer__status--complete .el-footer__status-gauge::before {
  opacity: 1;
}

/* Summary pill — keeps the original compact pill styling, sits below gauge */
.el-footer__status-pill {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.45rem 0.75rem;
  border-radius: 999px;
  font-size: 12px;
  line-height: 1;
  white-space: nowrap;
  background: var(--footer-status-pill-bg, transparent);
  border: 1px solid var(--footer-status-pill-border, transparent);
}
.el-footer__status-dot {
  width: 8px;
  height: 8px;
  border-radius: 50%;
  flex-shrink: 0;
  background: var(--footer-status-dot-up, transparent);
  box-shadow: 0 0 0 3px rgba(34,197,94,0.18), 0 0 8px rgba(34,197,94,0.55);
}
.el-footer__status-dot--degraded {
  background: var(--footer-status-dot-degraded, transparent);
  box-shadow: 0 0 0 3px rgba(245,158,11,0.18), 0 0 8px rgba(245,158,11,0.5);
}
.el-footer__status-dot--down {
  background: var(--footer-status-dot-down, transparent);
  box-shadow: 0 0 0 3px rgba(239,68,68,0.2), 0 0 8px rgba(239,68,68,0.5);
}
.el-footer__status-dot--unknown {
  background: var(--footer-status-dot-unknown, transparent);
  box-shadow: 0 0 0 3px rgba(148,163,184,0.18);
}
.el-footer__status-label {
  font-weight: 500;
  letter-spacing: 0.01em;
}
.el-footer__status-rt {
  display: inline-flex;
  align-items: baseline;
  gap: 0.15rem;
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.el-footer__status-rt-divider {
  display: inline-block;
  width: 1px;
  height: 11px;
  margin: 0 0.5rem 0 0.25rem;
  background: var(--footer-status-divider, transparent);
  align-self: center;
}
.el-footer__status-rt-value {
  font-weight: 700;
  font-size: 12px;
  letter-spacing: -0.01em;
  color: var(--footer-status-rt-color, currentColor);
}
.el-footer__status-rt-unit {
  font-weight: 500;
  font-size: 10px;
  opacity: 0.55;
  margin-left: 1px;
}
@media (prefers-reduced-motion: reduce) {
  .el-footer__status-gauge-ring { animation: none; transition: none; }
}
.el-footer--stacked .el-footer__brand-section,
.el-footer--minimal .el-footer__brand-section { align-items: center; max-width: min(var(--footer-brand-section-max-width, 480px), 100%); margin-bottom: 2rem; }
.el-footer--columns-first .el-footer__brand-section { align-items: center; margin-top: 2rem; }

.el-footer__logo {
  max-height: var(--footer-logo-max-height, 56px);
  width: auto;
  max-width: min(var(--footer-logo-max-width, 200px), 100%);
  object-fit: contain;
  /* Accent glow flows from the site theme — derived from --site-accent so
     each tenant gets a glow that matches their palette. The two drop-shadows
     stack a tight inner halo + a soft outer bloom; opacity is held in the
     glow CSS vars so a per-footer override can tune intensity without
     re-declaring the filter. color-mix lets us blend toward transparent
     without forcing authors into rgba() math. */
  filter:
    drop-shadow(0 0 14px var(--footer-logo-glow-inner, color-mix(in srgb, var(--site-accent, currentColor) 65%, transparent)))
    drop-shadow(0 0 32px var(--footer-logo-glow-outer, color-mix(in srgb, var(--site-accent, currentColor) 32%, transparent))) !important;
  animation: el-footer-logo-float 4.5s ease-in-out infinite;
  will-change: transform, filter;
}
@keyframes el-footer-logo-float {
  0%, 100% { transform: translateY(0); }
  50%     { transform: translateY(-6px); }
}
@media (prefers-reduced-motion: reduce) {
  .el-footer__logo { animation: none; }
}
.el-footer--brand-left .el-footer__logo {
  width: var(--footer-logo-max-height, 56px);
  height: auto;
  max-width: none;
}
.el-footer__brand-name {
  font-family: var(--site-font-heading);
  font-weight: var(--footer-brand-name-weight, 600);
  font-size: var(--footer-brand-name-size, 1.125rem);
  letter-spacing: 0.04em;
  color: var(--footer-brand-name-color, var(--site-text-on-primary));
}
.el-footer__tagline {
  font-size: 0.875rem;
  line-height: 1.5;
  margin: 0;
}

/* ── Columns grid ──
   Stepped collapse so the link columns never squeeze into 4 cramped rails
   at intermediate widths. The min-track has to be wide enough to hold the
   widest realistic uppercase column heading ("MORE INTEGRATIONS",
   "SOLUTIONS", etc.) at the default 0.9375rem / 0.03em letter-spacing —
   roughly 168–176px. Below the implicit auto-fit floor we add explicit
   breakpoints (see further down) so the grid steps cleanly 4 → 3 → 2 → 1
   instead of letting auto-fit produce odd dangling-column layouts. */
.el-footer__columns {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(var(--footer-column-min-width, 176px), 100%), 1fr));
  align-self: start;
  padding-top: 0;
}
.el-footer__column-heading {
  font-family: var(--site-font-heading);
  font-weight: var(--footer-column-heading-weight, 700);
  font-size: var(--footer-column-heading-size, 0.9375rem);
  margin: 0 0 0.75rem;
  text-transform: var(--footer-column-heading-transform, uppercase);
  letter-spacing: var(--footer-column-heading-letter-spacing, 0.03em);
  /* AGENTS.md responsive contract: never slice a word mid-character. With
     `keep-all` whole words stay intact; `hyphens: auto` hyphenates only at
     legal break points; `overflow-wrap: normal` disables the
     last-resort character break that was producing "SOLUTI / ONS" and
     "INTEGRATI / ONS" in narrow columns. If a word genuinely cannot fit
     it overflows the gap rather than shattering. */
  word-break: keep-all;
  overflow-wrap: normal;
  hyphens: auto;
  -webkit-hyphens: auto;
}
.el-footer__link-list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--footer-link-gap, 0.375rem);
}
.el-footer__link {
  text-decoration: none;
  font-size: var(--footer-link-font-size, 0.9375rem);
  transition: color 0.2s;
  cursor: pointer;
}

/* ── Bottom section ── */
.el-footer__bottom {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  padding-top: 1.5rem;
  gap: var(--footer-bottom-gap, 0.75rem);
}

/* ── Social links ── */
.el-footer__social {
  display: flex;
  justify-content: center;
  gap: var(--footer-social-gap, 1rem);
}
.el-footer__social-link {
  text-decoration: none;
  font-size: var(--footer-social-font-size, 0.875rem);
  transition: color 0.2s;
  cursor: pointer;
  /* WCAG 2.5.5 minimum tap target — social links were rendering ~36×46
     on mobile (icon + label, but link box only 36 wide). Floor at 40×40. */
  min-width: 40px;
  min-height: 40px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}

/* ── Compliance badges (equal housing, HUD, etc.) ── */
.el-footer__compliance {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--footer-compliance-gap, 1.25rem);
  flex-wrap: wrap;
}
.el-footer__compliance-badge {
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.el-footer__compliance-img {
  height: 24px;
  width: auto;
  max-width: 60px;
  object-fit: contain;
  opacity: 0.88;
}
.el-footer__compliance-label {
  font-size: 0.8125rem;
  white-space: nowrap;
}
.el-footer__compliance-link {
  text-decoration: none;
  transition: opacity 0.2s;
}
.el-footer__compliance-link:hover { opacity: 0.8; }

/* ── Copyright ── */
.el-footer__copyright {
  font-size: var(--footer-copyright-font-size, 0.875rem);
  margin: 0;
  line-height: 1.5;
}

/* ── Powered by ── */
.el-footer__powered-by {
  font-size: 0.8125rem;
  margin: 0;
}
.el-footer__powered-by a {
  text-decoration: none;
  transition: color 0.2s;
}

/* ── Mobile columns count (builder-controlled via class modifier) ── */
/* was @media(max-width:640px); bucketed to mobile (640 ≤ 768) */
@container site style(--site-bp: mobile) {
  .el-footer--mobile-cols-1 .el-footer__columns { grid-template-columns: 1fr; }
  .el-footer--mobile-cols-2 .el-footer__columns { grid-template-columns: repeat(2, 1fr); }
  .el-footer--mobile-cols-3 .el-footer__columns { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 640px) {
  .el-footer--mobile-cols-1 .el-footer__columns { grid-template-columns: 1fr; }
  .el-footer--mobile-cols-2 .el-footer__columns { grid-template-columns: repeat(2, 1fr); }
  .el-footer--mobile-cols-3 .el-footer__columns { grid-template-columns: repeat(3, 1fr); }
}

/* ── Mobile (≤768px) ──────────────────────────────────────────
   Mobile typography contract (Group D, Issue 16):
   - Column heading: clamp(15px, 4vw, 17px), weight 600 — readable scan target
   - Links: 14px / line-height 1.6 — comfortable tap rhythm, ≥44px row height
   - Brand description / tagline: 13.5px / 1.55 — narrative density
   - Bottom-row meta (copyright, powered-by, compliance): 12.5px / 1.5
   All values still token-overridable via --footer-*-size CSS vars set by the
   renderer when the author edits typography in the inspector. */
@container site style(--site-bp: mobile) {
  .el-footer__main { grid-template-columns: 1fr !important; justify-items: center !important; text-align: center; }
  .el-footer__brand-section { align-items: center; max-width: 100%; margin-bottom: 2rem; }
  /* Step cleanly to 2 columns at tablet/large-phone — `auto-fit` alone
     would briefly hold 3 cramped columns at this width with the 176px
     min-track. Forcing exactly 2 keeps headings readable and links tappable. */
  .el-footer__columns { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; gap: 1.25rem 1.5rem; }
  .el-footer__column { text-align: center; }
  .el-footer__logo { max-height: 44px; }

  /* Issue 16 — typography bump for legibility on phones. */
  .el-footer__column-heading {
    text-align: center;
    font-size: var(--footer-column-heading-size, clamp(15px, 4vw, 17px));
    font-weight: var(--footer-column-heading-weight, 600);
    margin-bottom: 0.625rem;
    line-height: 1.35;
  }
  .el-footer__link {
    font-size: var(--footer-link-font-size, 14px);
    line-height: 1.6;
    /* Tap-target — full-row block so the entire 44px row catches taps,
       not just the text-glyph width. inline-flex limited the hit target
       to ~30px wide ("CRM", "Blog", "Apps"). */
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    width: 100%;
  }
  .el-footer__link-list { align-items: center; gap: var(--footer-link-gap, 0.25rem); }
  .el-footer__brand-name { font-size: var(--footer-brand-name-size, 17px); }
  .el-footer__tagline,
  .el-footer__brand-description { font-size: 13.5px; line-height: 1.55; }
  .el-footer__copyright { font-size: var(--footer-copyright-font-size, 12.5px); line-height: 1.5; }
  .el-footer__powered-by { font-size: 12.5px; }
  .el-footer__compliance-label { font-size: 12.5px; }
  /* Social row stays in a horizontal strip but with comfortable touch spacing. */
  .el-footer__social { gap: var(--footer-social-gap, 1.25rem); flex-wrap: wrap; row-gap: 0.5rem; }
  .el-footer__social-link {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}
@media (max-width: 768px) {
  .el-footer__main { grid-template-columns: 1fr !important; justify-items: center !important; text-align: center; }
  .el-footer__brand-section { align-items: center; max-width: 100%; margin-bottom: 2rem; }
  /* Step cleanly to 2 columns at tablet/large-phone — `auto-fit` alone
     would briefly hold 3 cramped columns at this width with the 176px
     min-track. Forcing exactly 2 keeps headings readable and links tappable. */
  .el-footer__columns { grid-template-columns: repeat(2, minmax(0, 1fr)); width: 100%; gap: 1.25rem 1.5rem; }
  .el-footer__column { text-align: center; }
  .el-footer__logo { max-height: 44px; }

  /* Issue 16 — typography bump for legibility on phones. */
  .el-footer__column-heading {
    text-align: center;
    font-size: var(--footer-column-heading-size, clamp(15px, 4vw, 17px));
    font-weight: var(--footer-column-heading-weight, 600);
    margin-bottom: 0.625rem;
    line-height: 1.35;
  }
  .el-footer__link {
    font-size: var(--footer-link-font-size, 14px);
    line-height: 1.6;
    /* Tap-target — full-row block so the entire 44px row catches taps,
       not just the text-glyph width. inline-flex limited the hit target
       to ~30px wide ("CRM", "Blog", "Apps"). */
    min-height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    width: 100%;
  }
  .el-footer__link-list { align-items: center; gap: var(--footer-link-gap, 0.25rem); }
  .el-footer__brand-name { font-size: var(--footer-brand-name-size, 17px); }
  .el-footer__tagline,
  .el-footer__brand-description { font-size: 13.5px; line-height: 1.55; }
  .el-footer__copyright { font-size: var(--footer-copyright-font-size, 12.5px); line-height: 1.5; }
  .el-footer__powered-by { font-size: 12.5px; }
  .el-footer__compliance-label { font-size: 12.5px; }
  /* Social row stays in a horizontal strip but with comfortable touch spacing. */
  .el-footer__social { gap: var(--footer-social-gap, 1.25rem); flex-wrap: wrap; row-gap: 0.5rem; }
  .el-footer__social-link {
    min-width: 44px;
    min-height: 44px;
    display: inline-flex;
    align-items: center;
    justify-content: center;
  }
}

/* Tightest phones (≤480px): drop to 1-column when the author hasn't picked a
   different mobile column count, keeping headings as tap-friendly anchors.
   Typography stays readable — we DO NOT shrink heading/link sizes further
   (the previous shrink-to-12.75px broke legibility).
   `data-mobile-collapse="accordion"` on the renderer root opts into the
   <details> accordion mode (each column collapses, heading is the summary). */
/* was @media(max-width:480px); bucketed to mobile (480 ≤ 768) */
@container site style(--site-bp: mobile) {
  .el-footer--mobile-cols-1 .el-footer__columns { grid-template-columns: 1fr; gap: 1.25rem; }
  /* Even when author picks 2/3 columns, ≤360px gets one column to avoid
     orphaned single-character link rows. */
  .el-footer__columns { row-gap: 1.25rem; }
}
@media (max-width: 480px) {
  .el-footer--mobile-cols-1 .el-footer__columns { grid-template-columns: 1fr; gap: 1.25rem; }
  /* Even when author picks 2/3 columns, ≤360px gets one column to avoid
     orphaned single-character link rows. */
  .el-footer__columns { row-gap: 1.25rem; }
}
/* was @media(max-width:360px); bucketed to mobile (360 ≤ 768) */
@container site style(--site-bp: mobile) {
  .el-footer__columns { grid-template-columns: 1fr !important; }
}
@media (max-width: 360px) {
  .el-footer__columns { grid-template-columns: 1fr !important; }
}

/* Accordion mode (opt-in via data-mobile-collapse="accordion") — ≤480px each
   column becomes a <details> with the heading as <summary>. Renderer emits
   semantic <details>/<summary> when this prop is on, so this rule only has
   to hide the open-state arrow and tighten spacing. */
.el-footer[data-mobile-collapse="accordion"] .el-footer__column > details > summary {
  list-style: none;
}
.el-footer[data-mobile-collapse="accordion"] .el-footer__column > details > summary::-webkit-details-marker {
  display: none;
}
/* was @media(max-width:480px); bucketed to mobile (480 ≤ 768) */
@container site style(--site-bp: mobile) {
  .el-footer[data-mobile-collapse="accordion"] .el-footer__column > details > summary {
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.625rem 0;
    border-bottom: 1px solid color-mix(in srgb, currentColor 12%, transparent);
    min-height: 44px;
  }
  .el-footer[data-mobile-collapse="accordion"] .el-footer__column > details > summary::after {
    content: '';
    width: 10px;
    height: 10px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
    margin-left: 0.75rem;
    transition: transform 0.18s ease;
    opacity: 0.6;
  }
  .el-footer[data-mobile-collapse="accordion"] .el-footer__column > details[open] > summary::after {
    transform: rotate(-135deg);
  }
  .el-footer[data-mobile-collapse="accordion"] .el-footer__link-list { padding: 0.5rem 0 0.75rem; }
}
@media (max-width: 480px) {
  .el-footer[data-mobile-collapse="accordion"] .el-footer__column > details > summary {
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.625rem 0;
    border-bottom: 1px solid color-mix(in srgb, currentColor 12%, transparent);
    min-height: 44px;
  }
  .el-footer[data-mobile-collapse="accordion"] .el-footer__column > details > summary::after {
    content: '';
    width: 10px;
    height: 10px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
    margin-left: 0.75rem;
    transition: transform 0.18s ease;
    opacity: 0.6;
  }
  .el-footer[data-mobile-collapse="accordion"] .el-footer__column > details[open] > summary::after {
    transform: rotate(-135deg);
  }
  .el-footer[data-mobile-collapse="accordion"] .el-footer__link-list { padding: 0.5rem 0 0.75rem; }
}
@media (prefers-reduced-motion: reduce) {
  .el-footer[data-mobile-collapse="accordion"] .el-footer__column > details > summary::after {
    transition: none;
  }
}

/* ── Progressive-disclosure "show more" toggle on footer columns ─────────────
   When a column author sets `collapsedAfter > 0`, links beyond that index get
   `.el-footer__link-item--collapsed` and stay in the SSR DOM (SEO + AT see
   them). The CSS rule below toggles their visibility off the
   `data-expanded="false"` attribute on the column root; the renderer flips
   that attribute on click. The toggle button styling pulls from the same
   --footer-link-* vars so theme tokens drive everything. */
.el-footer__column[data-expanded="false"] .el-footer__link-item--collapsed {
  display: none;
}
.el-footer__column-toggle {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  margin-top: 0.5rem;
  padding: 0.25rem 0;
  background: transparent;
  border: 0;
  cursor: pointer;
  font-family: inherit;
  font-size: var(--footer-link-font-size, 0.9375rem);
  font-weight: 600;
  color: var(--footer-link-color, currentColor);
  text-decoration: none;
  transition: color 0.2s;
}
.el-footer__column-toggle:hover,
.el-footer__column-toggle:focus-visible {
  color: var(--footer-link-hover-color, currentColor);
}
.el-footer__column-toggle:focus-visible {
  outline: 2px solid var(--footer-link-hover-color, currentColor);
  outline-offset: 2px;
  border-radius: 2px;
}
/* Chevron — pure CSS, follows currentColor so theme tokens drive it. */
.el-footer__column-toggle-icon {
  display: inline-block;
  width: 8px;
  height: 8px;
  border-right: 2px solid currentColor;
  border-bottom: 2px solid currentColor;
  transform: rotate(45deg);
  transition: transform 0.18s ease;
  margin-bottom: 2px;
}
.el-footer__column-toggle[aria-expanded="true"] .el-footer__column-toggle-icon {
  transform: rotate(-135deg);
  margin-bottom: -2px;
}
@media (prefers-reduced-motion: reduce) {
  .el-footer__column-toggle-icon { transition: none; }
}
/* Mobile (≤480px) — accordion already provides the disclosure affordance, so
   hide the toggle button and reveal all links so the accordion is authoritative.
   This keeps mobile UX unchanged when both `collapsedAfter` and the global
   accordion mode are configured. */
/* was @media(max-width:480px); bucketed to mobile (480 ≤ 768) */
@container site style(--site-bp: mobile) {
  .el-footer__column-toggle { display: none; }
  .el-footer__column[data-expanded="false"] .el-footer__link-item--collapsed { display: list-item; }
}
@media (max-width: 480px) {
  .el-footer__column-toggle { display: none; }
  .el-footer__column[data-expanded="false"] .el-footer__link-item--collapsed { display: list-item; }
}

.el-navbar__brand-name {
  font-size: var(--navbar-brand-font-size, 18px);
  font-weight: var(--navbar-brand-font-weight, 700);
  letter-spacing: 0.02em;
  max-width: min(24vw, var(--navbar-brand-name-max-width, 220px));
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* ── Modal ─────────────────────────────────────────────────── */
/* Backdrop wraps the dialog. Opacity/blur are applied via a ::before
   pseudo-element so the dialog itself stays at 100% opacity. */
.el-modal__backdrop {
  position: fixed;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 1000;
  padding: 16px;
}
.el-modal__backdrop::before {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--modal-backdrop-color, transparent);
  opacity: var(--modal-backdrop-opacity, 1);
  backdrop-filter: blur(var(--modal-backdrop-blur, 0px));
  -webkit-backdrop-filter: blur(var(--modal-backdrop-blur, 0px));
  z-index: -1;
}

.el-modal__dialog {
  position: relative;
  background: var(--modal-dialog-bg, var(--site-surface, transparent));
  border-radius: var(--modal-dialog-radius, 16px);
  box-shadow: var(--modal-dialog-shadow, 0 20px 48px rgba(0, 0, 0, 0.18));
  max-height: calc(100vh - 32px);
  overflow-y: auto;
  width: 100%;
}

.el-modal__dialog--sm { max-width: var(--modal-dialog-max-width-sm, 480px); }
.el-modal__dialog--md { max-width: var(--modal-dialog-max-width-md, 640px); }
.el-modal__dialog--lg { max-width: var(--modal-dialog-max-width-lg, 880px); }
.el-modal__dialog--full { max-width: 100%; }

@container site style(--site-bp: mobile) {
  .el-modal__backdrop { padding: 12px; }
  .el-modal__dialog { max-height: calc(100vh - 24px); }
}
@media (max-width: 768px) {
  .el-modal__backdrop { padding: 12px; }
  .el-modal__dialog { max-height: calc(100vh - 24px); }
}

/* ── Navbar: mobile brand-name visibility (must win over desktop-tier caps) ──
   The @media (max-width: 1100px|1320px) rules earlier in this file also
   match at mobile widths. Since source order decides cascade ties, these
   end-of-file rules guarantee the brand stays readable on phones. */
@container site style(--site-bp: mobile) {
  /* Hidden by default on phones; opt-in via mobileShowBrandName. */
  .el-navbar__brand-name:not(.el-navbar__brand-name--mobile-visible) {
    display: none;
  }
  /* When opted in, give the logo+brand cluster room to grow (the desktop
     34vw cap leaves no space for text on phones) and let the brand wrap
     at WORD boundaries — never mid-word. */
  .el-navbar:has(.el-navbar__brand-name--mobile-visible) .el-navbar__logo {
    max-width: none;
    flex: 1 1 auto;
    min-width: 0;
  }
  .el-navbar__brand-name.el-navbar__brand-name--mobile-visible {
    display: inline-block;
    font-size: 0.95rem;
    max-width: none;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: break-word;
    word-break: normal;
    line-height: 1.15;
  }
}
@media (max-width: 768px) {
  /* Hidden by default on phones; opt-in via mobileShowBrandName. */
  .el-navbar__brand-name:not(.el-navbar__brand-name--mobile-visible) {
    display: none;
  }
  /* When opted in, give the logo+brand cluster room to grow (the desktop
     34vw cap leaves no space for text on phones) and let the brand wrap
     at WORD boundaries — never mid-word. */
  .el-navbar:has(.el-navbar__brand-name--mobile-visible) .el-navbar__logo {
    max-width: none;
    flex: 1 1 auto;
    min-width: 0;
  }
  .el-navbar__brand-name.el-navbar__brand-name--mobile-visible {
    display: inline-block;
    font-size: 0.95rem;
    max-width: none;
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    overflow-wrap: break-word;
    word-break: normal;
    line-height: 1.15;
  }
}
/* was @media(max-width:480px); bucketed to mobile (480 ≤ 768) */
@container site style(--site-bp: mobile) {
  .el-navbar__brand-name.el-navbar__brand-name--mobile-visible {
    font-size: 0.85rem;
    letter-spacing: 0.01em;
  }
}
@media (max-width: 480px) {
  .el-navbar__brand-name.el-navbar__brand-name--mobile-visible {
    font-size: 0.85rem;
    letter-spacing: 0.01em;
  }
}

/* ─────────────────────────────────────────────────────────────────────
   Section content-container — single source of truth for inner-wrapper
   width across every section-level element. No section may compute its
   own max-width / margin-inline / padding-inline ad-hoc — use this class
   on the inner wrapper that sits directly inside `.el.el--{type}`.

   Rules use `:where()` so the BASE specificity is 0,0,0 — element-
   specific sibling rules (`.el-compound-section__inner`,
   `.el-faq__inner`, `.el-hero__content`, …) keep working unchanged
   because their 0,1,0 specificity wins for any property they declare.
   The contract still wins on the properties NO sibling rule sets, so
   every section that ships with this class shares the same content
   column on its own.

   Token chain — declared in src/lib/themeContract.ts:
     --site-max-width        Default inner content width (1200px default)
     --site-container        Wide max — 1440px default
     --site-container-narrow 720px default — readable column for prose
     --site-content-gutter   Inline padding token (24px default)

   The default class clamps padding-inline to clamp(1rem, 4vw, 2rem) so
   360px viewport gets 16px gutter; 1280px+ gets 32px. No media queries
   needed. Per-element OPT-OUT only via the modifier classes (--narrow,
   --wide, --full) — no other escape hatches. Adding the class is the
   only safe way to widen, narrow, or full-bleed a section's content.

   Drift is enforced by:
     - scripts/builder/validate-elements.ts (rejects raw maxWidth on
       section-level element definitions)
     - src/components/elements/__tests__/siteContainerContract.test.tsx
       (every section renderer's inner wrapper must carry the class)

   See also:
     - src/lib/elements/siteContainer.ts — renderer helper (className +
       SITE_CONTAINER_WIDTH_FIELD)
     - src/ai_skills/evara-website-builder/SKILL.md § Section Container
       Contract
   ───────────────────────────────────────────────────────────────────── */
:where(.el-site-container) {
  width: 100%;
  max-width: var(--site-max-width, 1280px);
  margin-inline: auto;
  padding-inline: var(--site-content-gutter, clamp(1rem, 4vw, 2rem));
  box-sizing: border-box;
}
:where(.el-site-container--narrow) { max-width: var(--site-container-narrow, 720px); }
:where(.el-site-container--wide)   { max-width: var(--site-container, 1440px); }
:where(.el-site-container--full)   { max-width: 100%; padding-inline: 0; }
