/* er-content.css — hero, heading, rich-text, image, video, gallery, button, CTA, icon, testimonials, team, stats, pricing, timeline, feature-grid, comparison-table, blog, services */

/* ── Carousel pagination indicator variants ─────────────────────
   Driven by the shared `dotStyle` design-panel field (CAROUSEL_DOT_FIELDS).
   Each carousel renderer passes `data-dot-style="round|pill|bar|square|ring"`
   on its dots wrapper. Variants override only what each style requires;
   size/color/gap/active-width still come from the user's other dot fields. */
[data-dot-style="round"] > button[class*="__dot"] {
  border-radius: 999px;
}
[data-dot-style="round"] > button[class*="__dot"][class*="--active"] {
  width: var(--carousel-dot-size, 8px); /* equal width — round, no pill expansion */
  border-radius: 999px;
}
[data-dot-style="square"] > button[class*="__dot"],
[data-dot-style="square"] > button[class*="__dot"][class*="--active"] {
  border-radius: 2px;
}
[data-dot-style="bar"] > button[class*="__dot"] {
  height: 3px;
  border-radius: 0;
  width: var(--carousel-dot-active-width, 24px);
}
[data-dot-style="bar"] > button[class*="__dot"][class*="--active"] {
  height: 3px;
  border-radius: 0;
}
[data-dot-style="ring"] > button[class*="__dot"] {
  background: transparent !important;
  border: 2px solid var(--carousel-dot-color, currentColor);
  border-radius: 999px;
  box-sizing: border-box;
}
[data-dot-style="ring"] > button[class*="__dot"][class*="--active"] {
  background: var(--carousel-dot-active-color, var(--site-accent)) !important;
  border-color: var(--carousel-dot-active-color, var(--site-accent));
  width: var(--carousel-dot-size, 8px); /* ring active stays round, not pill */
}
/* "pill" is the renderer default — built-in CSS already produces it via
   `dotActiveWidth`. No override needed. */

/* Base layout + sizing for ComparisonCarousel's pagination dots.
   The renderer (ComparisonCarouselRenderer.tsx) emits `data-dot-style`
   on the `__dots` wrapper and `el-comparison-carousel__dot[--active]`
   on each button — no inline width/height/border-radius/background, so
   the variant rules above (specificity 0,2,1) actually take effect.
   The `pill` default expands the active dot via `--carousel-dot-active-width`
   without needing its own variant block. */
.el-comparison-carousel__dots {
  display: flex;
  justify-content: center;
  gap: var(--carousel-dot-gap, 0.5rem);
  margin-top: 1rem;
}
.el-comparison-carousel__dot {
  width: var(--carousel-dot-size, 0.625rem);
  height: var(--carousel-dot-size, 0.625rem);
  border-radius: 999px;
  border: none;
  padding: 0;
  cursor: pointer;
  background: var(--carousel-dot-color, var(--site-border));
  transition: background 0.2s ease, width 0.2s ease, height 0.2s ease,
    border-radius 0.2s ease;
}
.el-comparison-carousel__dot--active {
  background: var(--carousel-dot-active-color, var(--site-accent));
  width: var(--carousel-dot-active-width, 1.5rem);
}


/* ── Heading ──────────────────────────────────────────────── */
/* Heading — full type scale h1–h5. Margin baseline is 0: every widget
   that wants heading-to-body rhythm declares it itself
   (.el-services__heading, .el-compound-section__slot--heading, etc.),
   and the design panel's `marginBottom` spacing control writes an
   inline `style="margin-bottom: Xpx"` which always wins. This keeps the
   element's own bounding box tight by default so it doesn't bleed
   vertical whitespace into whatever compound widget is hosting it. */
.el-heading {
  margin: 0;
}
/* Section-level headings center by default — sectionHeading() helper is used
   for the heading at the top of a content section, which should always be
   centered. Editorial inline headings (used inside narrative blocks) keep
   their natural left alignment because they aren't a direct child of these
   contexts. Compound widgets (testimonials, feature-cards, stats) scope the
   center rule to headings inside `__content` only so nested card headings
   (e.g. author names on testimonial cards) keep their natural alignment. */
.el-section .el-heading,
.el-cta-band .el-heading,
.el-property-card-list .el-heading,
.el-feature-cards .el-compound-section__content .el-heading,
.el-testimonials .el-compound-section__content .el-heading,
.el-stats .el-compound-section__content .el-heading,
.el-feature-cards__header,
.el-stats__heading { text-align: center; }
/* Stat values and subtitles must never wrap — single-line presentation is
   part of the stat layout contract. Belt: nowrap. Suspenders: ellipsis on
   the subtitle so long labels truncate instead of overflowing their cell. */
.el-stats .el-heading__text { white-space: nowrap; }
.el-stats .el-heading__subtitle {
  text-wrap: auto;
  overflow-wrap: break-word;
  max-width: 100%;
}
/* Un-center nested author headings inside testimonial cards — they should
   sit flush-left with the quote body text above them. The card itself is
   nested inside `.el-section` on most pages, which would otherwise pick
   up the transitive center rule above. */
.el-testimonials__card .el-heading,
.el-testimonials__card .el-heading__text { text-align: left; }
.el-section .el-heading .el-heading__subtitle,
.el-section .el-heading .el-heading__subtext,
.el-contact-section__heading .el-heading .el-heading__subtitle,
.el-contact-section__heading .el-heading .el-heading__subtext,
.el-cta-band .el-heading .el-heading__subtitle,
.el-cta-band .el-heading .el-heading__subtext {
  margin-left: auto;
  margin-right: auto;
}
/*
 * Heading text consumes `--el-color` (set by ElementWrapper from
 * `props.textColor`) with `!important` so widget-level color cascades
 * (e.g. `.el-stats--dark .el-stats__value { color:#fff }`) can't clobber
 * an author-set Heading Text Color. When `textColor` is unset, `--el-color`
 * falls back to `initial`, the declaration becomes invalid, and
 * `.el-heading__text` inherits its ambient color from its parent — the
 * pre-2026 behaviour.
 *
 * Per-instance typography (`--el-heading-*`) is set inline by HeadingRenderer.
 * Per-level defaults (h1–h6 scale ramps below) take over when no override
 * is present, preserving the historical type scale.
 */
.el-heading__text {
  font-family: var(--site-font-heading);
  color: var(--el-color, inherit);
  margin: 0;
  line-height: var(--el-heading-line-height, 1.1);
  letter-spacing: normal;
  /* Base weight — never inherit from ancestor widget wrapper. h1–h5 rules
     below override per semantic level; this baseline catches `<p>`/`<div>`
     levels and any future tag and ensures the heading text doesn't pick up
     bold from an enclosing widget. */
  font-weight: var(--el-heading-font-weight, var(--site-fw-bold, 700));
  text-transform: var(--el-heading-text-transform, none);
  text-wrap: balance;
  /* Wrap policy: only break unbreakable tokens (URLs, IDs, long compound
     words). Regular words stay intact. `hyphens: auto` lets the browser
     soft-hyphenate at syllable boundaries when a single word genuinely
     cannot fit, instead of slicing mid-character. The previous
     `overflow-wrap: anywhere` produced "Moment | um" / "ac- | quisition"
     style breaks at narrow viewports even when alternative wrap points
     existed earlier in the line. */
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}
/* Heading sizes flow through the universal typography ladder
   (`--site-heading-N`) defined in public/css/er-typography.css and
   themeContract.ts. Per-element overrides still win via
   `--el-heading-font-size`. Inner clamp() preserves the legacy
   responsive rendering only when the active token is not set (i.e.
   ThemeProvider bypassed AND er-typography.css absent). See SKILL.md
   § Typography Ladder Contract. */
h1.el-heading__text { font-size: var(--el-heading-font-size, var(--site-heading-1, clamp(2.75rem, 6vw, 4.25rem))); font-weight: var(--el-heading-font-weight, var(--site-fw-bold, 700)); }
h2.el-heading__text { font-size: var(--el-heading-font-size, var(--site-heading-2, clamp(1.875rem, 4vw, 2.75rem))); font-weight: var(--el-heading-font-weight, var(--site-fw-bold, 700)); }
h3.el-heading__text { font-size: var(--el-heading-font-size, var(--site-heading-3, clamp(1.25rem, 2.5vw, 1.75rem))); font-weight: var(--el-heading-font-weight, var(--site-fw-semibold, 600)); }
h4.el-heading__text { font-size: var(--el-heading-font-size, var(--site-heading-4, 1.125rem)); font-weight: var(--el-heading-font-weight, var(--site-fw-semibold, 600)); }
h5.el-heading__text { font-size: var(--el-heading-font-size, var(--site-eyebrow-size, 0.875rem)); font-weight: var(--el-heading-font-weight, var(--site-fw-bold, 700)); letter-spacing: normal; text-transform: var(--el-heading-text-transform, var(--site-eyebrow-transform, uppercase)); }
/* Inside dark hero overlays / section variants, ensure the heading text
   uses the ambient (light) color rather than baking dark text. Only apply
   when no per-instance --el-color override is set, so authoring still wins.
   Use --site-text-on-primary (ambient light text token) so it tracks the
   theme — never reach for --site-bg here, since on a dark site that token
   is dark and would render invisible-on-dark. */
.el-section--dark .el-heading__text,
.el-cta-with-image--dark .el-heading__text,
.el-editorial-marquee .el-heading__text,
.el--editorial-marquee .el-heading__text {
  color: var(--el-color, var(--site-text-on-primary, currentColor));
}

/* Inside dark hero overlays / section variants, force the eyebrow to use the
   ambient text color (which is already set to a light token by the dark
   section). This guarantees AA contrast even when --site-accent resolves
   to a near-neutral tone that would fail on a dark navy background. */
.el-section--dark .el-heading__eyebrow,
.el-cta-with-image--dark .el-heading__eyebrow,
.el-editorial-marquee .el-heading__eyebrow,
.el--editorial-marquee .el-heading__eyebrow,
.el--cta-band .el-heading__eyebrow {
  color: var(--el-eyebrow-color, var(--site-eyebrow-on-dark, currentColor));
  opacity: 0.92;
}

.el-heading__eyebrow {
  font-family: var(--site-font-body);
  /* Eyebrow text resolution:
       1. --el-eyebrow-color (per-instance override)
       2. --site-eyebrow-color (per-site token, can be dark-aware)
       3. --site-accent-on-light (legacy: works on light surfaces)
       4. --site-accent (raw accent — last resort)
     If a dark section provides --site-eyebrow-color (or sets --el-eyebrow-color
     locally), the dark-on-dark contrast failure is eliminated. */
  color: var(--el-eyebrow-color, var(--site-eyebrow-color, var(--site-accent-on-light, var(--site-accent, currentColor))));
  /* The four typography fields below ride site tokens directly — no
     per-element panel surface today. Once an authoring need surfaces
     for any of them, add a panel field that emits the matching
     `--el-eyebrow-*` var and switch this back to a `var(...)`. */
  margin: 0 0 0.5rem;
  font-size: var(--site-eyebrow-size, 0.8125rem);
  font-weight: 700;
  line-height: 1.3;
  letter-spacing: normal;
  text-transform: uppercase;
}
.el-heading__subtitle {
  font-family: var(--site-font-body);
  color: var(--el-subtitle-color, inherit);
  /* No baked-in opacity — color is fully author-controlled now. */
  margin: var(--el-subtitle-margin-top, 0.375rem) 0 0;
  font-size: var(--el-subtitle-font-size, 0.9375rem);
  /* Default to regular (400) — never inherit. Without this, any ancestor
     widget wrapper that sets font-weight (e.g. .el-feature-cards__heading,
     .el-cta-band__heading, etc. all default to 700/800) would cascade
     into the subtitle and make it bold. The whole point of consolidating
     eyebrow/heading/subtitle into the heading element is that each line
     paints exactly the typography it was designed for, regardless of
     which widget the heading lives inside. */
  font-weight: var(--el-subtitle-font-weight, 400);
  line-height: var(--el-subtitle-line-height, 1.55);
  letter-spacing: normal;
  text-transform: var(--el-subtitle-text-transform, none);
  max-width: var(--el-subtitle-max-width, 72ch);
}
/* Inside compound section contexts, let subtitles span full container width */
.el-section .el-heading__subtitle,
.el-contact-section .el-heading__subtitle,
.el-cta-band .el-heading__subtitle,
.el-cta-with-image .el-heading__subtitle,
.el-feature-cards .el-heading__subtitle,
.el-testimonials .el-heading__subtitle,
.el-stats .el-heading__subtitle {
  max-width: var(--el-subtitle-max-width, 100%);
}

/* ── Rich Text ────────────────────────────────────────────── */
.el-rich-text {
  font-family: var(--site-font-body);
  color: var(--el-color, var(--site-text));
  line-height: 1.6;
  font-size: 0.9375rem;
  max-width: none;
}




/* Rich-text paragraph baseline. First/last/only paragraph never carries
   a vertical margin — that margin would bleed outside the element's
   bounding box and inflate the hosting widget's layout. Between
   paragraphs, keep a 1em gap so editorial copy reads naturally. Widget
   CSS (declared later) and the design panel's margin control both
   override this baseline. */
.el-rich-text > p { margin: 0; }
.el-rich-text > p + p { margin-top: 1em; }
.el-rich-text h2, .el-rich-text h3, .el-rich-text h4 { font-family: var(--site-font-heading); margin: 1.5em 0 0.75em; }
.el-rich-text h2 { font-size: 1.75rem; font-weight: 600; }
.el-rich-text h3 { font-size: 1.25rem; font-weight: 600; }
.el-rich-text a { color: var(--site-primary); text-decoration: underline; text-underline-offset: 2px; }
.el-rich-text a:hover { opacity: 0.8; }
.el-rich-text strong { font-weight: 600; color: var(--site-text); }
.el-rich-text em { font-style: italic; }
.el-rich-text ul, .el-rich-text ol { margin: 0 0 1.25em; padding-left: 0; list-style: none; }
.el-rich-text ul li, .el-rich-text ol li {
  padding: 0.375rem 0 0.375rem 1.5rem;
  position: relative;
  line-height: 1.65;
}
.el-rich-text ul li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.65rem;
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: var(--site-accent, var(--site-primary));
}
.el-rich-text ol { counter-reset: ol-counter; }
.el-rich-text ol li { counter-increment: ol-counter; }
.el-rich-text ol li::before {
  content: counter(ol-counter) '.';
  position: absolute;
  left: 0;
  font-weight: 600;
  color: var(--site-accent, var(--site-primary));
  font-size: 0.875em;
}
.el-rich-text blockquote {
  margin: 1.5em 0;
  padding: 1rem 1.5rem;
  border-left: 3px solid var(--site-accent, var(--site-primary));
  background: var(--site-surface-alt);
  border-radius: 0 var(--site-radius, 8px) var(--site-radius, 8px) 0;
  font-style: italic;
  color: var(--site-text-secondary);
}
.el-rich-text code {
  background: var(--site-surface-alt);
  padding: 0.15em 0.4em;
  border-radius: 4px;
  font-size: 0.875em;
  font-family: 'SF Mono', 'Fira Code', monospace;
}
.el-rich-text img {
  max-width: 100%;
  height: auto;
  border-radius: var(--site-radius, 8px);
  margin: 1em 0;
}
.el-rich-text img { max-width: 100%; height: auto; }

/* Section-owned media heroes: when a hero is nested inside a section that
   carries the background image/video, the hero frame must not repaint over
   the parent media with its default brand gradient. */
.el-section__inner > .el--hero {
  width: 100%;
  margin-left: 0;
  margin-right: 0;
}
.el-section__inner > .el--hero > .el-hero {
  background: transparent;
  background-image: none;
}
.el-section__inner > .el--hero > .el-hero::before {
  display: none;
  opacity: 0;
}

/* ── Image ────────────────────────────────────────────────── */
.el-image { margin: 0; }
.el-image__img {
  max-width: 100%;
  height: auto;
  display: block;
  border-radius: var(--site-radius-lg, 12px);
  /* Non-card media aspect contract — landscape preset. Per-instance
     overrides set --el-image-aspect (e.g. via mediaAspectPreset). */
  aspect-ratio: var(--el-image-aspect, var(--site-media-aspect-landscape, 16 / 10));
  object-fit: cover;
}
.el-image__link { display: block; }
.el-image__caption {
  margin-top: 0.5rem;
  font-family: var(--site-font-body, inherit);
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.5;
  color: var(--site-text-secondary, var(--site-text-muted, currentColor));
  text-align: center;
  overflow-wrap: break-word;
}

/* ── Video ────────────────────────────────────────────────── */
.el-video { width: 100%; }
.el-video__responsive {
  position: relative;
  /* Non-card media aspect contract — video preset (default 16/9).
     Per-instance overrides set --el-video-aspect via mediaAspectPreset. */
  aspect-ratio: var(--el-video-aspect, var(--site-media-aspect-video, 16 / 9));
  overflow: hidden;
}
.el-video__iframe {
  position: absolute;
  top: 0; left: 0;
  width: 100%; height: 100%;
  border: none;
  border-radius: var(--site-radius, 8px);
}
.el-video__native {
  display: block;
  max-width: 100%;
  border-radius: var(--site-radius, 8px);
  object-fit: var(--video-object-fit, contain);
}

/* ── Hero ─────────────────────────────────────────────────── */
/* Hero — full-width bleed, breaks out of any container */
.el--hero {
  width: 100vw;
  margin-left: calc(-50vw + 50%);
}
.el--editorial-marquee {
  width: 100vw;
  max-width: 100vw;
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
}
.el-region-portfolio__meta-chip {
  transition: background-color 180ms ease, border-color 180ms ease;
  cursor: default;
}
.el-region-portfolio__meta-chip:hover {
  background-color: var(--region-portfolio-accent-bg) !important;
  border-color: var(--region-portfolio-accent-border) !important;
  color: var(--site-primary-fg) !important;
}
.el-region-portfolio .cta-btn {
  box-shadow: 0 8px 18px rgba(21, 34, 56, 0.08);
}
.el-region-portfolio .cta-btn--primary:hover {
  background: var(--site-btn-primary-hover-bg, var(--site-primary, currentColor));
  border-color: var(--site-btn-primary-hover-bg, var(--site-primary, currentColor));
  color: var(--site-btn-primary-hover-text, var(--site-primary-fg)) !important;
  box-shadow: 0 14px 28px rgba(15, 26, 48, 0.22);
}
.el-region-portfolio .cta-btn--outline:hover {
  background: var(--site-btn-outline-hover-bg, var(--site-primary, currentColor));
  border-color: var(--site-btn-outline-border, var(--site-primary, currentColor));
  color: var(--site-btn-outline-hover-text, var(--site-primary-fg)) !important;
  box-shadow: 0 14px 28px rgba(21, 34, 56, 0.18);
}
.el-region-portfolio__row {
  grid-template-columns: repeat(2, minmax(0, 1fr)) !important;
  align-items: stretch;
}
.el-region-portfolio__media {
  height: var(--el-region-portfolio-media-height, 420px) !important;
  min-height: var(--el-region-portfolio-media-height, 420px) !important;
}
.el-region-portfolio__body {
  height: var(--el-region-portfolio-media-height, 420px) !important;
  min-height: var(--el-region-portfolio-media-height, 420px) !important;
  padding: clamp(26px, 4vw, 42px) !important;
}
@container site style(--site-bp: mobile) {
  .el-region-portfolio__row {
    grid-template-columns: 1fr !important;
  }
  .el-region-portfolio__media {
    height: var(--el-region-portfolio-media-height-mobile, 280px) !important;
    min-height: var(--el-region-portfolio-media-height-mobile, 280px) !important;
  }
  .el-region-portfolio__body {
    height: auto !important;
    min-height: 0 !important;
  }
}
@media (max-width: 768px) {
  .el-region-portfolio__row {
    grid-template-columns: 1fr !important;
  }
  .el-region-portfolio__media {
    height: var(--el-region-portfolio-media-height-mobile, 280px) !important;
    min-height: var(--el-region-portfolio-media-height-mobile, 280px) !important;
  }
  .el-region-portfolio__body {
    height: auto !important;
    min-height: 0 !important;
  }
}

/* ── Region Portfolio compound-widget cards (Stage 11A) ─────────────────
 * Card chrome is fully builder-driven:
 *   --rp-card-media-direction   → flex direction (column | row | reverse)
 *   --rp-card-border-{side}-*   → per-side border width + color (each side
 *                                 is independent; radius is preserved).
 *   --rp-card-accent-*          → the straight-edge accent ribbon (::before)
 *   --rp-card-shadow / bg / text / radius → surface tokens
 *
 * In `--alternating` layout every :nth-child(even) card mirrors the media
 * side. With `data-rp-border-alternate="true"` the left/right borders mirror
 * too. The `::before` accent already mirrors in alternating + auto modes. */
/* The card-container wrapper (`.el-region-portfolio__card-container`), the
 * alternating / per-row border rules, the accent ribbon, and the container
 * hover effect all live in the generated stylesheet:
 *   public/css/er-card-containers.css
 *   (source: src/lib/elements/cardContainerCss.ts)
 *
 * The inner-card base below stays as a legacy fallback for any path that
 * still renders without the container wrapper. */

/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-region-portfolio__card` (0,1,0) and zeros bg/border-radius/shadow. */
.el.el--region-card > .el-region-portfolio__card {
  background: var(--rp-card-bg, var(--site-surface, transparent));
  border-radius: var(--rp-card-radius, 8px);
  box-shadow: var(--rp-card-shadow, none);
}

.el-region-portfolio__card {
  display: flex;
  flex-direction: var(--rp-card-media-direction, column);
  overflow: hidden;
  border-radius: var(--rp-card-radius, 8px);
  /* Resting-state colors cascade through the unified card resting-state
     color contract (src/lib/themeContract.ts § Card resting-state colors).
     Per-element vars (`--rp-card-bg` etc.) win first; site-level
     `--site-card-bg` retints every card in one edit; legacy `--site-surface`
     chain stays as a final fallback. */
  background: var(--rp-card-bg, var(--site-card-bg, var(--site-surface, transparent)));
  color: var(--rp-card-text, var(--site-card-text, inherit));
  box-shadow: var(--rp-card-shadow, var(--site-card-elevation, none));
  transition: transform 220ms ease, box-shadow 220ms ease, border-color 220ms ease;
  /* Per-side borders — preserve the card's corner radius while letting the
     author flip a single edge without wrapping the card in a full frame.
     Border color falls through `--site-card-border` so a tenant can repaint
     every card edge in one edit. */
  border-top: var(--rp-card-border-top-width, 0) solid var(--rp-card-border-top-color, var(--rp-card-border-color, var(--site-card-border, transparent)));
  border-right: var(--rp-card-border-right-width, 0) solid var(--rp-card-border-right-color, var(--rp-card-border-color, var(--site-card-border, transparent)));
  border-bottom: var(--rp-card-border-bottom-width, 0) solid var(--rp-card-border-bottom-color, var(--rp-card-border-color, var(--site-card-border, transparent)));
  border-left: var(--rp-card-border-left-width, 0) solid var(--rp-card-border-left-color, var(--rp-card-border-color, var(--site-card-border, transparent)));
  position: relative;
  align-items: stretch;
}

/* CARD_HOVER_FIELDS contract — every hover property chains through the
   builder-set --region-portfolio-hover-* override → accent-derived default. */
[data-card-hover-shell]:hover .el-region-portfolio__card {
  transform: translateY(calc(var(--region-portfolio-hover-lift, 4px) * -1));
  border-color: var(--region-portfolio-hover-border-color,
    color-mix(in srgb, var(--rp-card-accent, var(--site-primary, currentColor)) 30%, transparent));
  background: var(--region-portfolio-hover-bg, var(--rp-card-bg, var(--site-card-bg, var(--site-surface, transparent))));
  box-shadow: var(--region-portfolio-hover-shadow,
    0 8px 24px rgba(0,0,0,0.10), 0 4px 8px rgba(0,0,0,0.06)),
    0 0 0 1px color-mix(in srgb, var(--rp-card-accent, var(--site-accent, currentColor)) calc(18% * var(--region-portfolio-hover-glow-opacity, 0.28)), transparent);
}

.el-region-portfolio__card--featured {
  outline: 2px solid var(--rp-card-accent, var(--site-primary, currentColor));
  outline-offset: -2px;
}
.el-region-portfolio__card-media {
  aspect-ratio: var(--rp-card-media-aspect, var(--site-card-media-aspect, 16 / 10));
  width: 100%;
  max-height: var(--rp-card-media-height, none);
  overflow: hidden;
  flex-shrink: 0;
  border-radius: 0;
}
/* Force every card image/video to fill the card-media wrapper at the same
   aspect-ratio (--rp-card-media-aspect, default 16/10) and crop with
   object-fit: cover. The wrapper sets the size; the img/video stretches to
   it and overflow is clipped. Also targets nested .el-image / .el-image__img
   shapes so the ImageRenderer's own aspect-ratio + sizing rules cannot
   cascade into the card and produce uneven heights between cards. */
.el-region-portfolio__card-media > img,
.el-region-portfolio__card-media > video,
.el-region-portfolio__card-media > .el-image,
.el-region-portfolio__card-media > .el-image > .el-image__img,
.el-region-portfolio__card-media .el-image__img,
.el-region-portfolio__card-media .el-image__link {
  width: 100% !important;
  height: 100% !important;
  max-width: 100% !important;
  max-height: 100% !important;
  display: block;
  object-fit: cover;
  object-position: center;
  /* Override the default 16/10 aspect-ratio set on .el-image__img — the
     wrapper already enforces aspect, double-applying here causes the inner
     img to letterbox and varies the visible crop between cards. */
  aspect-ratio: auto !important;
  border-radius: 0;
  margin: 0;
}
/* When media sits on the left or right — either via cardMediaPosition or
   via the alternating treatment — it claims a fixed side width. Media keeps
   a uniform aspect ratio (default 16:10, configurable via
   --rp-card-media-aspect) so cards line up across rows regardless of body
   length. The body still stretches via flex:1 to keep card heights equal,
   but media height is content-independent. */
.el-region-portfolio--media-left .el-region-portfolio__card-media,
.el-region-portfolio--media-right .el-region-portfolio__card-media,
.el-region-portfolio--alternating .el-region-portfolio__card-media {
  width: var(--rp-alt-media-width, var(--rp-card-media-side-width, 44%));
  aspect-ratio: var(--rp-card-media-aspect, var(--site-card-media-aspect, 16 / 10));
  align-self: flex-start;
  min-height: 0;
  height: auto;
  max-height: var(--rp-card-media-height, none);
}
@container site style(--site-bp: mobile) {
  /* On narrow viewports, always stack media above content — horizontal
     cards compress body copy below usable limits otherwise. Mobile breakpoint
     is 768px (matches navbar collapse + CompoundSection grid collapse). */
  .el-region-portfolio--media-left .el-region-portfolio__card,
  .el-region-portfolio--media-right .el-region-portfolio__card,
  .el-region-portfolio--alternating .el-compound-section__cards > .el-region-portfolio__card,
  .el-region-portfolio--alternating .el-compound-section__cards > .el-region-portfolio__card:nth-child(even) {
    flex-direction: column;
  }
  .el-region-portfolio--media-left .el-region-portfolio__card-media,
  .el-region-portfolio--media-right .el-region-portfolio__card-media,
  .el-region-portfolio--alternating .el-region-portfolio__card-media {
    width: 100%;
    aspect-ratio: var(--rp-card-media-aspect, var(--site-card-media-aspect, 16 / 10));
    min-height: 0;
  }
}
@media (max-width: 768px) {
  /* On narrow viewports, always stack media above content — horizontal
     cards compress body copy below usable limits otherwise. Mobile breakpoint
     is 768px (matches navbar collapse + CompoundSection grid collapse). */
  .el-region-portfolio--media-left .el-region-portfolio__card,
  .el-region-portfolio--media-right .el-region-portfolio__card,
  .el-region-portfolio--alternating .el-compound-section__cards > .el-region-portfolio__card,
  .el-region-portfolio--alternating .el-compound-section__cards > .el-region-portfolio__card:nth-child(even) {
    flex-direction: column;
  }
  .el-region-portfolio--media-left .el-region-portfolio__card-media,
  .el-region-portfolio--media-right .el-region-portfolio__card-media,
  .el-region-portfolio--alternating .el-region-portfolio__card-media {
    width: 100%;
    aspect-ratio: var(--rp-card-media-aspect, var(--site-card-media-aspect, 16 / 10));
    min-height: 0;
  }
}
.el-region-portfolio__card-media--empty {
  background: var(--rp-card-media-empty-bg, transparent);
  min-height: 180px;
}
.el-region-portfolio__card-body {
  display: flex;
  flex-direction: column;
  gap: 0.875rem;
  /* Padding cascades through the unified card-padding token so the
     region-portfolio body matches feature-cards / services / testimonials
     padding on every breakpoint. */
  padding: var(--rp-card-padding, var(--site-card-padding, clamp(1.5rem, 2vw, 1.75rem)));
  flex: 1;
  min-width: 0;
}
/* Side-by-side card layouts (alternating, media-left, media-right): center
   the body content vertically next to the image so descriptions + CTA read
   as a balanced pair instead of being pinned to the top while the image
   extends below. Stacked/column layouts keep default top alignment. */
.el-region-portfolio--alternating .el-region-portfolio__card-body,
.el-region-portfolio--media-left .el-region-portfolio__card-body,
.el-region-portfolio--media-right .el-region-portfolio__card-body {
  justify-content: center;
}
@container site style(--site-bp: mobile) {
  .el-region-portfolio--alternating .el-region-portfolio__card-body,
  .el-region-portfolio--media-left .el-region-portfolio__card-body,
  .el-region-portfolio--media-right .el-region-portfolio__card-body {
    justify-content: flex-start;
  }
}
@media (max-width: 768px) {
  .el-region-portfolio--alternating .el-region-portfolio__card-body,
  .el-region-portfolio--media-left .el-region-portfolio__card-body,
  .el-region-portfolio--media-right .el-region-portfolio__card-body {
    justify-content: flex-start;
  }
}
.el-region-portfolio__card-chips {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}
.el-region-portfolio__status-chip {
  border-radius: 999px;
  /* Darken the success token by ~22% to guarantee >=4.5:1 contrast against
     the default white chip text. Tailwind emerald-700 territory.
     Custom override via --rp-card-status-bg still wins. */
  background: var(--rp-card-status-bg, color-mix(in oklab, var(--site-success, transparent) 78%, black));
  /* Default to white text on the dark green bg. Authors can override. */
  color: var(--rp-card-status-text, currentColor);
  padding: 0.35rem 0.7rem;
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  overflow-wrap: break-word;
}
.el-region-portfolio__card-title {
  margin: 0;
  font-family: var(--site-font-heading, inherit);
  font-weight: var(--site-heading-weight, 700);
  color: var(--site-heading-color, inherit);
  font-size: clamp(1.25rem, 1.8vw, 1.55rem);
  line-height: 1.2;
  letter-spacing: -0.02em;
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-region-portfolio__card-title a {
  color: inherit;
  text-decoration: none;
}
.el-region-portfolio__card-summary {
  margin: 0;
  font-size: 0.98rem;
  line-height: 1.65;
  opacity: 0.85;
  overflow-wrap: break-word;
}
.el-region-portfolio__card-bullets {
  margin: 0;
  padding-left: 0;
  display: grid;
  gap: 8px;
  font-size: 0.92rem;
  line-height: 1.55;
  opacity: 0.9;
  list-style: none;
}
.el-region-portfolio__card-bullets li {
  display: flex;
  align-items: baseline;
  gap: 8px;
}
.el-region-portfolio__bullet-dot {
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--rp-card-accent, var(--site-primary, currentColor));
  flex-shrink: 0;
  margin-top: 0.45em;
}
.el-region-portfolio__card-actions {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  padding-top: 4px;
  margin-top: auto;
}
.el-region-portfolio__stats {
  color: var(--rp-card-text, inherit);
}
.el-region-portfolio__stat-card {
  display: grid;
  gap: 0.375rem;
  padding: 1rem 1.125rem 1rem 1.25rem;
  border-radius: var(--rp-stat-radius, var(--rp-card-radius, 8px));
  background: var(--rp-stat-bg, var(--rp-card-bg, var(--site-surface, transparent)));
  border: 1px solid var(--rp-stat-border-color, transparent);
  box-shadow: var(--rp-stat-shadow, none);
  color: inherit;
  text-decoration: none;
  position: relative;
  overflow: hidden;
}
.el-region-portfolio__stat-card::before {
  content: "";
  position: absolute;
  inset: 0 auto 0 0;
  width: min(var(--rp-card-accent-width, 6px), 8px);
  background: var(--rp-stat-accent, var(--rp-card-accent, var(--site-primary, currentColor)));
  pointer-events: none;
}
.el-region-portfolio__stat-value {
  font-size: 1.5rem;
  font-weight: 800;
  letter-spacing: -0.04em;
  line-height: 1;
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-region-portfolio__stat-label {
  font-size: 0.76rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  opacity: 0.72;
  overflow-wrap: break-word;
}

.el-hero {
  position: relative;
  min-height: clamp(360px, 65vh, 720px);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
  background-color: var(--el-bg, var(--hero-bg, var(--site-primary)));
  color: var(--hero-text, inherit);
  width: 100%;
}
.el-hero__content {
  position: relative;
  z-index: 2;
  text-align: center;
  padding-block: var(--hero-content-padding-y, var(--site-space-xl, 6rem));
}
.el-hero__content:not(.el-site-container) { max-width: var(--hero-content-max-width, 860px); }
.el-hero__heading {
  font-family: var(--site-font-heading);
  font-size: clamp(var(--hero-heading-size-min, 2.55rem), 6vw, var(--hero-heading-size-max, 5rem));
  font-weight: 700;
  color: var(--hero-heading, var(--site-primary-fg));
  margin: 0 0 1.25rem;
  line-height: var(--hero-heading-line-height, 1);
  letter-spacing: var(--hero-heading-letter-spacing, -0.04em);
  /* Word-break safety: long brand/product names ("FreshBooks", "SendGrid",
     "Conversions") were splitting mid-word at 390px because the default
     word-break rules treated them as breakable. Force word-level breaks
     and let hyphens absorb the rest. */
  overflow-wrap: break-word;
  word-break: keep-all;
  hyphens: auto;
}
.el-hero__subheading {
  font-size: clamp(var(--hero-subheading-size-min, 1rem), 1.8vw, var(--hero-subheading-size-max, 1.2rem));
  color: var(--hero-subheading, var(--site-hero-subtext, currentColor));
  margin: 0 0 2rem;
  line-height: var(--hero-subheading-line-height, 1.7);
}
.el-hero__actions {
  display: flex;
  gap: var(--hero-action-gap, 1rem);
  justify-content: center;
  flex-wrap: wrap;
}
.el-hero--left .el-hero__content { text-align: left; }
.el-hero--left .el-hero__actions { justify-content: flex-start; }
.el-hero--split {
  justify-content: flex-start;
  --el-padding-default: clamp(24px, 4vw, 56px);
}
.el-hero--split .el-hero__content {
  text-align: left;
  padding-block: clamp(28px, 4vw, 44px);
  border-radius: var(--hero-split-card-radius, 32px);
  background:
    linear-gradient(180deg, rgba(10, 18, 31, calc(var(--hero-split-card-tint-strength, 0.5) * 1)), rgba(10, 18, 31, calc(var(--hero-split-card-tint-strength, 0.5) * 0.48))),
    linear-gradient(145deg, rgba(255,255,255,0.12), rgba(255,255,255,0.04));
  border: 1px solid var(--hero-split-card-border-color, transparent);
  box-shadow: 0 30px 80px rgba(7, 12, 20, 0.28);
  backdrop-filter: blur(var(--hero-split-card-blur, 16px)) saturate(130%);
  -webkit-backdrop-filter: blur(var(--hero-split-card-blur, 16px)) saturate(130%);
}
.el-hero--split .el-hero__actions {
  justify-content: flex-start;
}
.el-hero::after {
  content: '';
  position: absolute;
  inset: auto auto -18% -8%;
  width: min(34vw, 420px);
  aspect-ratio: 1 / 1;
  border-radius: 999px;
  background: radial-gradient(circle, color-mix(in srgb, var(--site-accent) 34%, transparent) 0%, color-mix(in srgb, var(--site-accent) 8%, transparent) 42%, transparent 72%);
  z-index: 1;
  pointer-events: none;
}

/* ── Page Header ──────────────────────────────────────────── */
.el-page-header {
  --el-padding-default: clamp(4.5rem, 8vw, 7rem) var(--site-space-md, 2rem) clamp(2.4rem, 4vw, 3.2rem);
  --el-bg-default:      var(--site-surface-alt);
  border-bottom: 1px solid var(--site-border);
  position: relative;
  overflow: hidden;
}
.el-page-header__overlay {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.el-page-header--dark {
  background: var(--el-bg, var(--site-primary));
  border-bottom: none;
}
.el-page-header--dark .el-page-header__title,
.el-page-header--dark .el-page-header__subtitle { color: var(--site-primary-fg, currentColor); }
.el-page-header--dark .el-page-header__breadcrumbs,
.el-page-header--dark .el-page-header__breadcrumbs a { color: rgba(255,255,255,0.7); }
.el-page-header__inner {
  /* Defers to parent Section by default. Hero variants can override per-element
     via --hero-content-max-width (set through the design panel). */
  max-width: var(--hero-content-max-width, 100%);
  margin: 0 auto;
  position: relative;
  z-index: 1;
}
.el-page-header__breadcrumbs {
  font-size: 0.875rem;
  color: var(--site-text-muted);
  margin-bottom: 0.5rem;
}
.el-page-header__breadcrumbs a {
  color: var(--ph-breadcrumb-link, var(--site-text-muted));
  text-decoration: none;
}
.el-page-header__sep { margin: 0 0.5rem; }
.el-page-header__title {
  font-family: var(--site-font-heading);
  font-size: clamp(var(--hero-heading-size-min, 2.3rem), 4vw, var(--hero-heading-size-max, 4rem));
  font-weight: 700;
  color: var(--ph-title, var(--site-text));
  margin: 0;
  letter-spacing: var(--hero-heading-letter-spacing, -0.04em);
  line-height: var(--hero-heading-line-height, 0.98);
}
.el-page-header__subtitle {
  color: var(--ph-subtitle, var(--site-text-secondary));
  margin: 0.8rem 0 0;
  font-size: clamp(var(--hero-subheading-size-min, 1.05rem), 1.8vw, var(--hero-subheading-size-max, 1.25rem));
  /* Editable per-element via --hero-subtitle-max-width (typographic cap for readable line length). */
  max-width: var(--hero-subtitle-max-width, 100%);
  line-height: var(--hero-subheading-line-height, 1.75);
}

/* ── Feature Cards ────────────────────────────────────────── */
/* ── Feature Card — base ────────────────── */
.el-feature-cards {
  padding: 0; /* Section parent provides vertical padding */
  /* Subtle parent-frame elevation — one tier below the per-card shadow so
     the section reads as a coherent group without competing with item-
     level hover. Routed through --site-* tokens so tenants can re-tune
     in one design-panel edit. Default is a no-op transparent layer when
     the token is unset. */
  box-shadow: var(--feature-cards-frame-shadow, 0 0 transparent);
}
.el-feature-cards__header {
  text-align: center;
  margin-bottom: 2.5rem;
}
.el-feature-cards__heading {
  font-family: var(--site-font-heading);
  font-size: clamp(1.75rem, 4vw, 2.5rem);
  font-weight: 700;
  color: var(--fc-heading, var(--fc-text, var(--site-text)));
  margin: 0 0 0.75rem;
  letter-spacing: -0.025em;
}
.el-feature-cards__subheading {
  color: var(--fc-subheading, var(--fc-text, var(--site-text-secondary)));
  font-size: 1.0625rem;
  line-height: 1.7;
  max-width: 100%;
  margin: 0 auto;
}
.el-feature-cards__grid {
  display: grid;
  gap: var(--fc-gap, 1.25rem);
  align-items: stretch;
  grid-template-columns: repeat(var(--el-grid-cols, 3), minmax(0, 1fr));
}
.el-feature-cards__grid > * {
  height: 100%;
  display: flex;
  flex-direction: column;
}
.el-feature-cards__grid > * > .el-feature-cards__card {
  flex: 1;
  display: flex;
  flex-direction: column;
}
/* Descendant (not >) because `.el-compound-section__card-shell { display: contents }`
   makes the ElementWrapper a grandchild in the DOM tree — the > combinator
   never matched across display:contents. */
.el-compound-section__cards .el--feature-card {
  display: flex;
  height: 100%;
}

.el-feature-cards__card {
  /* Resting-state colors cascade through the unified card resting-state
     color contract (src/lib/themeContract.ts § Card resting-state colors). */
  background: var(--feature-card-bg, var(--fc-card-bg, var(--site-card-bg, transparent)));
  backdrop-filter: var(--feature-card-backdrop-filter, none);
  -webkit-backdrop-filter: var(--feature-card-backdrop-filter, none);
  /* Padding cascades through the unified card-padding token so a
     feature-cards block aligns with neighbouring testimonials / services /
     region-portfolio cards on every breakpoint. */
  padding: var(--feature-card-padding, var(--site-card-padding, 24px));
  border: var(--feature-card-border-width, var(--site-card-border-width, 1px)) solid var(--feature-card-border-color, var(--fc-card-border, var(--site-card-border, transparent)));
  /* Per-side accent bars — see .el-pricing-card__plan for rationale. */
  border-top-width: var(--feature-card-accent-bar-height, var(--feature-card-border-width, var(--site-card-border-width, 1px)));
  border-top-color: var(--feature-card-accent-bar-color, var(--feature-card-border-color, var(--fc-card-border, var(--site-card-border, transparent))));
  border-right-width: var(--feature-card-accent-bar-right-height, var(--feature-card-border-width, var(--site-card-border-width, 1px)));
  border-right-color: var(--feature-card-accent-bar-right-color, var(--feature-card-border-color, var(--fc-card-border, var(--site-card-border, transparent))));
  border-bottom-width: var(--feature-card-accent-bar-bottom-height, var(--feature-card-border-width, var(--site-card-border-width, 1px)));
  border-bottom-color: var(--feature-card-accent-bar-bottom-color, var(--feature-card-border-color, var(--fc-card-border, var(--site-card-border, transparent))));
  border-left-width: var(--feature-card-accent-bar-left-height, var(--feature-card-border-width, var(--site-card-border-width, 1px)));
  border-left-color: var(--feature-card-accent-bar-left-color, var(--feature-card-border-color, var(--fc-card-border, var(--site-card-border, transparent))));
  /* Radius cascades through the unified card-radius token. */
  border-radius: var(--feature-card-border-radius, var(--site-card-radius, var(--site-radius-lg, 16px)));
  overflow: hidden;
  /* Glass cards stack the inner highlight on top of the regular shadow so the
     panel reads as a real frosted-glass surface. `--feature-card-highlight`
     is set by the renderer when cardGlass=true; when unset the fallback MUST
     be a no-op transparent layer (`0 0 transparent`) — NOT the literal
     `none`. CSS does not allow `none` as one entry in a comma-separated
     shadow list; if the highlight var is missing, `box-shadow: none, <real>`
     becomes invalid syntax and the whole declaration is dropped, killing
     the user-set shadow.
     The resting elevation falls through `--site-card-elevation` so a
     tenant can re-tune lift across every card in one edit. */
  box-shadow:
    var(--feature-card-highlight, 0 0 transparent),
    var(--feature-card-shadow, var(--site-card-elevation, 0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04)));
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 0.4s cubic-bezier(0.16, 1, 0.3, 1),
              background 0.3s ease;
  text-decoration: none;
  color: var(--site-card-text, inherit);
  display: flex;
  flex-direction: column;
  position: relative;
  height: 100%;
}
/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-feature-cards__card` (0,1,0) and zeros background/padding/
   border-radius/box-shadow via the --el-* reset. Mirror the same fix
   already applied to testimonial-card at line ~2592. */
.el.el--feature-card > .el-feature-cards__card {
  background: var(--feature-card-bg, var(--fc-card-bg, var(--site-card-bg, transparent)));
  backdrop-filter: var(--feature-card-backdrop-filter, none);
  -webkit-backdrop-filter: var(--feature-card-backdrop-filter, none);
  display: flex;
  flex: 1 1 auto;
  flex-direction: column;
  height: 100%;
  /* Padding + radius cascade through the unified card token system —
     mirrors the parent rule above so the high-specificity bridge keeps
     the same default. */
  padding: var(--feature-card-padding, var(--site-card-padding, 24px));
  border-radius: var(--feature-card-border-radius, var(--site-card-radius, var(--site-radius-lg, 16px)));
  /* `!important` because nested `:where(.el .el)` resets and lower-specificity
     element-chrome rules can otherwise swallow the value even when the var
     is set. The fallback is a real bottom-right elevation (3-6px offset at
     ~10-14% alpha) so cards still ship with a visible drop when
     `--feature-card-shadow` is absent — matches the platform "cards have
     bottom-right shadow as default" rule. The inspector cardShadow controls
     override via `--feature-card-shadow` set on the section wrapper.
     `--feature-card-highlight` fallback MUST be `0 0 transparent`, NOT
     `none`: CSS rejects `none` as one entry in a comma-separated shadow
     list and the whole declaration silently drops, killing the user-set
     cardShadow when cardGlass is off (audit 2026-04-30). */
  box-shadow:
    var(--feature-card-highlight, 0 0 transparent),
    var(--feature-card-shadow, 3px 3px 24px rgba(15, 23, 42, 0.14), 6px 6px 48px rgba(15, 23, 42, 0.10)) !important;
}
/* When card bg is transparent, drop chrome BY DEFAULT — but route the
   shadow/border through the same `--feature-card-*` vars the inspector
   writes so explicit user choices still win. The previous implementation
   used `!important` and silently stripped any user-set shadow/border
   when cardBackground=transparent (audit: er-content.css ~870, 2026-04-29).
   `backdrop-filter` is intentionally killed because a transparent bg
   has nothing to blur; it remains `!important` to override any element
   chrome class that toggles a blur layer. */
.el-feature-cards__card[style*="background: transparent"],
.el-feature-cards__card[style*="background:transparent"] {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  border-color: var(--feature-card-border-color, transparent);
  box-shadow: var(--feature-card-shadow, none);
}
/* CARD_HOVER_FIELDS contract — every hover property chains through the
   builder-set --feature-card-hover-* override → accent-derived default.
   Documented in src/ai_skills/evara-website-builder/SKILL_REFERENCE.md
   § "Card Hover Contract". */
[data-card-hover-shell]:hover .el-feature-cards__card {
  transform: var(--fc-hover, translateY(calc(var(--feature-card-hover-lift, 6px) * -1)) scale(1.01));
  border-color: var(--feature-card-hover-border-color,
    color-mix(in srgb, var(--fc-accent, var(--site-accent, currentColor)) 55%, var(--feature-card-border-color, transparent)));
  background: var(--feature-card-hover-bg, var(--feature-card-bg, var(--fc-card-bg, var(--site-surface, transparent))));
  box-shadow: var(--feature-card-hover-shadow,
    0 4px 8px rgba(0, 0, 0, 0.08),
    0 14px 44px rgba(0, 0, 0, 0.14)),
    0 0 0 1px color-mix(in srgb, var(--fc-accent, var(--site-accent, currentColor)) calc(18% * var(--feature-card-hover-glow-opacity, 1)), transparent);
}
.el-feature-cards__card:hover::after {
  transform: scaleX(1);
}
a.el-feature-cards__card { cursor: pointer; }
/* Visual cards use a full-bleed image overlay — suppress the accent bar */
.el-feature-cards__card--visual::after { display: none; }
.el-feature-cards__card--visual:hover { background: transparent; }

/* ── Visual card (image + link = full-bleed) ── */
.el-feature-cards__card--visual {
  position: relative;
  border: none;
  border-radius: 0;
  aspect-ratio: 4 / 3;
}
.el-feature-cards__card--visual .el-feature-cards__card-image {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 0.5s cubic-bezier(0.2, 0, 0, 1);
}
.el-feature-cards__card--visual:hover .el-feature-cards__card-image {
  transform: scale(1.06);
}
.el-feature-cards__card--visual .el-feature-cards__card-overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.65) 0%, rgba(0, 0, 0, 0.1) 50%, transparent 100%);
  display: flex;
  align-items: flex-end;
  padding: 1.5rem;
  z-index: 1;
  transition: background 0.3s;
}
.el-feature-cards__card--visual:hover .el-feature-cards__card-overlay {
  background: linear-gradient(to top, rgba(0, 0, 0, 0.75) 0%, rgba(0, 0, 0, 0.15) 50%, transparent 100%);
}
.el-feature-cards__card-overlay-title {
  font-family: var(--site-font-heading);
  font-size: clamp(1.125rem, 2vw, 1.5rem);
  font-weight: 600;
  color: var(--site-fg, currentColor);
  letter-spacing: -0.01em;
}
/* Single-column visual card — wider aspect, cinematic feel */
.el-feature-cards__grid[style*="repeat(1"] .el-feature-cards__card--visual {
  aspect-ratio: 21 / 9;
}
.el-feature-cards__grid[style*="repeat(1"] .el-feature-cards__card-overlay {
  padding: 2rem 2.5rem;
}
.el-feature-cards__grid[style*="repeat(1"] .el-feature-cards__card-overlay-title {
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  border-left: 3px solid var(--site-accent);
  padding-left: 1rem;
}

/* ── Content card (no image or no link) ── */
.el-feature-cards__card-image-wrap {
  overflow: hidden;
  padding: var(--feature-card-image-padding, 0);
  background: var(--feature-card-image-bg, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
}
.el-feature-cards__card-image {
  width: 100%;
  aspect-ratio: 16 / 10;
  object-fit: var(--feature-card-image-fit, cover);
  display: block;
  transition: transform 0.4s ease;
}
/* Tinted logo: the background-color is the visible ink, the CSS mask
 * carries the shape. Hiding the underlying bitmap so only the masked color
 * shows through. */
.el-feature-cards__card-image--tinted {
  color: transparent;
}
.el-feature-cards__card-image--tinted::-moz-broken {
  color: transparent;
}
/* Logo mode — when --feature-card-image-height is set, use fixed height and drop aspect-ratio
   so logos of any native aspect render at identical visual size. */
.el-feature-cards[style*="--feature-card-image-height"] .el-feature-cards__card-image-wrap {
  height: var(--feature-card-image-height);
}
.el-feature-cards[style*="--feature-card-image-height"] .el-feature-cards__card-image {
  aspect-ratio: auto;
  width: 100%;
  height: 100%;
  max-height: var(--feature-card-image-height);
}
.el-feature-cards__card-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--feature-card-icon-size, 48px) + 20px);
  height: calc(var(--feature-card-icon-size, 48px) + 20px);
  border-radius: var(--feature-card-icon-radius, 16px);
  background: color-mix(in srgb, var(--fc-accent, var(--site-accent)) 12%, transparent 88%);
  border: 1px solid color-mix(in srgb, var(--fc-accent, var(--site-accent)) 22%, transparent 78%);
  color: var(--fc-accent, var(--site-accent));
  margin: var(--feature-card-icon-offset, 0) 0 0 0;
  align-self: flex-start;
  flex-shrink: 0;
  transition: background 0.3s ease, border-color 0.3s ease;
}
.el-feature-cards__card:hover .el-feature-cards__card-icon {
  background: color-mix(in srgb, var(--fc-accent, var(--site-accent)) 18%, transparent 82%);
  border-color: color-mix(in srgb, var(--fc-accent, var(--site-accent)) 40%, transparent 60%);
}
.el-feature-cards__card-icon .inline-icon {
  background-color: currentColor;
}
/* Icon child inside a feature-card icon-slot defaults to no chrome so
   it does not duplicate the parent .el-feature-cards__card-icon
   chrome (background / border / padding are painted by the parent
   from --feature-card-icon-* tokens). Defaults are NOT `!important`
   so any explicit inspector value on the icon child element (which
   ElementWrapper writes as inline `style` / `--el-*` vars at higher
   specificity) wins. Previous implementation used `!important` and
   silently ignored all icon inspector edits (audit: er-content.css
   ~1023, 2026-04-29). */
.el-feature-cards__card-icon > .el--icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 0;
  background: transparent;
  border: 0;
  box-shadow: none;
}
.el-feature-cards__card-icon > .el--icon > .el-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  padding: 0;
  background: transparent;
  color: inherit;
}
.el-feature-cards__card-icon > .el--icon > .el-icon .inline-icon {
  margin: auto;
}
/* Logo-mode icon fallback: when a card in logo mode has no image, render its
 * InlineIcon inside the same image-wrap box so alignment matches the logos. */
.el-feature-cards__card-image-wrap--icon-fallback {
  color: var(--fc-accent, var(--site-accent, currentColor));
}
.el-feature-cards__card-image-wrap--icon-fallback .inline-icon {
  background-color: currentColor;
}
.el-feature-cards__card:hover .el-feature-cards__card-image {
  transform: scale(1.04);
}
.el-feature-cards__card-body {
  gap: 0.5rem;
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
}
.el-feature-cards__card-body::before {
  content: none;
}
/* Pin the in-card CTA to the bottom of the body so cards with mixed
   description lengths still have aligned buttons across the row. */
.el-feature-cards__card-body > .el-feature-cards__card-cta {
  margin-top: auto;
}
.el-feature-cards__card-title {
  font-family: var(--site-font-heading);
  font-size: var(--feature-card-title-size, 1.125rem);
  font-weight: var(--feature-card-title-weight, 700);
  color: var(--fc-card-title, var(--fc-text, var(--site-fg)));
  margin: 0 0 0.4rem;
  line-height: 1.3;
  letter-spacing: -0.01em;
}
.el-feature-cards__card-desc {
  color: var(--fc-card-desc, var(--fc-text, var(--site-text)));
  font-size: var(--feature-card-description-size, 0.9rem);
  line-height: var(--feature-card-description-line-height, 1.65);
  margin: 0;
  display: block;
  overflow: visible;
}

/* Responsive — `.el-feature-cards` padding-y is driven by the
   `--site-section-pad-y` rhythm cascade (see er-layout.css § Section
   Vertical Rhythm Contract); the per-element mobile padding override
   that used to live here has been removed. */
@container site style(--site-bp: mobile) {
  .el-feature-cards__grid { grid-template-columns: 1fr; }
  .el-feature-cards__card--visual { aspect-ratio: 16 / 9; }
}
@media (max-width: 768px) {
  .el-feature-cards__grid { grid-template-columns: 1fr; }
  .el-feature-cards__card--visual { aspect-ratio: 16 / 9; }
}
/* was @media (min-width: 769px) and (max-width: 1024px); bucketed via intersection */
@container site style(--site-bp: tablet) {
  .el-feature-cards__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 769px) and (max-width: 1024px) {
  .el-feature-cards__grid { grid-template-columns: repeat(2, 1fr); }
}

/* ── Feature Cards — carousel layout ─────────────────────────── */
/* Mirrors the testimonials carousel contract: CSS scroll-snap viewport,
   --carousel-arrow-* / --carousel-dot-* vars from buildCarouselStyleVars,
   --fcpv / --fcard-gap set inline by the renderer so card width is pure CSS calc. */
.el-feature-cards__carousel {
  position: relative;
}
.el-feature-cards__viewport {
  display: flex;
  gap: var(--fcard-gap, 24px);
  overflow-x: scroll;
  /* `overflow-y: visible` would re-enable horizontal scroll-bleed in some
     browsers; use the explicit `clip` to allow vertical paint (card shadows
     above/below) without breaking the scroll axis. */
  overflow-y: clip;
  overflow-clip-margin-top: var(--site-carousel-shadow-bleed-block, 24px); overflow-clip-margin-bottom: var(--site-carousel-shadow-bleed-block, 24px);
  overflow-clip-margin-left: var(--site-carousel-shadow-bleed-inline, var(--fcard-gap, 24px)); overflow-clip-margin-right: var(--site-carousel-shadow-bleed-inline, var(--fcard-gap, 24px));
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  /* If/when this class is re-introduced in JSX, also add `scrollbar-none`
     (canonical helper in src/styles/main.css) to hide the bar. */
  /* Horizontal padding gives the first/last card room for their box-shadow
     before the scroll viewport's edge clips it. scroll-padding keeps
     scroll-snap landing positions aligned with that visual padding. */
  padding-block: var(--site-carousel-slide-bleed-block, 16px);
  padding-inline: var(--site-carousel-slide-bleed-inline, 16px);
  scroll-padding-inline: var(--site-carousel-slide-bleed-inline, 16px);
  -webkit-overflow-scrolling: touch;
}
.el-feature-cards__viewport > .el-feature-cards__card,
.el-feature-cards__viewport > a.el-feature-cards__card {
  flex: 0 0 calc((100% - var(--fcard-gap, 24px) * (var(--fcpv, 3) - 1)) / var(--fcpv, 3));
  min-width: 0;
  scroll-snap-align: start;
}
/* Equal-height cards in carousel: viewport stretches all children to the
   tallest card, image-wrap is locked to a uniform aspect ratio so cards
   with mixed image dimensions don't produce variable card heights, and the
   card-body grows to fill the remaining space (CTA pinned to the bottom).
   Default aspect-ratio override-able via --feature-card-image-aspect. */
.el-feature-cards__viewport {
  align-items: stretch;
}
.el-feature-cards--carousel .el-feature-cards__card {
  /* Override the base `height: 100%` (needed in grid mode so cards fill their
     AnimatedCard wrapper). In a flex-row scroll viewport, `height: 100%`
     interacts badly with `align-items: stretch` — browsers treat the
     cross-axis as "definite-but-resolving-to-auto" and skip stretching, so
     cards end up at their natural content heights. `height: auto` lets the
     viewport's stretch distribute the tallest card's height to every sibling. */
  height: auto;
  display: flex;
  flex-direction: column;
}
.el-feature-cards--carousel .el-feature-cards__card-image-wrap {
  /* Aspect cascades through the unified card-media-aspect token so a
     feature-cards carousel sitting next to a testimonials carousel and a
     services carousel shares the same media proportions per breakpoint. */
  aspect-ratio: var(--feature-card-image-aspect, var(--site-card-media-aspect, 16 / 9));
  height: auto;
  flex: 0 0 auto;
  overflow: hidden;
}
.el-feature-cards--carousel .el-feature-cards__card-image-wrap > .el-feature-cards__card-image {
  width: 100%;
  height: 100%;
  object-fit: var(--feature-card-image-fit, cover);
  display: block;
}
/* Prev / Next nav arrows — same --carousel-arrow-* contract as testimonials
   so arrow-styling controls work identically across elements. */
.el-feature-cards__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: var(--carousel-arrow-size, 44px);
  height: var(--carousel-arrow-size, 44px);
  border-radius: var(--carousel-arrow-radius, 50%);
  border: none;
  background: var(--carousel-arrow-bg, var(--site-accent, var(--site-primary)));
  color: var(--carousel-arrow-color, var(--site-accent-fg, var(--site-primary-fg, currentColor)));
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--carousel-arrow-shadow, 0 4px 16px rgba(0, 0, 0, 0.18));
  transition: transform 160ms ease, opacity 160ms ease, background-color 160ms ease, color 160ms ease, box-shadow 160ms ease, filter 160ms ease;
}
.el-feature-cards__nav--prev { left: -22px; }
.el-feature-cards__nav--next { right: -22px; }
.el-feature-cards__nav:hover {
  filter: var(--carousel-arrow-hover-filter, brightness(1.15));
  background: var(--carousel-arrow-hover-bg, var(--carousel-arrow-bg, var(--site-accent, var(--site-primary))));
  color: var(--carousel-arrow-hover-color, var(--carousel-arrow-color, currentColor));
  transform: translateY(-50%) scale(var(--carousel-arrow-hover-scale, 1.06));
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22);
}
.el-feature-cards__nav .inline-icon {
  background-color: currentColor;
  min-width: 20px;
  min-height: 20px;
}
.el-feature-cards__dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--carousel-dot-gap, 8px);
  margin-top: 1.5rem;
}
.el-feature-cards__dot {
  width: var(--carousel-dot-size, 8px);
  height: var(--carousel-dot-size, 8px);
  border-radius: 50%;
  border: none;
  background: var(--carousel-dot-color, var(--site-border));
  cursor: pointer;
  padding: 0;
  transition: background 0.25s ease, width 0.25s ease, border-radius 0.25s ease;
  flex-shrink: 0;
}
.el-feature-cards__dot--active {
  background: var(--carousel-dot-active-color, var(--site-primary));
  width: var(--carousel-dot-active-width, 24px);
  border-radius: 4px;
}

/* Per-card button (inside card body) — reads the element's accent + text color
   vars so it re-themes with the card by default. Purely additive — only renders
   when a card's `button.label` is set. */
.el-feature-cards__card-cta {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  align-self: flex-start;
  margin-top: 12px;
  padding: 10px 18px;
  font-family: inherit;
  font-size: 0.9rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  border-radius: var(--feature-card-cta-radius, 999px);
  background: var(--feature-card-cta-bg, var(--fc-accent, var(--site-accent, var(--site-primary))));
  color: var(--feature-card-cta-color, var(--site-accent-fg, var(--site-primary-fg, currentColor)));
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 160ms ease, color 160ms ease, transform 160ms ease, box-shadow 160ms ease, filter 160ms ease;
}
.el-feature-cards__card-cta:hover {
  filter: brightness(1.08);
  transform: translateY(-1px);
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.15);
}

@container site style(--site-bp: mobile) {
  /* Mobile carousel snap contract — same as testimonials viewport above.
     Strict mandatory snap + zero gap/padding/clip → one card per snap
     stop, no half-card peek. --fcpv forced to 1 on mobile so the card
     width calc resolves to 100% regardless of the author's columns prop. */
  .el-feature-cards--carousel .el-feature-cards__viewport {
    --fcpv: 1;
    gap: 0;
    padding-inline: 0;
    scroll-padding-inline: 0;
    overflow-clip-margin-left: 0; overflow-clip-margin-right: 0;
    scroll-snap-type: x mandatory;
  }
  .el-feature-cards--carousel .el-feature-cards__viewport > .el-feature-cards__card,
  .el-feature-cards--carousel .el-feature-cards__viewport > a.el-feature-cards__card {
    flex-basis: 100%;
  }
  .el-feature-cards--carousel .el-feature-cards__nav--prev { left: -8px; }
  .el-feature-cards--carousel .el-feature-cards__nav--next { right: -8px; }
  .el-feature-cards--carousel .el-feature-cards__nav { width: 36px; height: 36px; }
}
@media (max-width: 768px) {
  /* Mobile carousel snap contract — same as testimonials viewport above.
     Strict mandatory snap + zero gap/padding/clip → one card per snap
     stop, no half-card peek. --fcpv forced to 1 on mobile so the card
     width calc resolves to 100% regardless of the author's columns prop. */
  .el-feature-cards--carousel .el-feature-cards__viewport {
    --fcpv: 1;
    gap: 0;
    padding-inline: 0;
    scroll-padding-inline: 0;
    overflow-clip-margin-left: 0; overflow-clip-margin-right: 0;
    scroll-snap-type: x mandatory;
  }
  .el-feature-cards--carousel .el-feature-cards__viewport > .el-feature-cards__card,
  .el-feature-cards--carousel .el-feature-cards__viewport > a.el-feature-cards__card {
    flex-basis: 100%;
  }
  .el-feature-cards--carousel .el-feature-cards__nav--prev { left: -8px; }
  .el-feature-cards--carousel .el-feature-cards__nav--next { right: -8px; }
  .el-feature-cards--carousel .el-feature-cards__nav { width: 36px; height: 36px; }
}

/* ── Document Download Grid ─────────────────────────────────── */
.el-document-download-grid {
  background: var(--el-bg, var(--document-grid-bg, transparent));
  color: var(--document-grid-text, inherit);
}
.el-document-download-grid .el-compound-section__cards > * {
  border-radius: var(--document-grid-card-radius, inherit);
}

/* ── Quick Action Grid — portal / CTA card grid ─────────────── */
/* Vertical padding from the rhythm token (see er-layout.css § Section
   Vertical Rhythm Contract). Horizontal from the site gutter. */
.el-quick-action-grid {
  padding-block: var(--site-section-pad-y);
  padding-inline: var(--site-content-gutter, 24px);
  /* Defers to parent Section. Override per-element via --el-quick-action-grid-max-width. */
  max-width: var(--el-quick-action-grid-max-width, 100%);
  margin: 0 auto;
  background: var(--el-bg, var(--quick-grid-bg, transparent));
}
.el-quick-action-grid__heading {
  font-family: var(--site-font-heading);
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  font-weight: 700;
  letter-spacing: -0.02em;
  text-align: center;
  margin: 0 0 2rem;
  color: var(--quick-grid-heading-color, var(--site-fg));
}
.el-quick-action-grid__grid {
  display: grid;
  gap: 1.25rem;
  grid-template-columns: repeat(var(--el-grid-cols, 4), minmax(0, 1fr));
}
@container site style(--site-bp: mobile) or style(--site-bp: tablet) { .el-quick-action-grid__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 1024px) { .el-quick-action-grid__grid { grid-template-columns: repeat(2, 1fr); } }
/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) { .el-quick-action-grid__grid { grid-template-columns: 1fr; } }
@media (max-width: 480px) { .el-quick-action-grid__grid { grid-template-columns: 1fr; } }
/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-quick-action-grid__card` (0,1,0) and zeros bg/padding/border-radius/shadow. */
.el.el--quick-action-card > .el-quick-action-grid__card {
  background: var(--quick-grid-card-bg, var(--site-surface, transparent));
  padding: 1.25rem 1.5rem;
  border-radius: var(--quick-grid-card-radius, 0px);
  box-shadow: 0 4px 12px rgba(12, 20, 38, 0.06);
}

.el-quick-action-grid__card {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.25rem 1.5rem;
  background: var(--quick-grid-card-bg, var(--site-surface, transparent));
  border: 1px solid var(--quick-grid-card-border, var(--site-border));
  border-radius: var(--quick-grid-card-radius, 0px);
  box-shadow: 0 4px 12px rgba(12, 20, 38, 0.06);
  color: var(--quick-grid-card-color, var(--site-fg));
  text-decoration: none;
  font-family: var(--site-font-body);
  transition: background-color 0.25s cubic-bezier(0.16, 1, 0.3, 1), color 0.25s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.25s cubic-bezier(0.16, 1, 0.3, 1), transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.25s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1), filter 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
[data-card-hover-shell]:hover .el-quick-action-grid__card {
  transform: translateY(-3px);
  border-color: var(--btn-hover-border, var(--site-accent));
  background: var(--btn-hover-bg, var(--quick-grid-card-bg, var(--site-surface, transparent)));
  color: var(--btn-hover-color, var(--quick-grid-card-color, var(--site-fg, currentColor)));
  box-shadow: 0 12px 28px rgba(12, 20, 38, 0.12);
}
.el-quick-action-grid__icon {
  flex-shrink: 0;
  width: 48px;
  height: 48px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  background: var(--quick-grid-icon-bg, var(--site-primary));
  border: 1px solid color-mix(in srgb, var(--quick-grid-icon-bg, var(--site-primary)) 82%, black 18%);
  color: var(--quick-grid-icon-color, var(--site-accent));
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.14), 0 10px 22px rgba(12, 20, 38, 0.14);
}
.el-quick-action-grid__card:hover .el-quick-action-grid__icon {
  background: color-mix(in srgb, var(--btn-hover-bg, var(--quick-grid-icon-bg, var(--site-primary))) 86%, white 14%);
}
.el-quick-action-grid__label {
  flex: 1;
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: -0.005em;
}
.el-quick-action-grid__chevron {
  font-size: 1.25rem;
  color: var(--quick-grid-chevron-color, var(--site-primary));
  opacity: 0.98;
  transition: transform 0.25s ease, color 0.25s ease;
}
.el-quick-action-grid__card:hover .el-quick-action-grid__chevron {
  color: var(--btn-hover-color, var(--site-accent));
  transform: translateX(3px);
}
/* was @media (max-width: 860px); bucketed to mobile, tablet */
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-quick-action-grid__grid--cols-4 {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (max-width: 860px) {
  .el-quick-action-grid__grid--cols-4 {
    grid-template-columns: repeat(2, 1fr);
  }
}
/* was @media (max-width: 767px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-quick-action-grid__grid--cols-3 {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 767px) {
  .el-quick-action-grid__grid--cols-3 {
    grid-template-columns: 1fr;
  }
}
/* was @media (max-width: 560px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-quick-action-grid__grid--cols-2,
  .el-quick-action-grid__grid--cols-4 {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 560px) {
  .el-quick-action-grid__grid--cols-2,
  .el-quick-action-grid__grid--cols-4 {
    grid-template-columns: 1fr;
  }
}

/* ── Editorial Marquee hero — CTA sizing only ──────────────────
   All colors and hover behavior flow through the global .cta-btn--*
   rules so the site's theme button tokens (--site-btn-primary-bg,
   --site-btn-primary-hover-bg, --site-btn-outline-*, etc.) drive
   idle + hover on the hero exactly like everywhere else on the site.
   If a hero's theme produces low-contrast CTAs against a dark video
   overlay, configure the button tokens in Design Panel → Buttons —
   do NOT re-hardcode colors here. */
.el-editorial-marquee .cta-btn {
  padding: 14px 28px;
  font-weight: 600;
  border-radius: var(--site-radius-lg, 8px);
}

/* Marquee heroes always render content over a dark overlay (the renderer
   paints a gradient overlay on every bg image/video and subheading text
   defaults to primaryForeground). The base .cta-btn--outline fallback
   resolves to var(--site-primary), which on dark-primary themes matches
   the overlay and makes the button invisible. Force white-outline + white
   text, with a translucent glass fill on hover. Mirrors the safety-net
   pattern used by .el-section--dark and .el-cta-with-image--dark.
   Inline styles from element-level button overrides still win. */
.el-editorial-marquee .cta-btn--outline,
.el-editorial-marquee .cta-btn--secondary {
  background: rgba(255,255,255,0.05);
  color: var(--site-primary-fg);
  border-color: rgba(255,255,255,0.86);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.12);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
}
.el-editorial-marquee .cta-btn--outline:hover,
.el-editorial-marquee .cta-btn--secondary:hover {
  background: rgba(255,255,255,0.18);
  color: var(--site-primary-fg);
  border-color: var(--site-primary-fg, currentColor);
  backdrop-filter: blur(16px) saturate(140%);
  -webkit-backdrop-filter: blur(16px) saturate(140%);
  box-shadow: 0 12px 28px rgba(8,14,25,0.24), inset 0 0 0 1px rgba(255,255,255,0.24);
}

/* ── Editorial Marquee — content + supporting chrome ─────────── */
.el-editorial-marquee {
  color: var(--marquee-text, var(--site-primary-fg, currentColor));
}
.el-editorial-marquee__content {
  color: var(--marquee-text, var(--site-primary-fg, currentColor));
}
.el-editorial-marquee__eyebrow {
  display: inline-flex;
  width: fit-content;
  color: var(--marquee-accent, var(--site-accent, currentColor));
  font-size: 0.76rem;
  font-weight: 800;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  text-shadow: var(--marquee-heading-shadow, 0 1px 10px rgba(8, 14, 25, 0.32));
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-editorial-marquee__heading {
  margin: 0;
  color: var(--marquee-heading, var(--marquee-text, var(--site-primary-fg, currentColor)));
  font-family: var(--marquee-heading-font-family, var(--site-font-heading));
  /* Heading font-size pipeline (override-able by inspector via
     `headerFontSize`):
       - When `headerFontSize` is unset/'auto', authors get the responsive
         clamp() that scales fluidly between 360px and ~1600px wide. The
         lower bound (1.65rem ≈ 26px) keeps a one-word headline like
         "Development" from blowing past 360px viewports — the previous
         1.5rem clamp let the browser pick a width that wrapped mid-word.
       - When `headerFontSize` is a px number, the renderer emits
         `--marquee-heading-size` and that wins.
     `word-break: keep-all` keeps Latin words intact while still allowing
     CJK to break naturally. `overflow-wrap: anywhere` is the modern
     replacement for `word-break: break-word` (which is a non-standard
     alias) and only triggers as a last resort on tokens with no soft
     break opportunity. */
  font-size: var(--marquee-heading-size, clamp(1.65rem, 5.4vw, 4.4rem));
  font-weight: var(--marquee-heading-weight, 800);
  line-height: var(--marquee-heading-line-height, 1.04);
  letter-spacing: var(--marquee-heading-letter-spacing, -0.04em);
  text-transform: var(--marquee-heading-transform, none);
  text-shadow: var(--marquee-heading-shadow, none);
  /* Wrap policy: only break unbreakable tokens (URLs, long IDs); regular
     words stay intact. `hyphens: auto` lets the browser soft-hyphenate at
     syllable boundaries when a word genuinely cannot fit, so "Momentum" /
     "Development" never split mid-character. The previous
     `overflow-wrap: anywhere` produced visible mid-word breaks at narrow
     widths even when a soft-break elsewhere would have fit. */
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}
@container site style(--site-bp: mobile) {
  /* Tighter mobile clamp so long words like "Development" / "Momentum"
     stay on a single line at 360px+. Lower ceiling (2.25rem ≈ 36px)
     means a 9-character word fits in the available column without
     forcing a wrap. Authors who set `headerFontSize` explicitly still
     win via the `--marquee-heading-size` var. */
  .el-editorial-marquee__heading {
    font-size: var(--marquee-heading-size, clamp(1.4rem, 7vw, 2.25rem));
    line-height: var(--marquee-heading-line-height, 1.1);
    letter-spacing: var(--marquee-heading-letter-spacing, -0.02em);
  }
}
@media (max-width: 768px) {
  /* Tighter mobile clamp so long words like "Development" / "Momentum"
     stay on a single line at 360px+. Lower ceiling (2.25rem ≈ 36px)
     means a 9-character word fits in the available column without
     forcing a wrap. Authors who set `headerFontSize` explicitly still
     win via the `--marquee-heading-size` var. */
  .el-editorial-marquee__heading {
    font-size: var(--marquee-heading-size, clamp(1.4rem, 7vw, 2.25rem));
    line-height: var(--marquee-heading-line-height, 1.1);
    letter-spacing: var(--marquee-heading-letter-spacing, -0.02em);
  }
}
.el-editorial-marquee__subheading,
.el-editorial-marquee__intro,
.el-editorial-marquee__highlight-description,
.el-editorial-marquee__floating-body,
.el-editorial-marquee__fact-label {
  font-family: var(--marquee-body-font-family, var(--site-font-body));
  font-weight: var(--marquee-body-font-weight, 400);
  line-height: var(--marquee-body-line-height, 1.7);
  letter-spacing: var(--marquee-body-letter-spacing, normal);
  text-transform: var(--marquee-body-transform, none);
  text-shadow: var(--marquee-body-shadow, none);
}
.el-editorial-marquee__subheading {
  margin: 0;
  max-width: min(680px, 100%);
  font-size: var(--marquee-subheading-size, clamp(0.95rem, 1.5vw, 1.18rem));
  /* Default fallback chain: --marquee-subheading (author override) →
     --marquee-text (the marquee's resolved textColor) →
     --site-primary-fg (white on dark hero — the editorial marquee is
     always over a darkened hero image) → currentColor. Without the
     site-primary-fg fallback, `currentColor` inherits from the layout
     root (page foreground, e.g. #111827) producing dark subheading
     copy on a dark hero photo. */
  color: var(--marquee-subheading, var(--marquee-text, var(--site-primary-fg, currentColor)));
  overflow-wrap: break-word;
}
.el-editorial-marquee__intro {
  margin: 0;
  max-width: min(600px, 100%);
  font-size: var(--marquee-intro-size, clamp(0.9rem, 1.2vw, 1rem));
  color: color-mix(in srgb, var(--marquee-text, var(--site-primary-fg, currentColor)) 72%, transparent);
  overflow-wrap: break-word;
}
.el-editorial-marquee__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
}
.el-editorial-marquee__media-panel {
  position: relative;
}
.el-editorial-marquee__media-frame {
  position: absolute;
  inset: 0;
  border-radius: var(--editorial-marquee-panel-radius, 28px);
  overflow: hidden;
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 24%, transparent),
      color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 88%, transparent)
    ),
    var(--marquee-card-bg, var(--site-surface, transparent));
  border: 1px solid color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 22%, rgba(255,255,255,0.22));
  box-shadow: var(--marquee-panel-shadow, 0 32px 90px rgba(8, 14, 25, 0.24));
}
.el-editorial-marquee__media-overlays {
  position: absolute;
  z-index: 2;
  display: grid;
  align-content: space-between;
  gap: 16px;
  pointer-events: none;
}
.el-editorial-marquee__highlights {
  display: grid;
  gap: 12px;
  width: var(--marquee-highlight-width, min(320px, 100%));
  max-width: 100%;
}
.el-editorial-marquee__highlight-card,
.el-editorial-marquee__floating-card {
  text-decoration: none;
  color: var(--marquee-card-heading, var(--marquee-heading, var(--marquee-text, currentColor)));
  border-radius: var(--editorial-marquee-card-radius, 18px);
  border: 1px solid color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 18%, rgba(255,255,255,0.16));
  backdrop-filter: blur(var(--marquee-card-blur, 18px)) saturate(140%);
  -webkit-backdrop-filter: blur(var(--marquee-card-blur, 18px)) saturate(140%);
  box-shadow: var(--marquee-card-shadow, 0 20px 48px rgba(8, 14, 25, 0.22));
  pointer-events: auto;
}
.el-editorial-marquee__highlight-card {
  display: grid;
  gap: 6px;
  padding: 15px 16px;
  min-width: 0;
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 28%, transparent),
      color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 72%, transparent)
    );
}
.el-editorial-marquee__highlight-badge,
.el-editorial-marquee__floating-title {
  color: var(--marquee-accent, var(--site-accent, currentColor));
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-editorial-marquee__highlight-badge {
  margin-bottom: 4px;
}
.el-editorial-marquee__highlight-title,
.el-editorial-marquee__fact-value {
  color: var(--marquee-card-heading, var(--marquee-heading, var(--marquee-text, currentColor)));
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-editorial-marquee__highlight-title {
  font-weight: 800;
  line-height: 1.15;
}
.el-editorial-marquee__highlight-description,
.el-editorial-marquee__floating-body {
  color: var(--marquee-card-body, var(--marquee-subheading, currentColor));
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-editorial-marquee__highlight-description {
  font-size: var(--marquee-card-body-size, 0.84rem);
}
.el-editorial-marquee__floating-card {
  display: grid;
  gap: 12px;
  padding: 20px;
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 32%, transparent),
      color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 80%, transparent)
    );
}
.el-editorial-marquee__floating-title {
  margin-bottom: 8px;
}
.el-editorial-marquee__floating-body {
  margin: 0;
  font-size: var(--marquee-card-body-size, 0.94rem);
}
.el-editorial-marquee__fact-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100px, calc(50% - 5px)), 1fr));
  gap: 10px;
}
.el-editorial-marquee__fact {
  min-width: 0;
  padding: 10px 12px;
  border-radius: 16px;
  background: color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 14%, transparent);
}
.el-editorial-marquee__fact-label {
  color: var(--marquee-card-body, var(--marquee-subheading, currentColor));
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  overflow-wrap: break-word;
  word-break: break-word;
}

/* ── Editorial Marquee — metric cards ──────────────────────────
   Glass-morphism cards on top of the dark hero overlay. Uses explicit
   rgba(255,255,255,…) (same pattern as the hero CTA buttons above) so
   the glass is guaranteed visible regardless of currentColor inheritance.
   Hover chains through CARD_HOVER_FIELDS overrides.
   See SKILL_REFERENCE.md § Card Hover Contract. */
.el-editorial-marquee__metric {
  display: grid;
  gap: 8px;
  padding: 18px 18px 16px;
  border-radius: var(--editorial-marquee-card-radius, 18px);
  background:
    linear-gradient(
      180deg,
      color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 24%, transparent),
      color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 72%, transparent)
    );
  border: 1px solid color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 18%, rgba(255,255,255,0.22));
  backdrop-filter: blur(var(--marquee-card-blur, 20px)) saturate(140%);
  -webkit-backdrop-filter: blur(var(--marquee-card-blur, 20px)) saturate(140%);
  box-shadow: var(--marquee-card-shadow, 0 12px 32px rgba(8, 14, 25, 0.28));
  color: var(--marquee-text, var(--site-primary-fg, currentColor));
  transition: transform 180ms ease, background 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
}
[data-card-hover-shell]:hover .el-editorial-marquee__metric {
  transform: translateY(calc(var(--marquee-metric-hover-lift, 3px) * -1));
  background: var(--marquee-metric-hover-bg,
    linear-gradient(180deg, rgba(255,255,255,0.22), rgba(255,255,255,0.08)));
  border-color: var(--marquee-metric-hover-border-color,
    color-mix(in srgb, var(--site-accent, transparent) 55%, rgba(255,255,255,0.3)));
  box-shadow: var(--marquee-metric-hover-shadow,
    inset 0 1px 0 rgba(255,255,255,0.28),
    0 16px 40px rgba(8, 14, 25, 0.34)),
    0 0 0 1px color-mix(in srgb, var(--site-accent, currentColor) calc(22% * var(--marquee-metric-hover-glow-opacity, 1)), transparent);
}
@media (hover: none) {
  .el-editorial-marquee__metric:hover {
    transform: none;
    background:
      linear-gradient(
        180deg,
        color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 24%, transparent),
        color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 72%, transparent)
      );
    border-color: color-mix(in srgb, var(--marquee-card-bg, var(--site-surface, transparent)) 18%, rgba(255,255,255,0.22));
    box-shadow: var(--marquee-card-shadow, 0 12px 32px rgba(8, 14, 25, 0.28));
  }
}
.el-editorial-marquee__metric-value {
  /* Single visual scale for ALL metric values regardless of content type
     (numeric / alphabetic). Both kinds resolve to the same exact pixel
     size — drives off the site theme `--site-body-size` so the metrics
     read at the platform's body scale, not a custom marquee clamp.
     `--marquee-metric-value-size` is reserved for explicit author
     overrides via the style-group field; absent that, the body token
     wins. Removing the clamp() entirely was deliberate — clamp(min, vw,
     max) at 375px viewport produced 16px for one metric kind and 15px
     for another due to the vw component slipping above/below the min,
     creating the visible 1px size mismatch the user reported. */
  font-size: var(--marquee-metric-value-size, var(--site-body-size, 1rem));
  font-weight: var(--marquee-metric-value-weight, 800);
  letter-spacing: var(--marquee-metric-value-letter-spacing, -0.01em);
  line-height: 1.16;
  color: var(--marquee-text, var(--site-primary-fg, currentColor));
  overflow-wrap: normal;
  word-break: normal;
  hyphens: manual;
  white-space: nowrap;
}
.el-editorial-marquee__metric[data-metric-kind="text"] .el-editorial-marquee__metric-value > span {
  display: inline-block;
  max-width: 100%;
}
.el-editorial-marquee__metric-label {
  font-size: var(--marquee-metric-label-size, 0.72rem);
  font-weight: 600;
  letter-spacing: var(--marquee-metric-label-letter-spacing, 0.14em);
  text-transform: uppercase;
  color: var(--marquee-metric-label-color, currentColor);
  overflow-wrap: break-word;
  word-break: break-word;
}

@container site style(--site-bp: mobile) {
  .el-editorial-marquee__media-overlays {
    position: static;
    padding-top: 16px;
    gap: 14px;
  }
  .el-editorial-marquee__highlights,
  .el-editorial-marquee__floating-card {
    width: 100%;
  }
}
@media (max-width: 768px) {
  .el-editorial-marquee__media-overlays {
    position: static;
    padding-top: 16px;
    gap: 14px;
  }
  .el-editorial-marquee__highlights,
  .el-editorial-marquee__floating-card {
    width: 100%;
  }
}

/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-editorial-marquee__highlight-card,
  .el-editorial-marquee__floating-card,
  .el-editorial-marquee__metric {
    padding: 14px;
  }
  .el-editorial-marquee__media-overlays {
    padding-top: 12px;
    gap: 12px;
  }
  .el-editorial-marquee__metric[data-metric-kind="text"] .el-editorial-marquee__metric-value {
    font-size: clamp(0.9rem, 4vw, 1.12rem);
  }
}
@media (max-width: 480px) {
  .el-editorial-marquee__highlight-card,
  .el-editorial-marquee__floating-card,
  .el-editorial-marquee__metric {
    padding: 14px;
  }
  .el-editorial-marquee__media-overlays {
    padding-top: 12px;
    gap: 12px;
  }
  .el-editorial-marquee__metric[data-metric-kind="text"] .el-editorial-marquee__metric-value {
    font-size: clamp(0.9rem, 4vw, 1.12rem);
  }
}

/* Universal editor-only banner for data-driven elements that are hidden on
   the published site when empty. Injected by any renderer using the
   HIDE_IF_EMPTY_FIELD pattern. Colors tokenized so it reads right on dark or
   light themes. */
.el-empty-banner {
  margin: 0 auto 16px;
  max-width: min(760px, calc(100% - 24px));
  --el-padding-default: 12px 16px;
  border-radius: 10px;
  background: color-mix(in srgb, var(--site-accent, currentColor) 18%, transparent);
  border: 1px dashed color-mix(in srgb, var(--site-accent, currentColor) 55%, transparent);
  color: var(--site-text, currentColor);
  font-size: 0.84rem;
  line-height: 1.5;
  font-weight: 500;
  text-align: center;
}

/* ── CTA With Image — editorial 2-column layout ─────────────── */
/* Vertical padding from the rhythm token (see er-layout.css § Section
   Vertical Rhythm Contract). Horizontal from the site gutter. */
.el-cta-with-image {
  padding-block: var(--site-section-pad-y);
  position: relative;
  overflow: hidden;
}
/* Decorative section background (the Appearance > "Background Image" field).
   Sits behind everything as an absolute layer; content wrappers lift above
   via z-index. When present, a soft gradient veil keeps text readable on
   light or busy photos — driven by --site-surface so it matches the theme. */
.el-cta-with-image__section-bg {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
  pointer-events: none;
}
.el-cta-with-image--has-section-bg::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
  background: linear-gradient(
    135deg,
    color-mix(in srgb, var(--site-surface, transparent) 82%, transparent),
    color-mix(in srgb, var(--site-surface, transparent) 55%, transparent)
  );
}
.el-cta-with-image__inner {
  display: grid;
  grid-template-columns: 5fr 7fr;
  gap: clamp(1.5rem, 4vw, 3.5rem);
  align-items: center;
  position: relative;
  z-index: 1;
}
.el-cta-with-image__inner:not(.el-site-container) {
  max-width: var(--el-cta-with-image-max-width, 100%);
  margin: 0 auto;
}
.el-cta-with-image--image-left .el-cta-with-image__inner {
  grid-template-columns: 7fr 5fr;
}
.el-cta-with-image--image-left .el-cta-with-image__content {
  order: 2;
}
.el-cta-with-image--image-left .el-cta-with-image__media {
  order: 1;
}
/* No-media fallback — collapse to single column when neither flat
   props.image/video nor a media slot child carries a usable URL. Avoids
   the empty placeholder box on pre-migration data. Content centers and
   max-width is bounded to keep readable measure. */
.el-cta-with-image--no-media .el-cta-with-image__inner {
  grid-template-columns: 1fr;
  text-align: center;
}
.el-cta-with-image--no-media .el-cta-with-image__inner:not(.el-site-container) {
  max-width: var(--el-cta-with-image-max-width, 760px);
}
.el-cta-with-image--no-media .el-cta-with-image__content {
  align-items: center;
}
.el-cta-with-image--no-media .el-cta-with-image__actions {
  justify-content: center;
}
.el-cta-with-image__content {
  display: flex;
  flex-direction: column;
  gap: 1rem;
  /* Allow grid item to shrink below intrinsic content width on narrow viewports.
     Without this the panel padding (clamp 28-40px) plus gap pushes the column
     past the 1fr track at <=400px, causing horizontal overflow. */
  min-width: 0;
  /* Editable content-panel surface (glass-aware). Renderer emits
     `--cta-panel-bg` / `--cta-panel-border` from `panelBackground` /
     `panelBorderColor`; when `panelGlass` is true, `--cta-panel-backdrop-filter`
     and `--cta-panel-highlight` paint the frosted-glass effect. Defaults are
     transparent / 0 so the panel is invisible when the author opts out.
     Padding splits Y/X so the inspector's `panelPaddingY` /
     `panelPaddingX` (projected to --cta-panel-padding-y / -x) tune top
     and side breathing room independently. The clamp defaults are the
     "modern" baseline — heading and CTAs always sit comfortably away
     from the panel chrome at every viewport. */
  background: var(--cta-panel-bg, transparent);
  backdrop-filter: var(--cta-panel-backdrop-filter, none);
  -webkit-backdrop-filter: var(--cta-panel-backdrop-filter, none);
  border: 1px solid var(--cta-panel-border, transparent);
  border-radius: var(--site-radius-lg, 16px);
  padding:
    var(--cta-panel-padding-y, clamp(2.5rem, 5vw, 3.5rem))
    var(--cta-panel-padding-x, clamp(1.75rem, 4vw, 2.5rem));
  box-shadow: var(--cta-panel-highlight, none);
  text-align: var(--cta-text-align, left);
  align-items: var(--cta-align-items, flex-start);
}
.el-cta-with-image__eyebrow {
  font-family: var(--site-font-body);
  font-size: 0.75rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--cta-eyebrow-color, var(--site-accent));
  margin-bottom: 0.25rem;
}
.el-cta-with-image__heading {
  font-family: var(--site-font-heading);
  font-size: var(--el-heading-size, clamp(1.75rem, 3.8vw, 2.75rem));
  font-weight: var(--el-heading-weight, 700);
  line-height: 1.1;
  letter-spacing: -0.02em;
  color: var(--cta-heading-color, inherit);
  margin: 0;
}
.el-cta-with-image__body {
  font-family: var(--site-font-body);
  font-size: var(--el-body-size, 1.0625rem);
  line-height: 1.7;
  color: var(--cta-body-color, inherit);
  opacity: 0.88;
}
.el-cta-with-image__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.75rem;
}
.el-cta-with-image__body p {
  margin: 0 0 1rem;
}
.el-cta-with-image__body p:last-child {
  margin-bottom: 0;
}
.el-cta-with-image__button {
  align-self: flex-start;
  margin-top: 0.5rem;
  display: inline-flex;
  align-items: center;
  padding: 14px 28px;
  background: var(--site-accent);
  color: var(--site-accent-fg);
  border: 2px solid var(--site-accent);
  border-radius: var(--site-radius-lg, 8px);
  font-weight: 600;
  font-size: 0.95rem;
  text-decoration: none;
  transition: background-color 0.25s cubic-bezier(0.16, 1, 0.3, 1), color 0.25s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.25s cubic-bezier(0.16, 1, 0.3, 1), transform 0.25s cubic-bezier(0.16, 1, 0.3, 1), box-shadow 0.25s cubic-bezier(0.16, 1, 0.3, 1), opacity 0.25s cubic-bezier(0.16, 1, 0.3, 1), filter 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.el-cta-with-image__button:hover {
  filter: brightness(1.08);
  transform: translateY(-1px);
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.18);
}
.el-cta-with-image--dark .el-cta-with-image__button.cta-btn--primary {
  background: var(--site-accent);
  color: var(--site-accent-fg);
  border-color: var(--site-accent);
}
.el-cta-with-image--dark .el-cta-with-image__button.cta-btn--outline,
.el-cta-with-image--dark .el-cta-with-image__button.cta-btn--secondary {
  background: rgba(255,255,255,0.02) !important;
  color: var(--site-primary-fg) !important;
  border-color: rgba(255,255,255,0.82) !important;
}
.el-cta-with-image--dark .el-cta-with-image__button.cta-btn--outline:hover,
.el-cta-with-image--dark .el-cta-with-image__button.cta-btn--secondary:hover {
  background: rgba(255,255,255,0.12) !important;
  color: var(--site-primary-fg) !important;
  border-color: var(--site-primary-fg, currentColor) !important;
}
.el-section--dark .cta-btn--outline,
.el-section--dark .cta-btn--secondary {
  background: rgba(255,255,255,0.05);
  color: var(--site-primary-fg);
  border-color: rgba(255,255,255,0.86);
  box-shadow: inset 0 0 0 1px rgba(255,255,255,0.12);
}
.el-section--dark .cta-btn--outline:hover,
.el-section--dark .cta-btn--secondary:hover {
  background: rgba(255,255,255,0.14);
  color: var(--site-primary-fg);
  border-color: var(--site-primary-fg, currentColor);
}
.el-cta-with-image__media {
  position: relative;
  /* Aspect + min-height cascade through the unified card token system so
     a CTA-with-image media column aligns with neighbouring carousels and
     grids that read `--site-card-*` per breakpoint. Per-element overrides
     via `--cta-img-*` still win when set. */
  aspect-ratio: var(--cta-img-aspect, var(--site-card-media-aspect, 4 / 3));
  min-height: var(--site-card-min-h, 320px);
  max-height: var(--cta-img-max-height, none);
  border-radius: var(--cta-img-radius, 0px);
  overflow: hidden;
  box-shadow: var(--cta-img-shadow, none);
  max-width: 100%;
  min-width: 0;
}
.el-cta-with-image__image,
.el-cta-with-image__media > video,
.el-cta-with-image__media > img {
  width: 100%;
  height: 100%;
  max-width: 100%;
  object-fit: cover;
  display: block;
}
.el-cta-with-image__placeholder {
  width: 100%;
  height: 100%;
  background: linear-gradient(135deg, rgba(0, 0, 0, 0.04), rgba(0, 0, 0, 0.08));
  color: transparent;
  font-size: 0;
}
/* was @media (max-width: 860px); bucketed to mobile, tablet */
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-cta-with-image__inner,
  .el-cta-with-image--image-left .el-cta-with-image__inner {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  .el-cta-with-image--image-left .el-cta-with-image__content {
    order: 2;
  }
  .el-cta-with-image--image-left .el-cta-with-image__media {
    order: 1;
  }
  .el-cta-with-image__media {
    /* The unified `--site-card-min-h` already drops to `auto` at the
       768px mobile breakpoint via site-components.css, so the explicit
       260px floor here is redundant. Authors retune the floor by editing
       the unified card-min-h token (Cards group in the design panel). */
    min-height: var(--site-card-min-h, 260px);
    aspect-ratio: var(--cta-img-aspect, var(--site-card-media-aspect, 16 / 10));
  }
}
@media (max-width: 860px) {
  .el-cta-with-image__inner,
  .el-cta-with-image--image-left .el-cta-with-image__inner {
    grid-template-columns: 1fr;
    gap: 2rem;
  }
  .el-cta-with-image--image-left .el-cta-with-image__content {
    order: 2;
  }
  .el-cta-with-image--image-left .el-cta-with-image__media {
    order: 1;
  }
  .el-cta-with-image__media {
    /* The unified `--site-card-min-h` already drops to `auto` at the
       768px mobile breakpoint via site-components.css, so the explicit
       260px floor here is redundant. Authors retune the floor by editing
       the unified card-min-h token (Cards group in the design panel). */
    min-height: var(--site-card-min-h, 260px);
    aspect-ratio: var(--cta-img-aspect, var(--site-card-media-aspect, 16 / 10));
  }
}

/* ── CTA With Image — Background image mode ──────────────── */
.el-cta-with-image--bg-mode {
  padding: 0;
  position: relative;
  overflow: hidden;
  min-height: clamp(420px, 55vh, 680px);
  display: flex;
  align-items: stretch;
}
.el-cta-with-image--bg-mode .el-cta-with-image__bg-img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  z-index: 0;
}
.el-cta-with-image--bg-mode .el-cta-with-image__bg-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
}
.el-cta-with-image--bg-mode .el-cta-with-image__bg-content {
  position: relative;
  z-index: 2;
  width: 100%;
  padding-block: clamp(3rem, 6vw, 5.5rem);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  /* Glass-aware content panel (background mode). The content sits on a busy
     hero/video bg, so glass treatment is the default. Same CSS-var contract
     as `.el-cta-with-image__content` — renderer emits the values once and
     both modes pick them up. */
  background: var(--cta-panel-bg, transparent);
  backdrop-filter: var(--cta-panel-backdrop-filter, none);
  -webkit-backdrop-filter: var(--cta-panel-backdrop-filter, none);
  border: 1px solid var(--cta-panel-border, transparent);
  border-radius: var(--site-radius-lg, 16px);
  box-shadow: var(--cta-panel-highlight, none);
}
.el-cta-with-image--bg-mode .el-cta-with-image__bg-content:not(.el-site-container) {
  max-width: var(--el-cta-with-image-max-width, 100%);
  margin: 0 auto;
}
.el-cta-with-image--bg-mode.el-cta-with-image--align-right .el-cta-with-image__bg-content {
  align-items: flex-end;
  text-align: right;
}
.el-cta-with-image--bg-mode.el-cta-with-image--align-center .el-cta-with-image__bg-content {
  align-items: center;
  text-align: center;
}
.el-cta-with-image--bg-mode.el-cta-with-image--align-left .el-cta-with-image__bg-content {
  align-items: flex-start;
  text-align: left;
}
.el-cta-with-image--bg-mode .el-cta-with-image__eyebrow {
  margin-bottom: 0.5rem;
}
.el-cta-with-image--bg-mode .el-cta-with-image__heading {
  font-size: clamp(2rem, 5vw, 3.5rem);
  line-height: 1.05;
  /* Editable per-element via --el-cta-with-image-heading-max-width. */
  max-width: var(--el-cta-with-image-heading-max-width, 100%);
}
.el-cta-with-image--bg-mode .el-cta-with-image__body {
  /* Editable per-element via --el-cta-with-image-body-max-width. */
  max-width: var(--el-cta-with-image-body-max-width, 100%);
  font-size: 1rem;
}
.el-cta-with-image--bg-mode .el-cta-with-image__actions {
  margin-top: 0.5rem;
}
/* was @media (max-width: 600px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-cta-with-image--bg-mode.el-cta-with-image--align-right .el-cta-with-image__bg-content,
  .el-cta-with-image--bg-mode.el-cta-with-image--align-center .el-cta-with-image__bg-content {
    align-items: flex-start;
    text-align: left;
  }
}
@media (max-width: 600px) {
  .el-cta-with-image--bg-mode.el-cta-with-image--align-right .el-cta-with-image__bg-content,
  .el-cta-with-image--bg-mode.el-cta-with-image--align-center .el-cta-with-image__bg-content {
    align-items: flex-start;
    text-align: left;
  }
}

/* ── CTA Band ─────────────────────────────────────────────── */
.el-cta-band {
  --el-padding-default: 4rem var(--site-space-md, 2rem);
  --el-bg-default:      var(--site-primary);
  --el-color-default:   var(--site-primary-fg);
  text-align: center;
  position: relative;
  overflow: hidden;
}
.el-cta-band__overlay {
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}
.el-cta-band--light {
  background: var(--el-bg, var(--site-surface-alt));
  color: var(--site-text);
}
.el-cta-band--accent {
  background: var(--el-bg, var(--site-accent));
}
.el-cta-band__inner {
  /* Defers to parent Section. Override per-element via --el-cta-band-max-width. */
  max-width: var(--el-cta-band-max-width, 100%);
  margin: 0 auto;
  position: relative;
  z-index: 1;
  padding: clamp(24px, 4vw, 38px);
  border-radius: var(--cta-band-inner-radius, 0px);
  background: linear-gradient(180deg, rgba(255,255,255,0.08), rgba(255,255,255,0.04));
  border: 1px solid rgba(255,255,255,0.14);
  backdrop-filter: blur(14px) saturate(130%);
  -webkit-backdrop-filter: blur(14px) saturate(130%);
  box-shadow: 0 28px 72px rgba(7, 12, 20, 0.22);
}
.el-cta-band__heading {
  font-family: var(--site-font-heading);
  font-size: clamp(2rem, 4vw, 3rem);
  font-weight: 700;
  margin: 0 0 1rem;
  letter-spacing: -0.04em;
  line-height: 1.03;
  text-wrap: balance;
  /* See `.el-heading__text` wrap-policy comment — break only at word
     boundaries (or soft-hyphenate via `hyphens: auto` when a single word
     truly cannot fit), never mid-character. */
  overflow-wrap: break-word;
  word-break: normal;
  hyphens: auto;
}
.el-cta-band__subheading {
  font-size: 1rem;
  opacity: 0.82;
  margin: 0 0 1.5rem;
  line-height: 1.72;
  max-width: 620px;
  margin-left: auto;
  margin-right: auto;
}
.el-cta-band__actions {
  display: flex;
  gap: 1rem;
  justify-content: center;
  flex-wrap: wrap;
}
/* CTA Band buttons — variant-independent, scoped to `.el-cta-band-wrap`
   (the class emitted by CtaBandRenderer since Stage 7D). Styling flows
   through `--cta-*` vars set by the design panel; variant contrast
   fallbacks are seeded by `.el-cta-band-wrap--{brand,dark,accent}` in
   er-compound-section.css, so the primary button pops against colored
   section backgrounds without any per-site overrides. */
.el-cta-band-wrap .cta-btn,
.el-cta-band-wrap .cta-btn--primary,
.el-cta-band-wrap .cta-btn--outline,
.el-cta-band-wrap .cta-btn--secondary {
  padding: 14px 28px;
  font-size: clamp(0.95rem, 1vw + 0.5rem, 1.0625rem);
  font-weight: 700;
  letter-spacing: 0.005em;
  border-radius: var(--cta-btn-radius, var(--site-btn-radius, var(--site-radius, 10px)));
  border-width: 2px;
  border-style: solid;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease,
              transform 0.15s ease, box-shadow 0.2s ease, filter 0.2s ease;
}
.el-cta-band-wrap .cta-btn--primary {
  background: var(--cta-primary-bg, var(--site-btn-primary-bg, var(--site-accent, var(--site-primary))));
  color: var(--cta-primary-color, var(--site-btn-primary-text, var(--site-accent-fg, var(--site-primary-fg, currentColor))));
  border-color: var(--cta-primary-border, var(--cta-primary-bg, var(--site-btn-primary-bg, var(--site-accent, var(--site-primary)))));
  box-shadow: 0 12px 28px -12px rgba(0, 0, 0, 0.55);
}
.el-cta-band-wrap .cta-btn--primary:hover {
  filter: brightness(1.08);
  transform: translateY(-2px);
  box-shadow: 0 18px 36px -12px rgba(0, 0, 0, 0.65);
}
/* Outline + secondary fall to `currentColor` so they always read
   against whatever text color the variant projects — light text on
   brand/dark/accent, dark text on light. */
.el-cta-band-wrap .cta-btn--outline,
.el-cta-band-wrap .cta-btn--secondary {
  background: var(--cta-outline-bg, transparent);
  color: var(--cta-outline-color, currentColor);
  border-color: var(--cta-outline-border, currentColor);
}
.el-cta-band-wrap .cta-btn--outline:hover,
.el-cta-band-wrap .cta-btn--secondary:hover {
  /* Hover flips the outline button to a solid fill using the projected
     variant color — --cta-outline-color carries the text token the
     renderer picked, so on hover it becomes the background while text
     inverts to site-primary (brand tone). Shared --site-btn-outline-hover-*
     tokens still win when the theme defines them. */
  background: var(--site-btn-outline-hover-bg, var(--cta-outline-color, currentColor));
  color: var(--site-btn-outline-hover-text, var(--site-primary, currentColor));
  border-color: var(--cta-outline-border, currentColor);
  transform: translateY(-2px);
}

/* ── Pricing Table ───────────────────────────────────────────── */
.el-pricing-table {
  --el-padding-default: 3rem 0;
}
.el-pricing-table__header {
  text-align: center;
  margin-bottom: 2.5rem;
}
.el-pricing-table__heading {
  font-family: var(--site-font-heading);
  font-size: 2rem;
  font-weight: 700;
  color: var(--site-text);
  margin: 0;
}
.el-pricing-table__subheading {
  color: var(--pc-subheading, var(--site-text-secondary));
  margin: 0.5rem 0 0;
  font-size: 1.1rem;
}
.el-pricing-table,
.el-pricing-card {
  --el-accent: var(--pricing-accent, var(--site-accent, var(--site-primary)));
}
.el-pricing-table__grid {
  display: grid;
  /* Desktop: user-selected column count via --el-grid-cols, default 3.
     Collapses to 2 then 1 on smaller screens via the breakpoints below. */
  grid-template-columns: repeat(var(--el-grid-cols, 3), minmax(0, 1fr));
  gap: 1.5rem;
  align-items: stretch;
}
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-pricing-table__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 1024px) {
  .el-pricing-table__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
/* was @media (max-width: 640px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-pricing-table__grid { grid-template-columns: 1fr; }
}
@media (max-width: 640px) {
  .el-pricing-table__grid { grid-template-columns: 1fr; }
}
.el-pricing-table__card {
  position: relative;
  background: var(--pricing-card-bg, var(--site-surface, transparent));
  border: var(--pricing-card-border-width, 1px) solid var(--pricing-card-border-color, var(--site-border));
  /* Per-side accent bars — see .el-pricing-card__plan for rationale. */
  border-top-width: var(--pricing-card-accent-bar-height, var(--pricing-card-border-width, 1px));
  border-top-color: var(--pricing-card-accent-bar-color, var(--pricing-card-border-color, var(--site-border)));
  border-right-width: var(--pricing-card-accent-bar-right-height, var(--pricing-card-border-width, 1px));
  border-right-color: var(--pricing-card-accent-bar-right-color, var(--pricing-card-border-color, var(--site-border)));
  border-bottom-width: var(--pricing-card-accent-bar-bottom-height, var(--pricing-card-border-width, 1px));
  border-bottom-color: var(--pricing-card-accent-bar-bottom-color, var(--pricing-card-border-color, var(--site-border)));
  border-left-width: var(--pricing-card-accent-bar-left-height, var(--pricing-card-border-width, 1px));
  border-left-color: var(--pricing-card-accent-bar-left-color, var(--pricing-card-border-color, var(--site-border)));
  border-radius: var(--pricing-card-border-radius, var(--site-card-radius, var(--site-radius-lg, 16px)));
  padding: var(--pricing-card-padding, 2rem 1.5rem);
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  height: 100%;
  transition: box-shadow 0.2s, transform 0.2s;
  overflow: hidden;
  box-shadow: var(--pricing-card-shadow, 0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04));
}
.el-pricing-table__card > * {
  position: relative;
  z-index: 1;
}
/* Push the footer note + CTA to the bottom so all cards align. */
.el-pricing-table__features { flex: 1 1 auto; }
.el-pricing-table__footer-note {
  margin: 1rem 0 0;
  padding-top: 1rem;
  border-top: 1px dashed rgba(255, 255, 255, 0.08);
  font-size: 0.78rem;
  color: rgba(226, 232, 240, 0.5);
  text-align: center;
  width: 100%;
  font-style: italic;
}
/* CARD_HOVER_FIELDS contract — see SKILL_REFERENCE.md § Card Hover Contract. */
[data-card-hover-shell]:hover .el-pricing-table__card {
  transform: translateY(calc(var(--pricing-table-card-hover-lift, 4px) * -1));
  border-color: var(--pricing-table-card-hover-border-color,
    color-mix(in srgb, var(--site-primary, var(--site-accent, currentColor)) 55%, transparent));
  background: var(--pricing-table-card-hover-bg, transparent);
  box-shadow: var(--pricing-table-card-hover-shadow,
    0 8px 28px rgba(0, 0, 0, 0.12)),
    0 0 0 1px color-mix(in srgb, var(--site-primary, var(--site-accent, currentColor)) calc(18% * var(--pricing-table-card-hover-glow-opacity, 1)), transparent);
}
.el-pricing-table__card--highlighted {
  border-color: var(--site-primary);
  border-width: var(--pricing-card-border-width, 1px);
  transform: translateY(-6px);
  box-shadow: 0 8px 30px rgba(0,0,0,0.1);
}
.el-pricing-table__badge {
  position: absolute;
  top: -16px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--site-primary);
  color: var(--site-primary-fg);
  font-size: 0.75rem;
  font-weight: 600;
  padding: 0.25rem 1rem;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  z-index: 2;
}
.el-pricing-table__plan-name {
  font-family: var(--site-font-heading);
  font-size: 1.25rem;
  font-weight: 600;
  color: var(--site-text);
  margin: 0 0 0.75rem;
}
.el-pricing-table__price-wrap {
  margin-bottom: 1.5rem;
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.125rem;
}
.el-pricing-table__price {
  font-family: var(--site-font-heading);
  font-size: 2.5rem;
  font-weight: 700;
  color: var(--site-text);
  line-height: 1;
}
.el-pricing-table__period {
  font-size: 0.9375rem;
  color: var(--site-text-muted);
}
.el-pricing-table__features {
  list-style: none;
  margin: 0 0 1.5rem;
  padding: 0;
  width: 100%;
  text-align: left;
}
.el-pricing-table__feature {
  padding: 0.5rem 0;
  border-bottom: 1px solid var(--site-border);
  font-size: 0.9375rem;
  color: var(--site-text-secondary);
}
.el-pricing-table__feature:last-child {
  border-bottom: none;
}
.el-pricing-table__feature::before {
  content: '\2713';
  margin-right: 0.5rem;
  color: var(--site-primary);
  font-weight: 700;
}
@container site style(--site-bp: mobile) {
  .el-pricing-table__grid {
    grid-template-columns: 1fr;
  }
  .el-pricing-table__card--highlighted {
    transform: none;
  }
}
@media (max-width: 768px) {
  .el-pricing-table__grid {
    grid-template-columns: 1fr;
  }
  .el-pricing-table__card--highlighted {
    transform: none;
  }
}

/* ── Timeline ────────────────────────────────────────────────── */
.el-timeline {
  --el-padding-default: 2rem 0;
}

/* Vertical layout */
.el-timeline--vertical .el-timeline__item {
  display: grid;
  grid-template-columns: 40px 1fr;
  gap: var(--tl-gap, 1rem);
  min-height: 80px;
}
.el-timeline--vertical .el-timeline__marker {
  display: flex;
  flex-direction: column;
  align-items: center;
}
.el-timeline--vertical .el-timeline__dot {
  width: var(--tl-dot-size, 32px);
  height: var(--tl-dot-size, 32px);
  border-radius: 50%;
  background: var(--tl-dot, var(--tl-accent, var(--site-primary)));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  z-index: 1;
}
.el-timeline--vertical .el-timeline__dot-inner {
  width: var(--tl-dot-inner-size, 10px);
  height: var(--tl-dot-inner-size, 10px);
  border-radius: 50%;
  background: var(--site-primary-fg);
}
.el-timeline--vertical .el-timeline__icon {
  font-size: 0.875rem;
  color: var(--site-primary-fg);
  line-height: 1;
}
.el-timeline--vertical .el-timeline__line {
  flex: 1;
  width: var(--tl-line-w, 2px);
  background: var(--tl-line, var(--site-border));
  margin-top: 4px;
}
.el-timeline--vertical .el-timeline__content {
  padding-bottom: var(--tl-content-padding, 2rem);
}
.el-timeline__date {
  display: inline-block;
  font-size: var(--tl-date-size, 0.8125rem);
  font-weight: 600;
  /* Date label sits on the page surface — fall back to the contrast-safe
     accent token before the raw accent so light-bg sites stay legible. */
  color: var(--tl-date, var(--site-accent-on-light, var(--site-primary)));
  margin-bottom: 0.25rem;
  text-transform: uppercase;
  letter-spacing: 0.03em;
}
.el-timeline__title {
  font-family: var(--site-font-heading);
  font-size: var(--tl-title-size, 1.125rem);
  font-weight: var(--tl-title-weight, 600);
  color: var(--tl-title, var(--site-text));
  margin: 0 0 0.375rem;
}
.el-timeline__description {
  color: var(--tl-desc, var(--site-text-secondary));
  font-size: var(--tl-desc-size, 0.9375rem);
  line-height: var(--tl-desc-lh, 1.6);
  margin: 0;
}

/* Horizontal layout */
.el-timeline--horizontal {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.el-timeline--horizontal .el-timeline__item {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  min-width: 200px;
  text-align: center;
  vertical-align: top;
}
.el-timeline--horizontal .el-timeline__marker {
  display: flex;
  flex-direction: row;
  align-items: center;
  width: 100%;
  justify-content: center;
  margin-bottom: 1rem;
}
.el-timeline--horizontal .el-timeline__dot {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--site-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  z-index: 1;
}
.el-timeline--horizontal .el-timeline__dot-inner {
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--site-primary-fg);
}
.el-timeline--horizontal .el-timeline__icon {
  font-size: 0.875rem;
  color: var(--site-primary-fg);
  line-height: 1;
}
.el-timeline--horizontal .el-timeline__line {
  flex: 1;
  height: 2px;
  background: var(--site-border);
  margin-left: 4px;
}
.el-timeline--horizontal .el-timeline__content {
  padding: 0 1rem;
}
@container site style(--site-bp: mobile) {
  .el-timeline--horizontal .el-timeline__item {
    min-width: 160px;
  }
}
@media (max-width: 768px) {
  .el-timeline--horizontal .el-timeline__item {
    min-width: 160px;
  }
}

/* ── Team (alias for el-team__* used by TeamRenderer) ────────── */
.el-team { padding: 0; }
.el-team__header { text-align: center; margin-bottom: 2rem; }
.el-team__heading { font-family: var(--site-font-heading); font-size: clamp(1.5rem, 3vw, 2.25rem); font-weight: 600; color: var(--team-heading-color, inherit); margin: 0 0 0.5rem; }
.el-team__subheading { color: var(--team-subheading-color, var(--site-text-secondary)); font-size: 0.9375rem; max-width: 600px; margin: 0 auto; }
.el-team__grid { display: grid; gap: var(--team-gap, 2rem); grid-template-columns: repeat(var(--el-grid-cols, 3), 1fr); }
/* was @media (min-width: 769px) and (max-width: 1024px); bucketed via intersection */
@container site style(--site-bp: tablet) { .el-team__grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 769px) and (max-width: 1024px) { .el-team__grid { grid-template-columns: repeat(2, 1fr); } }
@container site style(--site-bp: mobile) { .el-team__grid { grid-template-columns: 1fr; } }
@media (max-width: 768px) { .el-team__grid { grid-template-columns: 1fr; } }
/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-team__card` (0,1,0) and zeros bg/border-radius/shadow. */
.el.el--team-member {
  /* Match wrapper radius to card radius so any builder-configured border
     on the wrapper follows the card's rounded corners (borders go on .el,
     radius via --el-* goes on .el > :not(style) by default). */
  --el-radius-default: var(--team-card-border-radius, 24px);
}
.el.el--team-member > .el-team__card {
  background: var(--team-card-bg, transparent);
  border-radius: var(--team-card-border-radius, var(--site-card-radius, 24px));
  box-shadow: var(--team-card-shadow, 0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04));
}
.el-team__card {
  position: relative;
  /* Resting-state colors cascade through the unified card resting-state
     color contract (src/lib/themeContract.ts § Card resting-state colors). */
  background: var(--team-card-bg, var(--site-card-bg, transparent));
  backdrop-filter: var(--team-card-backdrop-filter, blur(20px) saturate(180%));
  -webkit-backdrop-filter: var(--team-card-backdrop-filter, blur(20px) saturate(180%));
  border: var(--team-card-border-width, var(--site-card-border-width, 1px)) solid var(--team-card-border-color, var(--site-card-border, transparent));
  /* Per-side accent bars — see .el-pricing-card__plan for rationale. */
  border-top-width: var(--team-card-accent-bar-height, var(--team-card-border-width, var(--site-card-border-width, 1px)));
  border-top-color: var(--team-card-accent-bar-color, var(--team-card-border-color, var(--site-card-border, transparent)));
  border-right-width: var(--team-card-accent-bar-right-height, var(--team-card-border-width, var(--site-card-border-width, 1px)));
  border-right-color: var(--team-card-accent-bar-right-color, var(--team-card-border-color, var(--site-card-border, transparent)));
  border-bottom-width: var(--team-card-accent-bar-bottom-height, var(--team-card-border-width, var(--site-card-border-width, 1px)));
  border-bottom-color: var(--team-card-accent-bar-bottom-color, var(--team-card-border-color, var(--site-card-border, transparent)));
  border-left-width: var(--team-card-accent-bar-left-height, var(--team-card-border-width, var(--site-card-border-width, 1px)));
  border-left-color: var(--team-card-accent-bar-left-color, var(--team-card-border-color, var(--site-card-border, transparent)));
  border-radius: var(--team-card-border-radius, var(--site-card-radius, 24px));
  overflow: hidden;
  text-align: center;
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1),
              box-shadow 0.4s cubic-bezier(0.16, 1, 0.3, 1),
              background 0.3s ease;
  box-shadow:
    var(--team-card-shadow, var(--site-card-elevation, 0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04))),
    var(--team-card-highlight, 0 0 transparent);
}
/* CARD_HOVER_FIELDS contract — see SKILL_REFERENCE.md § Card Hover Contract. */
[data-card-hover-shell]:hover .el-team__card {
  transform: translateY(calc(var(--team-card-hover-lift, 6px) * -1)) scale(1.01);
  border-color: var(--team-card-hover-border-color,
    color-mix(in srgb, var(--team-accent, var(--site-accent, currentColor)) 55%, var(--team-card-border-color, transparent)));
  background: var(--team-card-hover-bg, var(--team-card-bg, var(--site-surface, transparent)));
  box-shadow: var(--team-card-hover-shadow,
    0 4px 8px rgba(0, 0, 0, 0.08),
    0 14px 44px rgba(0, 0, 0, 0.14)),
    0 0 0 1px color-mix(in srgb, var(--team-accent, var(--site-accent, currentColor)) calc(18% * var(--team-card-hover-glow-opacity, 1)), transparent);
}
.el-team__photo {
  width: var(--team-photo-size, 168px);
  height: var(--team-photo-size, 168px);
  border-radius: 50%;
  object-fit: cover;
  margin: 2.25rem auto 1.25rem;
  display: block;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  border: 3px solid rgba(255, 255, 255, 0.9);
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.el-team__card:hover .el-team__photo {
  transform: scale(1.05);
}
.el-team__photo-placeholder {
  width: var(--team-photo-size, 168px);
  height: var(--team-photo-size, 168px);
  border-radius: 50%;
  background: var(--site-surface-alt);
  margin: 2.25rem auto 1.25rem;
  border: 3px solid rgba(255, 255, 255, 0.9);
}
.el-team__info { padding: var(--team-card-padding, var(--site-card-padding, 0 2rem 2rem)); }
.el-team__name {
  font-family: var(--site-font-heading);
  font-size: var(--team-card-title-size, 1.25rem);
  font-weight: var(--team-card-title-weight, 700);
  color: var(--team-name-color, var(--site-text));
  margin: 0 0 0.375rem;
  letter-spacing: -0.015em;
}
.el-team__role {
  font-size: 0.75rem;
  color: var(--team-role-color, var(--site-accent));
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  margin: 0 0 1.125rem;
}
.el-team__bio {
  font-size: var(--team-card-description-size, 0.875rem);
  color: var(--team-bio-color, var(--site-text-secondary));
  line-height: var(--team-card-description-line-height, 1.7);
  margin: 0;
  text-align: left;
}
.el-team__socials { display: flex; gap: 0.625rem; justify-content: center; margin-top: 1.25rem; }
.el-team__social-link {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 50%;
  background: var(--site-surface-alt, transparent);
  color: var(--site-text-secondary);
  text-decoration: none;
  transition: background 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
  flex-shrink: 0;
}
.el-team__social-link:hover {
  background: var(--team-accent, var(--site-accent));
  color: var(--site-accent-fg, inherit);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--team-accent, var(--site-accent, currentColor)) 24%, transparent);
}

/* Stage 5 slot wrappers — the new team-member element emits these around
   each slot's children. Styling inherits from the matching .el-team__* rule
   so the legacy and compound-widget markup look identical. */
.el-team__photo-wrap {
  display: flex;
  justify-content: center;
  margin: 2.25rem auto 1.25rem;
}
.el-team__photo-wrap img {
  width: var(--team-photo-size, 168px);
  height: var(--team-photo-size, 168px);
  border-radius: 50%;
  object-fit: cover;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.08);
  border: 3px solid rgba(255, 255, 255, 0.9);
  transition: transform 0.4s cubic-bezier(0.16, 1, 0.3, 1);
}
.el-team__card:hover .el-team__photo-wrap img {
  transform: scale(1.05);
}
.el-team__name-wrap,
.el-team__role-wrap,
.el-team__bio-wrap {
  margin-bottom: 0.5rem;
}
.el-team__role-wrap {
  font-size: 0.75rem;
  color: var(--team-role-color, var(--site-accent));
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.1em;
}
.el-team__bio-wrap {
  font-size: var(--team-card-description-size, 0.875rem);
  color: var(--team-bio-color, var(--site-text-secondary));
  line-height: var(--team-card-description-line-height, 1.7);
  text-align: left;
}

/* ── Social Link element (used inside team-member social slot) ─ */
/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-social-link` (0,1,0) and zeros border-radius/bg. Each social-link
   is a slot child with its own ElementWrapper (.el.el--social-link). */
.el.el--social-link > .el-social-link {
  background: var(--site-surface-alt, transparent);
  border-radius: 50%;
}

.el-social-link {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: calc(var(--social-link-size, 20px) + 16px);
  height: calc(var(--social-link-size, 20px) + 16px);
  border-radius: 50%;
  background: var(--site-surface-alt, transparent);
  color: var(--social-link-color, var(--site-text-secondary));
  text-decoration: none;
  transition: background 0.2s ease, color 0.2s ease, box-shadow 0.2s ease;
  flex-shrink: 0;
}
.el-social-link:hover {
  background: var(--team-accent, var(--site-accent));
  color: var(--site-accent-fg, inherit);
  box-shadow: 0 0 0 2px color-mix(in srgb, var(--team-accent, var(--site-accent, currentColor)) 24%, transparent);
}
.el-social-link .inline-icon {
  width: var(--social-link-size, 20px);
  height: var(--social-link-size, 20px);
  background-color: currentColor;
}

/* ── Testimonial Card ────────────────────────────────────────── */
.el-testimonial {
  --el-padding-default: 3rem 0;
}
.el-testimonial--card .el-testimonial__list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 1.5rem;
}
.el-testimonial--carousel .el-testimonial__list {
  display: flex;
  gap: 1.5rem;
  overflow-x: auto;
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch;
  padding-bottom: 0.5rem;
}
.el-testimonial--carousel .el-testimonial__item {
  min-width: 320px;
  scroll-snap-align: start;
  flex-shrink: 0;
}
.el-testimonial--minimal .el-testimonial__list {
  display: flex;
  flex-direction: column;
  gap: 2rem;
  max-width: 700px;
  margin: 0 auto;
}
.el-testimonial__item {
  background: var(--site-surface, transparent);
  border: 1px solid var(--site-border);
  border-radius: var(--site-radius, 8px);
  padding: 1.5rem;
}
.el-testimonial--minimal .el-testimonial__item {
  background: transparent;
  border: none;
  padding: 0;
  text-align: center;
}
.el-testimonial__stars {
  margin-bottom: 0.75rem;
  display: flex;
  gap: 0.125rem;
}
.el-testimonial--minimal .el-testimonial__stars {
  justify-content: center;
}
.el-testimonial__star {
  font-size: 1.125rem;
  color: var(--site-border);
  line-height: 1;
}
.el-testimonial__star--filled {
  color: var(--site-accent);
}
.el-testimonial__quote {
  font-size: 1rem;
  line-height: 1.7;
  color: var(--site-text-secondary);
  margin: 0 0 1.25rem;
  padding: 0;
  border: none;
  font-style: italic;
}
.el-testimonial__quote::before {
  content: '\201C';
  font-size: 1.5em;
  color: var(--site-primary);
  margin-right: 0.125rem;
  line-height: 0;
  vertical-align: -0.2em;
}
.el-testimonial__author {
  display: flex;
  align-items: center;
  gap: 0.75rem;
}
.el-testimonial--minimal .el-testimonial__author {
  justify-content: center;
}
.el-testimonial__author-photo {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  object-fit: cover;
}
.el-testimonial__author-info {
  display: flex;
  flex-direction: column;
}
.el-testimonial__author-name {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--site-text);
}
.el-testimonial__author-title {
  font-size: 0.8125rem;
  color: var(--site-text-muted);
}
@container site style(--site-bp: mobile) {
  .el-testimonial--card .el-testimonial__list {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 768px) {
  .el-testimonial--card .el-testimonial__list {
    grid-template-columns: 1fr;
  }
}

/* ── Hero Gradient Fallback ──────────────────────────────────── */
/* Painted as a background-image on .el-hero itself (rather than ::before)
   so the ::before pseudo can host the wrapper-emitted --el-overlay-bg scrim
   shared with .el-section / .el-page-header / etc. The renderer's inline
   style.backgroundImage = url(...) cleanly overrides this fallback when the
   user sets a hero image. */
.el-hero {
  background-image: linear-gradient(135deg, var(--site-primary) 0%, color-mix(in srgb, var(--site-primary), #000 30%) 100%); /* mathematical darken-with-black */
}

/* ── Testimonials ────────────────────────────────────────────── */
/* Vertical padding from the rhythm token (see er-layout.css § Section
   Vertical Rhythm Contract). Horizontal from the site gutter. */
.el-testimonials {
  --el-padding-default: var(--site-section-pad-y) var(--site-content-gutter, 24px);
}
/* Wrapper — layout/colour only. Typography owned by the inner .el-heading
   element to prevent cascade into eyebrow/subtitle of the consolidated
   heading element. */
.el-testimonials__heading {
  margin: 0 0 2.5rem;
  color: var(--site-widget-heading-color, var(--testimonials-heading, var(--site-text)));
  text-align: var(--site-widget-heading-align, center);
  max-width: min(760px, 100%);
  margin-inline: auto;
}
.el-testimonials__heading .el-heading__subtitle,
.el-testimonials__heading .el-rich-text,
.el-testimonials__heading .el-rich-text > p {
  max-width: min(680px, 100%);
  margin-left: auto;
  margin-right: auto;
  text-align: center;
  line-height: 1.55;
}

/* Carousel wrapper */
.el-testimonials__carousel {
  position: relative;
}

/* Viewport — CSS scroll-snap container.
   Cards are direct children; no separate track div needed.
   overflow-x: scroll + scroll-snap-type: x proximity lets the browser handle
   all snap positioning natively — no JS transform math, works in any iframe context.
   Scrollbar is hidden visually but scrolling still works (touch, wheel, JS scrollTo). */
.el-testimonials__viewport {
  display: flex;
  gap: var(--tcard-gap, 32px);
  overflow-x: scroll;
  overflow-y: clip;
  overflow-clip-margin-top: var(--site-carousel-shadow-bleed-block, 24px); overflow-clip-margin-bottom: var(--site-carousel-shadow-bleed-block, 24px);
  overflow-clip-margin-left: var(--site-carousel-shadow-bleed-inline, var(--tcard-gap, 32px)); overflow-clip-margin-right: var(--site-carousel-shadow-bleed-inline, var(--tcard-gap, 32px));
  scroll-snap-type: x proximity;
  scroll-behavior: smooth;
  /* If/when this class is re-introduced in JSX, also add `scrollbar-none`
     (canonical helper in src/styles/main.css) to hide the bar. */
  /* Horizontal padding so first/last card shadows aren't clipped by the
     scroll viewport edge; scroll-padding keeps snap-align in place. */
  padding-block: var(--site-carousel-slide-bleed-block, 16px);
  padding-inline: var(--site-carousel-slide-bleed-inline, 16px);
  scroll-padding-inline: var(--site-carousel-slide-bleed-inline, 16px);
  /* Prevent momentum scrolling from overshooting on iOS */
  -webkit-overflow-scrolling: touch;
}

/* Card sizing — pure CSS calc, no JS pixel math needed.
   100% resolves against the scroll container's content-box width (the visible area),
   so (100% - gaps) / N gives exactly 1/N of the visible width per card. */
.el-testimonials__viewport .el-testimonials__card {
  flex: 0 0 calc((100% - var(--tcard-gap, 32px) * (var(--tcpv, 3) - 1)) / var(--tcpv, 3));
  min-width: 0;
  scroll-snap-align: start;
}

/* Prev / Next nav arrows — identical contract + fallbacks to .el-avail-table__nav
   so a testimonials carousel and an availability carousel on the same page render
   the exact same button style without each needing arrow overrides set. */
.el-testimonials__nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: var(--carousel-arrow-size, 44px);
  height: var(--carousel-arrow-size, 44px);
  border-radius: var(--carousel-arrow-radius, 50%);
  border: none;
  background: var(--carousel-arrow-bg, var(--site-accent, var(--site-primary)));
  color: var(--carousel-arrow-color, var(--site-accent-fg, var(--site-primary-fg, currentColor)));
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  box-shadow: var(--carousel-arrow-shadow, 0 4px 16px rgba(0, 0, 0, 0.18));
  transition: transform 160ms ease, opacity 160ms ease, background-color 160ms ease, color 160ms ease, box-shadow 160ms ease, filter 160ms ease;
}
.el-testimonials__nav--prev { left: -22px; }
.el-testimonials__nav--next { right: -22px; }
.el-testimonials__nav:hover {
  filter: var(--carousel-arrow-hover-filter, brightness(1.15));
  background: var(--carousel-arrow-hover-bg, var(--carousel-arrow-bg, var(--site-accent, var(--site-primary))));
  color: var(--carousel-arrow-hover-color, var(--carousel-arrow-color, currentColor));
  transform: translateY(-50%) scale(var(--carousel-arrow-hover-scale, 1.06));
  box-shadow: 0 8px 24px rgba(0, 0, 0, 0.22);
}
/* InlineIcon uses mask-image + currentColor — color is inherited from the button */
.el-testimonials__nav .inline-icon {
  background-color: currentColor;
  min-width: 20px;
  min-height: 20px;
}

/* Card — flex column, width set inline via cardsPerView calc.
   All card styling is var-driven; renderer emits --testimonials-card-* on the section root. */
.el-testimonials__card {
  /* Resting-state colors cascade through the unified card resting-state
     color contract (src/lib/themeContract.ts § Card resting-state colors). */
  background: var(--testimonials-card-bg, var(--site-card-bg, var(--site-surface, transparent)));
  border: var(--site-card-border-width, 1px) solid var(--testimonials-card-border-color, var(--site-card-border, var(--site-border)));
  /* Radius + padding cascade through the unified card token system so a
     testimonials carousel aligns with feature-cards / services / region
     cards on the same page on every breakpoint. */
  border-radius: var(--testimonials-card-radius, var(--site-card-radius, 8px));
  padding: var(--testimonials-card-padding, var(--site-card-padding, clamp(2rem, 2.4vw, 2.35rem)));
  position: relative;
  color: var(--site-card-text, inherit);
  /* Card chrome stack:
       1. Inset accent bar (flush with rounded top corners — `border-top`
          would leave a visible gap at the rounded-corner transition between
          a thick 5px top edge and a 1px side border). Height 0 = bar off.
       2. Author-set card shadow (or unified site-card elevation).
     The accent-bar layer is FIRST so it sits on top, visually bonded to
     the card's top edge. */
  box-shadow:
    inset 0 var(--testimonials-card-accent-bar-height, 0) 0 0 var(--testimonials-card-accent-bar-color, var(--testimonials-accent, var(--site-accent, currentColor))),
    var(--testimonials-card-shadow, var(--site-card-elevation, 0 4px 6px rgba(0,0,0,0.1)));
  -webkit-backdrop-filter: var(--testimonials-card-backdrop-filter, none);
          backdrop-filter: var(--testimonials-card-backdrop-filter, none);
  transition: box-shadow 0.25s ease, transform 0.25s ease;
  display: flex;
  flex-direction: column;
  /* Pack content from the top with a consistent rhythm. Rating, quote, and
     author footer sit directly under one another with a tight gap. When
     the grid equalizes card heights, the author footer uses `margin-top:
     auto` to pin to the bottom — the quote-wrap no longer flex-grows, so
     short quotes don't get inflated with dead whitespace. */
  justify-content: flex-start;
  gap: 0.9rem;
  margin: 0;
  box-sizing: border-box;
}

/* Testimonial cards are rendered inside their own ElementWrapper. The global
   `.el > :not(style)` bridge would otherwise treat the blockquote as a generic
   renderer root and overwrite the parent testimonial card chrome. */
.el.el--testimonial-card > .el-testimonials__card {
  background: var(--testimonials-card-bg, var(--site-card-bg, var(--site-surface, transparent)));
  border-radius: var(--testimonials-card-radius, var(--site-card-radius, 8px));
  padding: var(--testimonials-card-padding, var(--site-card-padding, clamp(2rem, 2.4vw, 2.35rem)));
  /* Mirror the accent-bar contract on the testimonial-card direct-render
     branch so authors get the same stripe regardless of which wrapper
     surface the card lands on. */
  box-shadow:
    inset 0 var(--testimonials-card-accent-bar-height, 0) 0 0 var(--testimonials-card-accent-bar-color, var(--testimonials-accent, var(--site-accent, currentColor))),
    var(--testimonials-card-shadow, var(--site-card-elevation, 0 4px 6px rgba(0,0,0,0.1)));
  -webkit-backdrop-filter: var(--testimonials-card-backdrop-filter, none);
          backdrop-filter: var(--testimonials-card-backdrop-filter, none);
}

/* CARD_HOVER_FIELDS contract — see SKILL_REFERENCE.md § Card Hover Contract. */
[data-card-hover-shell]:hover .el-testimonials__card {
  transform: translateY(calc(var(--testimonials-card-hover-lift, 2px) * -1));
  border-color: var(--testimonials-card-hover-border-color,
    color-mix(in srgb, var(--testimonials-accent, var(--site-accent, currentColor)) 55%, var(--testimonials-card-border-color, transparent)));
  background: var(--testimonials-card-hover-bg, var(--testimonials-card-bg, var(--site-surface, transparent)));
  /* Keep the accent-bar inset shadow on hover so the stripe doesn't blink
     off when the user mouses over the card. */
  box-shadow:
    inset 0 var(--testimonials-card-accent-bar-height, 0) 0 0 var(--testimonials-card-accent-bar-color, var(--testimonials-accent, var(--site-accent, currentColor))),
    var(--testimonials-card-hover-shadow, 0 8px 24px rgba(0, 0, 0, 0.12)),
    0 0 0 1px color-mix(in srgb, var(--testimonials-accent, var(--site-accent, currentColor)) calc(18% * var(--testimonials-card-hover-glow-opacity, 1)), transparent);
}

/* Quote-icon badge — filled accent square at the top of each card. The
   parent testimonials renderer can hide this by emitting
   `--testimonials-quote-icon-display: none`. Size, radius, and color all
   flow from --site-* / --testimonials-* vars so the treatment is
   builder-editable per site. */
.el-testimonials__quote-badge {
  display: var(--testimonials-quote-icon-display, inline-flex);
  align-items: center;
  justify-content: center;
  width: var(--testimonials-quote-icon-size, 40px);
  height: var(--testimonials-quote-icon-size, 40px);
  border-radius: var(--testimonials-quote-icon-radius, 8px);
  background: var(--testimonials-quote-mark, var(--testimonials-accent, var(--site-accent, var(--site-primary))));
  color: var(--testimonials-quote-icon-color, var(--site-accent-contrast, var(--site-surface, currentColor)));
  font-family: Georgia, serif;
  font-size: calc(var(--testimonials-quote-icon-size, 40px) * 0.85);
  line-height: 1;
  font-weight: 700;
  flex-shrink: 0;
  user-select: none;
  margin-bottom: 0.2rem;
}
.el-testimonials__quote-badge::before {
  content: '\201C';
  display: inline-block;
  transform: translateY(0.12em);
}
/* Legacy big typographic curly quote — kept for any site/content that
   still renders the old inline mark directly. Hidden by default unless a
   renderer explicitly opts in with `data-legacy-quote`. */
.el-testimonials__quote-mark[data-legacy-quote] {
  font-size: 4.5rem;
  line-height: 0.7;
  color: var(--testimonials-quote-mark, var(--testimonials-accent, var(--site-accent)));
  font-family: Georgia, serif;
  margin-bottom: 0.35rem;
  display: block;
}

/* Star rating row — tight below quote mark */
.el-testimonials__stars {
  display: flex;
  gap: 0.2rem;
  margin-bottom: 0.35rem;
}
.el-testimonials__star {
  font-size: 1.125rem;
  color: var(--site-border);
  line-height: 1;
  opacity: 0;
  transform: scale(0.5);
}
/* Animate: scale-in + color fill when in view */
.el-testimonials__star--animate {
  animation: testimonial-star-fill 0.35s ease forwards;
}
.el-testimonials__star--filled.el-testimonials__star--animate {
  animation: testimonial-star-fill-gold 0.35s ease forwards;
}
@keyframes testimonial-star-fill {
  0% { opacity: 0; transform: scale(0.5); }
  100% { opacity: 1; transform: scale(1); color: var(--site-border); }
}
@keyframes testimonial-star-fill-gold {
  0% { opacity: 0; transform: scale(0.5); }
  60% { transform: scale(1.2); }
  100% { opacity: 1; transform: scale(1); color: var(--el-star-fill, var(--site-surface)); }
}

/* Testimonial-card slot wraps — pack top-down with the card's `gap` rule
   supplying rhythm. The quote-wrap does NOT flex-grow: with equal-height
   cards in a grid the author footer's `margin-top: auto` pins it to the
   bottom, so the empty space sits between the quote and footer (as a
   block) instead of inside the quote column. */
.el-testimonials__rating-wrap {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}
.el-testimonials__quote-wrap {
  font-size: 1rem;
  line-height: 1.7;
  color: var(--testimonials-quote-text, var(--site-text-secondary));
  font-style: italic;
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  gap: 0.5rem;
}
.el-testimonials__quote-wrap > * { margin: 0; }
.el-testimonials__avatar-wrap {
  flex-shrink: 0;
  display: flex;
  align-items: center;
}
.el-testimonials__name-wrap .el-heading,
.el-testimonials__name-wrap .el-rich-text,
.el-testimonials__role-wrap .el-heading,
.el-testimonials__role-wrap .el-rich-text {
  margin: 0;
}
/* `.el-rich-text p { margin: 0 0 1em }` is the site-wide default; reset
   it inside every testimonial card slot-wrap so single-paragraph content
   (the quote, role, meta) doesn't drop a phantom 1em gap below itself. */
.el-testimonials__card .el-rich-text > p:only-child,
.el-testimonials__card .el-rich-text > p:last-child { margin: 0; }
.el-testimonials__name-wrap .el-heading__text {
  font-size: 0.95rem;
  font-weight: 600;
  margin: 0;
  line-height: 1.25;
}
.el-testimonials__role-wrap {
  font-size: 0.8125rem;
  color: var(--site-text-muted, currentColor);
}
.el-testimonials__role-wrap > * { margin: 0; font-size: inherit; }

/* Footer — sits directly after the quote. `margin-top: auto` pins the
   footer to the bottom of the card when the grid equalizes card heights;
   shorter quotes get the extra whitespace between quote and footer as a
   gap rather than inflating the quote column. A subtle separator line
   marks the transition from quote to author metadata. */
.el-testimonials__author {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  border-top: 1px solid var(--site-border);
  padding-top: 0.75rem;
  margin-top: auto;
}
.el-testimonials__avatar {
  width: var(--testimonials-avatar-size, 44px);
  height: var(--testimonials-avatar-size, 44px);
  border-radius: var(--testimonials-avatar-radius, 50%);
  object-fit: cover;
  flex-shrink: 0;
  border: var(--testimonials-avatar-border-width, 0) solid
    var(--testimonials-avatar-border-color,
      var(--testimonials-accent, var(--site-accent, var(--site-primary))));
}
.el-testimonials__avatar-placeholder {
  width: var(--testimonials-avatar-size, 44px);
  height: var(--testimonials-avatar-size, 44px);
  border-radius: var(--testimonials-avatar-radius, 50%);
  background: var(--testimonials-avatar-bg,
    color-mix(in srgb,
      var(--testimonials-accent, var(--site-accent, var(--site-primary))) 18%,
      transparent));
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--site-font-heading);
  font-weight: 700;
  font-size: 1.125rem;
  color: var(--testimonials-avatar-color,
    var(--testimonials-accent, var(--site-accent, var(--site-primary))));
  flex-shrink: 0;
  border: var(--testimonials-avatar-border-width, 0) solid
    var(--testimonials-avatar-border-color,
      var(--testimonials-accent, var(--site-accent, var(--site-primary))));
}
.el-testimonials__author-info {
  display: flex;
  flex-direction: column;
  gap: 0.125rem;
  min-width: 0;
}

/* Card action buttons — sit directly below the author footer when the
   card declares any of detailsHref / applyHref / portalHref (defined on
   the testimonial-card element). Styles resolve from --site-* tokens so
   every site inherits the brand treatment; per-card overrides can be
   authored via the design panel. */
.el-testimonials__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  margin-top: 0.75rem;
}
.el-testimonials__action {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0.5rem 0.9rem;
  border-radius: var(--site-radius-sm, 6px);
  font-family: var(--site-font-body);
  font-size: 0.8125rem;
  font-weight: 600;
  line-height: 1.2;
  text-decoration: none;
  border: 1px solid transparent;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, filter 0.2s ease;
  cursor: pointer;
  white-space: nowrap;
}
.el-testimonials__action--primary {
  background: var(--testimonials-accent, var(--site-accent, var(--site-primary)));
  color: var(--site-accent-contrast, var(--site-surface, currentColor));
  border-color: transparent;
}
.el-testimonials__action--primary:hover {
  filter: brightness(1.05);
}
.el-testimonials__action--secondary {
  background: transparent;
  color: var(--testimonials-accent, var(--site-accent, var(--site-primary)));
  border-color: color-mix(in srgb, var(--testimonials-accent, var(--site-accent, currentColor)) 45%, transparent);
}
.el-testimonials__action--secondary:hover {
  background: color-mix(in srgb, var(--testimonials-accent, var(--site-accent, currentColor)) 10%, transparent);
  border-color: color-mix(in srgb, var(--testimonials-accent, var(--site-accent, currentColor)) 68%, transparent);
}
.el-testimonials__action--tertiary {
  background: transparent;
  color: var(--testimonials-name, var(--site-text, inherit));
  border-color: var(--testimonials-card-border-color, var(--site-border));
}
.el-testimonials__action--tertiary:hover {
  background: color-mix(in srgb, var(--testimonials-name, var(--site-text, currentColor)) 6%, transparent);
  border-color: color-mix(in srgb, var(--testimonials-name, var(--site-text, currentColor)) 22%, transparent);
}
.el-testimonials__name {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--testimonials-name, var(--site-text));
  font-style: normal;
}
.el-testimonials__role {
  font-size: 0.8125rem;
  color: var(--site-text-muted);
}

/* Dot / page indicators */
.el-testimonials__dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--carousel-dot-gap, 8px);
  margin-top: 1.5rem;
}
.el-testimonials__dot {
  width: var(--carousel-dot-size, 8px);
  height: var(--carousel-dot-size, 8px);
  border-radius: 50%;
  border: none;
  background: var(--carousel-dot-color, var(--site-border));
  cursor: pointer;
  padding: 0;
  transition: background 0.25s ease, width 0.25s ease, border-radius 0.25s ease;
  flex-shrink: 0;
}
.el-testimonials__dot--active {
  background: var(--carousel-dot-active-color, var(--site-primary));
  width: var(--carousel-dot-active-width, 24px);
  border-radius: 4px;
}

@container site style(--site-bp: mobile) {
  /* `.el-testimonials` padding-y is driven by the `--site-section-pad-y`
     rhythm cascade (see er-layout.css § Section Vertical Rhythm
     Contract); the per-element mobile padding override has been removed. */
  /* --tcpv is set to 1 by JS on mobile, so CSS calc already gives 100% width cards */
  /* Mobile carousel snap contract — strict mandatory snap, zero gap, zero
     viewport padding, zero clip bleed → exactly one card per scroll-snap
     stop, no half-card peek (see er-compound-section.css for rationale).
     --tcpv pinned to 1 here as a CSS-side belt-and-braces; the existing
     JS already sets it on mount, but a no-JS / SSR-only render still
     gets a clean snap. */
  .el-testimonials__viewport {
    --tcpv: 1;
    gap: 0;
    padding-inline: 0;
    scroll-padding-inline: 0;
    overflow-clip-margin-left: 0; overflow-clip-margin-right: 0;
    scroll-snap-type: x mandatory;
  }
  .el-testimonials__viewport .el-testimonials__card {
    flex-basis: 100%;
    padding: var(--testimonials-card-padding, 1.75rem);
  }
  .el-testimonials__nav--prev { left: -8px; }
  .el-testimonials__nav--next { right: -8px; }
  .el-testimonials__nav { width: 36px; height: 36px; }
}
@media (max-width: 768px) {
  /* `.el-testimonials` padding-y is driven by the `--site-section-pad-y`
     rhythm cascade (see er-layout.css § Section Vertical Rhythm
     Contract); the per-element mobile padding override has been removed. */
  /* --tcpv is set to 1 by JS on mobile, so CSS calc already gives 100% width cards */
  /* Mobile carousel snap contract — strict mandatory snap, zero gap, zero
     viewport padding, zero clip bleed → exactly one card per scroll-snap
     stop, no half-card peek (see er-compound-section.css for rationale).
     --tcpv pinned to 1 here as a CSS-side belt-and-braces; the existing
     JS already sets it on mount, but a no-JS / SSR-only render still
     gets a clean snap. */
  .el-testimonials__viewport {
    --tcpv: 1;
    gap: 0;
    padding-inline: 0;
    scroll-padding-inline: 0;
    overflow-clip-margin-left: 0; overflow-clip-margin-right: 0;
    scroll-snap-type: x mandatory;
  }
  .el-testimonials__viewport .el-testimonials__card {
    flex-basis: 100%;
    padding: var(--testimonials-card-padding, 1.75rem);
  }
  .el-testimonials__nav--prev { left: -8px; }
  .el-testimonials__nav--next { right: -8px; }
  .el-testimonials__nav { width: 36px; height: 36px; }
}

/* ── Rating (leaf element — star row) ──────────────────────────
 * Stage 4 compound-widget children migration: the rating element is a
 * leaf that paints a row of stars for a 0–max numeric value. Consumes
 * `--rating-color`, `--rating-size`, `--rating-empty-opacity` and is used
 * as a slot child inside testimonial-card (and future per-item widgets
 * that carry a scalar rating).
 */
.el-rating {
  display: inline-flex;
  gap: 0.2rem;
  line-height: 1;
  color: var(--rating-color, var(--site-accent, currentColor));
  font-size: var(--rating-size, 20px);
}
.el-rating__star {
  display: inline-block;
  font-size: inherit;
  line-height: 1;
}
.el-rating__star--empty {
  opacity: var(--rating-empty-opacity, 0.2);
}
.el-rating__star--half {
  position: relative;
  opacity: var(--rating-empty-opacity, 0.2);
}
.el-rating__star--half::before {
  content: '★';
  position: absolute;
  left: 0;
  top: 0;
  width: 50%;
  overflow: hidden;
  opacity: calc(1 / var(--rating-empty-opacity, 0.2));
  color: inherit;
}

/* ── Testimonial card slot wrappers — tight defaults ──────────────
 * Per-slot element wrappers (`.el` → .el-heading / .el-rich-text /
 * .el-rating) must not carry their global vertical margins inside a
 * testimonial card; the card's own `gap` rule supplies rhythm. Anything
 * that would otherwise bloat a slot's bounding box (heading
 * margin-bottom, rich-text paragraph margin-bottom, inline-block quirks)
 * is zeroed here. The avatar sizing, author-name color, and role opacity
 * remain — they're display chrome, not spacing.
 */
.el-testimonials__avatar-wrap img {
  width: var(--testimonials-avatar-size, 44px);
  height: var(--testimonials-avatar-size, 44px);
  border-radius: var(--testimonials-avatar-radius, 50%);
  object-fit: cover;
  flex-shrink: 0;
}
.el-testimonials__name-wrap .el-heading,
.el-testimonials__name-wrap h1,
.el-testimonials__name-wrap h2,
.el-testimonials__name-wrap h3,
.el-testimonials__name-wrap h4 {
  font-size: 0.9375rem;
  font-weight: 600;
  color: var(--testimonials-name, currentColor);
  font-style: normal;
  margin: 0;
}
.el-testimonials__role-wrap {
  opacity: 0.72;
}
/* Kill every default vertical margin on the `.el` element wrappers
   (rating, rich-text, heading, image) that live inside a testimonial
   card. Without these resets the rating wrapper inherits 0.75rem
   bottom, the heading wrapper inherits 1.25rem bottom, and the
   rich-text paragraph inherits 1em bottom — producing the oversized
   selection boxes reported on this element. */
.el-testimonials__card .el-testimonials__rating-wrap > .el,
.el-testimonials__card .el-testimonials__quote-wrap > .el,
.el-testimonials__card .el-testimonials__name-wrap > .el,
.el-testimonials__card .el-testimonials__role-wrap > .el,
.el-testimonials__card .el-testimonials__avatar-wrap > .el {
  margin: 0;
  padding: 0;
}
.el-testimonials__card .el-testimonials__rating-wrap .el-rating,
.el-testimonials__card .el-testimonials__quote-wrap .el-rich-text,
.el-testimonials__card .el-testimonials__name-wrap .el-heading,
.el-testimonials__card .el-testimonials__role-wrap .el-rich-text {
  margin: 0;
  padding: 0;
  line-height: inherit;
}
.el-testimonials__card .el-rich-text > p { margin: 0; }
.el-testimonials__card .el-rich-text > p + p { margin-top: 0.5em; }

/* ── Services ────────────────────────────────────────────────── */
/* Vertical padding from the rhythm token (see er-layout.css § Section
   Vertical Rhythm Contract). Horizontal from the site gutter. */
.el-services {
  padding-block: var(--site-section-pad-y);
  padding-inline: var(--site-content-gutter, 24px);
}
.el-services__header {
  text-align: center;
  margin-bottom: 2.5rem;
}
.el-services__heading {
  font-family: var(--site-font-heading);
  font-size: 2rem;
  font-weight: 700;
  color: var(--site-text);
  margin: 0;
}
.el-services__subheading {
  color: var(--site-text-secondary);
  margin: 0.5rem 0 0;
  font-size: 1.1rem;
}
.el-services__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--svc-gap, 1.5rem);
}
/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-services__card` (0,1,0) and zeros bg/padding/border-radius/shadow. */
.el.el--service-card > .el-services__card {
  background: var(--services-card-bg, var(--site-surface, transparent));
  padding: var(--services-card-padding, var(--site-card-padding, 2rem 1.5rem));
  border-radius: var(--services-card-border-radius, var(--site-card-radius, var(--site-radius, 8px)));
  box-shadow: var(--services-card-shadow, none);
}

.el-services__card {
  position: relative;
  /* Resting-state colors cascade through the unified card resting-state
     color contract (src/lib/themeContract.ts § Card resting-state colors). */
  background: var(--services-card-bg, var(--site-card-bg, var(--site-surface, transparent)));
  color: var(--site-card-text, inherit);
  border: var(--services-card-border-width, var(--site-card-border-width, 1px)) solid var(--services-card-border-color, var(--site-card-border, var(--site-border)));
  /* Per-side accent bars — see .el-pricing-card__plan for rationale. */
  border-top-width: var(--services-accent-bar-height, var(--services-card-border-width, var(--site-card-border-width, 1px)));
  border-top-color: var(--services-accent-bar-color, var(--services-card-border-color, var(--site-card-border, var(--site-border))));
  border-right-width: var(--services-accent-bar-right-height, var(--services-card-border-width, var(--site-card-border-width, 1px)));
  border-right-color: var(--services-accent-bar-right-color, var(--services-card-border-color, var(--site-card-border, var(--site-border))));
  border-bottom-width: var(--services-accent-bar-bottom-height, var(--services-card-border-width, var(--site-card-border-width, 1px)));
  border-bottom-color: var(--services-accent-bar-bottom-color, var(--services-card-border-color, var(--site-card-border, var(--site-border))));
  border-left-width: var(--services-accent-bar-left-height, var(--services-card-border-width, var(--site-card-border-width, 1px)));
  border-left-color: var(--services-accent-bar-left-color, var(--services-card-border-color, var(--site-card-border, var(--site-border))));
  border-radius: var(--services-card-border-radius, var(--site-card-radius, var(--site-radius, 8px)));
  padding: var(--services-card-padding, var(--site-card-padding, 2rem 1.5rem));
  box-shadow: var(--services-card-shadow, var(--site-card-elevation, none));
  transition: box-shadow 0.25s ease, transform 0.25s ease, background 0.25s ease;
}
/* CARD_HOVER_FIELDS contract — see SKILL_REFERENCE.md § Card Hover Contract. */
[data-card-hover-shell]:hover .el-services__card {
  transform: translateY(calc(var(--services-card-hover-lift, 2px) * -1));
  border-color: var(--services-card-hover-border-color,
    color-mix(in srgb, var(--services-accent, var(--site-accent, currentColor)) 55%, var(--services-card-border-color, transparent)));
  background: var(--services-card-hover-bg, var(--services-card-bg, var(--site-surface, transparent)));
  box-shadow: var(--services-card-hover-shadow,
    0 8px 24px rgba(0, 0, 0, 0.12)),
    0 0 0 1px color-mix(in srgb, var(--services-accent, var(--site-accent, currentColor)) calc(18% * var(--services-card-hover-glow-opacity, 1)), transparent);
}
.el-services__icon {
  width: var(--services-icon-size, 56px);
  height: var(--services-icon-size, 56px);
  border-radius: var(--services-icon-radius, calc(var(--site-radius, 8px) * 0.75));
  background: color-mix(in srgb, var(--svc-accent, var(--site-primary)), transparent 88%);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: 1.25rem;
  margin-left: var(--services-icon-offset, 0);
  font-size: 1.5rem;
  color: var(--svc-accent, var(--site-primary));
}
.el-services__icon img,
.el-services__icon svg {
  width: calc(var(--services-icon-size, 56px) * 0.5);
  height: calc(var(--services-icon-size, 56px) * 0.5);
}
.el-services__title {
  font-family: var(--site-font-heading);
  font-size: var(--services-card-title-size, 1.125rem);
  font-weight: var(--services-card-title-weight, 600);
  color: var(--site-text);
  margin: 0 0 0.5rem;
}
.el-services__description {
  font-size: var(--services-card-description-size, 0.9375rem);
  color: var(--site-text-secondary);
  line-height: var(--services-card-description-line-height, 1.6);
  margin: 0 0 1.25rem;
}
.el-services__link {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--svc-accent, var(--site-primary));
  text-decoration: none;
  transition: gap 0.2s ease;
}
.el-services__link:hover {
  gap: 0.625rem;
}
.el-services__link::after {
  content: '\2192';
}
@container site style(--site-bp: mobile) {
  .el-services__grid {
    grid-template-columns: 1fr;
  }
  /* `.el-services` padding-y is driven by the `--site-section-pad-y`
     rhythm cascade — the per-element mobile override that lived here
     duplicated the rhythm-token mobile value and has been removed. */
}
@media (max-width: 768px) {
  .el-services__grid {
    grid-template-columns: 1fr;
  }
  /* `.el-services` padding-y is driven by the `--site-section-pad-y`
     rhythm cascade — the per-element mobile override that lived here
     duplicated the rhythm-token mobile value and has been removed. */
}

/* ── Stats ───────────────────────────────────────────────────── */
.el-stats {
  --el-padding-default: var(--site-space-lg, 3rem) var(--site-space-md, 2rem);
}
/* Thin-shell stats band (CompoundSectionRenderer + sectionClassName 'el-stats')
   ships with responsive top/bottom padding by default so the metrics always
   sit in a visibly padded band — authors can still override via the
   Spacing panel (paddingTop / paddingBottom) which writes inline style. */
.el-compound-section.el-stats {
  padding-block: var(--stats-band-padding-y, clamp(2.25rem, 4.5vw, 3.25rem));
}
.el-compound-section.el-stats .el-compound-section__inner {
  /* Authored via the stats design panel (Layout → Content Area Padding).
     Fallback keeps the responsive clamp so existing sites don't shift. */
}
/* Stats fills its parent flush — overrides both the bare-inner default AND
   the .el-site-container gutter (er-layout.css:2770) so the stats grid lines
   up with whatever wraps it (e.g. an outer bordered .el--stats wrapper).
   --cs-inner-padding-inline / --stats-container-max still let authors put
   gutters back via the design panel if they want. */
.el-compound-section.el-stats .el-compound-section__inner {
  max-width: var(--stats-container-max, 100%);
  padding-inline: var(--cs-inner-padding-inline, 0);
}
/* Stats-only: swap the generic grid for a wrap-flex row so card-containers
   (from CARD_CONTAINER_SCOPES['stats']) distribute with space-between and
   the vertical dividers land exactly at the midpoint of the space between
   every pair of items. --cs-grid-gap is still honoured: it becomes an
   explicit column-gap, and the divider `::after` offset below references
   that same var so dividers stay centered at any author-chosen gap. */
.el-compound-section.el-stats .el-compound-section__cards {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  align-items: stretch;
  column-gap: var(--cs-grid-gap, 0px);
  row-gap: max(var(--cs-grid-gap, 0px), 0px);
}
.el-compound-section.el-stats .el-stats__card-container {
  flex: 1 1 var(--cs-card-min-width, 180px);
  min-width: 0;
  position: relative;
}
/* Stats responsive stacking — fixes the "4 items crushed to 90px each on
   phones" failure mode where flex-shrink:1 + flex-basis:180px collapsed
   into a single squeezed row. The standard `.el-compound-section__cards`
   2-col / 1-col mobile breakpoints in er-compound-section.css don't fire
   for stats because of the higher specificity flex override above. So we
   re-add equivalent breakpoints scoped to `.el-stats` here. */
@container site style(--site-bp: mobile) {
  .el-compound-section.el-stats .el-stats__card-container {
    /* Two columns at tablet/small viewport: each item fills half-row,
       wrap kicks in past two. min-width matches flex-basis to force
       wrap instead of shrink. */
    flex: 1 1 calc(50% - var(--cs-grid-gap, 0px) / 2);
    min-width: calc(50% - var(--cs-grid-gap, 0px) / 2);
  }
}
@media (max-width: 768px) {
  .el-compound-section.el-stats .el-stats__card-container {
    /* Two columns at tablet/small viewport: each item fills half-row,
       wrap kicks in past two. min-width matches flex-basis to force
       wrap instead of shrink. */
    flex: 1 1 calc(50% - var(--cs-grid-gap, 0px) / 2);
    min-width: calc(50% - var(--cs-grid-gap, 0px) / 2);
  }
}
/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-compound-section.el-stats .el-compound-section__cards {
    /* Stack top→bottom on phones: column flow + 100% basis. */
    flex-direction: column;
  }
  .el-compound-section.el-stats .el-stats__card-container {
    flex: 1 1 100%;
    min-width: 100%;
    width: 100%;
  }
  /* Vertical dividers between items make no sense when items are stacked. */
  .el-stats--dark .el-stats__item:not(:last-child)::after,
  .el-stats .el-stats__item:not(:last-child)::after {
    display: none;
  }
}
@media (max-width: 480px) {
  .el-compound-section.el-stats .el-compound-section__cards {
    /* Stack top→bottom on phones: column flow + 100% basis. */
    flex-direction: column;
  }
  .el-compound-section.el-stats .el-stats__card-container {
    flex: 1 1 100%;
    min-width: 100%;
    width: 100%;
  }
  /* Vertical dividers between items make no sense when items are stacked. */
  .el-stats--dark .el-stats__item:not(:last-child)::after,
  .el-stats .el-stats__item:not(:last-child)::after {
    display: none;
  }
}
/* Section wrapping a full-width dark stats bar — collapse section padding so there's
   no white gap above/below the stats. The stats bar itself provides all spacing. */
.el-section:has(.el-stats--dark),
.el-section:has(.el-compound-section--tone-dark.el-stats) {
  padding: 0 !important;
}
/* Outer wrapper and section inner also need to be zero-height when just wrapping a dark stats bar */
.el--section:has(.el-stats--dark),
.el--section:has(.el-compound-section--tone-dark.el-stats) {
  margin: 0;
}
.el-section:has(.el-stats--dark) .el-section__inner,
.el-section:has(.el-compound-section--tone-dark.el-stats) .el-section__inner {
  /* max-width intentionally NOT set here — the .el-site-container contract
   * (siteContainerContract.test.tsx) owns width chrome on inner wrappers.
   * Padding goes to 0 because the dark-stats variant paints full-bleed. */
  padding: 0;
}

/* Stats directly after hero — overlapping transition */
.el--hero + .el--stats {
  margin-top: -3.5rem;
  position: relative;
  z-index: 3;
}
.el--hero + .el--stats .el-stats {
  width: min(1120px, calc(100% - 32px));
  margin-left: auto;
  margin-right: auto;
  padding-top: 1.35rem;
  padding-bottom: 1.35rem;
  border-radius: 24px;
  background: linear-gradient(180deg, rgba(255,255,255,0.92), rgba(255,255,255,0.72));
  border: 1px solid rgba(255,255,255,0.72);
  box-shadow: 0 22px 60px rgba(18, 28, 44, 0.14);
  backdrop-filter: blur(16px);
  -webkit-backdrop-filter: blur(16px);
}
.el--hero + .el--stats .el-stats--dark {
  border-top: none;
  border-bottom: 3px solid var(--site-accent);
}
.el-stats__inner,
.el-stats__grid {
  display: grid;
  /* User-selected column count via --el-grid-cols (default auto-fit). */
  grid-template-columns: repeat(var(--el-grid-cols, auto-fit), minmax(min(180px, 100%), 1fr));
  /* Stretch so every card in a row matches the tallest card's height —
     prevents ragged bottoms when labels wrap to different line counts.
     Cards control internal vertical alignment with `justify-content`
     on `.el-stats__item` (which is `center` by default). */
  align-items: stretch;
  gap: 0;
  /* Defers to parent Section. Override per-element via --el-stats-max-width. */
  max-width: var(--el-stats-max-width, 100%);
  width: 100%;
  margin: 0 auto;
}
/* Dark variant — full-width branded stat bar with gold accent */
.el-stats--dark {
  background: var(--el-bg, var(--site-primary));
  color: var(--site-primary-fg, currentColor);
  width: 100vw;
  margin-left: calc(-50vw + 50%);
  --el-padding-default: var(--site-space-lg, 3rem) var(--site-space-md, 2rem);
  border-top: 3px solid var(--site-accent);
  border-bottom: 3px solid var(--site-accent);
  position: relative;
}
/* Dark-variant text color is now driven by the heading child's own
   `textColor` / `subtitleColor` defaults (which default to
   `$primaryForeground` / `$accent`). The widget-layer fallback previously
   hard-coded `color: #ffffff` here, but that cascaded through `color:
   inherit` on `.el-heading__text`, fighting any author-picked token when
   the heading had no explicit override. Removing the widget-layer default
   lets the heading's own `--el-color` / `--el-subtitle-color` vars be the
   single source of truth. On dark surfaces the heading's
   `$primaryForeground` default still paints white; authors can override
   per heading instance without a specificity war. */
.el-stats--dark .el-stats__item:not(:last-child)::after {
  background: var(--site-accent);
  opacity: 0.45;
}
.el-stats--dark .el-stats__prefix,
.el-stats--dark .el-stats__suffix {
  color: var(--site-accent);
}
/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-stats__item` (0,1,0) and zeros the padding that drives item spacing. */
.el.el--stat-item > .el-stats__item {
  padding: var(--stats-item-padding, 18px) clamp(0.5rem, 2vw, 1.5rem);
}
.el-stats__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: var(--stats-item-padding, 18px) clamp(0.5rem, 2vw, 1.5rem);
  gap: var(--stats-item-gap, 0.35rem);
  position: relative;
  height: 100%;
  width: 100%;
}
/* Card-container wrapper — each stat-item is wrapped in a
   `.el-stats__card-container` by CompoundSectionRenderer (see StatsRenderer's
   `cardWrapperClassName` prop). This is the direct grid sibling, so the
   divider `::after` can rely on `:not(:last-child)` cleanly and per-item
   overrides written as inline CSS vars on the container are picked up by its
   own `::after`. The generator in `src/lib/elements/cardContainerCss.ts`
   emits card chrome (radius, background, border, overflow:hidden) for every
   scope — stats doesn't render as a card, so we neutralize those here. */
.el-compound-section.el-stats .el-stats__card-container {
  background: transparent;
  border-radius: 0;
  box-shadow: none;
  overflow: visible;
  transition: none;
  height: 100%;
}
/* Vertically center the stats row inside the section. When user padding /
   minHeight gives the section more vertical space than the cards need, the
   cards sit top-justified by default (grid align-items:center doesn't pull
   a single-row grid). Flexing the __inner as a column with center-aligned
   content distributes any slack above and below the cards. No-op on
   intrinsic-height sections (cards already fill the flex column). */
.el-compound-section.el-stats > .el-compound-section__inner {
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 100%;
}
.el-compound-section.el-stats .el-stats__card-container:hover {
  transform: none;
  box-shadow: none;
}

/* ── Display As Cards (opt-in via Content panel checkbox) ─────────────
   When the stats element has `displayAsCards: true`, paint each
   .el-stats__card-container as a glass card driven by site theme tokens.
   Chrome stays in lockstep with feature-cards / pricing / comparison
   so authors only need to edit theme tokens once. Defaults are unchanged
   for legacy stats widgets (data-display-as-cards="false" or missing). */
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container {
  /* Equal-share width: stats cards are laid out via flex-wrap row with
     space-between (er-content.css:3588), which leaves cards at content
     width. Cards mode wants every card to fill its share of the row, so
     opt every card-container into flex:1 1 0 for an even split. */
  flex: 1 1 0;
  /* Equal height across the row regardless of label wrap. The parent flex
     row sets align-items: stretch, but author per-element overrides that
     reset display/align on the card or its children can break that contract.
     `align-self: stretch` re-asserts cross-axis stretch, and `height: 100%`
     forces the container to fill the row's tallest sibling so cards with
     1-line vs 2-line labels still match height. */
  align-self: stretch;
  height: 100%;
  display: flex;
  flex-direction: column;
  background: var(--site-glass-bg, var(--site-card-bg));
  border: 1px solid var(--site-glass-border, var(--site-card-border));
  /* Per-side accent bars — see .el-pricing-card__plan for rationale. */
  border-top-width: var(--stats-card-accent-bar-height, 1px);
  border-top-color: var(--stats-card-accent-bar-color, var(--site-glass-border, var(--site-card-border)));
  border-right-width: var(--stats-card-accent-bar-right-height, 1px);
  border-right-color: var(--stats-card-accent-bar-right-color, var(--site-glass-border, var(--site-card-border)));
  border-bottom-width: var(--stats-card-accent-bar-bottom-height, 1px);
  border-bottom-color: var(--stats-card-accent-bar-bottom-color, var(--site-glass-border, var(--site-card-border)));
  border-left-width: var(--stats-card-accent-bar-left-height, 1px);
  border-left-color: var(--stats-card-accent-bar-left-color, var(--site-glass-border, var(--site-card-border)));
  border-radius: var(--stats-card-radius, var(--site-card-radius, 20px));
  padding: 32px 24px;
  -webkit-backdrop-filter: blur(var(--site-glass-blur, 22px)) saturate(180%);
          backdrop-filter: blur(var(--site-glass-blur, 22px)) saturate(180%);
  box-shadow: var(--site-card-elevation), var(--site-glass-highlight);
  overflow: hidden;
  transition: transform 320ms cubic-bezier(.2,.8,.2,1), border-color 320ms ease, box-shadow 320ms ease;
  isolation: isolate;
  position: relative;
}
.el-compound-section.el-stats.el-stats--glass {
  background: var(--stats-bg, transparent);
  border: var(--stats-border, 0 solid transparent);
  -webkit-backdrop-filter: var(--stats-backdrop-filter, none);
          backdrop-filter: var(--stats-backdrop-filter, none);
}
.el-compliance-badge-strip__badge {
  background: var(--compliance-badge-bg, transparent);
  border: var(--compliance-badge-border, 0 solid transparent);
  -webkit-backdrop-filter: var(--compliance-badge-backdrop-filter, none);
          backdrop-filter: var(--compliance-badge-backdrop-filter, none);
}
.el-compound-section.el-stats.el-compound-section--tone-dark[data-display-as-cards="true"] .el-stats__card-container {
  background:
    linear-gradient(180deg, rgba(255,255,255,0.10), rgba(255,255,255,0.045)),
    color-mix(in srgb, var(--site-bg) 5%, var(--site-fg) 95%);
  color: var(--site-bg);
  border-color: color-mix(in srgb, var(--site-bg) 16%, transparent);
  /* Re-apply per-side accent bars after the `border-color` shorthand above,
     so any author-configured accent edge keeps its color in dark-tone variant. */
  border-top-color: var(--stats-card-accent-bar-color, color-mix(in srgb, var(--site-bg) 16%, transparent));
  border-right-color: var(--stats-card-accent-bar-right-color, color-mix(in srgb, var(--site-bg) 16%, transparent));
  border-bottom-color: var(--stats-card-accent-bar-bottom-color, color-mix(in srgb, var(--site-bg) 16%, transparent));
  border-left-color: var(--stats-card-accent-bar-left-color, color-mix(in srgb, var(--site-bg) 16%, transparent));
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,0.12),
    0 18px 48px rgba(0,0,0,0.22);
}
.el-compound-section.el-stats.el-compound-section--tone-dark[data-display-as-cards="true"] .el-stats__value,
.el-compound-section.el-stats.el-compound-section--tone-dark[data-display-as-cards="true"] .el-heading__text {
  color: var(--site-bg);
}
.el-compound-section.el-stats.el-compound-section--tone-dark[data-display-as-cards="true"] .el-heading__subtitle {
  color: var(--site-accent, currentColor);
}
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container:hover {
  transform: translateY(-6px);
  border-color: color-mix(in srgb, var(--site-accent) 32%, transparent);
  /* Re-apply per-side accent bars after the `border-color` shorthand above,
     so any author-configured accent edge keeps its color on hover. */
  border-top-color: var(--stats-card-accent-bar-color, color-mix(in srgb, var(--site-accent) 32%, transparent));
  border-right-color: var(--stats-card-accent-bar-right-color, color-mix(in srgb, var(--site-accent) 32%, transparent));
  border-bottom-color: var(--stats-card-accent-bar-bottom-color, color-mix(in srgb, var(--site-accent) 32%, transparent));
  border-left-color: var(--stats-card-accent-bar-left-color, color-mix(in srgb, var(--site-accent) 32%, transparent));
  box-shadow: var(--site-card-elevation-hover, var(--site-card-elevation)), var(--site-glass-highlight);
}
/* Add a real grid gap between cards (the section sets --cs-grid-gap:0 inline) */
.el-compound-section.el-stats[data-display-as-cards="true"] .el-compound-section__cards {
  gap: 24px;
  --cs-grid-gap: 24px;
}
/* Suppress dividers in card mode (cards themselves separate items) */
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__divider { display: none; }

/* Stretch the inner stat-item to fill the card height so all card heights
   visually match (same baseline as feature-cards). The chain card-container
   → .el wrapper → .el-stats__item must each pass height through, otherwise
   the card-container stretches but the inner sits content-height with empty
   space below (which leaves card *content* equal but card BORDERS uneven if
   .el is content-sized). Explicit `display:flex; flex-direction:column;
   height:100%` on every link in the chain forces the row's tallest content
   to define the row, and every other card matches. */
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container > .el,
/* Animation observer wraps every reveal-animated child in a `.el-animate` div
   sitting between the container and the `.el` element. Without lifting
   `.el-animate` to height:100% the chain breaks here and the card content
   sizes to its natural height, leaving the visible card-container chrome
   taller than the inner content + uneven card heights across the row. */
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container > .el-animate,
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container > .el-animate > .el {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  width: 100%;
  height: 100%;
  min-height: 100%;
}
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__item {
  flex: 1 1 auto;
  width: 100%;
  height: 100%;
  /* Top-align — values sit at the same y across every card. */
  justify-content: flex-start !important;
}
/* Card-mode equal heights — switch from flex to CSS Grid for the cards
   region. Flex's `align-items: stretch` is inconsistent across widths
   when items have `flex: 1 1 <non-zero basis>` (verified via Playwright:
   1440 → 0px delta, 1280/1380/1920 → ~22px delta). CSS Grid's
   `grid-auto-rows: 1fr` natively enforces equal row heights regardless
   of content, with no quirks. We keep the flex selectors above for the
   non-card stats mode (inline stats with vertical dividers). */
.el-compound-section.el-stats[data-display-as-cards="true"] .el-compound-section__cards {
  display: grid !important;
  grid-template-columns: repeat(var(--cs-grid-columns, 3), minmax(min(var(--cs-card-min-width, 180px), 100%), 1fr));
  grid-auto-rows: 1fr;
  gap: var(--cs-grid-gap, 24px);
  align-items: stretch;
  /* Reset flex-only props in case they linger */
  flex-wrap: initial;
  justify-content: initial;
}
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container {
  /* Grid items size to their cell; clear flex overrides */
  flex: initial;
  max-width: 100%;
  align-self: stretch;
  width: 100%;
  height: 100%;
}

/* Card-mode stats need their own responsive floor because the desktop
   equal-share rule above (`flex: 1 1 0`) is intentionally more specific than
   the generic stats mobile stacking rules. Without this override, mobile
   card containers can keep a zero flex-basis, flatten vertically, and clip
   the stat content inside their `overflow:hidden` glass cards. */
@container site style(--site-bp: mobile) {
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-compound-section__cards {
    flex-direction: row;
    gap: max(var(--cs-grid-gap, 24px), 1rem);
  }
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container {
    flex: 1 1 calc(50% - max(var(--cs-grid-gap, 24px), 1rem) / 2);
    min-width: 0;
    max-width: calc(50% - max(var(--cs-grid-gap, 24px), 1rem) / 2);
    /* `height: auto` was forcing content-height even with align-self: stretch
       (Chrome's flex algorithm: an explicit `height` declaration suppresses
       the stretch). Drop it so `align-self: stretch` (set above with
       !important) actually lifts every card in a wrapped line to the line's
       max height. `min-height: 0` is kept — it's needed to prevent the
       opposite failure where cards stretch infinitely under flex shrink. */
    min-height: 0;
    align-self: stretch !important;
    padding: clamp(18px, 5vw, 28px) clamp(14px, 4vw, 22px);
  }
}
@media (max-width: 768px) {
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-compound-section__cards {
    flex-direction: row;
    gap: max(var(--cs-grid-gap, 24px), 1rem);
  }
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container {
    flex: 1 1 calc(50% - max(var(--cs-grid-gap, 24px), 1rem) / 2);
    min-width: 0;
    max-width: calc(50% - max(var(--cs-grid-gap, 24px), 1rem) / 2);
    /* `height: auto` was forcing content-height even with align-self: stretch
       (Chrome's flex algorithm: an explicit `height` declaration suppresses
       the stretch). Drop it so `align-self: stretch` (set above with
       !important) actually lifts every card in a wrapped line to the line's
       max height. `min-height: 0` is kept — it's needed to prevent the
       opposite failure where cards stretch infinitely under flex shrink. */
    min-height: 0;
    align-self: stretch !important;
    padding: clamp(18px, 5vw, 28px) clamp(14px, 4vw, 22px);
  }
}
/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-compound-section__cards {
    flex-direction: column;
  }
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container {
    flex: 0 0 auto;
    width: 100%;
    min-width: 100%;
    max-width: 100%;
  }
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container > .el,
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__item {
    height: auto;
    min-height: 0;
  }
}
@media (max-width: 480px) {
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-compound-section__cards {
    flex-direction: column;
  }
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container {
    flex: 0 0 auto;
    width: 100%;
    min-width: 100%;
    max-width: 100%;
  }
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container > .el,
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__item {
    height: auto;
    min-height: 0;
  }
}

/* Icon chip — match .el-feature-cards__card-icon: cyan-tinted square with
   rounded corners, accent border, accent-colored mask icon. Keeps the
   stats card visual language in lockstep with feature-cards so authors get
   a consistent metric/feature surface across the page. */
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 68px;
  height: 68px;
  border-radius: 16px;
  background: color-mix(in srgb, var(--site-accent) 12%, transparent 88%);
  border: 1px solid color-mix(in srgb, var(--site-accent) 22%, transparent 78%);
  color: var(--site-accent);
  margin-bottom: 18px;
  flex-shrink: 0;
  transition: background 0.3s ease, border-color 0.3s ease;
  position: relative;
  z-index: 1;
}
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container:hover .el-stats__icon {
  background: color-mix(in srgb, var(--site-accent) 18%, transparent 82%);
  border-color: color-mix(in srgb, var(--site-accent) 40%, transparent 60%);
}

/* Subtle attention-grabbing pulse glow behind stat icon discs.
   Universal layer: applies to every site that opts into displayAsCards on stats.
   Stagger across the first four cards so they don't flash in unison. */
@keyframes el-stats-icon-pulse {
  0% { transform: translate(-50%, -50%) scale(1); opacity: 0.5; }
  100% { transform: translate(-50%, -50%) scale(1.4); opacity: 0; }
}
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__icon::after {
  content: '';
  position: absolute;
  top: 50%;
  left: 50%;
  width: 100%;
  height: 100%;
  border-radius: inherit;
  background: color-mix(in srgb, var(--site-accent) 30%, transparent 70%);
  box-shadow: 0 0 24px color-mix(in srgb, var(--site-accent) 40%, transparent 60%);
  transform: translate(-50%, -50%) scale(1);
  opacity: 0.5;
  z-index: -1;
  pointer-events: none;
  animation: el-stats-icon-pulse 2.4s ease-out infinite;
}
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container:nth-child(1) .el-stats__icon::after { animation-delay: 0s; }
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container:nth-child(2) .el-stats__icon::after { animation-delay: 0.6s; }
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container:nth-child(3) .el-stats__icon::after { animation-delay: 1.2s; }
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__card-container:nth-child(4) .el-stats__icon::after { animation-delay: 1.8s; }
@media (prefers-reduced-motion: reduce) {
  .el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__icon::after {
    animation: none;
    opacity: 0;
  }
}
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__icon .el--icon,
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__icon .el-icon {
  display: inline-flex;
}
.el-compound-section.el-stats[data-display-as-cards="true"] .el-stats__icon .inline-icon {
  width: 32px;
  height: 32px;
  background-color: currentColor;
}

/* Divider is now a real DOM element rendered as the last child of every
   .el-stats__item (see StatItemRenderer). Clickable via the `divider`
   sub-part so authors can tune width/color/opacity directly. The container
   remains `position: relative` so the absolutely-positioned divider hangs
   on its right edge, centred in the grid gap (identical visual to the
   previous ::after treatment). Width/color/opacity prefer per-item
   overrides (`--stats-item-separator-*`, set on the card-container by
   StatItemRenderer's effect) and fall back to the widget-level separators. */
.el-stats__divider {
  display: var(--stats-divider-display, block);
  position: absolute;
  /* Position centered in the column gap between adjacent stat cards. When
     the gap var is missing or zero (no explicit gap authored), fall back to
     sitting flush at the item's right edge so authors still see a line. */
  right: calc(var(--cs-grid-gap, 24px) * -0.5);
  top: var(--stats-separator-inset, 20%);
  bottom: var(--stats-separator-inset, 20%);
  /* Width + color + opacity: per-item overrides win; fall back to widget
     controls; fall back to a safe accent-at-50% default so the divider is
     always visible even on pages that predate the divider controls. */
  width: var(--stats-item-separator-width, var(--stats-separator-width, 2px));
  background: var(--stats-item-separator-color, var(--stats-separator-color, var(--stats-separator, var(--site-accent, var(--site-border, transparent)))));
  opacity: var(--stats-item-separator-opacity, var(--stats-separator-opacity, 0.6));
  border-radius: var(--stats-separator-radius, 0);
  /* Keep the divider visually on top of any card-container background that
     might paint into the column gap (hover states, focus rings). */
  z-index: 2;
  pointer-events: auto;
  cursor: pointer;
}
/* Hide the divider on the final stat so the band ends cleanly. */
.el-compound-section.el-stats .el-compound-section__cards > .el-stats__card-container:last-child .el-stats__divider {
  display: none;
}
/* Content-panel toggle: `showDividers=false` projects `--stats-divider-display:none`
   on the section and adds `.el-stats--no-dividers`. Either signal is enough to
   suppress every divider across the bar in one place. */
.el-compound-section.el-stats.el-stats--no-dividers .el-stats__divider {
  display: none;
}
/* Mobile: hide vertical dividers below the navbar-collapse breakpoint. On
   narrow viewports the stats grid wraps to 2-column (or 1-column) layouts —
   the divider is absolutely positioned to the right edge of every item, so
   right-column items project their divider past the section edge into the
   page background. Hiding all dividers on mobile is the universal fix; the
   visual separation is provided by the row/column wrap itself. Applies to
   the `:last-child` exemption rule above too (those are already display:none).
   Using `!important` so per-item inline `--stats-item-separator-*` overrides
   set on `.el-stats__card-container` can't re-show a divider on mobile. */
@container site style(--site-bp: mobile) {
  .el-compound-section.el-stats .el-stats__divider {
    display: none !important;
  }
}
@media (max-width: 768px) {
  .el-compound-section.el-stats .el-stats__divider {
    display: none !important;
  }
}
.el-stats__value {
  font-family: var(--site-font-heading);
  font-size: var(--stats-value-font-size, clamp(2.1rem, 4vw, 3.15rem));
  font-weight: var(--stats-value-font-weight, 700);
  color: var(--stats-value-color, var(--site-primary, var(--site-text)));
  line-height: 1.05;
  letter-spacing: var(--site-heading-h2-tracking, -0.02em);
  /* The wrapper is now a configurable semantic tag (h1–h6, p, div) via the
     design-panel "Value HTML Tag" control. Reset browser default heading /
     paragraph margins so tag choice is purely semantic, never layout-shifting. */
  margin: 0;
}
/* Rich-text children inside the value slot inherit the value typography
   — they're plain text nodes wrapped in a div, so force-inherit so the
   H2-scale size lands on the visible text. */
.el-stats__value .el-rich-text,
.el-stats__value-slot .el-rich-text {
  font: inherit;
  color: inherit;
  line-height: inherit;
  letter-spacing: inherit;
  margin: 0;
  max-width: none;
}
.el-stats__value .el-rich-text > *:first-child,
.el-stats__value-slot .el-rich-text > *:first-child { margin-top: 0; }
.el-stats__value .el-rich-text > *:last-child,
.el-stats__value-slot .el-rich-text > *:last-child { margin-bottom: 0; }
.el-stats__prefix,
.el-stats__suffix {
  font-size: var(--stats-prefix-suffix-size, 0.6em);
  color: var(--stats-accent, var(--site-primary));
  font-weight: 600;
}
/* Descriptor label is now owned by the heading child's built-in subtitle
   (`.el-heading__subtitle`, rendered by HeadingRenderer when a `subtitle`
   prop is set). The parent Stats widget's `label*` design-panel controls
   still cascade to `--stats-label-*` CSS vars; those feed the subtitle
   inside the stat-item value slot as a widget-wide descriptor style.
   Per-item overrides come from the heading's own `subtitle*` props, which
   HeadingRenderer applies as inline styles with higher specificity. */
/* Stats descriptor defaults. The heading's own `--el-subtitle-*` vars
   (set inline by HeadingRenderer) win here via `var(--override, widget-default)`
   chaining, so an author-picked Subtitle Color on the heading child beats
   the widget-wide stats label color without `!important`. */
.el-stats__value-slot .el-heading__subtitle {
  font-size: var(--el-subtitle-font-size, var(--stats-label-font-size, 1.0625rem));
  color: var(--el-subtitle-color, var(--stats-label-color, var(--stats-label, var(--site-accent, var(--site-text-muted)))));
  font-weight: var(--el-subtitle-font-weight, var(--stats-label-font-weight, 600));
  text-transform: var(--el-subtitle-text-transform, var(--stats-label-transform, uppercase));
  letter-spacing: var(--stats-label-letter-spacing, 0.06em);
  line-height: var(--el-subtitle-line-height, 1.25);
  margin: 0;
  margin-top: var(--el-subtitle-margin-top, var(--stats-label-margin-top, 4px));
}
.el-stats__description {
  font-size: 0.8125rem;
  color: var(--site-text-secondary);
  margin-top: 0.25rem;
  line-height: 1.5;
}
/* Value size variants */
.el-stats--value-sm .el-stats__value { font-size: clamp(1.25rem, 2.5vw, 1.75rem); }
.el-stats--value-md .el-stats__value { font-size: clamp(1.5rem, 3vw, 2.25rem); }
.el-stats--value-lg .el-stats__value { font-size: clamp(2rem, 4vw, 3rem); }
.el-stats--value-xl .el-stats__value { font-size: clamp(2.5rem, 5vw, 4rem); }
/* Tablet stats (769–1024px) — keep 4 columns, the parent
   .el-compound-section__cards grid already respects --cs-grid-columns. */
/* was @media (min-width: 769px) and (max-width: 1024px); bucketed via intersection */
@container site style(--site-bp: tablet) {
  .el-compound-section.el-stats .el-compound-section__cards {
    --cs-grid-columns: 4;
  }
}
@media (min-width: 769px) and (max-width: 1024px) {
  .el-compound-section.el-stats .el-compound-section__cards {
    --cs-grid-columns: 4;
  }
}
/* Mobile (≤768px) — items collapse to 2×2 via .el-compound-section__cards
   (see er-compound-section.css). Verticals-only dividers don't map cleanly
   to a 2×2 layout, so we hide them and rely on row spacing instead. */
@container site style(--site-bp: mobile) {
  .el-compound-section.el-stats {
    padding-block: var(--stats-band-padding-y, clamp(2rem, 6vw, 2.75rem));
  }
  .el-compound-section.el-stats .el-stats__card-container {
    flex-basis: calc(50% - max(var(--cs-grid-gap, 0px), 0.75rem) / 2);
    max-width: calc(50% - max(var(--cs-grid-gap, 0px), 0.75rem) / 2);
  }
  .el-compound-section.el-stats .el-compound-section__cards {
    /* Ensure at least some row-gap for 2×2 stacking even when the author
       has set a 0px column gap to make the vertical dividers flush on
       desktop. Column gap continues to follow --cs-grid-gap. */
    column-gap: max(var(--cs-grid-gap, 0px), 0.75rem);
    row-gap: max(var(--cs-grid-gap, 0px), 1.25rem);
  }
  .el-stats__item {
    padding: 0.85rem 0.4rem;
  }
  .el-compound-section.el-stats .el-compound-section__cards > .el-stats__card-container:not(:last-child)::after {
    display: none;
  }
  .el-stats__value {
    font-size: min(var(--stats-value-font-size, clamp(1.75rem, 7vw, 2.5rem)), 3rem);
  }
  .el-stats__value-slot .el-heading__subtitle {
    font-size: min(var(--stats-label-font-size, 0.8125rem), 0.78rem);
    line-height: 1.35;
    letter-spacing: 0.04em;
    text-wrap: balance;
  }
}
@media (max-width: 768px) {
  .el-compound-section.el-stats {
    padding-block: var(--stats-band-padding-y, clamp(2rem, 6vw, 2.75rem));
  }
  .el-compound-section.el-stats .el-stats__card-container {
    flex-basis: calc(50% - max(var(--cs-grid-gap, 0px), 0.75rem) / 2);
    max-width: calc(50% - max(var(--cs-grid-gap, 0px), 0.75rem) / 2);
  }
  .el-compound-section.el-stats .el-compound-section__cards {
    /* Ensure at least some row-gap for 2×2 stacking even when the author
       has set a 0px column gap to make the vertical dividers flush on
       desktop. Column gap continues to follow --cs-grid-gap. */
    column-gap: max(var(--cs-grid-gap, 0px), 0.75rem);
    row-gap: max(var(--cs-grid-gap, 0px), 1.25rem);
  }
  .el-stats__item {
    padding: 0.85rem 0.4rem;
  }
  .el-compound-section.el-stats .el-compound-section__cards > .el-stats__card-container:not(:last-child)::after {
    display: none;
  }
  .el-stats__value {
    font-size: min(var(--stats-value-font-size, clamp(1.75rem, 7vw, 2.5rem)), 3rem);
  }
  .el-stats__value-slot .el-heading__subtitle {
    font-size: min(var(--stats-label-font-size, 0.8125rem), 0.78rem);
    line-height: 1.35;
    letter-spacing: 0.04em;
    text-wrap: balance;
  }
}
/* was @media (max-width: 360px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-compound-section.el-stats .el-stats__card-container {
    flex-basis: 100%;
    max-width: 100%;
  }
}
@media (max-width: 360px) {
  .el-compound-section.el-stats .el-stats__card-container {
    flex-basis: 100%;
    max-width: 100%;
  }
}

/* ── Gallery ─────────────────────────────────────────────────── */
.el-gallery {
  padding: 0;
}
.el-gallery__header {
  text-align: center;
  margin-bottom: 2rem;
}
.el-gallery__heading {
  font-family: var(--site-font-heading, inherit);
  font-size: 2rem;
  font-weight: 700;
  color: var(--site-text, currentColor);
  margin: 0;
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-gallery__subheading {
  font-family: var(--site-font-body, inherit);
  color: var(--site-text-secondary, var(--site-text-muted, currentColor));
  margin: 0.5rem 0 0;
  font-size: 1.1rem;
  overflow-wrap: break-word;
}
.el-gallery__filters {
  display: flex;
  justify-content: center;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 2rem;
}
.el-gallery__filter {
  padding: 0.5rem 1.125rem;
  border: 1px solid var(--site-border);
  border-radius: 999px;
  background: transparent;
  cursor: pointer;
  font-size: 0.875rem;
  font-weight: 500;
  color: var(--site-text-muted);
  transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease, opacity 0.2s ease, filter 0.2s ease;
}
.el-gallery__filter:hover {
  border-color: var(--site-primary);
  color: var(--site-primary);
}
.el-gallery__filter--active {
  background: var(--site-primary);
  border-color: var(--site-primary);
  color: var(--site-primary-fg);
}
.el-gallery__grid {
  display: grid;
  gap: 1rem;
  grid-template-columns: repeat(var(--el-gallery-cols, 3), 1fr);
}
.el-gallery__item {
  position: relative;
  overflow: hidden;
  margin: 0;
  /* --cs-media-radius / --cs-media-shadow are projected by GalleryRenderer
     (rounded + soft md as the global default; respects explicit opt-outs).
     Fall through to site theme tokens when the renderer didn't project,
     and finally to a sensible non-zero floor so a site theme with radius=0
     can't ship square gallery tiles by accident. */
  border-radius: var(--cs-media-radius, var(--site-radius-lg, 12px));
  /* Tile backing surface. Default transparent so the image fills the frame
     edge-to-edge (legacy behaviour — a tinted token would otherwise leak
     through as a visible rim around every photo). Authors who want a card-
     style frame set the gallery Tile Background field, which projects
     --cs-media-bg here; the existing overflow:hidden + --cs-media-radius
     clip the surface to the same rounded shape. */
  background: var(--cs-media-bg, transparent);
  border: 0;
  box-shadow: var(--cs-media-shadow, 0 4px 16px rgba(0,0,0,0.1), 0 2px 6px rgba(0,0,0,0.06));
}
/* High-specificity bridge — `.el > :not(style)` (specificity 0,1,1) repaints
   `box-shadow: var(--el-shadow, var(--el-shadow-default, none))` on the
   figure renderer-root and would otherwise silently zero the gallery tile
   shadow (the nested-.el reset sets `--el-shadow: initial; --el-shadow-
   default: none`). Mirrors the bridge already in place for `.el--feature-
   card > .el-feature-cards__card` above. The `!important` is required
   because the outer `.el > :not(style)` also wins on cascade order; the
   var fallback chain still respects an explicit `cardShadow='none'`
   (GalleryRenderer projects the literal string `'none'`). */
.el.el--gallery-item > .el-gallery__item {
  box-shadow: var(--cs-media-shadow, 0 4px 16px rgba(0,0,0,0.1), 0 2px 6px rgba(0,0,0,0.06)) !important;
  border-radius: var(--cs-media-radius, var(--site-radius-lg, 12px)) !important;
  /* The element wrapper for gallery-item is a flex column (user-controlled
     via the element's display/alignItems props). With align-items=center on
     a single-child wrapper, the figure shrinks to its content's intrinsic
     width (the image's natural width) instead of filling the column —
     producing tiles of mixed widths between siblings. Stretch the figure
     so the column drives the tile width every time, regardless of how the
     wrapper is configured. */
  align-self: stretch;
  width: 100%;
  height: 100%;
}
.el-gallery__item--clickable {
  cursor: pointer;
}
.el-gallery__image {
  width: 100%;
  aspect-ratio: var(--carousel-image-aspect-ratio, 4 / 3);
  object-fit: var(--el-gallery-image-fit, cover);
  display: block;
  transition: transform 0.35s ease;
}
.el-gallery__image--contain {
  aspect-ratio: auto;
  object-fit: contain;
  height: auto;
}
.el-gallery__item:hover .el-gallery__image {
  transform: scale(var(--carousel-hover-zoom, 1.05));
}
.el-gallery--no-hover .el-gallery__item:hover .el-gallery__image {
  transform: none;
}
/* Compound-section gallery items render the image as a child <image>
   element (.el-gallery__item-media > .el-image > .el-image__img) — the
   legacy .el-gallery__image class above never lands in the DOM. Retarget
   the same aspect-ratio / fit / hover-zoom rules at the wrapper + inner
   img so the inspector's cardImageAspectRatio control actually applies.
   Default fallback is `auto` (natural height) — `cardImageAspectRatio`
   has its own default of `16:9`, and `'free'` short-circuits the var
   projection in _carouselStyleVars so the wrapper falls back here. */
.el-gallery__item-media {
  width: 100%;
  aspect-ratio: var(--carousel-image-aspect-ratio, auto);
  overflow: hidden;
  position: relative;
}
.el-gallery__item-media > .el,
.el-gallery__item-media .el-image,
.el-gallery__item-media .el-image__link {
  display: block;
  width: 100%;
  height: 100%;
  margin: 0;
}
.el-gallery__item-media .el-image__img {
  width: 100%;
  height: 100%;
  max-width: none;
  /* Override the global .el-image__img aspect-ratio fallback (16/10) — the
     wrapper owns the shape; the image just fills it. */
  aspect-ratio: auto;
  object-fit: var(--el-gallery-image-fit, cover);
  border-radius: 0;
  display: block;
  transition: transform 0.35s ease;
}
.el-gallery__item:hover .el-gallery__item-media .el-image__img {
  transform: scale(var(--carousel-hover-zoom, 1.05));
}
.el-gallery--no-hover .el-gallery__item:hover .el-gallery__item-media .el-image__img {
  transform: none;
}
.el-gallery--no-hover .el-gallery__item:hover .el-gallery__overlay {
  background: rgba(0,0,0,0);
  opacity: 0;
}
.el-gallery__overlay {
  position: absolute;
  inset: 0;
  /* Base overlay — invisible unless overlayOpacity is raised. */
  background-color: var(--carousel-overlay-color, rgba(0, 0, 0, 0));
  opacity: var(--carousel-overlay-opacity, 0);
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.3s ease, opacity 0.3s ease;
}
.el-gallery__item:hover .el-gallery__overlay {
  /* Hover scrim: keep the legacy dark overlay when user overlayColor/Opacity are unset. */
  background-color: var(--carousel-overlay-color, transparent);
  opacity: max(var(--carousel-overlay-opacity, 0), 0.3);
}
.el-gallery__overlay-icon {
  color: var(--carousel-overlay-icon-color, var(--site-text));
  font-size: 1.5rem;
  opacity: 0;
  transform: translateY(8px);
  transition: opacity 0.3s ease, transform 0.3s ease;
}
.el-gallery__item:hover .el-gallery__overlay-icon {
  opacity: 1;
  transform: translateY(0);
}
.el-gallery__caption {
  margin: 0;
  padding: 0.5rem 0.75rem 0.625rem;
  font-family: var(--site-font-body, inherit);
  font-size: var(--el-gallery-caption-size, 0.8125rem);
  font-weight: var(--el-gallery-caption-weight, 500);
  font-style: var(--el-gallery-caption-style, normal);
  line-height: 1.45;
  letter-spacing: var(--el-gallery-caption-letter-spacing, 0.01em);
  text-transform: var(--el-gallery-caption-transform, none);
  color: var(--el-gallery-caption-color, var(--site-text-secondary, var(--site-text-muted, currentColor)));
  text-align: var(--el-gallery-caption-align, center);
  overflow-wrap: break-word;
}
/* Gallery lightbox backdrop */
.el-gallery__lightbox {
  position: fixed;
  inset: 0;
  z-index: 9999;
  background: rgba(0, 0, 0, 0.9);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 2rem;
}
.el-gallery__lightbox-image {
  max-width: 90vw;
  max-height: 85vh;
  object-fit: contain;
  border-radius: var(--site-radius, 8px);
}
.el-gallery__lightbox-close {
  position: absolute;
  top: 1.5rem;
  right: 1.5rem;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  border: none;
  background: rgba(255, 255, 255, 0.15);
  color: var(--site-fg, currentColor);
  font-size: 1.5rem;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s;
}
.el-gallery__lightbox-close:hover {
  background: rgba(255, 255, 255, 0.3);
}
/* Tablet/mobile gallery — collapse to 2-up then 1-up for readability */
/* was @media (min-width: 769px) and (max-width: 1024px); bucketed via intersection */
@container site style(--site-bp: tablet) {
  .el-gallery__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 769px) and (max-width: 1024px) {
  .el-gallery__grid { grid-template-columns: repeat(2, 1fr); }
}
@container site style(--site-bp: mobile) {
  .el-gallery__grid {
    gap: 0.75rem;
    grid-template-columns: repeat(2, 1fr);
  }
  .el-gallery {
    --el-padding-default: 2rem 1.25rem;
  }
}
@media (max-width: 768px) {
  .el-gallery__grid {
    gap: 0.75rem;
    grid-template-columns: repeat(2, 1fr);
  }
  .el-gallery {
    --el-padding-default: 2rem 1.25rem;
  }
}
/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-gallery__grid { grid-template-columns: 1fr; }
}
@media (max-width: 480px) {
  .el-gallery__grid { grid-template-columns: 1fr; }
}

/* ── Blog Grid / Blog Post List ──────────────────────────────── */
.el-blog-grid,
.el-blog-post-list {
  padding-block: var(--site-space-lg, 4rem);
}
.el-blog-grid {
  padding-inline: var(--site-space-md, 2rem);
}
.el-blog-grid__header,
.el-blog-post-list__header {
  text-align: center;
  margin-bottom: 2.5rem;
}
.el-blog-grid__heading,
.el-blog-post-list__heading {
  font-family: var(--site-font-heading);
  font-size: 2rem;
  font-weight: 700;
  color: var(--site-text);
  margin: 0;
}
.el-blog-grid__subheading,
.el-blog-post-list__subheading {
  color: var(--site-text-secondary);
  margin: 0.5rem 0 0;
  font-size: 1.1rem;
}
.el-blog-grid__grid,
.el-blog-post-list__grid {
  display: grid;
  grid-template-columns: repeat(var(--el-grid-cols, 3), minmax(min(300px, 100%), 1fr));
  gap: 2rem;
}
@container site style(--site-bp: mobile) or style(--site-bp: tablet) {
  .el-blog-grid__grid,
  .el-blog-post-list__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
@media (max-width: 1024px) {
  .el-blog-grid__grid,
  .el-blog-post-list__grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}
.el-blog-post-list__list {
  display: flex;
  flex-direction: column;
  gap: 2rem;
  max-width: 800px;
  margin: 0 auto;
}
/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-blog-grid__card` (0,1,0) and zeros bg/border-radius/shadow.
   No root-level padding on blog cards (padding is on the body sub-element). */
.el.el--blog-card > .el-blog-grid__card {
  background: var(--blog-card-bg, var(--site-surface, transparent));
  border-radius: var(--blog-card-radius, var(--site-card-radius, var(--site-radius, 8px)));
  box-shadow: var(--blog-card-shadow, none);
}

.el-blog-grid__card,
.el-blog-post-list__card {
  /* Resting-state colors cascade through the unified card resting-state
     color contract (src/lib/themeContract.ts § Card resting-state colors). */
  background: var(--blog-card-bg, var(--site-card-bg, var(--site-surface, transparent)));
  border: var(--site-card-border-width, 1px) solid var(--blog-card-border-color, var(--site-card-border, var(--site-border)));
  border-radius: var(--blog-card-radius, var(--site-card-radius, var(--site-radius, 8px)));
  color: var(--blog-card-text, var(--site-card-text, inherit));
  box-shadow: var(--blog-card-shadow, var(--site-card-elevation, none));
  overflow: hidden;
  transition: box-shadow 0.25s ease, transform 0.25s ease, background 0.2s ease;
}
/* CARD_HOVER_FIELDS contract — see SKILL_REFERENCE.md § Card Hover Contract. */
[data-card-hover-shell]:hover .el-blog-grid__card,
[data-card-hover-shell]:hover .el-blog-post-list__card {
  transform: translateY(calc(var(--blog-card-hover-lift, 2px) * -1));
  border-color: var(--blog-card-hover-border-color,
    color-mix(in srgb, var(--site-accent, currentColor) 55%, transparent));
  background: var(--blog-card-hover-bg, var(--blog-card-bg, var(--site-surface, transparent)));
  box-shadow: var(--blog-card-hover-shadow,
    0 8px 24px rgba(0, 0, 0, 0.12)),
    0 0 0 1px color-mix(in srgb, var(--site-accent, currentColor) calc(18% * var(--blog-card-hover-glow-opacity, 1)), transparent);
}
.el-blog-grid__thumbnail-wrap,
.el-blog-post-list__thumbnail-wrap {
  overflow: hidden;
}
.el-blog-grid__thumbnail,
.el-blog-grid__image,
.el-blog-post-list__thumbnail {
  width: 100%;
  aspect-ratio: var(--blog-thumb-ratio, 16 / 9);
  object-fit: cover;
  display: block;
  background: color-mix(in srgb, var(--site-text) 8%, transparent);
  transition: transform 0.4s ease;
}
.el-blog-grid__card:hover .el-blog-grid__thumbnail,
.el-blog-grid__card:hover .el-blog-grid__image,
.el-blog-post-list__card:hover .el-blog-post-list__thumbnail {
  transform: scale(1.03);
}
.el-blog-grid__body,
.el-blog-grid__content,
.el-blog-post-list__body,
.el-blog-post-list__content {
  padding: var(--blog-card-padding, var(--site-card-padding, 1.5rem));
}
.el-blog-grid__categories,
.el-blog-post-list__categories {
  display: flex;
  gap: 0.5rem;
  flex-wrap: wrap;
  margin-bottom: 0.75rem;
}
.el-blog-grid__category,
.el-blog-post-list__category {
  display: inline-block;
  padding: 0.1875rem 0.625rem;
  font-size: var(--blog-category-size, 0.6875rem);
  font-weight: var(--blog-category-weight, 600);
  text-transform: uppercase;
  letter-spacing: 0.05em;
  background: var(--blog-category-bg, color-mix(in srgb, var(--site-primary), transparent 88%));
  color: var(--blog-category-color, var(--site-primary));
  border-radius: 999px;
}
.el-blog-grid__title,
.el-blog-post-list__title {
  font-family: var(--site-font-heading);
  font-size: var(--blog-title-size, 1.25rem);
  font-weight: var(--blog-title-weight, 600);
  color: var(--site-text);
  margin: 0 0 0.5rem;
  line-height: 1.3;
}
.el-blog-grid__title a,
.el-blog-post-list__title a {
  color: inherit;
  text-decoration: none;
  transition: color 0.15s;
}
.el-blog-grid__title a:hover,
.el-blog-post-list__title a:hover {
  color: var(--site-primary);
}
.el-blog-grid__excerpt,
.el-blog-post-list__excerpt {
  font-size: var(--blog-excerpt-size, 0.9375rem);
  color: var(--blog-excerpt-color, var(--site-text-secondary));
  line-height: var(--blog-excerpt-line-height, 1.6);
  margin: 0 0 1.25rem;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}
.el-blog-grid__meta,
.el-blog-post-list__meta {
  display: flex;
  align-items: center;
  gap: var(--blog-meta-gap, 1rem);
  font-size: var(--blog-meta-size, 0.8125rem);
  font-weight: var(--blog-meta-weight, 400);
  color: var(--blog-meta-color, var(--site-text-muted));
}
.el-blog-grid__meta-author,
.el-blog-post-list__meta-author {
  font-weight: 600;
  color: var(--site-text);
}
.el-blog-grid__meta-sep,
.el-blog-post-list__meta-sep {
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: var(--blog-meta-color, var(--site-text-muted));
  flex-shrink: 0;
}
.el-blog-grid__read-more,
.el-blog-post-list__read-more {
  display: inline-flex;
  align-items: center;
  gap: 0.375rem;
  font-size: var(--blog-read-more-size, 0.875rem);
  font-weight: var(--blog-read-more-weight, 600);
  color: var(--blog-read-more-color, var(--site-primary));
  text-decoration: none;
  margin-top: 0.75rem;
  transition: gap 0.2s ease;
}
.el-blog-grid__read-more:hover,
.el-blog-post-list__read-more:hover {
  gap: 0.625rem;
}
.el-blog-grid__read-more::after,
.el-blog-post-list__read-more::after {
  content: '\2192';
}
/* Blog post list — vertical-stack list variant */
.el-blog-post-list__list {
  gap: var(--blog-row-gap, 2rem);
}
.el-blog-post-list__list .el-blog-post-list__card {
  padding: var(--blog-row-padding, 0);
}
/* Blog post list — horizontal card variant */
.el-blog-post-list__card--horizontal {
  display: grid;
  grid-template-columns: var(--blog-horizontal-image-width, 280px) 1fr;
}
.el-blog-post-list__card--horizontal .el-blog-post-list__thumbnail {
  height: 100%;
  aspect-ratio: auto;
}
@container site style(--site-bp: mobile) {
  .el-blog-grid__grid {
    grid-template-columns: 1fr;
  }
  .el-blog-post-list__card--horizontal {
    grid-template-columns: 1fr;
  }
  .el-blog-grid,
  .el-blog-post-list {
    padding-block: 2rem;
  }
  .el-blog-grid {
    padding-inline: 1.25rem;
  }
}
@media (max-width: 768px) {
  .el-blog-grid__grid {
    grid-template-columns: 1fr;
  }
  .el-blog-post-list__card--horizontal {
    grid-template-columns: 1fr;
  }
  .el-blog-grid,
  .el-blog-post-list {
    padding-block: 2rem;
  }
  .el-blog-grid {
    padding-inline: 1.25rem;
  }
}

/* ── Blog Card slot wrappers (Stage 6B compound-widget children) ─────
   The `blog-card` element renders each sub-part (media/meta/heading/body/
   primary-cta) inside a scoped wrapper so slot-selection highlights land on
   the right subtree in the inspector. All visual chrome continues to flow
   from the parent `blog-grid`'s `--blog-card-*` CSS vars consumed by
   `.el-blog-grid__card` above. */
.el-blog-grid__card .el-blog-grid__title-wrap {
  margin: 0 0 0.5rem;
}
.el-blog-grid__card .el-blog-grid__title-link {
  color: inherit;
  text-decoration: none;
  display: block;
  transition: color 0.15s;
}
.el-blog-grid__card .el-blog-grid__title-link:hover {
  color: var(--site-primary);
}
.el-blog-grid__card .el-blog-grid__category-wrap {
  margin-bottom: 0.75rem;
}
.el-blog-grid__card .el-blog-grid__excerpt-wrap {
  margin-bottom: 1.25rem;
}
.el-blog-grid__card .el-blog-grid__cta-wrap {
  margin-top: auto;
}
.el-blog-grid__card .el-blog-grid__card-extra {
  margin-top: 1rem;
}

/* ── Recent Posts (sidebar widget) ───────────────────────────── */
.el-recent-posts {
  --el-padding-default: var(--site-space-md, 1.5rem);
}
.el-recent-posts__heading {
  font-family: var(--site-font-heading);
  font-size: 0.8125rem;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--site-text-muted);
  margin: 0 0 1rem;
}
.el-recent-posts__preview-note {
  font-size: 0.75rem;
  color: var(--site-text-muted);
  font-style: italic;
  margin: 0 0 0.75rem;
}
.el-recent-posts__list {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--recent-item-gap, 12px);
}
.el-recent-posts__item {
  display: flex;
  align-items: flex-start;
  gap: var(--recent-thumb-gap, 12px);
}
.el-recent-posts__thumbnail {
  flex-shrink: 0;
  width: var(--recent-thumb-size, 72px);
  height: var(--recent-thumb-size, 72px);
  aspect-ratio: var(--recent-thumb-ratio, 1 / 1);
  border-radius: var(--site-radius, 8px);
  background: color-mix(in srgb, var(--site-text) 8%, transparent);
  object-fit: cover;
}
.el-recent-posts__info {
  flex: 1;
  min-width: 0;
}
.el-recent-posts__title {
  display: block;
  font-family: var(--site-font-heading);
  font-size: var(--recent-title-size, 0.875rem);
  font-weight: var(--recent-title-weight, 600);
  line-height: var(--recent-title-line-height, 1.4);
  color: var(--site-text);
  text-decoration: none;
  margin-bottom: 0.25rem;
  transition: color 0.15s ease;
}
.el-recent-posts__title:hover {
  color: var(--site-primary);
}
.el-recent-posts__date {
  display: block;
  font-size: var(--recent-meta-size, 0.75rem);
  font-weight: var(--recent-meta-weight, 400);
  color: var(--recent-meta-color, var(--site-text-muted));
}

/* ── Pricing Card (standalone) ───────────────────────────────── */
/* Outer container: layout only. Per-plan card chrome (bg, padding, border,
   radius, accent bar, hover) lives on .el-pricing-card__plan so each plan
   is its own card. */
.el-pricing-card {
  display: flex;
  flex-direction: column;
}
/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-pricing-card__plan` (0,1,0) and zeros bg/padding/border-radius/shadow. */
.el.el--pricing-tier > .el-pricing-card__plan {
  background: var(--pricing-card-bg, var(--site-surface, transparent));
  backdrop-filter: var(--pricing-card-backdrop-filter, none);
  -webkit-backdrop-filter: var(--pricing-card-backdrop-filter, none);
  padding: var(--pricing-card-padding, var(--site-card-padding, 2.5rem 2rem));
  border-radius: var(--pricing-card-border-radius, var(--site-card-radius, var(--site-radius, 8px)));
  /* Resting elevation routed through the unified --site-card-elevation
     token so a tenant can re-tune lift across every card in one edit.
     The fallback layer MUST be a no-op transparent layer (0 0
     transparent) — NOT the literal 'none'. CSS rejects 'none' as one
     entry in a comma-separated shadow list, which would silently drop
     the entire declaration (see memory/box_shadow_none_layer_pitfall). */
  box-shadow:
    var(--pricing-card-highlight, 0 0 transparent),
    var(--pricing-card-shadow, var(--site-card-elevation, 0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04)));
}
.el-pricing-card__plan {
  position: relative;
  background: var(--pricing-card-bg, var(--site-surface, transparent));
  backdrop-filter: var(--pricing-card-backdrop-filter, none);
  -webkit-backdrop-filter: var(--pricing-card-backdrop-filter, none);
  border: var(--pricing-card-border-width, 1px) solid var(--pricing-card-border-color, var(--site-border));
  /* Per-side accent bars rendered via border-{side}-width / border-{side}-color
     (NOT pseudos) so each stripe inherits the card's border-radius cleanly —
     pseudos get their corner radius clamped to half their own thickness, which
     overshoots past the much-larger card radius. When --pricing-card-accent-bar-*
     is unset, vars fall back to the regular 1px border above. */
  border-top-width: var(--pricing-card-accent-bar-height, var(--pricing-card-border-width, 1px));
  border-top-color: var(--pricing-card-accent-bar-color, var(--pricing-card-border-color, var(--site-border)));
  border-right-width: var(--pricing-card-accent-bar-right-height, var(--pricing-card-border-width, 1px));
  border-right-color: var(--pricing-card-accent-bar-right-color, var(--pricing-card-border-color, var(--site-border)));
  border-bottom-width: var(--pricing-card-accent-bar-bottom-height, var(--pricing-card-border-width, 1px));
  border-bottom-color: var(--pricing-card-accent-bar-bottom-color, var(--pricing-card-border-color, var(--site-border)));
  border-left-width: var(--pricing-card-accent-bar-left-height, var(--pricing-card-border-width, 1px));
  border-left-color: var(--pricing-card-accent-bar-left-color, var(--pricing-card-border-color, var(--site-border)));
  border-radius: var(--pricing-card-border-radius, var(--site-card-radius, var(--site-radius, 8px)));
  padding: var(--pricing-card-padding, var(--site-card-padding, 2.5rem 2rem));
  /* Glass cards stack the inner highlight on top of the regular shadow.
     Both layer fallbacks MUST be '0 0 transparent' (NOT 'none') so the
     comma-joined declaration stays valid when either var is unset.
     Resting elevation falls through --site-card-elevation. */
  box-shadow:
    var(--pricing-card-highlight, 0 0 transparent),
    var(--pricing-card-shadow, var(--site-card-elevation, 0 1px 2px rgba(0,0,0,0.03), 0 4px 12px rgba(0,0,0,0.04)));
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
  transition: box-shadow 0.25s ease, transform 0.25s ease, background 0.25s ease;
}
[data-card-hover-shell]:hover .el-pricing-card__plan {
  box-shadow: 0 8px 24px rgba(0,0,0,0.08);
  transform: translateY(calc(var(--pricing-card-hover-lift, 0px) * -1));
  background: var(--pricing-card-hover-bg, var(--pricing-card-bg, var(--site-surface, transparent)));
}
.el-pricing-card__plan--highlighted {
  border-color: var(--site-primary);
  border-width: 2px;
  /* Re-apply per-side accents so the border-width / border-color shorthands
     above don't clobber them on the highlighted plan. */
  border-top-width: var(--pricing-card-accent-bar-height, 5px);
  border-top-color: var(--pricing-card-accent-bar-color, var(--site-accent, var(--site-primary)));
  border-right-width: var(--pricing-card-accent-bar-right-height, 2px);
  border-right-color: var(--pricing-card-accent-bar-right-color, var(--site-primary));
  border-bottom-width: var(--pricing-card-accent-bar-bottom-height, 2px);
  border-bottom-color: var(--pricing-card-accent-bar-bottom-color, var(--site-primary));
  border-left-width: var(--pricing-card-accent-bar-left-height, 2px);
  border-left-color: var(--pricing-card-accent-bar-left-color, var(--site-primary));
  box-shadow: 0 12px 40px rgba(0,0,0,0.1);
}
.el-pricing-card__plan--highlighted:hover {
  box-shadow: 0 16px 48px rgba(0,0,0,0.12);
}
.el-pricing-card__badge {
  position: absolute;
  top: -14px;
  left: 50%;
  transform: translateX(-50%);
  background: var(--site-primary);
  color: var(--site-primary-fg);
  font-size: 0.75rem;
  font-weight: 700;
  padding: 0.3125rem 1.25rem;
  border-radius: 999px;
  text-transform: uppercase;
  letter-spacing: 0.06em;
}
.el-pricing-card__heading {
  font-family: var(--site-font-heading);
  font-size: clamp(1.75rem, 4vw, 2.5rem);
  font-weight: 700;
  color: var(--pc-heading, var(--site-text));
  margin: 0 0 0.75rem;
  letter-spacing: -0.025em;
}
.el-pricing-card__grid {
  display: grid;
  grid-template-columns: repeat(var(--el-grid-cols, 3), minmax(0, 1fr));
  gap: 1.5rem;
  align-items: stretch;
}
@container site style(--site-bp: mobile) { .el-pricing-card__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 768px) { .el-pricing-card__grid { grid-template-columns: repeat(2, 1fr); } }
/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) { .el-pricing-card__grid { grid-template-columns: 1fr; } }
@media (max-width: 480px) { .el-pricing-card__grid { grid-template-columns: 1fr; } }
.el-pricing-card__plan-name {
  font-family: var(--site-font-heading);
  font-size: var(--pricing-card-title-size, 1.25rem);
  font-weight: var(--pricing-card-title-weight, 600);
  color: var(--pc-plan-name, var(--site-text));
  margin: 0 0 0.5rem;
}
.el-pricing-card__plan-description {
  font-size: var(--pricing-card-description-size, 0.9375rem);
  color: var(--site-text-muted);
  margin: 0 0 1.5rem;
  line-height: var(--pricing-card-description-line-height, 1.5);
}
.el-pricing-card__price-wrap {
  display: flex;
  align-items: baseline;
  justify-content: center;
  gap: 0.125rem;
  margin-bottom: 2rem;
}
.el-pricing-card__currency {
  font-size: 1.5rem;
  font-weight: 600;
  color: var(--site-text);
  color: var(--pc-price, var(--site-text));
  align-self: flex-start;
  margin-top: 0.5rem;
}
.el-pricing-card__price {
  font-family: var(--site-font-heading);
  font-size: 3.5rem;
  font-weight: 800;
  color: var(--site-text);
  color: var(--pc-price, var(--site-text));
}
.el-pricing-card__period {
  font-size: 0.9375rem;
  color: var(--site-text-muted);
  color: var(--pc-period, var(--site-text-muted));
}
.el-pricing-card__features {
  list-style: none;
  margin: 0 0 2rem;
  padding: 0;
  width: 100%;
  text-align: left;
  order: 2;
}
.el-pricing-card__feature {
  display: flex;
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--site-border);
  font-size: 0.9375rem;
  color: var(--site-text-secondary);
  color: var(--pc-feature-text, var(--site-text-secondary));
  align-items: center;
  gap: 0.625rem;
}
/* Rich-text feature labels render a wrapping <p> by default — kill its margin
   so the check icon stays vertically centered with the label baseline. */
.el-pricing-card__feature .el-rich-text,
.el-pricing-card__feature .el-rich-text > p { margin: 0; }
.el-pricing-card__feature:last-child {
  border-bottom: none;
}
.el-pricing-card__feature::before {
  content: '\2713';
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--site-primary), transparent 88%);
  background: color-mix(in srgb, var(--pc-feature-check, var(--site-primary)), transparent 88%);
  color: var(--pc-feature-check, var(--site-primary));
  font-weight: 700;
  flex-shrink: 0;
}
.el-pricing-card__feature--disabled {
  color: var(--site-text-muted);
  text-decoration: line-through;
  opacity: 0.6;
}
.el-pricing-card__feature--disabled::before {
  content: '\2717';
  background: var(--site-surface-alt);
  color: var(--site-text-muted);
}
.el-pricing-card__cta {
  width: 100%;
  margin-top: auto;
}
@container site style(--site-bp: mobile) {
  .el-pricing-card__plan--highlighted {
    transform: none;
  }
}
@media (max-width: 768px) {
  .el-pricing-card__plan--highlighted {
    transform: none;
  }
}

/* Stage 6A slot wrappers — the new pricing-tier element emits these around
   each slot's children. Styling inherits from the matching .el-pricing-card__*
   rule so the legacy and compound-widget markup look identical. Reuses the
   existing --pricing-card-* CSS var namespace (per team/testimonials
   precedent) to avoid churning ~40 CSS declarations. */
.el-pricing-card__name-wrap {
  margin: 0 0 0.5rem;
}
.el-pricing-card__name-wrap :where(h1, h2, h3, h4, h5, h6) {
  font-family: var(--site-font-heading);
  font-size: var(--pricing-card-title-size, 1.25rem);
  font-weight: var(--pricing-card-title-weight, 600);
  color: var(--pc-plan-name, var(--site-text));
  margin: 0;
}
.el-pricing-card__price-slot {
  font-family: var(--site-font-heading);
  font-size: 3.5rem;
  font-weight: 800;
  color: var(--pc-price, var(--site-text));
  line-height: 1;
}
/* Rich-text inside the price slot must inherit slot typography — `.el-rich-text`
   declares its own 0.9375rem font-size which would otherwise shrink the price
   to body copy. */
.el-pricing-card__price-slot .el-rich-text,
.el-pricing-card__price-slot .el-rich-text > p {
  font-family: inherit;
  font-size: inherit;
  font-weight: inherit;
  line-height: inherit;
  color: inherit;
}
.el-pricing-card__period-slot {
  font-size: 0.9375rem;
  color: var(--pc-period, var(--site-text-muted));
  margin-left: 0.25rem;
}
.el-pricing-card__period-slot .el-rich-text,
.el-pricing-card__period-slot .el-rich-text > p {
  font-size: inherit;
  color: inherit;
}
.el-pricing-card__cta-wrap {
  width: 100%;
  margin-top: auto;
  display: flex;
  justify-content: stretch;
  order: 4;
}
.el-pricing-card__card-extra {
  order: 3;
  width: 100%;
  margin: -1rem 0 1.5rem;
  text-align: left;
}
.el-pricing-card__card-extra > .el {
  display: flex;
  align-items: center;
  gap: 0.625rem;
  padding: 0.625rem 0;
  border-bottom: 1px solid var(--site-border);
  color: var(--pc-feature-text, var(--site-text-secondary));
  font-size: 0.9375rem;
}
.el-pricing-card__card-extra > .el::before {
  content: '\2713';
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 20px;
  height: 20px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--pc-feature-check, var(--site-primary)), transparent 88%);
  color: var(--pc-feature-check, var(--site-primary));
  font-weight: 700;
  flex-shrink: 0;
}
.el-pricing-card__card-extra > .el:last-child {
  border-bottom: none;
}
.el-pricing-card__card-extra .el-rich-text,
.el-pricing-card__card-extra .el-rich-text > p {
  margin: 0;
  color: inherit;
}
/* CTA fills the card width — pricing CTAs read as primary actions, not
   compact text links. Authors can still override per-element via the button
   inspector. */
.el-pricing-card__cta-wrap > .el { width: 100%; }
.el-pricing-card__cta-wrap .el-button,
.el-pricing-card__cta-wrap a.cta-btn,
.el-pricing-card__cta-wrap button.cta-btn {
  width: 100%;
  padding-block: 0.875rem;
  padding-inline: 1.5rem;
}

/* ── CTA Buttons ─────────────────────────────────────────────── */
.cta-btn,
.cta-btn:hover,
.cta-btn:focus,
.cta-btn:active,
a.cta-btn {
  text-decoration: none !important;
}
.cta-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  font-family: var(--site-font-body);
  font-size: 0.9375rem;
  font-weight: 600;
  letter-spacing: -0.005em;
  padding: 0.6875rem 1.5rem;
  min-height: 42px;
  border-radius: var(--el-btn-radius, var(--site-btn-radius, var(--site-radius-lg, 8px)));
  border: 2px solid transparent;
  cursor: pointer;
  line-height: 1.2;
  transition: background-color 0.2s cubic-bezier(0.2, 0, 0, 1), color 0.2s cubic-bezier(0.2, 0, 0, 1), border-color 0.2s cubic-bezier(0.2, 0, 0, 1), transform 0.2s cubic-bezier(0.2, 0, 0, 1), box-shadow 0.2s cubic-bezier(0.2, 0, 0, 1), opacity 0.2s cubic-bezier(0.2, 0, 0, 1), filter 0.2s cubic-bezier(0.2, 0, 0, 1);
  white-space: nowrap;
}
/* ── Payment Button ──────────────────────────────────────────── */
.el-payment-btn { display: inline-flex; flex-direction: column; align-items: center; gap: 2px; }
.el-payment-btn__label { display: block; font-weight: 600; }
.el-payment-btn__price { display: block; font-size: 0.8em; opacity: 0.85; }
.el-payment-btn__price--unconfigured { font-style: italic; opacity: 0.55; font-size: 0.75em; }
.el-payment-btn:disabled { opacity: 0.6; cursor: not-allowed; }

/* Button style token: --site-button-style controls global button shape */
/* 'rounded' (default) uses --site-radius; 'pill' forces full-round; 'square' removes rounding */

.cta-btn:focus-visible {
  outline: 2px solid var(--site-primary);
  outline-offset: 2px;
}

/* Primary — solid fill */
.cta-btn--primary {
  background: var(--site-btn-primary-bg, var(--site-primary));
  color: var(--site-btn-primary-text, var(--site-primary-fg));
  border-color: var(--site-btn-primary-bg, var(--site-primary));
}
/* ── Per-element hover overrides (set via builder style props as CSS vars) ── */
/* When --btn-hover-bg / --btn-hover-color / --btn-hover-border are set on an
   ancestor element, they override the default hover behavior for all cta-btn
   children. This enables builder-editable hover effects on every CTA. */
.cta-btn:hover {
  background: var(--btn-hover-bg, revert-layer);
  color: var(--btn-hover-color, revert-layer);
  border-color: var(--btn-hover-border, revert-layer);
}

.cta-btn--primary:hover {
  background: var(--btn-hover-bg, var(--site-btn-primary-hover-bg, color-mix(in srgb, var(--site-btn-primary-bg, var(--site-primary)), #000 12%)));
  border-color: var(--btn-hover-border, var(--site-btn-primary-hover-bg, color-mix(in srgb, var(--site-btn-primary-bg, var(--site-primary)), #000 12%)));
  color: var(--btn-hover-color, var(--site-btn-primary-hover-text, var(--site-btn-primary-text, var(--site-primary-fg))));
  box-shadow: var(--site-shadow-md, 0 4px 16px rgba(0,0,0,0.08));
}
.cta-btn--primary:active {
  background: color-mix(in srgb, var(--site-btn-primary-bg, var(--site-primary)), #000 20%);
  border-color: color-mix(in srgb, var(--site-btn-primary-bg, var(--site-primary)), #000 20%);
  box-shadow: none;
  transform: translateY(1px);
}

/* Secondary — solid fill with secondary color */
.cta-btn--secondary {
  background: var(--site-btn-secondary-bg, var(--site-secondary));
  color: var(--site-btn-secondary-text, var(--site-secondary-fg));
  border-color: var(--site-btn-secondary-bg, var(--site-secondary));
}
.cta-btn--secondary:hover {
  background: var(--btn-hover-bg, var(--site-btn-secondary-hover-bg, color-mix(in srgb, var(--site-btn-secondary-bg, var(--site-secondary)), #000 12%)));
  border-color: var(--btn-hover-border, var(--site-btn-secondary-hover-bg, color-mix(in srgb, var(--site-btn-secondary-bg, var(--site-secondary)), #000 12%)));
  color: var(--btn-hover-color, var(--site-btn-secondary-hover-text, var(--site-btn-secondary-text, var(--site-secondary-fg))));
  box-shadow: 0 4px 12px color-mix(in srgb, var(--site-btn-secondary-bg, var(--site-secondary)), transparent 60%);
}
.cta-btn--secondary:active {
  background: color-mix(in srgb, var(--site-btn-secondary-bg, var(--site-secondary)), #000 20%);
  box-shadow: none;
  transform: translateY(1px);
}

/* Link — text-only, underlined */
.cta-btn--link {
  background: transparent;
  color: var(--site-btn-outline-text, var(--site-primary));
  border: none;
  padding: 0;
  text-decoration: underline;
  text-underline-offset: 3px;
  display: inline;
}
.cta-btn--link:hover {
  opacity: 0.8;
}

/* Outline — bordered */
.cta-btn--outline {
  background: transparent;
  color: var(--site-btn-outline-text, var(--site-primary));
  border-color: var(--site-btn-outline-border, var(--site-primary));
}
/* Dark-surface safety net: when outline CTAs are placed inside a section
   flagged as dark (via the renderer's `data-is-dark` / `--el-is-dark`
   contract — see SectionRenderer.tsx), force white fill/border so they stay
   visible. Manual override lives on the Section inspector field "Dark Section"
   (auto | dark | light). Specific modifiers above still win. */
.el-section[data-is-dark="1"] .cta-btn--outline,
[data-theme="dark"] .cta-btn--outline {
  background: var(--el-btn-bg, rgba(255,255,255,0.06));
  color: var(--el-btn-text, var(--site-bg, currentColor));
  border-color: var(--el-btn-border, rgba(255,255,255,0.85));
}
.el-section[data-is-dark="1"] .cta-btn--outline:hover,
[data-theme="dark"] .cta-btn--outline:hover {
  background: var(--el-btn-hover-bg, rgba(255,255,255,0.16));
  border-color: var(--el-btn-hover-border, var(--el-btn-border, var(--site-bg, currentColor)));
  color: var(--el-btn-hover-text, var(--el-btn-text, var(--site-bg, currentColor)));
}
.cta-btn--outline:hover {
  background: var(--btn-hover-bg, var(--site-btn-outline-hover-bg, var(--site-btn-outline-border, var(--site-primary))));
  color: var(--btn-hover-color, var(--site-btn-outline-hover-text, var(--site-primary-fg)));
  border-color: var(--btn-hover-border, var(--site-btn-outline-border, var(--site-primary)));
  box-shadow: var(--site-shadow-md, 0 4px 16px rgba(0,0,0,0.08));
}
.cta-btn--outline:active {
  background: color-mix(in srgb, var(--site-btn-outline-border, var(--site-primary)), #000 12%);
  border-color: color-mix(in srgb, var(--site-btn-outline-border, var(--site-primary)), #000 12%);
  transform: translateY(1px);
}

/* Ghost — minimal */
.cta-btn--ghost {
  background: var(--el-btn-bg, transparent);
  color: var(--site-btn-outline-text, var(--site-primary));
  border-color: var(--el-btn-border, transparent);
}
.cta-btn--ghost:hover {
  background: var(--el-btn-hover-bg, color-mix(in srgb, currentColor 8%, transparent));
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-thickness: 2px;
}
.cta-btn--ghost:active {
  opacity: 0.8;
}

/* White variant — for dark backgrounds (hero, CTA band).
   Defaults to the site fg token so the "white" name still respects per-tenant theming. */
.cta-btn--white {
  background: var(--site-fg, transparent);
  color: var(--site-btn-primary-bg, var(--site-primary));
  border-color: var(--site-fg, transparent);
}
.cta-btn--white:hover {
  background: rgba(255, 255, 255, 0.9);
  box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
}

/* White outline — for dark backgrounds */
.cta-btn--white-outline {
  background: transparent;
  color: var(--site-fg, currentColor);
  border-color: rgba(255, 255, 255, 0.75);
}
.cta-btn--white-outline:hover {
  background: rgba(255, 255, 255, 0.15);
  border-color: var(--site-fg, currentColor);
}

/* Size variants — compound selectors so they out-rank the base
   `.cta-btn { padding: 12px 24px }` and `.site-btn { padding: 12px 24px }`
   rules regardless of CSS load order. Without the compound, lg's padding
   silently lost the cascade and lg buttons rendered with md gutters. */
.cta-btn.cta-btn--sm,
.site-btn.cta-btn--sm {
  font-size: 0.8125rem;
  padding: 0.5625rem 1.25rem;
}
.cta-btn.cta-btn--lg,
.site-btn.cta-btn--lg {
  font-size: 1.0625rem;
  padding: 1rem 2.75rem;
}

/* Button style overrides — set by data-button-style attribute on site wrapper */
/* Templates/themes set this via themeTokens.buttonStyle */
/* --site-btn-radius takes priority; data-button-style is the shape preset fallback */
[data-button-style="pill"] .cta-btn { border-radius: var(--el-btn-radius, var(--site-btn-radius, 9999px)); }
[data-button-style="square"] .cta-btn { border-radius: var(--el-btn-radius, var(--site-btn-radius, 0)); }
[data-button-style="rounded"] .cta-btn { border-radius: var(--el-btn-radius, var(--site-btn-radius, var(--site-radius, 8px))); }

/* Full-width */
.cta-btn--block {
  width: 100%;
}

@container site style(--site-bp: mobile) {
  .cta-btn {
    padding: 0.75rem 1.5rem;
    font-size: 0.875rem;
  }
  .cta-btn.cta-btn--lg,
  .site-btn.cta-btn--lg {
    padding: 0.875rem 2rem;
    font-size: 1rem;
  }
}
@media (max-width: 768px) {
  .cta-btn {
    padding: 0.75rem 1.5rem;
    font-size: 0.875rem;
  }
  .cta-btn.cta-btn--lg,
  .site-btn.cta-btn--lg {
    padding: 0.875rem 2rem;
    font-size: 1rem;
  }
}


/* ============================================================
   Blueprint Variants
   ============================================================ */

/* ── Hero variants ───────────────────────────────────────── */

.el-hero--split-image-right,
.el-hero--split-image-left {
  display: grid;
  grid-template-columns: 1fr 1fr;
  min-height: 500px;
  align-items: center;
}
.el-hero--split-image-right .el-hero__content,
.el-hero--split-image-left .el-hero__content {
  text-align: left;
  padding-block: var(--site-space-lg, 4rem);
}
.el-hero--split-image-right .el-hero__actions,
.el-hero--split-image-left .el-hero__actions {
  justify-content: flex-start;
}
.el-hero--split-image-left {
  direction: rtl;
}
.el-hero--split-image-left > * {
  direction: ltr;
}
@container site style(--site-bp: mobile) {
  .el-hero--split-image-right,
  .el-hero--split-image-left {
    grid-template-columns: 1fr;
  }
  .el-hero--split-image-left {
    direction: ltr;
  }
}
@media (max-width: 768px) {
  .el-hero--split-image-right,
  .el-hero--split-image-left {
    grid-template-columns: 1fr;
  }
  .el-hero--split-image-left {
    direction: ltr;
  }
}

.el-hero--minimal {
  min-height: auto;
  --el-padding-default: 2rem 1.5rem;
  background: var(--el-bg, transparent);
}
/* Overlay scrim is painted by the shared .el-hero::before rule
   (er-layout.css). Minimal hero opts out — no scrim, no fallback gradient. */
.el-hero--minimal {
  background-image: none;
}
.el-hero--minimal::before {
  display: none;
}
.el-hero--minimal .el-hero__heading {
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  color: var(--site-text);
}
.el-hero--minimal .el-hero__subheading {
  color: var(--site-text-muted);
}

.el-hero--video-ambient {
  /* True black is correct here — video poster scrim needs solid black behind translucent content */
  background: var(--el-bg, var(--el-bg-default, transparent));
}
/* Video-ambient default scrim — feeds defaults INTO --el-overlay-bg /
   --el-overlay-opacity so the shared .el-hero::before rule paints them.
   When the inspector sets overlayColor / overlayOpacity, ElementWrapper
   re-defines those vars on .el-hero inline-style, overriding these. */
.el-hero--video-ambient {
  --el-overlay-bg: rgba(0, 0, 0, 0.55);
  --el-overlay-opacity: 1;
}

/* ── CTA Band variants ───────────────────────────────────── */

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

.el-cta-band--gradient {
  background: var(--el-bg, linear-gradient(135deg, var(--site-primary), var(--site-accent)));
  color: var(--site-primary-fg, currentColor);
}

/* ── Rating Display ──────────────────────────────────────────── */
.el-rating { --rating-star-color: var(--el-star-fill, var(--site-accent)); --rating-grid-columns: 2; width: 100%; }
.el-rating__header { margin-bottom: 24px; }
.el-rating__heading { font-size: 24px; font-weight: 700; margin: 0 0 12px; }
.el-rating__average { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.el-rating__average-value { font-size: 32px; font-weight: 800; line-height: 1; }
.el-rating__average-count { font-size: 14px; color: var(--site-text-muted); }
.el-rating__stars { display: inline-flex; align-items: center; gap: 2px; }
.el-rating__star { flex-shrink: 0; }
.el-rating__star--filled { color: var(--rating-star-color, var(--site-text)); }
.el-rating__star--empty { color: var(--site-border); }
.el-rating__list { display: flex; flex-direction: column; gap: 20px; }
.el-rating__grid { display: grid; grid-template-columns: repeat(var(--rating-grid-columns), 1fr); gap: 20px; }
/* was @media (max-width: 640px); bucketed to mobile */
@container site style(--site-bp: mobile) { .el-rating__grid { grid-template-columns: 1fr; } }
@media (max-width: 640px) { .el-rating__grid { grid-template-columns: 1fr; } }
.el-rating__review { padding: 16px 0; border-bottom: 1px solid var(--site-border); }
.el-rating__review:last-child { border-bottom: none; }
.el-rating__author { display: block; font-weight: 600; font-size: 14px; margin-top: 8px; }
.el-rating__date { display: block; font-size: 12px; color: var(--site-text-muted); margin-top: 2px; }
.el-rating__text { font-size: 14px; line-height: 1.6; color: var(--site-text); margin: 8px 0 0; }
.el-rating__empty { font-size: 14px; color: var(--site-text-muted); text-align: center; padding: 32px 0; }
.el-rating--cards .el-rating__review {
  background: var(--site-bg, transparent); border: 1px solid var(--site-border); border-radius: 12px;
  padding: 20px; box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.el-rating--minimal .el-rating__review { padding: 12px 0; border-bottom: none; }
.el-rating--minimal .el-rating__heading { font-size: 18px; }
.el-rating__carousel,
.el-rating--carousel .el-rating__list,
.el-rating--carousel .el-rating__grid {
  display: flex; flex-direction: row; overflow-x: auto; overflow-y: clip; scroll-snap-type: x proximity; scroll-behavior: smooth;
  overflow-clip-margin-top: var(--site-carousel-shadow-bleed-block, 24px); overflow-clip-margin-bottom: var(--site-carousel-shadow-bleed-block, 24px);
  overflow-clip-margin-left: var(--site-carousel-shadow-bleed-inline, 16px); overflow-clip-margin-right: var(--site-carousel-shadow-bleed-inline, 16px);
  -webkit-overflow-scrolling: touch; gap: 16px;
  padding-block: var(--site-carousel-slide-bleed-block, 8px);
  padding-inline: var(--site-carousel-slide-bleed-inline, 16px);
  scroll-padding-inline: var(--site-carousel-slide-bleed-inline, 16px);
}
.el-rating__carousel .el-rating__review,
.el-rating--carousel .el-rating__review { flex: 0 0 300px; scroll-snap-align: start; border-bottom: none; }

/* ── Logo Slider — horizontal logo rail with shared carousel bleed controls ──
   Width chrome (width / max-width / margin-inline / padding-inline) lives on
   the Site-Container Contract (`.el-site-container`) which this same node
   carries — redeclaring it here would silently override the author's chosen
   width preset (default / narrow / wide / full). Only set properties the
   contract does NOT own. */
.el-logo-slider {
  min-width: 0;
  overflow-x: auto;
  overflow-y: clip;
  overflow-clip-margin-top: var(--site-carousel-shadow-bleed-block, 24px); overflow-clip-margin-bottom: var(--site-carousel-shadow-bleed-block, 24px);
  overflow-clip-margin-left: var(--site-carousel-shadow-bleed-inline, var(--site-card-gap, 24px)); overflow-clip-margin-right: var(--site-carousel-shadow-bleed-inline, var(--site-card-gap, 24px));
  -webkit-overflow-scrolling: touch;
}
.el-logo-slider__item,
.el-logo-slider__link,
.el-logo-slider__media {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 0;
}
.el-logo-slider__item {
  flex: 0 0 auto;
  padding: var(--logo-slider-item-padding, 0.875rem 1.25rem);
  border-radius: var(--logo-slider-radius, var(--site-card-radius, 8px));
  background: var(--logo-slider-card-bg, transparent);
  box-shadow: var(--el-card-shadow, none);
}
.el-logo-slider--boxed .el-logo-slider__item {
  background: var(--logo-slider-card-bg, var(--site-card-bg, var(--site-surface, transparent)));
  border: 1px solid var(--site-card-border, var(--site-border, transparent));
}
.el-logo-slider__link {
  color: inherit;
  text-decoration: none;
}
.el-logo-slider__media img,
.el-logo-slider__media picture,
.el-logo-slider__media svg {
  display: block;
  max-width: 160px;
  max-height: 64px;
  width: auto;
  height: auto;
  object-fit: contain;
}
.el-logo-slider--grayscale .el-logo-slider__media {
  filter: grayscale(1);
  opacity: 0.78;
  transition: filter 0.2s ease, opacity 0.2s ease;
}
.el-logo-slider--grayscale .el-logo-slider__item:hover .el-logo-slider__media,
.el-logo-slider--grayscale .el-logo-slider__link:focus-visible .el-logo-slider__media {
  filter: grayscale(0);
  opacity: 1;
}
/* ── Review Card (per-item child of rating-display) ──────────────
 * Stage 7B of the compound-widget children migration. Each `.el-review-card`
 * is one child of a rating-display compound widget. All chrome flows from
 * `--review-card-*` CSS vars projected by `RatingDisplayRenderer`.
 *
 * Card hover follows the SKILL_REFERENCE Card Hover Contract — `--review-card-
 * hover-*` vars driven by `extractCardHoverCssVars(..., 'review-card')`.
 * Defaults derive from `--site-accent` so the cards still react on themes
 * that haven't customised hover.
 */
/* High-specificity bridge — same fix as feature-card / testimonial-card. */
.el.el--review-card > .el-review-card {
  background: var(--review-card-bg, var(--site-surface, transparent));
  padding: var(--review-card-padding, 20px);
  border-radius: var(--review-card-radius, 8px);
  box-shadow: var(--review-card-shadow, none);
}
.el-review-card {
  display: flex;
  flex-direction: column;
  gap: 12px;
  background: var(--review-card-bg, var(--site-surface, transparent));
  color: var(--review-card-text, inherit);
  border: 1px solid var(--review-card-border-color, transparent);
  border-radius: var(--review-card-radius, 8px);
  --el-padding-default: var(--review-card-padding, 20px);
  box-shadow: var(--review-card-shadow, none);
  transition: transform 0.18s ease, background 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease, color 0.18s ease;
}
[data-card-hover-shell]:hover .el-review-card {
  background: var(--review-card-hover-bg, var(--review-card-bg, var(--site-surface, transparent)));
  color: var(--review-card-hover-color, var(--review-card-text, inherit));
  border-color: var(--review-card-hover-border-color, var(--review-card-border-color, transparent));
  transform: translateY(calc(var(--review-card-hover-lift, 0px) * -1));
  box-shadow: var(--review-card-hover-shadow, var(--review-card-shadow, none));
}
.el-review-card__header {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.el-review-card__rating-wrap {
  display: inline-flex;
  align-items: center;
}
.el-review-card__author-wrap {
  font-weight: 600;
}
.el-review-card__text-wrap {
  font-size: 14px;
  line-height: 1.6;
}
.el-review-card__date-wrap {
  font-size: 12px;
  color: var(--site-text-muted, inherit);
  opacity: 0.75;
}
.el-review-card__extra {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Variant cascades — `--review-card-variant` is set on the section root by
 * the thin shell so child cards can adapt without reading parent classes. */
.el-compound-section[style*="--review-card-variant: minimal"] .el-review-card {
  border: none;
  background: transparent;
  padding: 12px 0;
  box-shadow: none;
}
.el-compound-section[style*="--review-card-variant: minimal"] .el-review-card:hover {
  transform: none;
  background: transparent;
  box-shadow: none;
}

/* ── Data Table ──────────────────────────────────────────────── */
.el-table {
  width: 100%;
  max-width: min(100%, 100%);
  border-radius: var(--tbl-border-radius, 0px);
  border: 1px solid var(--tbl-border-color, var(--site-border, transparent));
  overflow: hidden;
  background: var(--el-bg, transparent);
  color: var(--el-color, inherit);
}
.el-table__scroll-wrapper {
  width: 100%;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
}
.el-table__table {
  width: 100%;
  border-collapse: collapse;
  font-size: 14px;
}
.el-table__caption {
  caption-side: top;
  text-align: left;
  padding: 12px 16px;
  font-size: var(--tbl-caption-font-size, 13px);
  font-weight: var(--tbl-caption-font-weight, 600);
  color: var(--tbl-caption-color, var(--site-text-muted, currentColor));
}
.el-table__thead {
  background: var(--tbl-header-bg, var(--site-surface-alt, transparent));
}
.el-table__th {
  padding: var(--tbl-row-padding-y, 12px) var(--tbl-row-padding-x, 16px);
  text-align: left;
  color: var(--tbl-header-color, var(--site-text-primary, inherit));
  font-size: var(--tbl-header-font-size, 13px);
  font-weight: var(--tbl-header-font-weight, 700);
  text-transform: var(--tbl-header-text-transform, uppercase);
  letter-spacing: var(--tbl-header-letter-spacing, 0.05em);
  border-bottom: var(--tbl-separator-width, 1px) solid var(--tbl-separator-color, var(--site-border, transparent));
}
.el-table__td {
  padding: var(--tbl-row-padding-y, 12px) var(--tbl-row-padding-x, 16px);
  border-bottom: var(--tbl-separator-width, 1px) solid var(--tbl-separator-color, var(--site-border, transparent));
  color: inherit;
}
.el-table__tbody tr:last-child .el-table__td { border-bottom: none; }
.el-table--striped .el-table__tbody tr:nth-child(even) .el-table__td {
  background: var(--tbl-stripe-bg, var(--site-surface-alt, transparent));
}
.el-table--no-stripe .el-table__tbody tr:nth-child(even) .el-table__td {
  background: transparent;
}
.el-table--bordered .el-table__th,
.el-table--bordered .el-table__td {
  border: var(--tbl-separator-width, 1px) solid var(--tbl-separator-color, var(--site-border, transparent));
}
.el-table__tbody tr:hover .el-table__td {
  background: var(--tbl-hover-bg, var(--site-surface, transparent));
}
.el-table__row--empty .el-table__td {
  text-align: center;
  color: var(--site-text-muted, currentColor);
  font-style: italic;
}
/* was @media (max-width: 640px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-table__th,
  .el-table__td {
    padding: calc(var(--tbl-row-padding-y, 12px) * 0.75) calc(var(--tbl-row-padding-x, 16px) * 0.75);
  }
}
@media (max-width: 640px) {
  .el-table__th,
  .el-table__td {
    padding: calc(var(--tbl-row-padding-y, 12px) * 0.75) calc(var(--tbl-row-padding-x, 16px) * 0.75);
  }
}

/* ── Comparison Table ────────────────────────────────────────── */
.el-comparison {
  /* ── Design token API ──────────────────────────────────────────
     Set these via element inspector props (renderer wires them) or
     site theme tokens. All premium visual features are off by default
     and unlocked by the "premium" variant or per-prop overrides.
     ────────────────────────────────────────────────────────────── */
  --ct-radius: 20px;         /* outer container border-radius */
  --ct-inner-radius: 0px;    /* top corners of highlighted column */
  --ct-ring-opacity: 0;      /* 0–1: conic gradient ring border */
  --ct-ambient-opacity: 0;   /* 0–1: radial glow above highlighted column */
  --ct-badge-display: none;  /* none | inline-block: floating column badge */

  width: 100%;
  max-width: var(--el-comparison-max-width, 100%);
  margin: 0 auto;
  position: relative;
  border-radius: var(--ct-radius);
  overflow: hidden;
  background: var(--el-bg, var(--ct-bg, transparent));
  border: 1px solid var(--ct-border, transparent);
  backdrop-filter: var(--ct-backdrop-filter, none);
  -webkit-backdrop-filter: var(--ct-backdrop-filter, none);
  /* Shadow is opt-in. Previously the base rule baked a 0 24px 60px shadow
     into every comparison-table — even with glass off and a transparent
     bg, the shadow read as a visible "card", and adjusting the radius
     reshaped the shadow which felt like the radius was changing the bg.
     Now: glass-on flips --ct-shadow to the recipe via the renderer; glass-
     off leaves it at `none` so a transparent table really IS invisible. */
  box-shadow: var(--ct-shadow, none);
  font-family: var(--ct-body-font-family, var(--site-font-body, inherit));
}

/* Conic gradient ring — accent-derived, hidden when --ct-ring-opacity is 0.
   Uses color-mix() to build a multi-stop fade from the accent color so
   any single accent value produces a coherent ring without manual tuning. */
.el-comparison::before {
  content: '';
  position: absolute;
  inset: -1px;
  border-radius: calc(var(--ct-radius) + 1px);
  background: conic-gradient(
    from 200deg at 26% 48%,
    var(--ct-ring-color, var(--ct-highlight, var(--site-accent, transparent))),
    color-mix(in srgb, var(--ct-ring-color, var(--ct-highlight, var(--site-accent, transparent))) 20%, transparent),
    color-mix(in srgb, var(--ct-ring-color, var(--ct-highlight, var(--site-accent, transparent))) 50%, transparent),
    color-mix(in srgb, var(--ct-ring-color, var(--ct-highlight, var(--site-accent, transparent))) 10%, transparent),
    var(--ct-ring-color, var(--ct-highlight, var(--site-accent, transparent)))
  );
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
          mask-composite: exclude;
  pointer-events: none;
  opacity: var(--ct-ring-opacity, 0);
  z-index: 0;
}

.el-comparison__heading {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: -0.01em;
  margin: 0;
  padding: 24px 28px 4px;
  color: var(--ct-heading, inherit);
  text-align: center;
}
.el-comparison__scroll-wrapper {
  box-sizing: border-box;
  width: 100%;
  overflow-x: auto;
  overflow-y: visible;
  -webkit-overflow-scrolling: touch;
  padding:
    var(--ct-scroll-pad-top, 12px)
    var(--ct-scroll-pad-inline, clamp(1rem, 3vw, 2rem))
    0;
  max-width: 100%;
  background: transparent !important;
  border-color: transparent !important;
  box-shadow: none !important;
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
  /* Custom horizontal scrollbar — themed via site tokens with sensible
     fallbacks so it reads as part of the surface rather than the OS chrome. */
  scrollbar-width: thin;
  scrollbar-color: var(--site-scrollbar-thumb, color-mix(in srgb, var(--site-accent, currentColor) 55%, transparent)) transparent;
}
.el-comparison__scroll-wrapper::-webkit-scrollbar {
  height: 10px;
}
.el-comparison__scroll-wrapper::-webkit-scrollbar-track {
  background: transparent;
}
.el-comparison__scroll-wrapper::-webkit-scrollbar-thumb {
  background: var(--site-scrollbar-thumb, color-mix(in srgb, var(--site-accent, transparent) 45%, transparent));
  border-radius: 999px;
  border: 2px solid transparent;
  background-clip: padding-box;
}
.el-comparison__scroll-wrapper::-webkit-scrollbar-thumb:hover {
  background: var(--site-scrollbar-thumb-hover, color-mix(in srgb, var(--site-accent, transparent) 75%, transparent));
  background-clip: padding-box;
}
.el-comparison__table { width: 100%; min-width: max-content; border-collapse: collapse; font-size: var(--ct-cell-font-size, 14px); table-layout: auto; }
@container site style(--site-bp: mobile) {
  /* Mobile card-stack: a horizontal-scroll table on a 390px viewport always
     orphans the right-most column under the thumb, so on narrow viewports
     the table reflows to one card per row. THEAD is hidden — each TD shows
     its column name via the `data-col-label` attribute the renderer stamps
     on every cell. Scroll wrapper drops its overflow so cards can flow. */
  .el-comparison__scroll-wrapper { overflow-x: clip; max-width: 100%; }
  .el-comparison__table,
  .el-comparison__table thead,
  .el-comparison__table tbody,
  .el-comparison__table tr,
  .el-comparison__table th,
  .el-comparison__table td { display: block; max-width: 100%; }
  .el-comparison__table { width: 100% !important; min-width: 0 !important; }
  .el-comparison__table thead { position: absolute; left: -9999px; top: -9999px; }
  .el-comparison__table tr {
    background: var(--ct-card-bg, var(--site-glass-bg, transparent));
    border: 1px solid var(--ct-divider, var(--ct-border, transparent));
    border-radius: var(--site-radius-lg, 16px);
    padding: 16px 18px;
    margin: 0 0 12px;
  }
  .el-comparison__table td {
    padding: 10px 0 !important;
    border: 0 !important;
    text-align: left;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    border-bottom: 1px solid var(--ct-divider, transparent) !important;
  }
  .el-comparison__table td:last-child { border-bottom: 0 !important; }
  .el-comparison__table td:first-child {
    padding: 0 0 12px !important;
    border-bottom: 1px solid var(--ct-divider, transparent) !important;
    margin: 0 0 8px !important;
    font-weight: 700;
    font-size: 16px;
    color: var(--ct-feature, currentColor);
  }
  .el-comparison__table td[data-col-label]::before {
    content: attr(data-col-label);
    color: var(--ct-th-color, var(--site-text-muted, currentColor));
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    flex: 0 0 auto;
  }
  .el-comparison__table td .el-comparison__text-value,
  .el-comparison__table td > svg { flex: 0 0 auto; text-align: right; }
  /* Striping doesn't apply when rows are cards. */
  .el-comparison--striped .el-comparison__table tbody tr:nth-child(even) td:not(.el-comparison__col--highlighted) {
    background: transparent;
  }
}
@media (max-width: 768px) {
  /* Mobile card-stack: a horizontal-scroll table on a 390px viewport always
     orphans the right-most column under the thumb, so on narrow viewports
     the table reflows to one card per row. THEAD is hidden — each TD shows
     its column name via the `data-col-label` attribute the renderer stamps
     on every cell. Scroll wrapper drops its overflow so cards can flow. */
  .el-comparison__scroll-wrapper { overflow-x: clip; max-width: 100%; }
  .el-comparison__table,
  .el-comparison__table thead,
  .el-comparison__table tbody,
  .el-comparison__table tr,
  .el-comparison__table th,
  .el-comparison__table td { display: block; max-width: 100%; }
  .el-comparison__table { width: 100% !important; min-width: 0 !important; }
  .el-comparison__table thead { position: absolute; left: -9999px; top: -9999px; }
  .el-comparison__table tr {
    background: var(--ct-card-bg, var(--site-glass-bg, transparent));
    border: 1px solid var(--ct-divider, var(--ct-border, transparent));
    border-radius: var(--site-radius-lg, 16px);
    padding: 16px 18px;
    margin: 0 0 12px;
  }
  .el-comparison__table td {
    padding: 10px 0 !important;
    border: 0 !important;
    text-align: left;
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 16px;
    border-bottom: 1px solid var(--ct-divider, transparent) !important;
  }
  .el-comparison__table td:last-child { border-bottom: 0 !important; }
  .el-comparison__table td:first-child {
    padding: 0 0 12px !important;
    border-bottom: 1px solid var(--ct-divider, transparent) !important;
    margin: 0 0 8px !important;
    font-weight: 700;
    font-size: 16px;
    color: var(--ct-feature, currentColor);
  }
  .el-comparison__table td[data-col-label]::before {
    content: attr(data-col-label);
    color: var(--ct-th-color, var(--site-text-muted, currentColor));
    font-size: 12px;
    font-weight: 600;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    flex: 0 0 auto;
  }
  .el-comparison__table td .el-comparison__text-value,
  .el-comparison__table td > svg { flex: 0 0 auto; text-align: right; }
  /* Striping doesn't apply when rows are cards. */
  .el-comparison--striped .el-comparison__table tbody tr:nth-child(even) td:not(.el-comparison__col--highlighted) {
    background: transparent;
  }
}
.el-comparison__table th {
  padding: var(--ct-cell-padding-y, 18px) var(--ct-cell-padding-x, 20px);
  text-align: center;
  font-family: var(--ct-header-font-family, var(--site-font-heading, var(--site-font-body, inherit)));
  font-weight: var(--ct-header-font-weight, var(--site-font-heading-weight, 700));
  font-size: var(--ct-header-size, clamp(16px, 1.1vw, 20px));
  letter-spacing: 0;
  line-height: 1.18;
  color: var(--ct-th-color, currentColor);
  background: var(--ct-th-bg, transparent);
  border-bottom: 1px solid var(--ct-divider, var(--ct-border, transparent));
  white-space: nowrap;
}
.el-comparison__table th:first-child { text-align: left; padding-left: 28px; }
.el-comparison__table th:last-child { padding-right: 28px; }
.el-comparison__header-label {
  display: inline-block;
  position: relative;
  max-width: 100%;
  white-space: normal;
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-comparison__table td {
  padding: var(--ct-cell-padding-y, 16px) var(--ct-cell-padding-x, 20px);
  text-align: center;
  font-family: var(--ct-body-font-family, var(--site-font-body, inherit));
  font-size: var(--ct-cell-font-size, 14px);
  color: var(--ct-cell-text, var(--ct-text, currentColor));
  border-bottom: 1px solid var(--ct-divider, var(--ct-border, transparent));
}
.el-comparison__table td:first-child {
  text-align: left;
  font-weight: var(--ct-feature-font-weight, 600);
  padding-left: 28px;
  color: var(--ct-feature, currentColor);
}
.el-comparison__table td:last-child { padding-right: 28px; }
.el-comparison__table tbody tr:last-child td { border-bottom: none; }
.el-comparison__table tbody tr:hover td:not(.el-comparison__col--highlighted) {
  background: var(--ct-hover-bg, transparent);
}
.el-comparison__col--highlighted {
  background: var(--ct-highlight-bg, transparent);
}
.el-comparison__col--highlighted th {
  color: var(--ct-highlight, var(--site-accent));
  background: var(--ct-highlight-th-bg, transparent);
}

/* Highlighted column header: inner radius + pseudo-element slots for badge
   (::before) and ambient glow (::after). Both are off by default. */
.el-comparison__table th.el-comparison__col--highlighted {
  position: relative;
  border-top-left-radius: var(--ct-inner-radius);
  border-top-right-radius: var(--ct-inner-radius);
}

/* Floating badge above highlighted column — text from data-ct-badge attr,
   shown by setting --ct-badge-display: inline-block or using .el-comparison--premium */
.el-comparison__table th.el-comparison__col--highlighted::before {
  display: var(--ct-badge-display, none);
  content: attr(data-ct-badge);
  position: absolute;
  top: -34px;
  left: 50%;
  transform: translateX(-50%);
  padding: 5px 17px;
  background: var(--ct-badge-bg, linear-gradient(135deg, color-mix(in srgb, var(--ct-highlight, var(--site-accent, transparent)) 70%, #67e8f9) 0%, var(--ct-highlight, var(--site-accent, transparent)) 55%, color-mix(in srgb, var(--ct-highlight, var(--site-accent, transparent)) 70%, #2dd4bf) 100%));
  color: var(--ct-badge-text-color, currentColor);
  font-size: 9.5px;
  font-weight: 800;
  letter-spacing: 0.20em;
  text-transform: uppercase;
  border-radius: 999px;
  box-shadow:
    0 0 0 1px color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 40%, transparent),
    0 4px 18px color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 52%, transparent),
    0 8px 32px color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 28%, transparent),
    inset 0 1px 0 rgba(255, 255, 255, 0.50);
  white-space: nowrap;
  text-shadow: none;
  pointer-events: none;
}

/* Ambient radial glow above the highlighted column — opacity-gated */
.el-comparison__table th.el-comparison__col--highlighted::after {
  content: none;
  display: none !important;
}
.el-comparison__table th.el-comparison__col--highlighted .el-comparison__header-label::after {
  content: '';
  position: absolute;
  bottom: -10px;
  left: 50%;
  transform: translateX(-50%);
  width: min(var(--ct-highlight-underline-width, 82px), calc(100% + 18px));
  height: 2px;
  border-radius: 999px;
  background: linear-gradient(
    90deg,
    transparent,
    color-mix(in srgb, var(--ct-highlight, var(--site-accent, transparent)) 72%, transparent),
    transparent
  );
  box-shadow: 0 0 16px color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 38%, transparent);
  pointer-events: none;
  opacity: var(--ct-ambient-opacity, 0);
  z-index: 0;
}

/* Check / cross icons sit centered in their data cell. */
.el-comparison__check,
.el-comparison__cross { display: block; margin: 0 auto; }
.el-comparison__check { color: var(--ct-check, var(--site-success)); }
/* Base cross icon — two diagonal bars composed into an X. The premium
   variant overrides background/box-shadow/colors below; this base block
   ensures the X actually has dimensions in every other variant
   (default / striped / bordered) where the bars would otherwise collapse
   to invisible 0×0 spans. */
.el-comparison__cross {
  position: relative;
  width: var(--ct-icon-size, 24px);
  height: var(--ct-icon-size, 24px);
  color: var(--ct-cross, var(--site-text-muted, currentColor));
}
.el-comparison__cross-bar {
  position: absolute;
  left: 50%;
  top: 50%;
  display: block;
  width: 70%;
  height: max(2px, calc(var(--ct-icon-size, 24px) * 0.10));
  border-radius: 999px;
  background: currentColor;
  transform-origin: center;
  pointer-events: none;
}
.el-comparison__cross-bar--one { transform: translate(-50%, -50%) rotate(45deg); }
.el-comparison__cross-bar--two { transform: translate(-50%, -50%) rotate(-45deg); }
.el-comparison__feature-label { display: block; font-weight: 600; line-height: 1.35; }
.el-comparison__feature-desc { display: block; font-weight: 400; font-size: 0.875em; opacity: 0.55; margin-top: 3px; line-height: 1.4; }
.el-comparison__text-value { display: inline-block; }
.el-comparison--striped .el-comparison__table tbody tr:nth-child(even) td:not(.el-comparison__col--highlighted) {
  background: var(--ct-stripe, transparent);
}
.el-comparison--bordered .el-comparison__table th,
.el-comparison--bordered .el-comparison__table td {
  border: 1px solid var(--ct-divider, var(--ct-border, transparent));
}
.el-comparison--empty {
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 120px;
  color: var(--site-text-muted, currentColor);
  font-size: 14px;
}

/* ── Premium variant — card-row design ─────────────────────────
   Each body row is a floating card. The highlighted column reads
   as a distinct accent card within each row. No cell borders —
   depth comes from layered backgrounds and spacing.
   All colors derive from --ct-highlight via color-mix() so any
   accent produces a coherent look with zero manual tuning.
   ────────────────────────────────────────────────────────────── */
.el-comparison--premium {
  --ct-radius: 32px;
  --ct-inner-radius: 22px;
  --ct-ring-opacity: 0.42;
  --ct-ambient-opacity: 1;
  --ct-badge-display: inline-block;
  --ct-scroll-pad-top: 0px;
  --ct-cell-font-size: 15px;
  overflow: visible;
}

/* Let badge + ambient glow escape the scroll clip. overflow-x:auto on
   the base scroll-wrapper also clips vertically (browser BFC behavior),
   cutting off the badge (top:-16px) and the glow (bottom:calc(100%+4px)).
   Premium uses a fixed column layout that never needs horizontal scroll
   on desktop; mobile already reflowed to block-display. */
.el-comparison--premium .el-comparison__scroll-wrapper {
  overflow: visible;
}

/* Separate border model + row gaps to create the card feel */
.el-comparison--premium .el-comparison__table {
  border-collapse: separate;
  border-spacing: 0;
}

/* Header cells: no bottom border — row gap provides the separation */
.el-comparison--premium .el-comparison__table th {
  border-bottom: none;
  padding-bottom: 24px;
  font-size: var(--ct-header-size, clamp(18px, 1.25vw, 22px)) !important;
  line-height: 1.18;
  font-weight: var(--ct-header-font-weight, var(--site-font-heading-weight, 800));
  letter-spacing: 0;
  overflow-wrap: break-word;
  word-break: break-word;
}

/* Highlighted column header — NO background. Any background on the th
   creates a visible accent edge at the bottom of the cell against the
   4px border-spacing gap, producing a bright unwanted divider line.
   Column identity comes from the badge above + accent td cells below. */
.el-comparison--premium .el-comparison__table th.el-comparison__col--highlighted {
  background: none;
  color: var(--ct-highlight, var(--site-accent, currentColor));
  font-size: var(--ct-header-size, clamp(18px, 1.25vw, 22px)) !important;
  font-weight: var(--ct-header-font-weight, var(--site-font-heading-weight, 800));
  letter-spacing: 0;
  text-shadow: none;
}

/* ── ROW CARDS ──────────────────────────────────────────────────
   Every td in a body row shares a card background. The first and
   last cells carry the row's corner radius. No borders anywhere —
   depth comes from the background alone.
   ────────────────────────────────────────────────────────────── */
.el-comparison--premium .el-comparison__table tbody td {
  position: relative;
  background: var(--ct-row-bg, transparent);
  border: none;
  border-top: 1px solid var(--ct-row-divider, transparent);
  box-shadow: none;
  transition: background 0.15s ease, border-color 0.15s ease;
  vertical-align: middle;
}
.el-comparison--premium .el-comparison__table tbody td > * {
  position: relative;
  z-index: 1;
}
.el-comparison--premium .el-comparison__table tbody td:first-child {
  border-radius: var(--ct-row-radius, 0) 0 0 var(--ct-row-radius, 0);
  box-shadow: none;
}
.el-comparison--premium .el-comparison__table tbody td:last-child {
  border-radius: 0 var(--ct-row-radius, 0) var(--ct-row-radius, 0) 0;
  box-shadow: none;
}
.el-comparison--premium .el-comparison__table tbody tr:hover td {
  background: var(--ct-row-hover-bg, transparent);
  border-top-color: rgba(255, 255, 255, 0.085);
}

/* Highlighted column cells — accent-tinted card within the row card.
   Scoped to td only — th must stay background-free to avoid the bright
   divider artifact where the accent edge meets the border-spacing gap. */
.el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted {
  background: var(--ct-row-bg, transparent) !important;
}
.el-comparison--premium .el-comparison__table tbody tr:hover td.el-comparison__col--highlighted {
  background: var(--ct-row-hover-bg, transparent) !important;
}
.el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted {
  font-weight: 700;
  font-size: 15px;
}
.el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted::before {
  content: '';
  position: absolute;
  inset: var(--ct-highlight-cell-inset-y, 6px) var(--ct-highlight-cell-inset-x, 18px);
  border-radius: var(--ct-highlight-cell-radius, 10px);
  background: var(--ct-highlight-cell-bg, color-mix(in srgb, var(--ct-highlight, var(--site-accent, transparent)) 16%, rgba(255, 255, 255, 0.025)));
  box-shadow:
    inset 0 1px 0 color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 18%, rgba(255, 255, 255, 0.06)),
    0 0 18px color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 8%, transparent);
  pointer-events: none;
  z-index: 0;
}
.el-comparison--premium .el-comparison__table tbody tr:hover td.el-comparison__col--highlighted::before {
  background: var(--ct-highlight-cell-hover-bg, color-mix(in srgb, var(--ct-highlight, var(--site-accent, transparent)) 22%, rgba(255, 255, 255, 0.04)));
}

/* Highlighted column text value pills */
.el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted .el-comparison__text-value {
  display: inline-flex;
  align-items: center;
  padding: 4px 14px;
  border-radius: 999px;
  background: color-mix(in srgb, var(--ct-highlight, var(--site-accent, transparent)) 14%, transparent);
  border: 1px solid color-mix(in srgb, var(--ct-highlight, var(--site-accent, transparent)) 28%, transparent);
  font-size: 13px;
  font-weight: 600;
}

/* Competitor text values — subtle, clearly secondary */
.el-comparison--premium .el-comparison__table td:not(.el-comparison__col--highlighted):not(:first-child) .el-comparison__text-value {
  color: rgba(226, 232, 240, 0.50);
  font-size: 13px;
}

/* ── Status badges — identical glass badge geometry, color differs ── */
.el-comparison--premium .el-comparison__check,
.el-comparison--premium .el-comparison__cross {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  box-sizing: border-box;
  flex: 0 0 var(--ct-icon-size, 38px);
  width: var(--ct-icon-size, 38px);
  height: var(--ct-icon-size, 38px);
  min-width: var(--ct-icon-size, 38px);
  min-height: var(--ct-icon-size, 38px);
  padding: 0;
  color: #ffffff !important;
  border-radius: 50%;
  margin: 0 auto;
  border: 1px solid transparent;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.24),
    0 3px 14px rgba(0, 0, 0, 0.18);
}

/* ── CHECK ICON — filled accent circle ──────────────────────── */
.el-comparison--premium .el-comparison__check {
  padding: calc(var(--ct-icon-size, 38px) * 0.23);
  background: linear-gradient(
    135deg,
    var(--ct-check, var(--ct-highlight, var(--site-accent, transparent))) 0%,
    color-mix(in srgb, var(--ct-check, var(--ct-highlight, var(--site-accent, transparent))) 75%, #10b981) 100%
  );
  border-color: color-mix(in srgb, var(--ct-check, var(--ct-highlight, var(--site-accent, transparent))) 46%, rgba(255, 255, 255, 0.16));
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.24),
    0 0 0 1px color-mix(in srgb, var(--ct-check, var(--ct-highlight, var(--site-accent, currentColor))) 35%, transparent),
    0 3px 14px color-mix(in srgb, var(--ct-check, var(--ct-highlight, var(--site-accent, currentColor))) 35%, transparent);
}

/* ── CROSS ICON — red filled circle matching the check icon size ── */
.el-comparison--premium .el-comparison__cross {
  position: relative;
  background:
    radial-gradient(circle at 35% 28%, rgba(255, 255, 255, 0.18), transparent 38%),
    linear-gradient(
      135deg,
      color-mix(in srgb, var(--ct-cross-bg-start, var(--site-danger, transparent)) 42%, rgba(12, 21, 37, 0.76)) 0%,
      color-mix(in srgb, var(--ct-cross-bg-start, var(--site-danger, transparent)) 26%, rgba(11, 18, 34, 0.90)) 100%
    );
  border-color: color-mix(in srgb, var(--ct-cross-bg-start, var(--site-danger, transparent)) 62%, rgba(255, 255, 255, 0.14));
  opacity: 1 !important;
  color: #ffffff !important;
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, 0.24),
    0 0 0 1px color-mix(in srgb, var(--ct-cross-bg-start, var(--site-danger, currentColor)) 42%, transparent),
    0 3px 14px color-mix(in srgb, var(--ct-cross-bg-start, var(--site-danger, currentColor)) 30%, transparent);
}
.el-comparison--premium .el-comparison__cross-bar {
  position: absolute;
  left: 50%;
  top: 50%;
  display: block;
  width: 60%;
  height: max(3px, calc(var(--ct-icon-size, 38px) * 0.10));
  border-radius: 999px;
  background: #ffffff;
  box-shadow: 0 0 8px rgba(255, 255, 255, 0.62);
  transform-origin: center;
  pointer-events: none;
  z-index: 2;
}
.el-comparison--premium .el-comparison__cross-bar--one {
  transform: translate(-50%, -50%) rotate(45deg);
}
.el-comparison--premium .el-comparison__cross-bar--two {
  transform: translate(-50%, -50%) rotate(-45deg);
}
.el-comparison--premium[data-element-id="evara-home-compare"] .el-comparison__cross,
[data-element-id="evara-home-compare"] .el-comparison--premium .el-comparison__cross,
[data-element-id="evara-home-compare"] .el-comparison__cross {
  width: var(--ct-icon-size, 38px) !important;
  height: var(--ct-icon-size, 38px) !important;
  min-width: var(--ct-icon-size, 38px) !important;
  min-height: var(--ct-icon-size, 38px) !important;
  opacity: 1 !important;
  color: #ffffff !important;
}
.el-comparison--premium .el-comparison__feature-label {
  font-size: var(--ct-feature-font-size, 15px);
  font-weight: var(--ct-feature-font-weight, 700);
}

/* Premium: mobile badge clearance */
@container site style(--site-bp: mobile) {
  .el-comparison--premium { --ct-scroll-pad-top: 0px; }
  .el-comparison--premium .el-comparison__table th.el-comparison__col--highlighted::before { top: -30px; font-size: 9px; padding: 4px 12px; }
  .el-comparison--premium .el-comparison__table { border-spacing: 0; }
  .el-comparison--premium .el-comparison__table tbody td:first-child,
  .el-comparison--premium .el-comparison__table tbody td:last-child { border-radius: 0; }
}
@media (max-width: 768px) {
  .el-comparison--premium { --ct-scroll-pad-top: 0px; }
  .el-comparison--premium .el-comparison__table th.el-comparison__col--highlighted::before { top: -30px; font-size: 9px; padding: 4px 12px; }
  .el-comparison--premium .el-comparison__table { border-spacing: 0; }
  .el-comparison--premium .el-comparison__table tbody td:first-child,
  .el-comparison--premium .el-comparison__table tbody td:last-child { border-radius: 0; }
}

/* ── Animated Counter ────────────────────────────────────────── */
.el-animated-counter { width: 100%; text-align: center; }
.el-animated-counter__heading { font-size: 24px; font-weight: 700; margin: 0 0 24px; color: var(--counter-heading-color, inherit); }
.el-animated-counter__grid { display: grid; gap: 24px; grid-template-columns: repeat(var(--el-grid-cols, 3), 1fr); }
@container site style(--site-bp: mobile) { .el-animated-counter__grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 768px) { .el-animated-counter__grid { grid-template-columns: repeat(2, 1fr); } }
/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) { .el-animated-counter__grid { grid-template-columns: 1fr; } }
@media (max-width: 480px) { .el-animated-counter__grid { grid-template-columns: 1fr; } }
.el-animated-counter__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  padding: var(--counter-item-padding, 0px);
  position: relative;
}
.el-animated-counter__item:not(:last-child)::after {
  content: '';
  position: absolute;
  right: 0;
  top: 20%;
  height: 60%;
  width: var(--counter-separator-width, 0px);
  background: var(--counter-separator-color, var(--site-border));
}
.el-animated-counter__value {
  font-size: var(--counter-value-font-size, 36px);
  font-weight: var(--counter-value-font-weight, 800);
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
  color: var(--counter-value-color, var(--site-accent));
}
.el-animated-counter__prefix,
.el-animated-counter__suffix {
  font-size: var(--counter-prefix-suffix-size, 0.6em);
}
.el-animated-counter__label {
  font-size: var(--counter-label-font-size, 14px);
  font-weight: var(--counter-label-font-weight, 500);
  text-transform: var(--counter-label-transform, uppercase);
  letter-spacing: var(--counter-label-letter-spacing, 0.08em);
  color: var(--counter-label-color, var(--site-text-muted));
}
.el-animated-counter__suffix { color: var(--counter-suffix-color, inherit); }
.el-animated-counter--cards .el-animated-counter__item {
  background: var(--site-bg, transparent); border: 1px solid var(--site-border); border-radius: var(--el-animated-counter-radius, 12px); padding: 24px 16px;
  box-shadow: 0 1px 3px rgba(0,0,0,0.06);
}
.el-animated-counter--minimal .el-animated-counter__value { font-size: 28px; font-weight: 700; }
.el-animated-counter--minimal .el-animated-counter__label { font-size: 12px; }
.el-animated-counter--empty { display: flex; align-items: center; justify-content: center; min-height: 120px; color: var(--site-text-muted); font-size: 14px; }

/* ── Intro ────────────────────────────────────────────────── */
.el-intro {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 2.5rem;
  align-items: center;
  --el-padding-default: var(--intro-content-padding-y, 2rem) 0;
}
/* was @media (max-width: 767px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-intro { grid-template-columns: 1fr; }
}
@media (max-width: 767px) {
  .el-intro { grid-template-columns: 1fr; }
}
.el-intro--full,
.el-intro--text-only,
.el-intro--centered { grid-template-columns: 1fr; max-width: var(--intro-content-max-width, 800px); margin: 0 auto; }
.el-intro--centered { text-align: center; }
.el-intro__content { display: flex; flex-direction: column; gap: 1rem; }
.el-intro__eyebrow {
  display: inline-block;
  font-size: var(--intro-eyebrow-size, 13px);
  font-weight: var(--intro-eyebrow-weight, 600);
  letter-spacing: var(--intro-eyebrow-letter-spacing, 0.08em);
  color: var(--intro-eyebrow-color, var(--site-accent, var(--site-primary)));
  text-transform: uppercase;
  margin: 0 0 0.25rem;
}
.el-intro__heading {
  font-size: clamp(var(--intro-heading-size-min, 1.75rem), 3.5vw, var(--intro-heading-size-max, 2.75rem));
  font-weight: 800;
  color: var(--site-text);
  margin: 0;
  line-height: var(--intro-heading-line-height, 1.15);
}
.el-intro__subheading {
  font-size: var(--intro-subheading-size, 1.125rem);
  line-height: var(--intro-subheading-line-height, 1.5);
  color: var(--intro-subheading-color, var(--site-text-muted));
  margin: 0;
  font-weight: 500;
}
.el-intro__body { font-size: 1.0625rem; color: var(--site-text-muted); margin: 0; line-height: 1.6; }
.el-intro__cta {
  display: inline-block;
  padding: 0.75rem 1.75rem;
  background: var(--site-primary);
  color: var(--site-btn-primary-text);
  border-radius: var(--site-radius, 0.5rem);
  font-size: 0.9375rem;
  font-weight: 600;
  text-decoration: none;
  align-self: flex-start;
  transition: opacity 0.2s;
}
.el-intro__cta:hover { opacity: 0.88; }
.el-intro__image { border-radius: var(--site-radius, 0.75rem); overflow: hidden; }
.el-intro__image img { width: 100%; display: block; object-fit: cover; }

/* ── Blockquote ───────────────────────────────────────────── */
.el-blockquote {
  position: relative;
  --el-padding-default: 2.25rem 1.75rem 1.5rem 2.25rem;
  margin: 1.5rem 0;
  background: var(--el-bg, var(--site-surface-alt));
  border-radius: var(--site-radius, 0.5rem);
  overflow: hidden;
}
.el-blockquote--bordered {
  border-left: 4px solid var(--bq-accent, var(--site-primary));
}
.el-blockquote__text {
  font-size: 1.125rem;
  font-style: italic;
  color: var(--bq-quote-text, var(--site-text));
  margin: 0 0 0.75rem;
  line-height: 1.6;
}
.el-blockquote__attribution {
  font-family: var(--site-font-body, inherit);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--bq-attribution, var(--site-text-secondary, var(--site-text-muted, currentColor)));
  margin: 0;
}
.el-blockquote__attribution::before { content: '— '; }

/* ── Code Block ───────────────────────────────────────────── */
/* Standalone prism-highlighted code snippet. All chrome chains through
   site theme tokens so dark and light sites pick up the right palette
   automatically. Authors override per-instance via the Style panel
   (background/text-color/border-radius are universal BASE_STYLE_FIELDS
   that paint via --el-* on the wrapper). */
.el-code-block {
  --code-block-bg: var(--site-surface, var(--site-bg, transparent));
  --code-block-fg: var(--site-fg, currentColor);
  --code-block-border: var(--site-border, transparent);
  --code-block-muted: var(--site-text-muted, transparent);
  --code-block-accent: var(--site-accent, currentColor);
  --code-block-radius: var(--site-radius-md, var(--site-radius, 8px));
  --code-block-font: var(--site-font-mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace);
  margin: 0;
  background: var(--el-bg, var(--code-block-bg));
  color: var(--code-block-fg);
  border: 1px solid var(--code-block-border);
  border-radius: var(--code-block-radius);
  overflow: hidden;
  font-family: var(--code-block-font);
}
/* Forced light/dark themes override the auto palette; auto inherits
   site tokens so the snippet matches whatever section it sits in. */
.el-code-block[data-theme="light"] {
  --code-block-bg: #f8fafc;
  --code-block-fg: #1e293b;
  --code-block-border: rgba(15, 23, 42, 0.12);
  --code-block-muted: rgba(15, 23, 42, 0.55);
}
.el-code-block[data-theme="dark"] {
  --code-block-bg: #0c1525;
  --code-block-fg: #e2e8f0;
  --code-block-border: rgba(255, 255, 255, 0.08);
  --code-block-muted: rgba(226, 232, 240, 0.55);
}
.el-code-block__toolbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.5rem 0.875rem;
  border-bottom: 1px solid var(--code-block-border);
  font-size: 0.75rem;
  color: var(--code-block-muted);
  font-family: var(--site-font-body, inherit);
}
.el-code-block__lang {
  text-transform: uppercase;
  letter-spacing: 0.06em;
  font-weight: 600;
}
.el-code-block__copy {
  appearance: none;
  background: transparent;
  border: 1px solid var(--code-block-border);
  border-radius: 4px;
  color: var(--code-block-fg);
  padding: 0.25rem 0.625rem;
  font-size: 0.75rem;
  font-weight: 600;
  cursor: pointer;
  font-family: inherit;
  transition: border-color 120ms ease, color 120ms ease, background 120ms ease;
}
.el-code-block__copy:hover {
  border-color: var(--code-block-accent);
  color: var(--code-block-accent);
}
.el-code-block__copy:focus-visible {
  outline: 2px solid var(--code-block-accent);
  outline-offset: 2px;
}
.el-code-block__copy[data-copied="true"] {
  color: var(--code-block-accent);
  border-color: var(--code-block-accent);
}
.el-code-block__pre {
  margin: 0;
  padding: 1rem 1.125rem;
  overflow-x: auto;
  font-size: 0.875rem;
  line-height: 1.55;
  font-family: var(--code-block-font);
  background: transparent;
  color: inherit;
}
.el-code-block__pre code {
  font-family: inherit;
  background: transparent;
  color: inherit;
  white-space: pre;
  word-break: normal;
  overflow-wrap: normal;
}
.el-code-block[data-wrap="true"] .el-code-block__pre {
  overflow-x: hidden;
}
.el-code-block[data-wrap="true"] .el-code-block__pre code {
  white-space: pre-wrap;
  overflow-wrap: anywhere;
  word-break: break-word;
}
.el-code-block[data-line-numbers="true"] .el-code-block__pre {
  counter-reset: line;
}
/* Line numbers — purely a visual hint, painted via a left gutter pseudo
   element. We do not split into per-line spans here (keeps the SSR
   markup minimal); authors who want true line-numbered output can
   enable Prism's line-numbers plugin in a future iteration. */
.el-code-block[data-line-numbers="true"] .el-code-block__pre code {
  display: block;
  padding-left: 2.5rem;
  position: relative;
  counter-increment: line;
}
.el-code-block__caption {
  padding: 0.5rem 1.125rem 0.875rem;
  font-size: 0.8125rem;
  color: var(--code-block-muted);
  font-family: var(--site-font-body, inherit);
}
/* Prism token colors — keyed off site accent + neutral muted. Mirrors
   the palette used by the inline blog highlighter so a snippet shipped
   in either context looks consistent. */
.el-code-block .token.comment,
.el-code-block .token.prolog,
.el-code-block .token.doctype,
.el-code-block .token.cdata { color: var(--code-block-muted); font-style: italic; }
.el-code-block .token.punctuation { color: var(--code-block-fg); opacity: 0.7; }
.el-code-block .token.property,
.el-code-block .token.tag,
.el-code-block .token.boolean,
.el-code-block .token.number,
.el-code-block .token.constant,
.el-code-block .token.symbol,
.el-code-block .token.deleted { color: var(--code-block-accent); }
.el-code-block .token.selector,
.el-code-block .token.attr-name,
.el-code-block .token.string,
.el-code-block .token.char,
.el-code-block .token.builtin,
.el-code-block .token.inserted { color: #86efac; }
.el-code-block[data-theme="light"] .token.string,
.el-code-block[data-theme="light"] .token.inserted,
.el-code-block[data-theme="light"] .token.selector,
.el-code-block[data-theme="light"] .token.attr-name,
.el-code-block[data-theme="light"] .token.char,
.el-code-block[data-theme="light"] .token.builtin { color: #16a34a; }
.el-code-block .token.atrule,
.el-code-block .token.attr-value,
.el-code-block .token.keyword { color: #f0abfc; }
.el-code-block[data-theme="light"] .token.atrule,
.el-code-block[data-theme="light"] .token.attr-value,
.el-code-block[data-theme="light"] .token.keyword { color: #a21caf; }
.el-code-block .token.function,
.el-code-block .token.class-name { color: #fbbf24; }
.el-code-block[data-theme="light"] .token.function,
.el-code-block[data-theme="light"] .token.class-name { color: #b45309; }
.el-code-block .token.regex,
.el-code-block .token.important,
.el-code-block .token.variable { color: #fca5a5; }
.el-code-block[data-theme="light"] .token.regex,
.el-code-block[data-theme="light"] .token.important,
.el-code-block[data-theme="light"] .token.variable { color: #b91c1c; }

/* ── Icon ─────────────────────────────────────────────────── */
.el-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--site-primary);
}
.el-icon__svg { display: block; }

/* ── Media Story Grid (Stage 11B) ─────────────────────────────
   Parent `media-story-grid` delegates to CompoundSectionRenderer with
   `layout='grid'`. Each story panel is a `story-panel` child.
   Wrapper classes:
     .el-media-story-grid--editorial  — first panel (or any panel flagged
                                         `featured`) gets hero treatment
     .el-media-story-grid--stacked    — uniform grid, no hero
   All chrome via --msg-* CSS vars emitted by the parent shell. No hardcoded
   colors. */

.el-media-story-grid {
  --el-padding-default: 1rem 0;
  display: block;
  --el-padding-default: 1rem 0;
}

.el-media-story-grid .el-compound-section__cards {
  display: grid;
  gap: var(--msg-card-gap, 18px);
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}

/* Editorial layout — asymmetric 12-col grid. First panel (or any panel
   with `data-featured="true"`) spans the full row. Other panels take 4
   columns on wide viewports, auto-fit on narrower. */
.el-media-story-grid--editorial .el-compound-section__cards {
  grid-template-columns: repeat(12, minmax(0, 1fr));
}
.el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel {
  grid-column: span 6;
}
.el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel:first-child,
.el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel[data-featured="true"] {
  grid-column: span 12;
}
/* was @media (min-width: 900px); bucketed to tablet, desktop */
@container site style(--site-bp: tablet) or style(--site-bp: desktop) {
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel {
    grid-column: span 4;
  }
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel:first-child,
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel[data-featured="true"] {
    grid-column: span 12;
  }
}
@media (min-width: 900px) {
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel {
    grid-column: span 4;
  }
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel:first-child,
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel[data-featured="true"] {
    grid-column: span 12;
  }
}

/* Stacked layout — uniform responsive grid, no hero panel. */
.el-media-story-grid--stacked .el-compound-section__cards {
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
}

/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-story-panel` (0,1,0) and zeros bg/border-radius/shadow. Each
   story-panel is a slot child inside its own ElementWrapper
   (.el.el--story-panel) rendered by CompoundSectionRenderer. */
.el.el--story-panel > .el-story-panel {
  background: var(--msg-card-bg, var(--site-surface, transparent));
  border-radius: var(--msg-card-radius, 20px);
  box-shadow: var(--msg-card-shadow, 0 14px 30px rgba(21, 34, 56, 0.08));
}

/* Story panel card. */
.el-story-panel {
  display: flex;
  flex-direction: column;
  color: inherit;
  text-decoration: none;
  overflow: hidden;
  background: var(--el-bg, var(--msg-card-bg, var(--site-surface, transparent)));
  border-radius: var(--msg-card-radius, 20px);
  box-shadow: var(--msg-card-shadow, 0 14px 30px rgba(21, 34, 56, 0.08));
  transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease, border-color 0.2s ease;
  /* Floor cascades through the unified card-min-h token so story panels
     align with neighbouring carousels/grids on every breakpoint. */
  min-height: var(--site-card-min-h, 280px);
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-story-panel:hover {
  transform: translateY(var(--msg-card-hover-translate-y, -3px));
  background: var(--msg-card-hover-bg, var(--msg-card-bg, inherit));
  box-shadow: var(--msg-card-hover-shadow, 0 22px 48px rgba(21, 34, 56, 0.12));
}
.el-media-story-grid--editorial .el-story-panel:first-child,
.el-media-story-grid--editorial .el-story-panel[data-featured="true"] {
  min-height: 420px;
}

.el-story-panel__media {
  position: relative;
  display: block;
  width: 100%;
  /* Non-card media aspect contract — video preset (16/9). Story panels
     are an editorial media surface, not a card grid. */
  aspect-ratio: var(--story-panel-media-aspect, var(--site-media-aspect-video, 16 / 9));
  background: color-mix(in srgb, var(--msg-accent, var(--site-primary, currentColor)) 10%, transparent);
  overflow: hidden;
}
.el-story-panel__media--empty::after {
  content: '';
  display: block;
  width: 100%;
  height: 100%;
}
.el-story-panel__image {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--msg-image-object-position, center);
}

.el-story-panel__body {
  padding: var(--msg-card-padding, 18px);
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
}
.el-story-panel__badge {
  font-size: 0.72rem;
  font-weight: 800;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--msg-accent, var(--site-primary, currentColor));
}
.el-story-panel__title {
  margin: 0;
  font-size: 1.15rem;
  line-height: 1.2;
  letter-spacing: -0.02em;
  color: inherit;
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-media-story-grid--editorial .el-story-panel:first-child .el-story-panel__title,
.el-media-story-grid--editorial .el-story-panel[data-featured="true"] .el-story-panel__title {
  font-size: clamp(1.5rem, 2.4vw, 2.2rem);
  letter-spacing: -0.04em;
}
.el-story-panel__summary {
  margin: 0;
  line-height: 1.6;
  opacity: 0.84;
  overflow-wrap: break-word;
}
.el-story-panel__cta {
  margin-top: auto;
  color: var(--msg-accent, var(--site-primary, currentColor));
  font-weight: 700;
  text-decoration: none;
}

/* was @media (max-width: 640px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-media-story-grid--editorial .el-compound-section__cards,
  .el-media-story-grid--stacked .el-compound-section__cards {
    grid-template-columns: 1fr;
  }
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel,
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel:first-child,
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel[data-featured="true"] {
    grid-column: auto;
  }
}
@media (max-width: 640px) {
  .el-media-story-grid--editorial .el-compound-section__cards,
  .el-media-story-grid--stacked .el-compound-section__cards {
    grid-template-columns: 1fr;
  }
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel,
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel:first-child,
  .el-media-story-grid--editorial .el-compound-section__cards > .el-story-panel[data-featured="true"] {
    grid-column: auto;
  }
}

/* ── Project Showcase ─────────────────────────────────────── */
.el-project-showcase { --el-padding-default: 2rem 0; }
.el-project-showcase__card { position: relative; }
[data-card-hover-shell]:hover .el-project-showcase__card { transform: translateY(-3px); }
.el-project-showcase__card::after {
  content: '';
  position: absolute;
  bottom: 0;
  left: 0;
  width: 100%;
  height: 3px;
  background: var(--showcase-accent, var(--site-accent));
  transform: scaleX(0);
  transform-origin: center;
  transition: transform 0.35s ease;
  border-radius: 0 0 var(--showcase-card-radius, 0px) var(--showcase-card-radius, 0px);
}
.el-project-showcase__card:hover::after { transform: scaleX(1); }
.el-project-showcase__heading {
  font-size: clamp(1.5rem, 3vw, 2.25rem);
  font-weight: 800;
  color: var(--showcase-heading-color, var(--site-text));
  margin: 0 0 0.75rem;
}
.el-project-showcase__description {
  font-size: 1rem;
  color: var(--showcase-intro-color, var(--site-text-secondary));
  margin: 0 0 2rem;
  max-width: 600px;
  line-height: 1.6;
}
.el-project-showcase__grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
  gap: 1.5rem;
}
.el-project-showcase__item {
  position: relative;
  border-radius: var(--site-radius, 0.75rem);
  overflow: hidden;
  background: var(--site-surface-alt);
  transition: transform 0.2s, box-shadow 0.2s;
}
[data-card-hover-shell]:hover .el-project-showcase__item { transform: translateY(-4px); box-shadow: 0 12px 32px rgba(0,0,0,0.12); }
.el-project-showcase__image { width: 100%; aspect-ratio: var(--site-card-media-aspect, 16/9); object-fit: cover; display: block; }
.el-project-showcase__image-placeholder { width: 100%; aspect-ratio: var(--site-card-media-aspect, 16/9); background: var(--site-surface-alt); }
.el-project-showcase__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0,0,0,0.72) 0%, transparent 55%);
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: 1.25rem;
}
.el-project-showcase__title { font-size: 1.0625rem; font-weight: 700; color: var(--showcase-project-title-color, inherit); margin: 0 0 0.25rem; }
.el-project-showcase__category { font-size: 0.8125rem; color: var(--showcase-category-color, currentColor); }
.el-project-showcase__meta { color: var(--showcase-meta-color, inherit); }
.el-project-showcase__link { position: absolute; inset: 0; }

/* ── Content Slider ──────────────────────────────────────── */
.el-content-slider {
  position: relative;
  padding: 0;
}
/* Grid mode — static grid, no carousel */
.el-content-slider--grid {
  overflow: visible;
}
.el-content-slider--grid .el-content-slider__slide {
  flex-shrink: unset;
}
.el-content-slider--empty {
  text-align: center;
  padding: 3rem;
}
.el-content-slider__placeholder {
  color: var(--site-text-secondary);
  font-style: italic;
}
/* `overflow: clip` clips layout (off-screen slides stay hidden) but lets
   decorative paint — card box-shadows, focus rings — bleed past the clip box
   up to `overflow-clip-margin`. Fixes shadow clipping on all four edges
   without breaking the transform-based slide animation. */
.el-content-slider__viewport {
  overflow: clip;
  overflow-clip-margin-top: var(--site-carousel-shadow-bleed-block, 24px); overflow-clip-margin-bottom: var(--site-carousel-shadow-bleed-block, 24px);
  overflow-clip-margin-left: var(--site-carousel-shadow-bleed-inline, var(--cs-carousel-gap, var(--site-card-gap, 24px))); overflow-clip-margin-right: var(--site-carousel-shadow-bleed-inline, var(--cs-carousel-gap, var(--site-card-gap, 24px)));
  border-radius: var(--site-radius, 0.75rem);
  position: relative;
}
/* Track is a flex row that slides via transform */
.el-content-slider__track {
  display: flex;
  flex-wrap: nowrap;
  transition: transform 0.6s cubic-bezier(0.25, 0.1, 0.25, 1);
  will-change: transform;
}
/* High-specificity bridge — `.el > :not(style)` (0,1,1) beats
   `.el-content-slider__slide` (0,1,0) and zeros bg/border-radius/shadow.
   Each content-slide is a slot child in its own ElementWrapper
   (.el.el--content-slide) rendered by CompoundSectionRenderer. */
.el.el--content-slide > .el-content-slider__slide {
  background: var(--cs-card-bg, var(--site-bg-secondary, transparent));
  border-radius: var(--cs-card-radius, var(--site-radius, 0.75rem));
  box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 4px 16px rgba(0,0,0,0.05);
}
/* Each slide card */
.el-content-slider__slide {
  border-radius: var(--cs-card-radius, var(--site-radius, 0.75rem));
  overflow: hidden;
  background: var(--cs-card-bg, var(--site-bg-secondary, transparent));
  border: 1px solid rgba(0,0,0,0.06);
  box-shadow: 0 1px 3px rgba(0,0,0,0.04), 0 4px 16px rgba(0,0,0,0.05);
  flex-shrink: 0;
  min-width: 0;
}
.el-content-slider__slide-image-wrap {
  overflow: hidden;
  position: relative;
}
.el-content-slider__slide-image {
  width: 100%;
  /* Non-card media aspect contract — landscape preset. */
  aspect-ratio: var(--content-slider-image-aspect, var(--site-media-aspect-landscape, 16 / 10));
  object-fit: cover;
  display: block;
  transition: transform 0.5s cubic-bezier(0.2, 0, 0, 1);
}
.el-content-slider__slide:hover .el-content-slider__slide-image {
  transform: scale(1.05);
}
.el-content-slider__slide-image-placeholder {
  width: 100%;
  aspect-ratio: var(--content-slider-image-aspect, var(--site-media-aspect-landscape, 16 / 10));
  background: var(--site-surface-alt);
}
.el-content-slider__slide-caption {
  padding: 0.75rem 1rem 0.5rem;
  text-align: center;
  background: transparent;
}
.el-content-slider__slide-caption span {
  font-family: var(--site-font-heading);
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--cs-title-color, var(--site-fg));
  letter-spacing: -0.01em;
  line-height: 1.4;
  overflow-wrap: break-word;
}
.el-content-slider__slide-desc {
  color: var(--cs-desc-color, var(--site-text-secondary));
  font-size: 0.8125rem;
  line-height: 1.6;
  padding: 0 1rem 0.875rem;
  margin: 0;
  overflow-wrap: break-word;
}
/* CTA button per slide — uses design panel tokens */
.el-content-slider__slide-cta {
  display: block;
  margin: 0 auto 25px;
  padding: 0.5rem 1.25rem;
  width: fit-content;
  font-size: 0.85rem;
  font-weight: 600;
  color: var(--cs-cta-color, var(--site-btn-primary-text));
  background: var(--cs-cta-bg, var(--site-btn-primary-bg, var(--site-accent)));
  border-radius: var(--site-btn-radius, 8px);
  text-align: center;
  text-decoration: none;
  transition: background 0.2s, transform 0.2s;
  cursor: pointer;
}
.el-content-slider__slide-cta:hover {
  filter: brightness(1.1);
}
/* Arrows */
.el-content-slider__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  z-index: 2;
  width: 44px;
  height: 44px;
  padding: 10px;
  border-radius: 50%;
  background: var(--cs-arrow-bg, var(--site-primary));
  border: none;
  box-shadow: 0 2px 12px rgba(0,0,0,0.2);
  cursor: pointer;
  color: var(--cs-arrow-color, var(--site-text));
  display: flex;
  align-items: center;
  justify-content: center;
  transition: background 0.2s, box-shadow 0.2s, opacity 0.2s, transform 0.2s;
}
.el-content-slider__arrow:hover {
  background: var(--site-secondary);
  box-shadow: 0 4px 20px rgba(0,0,0,0.25);
  transform: translateY(-50%) scale(1.08);
}
.el-content-slider__arrow:disabled {
  opacity: 0.25;
  cursor: default;
  pointer-events: none;
}
.el-content-slider__arrow--prev { left: 12px; }
.el-content-slider__arrow--next { right: 12px; }
/* Dots — consume --carousel-dot-* vars from buildCarouselStyleVars
   so the shared design-panel controls (CAROUSEL_DOT_FIELDS) drive them. */
.el-content-slider__dots {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: var(--carousel-dot-gap, 8px);
  margin-top: 1.25rem;
}
.el-content-slider__dot {
  width: var(--carousel-dot-size, 8px);
  height: var(--carousel-dot-size, 8px);
  border-radius: 50%;
  border: none;
  background: var(--carousel-dot-color, var(--site-text-secondary, transparent));
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
  transition: background 0.25s, transform 0.25s, width 0.25s, border-radius 0.25s;
}
.el-content-slider__dot:hover {
  filter: brightness(1.15);
}
.el-content-slider__dot--active {
  background: var(--carousel-dot-active-color, var(--site-accent));
  width: var(--carousel-dot-active-width, 20px);
  border-radius: 4px;
}
/* Responsive: reduce slides on smaller screens */
@container site style(--site-bp: mobile) {
  .el-content-slider__arrow { width: 36px; height: 36px; padding: 8px; }
  .el-content-slider__arrow--prev { left: 8px; }
  .el-content-slider__arrow--next { right: 8px; }
}
@media (max-width: 768px) {
  .el-content-slider__arrow { width: 36px; height: 36px; padding: 8px; }
  .el-content-slider__arrow--prev { left: 8px; }
  .el-content-slider__arrow--next { right: 8px; }
}
/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-content-slider__dots { gap: 6px; margin-top: 1rem; }
}
@media (max-width: 480px) {
  .el-content-slider__dots { gap: 6px; margin-top: 1rem; }
}

/* ── Location Showcase — editorial split ────────────────── */
.el-location-showcase--split {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: clamp(20px, 4vw, 40px);
  align-items: stretch;
  position: relative;
  min-width: 0;
  max-width: 100%;
  overflow-x: clip;
  background: var(--el-bg, var(--ls-bg, transparent));
  color: var(--ls-text, inherit);
  border-radius: var(--ls-border-radius, 0);
}
/* Protect the split-grid columns from blowout when content exceeds its
   track. NOTE: do NOT include `.el-compound-section__inner` here — that
   wrapper carries `.el-site-container` and its width is governed by the
   Section Container Contract (siteContainerWidth dropdown), not by
   per-element overrides. See siteContainerContract.test.tsx. */
.el-location-showcase .el-compound-section__content,
.el-location-showcase .el-compound-section__media {
  min-width: 0;
  max-width: 100%;
}
/* Content column */
.el-location-showcase__content {
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 1rem;
  order: 1;
}
.el-location-showcase--reverse .el-location-showcase__content { order: 2; }
/* Alignment modifiers */
.el-location-showcase--center .el-location-showcase__content { text-align: center; }
.el-location-showcase--right .el-location-showcase__content { text-align: right; }
/* Eyebrow */
.el-location-showcase__eyebrow {
  text-transform: uppercase;
  letter-spacing: 0.18em;
  font-size: 0.72rem;
  color: var(--ls-accent, var(--site-accent));
  font-weight: 800;
}
/* Heading */
.el-location-showcase__heading {
  margin: 0;
  font-family: var(--site-font-heading);
  font-size: clamp(2rem, 3vw, 3.4rem);
  font-weight: 700;
  line-height: 0.95;
  letter-spacing: -0.05em;
  overflow-wrap: break-word;
  word-break: break-word;
}
/* Subheading */
.el-location-showcase__subheading {
  margin: 0;
  max-width: min(640px, 100%);
  font-size: 1.04rem;
  line-height: 1.7;
  opacity: 0.9;
  overflow-wrap: break-word;
}
.el-location-showcase--center .el-location-showcase__subheading { margin-inline: auto; }
/* Intro */
.el-location-showcase__intro {
  margin: 0;
  max-width: min(680px, 100%);
  font-size: 1rem;
  line-height: 1.75;
  opacity: 0.92;
  overflow-wrap: break-word;
}
.el-location-showcase--center .el-location-showcase__intro { margin-inline: auto; }
/* Stats grid */
.el-location-showcase__stat-grid {
  display: grid;
  grid-template-columns: repeat(var(--ls-stat-cols, 4), minmax(0, 1fr));
  gap: 12px;
}
@container site style(--site-bp: mobile) {
  .el-location-showcase__stat-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 768px) {
  .el-location-showcase__stat-grid { grid-template-columns: repeat(2, 1fr); }
}
.el-location-showcase__stat-card {
  padding: 14px 16px;
  border-radius: var(--ls-card-radius, 18px);
  background: var(--ls-card-bg, var(--site-bg-secondary, transparent));
  box-shadow: var(--ls-shadow, 0 4px 12px rgba(0,0,0,0.06));
}
.el-location-showcase__stat-value {
  font-size: 1.4rem;
  font-weight: 800;
  letter-spacing: -0.04em;
}
.el-location-showcase__stat-label {
  font-size: 0.78rem;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  opacity: 0.72;
}
/* Facts (pill badges) */
.el-location-showcase__facts {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.el-location-showcase__fact {
  border-radius: 6px;
  padding: 0.55rem 0.9rem;
  background: var(--ls-fact-bg, var(--ls-card-bg, var(--site-bg-secondary, transparent)));
  border: none;
  border-left: 3px solid var(--ls-fact-accent, var(--ls-accent, var(--site-accent)));
  color: var(--ls-fact-text, inherit);
  font-size: 0.9rem;
  font-weight: 600;
  overflow-wrap: break-word;
}
.el-location-showcase__fact-label { opacity: 0.7; }
.el-location-showcase__fact-value { overflow-wrap: break-word; }
/* Chips */
.el-location-showcase__chips {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.el-location-showcase__chip {
  border-radius: 999px;
  padding: 0.55rem 0.85rem;
  background: var(--ls-card-bg, var(--site-bg-secondary, transparent));
  border: 1px solid rgba(0,0,0,0.06);
  font-size: 0.88rem;
  font-weight: 700;
  overflow-wrap: break-word;
}
/* Bullets */
.el-location-showcase__bullets {
  margin: 0;
  padding-left: 0;
  list-style: none;
  display: grid;
  gap: var(--ls-bullet-row-gap, 8px);
  line-height: 1.6;
}
.el-location-showcase__bullet {
  display: flex;
  align-items: center;
  gap: var(--ls-bullet-inner-gap, 8px);
  padding: var(--ls-bullet-pad-top, 0) var(--ls-bullet-pad-right, 0) var(--ls-bullet-pad-bottom, 0) var(--ls-bullet-pad-left, 0);
  margin: var(--ls-bullet-margin-top, 0) var(--ls-bullet-margin-right, 0) var(--ls-bullet-margin-bottom, 0) var(--ls-bullet-margin-left, 0);
}
.el-location-showcase__bullet-marker {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: var(--ls-bullet-icon-size, 16px);
  min-width: var(--ls-bullet-icon-size, 16px);
  height: var(--ls-bullet-icon-size, 16px);
  color: var(--ls-bullet-accent, var(--ls-accent, var(--site-primary)));
}
.el-location-showcase__bullet-icon {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}
.el-location-showcase__bullet-text {
  overflow-wrap: break-word;
}
/* CTA actions */
.el-location-showcase__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 12px;
  padding-top: 4px;
}
.el-location-showcase--center .el-location-showcase__actions { justify-content: center; }
.el-location-showcase--right .el-location-showcase__actions { justify-content: flex-end; }
.el-location-showcase__cta {
  border-radius: 999px;
  padding: 0.9rem 1.25rem;
  font-size: 0.95rem;
  font-weight: 700;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  transition: transform 180ms ease, box-shadow 180ms ease, background-color 180ms ease, border-color 180ms ease;
}
.el-location-showcase__cta--primary {
  background: var(--site-primary);
  color: var(--site-primary-fg);
  border: 1px solid var(--site-primary);
  box-shadow: 0 18px 32px rgba(0,0,0,0.18);
}
.el-location-showcase__cta--primary:hover {
  box-shadow: 0 22px 40px rgba(0,0,0,0.22);
}
.el-location-showcase__cta--secondary {
  background: transparent;
  color: currentColor;
  border: 1px solid currentColor;
}
.el-location-showcase__cta--secondary:hover {
  box-shadow: 0 8px 24px rgba(0,0,0,0.08);
}
/* Media column */
.el-location-showcase .el-compound-section__media,
.el-location-showcase__media {
  position: relative;
  min-height: clamp(320px, 48vw, 520px);
  order: 2;
  overflow: hidden;
  border-radius: calc(var(--ls-card-radius, 18px) + 4px);
}
.el-location-showcase--reverse .el-compound-section__media,
.el-location-showcase--reverse .el-location-showcase__media { order: 1; }
/* Primary image frame */
.el-location-showcase .el-compound-section__media-primary,
.el-location-showcase__primary-frame {
  position: absolute;
  inset: 0;
  border-radius: calc(var(--ls-card-radius, 18px) + 4px);
  overflow: hidden;
  background: var(--ls-card-bg, transparent);
  border: var(--ls-frame-border, none);
  box-shadow: var(--ls-shadow, none);
}
.el-location-showcase .el-compound-section__media-primary > .el,
.el-location-showcase .el-compound-section__media-primary > .el > * {
  width: 100%;
  height: 100%;
}
.el-location-showcase .el-compound-section__media-primary img,
.el-location-showcase .el-compound-section__media-primary video,
.el-location-showcase__primary-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--ls-primary-fp, center);
  display: block;
}
.el-location-showcase__placeholder {
  width: 100%;
  height: 100%;
  display: grid;
  place-items: center;
  color: rgba(21,34,56,0.45);
  background: linear-gradient(135deg, rgba(26,39,68,0.04), rgba(200,164,92,0.08));
}
/* Secondary image frame (inset card) */
.el-location-showcase .el-compound-section__media-secondary,
.el-location-showcase__secondary-frame {
  position: absolute;
  right: 0;
  bottom: 24px;
  width: 42%;
  max-width: 240px;
  /* Non-card media aspect contract — portrait preset for the inset
     secondary frame in a location-showcase. */
  aspect-ratio: var(--ls-secondary-aspect, var(--site-media-aspect-portrait, 4 / 5));
  border-radius: calc(var(--ls-card-radius, 18px) + 4px);
  overflow: hidden;
  background: var(--ls-card-bg, transparent);
  border: var(--ls-secondary-border, 4px solid rgba(251,250,247,0.92));
  box-shadow: var(--ls-shadow, none);
}
.el-location-showcase--reverse .el-compound-section__media-secondary,
.el-location-showcase__secondary-frame--left {
  right: auto;
  left: 0;
}
.el-location-showcase .el-compound-section__media-secondary > .el,
.el-location-showcase .el-compound-section__media-secondary > .el > * {
  width: 100%;
  height: 100%;
}
.el-location-showcase .el-compound-section__media-secondary img,
.el-location-showcase .el-compound-section__media-secondary video,
.el-location-showcase__secondary-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--ls-secondary-fp, center);
  display: block;
}
/* Responsive */
@container site style(--site-bp: mobile) {
  .el-location-showcase--split {
    grid-template-columns: 1fr;
  }
  .el-location-showcase__content { order: 2 !important; }
  .el-location-showcase .el-compound-section__media,
  .el-location-showcase__media { order: 1 !important; min-height: 300px; }
  .el-location-showcase .el-compound-section__media-secondary,
  .el-location-showcase__secondary-frame { width: 35%; max-width: 160px; }
}
@media (max-width: 768px) {
  .el-location-showcase--split {
    grid-template-columns: 1fr;
  }
  .el-location-showcase__content { order: 2 !important; }
  .el-location-showcase .el-compound-section__media,
  .el-location-showcase__media { order: 1 !important; min-height: 300px; }
  .el-location-showcase .el-compound-section__media-secondary,
  .el-location-showcase__secondary-frame { width: 35%; max-width: 160px; }
}
/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-location-showcase__stat-grid { grid-template-columns: 1fr; }
  .el-location-showcase .el-compound-section__media-secondary,
  .el-location-showcase__secondary-frame {
    width: min(42%, 136px);
    max-width: 136px;
    bottom: 16px;
  }
}
@media (max-width: 480px) {
  .el-location-showcase__stat-grid { grid-template-columns: 1fr; }
  .el-location-showcase .el-compound-section__media-secondary,
  .el-location-showcase__secondary-frame {
    width: min(42%, 136px);
    max-width: 136px;
    bottom: 16px;
  }
}

/* ── Location Detail — compound split ────────────────── */
.el-location-detail--compound .el-compound-section__content {
  min-width: 0;
}
.el-location-detail--compound .el-compound-section__media {
  position: relative;
  min-height: clamp(320px, 48vw, 520px);
  border-radius: calc(var(--ld-card-radius, 14px) + 4px);
  overflow: hidden;
}
.el-location-detail--compound .el-compound-section__media-primary {
  position: absolute;
  inset: 0;
  border-radius: calc(var(--ld-card-radius, 14px) + 4px);
  overflow: hidden;
  background: var(--ld-card-bg, transparent);
  box-shadow: var(--ld-card-shadow, none);
}
.el-location-detail--compound .el-compound-section__media-primary > .el,
.el-location-detail--compound .el-compound-section__media-primary > .el > * {
  width: 100%;
  height: 100%;
}
.el-location-detail--compound .el-compound-section__media-primary img,
.el-location-detail--compound .el-compound-section__media-primary video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--ld-primary-fp, center);
  display: block;
}
.el-location-detail--compound .el-compound-section__media-secondary {
  position: absolute;
  right: 0;
  bottom: 24px;
  width: min(42%, 220px);
  max-width: 220px;
  /* Non-card media aspect contract — portrait preset for the inset
     secondary frame in a location-detail compound section. */
  aspect-ratio: var(--ld-secondary-aspect, var(--site-media-aspect-portrait, 4 / 5));
  border-radius: calc(var(--ld-card-radius, 14px) + 2px);
  overflow: hidden;
  background: var(--ld-card-bg, transparent);
  border: 1px solid color-mix(in srgb, var(--ld-card-text, currentColor) 10%, transparent);
  box-shadow: var(--ld-card-shadow, none);
}
.el-location-detail--compound .el-compound-section__media-secondary > .el,
.el-location-detail--compound .el-compound-section__media-secondary > .el > * {
  width: 100%;
  height: 100%;
}
.el-location-detail--compound .el-compound-section__media-secondary img,
.el-location-detail--compound .el-compound-section__media-secondary video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: var(--ld-secondary-fp, center);
  display: block;
}
.el-location-detail__facts-grid {
  grid-template-columns: repeat(auto-fit, minmax(min(180px, calc(50% - 7px)), 1fr));
}
@container site style(--site-bp: mobile) {
  .el-location-detail--compound .el-compound-section__media {
    min-height: 300px;
  }
  .el-location-detail--compound .el-compound-section__media-secondary {
    width: min(36%, 160px);
    max-width: 160px;
  }
}
@media (max-width: 768px) {
  .el-location-detail--compound .el-compound-section__media {
    min-height: 300px;
  }
  .el-location-detail--compound .el-compound-section__media-secondary {
    width: min(36%, 160px);
    max-width: 160px;
  }
}
/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-location-detail__facts-grid {
    grid-template-columns: 1fr;
  }
  .el-location-detail--compound .el-compound-section__media-secondary {
    width: min(42%, 136px);
    max-width: 136px;
    bottom: 16px;
  }
}
@media (max-width: 480px) {
  .el-location-detail__facts-grid {
    grid-template-columns: 1fr;
  }
  .el-location-detail--compound .el-compound-section__media-secondary {
    width: min(42%, 136px);
    max-width: 136px;
    bottom: 16px;
  }
}

/* ── Floor Plans ────────────────────────────────────────────── */
.el-floor-plans {
  width: 100%;
  max-width: 100%;
  margin-left: auto;
  margin-right: auto;
}
.el-floor-plans__heading {
  font-family: var(--site-font-heading);
  font-weight: 800;
  color: var(--site-heading, inherit);
  margin: 0 0 0.5rem;
  width: 100%;
  letter-spacing: -0.01em;
  line-height: 1.2;
}
.el-floor-plans__subheading {
  font-size: 1.05rem;
  color: var(--site-text-secondary);
  margin: 0 0 1.5rem;
  text-align: center;
}
.el-floor-plans__grid {
  width: 100%;
}
.el-floor-plans__item {
  margin: 0;
  padding: 0;
  background: var(--site-surface-alt);
}
.el-floor-plans__item--clickable {
  cursor: pointer;
  transition: transform 0.2s ease, background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
/* CARD_HOVER_FIELDS contract — every property chains the builder-set
   --fp-card-hover-* override → accent-derived default. See
   src/ai_skills/evara-website-builder/SKILL_REFERENCE.md § Card Hover Contract. */
[data-card-hover-shell]:hover .el-floor-plans__item--clickable {
  transform: translateY(calc(var(--fp-card-hover-lift, 4px) * -1));
  background: var(--fp-card-hover-bg, var(--site-surface-alt));
  color: var(--fp-card-hover-color, inherit);
  border-color: var(--fp-card-hover-border-color,
    color-mix(in srgb, var(--site-accent, currentColor) 45%, transparent));
  box-shadow: var(--fp-card-hover-shadow,
    0 4px 16px rgba(0, 0, 0, calc(0.08 * var(--fp-card-hover-glow-opacity, 1))));
}
.el-floor-plans__image {
  width: 100%;
  height: auto;
  display: block;
}
.el-floor-plans__caption {
  padding: 0.75rem 1rem;
  font-family: var(--site-font-body, inherit);
  font-size: 0.875rem;
  font-weight: 500;
  line-height: 1.45;
  color: var(--site-text-secondary, var(--site-text-muted, currentColor));
  text-align: center;
  overflow-wrap: break-word;
}
.el-floor-plans__empty {
  text-align: center;
  padding: 3rem 1rem;
  color: var(--site-text-secondary);
}
/* was @media (max-width: 640px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-floor-plans__grid {
    grid-template-columns: 1fr !important;
  }
}
@media (max-width: 640px) {
  .el-floor-plans__grid {
    grid-template-columns: 1fr !important;
  }
}

/* ── Responsive radius reset ─────────────────────────────────────────
   When elements span the full screen width on tablet/mobile, remove
   border-radius so corners flush with the viewport edge for cleaner reads.
   Removed: the global `border-radius: 0 !important` clobber previously here
   was overriding user-set borderRadius on 8 card types. Cards now respect
   the builder's borderRadius prop on all breakpoints. */

/* ── Page-kind: legal ────────────────────────────────────────────────
   Terms, privacy, unsubscribe should read like documents, not landings.
   Tone down hero, wrap rich-text in a glass document card, soften
   the bottom CTA so it doesn't feel like a sales pitch. */


/* Legal-page intentional override (per §5 specificity fix) — drives the
   shared .el-hero::before scrim by overriding --el-overlay-bg /
   --el-overlay-opacity with !important so the wrapper's inline-style vars
   can't soften the legal-page chrome. */
















/* Bottom CTA on legal pages — strip the bright cyan, make it a quiet
   support strip, NOT a promotional band. */









/* (page-kind solutions/compare CTA-band overrides intentionally removed —
   each marketing cta-band carries its own unique animated video bg
   instead, keeping the glass panel + cyan CTA buttons consistent.) */

/* ── Page-kind: solutions — compact stats variant ───────────────────
   Solutions pages get a denser, pill-row treatment instead of the
   big-number bar used on home/features/pricing. Same data, different
   signature so /solutions doesn't look like a copy of /home. */








/* Page-kind: compare — keep stats hidden (handled in DB), but if a stats
   slips through ever, give it the same pill treatment so it doesn't read
   like the cloned big-number bar. */







/* ── Page-kind: compare — intent-router as editorial cards ──────────
   Comparison hub uses bigger heading + tighter cards so it reads as
   "pick your migration" rather than another marketing intent panel. */



/* ── Page-kind: compare/* — comparison-table breathes, no narrow cap ─ */



/* Pricing-table + cta-with-image: default container padding + max-width.
   Users can override via the design panel's padding/maxWidth controls
   (--el-padding CSS var and the maxWidth prop). */
/* Width is owned by the section's `siteContainerWidth` control via
   `.el-site-container[--narrow|--wide|--full]` on the inner wrapper.
   Hard 1200px caps here used to override that — removed so the inspector
   field wins. Authors who need a tight column should pick "Default" or
   "Narrow" in Content Width. */

/* ─────────────────────────────────────────────────────────────────────────
   Marketing reveal-on-scroll animations
   ─────────────────────────────────────────────────────────────────────────
   Driven by `MarketingRevealObserver` (mounted in MarketingPageRuntime).
   The observer adds `data-revealed="true"` once the element intersects;
   we transition opacity + translateY here. Targets initial-state opacity:0
   on marketing pages only — never inside the builder/admin chrome.

   Reduced motion: handled in JS (observer bails before adding the attribute)
   AND defended again in CSS via @media (prefers-reduced-motion: reduce).
   ───────────────────────────────────────────────────────────────────────── */
/* Reveal-on-scroll: cards are visible by default. JS observer adds
   `data-revealed="true"` for the slide-up animation as a progressive
   enhancement — if JS fails or the observer never fires (e.g. CSS
   reflow timing), cards stay fully visible. */


/* Initial hidden state ONLY when the observer has explicitly marked
   the element as not yet revealed. The observer in MarketingRevealObserver
   sets data-revealed="false" before the IntersectionObserver fires, then
   flips to "true" when the element enters the viewport. */




/* Stagger sibling cards so a row reveals as a wave, not a wall */
















/* Legal pages stay calm/static — no reveal motion at all */


/* Reduced-motion: kill animation entirely (defense-in-depth) */


/* ─────────────────────────────────────────────────────────────────────────
   Per-page-kind feature-card surface variants
   ─────────────────────────────────────────────────────────────────────────
   Same element, distinct surface treatment per page family. Touches only
   structural surface props (padding, radius, hover-lift, border tint, glow
   color) — NEVER the user-driven --fc-accent / --fc-card-bg vars.
   Use !important sparingly to override the renderer's inline `cardStyle`
   fall-throughs (borderRadius, padding) only where it matters.
   ───────────────────────────────────────────────────────────────────────── */

/* solutions/* — tighter, more dense, subtle lift */



/* features — wider, more generous, cyan glow on hover */



/* oncue-ai — purple-tinted hover (the AI surface is purple-leaning) */



/* compare — render any feature-cards as compact, text-dense stat tiles */





/* landing/home — keep generous defaults but add a subtle inset highlight on hover */



/* ─────────────────────────────────────────────────────────────────────────
   /solutions/* — give the cta-with-image block a different look on operators
   so split / left-flip / background-mode each feel intentional.
   ───────────────────────────────────────────────────────────────────────── */



/* ─────────────────────────────────────────────────────────────────────────
   Marketing payload pages: constrain section-level element wrappers
   (.el--intent-router, .el--feature-cards, .el--stats, etc.) so they don't
   bleed to the viewport edge. The shared site CSS doesn't max-width these
   wrappers because client sites typically embed them inside their own
   container — but marketing payload pages render them as direct children
   of the page wrapper.
   ───────────────────────────────────────────────────────────────────────── */


/* On wide enough viewports the cta-band gets a touch more breathing room */


/* ─────────────────────────────────────────────────────────────────────────
   Comparison Table — `glass-dark` variant.
   Deep midnight glassmorphic panel with cyan/indigo radial highlights,
   gradient white-fade heading, fixed-table layout with widened feature
   column. Designed for dark site backgrounds. Opt in per-instance via the
   inspector (`Variant → Glass Dark`) — emitted as `.el-comparison--glass-dark`
   by the renderer, no wrapper-attribute scope.
   ───────────────────────────────────────────────────────────────────────── */
.el-comparison--glass-dark {
  max-width: min(1260px, 100%);
  background:
    radial-gradient(ellipse 55% 38% at 22% -10%, rgba(56, 189, 248, 0.09) 0%, transparent 58%),
    radial-gradient(ellipse 40% 30% at 80% 108%, rgba(99, 102, 241, 0.07) 0%, transparent 55%),
    linear-gradient(172deg, rgba(7, 14, 29, 0.98) 0%, rgba(3, 6, 16, 0.99) 55%, rgba(5, 11, 25, 0.98) 100%);
  border: 1px solid rgba(255, 255, 255, 0.052);
  box-shadow:
    0 0 0 1px rgba(56, 189, 248, 0.038),
    inset 0 1px 0 rgba(255, 255, 255, 0.042),
    0 40px 100px rgba(0, 0, 0, 0.50),
    0 70px 160px rgba(0, 0, 0, 0.30);
}

.el-comparison--glass-dark .el-comparison__heading {
  font-size: clamp(1.55rem, 2.6vw, 2.2rem);
  font-weight: 800;
  letter-spacing: -0.038em;
  line-height: 1.15;
  padding: 44px 36px 28px;
  background: linear-gradient(180deg, #ffffff 0%, rgba(255, 255, 255, 0.72) 100%);
  -webkit-background-clip: text;
          background-clip: text;
  -webkit-text-fill-color: transparent;
}

.el-comparison--glass-dark .el-comparison__table {
  table-layout: fixed;
  min-width: 800px;
}
.el-comparison--glass-dark .el-comparison__table th:first-child,
.el-comparison--glass-dark .el-comparison__table td:first-child { width: 35%; }
.el-comparison--glass-dark .el-comparison__table th.el-comparison__col--highlighted,
.el-comparison--glass-dark .el-comparison__table td.el-comparison__col--highlighted { width: 17%; }

.el-comparison--glass-dark .el-comparison__table th {
  font-family: var(--ct-header-font-family, var(--site-font-heading, var(--site-font-body, inherit))) !important;
  font-size: var(--ct-header-size, clamp(18px, 1.25vw, 22px)) !important;
  line-height: 1.18;
  font-weight: var(--ct-header-font-weight, var(--site-font-heading-weight, 800)) !important;
  letter-spacing: 0;
  color: rgba(226, 232, 240, 0.78);
  padding: 34px 18px 28px;
  border-bottom-color: rgba(255, 255, 255, 0.055);
  text-transform: none;
  text-align: center;
  overflow-wrap: break-word;
  word-break: break-word;
}
.el-comparison--glass-dark .el-comparison__table th:first-child {
  padding-left: 36px;
  text-align: left;
}

.el-comparison--glass-dark .el-comparison__table td {
  color: rgba(226, 232, 240, 0.62);
  border-bottom-color: rgba(255, 255, 255, 0.038);
  transition: background 0.18s ease, color 0.18s ease;
  vertical-align: middle;
}
.el-comparison--glass-dark .el-comparison__table td:first-child {
  color: rgba(226, 232, 240, 0.92);
  padding-left: 36px;
}
.el-comparison--glass-dark .el-comparison__table tbody tr:hover td:first-child {
  color: rgba(226, 232, 240, 1);
}

@container site style(--site-bp: mobile) {
  .el-comparison--glass-dark { border-radius: 24px; }
  .el-comparison--glass-dark .el-comparison__heading { font-size: 1.35rem; padding: 26px 20px 16px; }
  .el-comparison--glass-dark .el-comparison__table th { padding: 20px 12px; }
  .el-comparison--glass-dark .el-comparison__table td { padding: 16px 12px; }
  .el-comparison--glass-dark .el-comparison__table td:first-child { padding-left: 18px; }
}
@media (max-width: 768px) {
  .el-comparison--glass-dark { border-radius: 24px; }
  .el-comparison--glass-dark .el-comparison__heading { font-size: 1.35rem; padding: 26px 20px 16px; }
  .el-comparison--glass-dark .el-comparison__table th { padding: 20px 12px; }
  .el-comparison--glass-dark .el-comparison__table td { padding: 16px 12px; }
  .el-comparison--glass-dark .el-comparison__table td:first-child { padding-left: 18px; }
}

/* Final mobile comparison-table contract.
   This lives after premium/glass-dark variants so every comparison table
   reflows to compact, readable feature cards instead of inheriting desktop
   table spacing on phones. */
@container site style(--site-bp: mobile) {
  .el-comparison {
    width: min(
      var(--el-comparison-mobile-width, calc(100% - clamp(3rem, 12vw, 6rem))),
      var(--el-comparison-max-width, 100%)
    );
    max-width: var(--el-comparison-max-width, 100%);
    margin-inline: auto;
    padding-inline: 0 !important;
    border-radius: min(var(--ct-radius, 20px), 24px);
    background: transparent !important;
    border-color: transparent !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    overflow: visible;
  }

  .el-comparison::before {
    display: none;
  }

  .el-comparison__heading-wrap,
  .el-comparison__body-wrap {
    box-sizing: border-box;
    width: 100%;
    padding-inline: clamp(0.75rem, 4vw, 1.25rem);
  }

  .el-comparison__scroll-wrapper {
    overflow-x: visible;
    box-sizing: border-box;
    width: min(
      var(--el-comparison-scroll-mobile-width, calc(100% - clamp(1.5rem, 8vw, 2.5rem))),
      100%
    );
    margin-inline: auto;
    padding: 0;
    background: transparent !important;
    border-color: transparent !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }

  .el-comparison__table {
    width: 100% !important;
    min-width: 0 !important;
    border-spacing: 0 !important;
  }

  .el-comparison__table th {
    text-align: center !important;
  }

  .el-comparison__table tr {
    box-sizing: border-box;
    width: 100%;
    overflow: hidden;
    padding: 0 !important;
    margin: 0 0 14px;
    border: 1px solid var(--ct-divider, var(--ct-border, transparent));
    border-radius: var(--site-radius-lg, 16px);
    background: var(--ct-card-bg, var(--ct-row-bg, var(--site-glass-bg, transparent)));
  }

  .el-comparison__table td {
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 16px;
    padding: 12px 14px !important;
    border: 0 !important;
    border-bottom: 1px solid var(--ct-divider, transparent) !important;
    text-align: left;
  }

  .el-comparison__table td:first-child {
    display: block !important;
    margin: 0 !important;
    padding: 14px 15px 13px !important;
    border-bottom: 1px solid var(--ct-divider, transparent) !important;
    border-radius: 0 !important;
    background: color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 8%, transparent);
    font-size: clamp(15px, 4vw, 17px);
    line-height: 1.25;
    text-align: center !important;
  }

  .el-comparison__table td:first-child .el-comparison__feature-label,
  .el-comparison__table td:first-child .el-comparison__feature-desc {
    text-align: center !important;
  }

  .el-comparison__table td:last-child {
    border-bottom: 0 !important;
  }

  .el-comparison__table td[data-col-label]::before {
    min-width: 0;
    color: var(--ct-th-color, var(--site-text-muted, currentColor));
    font-size: 11px;
    line-height: 1.2;
    letter-spacing: 0.06em;
    overflow-wrap: break-word;
    word-break: break-word;
  }

  .el-comparison__table td .el-comparison__text-value,
  .el-comparison__table td .el-comparison__check,
  .el-comparison__table td .el-comparison__cross {
    justify-self: end;
    margin-left: auto;
    margin-right: 0;
  }

  .el-comparison__table td .el-comparison__text-value {
    max-width: 100%;
    text-align: right;
    overflow-wrap: break-word;
  }

  /* Mobile premium highlighted cell — restore the column label on the
     LEFT side of the row card so it matches the other competitor rows.
     The desktop premium rule paints a translucent pill via `::before`
     (content: ''; position: absolute) which silently overrides the
     base mobile rule that uses `::before` for the data-col-label.
     Result on mobile: highlighted row showed an empty left side and
     a free-floating icon on the right. Fix: on mobile, the ::before
     becomes the label (matching the other rows) and we move the
     glass pill chrome to ::after. */
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted[data-col-label]::before {
    content: attr(data-col-label);
    position: static;
    inset: auto;
    background: none;
    box-shadow: none;
    border-radius: 0;
    color: var(--ct-th-color, var(--site-text-muted, currentColor));
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    line-height: 1.2;
    text-transform: uppercase;
    pointer-events: auto;
    z-index: auto;
    flex: 0 0 auto;
    overflow-wrap: break-word;
    word-break: break-word;
    min-width: 0;
  }
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted::after {
    content: '';
    position: absolute;
    inset: var(--ct-highlight-cell-inset-y, 6px) var(--ct-highlight-cell-inset-x, 10px);
    border-radius: var(--ct-highlight-cell-radius, 12px);
    background: var(--ct-highlight-cell-bg, color-mix(in srgb, var(--ct-highlight, var(--site-accent, transparent)) 16%, rgba(255, 255, 255, 0.025)));
    box-shadow:
      inset 0 1px 0 color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 18%, rgba(255, 255, 255, 0.06)),
      0 0 18px color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 8%, transparent);
    pointer-events: none;
    z-index: 0;
  }
  /* Right-align the icon/value as a grid item (the existing rule sets
     justify-self: end / margin: 0) — the highlighted cell needs the same
     alignment, otherwise the premium `margin: 0 auto` on the icon
     centers it inside the right grid track and visually drifts off the
     icons in the other rows. */
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted .el-comparison__check,
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted .el-comparison__cross,
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted .el-comparison__text-value {
    justify-self: end;
    margin-left: auto;
    margin-right: 0;
    position: relative;
    z-index: 1;
  }
}
@media (max-width: 768px) {
  .el-comparison {
    width: min(
      var(--el-comparison-mobile-width, calc(100% - clamp(3rem, 12vw, 6rem))),
      var(--el-comparison-max-width, 100%)
    );
    max-width: var(--el-comparison-max-width, 100%);
    margin-inline: auto;
    padding-inline: 0 !important;
    border-radius: min(var(--ct-radius, 20px), 24px);
    background: transparent !important;
    border-color: transparent !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    overflow: visible;
  }

  .el-comparison::before {
    display: none;
  }

  .el-comparison__heading-wrap,
  .el-comparison__body-wrap {
    box-sizing: border-box;
    width: 100%;
    padding-inline: clamp(0.75rem, 4vw, 1.25rem);
  }

  .el-comparison__scroll-wrapper {
    overflow-x: visible;
    box-sizing: border-box;
    width: min(
      var(--el-comparison-scroll-mobile-width, calc(100% - clamp(1.5rem, 8vw, 2.5rem))),
      100%
    );
    margin-inline: auto;
    padding: 0;
    background: transparent !important;
    border-color: transparent !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }

  .el-comparison__table {
    width: 100% !important;
    min-width: 0 !important;
    border-spacing: 0 !important;
  }

  .el-comparison__table th {
    text-align: center !important;
  }

  .el-comparison__table tr {
    box-sizing: border-box;
    width: 100%;
    overflow: hidden;
    padding: 0 !important;
    margin: 0 0 14px;
    border: 1px solid var(--ct-divider, var(--ct-border, transparent));
    border-radius: var(--site-radius-lg, 16px);
    background: var(--ct-card-bg, var(--ct-row-bg, var(--site-glass-bg, transparent)));
  }

  .el-comparison__table td {
    box-sizing: border-box;
    width: 100%;
    min-width: 0;
    display: grid !important;
    grid-template-columns: minmax(0, 1fr) auto;
    align-items: center;
    gap: 16px;
    padding: 12px 14px !important;
    border: 0 !important;
    border-bottom: 1px solid var(--ct-divider, transparent) !important;
    text-align: left;
  }

  .el-comparison__table td:first-child {
    display: block !important;
    margin: 0 !important;
    padding: 14px 15px 13px !important;
    border-bottom: 1px solid var(--ct-divider, transparent) !important;
    border-radius: 0 !important;
    background: color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 8%, transparent);
    font-size: clamp(15px, 4vw, 17px);
    line-height: 1.25;
    text-align: center !important;
  }

  .el-comparison__table td:first-child .el-comparison__feature-label,
  .el-comparison__table td:first-child .el-comparison__feature-desc {
    text-align: center !important;
  }

  .el-comparison__table td:last-child {
    border-bottom: 0 !important;
  }

  .el-comparison__table td[data-col-label]::before {
    min-width: 0;
    color: var(--ct-th-color, var(--site-text-muted, currentColor));
    font-size: 11px;
    line-height: 1.2;
    letter-spacing: 0.06em;
    overflow-wrap: break-word;
    word-break: break-word;
  }

  .el-comparison__table td .el-comparison__text-value,
  .el-comparison__table td .el-comparison__check,
  .el-comparison__table td .el-comparison__cross {
    justify-self: end;
    margin-left: auto;
    margin-right: 0;
  }

  .el-comparison__table td .el-comparison__text-value {
    max-width: 100%;
    text-align: right;
    overflow-wrap: break-word;
  }

  /* Mobile premium highlighted cell — restore the column label on the
     LEFT side of the row card so it matches the other competitor rows.
     The desktop premium rule paints a translucent pill via `::before`
     (content: ''; position: absolute) which silently overrides the
     base mobile rule that uses `::before` for the data-col-label.
     Result on mobile: highlighted row showed an empty left side and
     a free-floating icon on the right. Fix: on mobile, the ::before
     becomes the label (matching the other rows) and we move the
     glass pill chrome to ::after. */
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted[data-col-label]::before {
    content: attr(data-col-label);
    position: static;
    inset: auto;
    background: none;
    box-shadow: none;
    border-radius: 0;
    color: var(--ct-th-color, var(--site-text-muted, currentColor));
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.06em;
    line-height: 1.2;
    text-transform: uppercase;
    pointer-events: auto;
    z-index: auto;
    flex: 0 0 auto;
    overflow-wrap: break-word;
    word-break: break-word;
    min-width: 0;
  }
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted::after {
    content: '';
    position: absolute;
    inset: var(--ct-highlight-cell-inset-y, 6px) var(--ct-highlight-cell-inset-x, 10px);
    border-radius: var(--ct-highlight-cell-radius, 12px);
    background: var(--ct-highlight-cell-bg, color-mix(in srgb, var(--ct-highlight, var(--site-accent, transparent)) 16%, rgba(255, 255, 255, 0.025)));
    box-shadow:
      inset 0 1px 0 color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 18%, rgba(255, 255, 255, 0.06)),
      0 0 18px color-mix(in srgb, var(--ct-highlight, var(--site-accent, currentColor)) 8%, transparent);
    pointer-events: none;
    z-index: 0;
  }
  /* Right-align the icon/value as a grid item (the existing rule sets
     justify-self: end / margin: 0) — the highlighted cell needs the same
     alignment, otherwise the premium `margin: 0 auto` on the icon
     centers it inside the right grid track and visually drifts off the
     icons in the other rows. */
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted .el-comparison__check,
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted .el-comparison__cross,
  .el-comparison--premium .el-comparison__table td.el-comparison__col--highlighted .el-comparison__text-value {
    justify-self: end;
    margin-left: auto;
    margin-right: 0;
    position: relative;
    z-index: 1;
  }
}

/* was @media (max-width: 480px); bucketed to mobile */
@container site style(--site-bp: mobile) {
  .el-comparison {
    --ct-icon-size: 34px;
  }

  .el-comparison__table tr {
    margin-bottom: 10px;
  }

  .el-comparison__table td {
    padding: 11px 12px !important;
    gap: 10px;
  }

  .el-comparison__table td:first-child {
    padding: 13px 12px 12px !important;
  }

  .el-comparison__table td[data-col-label]::before {
    font-size: 10.5px;
  }
}
@media (max-width: 480px) {
  .el-comparison {
    --ct-icon-size: 34px;
  }

  .el-comparison__table tr {
    margin-bottom: 10px;
  }

  .el-comparison__table td {
    padding: 11px 12px !important;
    gap: 10px;
  }

  .el-comparison__table td:first-child {
    padding: 13px 12px 12px !important;
  }

  .el-comparison__table td[data-col-label]::before {
    font-size: 10.5px;
  }
}

/* ─────────────────────────────────────────────────────────────────────────
   Marketing payload pages: brand-correct CTA buttons + tighter section
   spacing.
   The default --site-accent fallback is gold (#c9a84c) which leaks into
   any cta-band whose primaryButtonColor wasn't explicitly set. Force cyan
   on every marketing payload CTA and pair with consistent section padding.
   ───────────────────────────────────────────────────────────────────────── */




/* Vertical breathing room between sections — head-to-head, intent-router,
   feature-cards, stats etc. were stacking with no gap on /compare. */


/* Intent-router headers (eyebrow + heading + subheading) need the same
   horizontal breathing room as the cards inside. The renderer doesn't apply
   side padding to the <header>; we add it here at marketing scope. */


/* CTA-band on marketing pages: ensure the inner content card respects the
   wrapper's width so the right edge doesn't appear cut off when the band
   carries a video/image background. */



/* ── Presigned upload placeholders ────────────────────────────────────────
   Rendered by ImageRenderer / VideoRenderer while a browser-initiated
   direct-to-Spaces upload is in flight (uploadStatus='pending') or has
   failed. Styling is tokenized through --el-* / --site-* custom
   properties so theme overrides cascade correctly; no hardcoded colors.
   Shared skeleton keyframes live here because er-content.css is always
   loaded (CSS_ALWAYS_LOADED in elementCssCategories.ts). */
.el-upload-placeholder {
  position: relative;
  width: 100%;
  min-height: 200px;
  aspect-ratio: var(--el-upload-placeholder-aspect, 16 / 9);
  border-radius: var(--el-border-radius, var(--site-radius-md, 8px));
  background: var(
    --el-upload-placeholder-bg,
    var(--site-surface-muted, transparent)
  );
  color: var(--el-upload-placeholder-fg, var(--site-text-muted, currentColor));
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
  overflow: hidden;
}

.el-upload-skeleton::before {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(
    90deg,
    transparent 0%,
    var(--el-upload-shimmer, transparent) 50%,
    transparent 100%
  );
  animation: el-upload-shimmer 1.6s linear infinite;
}

@keyframes el-upload-shimmer {
  from { transform: translateX(-100%); }
  to   { transform: translateX(100%); }
}

.el-upload-placeholder__label {
  position: relative;
  z-index: 1;
  padding: 0 1rem;
  text-align: center;
  font-weight: 500;
}

.el-upload-placeholder--failed {
  background: var(
    --el-upload-failed-bg,
    var(--site-surface-muted, transparent)
  );
  color: var(--el-upload-failed-fg, var(--site-danger, currentColor));
}

/* ─────────────────────────────────────────────────────────────────────
   Stage 7A — compound-widget children migration
   stats / animated-counter / timeline thin-shell variant cascade.

   The legacy renderers wrapped items in `.el-stats / .el-animated-counter
   / .el-timeline` and applied variant modifiers to that wrapper. With the
   thin-shell + CompoundSectionRenderer model the wrapper is now
   `.el-compound-section`, so variant rules need a new hook. The thin
   shells project the chosen variant onto a `--stats-variant /
   --counter-variant / --tl-variant` CSS var on the section. Items inside
   `.el-compound-section__cards` then read those vars.

   Where the variant only changed colors / typography, the existing
   `--stats-* / --counter-* / --tl-*` var setters in the thin shell
   already cover it (the variant modifier was a convenience). The blocks
   below restore the visual treatments that were structural rather than
   stylistic (e.g. animated-counter `--cards` adds a background+border to
   each item, animated-counter `--minimal` overrides typography).
   ───────────────────────────────────────────────────────────────────── */
.el-compound-section .el-animated-counter__item,
.el-compound-section .el-stats__item,
.el-compound-section .el-timeline__item {
  /* Items inside the cards-grid inherit the parent section's --variant
     vars without us touching the existing block above. */
}

/* Animated Counter variant cascade — the cards variant adds a card chrome
   to each counter item. Hooks `--counter-variant: cards` on the section. */
.el-compound-section[style*="--counter-variant: cards"] .el-animated-counter__item,
.el-compound-section[style*="--counter-variant:cards"] .el-animated-counter__item {
  background: var(--site-bg, transparent);
  border: 1px solid var(--site-border);
  border-radius: var(--el-animated-counter-radius, 12px);
  padding: 24px 16px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.06);
}
.el-compound-section[style*="--counter-variant: minimal"] .el-animated-counter__value,
.el-compound-section[style*="--counter-variant:minimal"] .el-animated-counter__value {
  font-size: 28px;
  font-weight: 700;
}
.el-compound-section[style*="--counter-variant: minimal"] .el-animated-counter__label,
.el-compound-section[style*="--counter-variant:minimal"] .el-animated-counter__label {
  font-size: 12px;
}

/* Stats variant cascade — `--dark` paints a full-bleed band, `--brand` uses
   accent color. The wrapper-side full-bleed treatment from
   `.el-stats--dark` (line ~2443) only mattered when the wrapper itself was
   the painted band; in the new model the section wrapper handles bleed via
   its own background fields. We forward the value-color override here so
   dark/brand variants keep readable on their picked backgrounds. */
.el-compound-section[style*="--stats-variant: dark"] .el-stats__value,
.el-compound-section[style*="--stats-variant:dark"] .el-stats__value {
  color: var(--stats-value-color, currentColor);
}

/* ── Section-on-dark universal cascade ───────────────────────────────────
   When CompoundSectionRenderer detects a dark section tone it sets
   `--section-on-dark: 1` and `.el-compound-section--tone-dark`. Any child
   widget that reads one of these token fallbacks flips to the site's
   primary-fg for legibility. This is the universal fix for Stats / Intent /
   Feature-cards / Testimonials sitting on a $primary / $secondary band.  */
.el-compound-section--tone-dark {
  --stats-value-color: var(--site-primary-fg, currentColor);
  --stats-label-color: var(--site-accent, currentColor);
  --stats-accent: var(--site-accent, currentColor);
  --fc-card-title: var(--site-primary-fg, currentColor);
  --fc-card-desc: color-mix(in srgb, var(--site-primary-fg, currentColor) 82%, transparent);
  --feature-card-description-color: color-mix(in srgb, var(--site-primary-fg, currentColor) 82%, transparent);
  --rp-card-text: var(--site-primary-fg, currentColor);
  --rp-eyebrow: var(--site-accent, currentColor);
  --ir-card-text: var(--site-primary-fg, currentColor);
  --ir-card-title: var(--site-primary-fg, currentColor);
  --cs-heading-color: var(--site-primary-fg, currentColor);
  --cs-body-color: color-mix(in srgb, var(--site-primary-fg, currentColor) 82%, transparent);
}
.el-compound-section--tone-dark .el-heading,
.el-compound-section--tone-dark h1,
.el-compound-section--tone-dark h2,
.el-compound-section--tone-dark h3,
.el-compound-section--tone-dark h4 {
  color: var(--site-primary-fg, currentColor);
}
.el-compound-section--tone-dark .el-subheading,
.el-compound-section--tone-dark .el-compound-section__slot--body {
  color: color-mix(in srgb, var(--site-primary-fg, currentColor) 84%, transparent);
}
.el-compound-section[style*="--stats-variant: dark"] .el-stats__label,
.el-compound-section[style*="--stats-variant:dark"] .el-stats__label {
  color: var(--stats-label-color, var(--site-accent, currentColor));
}
.el-compound-section[style*="--stats-variant: dark"] .el-stats__prefix,
.el-compound-section[style*="--stats-variant:dark"] .el-stats__prefix,
.el-compound-section[style*="--stats-variant: dark"] .el-stats__suffix,
.el-compound-section[style*="--stats-variant:dark"] .el-stats__suffix {
  color: var(--stats-accent, var(--site-accent));
}

/* Timeline rail — each timeline-event is a sibling under
   `.el-compound-section__cards`. The rail line is drawn via the
   `.el-timeline__line` pseudo-element on each event marker (declared in
   the existing `.el-timeline--vertical/.el-timeline--horizontal` blocks
   ~line 1527). Suppress the line on the LAST event so the rail terminates
   cleanly. We use `:last-child` on the cards grid item, since each event
   is now a top-level grid child not a `.el-timeline__item` of the timeline
   wrapper. */
.el-compound-section__cards > :last-child .el-timeline__line {
  display: none;
}

/* Timeline-event ElementWrapper reset — stale inline layout props
   (display:flex / alignItems:center / flexDirection:column) on legacy
   timeline-event rows collapse the event to content-width and misalign the
   rail. The rail layout is structural, not user-configurable, so pin the
   wrapper to a block-level, full-width, left-aligned box inside any timeline
   compound-section. !important is required to beat the inline styles. */
.el-compound-section[style*="--tl-layout: vertical"] .el-compound-section__cards > .el--timeline-event,
.el-compound-section[style*="--tl-layout:vertical"] .el-compound-section__cards > .el--timeline-event {
  display: block !important;
  width: 100% !important;
  align-items: stretch !important;
  justify-content: flex-start !important;
  flex-direction: row !important;
  text-align: left;
}

/* Vertical timeline default for events rendered under .el-compound-section
   (no .el-timeline--vertical wrapper class anymore). Hooks the new
   `--tl-layout` var. */
.el-compound-section[style*="--tl-layout: vertical"] .el-timeline__item,
.el-compound-section[style*="--tl-layout:vertical"] .el-timeline__item {
  display: grid;
  grid-template-columns: var(--tl-dot-size, 14px) 1fr;
  column-gap: clamp(16px, 2vw, 24px);
  align-items: start;
}
.el-compound-section[style*="--tl-layout: vertical"] .el-timeline__marker,
.el-compound-section[style*="--tl-layout:vertical"] .el-timeline__marker {
  display: flex;
  flex-direction: column;
  align-items: center;
  position: relative;
  min-height: 100%;
  padding-top: 6px;
}
.el-compound-section[style*="--tl-layout: vertical"] .el-timeline__dot,
.el-compound-section[style*="--tl-layout:vertical"] .el-timeline__dot {
  width: var(--tl-dot-size, 14px);
  height: var(--tl-dot-size, 14px);
  border-radius: 50%;
  background: var(--tl-dot, var(--tl-accent, var(--site-accent, var(--site-primary))));
  box-shadow:
    0 0 0 4px color-mix(in srgb, var(--tl-dot, var(--tl-accent, var(--site-accent, var(--site-primary)))) 18%, transparent),
    0 0 0 1px color-mix(in srgb, var(--tl-dot, var(--tl-accent, var(--site-accent, var(--site-primary)))) 40%, transparent);
  flex-shrink: 0;
  z-index: 1;
}
.el-compound-section[style*="--tl-layout: vertical"] .el-timeline__line,
.el-compound-section[style*="--tl-layout:vertical"] .el-timeline__line {
  flex: 1;
  width: var(--tl-line-w, 2px);
  background: var(--tl-line, var(--site-border));
  margin-top: 6px;
}
.el-compound-section[style*="--tl-layout: vertical"] .el-timeline__content,
.el-compound-section[style*="--tl-layout:vertical"] .el-timeline__content {
  padding-bottom: clamp(28px, 3vw, 48px);
  padding-top: 0;
}
.el-compound-section[style*="--tl-layout: vertical"] .el-timeline__date,
.el-compound-section[style*="--tl-layout:vertical"] .el-timeline__date {
  display: inline-block;
  font-size: var(--tl-date-size, 0.75rem);
  font-weight: 600;
  color: var(--tl-date, var(--site-accent-on-light, var(--site-accent, var(--site-primary))));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 0.5rem;
}
.el-compound-section[style*="--tl-layout: vertical"] .el-timeline__title,
.el-compound-section[style*="--tl-layout:vertical"] .el-timeline__title {
  font-family: var(--site-font-heading);
  font-size: var(--tl-title-size, 1.25rem);
  font-weight: var(--tl-title-weight, 700);
  line-height: 1.25;
  color: var(--tl-title, var(--site-text));
  margin: 0 0 0.5rem;
}
.el-compound-section[style*="--tl-layout: vertical"] .el-timeline__description,
.el-compound-section[style*="--tl-layout:vertical"] .el-timeline__description {
  color: var(--tl-desc, var(--site-text-secondary));
  font-size: var(--tl-desc-size, 0.9375rem);
  line-height: var(--tl-desc-lh, 1.65);
  max-width: 68ch;
}

/* Last event in a vertical rail — no trailing padding below content */
.el-compound-section[style*="--tl-layout: vertical"] .el-compound-section__cards > :last-child .el-timeline__content,
.el-compound-section[style*="--tl-layout:vertical"] .el-compound-section__cards > :last-child .el-timeline__content {
  padding-bottom: 0;
}

/* Vertical timeline cards grid — force single-column flow with comfortable
   rhythm between events. The thin-shell sets --cs-grid-columns:1 already;
   this enforces the row-gap in case a consumer overrides the grid. */
.el-compound-section[style*="--tl-layout: vertical"] .el-compound-section__cards,
.el-compound-section[style*="--tl-layout:vertical"] .el-compound-section__cards {
  display: grid;
  grid-template-columns: 1fr;
  /* Reset the cards-grid default `grid-auto-rows: 1fr` (set on
     `.el-compound-section__cards` for equal-height card grids) — for a
     vertical timeline each event must size to its own content. Without this
     every row stretches to the height of the tallest event and short
     events get padded with blank vertical space, which reads as "too much
     padding between numbered items". */
  grid-auto-rows: auto;
  row-gap: 0;
}

/* Horizontal timeline — events sit in the cards grid in row order, so the
   parent already lays them out. Per-event marker layout adapts. */
.el-compound-section[style*="--tl-layout: horizontal"] .el-timeline__item,
.el-compound-section[style*="--tl-layout:horizontal"] .el-timeline__item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
}
.el-compound-section[style*="--tl-layout: horizontal"] .el-timeline__marker,
.el-compound-section[style*="--tl-layout:horizontal"] .el-timeline__marker {
  display: flex;
  flex-direction: row;
  align-items: center;
  width: 100%;
  margin-bottom: 1rem;
}
.el-compound-section[style*="--tl-layout: horizontal"] .el-timeline__dot,
.el-compound-section[style*="--tl-layout:horizontal"] .el-timeline__dot {
  width: var(--tl-dot-size, 14px);
  height: var(--tl-dot-size, 14px);
  border-radius: 50%;
  background: var(--tl-dot, var(--tl-accent, var(--site-accent, var(--site-primary))));
  box-shadow:
    0 0 0 4px color-mix(in srgb, var(--tl-dot, var(--tl-accent, var(--site-accent, var(--site-primary)))) 18%, transparent),
    0 0 0 1px color-mix(in srgb, var(--tl-dot, var(--tl-accent, var(--site-accent, var(--site-primary)))) 40%, transparent);
  flex-shrink: 0;
  z-index: 1;
}
.el-compound-section[style*="--tl-layout: horizontal"] .el-timeline__line,
.el-compound-section[style*="--tl-layout:horizontal"] .el-timeline__line {
  flex: 1;
  height: var(--tl-line-w, 2px);
  background: var(--tl-line, var(--site-border));
}
.el-compound-section[style*="--tl-layout: horizontal"] .el-timeline__date,
.el-compound-section[style*="--tl-layout:horizontal"] .el-timeline__date {
  display: inline-block;
  font-size: var(--tl-date-size, 0.75rem);
  font-weight: 600;
  color: var(--tl-date, var(--site-accent-on-light, var(--site-accent, var(--site-primary))));
  letter-spacing: 0.12em;
  text-transform: uppercase;
  margin-bottom: 0.375rem;
}
.el-compound-section[style*="--tl-layout: horizontal"] .el-timeline__title,
.el-compound-section[style*="--tl-layout:horizontal"] .el-timeline__title {
  font-family: var(--site-font-heading);
  font-size: var(--tl-title-size, 1.125rem);
  font-weight: var(--tl-title-weight, 700);
  line-height: 1.3;
  color: var(--tl-title, var(--site-text));
  margin: 0 0 0.5rem;
}
.el-compound-section[style*="--tl-layout: horizontal"] .el-timeline__description,
.el-compound-section[style*="--tl-layout:horizontal"] .el-timeline__description {
  color: var(--tl-desc, var(--site-text-secondary));
  font-size: var(--tl-desc-size, 0.9375rem);
  line-height: var(--tl-desc-lh, 1.6);
}

/* ── Timeline with media holder ─────────────────────────────────────────
   Universal media holder beside the timeline rail. Activated by the
   renderer when `mediaPosition` is left/right/top/bottom AND a media URL
   is set. Authoring controls live on the timeline element design panel
   (mediaPosition / mediaWidth / mediaHeight / mediaSticky / mediaAspectRatio
   / mediaObjectFit / mediaObjectPosition / mediaRadius / mediaShadow*).

   Layout: a 2-track grid inside `.el-timeline-with-media__body`. Heading +
   body sit above on a single track via the existing
   `.el-compound-section__content` wrapper. The variant class
   (`--left/--right/--top/--bottom`) flips track order; below 768px every
   variant collapses to a single column with media first so mobile reads
   media-then-rail consistently. */
.el-timeline-with-media__inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(2rem, 4vw, 3.5rem);
  align-items: start;
  padding-inline: var(--cs-inner-padding-inline, clamp(1.25rem, 4vw, 3rem));
}
.el-timeline-with-media__header {
  width: 100%;
}
.el-timeline-with-media__body {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.5rem);
  /* Stretch so the media lane runs the full height of the timeline rail —
     the inner `__media-frame` then sits inside that lane (sticky / centered)
     instead of dictating the row height itself. */
  align-items: stretch;
  width: 100%;
}
/* Media column is CAPPED at `--tl-media-width` (default 40%) — never auto.
   Without the cap, the inner image's intrinsic width (e.g. 1200px) would
   blow past the requested column width and force a giant sticky holder. */
.el-timeline-with-media--right .el-timeline-with-media__body {
  grid-template-columns: minmax(0, 1fr) minmax(0, min(var(--tl-media-width, 40%), 100%));
}
.el-timeline-with-media--left .el-timeline-with-media__body {
  grid-template-columns: minmax(0, min(var(--tl-media-width, 40%), 100%)) minmax(0, 1fr);
}
.el-timeline-with-media--right .el-timeline-with-media__rail { order: 1; }
.el-timeline-with-media--right .el-timeline-with-media__media { order: 2; }
.el-timeline-with-media--left .el-timeline-with-media__media { order: 1; }
.el-timeline-with-media--left .el-timeline-with-media__rail { order: 2; }

.el-timeline-with-media--top .el-timeline-with-media__body,
.el-timeline-with-media--bottom .el-timeline-with-media__body {
  grid-template-columns: minmax(0, 1fr);
}
.el-timeline-with-media--top .el-timeline-with-media__media { order: 1; }
.el-timeline-with-media--top .el-timeline-with-media__rail { order: 2; }
.el-timeline-with-media--bottom .el-timeline-with-media__rail { order: 1; }
.el-timeline-with-media--bottom .el-timeline-with-media__media { order: 2; }

/* Outer media lane — fills the full height of the timeline rail (via the
   parent `align-items: stretch`). Acts as the sticky positioning context
   so the inner frame can pin to the top of the lane while scrolling
   through the rail. */
.el-timeline-with-media__media {
  position: relative;
  width: 100%;
  max-width: 100%;
  min-width: 0;
  /* Stretch lets the lane run from the first event to the last — the frame
     inside is sized independently. */
  height: 100%;
}
/* Inner frame — the actual sized box that holds the image/video.
   Behavior is driven by the `--behavior-{sticky|fill|static}` modifier on
   the section root. Aspect-ratio + radius + shadow live here, not on the
   lane, so the lane can stretch without distorting the image. */
.el-timeline-with-media__media-frame {
  width: 100%;
  height: var(--tl-media-height, auto);
  aspect-ratio: var(--tl-media-aspect, 16 / 10);
  border-radius: var(--tl-media-radius, 16px);
  overflow: hidden;
  box-shadow: var(--tl-media-shadow, var(--el-media-shadow, none));
  background: color-mix(in srgb, var(--site-text) 4%, transparent);
}
/* Sticky (default) — frame pins to the top of the lane while the rail
   scrolls past. Top offset clears a typical 80px global header. */
.el-timeline-with-media--behavior-sticky .el-timeline-with-media__media-frame {
  position: sticky;
  top: clamp(80px, 12vh, 120px);
}
/* Fill — frame stretches to the full height of the lane (i.e. the
   timeline rail). Drops the aspect ratio so the lane drives height; the
   image inside still fills via object-fit. Authors who want a different
   height in fill mode set Media Holder Height explicitly. */
.el-timeline-with-media--behavior-fill .el-timeline-with-media__media-frame {
  position: relative;
  height: var(--tl-media-height, 100%);
  aspect-ratio: auto;
}
/* Static — frame scrolls with the rail at its authored size. */
.el-timeline-with-media--behavior-static .el-timeline-with-media__media-frame {
  position: relative;
}
/* When the holder is positioned above/below the rail it spans the full
   row, so the sticky behavior + portrait aspect would force an awkward
   tall block. Switch to a wide aspect and drop the sticky pin regardless
   of the chosen behavior — sticky has no anchor outside a 2-track row. */
.el-timeline-with-media--top .el-timeline-with-media__media-frame,
.el-timeline-with-media--bottom .el-timeline-with-media__media-frame {
  position: static;
  aspect-ratio: var(--tl-media-aspect, 16 / 9);
}
.el-timeline-with-media__img,
.el-timeline-with-media__player,
.el-timeline-with-media__media-frame video,
.el-timeline-with-media__media-frame img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: var(--tl-media-fit, cover);
  object-position: var(--tl-media-focal, center);
}
/* HlsPlayer ships its own wrapper with `position: relative`; ensure it
   stretches to fill the inner frame. */
.el-timeline-with-media__media-frame > * {
  width: 100%;
  height: 100%;
}

@container site style(--site-bp: mobile) {
  /* Every variant collapses to single column on mobile. Media renders
     after the rail so the process reads in sequence before the supporting
     image. */
  .el-timeline-with-media--right .el-timeline-with-media__body,
  .el-timeline-with-media--left .el-timeline-with-media__body {
    grid-template-columns: minmax(0, 1fr);
  }
  .el-timeline-with-media__rail {
    order: 1;
  }
  .el-timeline-with-media__media {
    height: auto;
    order: 2;
  }
  /* Mobile collapses to single column — sticky/fill have no rail to track
     against, so always render static at the requested aspect. The image
     fills the full viewport width: zero inline padding around the inner
     wrap, zero radius on the frame, drop the holder width cap, and let
     the image stretch edge-to-edge. Authors who want a contained look
     can still set `mediaRadius` / `siteContainerWidth` per element. */
  .el-timeline-with-media__inner {
    padding-inline: 0;
  }
  .el-timeline-with-media__media-frame {
    position: static;
    height: var(--tl-media-height, auto);
    aspect-ratio: var(--tl-media-aspect, 16 / 9);
    border-radius: 0;
    box-shadow: none;
  }
  /* `--tl-media-width` defaults to 40% so the lane is narrow on desktop;
     drop the cap on mobile so the image holder runs the full row width. */
  .el-timeline-with-media__media {
    --tl-media-width: 100%;
    width: 100%;
    max-width: 100%;
  }
  .el-timeline-with-media__rail {
    order: 2;
  }
  /* Tighter card-content rhythm so the rail keeps reading native on
     narrow viewports — matches the rest of the carousel/card mobile
     defaults shipped in Group B. */
  .el-timeline--vertical .el-timeline__content {
    padding-bottom: var(--tl-content-padding, 1.5rem);
  }
  /* Clamp horizontal padding on the timeline section so author-set
     desktop padding (e.g. 80px) doesn't squeeze the rail/text into
     ~50% of the viewport at mobile widths. The `.el > :not(style)`
     universal applies `--el-padding` to the section; we keep its block
     value but force inline to a small gutter so the rail and body
     copy can use near-full content width. */
  .el.el--timeline > .el-compound-section.el-timeline-with-media {
    padding-inline: clamp(16px, 4vw, 24px) !important;
  }
}
@media (max-width: 768px) {
  /* Every variant collapses to single column on mobile. Media renders
     after the rail so the process reads in sequence before the supporting
     image. */
  .el-timeline-with-media--right .el-timeline-with-media__body,
  .el-timeline-with-media--left .el-timeline-with-media__body {
    grid-template-columns: minmax(0, 1fr);
  }
  .el-timeline-with-media__rail {
    order: 1;
  }
  .el-timeline-with-media__media {
    height: auto;
    order: 2;
  }
  /* Mobile collapses to single column — sticky/fill have no rail to track
     against, so always render static at the requested aspect. The image
     fills the full viewport width: zero inline padding around the inner
     wrap, zero radius on the frame, drop the holder width cap, and let
     the image stretch edge-to-edge. Authors who want a contained look
     can still set `mediaRadius` / `siteContainerWidth` per element. */
  .el-timeline-with-media__inner {
    padding-inline: 0;
  }
  .el-timeline-with-media__media-frame {
    position: static;
    height: var(--tl-media-height, auto);
    aspect-ratio: var(--tl-media-aspect, 16 / 9);
    border-radius: 0;
    box-shadow: none;
  }
  /* `--tl-media-width` defaults to 40% so the lane is narrow on desktop;
     drop the cap on mobile so the image holder runs the full row width. */
  .el-timeline-with-media__media {
    --tl-media-width: 100%;
    width: 100%;
    max-width: 100%;
  }
  .el-timeline-with-media__rail {
    order: 2;
  }
  /* Tighter card-content rhythm so the rail keeps reading native on
     narrow viewports — matches the rest of the carousel/card mobile
     defaults shipped in Group B. */
  .el-timeline--vertical .el-timeline__content {
    padding-bottom: var(--tl-content-padding, 1.5rem);
  }
  /* Clamp horizontal padding on the timeline section so author-set
     desktop padding (e.g. 80px) doesn't squeeze the rail/text into
     ~50% of the viewport at mobile widths. The `.el > :not(style)`
     universal applies `--el-padding` to the section; we keep its block
     value but force inline to a small gutter so the rail and body
     copy can use near-full content width. */
  .el.el--timeline > .el-compound-section.el-timeline-with-media {
    padding-inline: clamp(16px, 4vw, 24px) !important;
  }
}

/* ══════════════════════════════════════════════════════════════
   2026 Universal Contracts — typography, media, quote chrome
   ══════════════════════════════════════════════════════════════
   These tokens ship site-wide defaults that every renderer inherits.
   Any element can override by setting the corresponding --site-* or
   --el-* CSS var on a parent scope. DO NOT hardcode values below in
   renderers — always go through the tokens. */

:where(:root, .el-site-root) {
  /* Typography scale — single source of truth for display/h1..h6.
     Renderers should apply via the .el-heading--{display|h1..h6}
     class hooks below, never by setting fontSize inline. */
  --site-heading-display-size: clamp(2.75rem, 5.5vw, 4.5rem);
  --site-heading-display-tracking: -0.04em;
  --site-heading-h1-size: clamp(2rem, 4vw, 3rem);
  --site-heading-h1-tracking: -0.03em;
  --site-heading-h2-size: clamp(1.625rem, 3vw, 2.25rem);
  --site-heading-h2-tracking: -0.02em;
  --site-heading-h3-size: clamp(1.25rem, 2.2vw, 1.625rem);
  --site-heading-h3-tracking: -0.015em;
  --site-heading-h4-size: 1.125rem;
  --site-heading-h4-tracking: -0.01em;
  --site-heading-h5-size: 1rem;
  --site-heading-h5-tracking: 0;
  --site-heading-h6-size: 0.875rem;
  --site-heading-h6-tracking: 0.02em;
  --site-heading-line: 1.15;
  --site-heading-weight: 700;

  /* Eyebrow / subheading contract — applied to anything uppercase-tracked. */
  --site-eyebrow-size: 0.72rem;
  --site-eyebrow-tracking: 0.18em;
  --site-eyebrow-weight: 800;
  --site-eyebrow-transform: uppercase;
  --site-subheading-size: 1.0625rem;
  --site-subheading-line: 1.55;
  --site-subheading-weight: 500;

  /* Media aspect ratios — applied via .el-media--{variant} classes.
     Override at any scope: `--site-media-aspect-card: 1 / 1`, etc.
     These :root values are CSS-only fallbacks used when ThemeProvider is
     not in the tree (e.g. plain template previews). When ThemeProvider
     is present, the values from src/lib/themeContract.ts win — see
     SKILL.md § Media Aspect Ratio Contract. */
  --site-media-aspect-hero: 21 / 9;
  --site-media-aspect-wide: 21 / 9;
  --site-media-aspect-card: 4 / 3;
  --site-media-aspect-portrait: 4 / 5;
  --site-media-aspect-square: 1 / 1;
  --site-media-aspect-story: 9 / 16;
  --site-media-aspect-landscape: 16 / 10;
  --site-media-aspect-video: 16 / 9;
  --site-media-aspect-cinematic: 2.4 / 1;
}

/* ── Universal heading scale (opt-in via class hooks) ──────── */
.el-heading--display,
:where(h1, h2, h3, h4, h5, h6).el-heading--display {
  font-size: var(--site-heading-display-size);
  letter-spacing: var(--site-heading-display-tracking);
  line-height: var(--site-heading-line);
  font-weight: var(--site-heading-weight);
  font-family: var(--site-font-heading, inherit);
}
.el-heading--h1 { font-size: var(--site-heading-h1-size); letter-spacing: var(--site-heading-h1-tracking); line-height: var(--site-heading-line); font-weight: var(--site-heading-weight); font-family: var(--site-font-heading, inherit); }
.el-heading--h2 { font-size: var(--site-heading-h2-size); letter-spacing: var(--site-heading-h2-tracking); line-height: var(--site-heading-line); font-weight: var(--site-heading-weight); font-family: var(--site-font-heading, inherit); }
.el-heading--h3 { font-size: var(--site-heading-h3-size); letter-spacing: var(--site-heading-h3-tracking); line-height: 1.25; font-weight: var(--site-heading-weight); font-family: var(--site-font-heading, inherit); }
.el-heading--h4 { font-size: var(--site-heading-h4-size); letter-spacing: var(--site-heading-h4-tracking); line-height: 1.3; font-weight: var(--site-heading-weight); font-family: var(--site-font-heading, inherit); }
.el-heading--h5 { font-size: var(--site-heading-h5-size); letter-spacing: var(--site-heading-h5-tracking); line-height: 1.35; font-weight: 600; font-family: var(--site-font-heading, inherit); }
.el-heading--h6 { font-size: var(--site-heading-h6-size); letter-spacing: var(--site-heading-h6-tracking); line-height: 1.4; font-weight: 600; font-family: var(--site-font-heading, inherit); }

/* Eyebrow — uppercase, letterspaced label used above headings.
   Many renderers currently inline these styles. Replace with this class. */
.el-eyebrow {
  font-size: var(--site-eyebrow-size);
  letter-spacing: var(--site-eyebrow-tracking);
  font-weight: var(--site-eyebrow-weight);
  text-transform: var(--site-eyebrow-transform);
  color: var(--el-eyebrow-color, var(--site-accent, currentColor));
  font-family: var(--site-font-heading, inherit);
  overflow-wrap: break-word;
  word-break: break-word;
}

/* Subheading — token-driven supporting copy under headings. */
.el-subheading {
  font-size: var(--site-subheading-size);
  line-height: var(--site-subheading-line);
  font-weight: var(--site-subheading-weight);
  color: var(--el-subheading-color, var(--site-text-secondary, currentColor));
  font-family: var(--site-font-body, inherit);
  overflow-wrap: break-word;
}

/* ── Universal media alignment ─────────────────────────────────
   Apply via class; wraps any <img>, <video>, or <picture> child.
   Guarantees consistent aspect ratio + object-fit across widgets.
   Override per-site with --site-media-aspect-* tokens. */
.el-media {
  display: block;
  width: 100%;
  max-width: 100%;
  overflow: hidden;
  background: var(--el-bg, var(--el-media-placeholder-bg, var(--site-surface-alt, transparent)));
  border-radius: var(--el-media-radius, var(--site-radius-card, var(--site-radius, 12px)));
}
.el-media > img,
.el-media > video,
.el-media > picture,
.el-media > picture > img {
  width: 100%;
  height: 100%;
  display: block;
  object-fit: cover;
  object-position: var(--el-media-position, center);
}
.el-media--contain > img,
.el-media--contain > video,
.el-media--contain > picture > img { object-fit: contain; background: transparent; }
.el-media--hero { aspect-ratio: var(--site-media-aspect-hero); }
.el-media--wide { aspect-ratio: var(--site-media-aspect-wide); }
.el-media--card { aspect-ratio: var(--site-media-aspect-card); }
.el-media--portrait { aspect-ratio: var(--site-media-aspect-portrait); }
.el-media--square { aspect-ratio: var(--site-media-aspect-square); }
.el-media--story { aspect-ratio: var(--site-media-aspect-story); }
/* Non-card media aspect contract — preset variants. See
   SITE_MEDIA_ASPECT_PRESETS in src/lib/elements/responsiveDefaults.ts. */
.el-media--landscape { aspect-ratio: var(--site-media-aspect-landscape); }
.el-media--video { aspect-ratio: var(--site-media-aspect-video); }
.el-media--cinematic { aspect-ratio: var(--site-media-aspect-cinematic); }
.el-media--logo { aspect-ratio: auto; background: transparent; }
.el-media--logo > img,
.el-media--logo > picture > img { object-fit: contain; height: auto; }

/* ── Quote / testimonial chrome — universal ───────────────────
   Any card-style quote widget gets a decorative opening glyph
   and shared typographic posture. Applied via .el-has-quote-chrome
   or directly on the existing element classes. Token-driven color
   so dark/light themes both read cleanly. */
.el-blockquote::before,
.el-review-card::before,
.el-pull-quote::before,
.el-quote-block::before,
.el-has-quote-chrome::before {
  content: '\201C';
  position: absolute;
  top: var(--quote-chrome-top, -0.35em);
  left: var(--quote-chrome-left, 0.35em);
  font-family: var(--quote-chrome-font, 'Georgia', 'Times New Roman', serif);
  font-size: var(--quote-chrome-size, 4.5rem);
  line-height: 1;
  color: var(--quote-chrome-color, var(--site-accent, var(--site-primary, currentColor)));
  opacity: var(--quote-chrome-opacity, 0.22);
  pointer-events: none;
  font-weight: 900;
}
.el-review-card,
.el-pull-quote,
.el-quote-block,
.el-has-quote-chrome { position: relative; }
/* Blockquote already has position: relative from earlier block */
.el-pull-quote,
.el-quote-block {
  background: var(--el-bg, var(--quote-card-bg, var(--site-surface, transparent)));
  border-radius: var(--quote-card-radius, var(--site-radius-card, var(--site-radius, 12px)));
  --el-padding-default: var(--quote-card-padding, 2rem 2rem 1.5rem);
  box-shadow: var(--quote-card-shadow, var(--site-shadow-card, 0 2px 12px rgba(0,0,0,0.06)));
  border: 1px solid var(--quote-card-border, var(--site-border, transparent));
}

/* ── Pricing billing-frequency toggle (Phase 2 #8) ─────────────────
   Universal toggle UI emitted by PricingBillingProvider when the parent
   pricing-table has `billingToggle: true`. All visuals derive from
   --site-* tokens. */
.el-pricing-billing-toggle {
  /* All --pbt-* vars are emitted by PricingTableRenderer when billingToggle
     is on (per renderer-var coverage contract). CSS only consumes them. */
  display: inline-flex;
  align-items: stretch;
  gap: 4px;
  --el-padding-default: 4px;
  margin: 0 auto clamp(1.25rem, 2.5vw, 2rem);
  border: 1px solid var(--pbt-border);
  border-radius: 999px;
  background: var(--el-bg, var(--pbt-bg));
  backdrop-filter: blur(var(--site-glass-blur, 20px));
  -webkit-backdrop-filter: blur(var(--site-glass-blur, 20px));
}
.el-pricing-billing-toggle__btn {
  appearance: none;
  -webkit-appearance: none;
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 1.25rem;
  border: 0;
  border-radius: 999px;
  background: transparent;
  color: color-mix(in srgb, currentColor 65%, transparent);
  font: inherit;
  font-size: 13px;
  font-weight: 600;
  cursor: pointer;
  transition: background 200ms ease, color 200ms ease, box-shadow 250ms ease;
}
.el-pricing-billing-toggle__btn:hover:not(.el-pricing-billing-toggle__btn--active) {
  color: color-mix(in srgb, currentColor 85%, transparent);
  background: color-mix(in srgb, currentColor 5%, transparent);
}
.el-pricing-billing-toggle__btn--active {
  background: var(--pbt-active-bg);
  color: var(--pbt-active-fg);
  box-shadow: 0 6px 18px color-mix(in srgb, var(--pbt-active-bg) 30%, transparent);
}
.el-pricing-billing-toggle__hint {
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  padding: 2px 8px;
  border-radius: 999px;
  background: color-mix(in srgb, currentColor 18%, transparent);
}
.el-pricing-billing-toggle__btn--active .el-pricing-billing-toggle__hint {
  background: color-mix(in srgb, var(--pbt-active-fg) 18%, transparent);
  color: var(--pbt-active-fg);
}

/* Dual price slots — show one based on the parent tier's data-billing attr */
.el-pricing-card__price-wrap--dual {
  display: grid;
}
.el-pricing-card__price-wrap--dual > .el-pricing-card__price-slot {
  grid-area: 1 / 1;
  display: flex;
  align-items: baseline;
  gap: 0.5rem;
  opacity: 0;
  transform: translateY(-2px);
  transition: opacity 220ms ease, transform 220ms ease;
  pointer-events: none;
}
.el--pricing-tier[data-billing="monthly"] .el-pricing-card__price-slot--monthly,
.el--pricing-tier[data-billing="annual"] .el-pricing-card__price-slot--annual,
.el-pricing-card__plan[data-billing="monthly"] .el-pricing-card__price-slot--monthly,
.el-pricing-card__plan[data-billing="annual"] .el-pricing-card__price-slot--annual {
  opacity: 1;
  transform: translateY(0);
  pointer-events: auto;
}
.el-pricing-card__price-value {
  font-family: var(--site-font-heading);
  font-size: 3.5rem;
  font-weight: 800;
  color: var(--pc-price, var(--site-text));
  line-height: 1;
  font-variant-numeric: tabular-nums;
}
.el-pricing-card__price-period {
  font-size: 0.9375rem;
  color: var(--pc-period, var(--site-text-muted));
}

/* ── Card Hover Contract: batch 1 — accordion / amenity-grid / blog-post-content / blog-post-list / contact-section / content-slider ───────────── */
/* Wires CARD_HOVER_FIELDS for blog-post-content (--bpc-hover-*),
   blog-post-list (--bpl-hover-*), and content-slider (--csl-hover-*). Vars
   come from extractCardHoverCssVars() in src/lib/elements/cardHoverVars.ts;
   CSS chains var(--scope-hover-X, existing-fallback) so unset values do
   not change current visuals. The bpl rule uses a descendant-boost selector
   (.el-blog-post-list .el-blog-post-list__card:hover) to layer on top of
   the existing --blog-card-hover-* rule without editing it. */
[data-card-hover-shell]:hover .el-blog-post-content {
  background: var(--bpc-hover-bg, transparent);
  color: var(--bpc-hover-color, inherit);
  border-color: var(--bpc-hover-border-color, transparent);
  box-shadow: var(--bpc-hover-shadow, none);
  transform: translateY(calc(var(--bpc-hover-lift, 0px) * -1));
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.25s ease, transform 0.25s ease;
}
[data-card-hover-shell]:hover .el-blog-post-list .el-blog-post-list__card,
.el-blog-post-list .el-blog-post-list__card:hover {
  background: var(--bpl-hover-bg, var(--blog-card-hover-bg, var(--blog-card-bg, var(--site-surface, transparent))));
  color: var(--bpl-hover-color, inherit);
  border-color: var(--bpl-hover-border-color, var(--blog-card-hover-border-color,
    color-mix(in srgb, var(--site-accent, currentColor) 55%, transparent)));
  box-shadow: var(--bpl-hover-shadow, var(--blog-card-hover-shadow,
    0 8px 24px rgba(0, 0, 0, 0.12)));
  transform: translateY(calc(var(--bpl-hover-lift, var(--blog-card-hover-lift, 2px)) * -1));
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.25s ease, transform 0.25s ease;
}
[data-card-hover-shell]:hover .el-content-slider .el-content-slider__slide,
.el-content-slider .el-content-slider__slide:hover {
  background: var(--csl-hover-bg, var(--cs-card-bg, var(--site-bg-secondary, transparent)));
  color: var(--csl-hover-color, inherit);
  border-color: var(--csl-hover-border-color, transparent);
  box-shadow: var(--csl-hover-shadow, var(--cs-card-shadow,
    0 1px 3px rgba(0, 0, 0, calc(0.04 * var(--csl-hover-glow-opacity, 1))),
    0 4px 16px rgba(0, 0, 0, calc(0.05 * var(--csl-hover-glow-opacity, 1)))));
  transform: translateY(calc(var(--csl-hover-lift, 0px) * -1));
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.25s ease, transform 0.25s ease;
}

/* ── Card Hover Contract: batch 2 — floor-plan-viewer / form ───────────── */
/* See SKILL_REFERENCE.md § Card Hover Contract. Every hover property chains
   the builder-set `--<scope>-hover-*` override (emitted by
   extractCardHoverCssVars) → an accent-derived default. */

.el-floor-plan-viewer__card {
  transition: transform 0.2s ease, background 0.2s ease, color 0.2s ease,
              border-color 0.2s ease, box-shadow 0.25s ease;
}
[data-card-hover-shell]:hover .el-floor-plan-viewer__card {
  transform: translateY(calc(var(--fpv-card-hover-lift, 4px) * -1));
  background: var(--fpv-card-hover-bg, var(--site-surface-alt, transparent));
  color: var(--fpv-card-hover-color, inherit);
  border-color: var(--fpv-card-hover-border-color,
    color-mix(in srgb, var(--site-accent, currentColor) 45%, transparent));
  box-shadow: var(--fpv-card-hover-shadow,
    0 4px 8px rgba(0, 0, 0, calc(0.08 * var(--fpv-card-hover-glow-opacity, 1))),
    0 14px 44px rgba(0, 0, 0, calc(0.14 * var(--fpv-card-hover-glow-opacity, 1))));
}

.el--form.el--top-level {
  padding: clamp(56px, 7vw, 96px) var(--site-content-gutter, 24px);
  background: var(--site-surface-alt, color-mix(in srgb, var(--site-surface, transparent), var(--site-text, currentColor) 4%));
}
/* Nested form widget: cap the WRAPPER at the same max-width as the renderer
   card so the wrapper bg (painted from --el-bg via the .el bridge) doesn't
   extend past the card and show as a square-cornered band on either side.
   Top-level forms (own-section banded layout) keep their full-bleed surface
   via the .el--top-level rule above. */
:where(.el .el).el--form {
  max-width: var(--el-form-max-width, 920px);
  margin-inline: auto;
}
.el-form {
  width: min(var(--el-form-max-width, 920px), 100%);
  margin-inline: auto;
  --el-padding-default: clamp(28px, 4vw, 48px);
  background: var(--site-card-bg, var(--site-surface, transparent));
  color: var(--site-text);
  border: 1px solid var(--site-border, transparent);
  border-radius: var(--site-card-radius, 18px);
  box-shadow: var(--site-shadow-card, 0 18px 60px rgba(15, 23, 42, 0.10));
  transition: transform 0.2s ease, background 0.2s ease, color 0.2s ease,
              border-color 0.2s ease, box-shadow 0.25s ease;
}
.el-form__heading {
  margin: 0;
  color: var(--site-heading, var(--site-text));
  font-family: var(--site-font-heading);
  font-size: clamp(1.75rem, 3vw, 2.5rem);
  line-height: 1.12;
  text-align: center;
}
.el-form__subheading {
  max-width: 680px;
  margin: 0.75rem auto 2rem;
  color: var(--site-text-secondary, var(--site-text));
  font-size: 1rem;
  line-height: 1.65;
  text-align: center;
}
.el-form__form {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 1rem;
}
.el-form__field,
.el-form__field--row-full,
.el-form__submit,
.el-form__error,
.el-form__success,
.el-form__unconfigured {
  grid-column: 1 / -1;
}
.el-form__field--row-half,
.el-form__field--row-third,
.el-form__field--row-quarter {
  grid-column: span 1;
}
.el-form__label {
  display: block;
  margin-bottom: 0.4rem;
  color: var(--site-text);
  font-size: 0.875rem;
  font-weight: 700;
}
.el-form__input,
.el-form__textarea,
.el-form__select {
  width: 100%;
  min-height: 48px;
  padding: 0.875rem 1rem;
  color: var(--site-text);
  background: var(--site-surface, transparent);
  border: 1px solid var(--site-border, transparent);
  border-radius: var(--site-input-radius, 10px);
  font: inherit;
}
.el-form__textarea {
  min-height: 132px;
  resize: vertical;
}
.el-form__input:focus,
.el-form__textarea:focus,
.el-form__select:focus {
  outline: 3px solid color-mix(in srgb, var(--site-primary), transparent 76%);
  border-color: var(--site-primary);
}
.el-form__submit {
  justify-self: center;
  min-width: min(100%, 240px);
  min-height: 52px;
  padding: 0.95rem 1.5rem;
  color: var(--btn-primary-text, var(--site-btn-primary-text, var(--site-primary-fg, var(--site-text-on-primary, currentColor))));
  background: var(--btn-primary-bg, var(--site-btn-primary-bg, var(--site-primary)));
  border: 1px solid var(--btn-primary-bg, var(--site-btn-primary-bg, var(--site-primary)));
  border-radius: var(--el-btn-radius, 999px);
  font-weight: 800;
  cursor: pointer;
}
.el-form__submit:hover:not(:disabled) {
  background: var(--btn-hover-bg, var(--site-btn-primary-hover-bg, var(--site-btn-primary-bg, var(--site-primary))));
  color: var(--btn-hover-color, var(--site-btn-primary-hover-text, var(--btn-primary-text, var(--site-btn-primary-text, currentColor))));
  border-color: var(--btn-hover-border, var(--btn-hover-bg, var(--site-btn-primary-hover-bg, var(--site-primary))));
}
.el-form__submit:disabled {
  cursor: not-allowed;
  opacity: 0.62;
}
@container site style(--site-bp: mobile) {
  .el-form {
    --el-padding-default: 24px;
  }
  .el-form__form,
  .el-form__field {
    grid-column: 1 / -1;
  }
}
@media (max-width: 768px) {
  .el-form {
    --el-padding-default: 24px;
  }
  .el-form__form,
  .el-form__field {
    grid-column: 1 / -1;
  }
}
[data-card-hover-shell]:hover .el-form {
  transform: translateY(calc(var(--frm-card-hover-lift, 4px) * -1));
  background: var(--frm-card-hover-bg, transparent);
  color: var(--frm-card-hover-color, inherit);
  border-color: var(--frm-card-hover-border-color,
    color-mix(in srgb, var(--site-accent, currentColor) 45%, transparent));
  box-shadow: var(--frm-card-hover-shadow,
    0 4px 8px rgba(0, 0, 0, calc(0.06 * var(--frm-card-hover-glow-opacity, 1))),
    0 14px 44px rgba(0, 0, 0, calc(0.10 * var(--frm-card-hover-glow-opacity, 1))));
}

/* ── Card Hover Contract: batch 4 — logo-slider / pricing-card / product-detail / product-featured / product-grid / project-card / property-grid / recent-posts ───────────── */

/* CARD_HOVER_FIELDS contract — see SKILL_REFERENCE.md § Card Hover Contract.
   logo-slider — per-logo card hover state. Scope `--ls-logo-` because `--ls-`
   is reserved for location-showcase. Rests through the existing
   --logo-slider-card-bg / --logo-slider-radius chain in this file. */
.el-logo-slider .el-logo-slider__item {
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.25s ease, transform 0.25s ease;
}
[data-card-hover-shell]:hover .el-logo-slider .el-logo-slider__item,
.el-logo-slider .el-logo-slider__item:hover {
  background: var(--ls-logo-hover-bg, var(--logo-slider-card-bg, var(--site-card-bg, transparent)));
  color: var(--ls-logo-hover-color, inherit);
  border-color: var(--ls-logo-hover-border-color,
    color-mix(in srgb, var(--site-accent, currentColor) 35%, transparent));
  box-shadow: var(--ls-logo-hover-shadow,
    0 6px 18px rgba(0, 0, 0, calc(0.08 * var(--ls-logo-hover-glow-opacity, 1))));
  transform: translateY(calc(var(--ls-logo-hover-lift, 0px) * -1));
}

/* CARD_HOVER_FIELDS contract — see SKILL_REFERENCE.md § Card Hover Contract.
   pricing-card — extends the existing `--pricing-card-hover-lift` /
   `--pricing-card-hover-bg` chain with the missing color / border / shadow /
   glow vars emitted by extractCardHoverCssVars('pricing-card'). The original
   `.el-pricing-card__plan:hover` rule above already paints the lift+bg;
   this rule layers the new contract vars on top so unset values keep the
   prior visuals. */
.el-pricing-card .el-pricing-card__plan:hover {
  color: var(--pricing-card-hover-color, inherit);
  border-color: var(--pricing-card-hover-border-color,
    color-mix(in srgb, var(--site-accent, currentColor) 45%, transparent));
  box-shadow: var(--pricing-card-hover-shadow,
    0 8px 24px rgba(0, 0, 0, calc(0.08 * var(--pricing-card-hover-glow-opacity, 1))));
}

/* CARD_HOVER_FIELDS contract — see SKILL_REFERENCE.md § Card Hover Contract.
   recent-posts — per-item hover. Scope `--rcp-` (recent-posts compact)
   avoids region-portfolio `--rp-` namespace collision (eyebrow + card vars
   in er-card-containers.css) — the coverage-matrix audit's longest-prefix
   attribution would otherwise credit region-portfolio for these vars. */
.el-recent-posts .el-recent-posts__item {
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.25s ease, transform 0.25s ease;
}
[data-card-hover-shell]:hover .el-recent-posts .el-recent-posts__item,
.el-recent-posts .el-recent-posts__item:hover {
  background: var(--rcp-hover-bg, transparent);
  color: var(--rcp-hover-color, inherit);
  border-color: var(--rcp-hover-border-color,
    color-mix(in srgb, var(--site-accent, currentColor) 35%, transparent));
  box-shadow: var(--rcp-hover-shadow,
    0 4px 12px rgba(0, 0, 0, calc(0.08 * var(--rcp-hover-glow-opacity, 1))));
  transform: translateY(calc(var(--rcp-hover-lift, 0px) * -1));
}

/* ── Card Hover Contract: batch 3 — hud-income-limits / location-availability / location-search / login-form / register-form / tabs ───────────── */
/* Wires CARD_HOVER_FIELDS + CARD_SHADOW_FIELDS for register-form
   (--rf-hover-* + --rf-card-shadow). Vars come from extractCardHoverCssVars
   + resolveShadow in RegisterFormRenderer.tsx; CSS chains
   var(--rf-..., existing-fallback) so unset values do not change current
   visuals. */
.el-register-form .el-register-form__surface {
  box-shadow: var(--rf-card-shadow, var(--site-shadow-card, 0 2px 12px rgba(0,0,0,0.06)));
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.25s ease, transform 0.25s ease;
}
[data-card-hover-shell]:hover .el-register-form .el-register-form__surface,
.el-register-form .el-register-form__surface:hover {
  background: var(--rf-hover-bg, var(--site-surface, transparent));
  color: var(--rf-hover-color, inherit);
  border-color: var(--rf-hover-border-color, var(--site-border, transparent));
  box-shadow: var(--rf-hover-shadow, var(--rf-card-shadow, var(--site-shadow-card, 0 6px 24px rgba(0,0,0,0.10))));
  transform: translateY(calc(var(--rf-hover-lift, 0px) * -1));
}

/* ── Card Hover Contract: deferred — image-carousel-slide ───────────── */
/* CARD_HOVER_FIELDS contract — see SKILL_REFERENCE.md § Card Hover Contract.
   Hover controls live on the parent image-carousel definition (no per-slide
   hover surface — see definitions/sliders-carousels.ts comment on
   imageCarouselSlideElement). ImageCarouselRenderer.tsx projects vars onto
   the .el-compound-section frame; this rule consumes them via cascade on
   each .el-image-carousel__slide child. Scope 'ic-slide' chosen — no
   collision with --carousel-*, --cs-*, or any prior --ic- prefix. */
.el-image-carousel__slide {
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.25s ease, transform 0.25s ease;
}
[data-card-hover-shell]:hover .el-image-carousel__slide {
  background: var(--ic-slide-hover-bg, transparent);
  color: var(--ic-slide-hover-color, inherit);
  border-color: var(--ic-slide-hover-border-color, transparent);
  box-shadow: var(--ic-slide-hover-shadow,
    0 6px 16px rgba(0, 0, 0, calc(0.08 * var(--ic-slide-hover-glow-opacity, 1))));
  transform: translateY(calc(var(--ic-slide-hover-lift, 0px) * -1));
}

/* ── Dynamic List grid layout — consumes --dl-columns from DynamicListRenderer.tsx ───────────── */
.el-dynamic-list--grid .el-dynamic-list__container,
.el-dynamic-list--cards .el-dynamic-list__container {
  display: grid;
  grid-template-columns: repeat(var(--dl-columns, 3), minmax(min(240px, 100%), 1fr));
  gap: var(--site-section-gap, 1.5rem);
}
@container site style(--site-bp: mobile) {
  .el-dynamic-list--grid .el-dynamic-list__container,
  .el-dynamic-list--cards .el-dynamic-list__container {
    grid-template-columns: 1fr;
  }
}
@media (max-width: 768px) {
  .el-dynamic-list--grid .el-dynamic-list__container,
  .el-dynamic-list--cards .el-dynamic-list__container {
    grid-template-columns: 1fr;
  }
}

/* ── Gallery lightbox (Group D, Issue 15) ──
   Lightweight overlay that opens when a gallery image tile is clicked.
   Mounted by <GalleryLightbox /> only when the parent gallery has the
   `enableLightbox` toggle on (default true). All visuals via --site-* tokens
   so a tenant theme can recolor without forking. */
.el-gallery-lightbox-mount { position: static; }
.el-gallery-lightbox {
  position: fixed;
  inset: 0;
  z-index: 9000;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(0, 0, 0, 0.92);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  padding: clamp(8px, 3vw, 32px);
  animation: el-gallery-lightbox-fade-in 220ms ease;
  /* Center the figure responsively; nav buttons absolutely positioned. */
}
.el-gallery-lightbox--no-motion {
  animation: none;
}
@keyframes el-gallery-lightbox-fade-in {
  from { opacity: 0; transform: scale(0.98); }
  to   { opacity: 1; transform: scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  .el-gallery-lightbox { animation: none; }
}

.el-gallery-lightbox__figure {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  margin: 0;
  max-width: min(95vw, 1400px);
  max-height: 90vh;
  gap: 12px;
}
.el-gallery-lightbox__image {
  display: block;
  max-width: 100%;
  max-height: 80vh;
  width: auto;
  height: auto;
  object-fit: contain;
  border-radius: var(--site-radius-md, 6px);
  box-shadow: 0 24px 80px rgba(0, 0, 0, 0.5);
  user-select: none;
  -webkit-user-drag: none;
}
.el-gallery-lightbox__caption {
  color: rgba(255, 255, 255, 0.92);
  font-family: var(--site-font-body, system-ui, sans-serif);
  font-size: 14px;
  line-height: 1.5;
  text-align: center;
  max-width: min(80vw, 720px);
  margin: 0;
}
.el-gallery-lightbox__counter {
  position: absolute;
  top: -36px;
  left: 50%;
  transform: translateX(-50%);
  color: rgba(255, 255, 255, 0.65);
  font-family: var(--site-font-body, system-ui, sans-serif);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.06em;
}

.el-gallery-lightbox__close,
.el-gallery-lightbox__nav {
  position: absolute;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 48px;
  height: 48px;
  min-width: 44px;
  min-height: 44px;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.12);
  background: rgba(15, 23, 42, 0.6);
  color: var(--site-fg, currentColor);
  cursor: pointer;
  transition: background 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
  padding: 0;
}
.el-gallery-lightbox__close:hover,
.el-gallery-lightbox__nav:hover {
  background: rgba(15, 23, 42, 0.85);
  border-color: rgba(255, 255, 255, 0.28);
}
.el-gallery-lightbox__close:focus-visible,
.el-gallery-lightbox__nav:focus-visible {
  outline: 2px solid var(--site-accent, currentColor);
  outline-offset: 3px;
}
.el-gallery-lightbox__close {
  top: clamp(12px, 3vw, 24px);
  right: clamp(12px, 3vw, 24px);
}
.el-gallery-lightbox__nav--prev {
  left: clamp(8px, 2vw, 24px);
}
.el-gallery-lightbox__nav--next {
  right: clamp(8px, 2vw, 24px);
}
@container site style(--site-bp: mobile) {
  .el-gallery-lightbox__nav {
    width: 44px;
    height: 44px;
  }
  .el-gallery-lightbox__counter {
    top: -28px;
    font-size: 11px;
  }
  .el-gallery-lightbox__caption {
    font-size: 13px;
  }
}
@media (max-width: 768px) {
  .el-gallery-lightbox__nav {
    width: 44px;
    height: 44px;
  }
  .el-gallery-lightbox__counter {
    top: -28px;
    font-size: 11px;
  }
  .el-gallery-lightbox__caption {
    font-size: 13px;
  }
}
@media (prefers-reduced-motion: reduce) {
  .el-gallery-lightbox__close,
  .el-gallery-lightbox__nav {
    transition: none;
  }
}

/* Ensure gallery tiles read as interactive when lightbox is on. The runtime
   adds role/tabindex/aria-label, but we surface the affordance visually too
   so authors recognise it in the live site. */
[data-enable-lightbox="true"] .el-gallery__item {
  cursor: zoom-in;
}
[data-enable-lightbox="true"] .el-gallery__item:focus-visible {
  outline: 2px solid var(--site-accent, currentColor);
  outline-offset: 3px;
  border-radius: var(--cs-media-radius, 12px);
}

/* Logo Slider — brightness / contrast normalization */
.el-logo-slider__item img,
.el-logo-slider__media img {
  filter: brightness(var(--logo-slider-brightness, 100%)) contrast(var(--logo-slider-contrast, 100%));
}
.el-logo-slider--grayscale .el-logo-slider__item img,
.el-logo-slider--grayscale .el-logo-slider__media img {
  filter: grayscale(1) brightness(var(--logo-slider-brightness, 100%)) contrast(var(--logo-slider-contrast, 100%));
}

/* Logo Slider — reverse direction */
.el-logo-slider--reverse .slick-track,
.el-logo-slider--reverse .el-logo-slider__track {
  animation-direction: reverse;
}

/* Image Carousel — caption positioning */
.ic-caption { display: block; padding: 16px; }
.ic-caption[data-position="top"] { order: -1; }
.ic-caption[data-position="bottom"] { order: 1; }
.ic-caption[data-position="overlay-bottom"],
.ic-caption[data-position="overlay-top"],
.ic-caption[data-position="overlay-center"] {
  position: absolute; left: 0; right: 0; color: white;
  background: linear-gradient(180deg, transparent 0%, rgba(0,0,0,calc(var(--ic-caption-gradient-strength, 60) * 1%)) 100%);
  font-size: calc(var(--ic-caption-font-size, 18) * 1px);
  font-weight: var(--ic-caption-font-weight, 500);
}
.ic-caption[data-position="overlay-bottom"] { bottom: 0; padding-top: 60px; }
.ic-caption[data-position="overlay-top"] { top: 0; padding-bottom: 60px; background: linear-gradient(0deg, transparent 0%, rgba(0,0,0,calc(var(--ic-caption-gradient-strength, 60) * 1%)) 100%); }
.ic-caption[data-position="overlay-center"] { top: 50%; transform: translateY(-50%); background: rgba(0,0,0,calc(var(--ic-caption-gradient-strength, 60) * 0.6%)); text-align: center; }
.ic-caption > * { max-width: calc(var(--ic-caption-max-width, 720) * 1px); margin-inline: auto; }

/* Image Carousel — Ken Burns active-slide zoom. 8s base duration matches
 * the default autoplay interval so the zoom completes before the slide
 * advances. Authors can speed up via Transition Duration if needed. */
.uc .slick-active .ic-slide-img {
  animation: ic-ken-burns 8000ms ease-in-out forwards;
  transform-origin: center;
}
@keyframes ic-ken-burns {
  from { transform: scale(1); }
  to { transform: scale(calc(1 + var(--ic-kb-intensity, 0) * 0.01)); }
}

/* Content Slider — wrap-whole-card link */
a.el-content-slider__slide-link {
  display: block;
  color: inherit;
  text-decoration: none;
}
a.el-content-slider__slide-link:hover { text-decoration: none; }
a.el-content-slider__slide-link button { pointer-events: auto; }

/* Image Carousel — image fit */
.uc[data-image-fit="cover"] .slick-slide img { object-fit: cover; }
.uc[data-image-fit="contain"] .slick-slide img { object-fit: contain; }
.uc[data-image-fit="fill"] .slick-slide img { object-fit: fill; width: 100%; height: 100%; }

/* Carousel — locked aspect ratio */
.uc[data-aspect-ratio]:not([data-aspect-ratio="free"]) .slick-slide {
  aspect-ratio: var(--uc-aspect-ratio, auto);
}
