/* Fenix CMS public page styles
   Loaded by Render.cshtml. Consumes CSS variables emitted by FenixThemeStyleViewComponent. */

/* ===== Generic design-vocabulary var DEFAULTS (2026-07-19) ==============================
   Hand-authored sections (and the hbl/hpa landing kits) use a few generic vars — --accent,
   --accent-deep, --accent-hover, --sec-a, --sec-b, --c-tint — that SOME theme bridges define
   in their extraCss and others don't. A page built under a theme that defines them broke (blank
   accent cards, white-on-white bands) when SWITCHED to a theme that doesn't (e.g. Blush2 44).
   Alias them to the standard --c-* / --fenix-color-* set every theme DOES emit, at ZERO
   specificity via :where() — so a theme that sets its own value in extraCss (0,1,0) always wins,
   and a theme that omits it falls back here. Makes pages theme-portable across the switcher. */
:where(.fenix-page-body) {
    --accent:       var(--c-primary,        var(--fenix-color-primary, #298a8a));
    --accent-deep:  var(--c-primary-strong, var(--fenix-color-primary-dark, #126567));
    --accent-hover: var(--c-primary-hover,  var(--fenix-color-primary, #35a3a3));
    --sec-a:        var(--fenix-color-surface, #ffffff);
    --sec-b:        var(--c-veryLt,          #f7f7f7);
    --c-tint:       var(--c-veryLt,          var(--c-petal2, #f0f7f7));

    /* Core --c-* semantic bridge FALLBACK (2026-07-20) — a theme whose extraCss omits the
       --c-* bridge (or an empty-bridge theme) previously left every var(--c-*) EMPTY on the
       live page → white-on-white text + rainbow accents (pg 663). Alias the core semantic
       slots to the --fenix-* tokens the emitter ALWAYS emits, at ZERO specificity via :where.
       A theme that declares its own --c-* in extraCss (specificity 0,1,0) always wins; a theme
       that omits them degrades to a readable --fenix-* value instead of blank. Only the CORE
       slots are bridged here — brand tints (--c-petal/--c-hair/…) still need the theme's own
       extraCss bridge for full fidelity. */
    --c-ink:            var(--fenix-color-text, #1e293b);
    --c-body:           var(--fenix-color-text-secondary, var(--fenix-color-text, #334155));
    --c-muted:          var(--fenix-color-text-muted, #64748b);
    --c-faint:          var(--fenix-color-text-faint, var(--fenix-color-text-muted, #94a3b8));
    --c-primary:        var(--fenix-color-primary, #298a8a);
    --c-primary-strong: var(--fenix-color-primary-dark, #126567);
    --c-primary-hover:  var(--fenix-color-primary-hover, #35a3a3);
    --c-surface:        var(--fenix-color-surface, #ffffff);
    --c-card:           var(--fenix-color-surface, #ffffff);
    --c-cardBorder:     var(--fenix-color-border, #e5e7eb);
    --c-border:         var(--fenix-color-border, #e5e7eb);
    --c-onDark:         #ffffff;
}

/* PAGE GROUND FALLBACK (2026-07-20) — the durable white-on-white fix. The rendered
   .fenix-page* elements carry NO data-profile, so a theme whose ExtraCss scopes its ground to
   [data-profile] (or omits it) left the body transparent → light text on the site's white body
   = white-on-white (pg 664 Spectrum dark). Paint the CONTENT GROUND only (the .page-body
   element that holds the sections), UNSCOPED, at ZERO specificity via :where — so any real
   ExtraCss ground (scoped or not, with or without !important) still wins, and this only fills
   the gap when a theme painted none.
   - ONE element, not host+page+body: painting the outer .fenix-page-host too would COVER a
     host-only atmosphere (gradient/photo wash a theme paints on the host expecting the body to
     show through). The content ground is where text sits — that's the WOW-critical surface.
   - --fenix-color-surface (the DEFAULT page surface per SurfaceTokens), NOT sunken (an inset
     role) nor gradientFrom (a brand/button stop). darkMode (FenixThemeStyle) flips
     --fenix-color-surface to #15151a, so a dark theme paints a dark ground automatically. */
:where(.page-body.fenix-page-body) {
    background-color: var(--fenix-color-surface, #ffffff);
}

/* B8 — breadcrumb. Phase 1 (2026-05-03): the breadcrumb is now rendered by
   _FenixBreadcrumb.{StripBelow|InlineTop} variant partials with Tailwind classes;
   the rules below were authored for the legacy inline breadcrumb that lived in
   Render.cshtml. Removed to stop:
   - the gray background overriding the user-required transparent background
   - the li::before injecting a duplicate › separator (the partials emit their
     own <li>›</li> separator inside the breadcrumb item list).
   The .fenix-breadcrumb class itself is still emitted by the partials as a hook
   for theme-specific overrides; just no default rules. */

/* B9 — body font wiring.
   FenixThemeStyleViewComponent emits variables --fenix-font-body / --fenix-font-heading / --fenix-font-script.
   Apply to the page body so authored text inherits the active theme font.
   We only target inside .fenix-page so we don't override the rest of the GVTheme. */
.fenix-page {
    font-family: var(--fenix-font-body, 'Inter', system-ui, -apple-system, sans-serif);
    color: #1e293b;
}
/* Script-accent opt-in. Add class="script-accent" (or `font-script`, kept for
   compat with theme.css) to any inline element to swap to the active script
   font from the theme profile. Designed for hero accents like "<em class='script-accent'>breakthrough</em>"
   without making every <em> use the script font (legal/policy pages need plain
   italic, not flourish). v1.94. */
.fenix-page .fenix-page-body .script-accent,
.fenix-page .fenix-page-body .font-script {
    font-family: var(--fenix-font-script, 'Caveat', cursive);
    font-style: normal; /* the script faces are usually inherently calligraphic */
    font-weight: 400;
}

.fenix-page .fenix-page-body h1,
.fenix-page .fenix-page-body h2,
.fenix-page .fenix-page-body h3,
.fenix-page .fenix-page-body h4 {
    /* !important + --fenix-font-heading is REQUIRED. theme.css loads AFTER the inline
       #fenix-theme-vars block and re-declares :root{--font-heading:'Playfair Display'}
       (same :root specificity, later in document order → wins), so --font-heading is
       clobbered back to Playfair on the live page. theme.css then paints headings via
       h1..h6{font-family:var(--font-heading)!important}. We pin to --fenix-font-heading
       (NOT --font-heading — that one is the clobbered legacy var) and add !important to
       beat theme.css's own !important. Mirrors the font-weight override just below. v2.43. */
    font-family: var(--fenix-font-heading, var(--fenix-font-body, 'Inter', sans-serif)) !important;
    word-break: normal;
}
/* Beat theme.css h1–h6 { font-weight: … !important }. Template font-* utilities below win. */
.fenix-page .fenix-page-body :is(h1, h2, h3, h4) {
    font-weight: var(--fenix-font-weight-heading, 700) !important;
}
.fenix-page .fenix-page-body h2,
.fenix-page .fenix-page-body h3,
.fenix-page .fenix-page-body h4 {
    overflow-wrap: anywhere;
}
/* H1 — auto wrap (builder parity). balance/pretty both nudge break points vs the
   builder canvas; hero {{workshop.titleHtml}} with explicit text-* should wrap
   only when the line genuinely runs out of width. */
.fenix-page .fenix-page-body h1 {
    text-wrap: auto;
    overflow-wrap: normal;
}
/* Templates that carry Tailwind text-* on the H1 own their sizing — never
   second-guess their line breaks (same as builder, which has no pretty/anywhere). */
.fenix-page .fenix-page-body h1[class*="text-"] {
    text-wrap: auto;
    overflow-wrap: normal;
    word-break: normal;
}
/* v2.41 — Centered workshop hero titleHtml on one line at desktop.
   Nowrap on h1 only — NOT on h1 > span. A nowrap wrapper span balloons past
   max-w-4xl and shifts glyphs right despite text-align:center on the h1. */
@media (min-width: 1024px) {
    .fenix-page .fenix-page-body .max-w-4xl.text-center h1[class*="text-"],
    .fenix-page .fenix-page-body section.text-center .max-w-4xl h1 {
        white-space: nowrap;
    }
    .fenix-page .fenix-page-body .max-w-4xl.text-center h1[class*="text-"] > span,
    .fenix-page .fenix-page-body section.text-center .max-w-4xl h1 > span {
        white-space: normal;
    }
}
/* H2–H4 — balance still helps subheads when theme fonts change glyph widths. v1.93. */
.fenix-page .fenix-page-body h2,
.fenix-page .fenix-page-body h3,
.fenix-page .fenix-page-body h4 {
    text-wrap: balance;
}
/* Page-builder canvas parity — mirror live heading font so titleHtml measures the same. */
.builder-section h1,
.builder-section h2,
.builder-section h3,
.builder-section h4 {
    font-family: var(--fenix-font-heading, var(--fenix-font-body, 'Inter', sans-serif));
}
.builder-section :is(h1, h2, h3, h4) {
    font-weight: var(--fenix-font-weight-heading, 700) !important;
}
/* Tailwind font-serif / font-sans utilities baked into section HTML must follow the
   active THEME profile, not Tailwind's hardcoded stacks. Without this, a heading saved
   with class="font-serif" renders in Playfair Display (output.css: .font-serif{font-family:
   Playfair Display,serif}) and IGNORES the admin's heading-font pick — the theme-profile
   font change appears to "not work" on the live page even though --fenix-font-heading is
   emitted correctly. We re-point both utilities to the theme vars (heading var for the
   serif/display slot, body var for the sans slot) so "change the theme font" wins. Scoped
   to Fenix pages + the builder canvas only, so the rest of GVTheme keeps its Tailwind stacks.
   !important + the class on the selector beats theme.css's element-level heading rule. v2.42. */
.fenix-page .fenix-page-body .font-serif,
.builder-section .font-serif {
    font-family: var(--fenix-font-heading, var(--font-heading, 'Inter', sans-serif)) !important;
}
.fenix-page .fenix-page-body .font-sans,
.builder-section .font-sans {
    font-family: var(--fenix-font-body, var(--font-body, 'Inter', system-ui, sans-serif)) !important;
}
/* Template Tailwind font-* on headings — builder ↔ live parity (beats theme.css). */
.fenix-page .fenix-page-body :is(h1, h2, h3, h4).font-thin,
.builder-section :is(h1, h2, h3, h4).font-thin { font-weight: 100 !important; }
.fenix-page .fenix-page-body :is(h1, h2, h3, h4).font-extralight,
.builder-section :is(h1, h2, h3, h4).font-extralight { font-weight: 200 !important; }
.fenix-page .fenix-page-body :is(h1, h2, h3, h4).font-light,
.builder-section :is(h1, h2, h3, h4).font-light { font-weight: 300 !important; }
.fenix-page .fenix-page-body :is(h1, h2, h3, h4).font-normal,
.builder-section :is(h1, h2, h3, h4).font-normal { font-weight: 400 !important; }
.fenix-page .fenix-page-body :is(h1, h2, h3, h4).font-medium,
.builder-section :is(h1, h2, h3, h4).font-medium { font-weight: 500 !important; }
.fenix-page .fenix-page-body :is(h1, h2, h3, h4).font-semibold,
.builder-section :is(h1, h2, h3, h4).font-semibold { font-weight: 600 !important; }
.fenix-page .fenix-page-body :is(h1, h2, h3, h4).font-bold,
.builder-section :is(h1, h2, h3, h4).font-bold { font-weight: 700 !important; }
.fenix-page .fenix-page-body :is(h1, h2, h3, h4).font-extrabold,
.builder-section :is(h1, h2, h3, h4).font-extrabold { font-weight: 800 !important; }
.fenix-page .fenix-page-body :is(h1, h2, h3, h4).font-black,
.builder-section :is(h1, h2, h3, h4).font-black { font-weight: 900 !important; }
.builder-section .script-accent,
.builder-section .font-script {
    font-family: var(--fenix-font-script, var(--font-script, 'Caveat', cursive));
    font-style: normal;
    font-weight: 400;
}

/* ─── HERO TREATMENT (global) ─────────────────────────────────────
   Applied to the FIRST hero-position H1 on any page, so every Fenix page
   inherits a consistent hero rhythm regardless of saved Tailwind classes.
   Pages that intentionally want a smaller hero can override by setting
   class="fenix-hero-compact" on the .fenix-page wrapper.

   The selectors target BOTH section conventions: pages ported via the
   modern pipeline use `.fenix-section`; older pages use `.builder-section`
   wrappers around an inner `<section>`. Either layout's first H1 gets
   the hero treatment; the rest of the page (h2/h3 etc.) is untouched.

   Two effects:
   1. Badge breathing room — saved hero badges with `mb-2` look cramped
      beneath a large H1. Force ~1.5rem so the badge reads as an eyebrow.
   2. H1 size + weight bump — pages saved with `text-4xl md:text-6xl
      font-medium` look wimpy as a hero. Promote to clamp(2.5rem, 4.5rem)
      and 700 weight so the H1 anchors the page. v1.95. */

/* Badge breathing room — the standalone hero EYEBROW pill (the lone
   category-label badge above the H1) gets 1.5rem below it so it reads as
   an eyebrow rather than crowding the headline.
   2026-05-16 — `:not(.flex *)` excludes badges that live inside a flex
   badge-ROW (e.g. Elegant Hero's "+POV Days / HRP / HWP" pills). Without
   it, the over-broad match gave the pink HRP badge a 1.5rem bottom margin,
   inflating its flex line to 56px and knocking the badge row out of
   vertical alignment. The eyebrow is never inside a flex row, so excluding
   flex-row descendants keeps the intended effect and drops the false hit. */
.fenix-page .fenix-page-body .builder-section:first-of-type [class*="rounded-full"][class*="bg-rose-"]:not(.flex *),
.fenix-page .fenix-page-body .builder-section:first-of-type [class*="rounded-full"][class*="bg-pink-"]:not(.flex *),
.fenix-page .fenix-page-body .builder-section:first-of-type [class*="rounded-full"][class*="bg-amber-"]:not(.flex *),
.fenix-page .fenix-page-body .fenix-section:first-of-type [class*="rounded-full"][class*="bg-rose-"]:not(.flex *),
.fenix-page .fenix-page-body .fenix-section:first-of-type [class*="rounded-full"][class*="bg-pink-"]:not(.flex *),
.fenix-page .fenix-page-body .fenix-section:first-of-type [class*="rounded-full"][class*="bg-amber-"]:not(.flex *) {
    margin-bottom: 1.5rem;
}

/* Hero H1 sizing — first H1 in either section convention.
   2026-05-20 — :not([class*="text-"]) lets templates with explicit Tailwind
   sizing (text-4xl/5xl/etc) win the cascade. Without this, the magnify rule
   ran the public render at 72px while the builder showed the Tailwind size,
   so any template carrying Tailwind text-* classes diverged builder-vs-live. */
.fenix-page:not(.fenix-hero-compact) .fenix-page-body .builder-section:first-of-type h1:not([class*="text-"]),
.fenix-page:not(.fenix-hero-compact) .fenix-page-body .fenix-section:first-of-type h1:not([class*="text-"]) {
    font-size: clamp(2.5rem, 5vw + 1rem, 4.5rem);
    font-weight: 700;
    line-height: 1.1;
}
/* Long unbroken strings in body copy (URLs, codes) shouldn't overflow either,
   but use break-word (gentler than anywhere) so paragraphs still read naturally. */
.fenix-page .fenix-page-body p,
.fenix-page .fenix-page-body li {
    overflow-wrap: break-word;
}
/* Card / grid children: when a heading inside a flex/grid item gets wider with
   a new font, min-width:0 lets the item shrink so siblings stay visible.
   Without this rule, a 2-up card grid can collapse to 1-up unexpectedly. */
.fenix-page .fenix-page-body .grid > *,
.fenix-page .fenix-page-body .flex > * {
    min-width: 0;
}
.fenix-page .fenix-page-body p {
    line-height: 1.7;
    margin-bottom: 1em;
}
/* A <p> that is a DIRECT child of a vertically-centered flex/grid row must not
   carry the base 1em bottom margin: flexbox centers the MARGIN box, so the stray
   bottom margin shifts the visible text up by half the margin and breaks
   icon↔label centering (e.g. the trainer "Credentials" rows — check sits centered,
   label floats high). Zero the block margin only in that centered-row context;
   normal paragraph rhythm elsewhere is untouched. v2.26. */
.fenix-page-body .flex.items-center > p,
.fenix-page-body .grid.items-center > p,
#canvas .flex.items-center > p,
#canvas .grid.items-center > p {
    margin-block: 0;
}
/* Heading rhythm — Tailwind preflight zeros all heading margins. Reinstate so
   numbered policy headings (3. Purposes…), feature-block headings, FAQ titles
   etc. get proper top spacing above and below them. Use top margin so the
   heading "owns" the gap before it (collapses with previous block's bottom). */
/* :not(...) guards let explicit Tailwind margin utilities win without
   !important. Word-boundary aware so `mb-6` doesn't accidentally defeat the
   top-margin rule (and vice versa). v1.91. */
.fenix-page .fenix-page-body h1:not([class*=" mt-"]):not([class^="mt-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]) { margin-top: 1.5em; }
/* 2026-05-21 (v2.14) — Hero sections control their own spacing precisely via
   template padding. The 1.5em default rhythm above (intended for content-style
   H1s — policy pages, FAQ blocks, etc.) was silently being applied to every
   hero template's H1, leaving a ~80px gap between the badge/eyebrow and the
   headline that the template author didn't ask for. Reset to 0 for any H1
   that descends from a section whose class starts with `hero-`. Content-style
   H1s outside hero sections still get the full rhythm.
   IMPORTANT: the rule above uses six :not() pseudo-classes, each adding to
   specificity (~0,0,2,1 with six :not bumps). A bare `.fenix-page-body [class^="hero-"] h1`
   would lose the cascade. Use !important here — this IS the explicit override,
   and the rule it's overriding is itself a deliberate default. v2.14. */
.fenix-page .fenix-page-body [class^="hero-"] h1,
.fenix-page .fenix-page-body [class*=" hero-"] h1 { margin-top: 0 !important; }
/* 2026-05-21 (v2.18) — Structural hero-pattern catch. Any h1 immediately
   preceded by a sibling div is a hero composition (badge/pill div → headline),
   not a content rhythm break. The 1.5em default above is meant for content
   h1s that follow body text (which always ends in <p>, not <div>). A codebase
   audit showed 11 div+h1 pairs (all hero badges) vs 1 p+h1 pair (genuine
   rhythm case). This rule catches every hero where the author forgot to
   prefix the <section> with `hero-` (e.g. "Gradient Welcome" template).
   !important required for the same reason as the [class^="hero-"] override
   above — the 1.5em rule's six :not() chain has higher specificity (0,8,1)
   than this sibling combinator (0,2,2). */
/* Kicker pill (div.mb-*) → headline (h1/h2/h3) — FAQ, hero, section headers.
   Without this, fenix-page.css heading rhythm (1.4em on h2) stacks on the pill's
   mb-* on live render while the builder canvas skips rhythm (no .fenix-page ancestor). */
.fenix-page .fenix-page-body div + h1,
.fenix-page .fenix-page-body div + h2,
.fenix-page .fenix-page-body div + h3 { margin-top: 0 !important; }
/* Builder canvas parity — same pill → headline pattern inside .builder-section.
   2026-09-14: was `#canvas .builder-section div + h2` — the ID out-ranked the live rule (0,2,2),
   so a brand kit's `.fenix-page-host .fenix-page-body .va-article h2 { margin-top:14px !important }`
   won on /page/{slug} but lost on the canvas. `.fenix-page-body .builder-section` = same (0,2,2). */
.builder-section div + h1,
.builder-section div + h2,
.builder-section div + h3,
.fenix-page-body .builder-section div + h1,
.fenix-page-body .builder-section div + h2,
.fenix-page-body .builder-section div + h3 { margin-top: 0 !important; }
.fenix-page .fenix-page-body h2:not([class*=" mt-"]):not([class^="mt-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]) { margin-top: 1.4em; }
.fenix-page .fenix-page-body h3:not([class*=" mt-"]):not([class^="mt-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]) { margin-top: 1.2em; }
.fenix-page .fenix-page-body h4:not([class*=" mt-"]):not([class^="mt-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]),
.fenix-page .fenix-page-body h5:not([class*=" mt-"]):not([class^="mt-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]),
.fenix-page .fenix-page-body h6:not([class*=" mt-"]):not([class^="mt-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]) { margin-top: 1em; }
.fenix-page .fenix-page-body h1:not([class*=" mb-"]):not([class^="mb-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]) { margin-bottom: 0.6em; }
.fenix-page .fenix-page-body h2:not([class*=" mb-"]):not([class^="mb-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]) { margin-bottom: 0.6em; }
.fenix-page .fenix-page-body h3:not([class*=" mb-"]):not([class^="mb-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]) { margin-bottom: 0.5em; }
.fenix-page .fenix-page-body h4:not([class*=" mb-"]):not([class^="mb-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]),
.fenix-page .fenix-page-body h5:not([class*=" mb-"]):not([class^="mb-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]),
.fenix-page .fenix-page-body h6:not([class*=" mb-"]):not([class^="mb-"]):not([class*=" my-"]):not([class^="my-"]):not([class*=" m-"]):not([class^="m-"]) { margin-bottom: 0.4em; }
/* First heading in a section shouldn't push down extra — the section's own padding handles that. */
.fenix-page .fenix-page-body section > h1:first-child,
.fenix-page .fenix-page-body section > h2:first-child,
.fenix-page .fenix-page-body section > h3:first-child,
.fenix-page .fenix-page-body section > div > h1:first-child,
.fenix-page .fenix-page-body section > div > h2:first-child,
.fenix-page .fenix-page-body section > div > h3:first-child { margin-top: 0; }
/* Hero pattern — heading directly after a label/pill span/small as the
   section's first child should NOT pick up the 1.5em rhythm. */
.fenix-page .fenix-page-body section > span:first-child + h1,
.fenix-page .fenix-page-body section > span:first-child + h2,
.fenix-page .fenix-page-body section > span:first-child + h3,
.fenix-page .fenix-page-body section > div > span:first-child + h1,
.fenix-page .fenix-page-body section > div > span:first-child + h2,
.fenix-page .fenix-page-body section > div > span:first-child + h3,
.fenix-page .fenix-page-body section > small:first-child + h1,
.fenix-page .fenix-page-body section > small:first-child + h2,
.fenix-page .fenix-page-body section > div > small:first-child + h1,
.fenix-page .fenix-page-body section > div > small:first-child + h2 { margin-top: 0; }

/* List rendering — defeats GVTheme/output.css's Tailwind preflight `ol,ul{list-style:none}`.
   Without these, mockup pages with <ul>/<ol> in policy text or feature lists render as
   bullet-less plain lines (FAQ items, compliance lists, etc.). Mirror of builder iframe
   rules in dist/theme.css:5314+ so PUBLIC matches BUILDER preview. 2026-05-07. */
.fenix-page .fenix-page-body ul,
.fenix-page .fenix-page-body ol {
    margin-bottom: 1em;
    padding-left: 1.5em !important;
}
.fenix-page .fenix-page-body ul { list-style: disc outside !important; list-style-type: disc !important; }
.fenix-page .fenix-page-body ol { list-style: decimal outside !important; list-style-type: decimal !important; }
.fenix-page .fenix-page-body ul li { list-style-type: disc !important; display: list-item !important; line-height: 1.7; }
.fenix-page .fenix-page-body ol li { list-style-type: decimal !important; display: list-item !important; line-height: 1.7; }
.fenix-page .fenix-page-body li { margin-bottom: 0.5em; }
.fenix-page .fenix-page-body ul ul,
.fenix-page .fenix-page-body ol ol,
.fenix-page .fenix-page-body ul ol,
.fenix-page .fenix-page-body ol ul { margin-bottom: 0; padding-left: 1.5em !important; }

/* Escape hatch: `<ul class="list-none">` is the Tailwind / mockup convention for
   icon-checkmark lists (see WorkshopHeroRenderer bullets, FeaturesChecklistRenderer,
   r2o triangle nodes). The disc override above forces them back to default-bullet
   + list-item display, which (a) shows two markers per line (• + checkmark) and
   (b) breaks the `<li class="flex">` layout because list-item beats flex.

   Selector note: live pages wrap content in <main class="fenix-page-host"><div
   class="fenix-page-body">…</div></main>. There's NO `.fenix-page` ancestor —
   only `-host` and `-body`. Earlier rules in this file using `.fenix-page
   .fenix-page-body` work because `.fenix-page` is also a literal substring of
   the body class name, but to override the same-specificity `.builder-section`
   rule from dist/theme.css:5374 we need to be explicit about list-none here.

   Ordering: this block is AFTER the disc-forcing block above, so equal-
   specificity + later-in-cascade lets it win. Both branches use !important. */
/* First-heading inside a padded card: cancel the heading-rhythm margin-top.
   GVTheme's .builder-section h1/h2/h3 { margin-top: 1.4em } adds vertical breathing
   between sequential blocks but visibly stacks on top of the card's `p-8` (2rem)
   padding when the heading is the FIRST child — producing ~5rem of dead space at
   the top, vs the 2rem at the bottom. Reset margin-top to 0 for first-of-type
   headings. The next sibling spacing is preserved by the heading's own mb-* class. */
.fenix-page-body .builder-section [class*="rounded-"] > h1:first-child,
.fenix-page-body .builder-section [class*="rounded-"] > h2:first-child,
.fenix-page-body .builder-section [class*="rounded-"] > h3:first-child,
.builder-section [class*="rounded-"] > h1:first-child,
.builder-section [class*="rounded-"] > h2:first-child,
.builder-section [class*="rounded-"] > h3:first-child,
.fenix-page-body [class*="p-8"] > h1:first-child,
.fenix-page-body [class*="p-8"] > h2:first-child,
.fenix-page-body [class*="p-8"] > h3:first-child {
    margin-top: 0 !important;
}

/* Note 2026-05-09: drop the .fenix-page-body ancestor so the rules also apply inside
   the Page Builder iframe canvas (page-builder.html) which doesn't wrap content in
   .fenix-page-body. Plain `ul.list-none` selector is enough — same specificity as
   `.builder-section ul li` from theme.css but appears later in cascade so wins. */
ul.list-none,
.fenix-page-body ul.list-none,
.builder-section ul.list-none {
    list-style: none !important;
    list-style-type: none !important;
    padding-left: 0 !important;
}
ul.list-none > li,
.fenix-page-body ul.list-none > li,
.builder-section ul.list-none > li {
    list-style-type: none !important;
    /* Don't force display:list-item — let the markup's own class (flex / grid / block)
       win. Re-assert flex / grid / block on the next selectors below so they out-
       specificity any default `display:list-item` rule. */
    display: revert !important;
}
ul.list-none > li.flex,
.fenix-page-body ul.list-none > li.flex,
.builder-section ul.list-none > li.flex { display: flex !important; }
ul.list-none > li.grid,
.fenix-page-body ul.list-none > li.grid,
.builder-section ul.list-none > li.grid { display: grid !important; }
ul.list-none > li.block,
.fenix-page-body ul.list-none > li.block,
.builder-section ul.list-none > li.block { display: block !important; }

/* 2026-05-16 — Icon-row list items must NOT show a bullet.
   The disc-forcing block above (`.fenix-page-body ul li { list-style:disc;
   display:list-item }`) is correct for plain prose lists, but the checklist
   templates (checklist-gvt-*, checklist-indigo-*, Vplus hero feature lists,
   features-checklist) use `<li class="flex …">` / `<li class="grid …">` as a
   LAYOUT ROW — an editable check-icon span + text — inside a `<ul>` whose
   class is `space-y-3` / `grid …`, NOT `list-none`. So the escape hatch above
   never fired and every row showed a default `•` next to the check-icon, and
   `display:list-item` fought the flex layout.
   Fix: a list item whose OWN class makes it flex/grid is, by definition, not a
   bulleted item — kill the marker and honour its layout display, regardless of
   the parent <ul>'s class. Plain prose `<li>` (no layout class) is untouched,
   so genuine bulleted lists still get their disc. */
/* Specificity note: the disc-forcing rule above is `.fenix-page
   .fenix-page-body ul li` = (0,3,1). To beat it we must match or exceed that.
   `.fenix-page .fenix-page-body ul li.flex` = (0,3,2) — wins cleanly. The
   builder iframe has no `.fenix-page` ancestor, so `.builder-section ul li.flex`
   (0,2,1) is enough there (the theme.css rule it competes with is also lower). */
.fenix-page .fenix-page-body ul li.flex,
.fenix-page .fenix-page-body ul li.inline-flex,
.fenix-page .fenix-page-body ol li.flex,
.fenix-page .fenix-page-body ol li.inline-flex,
.fenix-page-body ul li.flex,
.fenix-page-body ul li.inline-flex,
.fenix-page-body ol li.flex,
.fenix-page-body ol li.inline-flex,
.builder-section ul li.flex,
.builder-section ul li.inline-flex,
.builder-section ol li.flex,
.builder-section ol li.inline-flex,
ul li.flex,
ul li.inline-flex,
ol li.flex,
ol li.inline-flex {
    list-style: none !important;
    list-style-type: none !important;
    display: flex !important;
}
.fenix-page .fenix-page-body ul li.grid,
.fenix-page .fenix-page-body ol li.grid,
.fenix-page-body ul li.grid,
.fenix-page-body ol li.grid,
.builder-section ul li.grid,
.builder-section ol li.grid,
ul li.grid,
ol li.grid {
    list-style: none !important;
    list-style-type: none !important;
    display: grid !important;
}
/* A <ul>/<ol> made of icon-rows shouldn't reserve the marker gutter either. */
.fenix-page .fenix-page-body ul:has(> li.flex),
.fenix-page .fenix-page-body ul:has(> li.grid),
.fenix-page .fenix-page-body ul:has(> li.inline-flex),
.fenix-page .fenix-page-body ol:has(> li.flex),
.fenix-page .fenix-page-body ol:has(> li.grid),
.fenix-page .fenix-page-body ol:has(> li.inline-flex),
.fenix-page-body ul:has(> li.flex),
.fenix-page-body ul:has(> li.grid),
.fenix-page-body ul:has(> li.inline-flex),
.fenix-page-body ol:has(> li.flex),
.fenix-page-body ol:has(> li.grid),
.fenix-page-body ol:has(> li.inline-flex),
.builder-section ul:has(> li.flex),
.builder-section ul:has(> li.grid),
.builder-section ul:has(> li.inline-flex),
.builder-section ol:has(> li.flex),
.builder-section ol:has(> li.grid),
.builder-section ol:has(> li.inline-flex),
ul:has(> li.flex),
ul:has(> li.grid),
ul:has(> li.inline-flex),
ol:has(> li.flex),
ol:has(> li.grid),
ol:has(> li.inline-flex) {
    list-style: none !important;
    padding-left: 0 !important;
}

/* 2026-06-03 — INLINE-STYLE escape hatch (Page Wizard markup).
   The escape hatches above key off a CLASS on the <li> (.flex / .grid). The Page
   Wizard generator instead emits icon-row lists with INLINE styles and NO class:
       <ul style="list-style:none; … ">
         <li style="display:flex;align-items:flex-start;gap:14px"> …icon + text… </li>
   The disc-forcing rule `.fenix-page-body ul li { list-style:disc; display:list-item
   !important }` therefore beats the <ul>'s inline `list-style:none` (stylesheet
   !important > inline non-important) AND overrides the <li>'s inline `display:flex`,
   so every essentials row showed a • bullet and the icon/label stack broke out of
   its flex row. CSS can't read the inline `display` value, but it CAN match the
   wizard's signature via attribute selectors: a list-none <ul> + a flex/grid <li>.
   Kill the marker and honour the inline display for exactly that shape. Plain prose
   <li> (no inline display) is untouched, so genuine bulleted lists still get discs. */
.fenix-page-body ul[style*="list-style:none"],
.fenix-page-body ul[style*="list-style: none"],
.builder-section ul[style*="list-style:none"],
.builder-section ul[style*="list-style: none"],
ul[style*="list-style:none"],
ul[style*="list-style: none"] {
    list-style: none !important;
    padding-left: 0 !important;
}
.fenix-page-body ul[style*="list-style:none"] > li[style*="display:flex"],
.fenix-page-body ul[style*="list-style: none"] > li[style*="display:flex"],
.builder-section ul[style*="list-style:none"] > li[style*="display:flex"],
.builder-section ul[style*="list-style: none"] > li[style*="display:flex"],
ul[style*="list-style:none"] > li[style*="display:flex"],
ul[style*="list-style: none"] > li[style*="display:flex"] {
    list-style: none !important;
    list-style-type: none !important;
    display: flex !important;
}
.fenix-page-body ul[style*="list-style:none"] > li[style*="display:grid"],
.fenix-page-body ul[style*="list-style: none"] > li[style*="display:grid"],
.builder-section ul[style*="list-style:none"] > li[style*="display:grid"],
.builder-section ul[style*="list-style: none"] > li[style*="display:grid"],
ul[style*="list-style:none"] > li[style*="display:grid"],
ul[style*="list-style: none"] > li[style*="display:grid"] {
    list-style: none !important;
    list-style-type: none !important;
    display: grid !important;
}

/* 2026-06-03 — HERO meta-pill legibility (white-on-white fix).
   Hero / scrim sections override --fenix-color-text to #ffffff so the headline
   reads on the dark photo. But the Page Wizard styles the hero meta badges with
   an inline `background:#ffffff` + `color:var(--fenix-color-text)` → white text on
   a white pill = invisible (the "white blobs" in the hero). The generator backstop
   (FenixWorkshop234Conformance step 9) prevents this on NEW pages, but ALREADY-
   PUBLISHED snapshots keep the bad inline fill, so heal them at render time too:
   inside .fenix-hero-scrim, any inline-white pill gets a translucent dark surface
   + explicit white text so it reads on the photo. Scoped to .fenix-hero-scrim only,
   so white CONTENT cards in light sections are untouched. !important beats the
   inline background:#ffffff. */
.fenix-hero-scrim span[style*="background:#ffffff"],
.fenix-hero-scrim span[style*="background:#fff;"],
.fenix-hero-scrim span[style*="background: #ffffff"] {
    background: rgba(0, 0, 0, 0.28) !important;
    border-color: rgba(255, 255, 255, 0.45) !important;
    color: #ffffff !important;
}

/* 2026-05-16 — Neutralise Tailwind's `@container` on INLINE elements.
   Many atomic templates (cta-button-pill, cta-button-outline, cta-spots-left,
   cta-mini-card, badges) carry `class="@container inline-flex …"`. Tailwind's
   `@container` utility sets `container-type: inline-size`, which on an
   inline-flex / inline-block element collapses it to min-content width — the
   button text wraps one word per line and the pill crushes to ~48px.
   `@container` only makes sense on a block-level layout wrapper, and only when
   container-query (`@sm:` / `@md:`) CSS is compiled — which the public render
   does NOT do. So: wherever `@container` lands on an inline-display element,
   force `container-type: normal`. Block-level `@container` wrappers are left
   alone (harmless). Targets the literal class — Tailwind escapes `@` so the
   class attribute value is literally `@container`. */
[class~="@container"].inline-flex,
[class~="@container"].inline-block,
[class~="@container"].inline,
.fenix-page-body [class~="@container"].inline-flex,
.fenix-page-body [class~="@container"].inline-block,
.builder-section [class~="@container"].inline-flex,
.builder-section [class~="@container"].inline-block {
    container-type: normal !important;
}

/* 2026-05-16 — Equalise pill-badge heights in hero/title template rows.
   Workshop templates (e.g. Elegant Hero) render a `flex flex-wrap` row of
   `inline-flex` pill badges. The row has no `items-*` class, so it defaults
   to `align-items: stretch` — every badge is stretched to the row's tallest
   child. One badge ends up genuinely tall (its Lucide SVG is authored with
   `width="24" height="24"` ATTRIBUTES; when the `w-3 h-3` utility loses the
   cascade on the public render the SVG falls back to 24px), the row grows to
   match, and stretch then inflates the SHORT badges too — text floats in a
   tall pill. The builder render keeps `w-3 h-3` winning, so it looks fine
   there. Two-part fix:
   1. Pin Lucide SVGs inside badges to a real 1em box so they never report
      their 24px attribute size — this stops any badge being genuinely tall.
   2. Stop the badge row stretching its children, so a tall sibling can't
      inflate the rest. Each badge then sizes purely to its own content. */
.fenix-page-body .flex > .inline-flex,
.fenix-page-body .inline-flex > .inline-flex,
.builder-section .flex > .inline-flex,
.builder-section .inline-flex > .inline-flex {
    white-space: nowrap;
    align-self: center;
}
.fenix-page-body .inline-flex > svg[data-lucide],
.fenix-page-body :not(li).flex > svg[data-lucide],
.fenix-page-body .flex > .inline-flex > svg[data-lucide],
.builder-section .inline-flex > svg[data-lucide],
.builder-section :not(li).flex > svg[data-lucide],
.builder-section .flex > .inline-flex > svg[data-lucide] {
    flex: 0 0 auto;
    width: 1em;
    height: 1em;
    vertical-align: middle;
}

/* Trainer / checklist icon rows (<li class="flex …"> + Lucide checkmark).
   The 1em pin above is for badge/chip Lucide icons only — on checklist rows it
   shrank w-5 icons and threw off vertical alignment with the label text. */
.fenix-page-body ul li.flex,
.fenix-page-body ol li.flex,
.builder-section ul li.flex,
.builder-section ol li.flex,
#canvas ul li.flex,
#canvas ol li.flex {
    line-height: 1.5;
}
.fenix-page-body li.flex > svg[data-lucide],
.fenix-page-body li.flex > i[data-lucide],
.builder-section li.flex > svg[data-lucide],
.builder-section li.flex > i[data-lucide],
#canvas li.flex > svg[data-lucide],
#canvas li.flex > i[data-lucide] {
    flex-shrink: 0;
    align-self: flex-start;
    margin-top: 0.125rem;
}
.fenix-page-body ul li.flex > span[data-field],
.fenix-page-body ul li.flex > span[data-editable],
.builder-section ul li.flex > span[data-field],
.builder-section ul li.flex > span[data-editable],
#canvas ul li.flex > span[data-field],
#canvas ul li.flex > span[data-editable] {
    flex: 1 1 0%;
    min-width: 0;
    line-height: 1.5;
}

/* Default <img> behaviour: shrink-to-fit with intrinsic aspect ratio.
   The :not(...) escape lets ported pages override via class="h-full",
   class="h-[500px]", class="h-screen", or `style="height:..."`, which
   would otherwise lose the cascade fight to this rule's higher specificity
   (.fenix-page .fenix-page-body img is 0,2,1 vs .fenix-page .h-full at 0,2,0).
   Without the escape, photos in `<img class="w-full h-full object-cover">`
   cards (e.g. trainer photos in pov-miniseries) shrink to intrinsic size
   instead of filling their fixed-height container. */
.fenix-page .fenix-page-body img:not(.h-full):not([class*="h-["]):not([class*="h-screen"]):not([style*="height"]) {
    max-width: 100%;
    height: auto;
}

/* ─── Container alignment ──────────────────────────────────────────────
   Lock page-body content to the SAME container shape as header + breadcrumb
   (max-width: 1152px / max-w-6xl, centered, 32px side padding / px-8). The
   TranslucentHero header inner is 1152px + 32px padding (see
   _FenixHeader.TranslucentHero.cshtml). The breadcrumb partial is also
   max-w-6xl px-8 (see _FenixBreadcrumb.StripBelow.cshtml). Body MUST match
   or the page renders with three different left edges (logo / breadcrumb
   at one column, content slightly further left at narrow viewports).

   2026-05-06 fix — pre-v1.69 we drifted to 1280px / 1.5rem here, which broke
   the alignment promise documented in the header partial. Restored to
   1152px / 2rem so logo, breadcrumb, and body content share one rail. */
.fenix-page .fenix-page-body .fenix-section-inner {
    max-width: 1152px !important;
    margin-left: auto;
    margin-right: auto;
    padding-left: 2rem;
    padding-right: 2rem;
    box-sizing: border-box;
}

/* ─── Gear background preset: dark pattern (2026-06-06) ───────────────────────
   BACKGROUND_STYLES['dark-pattern'] emits pb-bg-dark-pattern on fenix-section /
   builder-section. Was builder-only inline CSS in page-builder.html — live pages
   never loaded it. Scoped to section gear wrappers only. */
.fenix-page .fenix-section.pb-bg-dark-pattern,
.fenix-page .builder-section.pb-bg-dark-pattern {
    position: relative;
    background: linear-gradient(135deg, #1e293b 0%, #334155 100%);
}
.fenix-page .fenix-section.pb-bg-dark-pattern::before,
.fenix-page .builder-section.pb-bg-dark-pattern::before {
    content: '';
    position: absolute;
    inset: 0;
    background: url("data:image/svg+xml,%3Csvg width='60' height='60' viewBox='0 0 60 60' xmlns='http://www.w3.org/2000/svg'%3E%3Cg fill='none' fill-rule='evenodd'%3E%3Cg fill='%23ffffff' fill-opacity='0.03'%3E%3Cpath d='M36 34v-4h-2v4h-4v2h4v4h2v-4h4v-2h-4zm0-30V0h-2v4h-4v2h4v4h2V6h4V4h-4zM6 34v-4H4v4H0v2h4v4h2v-4h4v-2H6zM6 4V0H4v4H0v2h4v4h2V6h4V4H6z'/%3E%3C/g%3E%3C/g%3E%3C/svg%3E");
    pointer-events: none;
}

/* ─── Ported-page section gutter (2026-05-06) ────────────────────────────
   Mockups ported through fenix-page-port often render as:

     <section class="px-6">                  <!-- 24px gutter -->
       <div class="max-w-6xl mx-auto">       <!-- 1152px column, centered -->
         …content…
       </div>
     </section>

   The header + breadcrumb use a single rail (max-width:1152 + 32px gutter).
   The ported-page form has TWO containers — the outer section's padding
   plus the inner column's auto-margins — and the math diverges from the
   header's at any viewport ≠ exactly 1152+padding wide:

     • At narrow viewports (<1152): inner column is viewport-bound, sits at
       section.padding-left (24px). Header sits at 32px. → 8px mismatch.
     • At wide viewports (>1152): inner column is 1152, centered inside
       (viewport − section.padding), so its left edge ≠ header's left edge.

   The only single rule that aligns all three at every width is to make
   the outer section adopt the header's exact rail: max-width:1152, auto
   margins, 2rem (32px) side padding. The inner .max-w-6xl.mx-auto then
   becomes a no-op (1152 inside 1152 with auto margins). */
.fenix-page .fenix-page-body > section.px-6,
.fenix-page .fenix-page-body > .fenix-section > section.px-6,
.fenix-page .fenix-page-body > section.px-8,
.fenix-page .fenix-page-body > .fenix-section > section.px-8 {
    max-width: 1152px !important;        /* matches header inner exactly */
    margin-left: auto !important;
    margin-right: auto !important;
    padding-left: 2rem !important;       /* 32px — same as header */
    padding-right: 2rem !important;
    box-sizing: border-box !important;   /* match header so 1152 INCLUDES padding */
}

/* ─── Page-builder grid + section column primitives ───────────────────
   The iframe page-builder produces .pb-responsive-grid + .pb-grid-{N} +
   .section-column wrappers. The builder's own CSS gates these on
   @container queries ("template" container) which don't exist in the
   public render context, so they collapse to single-column. Add plain
   media-query fallbacks scoped under .fenix-page so we don't bleed into
   the rest of GVTheme. */

.fenix-page .pb-responsive-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
}

.fenix-page .pb-grid-2 { grid-template-columns: 1fr; }
.fenix-page .pb-grid-3 { grid-template-columns: 1fr; }
.fenix-page .pb-grid-4 { grid-template-columns: 1fr; }

@media (min-width: 768px) {
    .fenix-page .pb-grid-2 { grid-template-columns: repeat(2, 1fr); gap: 2rem; align-items: center; }
    .fenix-page .pb-grid-3 { grid-template-columns: repeat(3, 1fr); gap: 2rem; }
    .fenix-page .pb-grid-4 { grid-template-columns: repeat(4, 1fr); gap: 2rem; }
}

/* split-40-60 section type: image (col 0) gets 2fr, text (col 1) gets 3fr.
   The page-builder writes the section type as part of the data-section-id
   wrapper class but NOT into the inner .pb-grid-2 wrapper, so we target
   via the parent .builder-section + section-type marker if present.
   Falls back to vanilla 50/50 if section type isn't set. */
@media (min-width: 768px) {
    .fenix-page .builder-section.section-split-40-60 .pb-grid-2 {
        grid-template-columns: 2fr 3fr;
        gap: 3rem;
    }
}

.fenix-page .section-column {
    min-width: 0;  /* prevents grid item overflow */
}

/* ─── Position + display primitives the builder emits ─────────────── */

.fenix-page .relative { position: relative; }
.fenix-page .absolute { position: absolute; }
.fenix-page .top-0 { top: 0; }
.fenix-page .left-0 { left: 0; }
.fenix-page .right-0 { right: 0; }
.fenix-page .bottom-0 { bottom: 0; }
.fenix-page .top-6 { top: 1.5rem; }
.fenix-page .left-6 { left: 1.5rem; }
/* Hero blob offsets (GVTheme home.html pattern) — mirrored under .fenix-page-body below. */
.fenix-page .top-10 { top: 2.5rem; }
.fenix-page .top-20 { top: 5rem; }
.fenix-page .top-40 { top: 10rem; }
.fenix-page .left-10 { left: 2.5rem; }
.fenix-page .right-10 { right: 2.5rem; }
.fenix-page .bottom-20 { bottom: 5rem; }
.fenix-page .w-72 { width: 18rem; }
.fenix-page .h-72 { height: 18rem; }
.fenix-page .inset-0 { top: 0; right: 0; bottom: 0; left: 0; }
.fenix-page .overflow-hidden { overflow: hidden; }
.fenix-page .object-cover { object-fit: cover; }

/* Image component: the wrapper has style="aspect-ratio: 4/5" inline, so
   we just need the img itself to fill the box. Only full-bleed slots — skip
   fixed-size portrait frames (w-40 circle, aspect-square cards, etc.). */
.fenix-page [data-editable-image]:not([class*="w-"]):not([class*="aspect-"]):not([style*="width"]),
.fenix-page-body [data-editable-image]:not([class*="w-"]):not([class*="aspect-"]):not([style*="width"]) {
    width: 100%;
}
/* Default fill behaviour for editable images. Skip imgs that explicitly opt
   into a different fit (e.g. object-contain on the trainer-circle hero, which
   needs the full figure letterboxed, not cropped). Without this exclusion the
   blanket object-fit:cover (0,2,1) overrode the template's .object-contain
   (0,1,0) and the live page cropped the figure that the builder showed whole. */
.fenix-page [data-editable-image] img:not([class*="object-"]) {
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* Inline aspect-ratio portrait frames (neo-brutalist trainer widgets). */
.fenix-page [data-editable-image][style*="aspect-ratio"],
.fenix-page-body [data-editable-image][style*="aspect-ratio"] {
    width: 100%;
}
/* 2026-05-21 — Hero scroll-strip slots use their own `width:var(--w)` for
   the fanned trapezoid carousel. The blanket `[data-editable-image]
   width:100%` above was forcing all 7 slots to viewport width and stacking
   them. Restore slot-controlled widths inside the strip. v2.16. */
.fenix-page .hsp-strip [data-editable-image].hsp-slot-2,
.fenix-page .hsp-strip [data-editable-image].hsp-slot-3,
.fenix-page .hsp-strip [data-editable-image].hsp-slot-4,
.fenix-page .hsp-strip [data-editable-image].hsp-slot-5,
.fenix-page .hsp-strip [data-editable-image].hsp-slot-6 { width: var(--w); }
.fenix-page .hsp-strip [data-editable-image].hsp-slot-1,
.fenix-page .hsp-strip [data-editable-image].hsp-slot-7 { width: var(--wE); }

/* Pretty rounded radius literals used by the builder + ported pages (rounded-[2rem],
   rounded-[2.5rem], rounded-[3rem]) plus the named Tailwind 2xl. */
.fenix-page .rounded-\[2rem\]   { border-radius: 2rem; }
.fenix-page .rounded-\[2\.5rem\]{ border-radius: 2.5rem; }
.fenix-page .rounded-\[3rem\]   { border-radius: 3rem; }
.fenix-page .rounded-2xl        { border-radius: 1rem; }
.fenix-page .rounded-3xl        { border-radius: 1.5rem; }

/* Sizing — full-parent utilities. Without these `<img class="w-full h-full">`
   renders at the intrinsic image size and floats inside its container instead
   of filling. Tailwind's `w-full / h-full` are NOT in fenix-page.css's vocabulary
   by default, so ported pages with photo cards (e.g. the Meet Our Trainers
   section in pov-miniseries) shrink to thumbnail size. */
.fenix-page .w-full  { width: 100%; }
.fenix-page .h-full  { height: 100%; }
.fenix-page .w-40, .fenix-page-body .w-40 { width: 10rem; }
.fenix-page .h-40, .fenix-page-body .h-40 { height: 10rem; }
@media (min-width: 768px) {
    .fenix-page .md\:w-48, .fenix-page-body .md\:w-48 { width: 12rem; }
    .fenix-page .md\:h-48, .fenix-page-body .md\:h-48 { height: 12rem; }
}

/* Shadows — soft + lifted card variants. */
.fenix-page .shadow-sm  { box-shadow: 0 1px 2px 0 rgba(0,0,0,0.05); }
.fenix-page .shadow-md  { box-shadow: 0 4px 6px -1px rgba(0,0,0,0.10), 0 2px 4px -2px rgba(0,0,0,0.10); }
.fenix-page .shadow-lg  { box-shadow: 0 10px 15px -3px rgba(0,0,0,0.10), 0 4px 6px -4px rgba(0,0,0,0.10); }
.fenix-page .shadow-xl  { box-shadow: 0 20px 25px -5px rgba(0,0,0,0.10), 0 8px 10px -6px rgba(0,0,0,0.10); }
.fenix-page .shadow-2xl { box-shadow: 0 25px 50px -12px rgba(0,0,0,0.25); }

/* Card photo rotations — used by ported "polaroid" / tilted photo cards.
   Negative + positive 1°-6° degree variants. */
.fenix-page .-rotate-\[3deg\]   { transform: rotate(-3deg); }
.fenix-page .rotate-\[3deg\]    { transform: rotate(3deg); }
.fenix-page .-rotate-3          { transform: rotate(-3deg); }
.fenix-page .rotate-3           { transform: rotate(3deg); }
.fenix-page .-rotate-6          { transform: rotate(-6deg); }
.fenix-page .rotate-6           { transform: rotate(6deg); }

/* ─── Decorative blob support ────────────────────────────────────────
   Many ported mockups use `<div class="fixed inset-0 ..."><div class="absolute
   ... w-[Npx] h-[Npx] rounded-full mix-blend-multiply filter blur-3xl ...">`
   as soft pink/amber decoration in the page corners. These classes (arbitrary
   sizes + filter + mix-blend + blur-3xl) are NOT in fenix-page.css's vocabulary
   and Tailwind purge skips them because the plugin output.css is built without
   the saved page contentJson in scope. Provide them as static utilities so
   any Fenix page can use the pattern without re-compiling Tailwind. */

.fenix-page .fixed { position: fixed; }
.fenix-page .pointer-events-none { pointer-events: none; }
.fenix-page .rounded-full { border-radius: 9999px; }
/* Omit a bare `.filter` override — Tailwind's `.filter` enables the var(--tw-blur) stack
   for sibling utilities like `blur-3xl`. A `.fenix-page .filter { filter:none }` rule
   was winning over output.css in the code-editor preview and killing blob blur. */
.fenix-page .blur-3xl,
.fenix-page-body .blur-3xl { filter: blur(64px); }
.fenix-page .bg-pink-200,
.fenix-page-body .bg-pink-200 { background-color: #fbcfe8; }
.fenix-page .bg-rose-200,
.fenix-page-body .bg-rose-200 { background-color: #fecdd3; }
@keyframes fenix-blob {
    0%, 100% { transform: translate(0, 0) scale(1); }
    25% { transform: translate(20px, -50px) scale(1.1); }
    50% { transform: translate(-20px, 20px) scale(0.9); }
    75% { transform: translate(50px, 50px) scale(1.05); }
}
.fenix-page .animate-blob,
.fenix-page-body .animate-blob { animation: fenix-blob 7s infinite; }
.fenix-page .animation-delay-2000,
.fenix-page-body .animation-delay-2000 { animation-delay: 2s; }
.fenix-page .animation-delay-4000,
.fenix-page-body .animation-delay-4000 { animation-delay: 4s; }
.fenix-page .mix-blend-multiply { mix-blend-mode: multiply; }
.fenix-page .opacity-50 { opacity: 0.5; }
.fenix-page .opacity-30 { opacity: 0.3; }
.fenix-page .opacity-20 { opacity: 0.2; }

/* Arbitrary width/height literals for decorative blobs.
   Common sizes used across ported mockups (100day-program, r2o, etc.). */
.fenix-page .w-\[800px\]  { width: 800px; }
.fenix-page .h-\[800px\]  { height: 800px; }
.fenix-page .w-\[600px\]  { width: 600px; }
.fenix-page .h-\[600px\]  { height: 600px; }
.fenix-page .w-\[500px\]  { width: 500px; }
.fenix-page .h-\[500px\]  { height: 500px; }

/* Static positioning helpers used by decorative blobs */
.fenix-page .top-1\/2     { top: 50%; }
.fenix-page .right-1\/4   { right: 25%; }
.fenix-page .-left-40     { left: -10rem; }

/* Static blob helper — replaces GVTheme's :hover-only `t-bg-light-hover`.
   Applies a soft Tailwind pink-100 wash so legacy in-template blob divs still
   render something. The MAIN decoration system is now `.fenix-page-deco` below
   (page-level, brand-aware, configurable). Don't add `bg-pink-100` / `bg-rose-100`
   overrides here — those are in-template utility classes used by badges, icon
   tiles, etc., and globally re-colouring them broke pill backgrounds. */
.fenix-page .t-bg-light-static {
    background-color: #fce7f3;
}

/* ─── Theme-token utility classes (2026-05-29) ──────────────────────────────────
   Brand-tied colour classes used by EXTRACTED / authored section templates so a
   page's theme profile recolours every section as a unit. Previously these were
   defined ONLY in wizard/dist/theme.css, which loads in the builder iframe + admin
   preview but NOT on the public page — so on a published page a `t-text` span had
   NO rule and rendered colourless. Defining them here (fenix-page.css always loads
   on public pages) closes that gap.

   They read the legacy --color-primary* family, which FenixThemeStyle/Default.cshtml
   now re-emits from the ACTIVE theme profile (the bridge added the same day). The
   fallback hexes below are the Rose preset (GVT default) values and only fire if a
   page somehow renders without the theme-vars block — so the fallback matches the
   real brand pink (#c9437f) rather than a different shade.
   Scope: brand-tied tokens ONLY — do NOT add bg-pink-*/bg-rose-* here (per the note
   above, globally recolouring those broke pill backgrounds). */
.fenix-page .t-text             { color: var(--color-primary, #c9437f); }
.fenix-page .t-text-hover:hover { color: var(--color-primary-hover, #a82e6c); }
.fenix-page .t-text-muted       { color: var(--color-primary-dark, #7a2752); }
.fenix-page .t-bg               { background-color: var(--color-primary, #c9437f); }
.fenix-page .t-bg-light         { background-color: var(--color-primary-light, #f4d6e3); }
.fenix-page .t-bg-light-hover:hover { background-color: var(--color-primary-light, #f4d6e3); }
.fenix-page .t-border           { border-color: var(--color-primary, #c9437f); }
.fenix-page .t-border-light     { border-color: var(--color-primary-light-hover, #f4d6e3); }

/* ─── Workshop wizard chips + CTAs (v2.29) ─────────────────────────────────────
   Hallmark/Claude generations use .chip-pill / .btn-primary / .btn-ghost / .fenix-whatsapp-cta
   but those classes were not in this bundle — chips rendered as raw icon+text on the hero scrim. */
.fenix-page .fenix-page-body .chip-pill {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 8px 14px;
    border-radius: 9999px;
    background: var(--fenix-color-surface, rgba(255, 255, 255, 0.14));
    border: 1px solid var(--fenix-color-border, rgba(255, 255, 255, 0.28));
    color: var(--fenix-color-text-muted, #64748b);
    font-size: 13px;
    line-height: 1.3;
    white-space: nowrap;
}
.fenix-page .fenix-page-body .chip-pill span[data-editable] {
    color: inherit;
}
/* Workshop Standard hero — dark text on light wash (not fenix-hero-scrim white-on-photo). */
.fenix-page .fenix-page-body .fenix-hero-light .chip-pill {
    background: var(--fenix-color-surface, #ffffff);
    border-color: var(--fenix-color-border, #e2e8f0);
    color: var(--fenix-color-text-muted, #475569);
}
.fenix-page .fenix-page-body .fenix-hero-light button.btn-ghost,
.fenix-page .fenix-page-body .fenix-hero-light [data-share-button].btn-ghost {
    background: #ffffff;
    border: 1px solid var(--fenix-color-border, #e2e8f0);
    color: var(--fenix-color-text-muted, #475569);
}
/* ─── Theme-bound CTA vocabulary (Fix Editability Tier B — 2026-06-06) ─────────
   Register → fenix-cta-primary (filled). Share → fenix-cta-secondary (surface fill + outline).
   Colour + radius come from the page's FenixThemeProfile via fenix-theme-vars
   (--fenix-color-primary, --fenix-radius-btn). Do NOT hardcode pill shape here —
   profile 1 Rose uses radiusButton 8px; Sage uses 999px. */
.fenix-page .fenix-page-body a.fenix-cta-primary,
.fenix-page .fenix-page-body button.fenix-cta-primary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 28px;
    min-height: 48px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    color: #ffffff !important;
    background-color: var(--fenix-color-primary, var(--color-primary, #c9437f)) !important;
    border: none;
    box-shadow: 0 8px 24px -12px rgba(0, 0, 0, 0.35);
    border-radius: var(--fenix-radius-btn, var(--radius-btn, 0.75rem)) !important;
}
.fenix-page .fenix-page-body a.fenix-cta-secondary,
.fenix-page .fenix-page-body button.fenix-cta-secondary,
.fenix-page .fenix-page-body button.fenix-cta-share.fenix-cta-secondary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 28px;
    min-height: 48px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    color: var(--fenix-color-primary, var(--color-primary, #c9437f)) !important;
    background-color: var(--fenix-color-surface, var(--color-surface, #ffffff)) !important;
    border: 2px solid var(--fenix-color-primary, var(--color-primary, #c9437f)) !important;
    box-shadow: none;
    border-radius: var(--fenix-radius-btn, var(--radius-btn, 0.75rem)) !important;
}
.fenix-page .fenix-page-body a.fenix-cta-secondary:hover,
.fenix-page .fenix-page-body button.fenix-cta-secondary:hover {
    background-color: var(--fenix-color-primary-light, var(--color-primary-light, #f4d6e3)) !important;
}

/* Page-builder canvas — sections render inside .builder-section, not .fenix-page-body. */
.builder-section a.fenix-cta-primary,
.builder-section button.fenix-cta-primary,
.builder-section a.fenix-cta-secondary,
.builder-section button.fenix-cta-secondary,
.builder-section button.fenix-cta-share.fenix-cta-secondary {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 28px;
    min-height: 48px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    border-radius: var(--fenix-radius-btn, var(--radius-btn, 0.75rem)) !important;
}
.builder-section a.fenix-cta-primary,
.builder-section button.fenix-cta-primary {
    color: #ffffff !important;
    background-color: var(--fenix-color-primary, var(--color-primary, #c9437f)) !important;
    border: none;
    box-shadow: 0 8px 24px -12px rgba(0, 0, 0, 0.35);
}
.builder-section a.fenix-cta-secondary,
.builder-section button.fenix-cta-secondary,
.builder-section button.fenix-cta-share.fenix-cta-secondary {
    color: var(--fenix-color-primary, var(--color-primary, #c9437f)) !important;
    background-color: var(--fenix-color-surface, var(--color-surface, #ffffff)) !important;
    border: 2px solid var(--fenix-color-primary, var(--color-primary, #c9437f)) !important;
    box-shadow: none;
}

/* Workshop Standard CTAs — OPT-IN via .btn-primary / [data-field="ctaRegister"] ONLY.
   Do NOT style by href*="/workshops/register/" — that fought template utility classes
   (rounded-full, px-8 py-4) and made register/WhatsApp siblings diverge in builder
   and on the live page. Artistic templates own CTA chrome in HTML; page-234 style
   templates add .btn-primary explicitly. */
.fenix-page .fenix-page-body a.btn-primary,
.fenix-page .fenix-page-body a.t-bg.btn-primary,
.fenix-page .fenix-page-body a[data-field="ctaRegister"] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 28px;
    min-height: 48px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    color: #ffffff !important;
    background-color: var(--fenix-color-primary, var(--color-primary, #c9437f)) !important;
    border: none;
    box-shadow: 0 8px 24px -12px rgba(0, 0, 0, 0.35);
    border-radius: var(--fenix-radius-btn, var(--radius-btn, 0.75rem)) !important;
}
/* Share with fenix-cta-primary wins over legacy btn-dark (repair strips btn-dark). */
.fenix-page .fenix-page-body [data-share-button].btn-dark:not(.fenix-cta-primary) {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 28px;
    min-height: 48px;
    border-radius: var(--fenix-radius-btn, var(--radius-btn, 0.75rem)) !important;
    font-size: 16px;
    font-weight: 700;
    line-height: 1.2;
    text-decoration: none;
    cursor: pointer;
    color: #ffffff !important;
    background-color: var(--color-dark, #1e293b) !important;
    border: none;
    box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.2);
}
.fenix-page .fenix-page-body button.btn-ghost,
.fenix-page .fenix-page-body [data-share-button].btn-ghost {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 12px 22px;
    min-height: 48px;
    border-radius: 12px;
    font-size: 15px;
    font-weight: 500;
    cursor: pointer;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid var(--fenix-color-border, rgba(255, 255, 255, 0.35));
    color: var(--fenix-color-text-muted, rgba(255, 255, 255, 0.82));
}
.fenix-page .fenix-page-body a.btn-secondary,
.fenix-page .fenix-page-body a.btn-secondary.t-border,
.fenix-page .fenix-page-body a.fenix-whatsapp-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 14px 28px;
    min-height: 48px;
    margin-top: 0;
    border-radius: 12px;
    font-size: 16px;
    font-weight: 600;
    line-height: 1.2;
    text-decoration: none;
    color: var(--fenix-color-primary, var(--color-primary, #c9437f)) !important;
    background-color: var(--fenix-color-surface, var(--color-surface, #ffffff));
    border: 2px solid var(--fenix-color-primary, var(--color-primary, #c9437f));
    box-shadow: none;
}
.fenix-page .fenix-page-body a.btn-secondary:hover,
.fenix-page .fenix-page-body a.fenix-whatsapp-cta:hover {
    background-color: var(--fenix-color-primary-light, var(--color-primary-light, #f4d6e3));
}
.fenix-page .fenix-page-body .flex.flex-wrap.items-center a.btn-primary + a.fenix-whatsapp-cta,
.fenix-page .fenix-page-body .flex.flex-wrap.items-center a.fenix-whatsapp-cta + a.btn-primary,
.fenix-page .fenix-page-body .flex.flex-wrap.items-center a.btn-primary + a.btn-secondary,
.fenix-page .fenix-page-body .flex.flex-wrap.items-center a.btn-secondary + a.btn-primary {
    margin-top: 0;
}
/* Explicit rounded-full on CTAs beats btn-* fixed radius (hero split-right WhatsApp pill) */
.fenix-page .fenix-page-body a.rounded-full,
.fenix-page .fenix-page-body a.btn-secondary.rounded-full,
.fenix-page .fenix-page-body a.btn-primary.rounded-full,
.builder-section a.rounded-full,
.builder-section a.btn-secondary.rounded-full,
.builder-section a.btn-primary.rounded-full {
    border-radius: 9999px !important;
}

/* ─── Page-level decoration layer (v1.69, 2026-05-06) ───────────────────────────
   Body-level fixed background with three blurred blobs, sitting BEHIND every
   section regardless of section bg-* utilities. Activated by setting
   FenixPage.BackgroundDecorationKey on a per-page basis. Render.cshtml emits
   <div class="fenix-page-deco fenix-page-deco--{key}"> with three .blob children.

   Why this design:
   • z-index: -1 (not -10) so the layer outranks the page's white root but stays
     beneath all content. Sections without their own bg paint show the decoration;
     sections with explicit bg-white obscure it (intentional — content sections
     stay clean).
   • mix-blend-multiply + blur(64px) + low opacity matches the GVTheme home-3.html
     mockup recipe so it reads as a tinted wash, not a flat circle.
   • Each preset overrides only colour vars on the parent — children inherit. */
.fenix-page-deco {
    position: fixed;
    inset: 0;
    overflow: hidden;
    pointer-events: none;
    z-index: -1;
}
.fenix-page-deco__blob {
    position: absolute;
    border-radius: 9999px;
    mix-blend-mode: multiply;
    filter: blur(64px);
    opacity: 0.55;
}
.fenix-page-deco__blob--a {
    top: 0;
    right: 0;
    width: 800px;
    height: 800px;
    background-color: var(--fenix-deco-color-a, rgba(236, 72, 153, 0.3));
}
.fenix-page-deco__blob--b {
    top: 50%;
    left: -10rem;
    width: 600px;
    height: 600px;
    background-color: var(--fenix-deco-color-b, rgba(236, 72, 153, 0.25));
}
.fenix-page-deco__blob--c {
    bottom: 0;
    right: 25%;
    width: 500px;
    height: 500px;
    background-color: var(--fenix-deco-color-c, rgba(253, 230, 138, 0.5));
}

/* AI-generated decorative blob (class `.fenix-blob`, optionally `.fenix-blob-in`).
   Wizard / Stitch generations sometimes emit per-SECTION floating blobs as
   <div class="fenix-blob" style="width:..;height:..;top:..;left:..;transform:.."> —
   meant to be soft brand-tinted circles floating BEHIND the section content. They carry
   their own size/position inline, and assume `position:absolute`. Without a rule for the
   class the elements default to `position:static; display:block`, so each one occupies
   420–680px of REAL vertical space at the top of its section and shoves all content down
   (the "unusually large top padding on every section" bug). Pin them so they float behind
   content and contribute ZERO layout height. The parent <section> is position:relative via
   the renderSection wrapper, so absolute here resolves against the section. */
section { position: relative; }
/* 2026-06-04 — Decorative per-section blobs DISABLED globally (user: "not nice anyway, totally
   disable it"). The deterministic strip pass (FenixSectionEditabilityRepairer.StripDecorativeBlobs)
   removes .fenix-blob from NEW generations/redesigns/publishes; this display:none also hides any
   blob already BAKED into an existing page's snapshot, so old pages go clean with NO re-publish.
   To re-enable, restore the original .fenix-blob radial-gradient rule. */
.fenix-blob, .fenix-blob-in { display: none !important; }

/* Pink — uses the active brand's --rgb-primary so each preset (GVT, Indigo,
   Vplus, etc.) gets its own primary blob hue automatically. Alphas halved
   from initial v1.69 tuning — the original 0.30/0.25/0.40 read as a strong
   pink wash on white pages; 0.15/0.12/0.20 keeps the same palette but lets
   it sit behind content as soft decoration rather than a dominant tint. */
.fenix-page-deco--pink {
    --fenix-deco-color-a: rgba(var(--rgb-primary, 236, 72, 153), 0.15);
    --fenix-deco-color-b: rgba(var(--rgb-primary, 236, 72, 153), 0.12);
    --fenix-deco-color-c: rgba(253, 224, 71, 0.20);  /* amber-300 warm accent */
}
.fenix-page-deco--mint {
    --fenix-deco-color-a: rgba(110, 231, 183, 0.45);  /* emerald-300 */
    --fenix-deco-color-b: rgba(94, 234, 212, 0.40);   /* teal-300 */
    --fenix-deco-color-c: rgba(165, 243, 252, 0.50);  /* cyan-200 */
}
.fenix-page-deco--lavender {
    --fenix-deco-color-a: rgba(196, 181, 253, 0.45);  /* violet-300 */
    --fenix-deco-color-b: rgba(216, 180, 254, 0.40);  /* purple-300 */
    --fenix-deco-color-c: rgba(191, 219, 254, 0.45);  /* blue-200 */
}
.fenix-page-deco--peach {
    --fenix-deco-color-a: rgba(253, 186, 116, 0.45);  /* orange-300 */
    --fenix-deco-color-b: rgba(252, 165, 165, 0.40);  /* red-300 */
    --fenix-deco-color-c: rgba(253, 224, 71, 0.40);   /* amber-300 */
}
.fenix-page-deco--sky {
    --fenix-deco-color-a: rgba(125, 211, 252, 0.50);  /* sky-300 */
    --fenix-deco-color-b: rgba(147, 197, 253, 0.45);  /* blue-300 */
    --fenix-deco-color-c: rgba(165, 243, 252, 0.45);  /* cyan-200 */
}
.fenix-page-deco--grey {
    --fenix-deco-color-a: rgba(148, 163, 184, 0.45);  /* slate-400 */
    --fenix-deco-color-b: rgba(100, 116, 139, 0.40);  /* slate-500 */
    --fenix-deco-color-c: rgba(203, 213, 225, 0.45);  /* slate-300 */
}
.fenix-page-deco--red {
    --fenix-deco-color-a: rgba(252, 165, 165, 0.45);  /* red-300 */
    --fenix-deco-color-b: rgba(248, 113, 113, 0.40);  /* red-400 */
    --fenix-deco-color-c: rgba(253, 224, 71, 0.40);   /* amber-300 warm accent */
}

/* Per-page opacity multiplier (v1.70.6) — Render.cshtml emits
   `style="--fenix-deco-alpha:0.6"` on the `.fenix-page-deco` wrapper when
   the saved key carries a `:0.6` suffix. The opacity rule below multiplies
   the blob layer's intrinsic opacity by that factor, giving editors a
   brightness/dimness dial without re-tuning every preset's RGBA. Default
   = 1.0 keeps original tuning. */
.fenix-page-deco {
    opacity: calc(var(--fenix-deco-alpha, 1) * 1);
}

/* When deco is active, neutralise the default bg-white that the page-builder
   bakes into every .builder-section wrapper — otherwise each section paints
   an opaque white slab over the deco layer and you only see the wash in the
   gaps (e.g. behind the breadcrumb).
   • Only targets .builder-section bg-white (the outer wrapper). Inner
     <section> tags with bg-* utilities (dark CTA, coloured cards) keep theirs.
   • Use background:transparent (not "remove the class") so the original Tailwind
     remains intact for any non-deco pages and for the page-builder canvas iframe.
   • Scoped to .fenix-page .fenix-page-deco ~ * so it only applies on pages that
     actually rendered a deco layer. */
.fenix-page:has(.fenix-page-deco) .builder-section.bg-white {
    background-color: transparent;
}
/* Component wrappers also paint a white background in some renderer paths. */
.fenix-page:has(.fenix-page-deco) .component-wrapper {
    background-color: transparent;
}

/* Hero progress card — keep the card surface above its sibling decorative
   blobs so the blobs ring the card from outside instead of bleeding onto
   its rounded top-right / bottom-left corners. The mockup placed amber
   `-top-4 -right-4` and pink `-bottom-8 -left-8` blur-xl blobs as siblings
   of the card; without z-index ordering they paint over the card and look
   like the card has notches cut out of it. Targeting the specific class
   combo so this rule only touches the hero card. */
.fenix-page .relative.bg-white.rounded-\[3rem\].p-8.shadow-xl {
    z-index: 1;
}

/* Hero video background — keep the dark gradient overlay above the <video> plane
   and below z-10 content. Mirrors the page-builder stacking fix (v5.15+). */
.fenix-page section > video.absolute + .absolute.inset-0,
.fenix-page section > .fenix-editable-video-wrap + .absolute.inset-0 {
    z-index: 2;
}

/* Watch Video lightbox — public render of [data-watch-video] play buttons */
.fenix-video-lightbox {
    position: fixed;
    inset: 0;
    z-index: 10050;
    display: none;
    align-items: center;
    justify-content: center;
    padding: 2rem;
    background: rgba(0, 0, 0, 0.9);
}

.fenix-video-lightbox.is-open {
    display: flex;
}

body.fenix-video-lightbox-open {
    overflow: hidden;
}

.fenix-video-lightbox__panel {
    position: relative;
    width: min(90vw, 1200px);
    aspect-ratio: 16 / 9;
    max-height: 90vh;
}

.fenix-video-lightbox__player {
    width: 100%;
    height: 100%;
    background: #000;
    border-radius: 0.5rem;
}

.fenix-video-lightbox__close {
    position: absolute;
    top: -2.75rem;
    right: 0;
    border: none;
    background: transparent;
    color: #fff;
    font-size: 2rem;
    line-height: 1;
    cursor: pointer;
    padding: 0.25rem 0.5rem;
}

.fenix-video-lightbox__close:hover {
    opacity: 0.75;
}

.fenix-page [data-watch-video] {
    cursor: pointer;
}

/* When deco is active, card shadows lose their definition because the wash
   behind reduces contrast between the card edge and surrounding canvas.
   Boost any rounded white card with a weak `shadow-sm` so the card body
   reads cleanly against the tinted background. Targets cards that opted in
   to a non-trivial border-radius (rounded-2xl/3xl/[2rem]/[3rem]) so we don't
   restyle every plain Tailwind utility container. */
.fenix-page:has(.fenix-page-deco) .bg-white.shadow-sm[class*="rounded-"] {
    box-shadow:
        0 1px 2px rgba(15, 23, 42, 0.04),
        0 8px 24px -8px rgba(15, 23, 42, 0.10);
}

/* Hide in-template "decorative blobs" inside dark sections (v1.69.5).
   Templates like the dark CTA "What Opens for You" bake low-alpha pink
   blobs (`bg-pink-500/10 blur-3xl`) into their inner DOM as a built-in
   glow. With the page-level deco layer doing this job globally, those
   in-template blobs become redundant — and they read as edge-bleed against
   the dark section background instead of the subtle accent the mockup
   intended. Specifically targets ABSOLUTELY-POSITIONED, POINTER-EVENTS-NONE
   blobs with blur — the unmistakable decorative signature. This avoids
   wiping legitimate content cards which use `backdrop-blur-sm` (no `blur-*`
   class), are not absolute, and respond to clicks. */
.fenix-page .builder-section[class*="bg-slate-8"] .absolute[class*="blur-"].pointer-events-none,
.fenix-page .builder-section[class*="bg-slate-9"] .absolute[class*="blur-"].pointer-events-none,
.fenix-page .builder-section[class*="bg-zinc-8"]  .absolute[class*="blur-"].pointer-events-none,
.fenix-page .builder-section[class*="bg-zinc-9"]  .absolute[class*="blur-"].pointer-events-none,
.fenix-page .builder-section[class*="bg-gradient-to-"] .absolute[class*="blur-"].pointer-events-none,
.fenix-page section[class*="bg-slate-8"] .absolute[class*="blur-"].pointer-events-none,
.fenix-page section[class*="bg-slate-9"] .absolute[class*="blur-"].pointer-events-none,
.fenix-page section[class*="bg-gradient-to-"] .absolute[class*="blur-"].pointer-events-none {
    display: none;
}

/* Full-bleed builder-sections (v1.69.4) — when the page-builder Section
   Style modal applies a heavy outer background (dark, brand-coloured), the
   bg sits on the .builder-section wrapper which is bound to the page's
   max-width container (typically ~1741px on a wide viewport). With a deco
   layer behind, anything narrower than 100vw shows pink slivers on the
   sides flanking the dark slab.

   Fix: when deco is active, break .builder-section elements with a heavy
   bg out of their max-width container so the colour paints viewport-edge-
   to-edge. Light backgrounds (white/cream) are skipped — those don't fight
   the deco wash and shouldn't go full-bleed.

   Implementation: standard "full-bleed inside a max-width parent" trick.
   `width: 100vw` + `margin-left: 50%` + `transform: translateX(-50%)`.
   Targets .builder-section AND any inner <section> with opaque bg classes
   (covers both the page-builder rendered chrome AND the legacy template
   sections that had bg-* baked into the inner <section>). */
.fenix-page:has(.fenix-page-deco) .builder-section[class*="bg-slate-8"],
.fenix-page:has(.fenix-page-deco) .builder-section[class*="bg-slate-9"],
.fenix-page:has(.fenix-page-deco) .builder-section[class*="bg-zinc-8"],
.fenix-page:has(.fenix-page-deco) .builder-section[class*="bg-zinc-9"],
.fenix-page:has(.fenix-page-deco) .builder-section[class*="bg-neutral-8"],
.fenix-page:has(.fenix-page-deco) .builder-section[class*="bg-neutral-9"],
.fenix-page:has(.fenix-page-deco) .builder-section[class*="bg-gradient-to-"],
.fenix-page:has(.fenix-page-deco) section[class*="bg-gradient-to-"],
.fenix-page:has(.fenix-page-deco) section[class*="bg-slate-8"],
.fenix-page:has(.fenix-page-deco) section[class*="bg-slate-9"],
.fenix-page:has(.fenix-page-deco) section[class*="bg-zinc-8"],
.fenix-page:has(.fenix-page-deco) section[class*="bg-zinc-9"],
.fenix-page:has(.fenix-page-deco) section[class*="bg-neutral-8"],
.fenix-page:has(.fenix-page-deco) section[class*="bg-neutral-9"] {
    width: 100vw;
    margin-left: 50%;
    transform: translateX(-50%);
    max-width: 100vw;
}

/* ─── Tailwind utility backfill (Phase 2 slim — 2026-06-06) ───────────────────
   GVTheme/output.css in <head> owns all standard Tailwind utilities (flex, grid,
   spacing, max-w, responsive sm:/md:/lg:, container @md:flex-row, etc.).
   This block keeps ONLY rules output.css cannot provide:
   • theme-token colour remaps (text-pink-* → var(--color-primary))
   • prose defaults (no Typography plugin on live pages)
   • h1.font-medium beats global heading-weight
   Do NOT re-add .fenix-page-body duplicates of output.css utilities — higher
   specificity here blocked responsive variants (quotation text-3xl bug). */

/* Theme-aware brand text — mirror wizard/dist/theme.css .gvt-page mapping so
   legacy text-pink-* in titleHtml accents follow the page theme (Sage, Coral, …). */
.fenix-page-body .text-pink-500,
.fenix-page-body .text-rose-500,
.fenix-page-body .text-pink-600,
.fenix-page-body .text-rose-600 { color: var(--color-primary, #ec4899); }
.fenix-page-body .text-pink-400,
.fenix-page-body .text-rose-400 { color: var(--color-primary-hover, #db2777); }
.fenix-page-body .text-pink-700 { color: var(--color-primary-dark, #be185d); }

/* prose utility — workshop description has class="prose prose-lg prose-slate".
   We don't load Typography plugin; just give it sensible defaults so paragraphs
   don't shrink and bullets stay readable. */
.fenix-page-body .prose p { margin-bottom: 1em; }
.fenix-page-body .prose-lg p { font-size: 1.125rem; line-height: 1.7; }
.fenix-page-body .prose ul { margin-bottom: 1em; }
.fenix-page-body .lead { font-size: 1.125rem; line-height: 1.7; }

/* ─── Workshop hero responsive layout (Section A.5: mobile reorder) ──────────
   Mobile (< 768px): flat vertical stack in this order:
     1. ws-hero-image
     2. ws-hero-content (Title + Subtitle + Description)
     3. ws-hero-booking
     4. ws-hero-trainer
     5. ws-hero-faq

   Desktop (≥ 768px): two-column grid mirroring the original mockup:
     ┌──────────┬──────────┐
     │  image   │ content  │
     │  booking │ trainer  │
     │          │   faq    │
     └──────────┴──────────┘
   image+booking pinned to left column (booking widget keeps its sticky top-24
   behaviour relative to the image), content+trainer+faq flow down right column.
   Implementation: grid-template-areas for explicit area-name placement. */
.fenix-page-body .ws-hero-grid,
.builder-section .ws-hero-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 3rem;
}

.fenix-page-body .ws-hero-image   { margin-bottom: 0; }
.fenix-page-body .ws-hero-content { margin-bottom: 0; }
.fenix-page-body .ws-hero-booking { margin-bottom: 0; }
.fenix-page-body .ws-hero-trainer { margin-bottom: 0; }
.fenix-page-body .ws-hero-faq     { margin-bottom: 0; }

@media (min-width: 768px) {
    .fenix-page-body .ws-hero-grid,
    .builder-section .ws-hero-grid {
        grid-template-columns: 1fr 1fr;
        grid-template-areas:
            "image   content"
            "booking trainer"
            "booking faq";
        gap: 3rem;
    }
    .fenix-page-body .ws-hero-image   { grid-area: image; }
    .fenix-page-body .ws-hero-content { grid-area: content; }
    .fenix-page-body .ws-hero-booking { grid-area: booking; }
    .fenix-page-body .ws-hero-trainer { grid-area: trainer; }
    .fenix-page-body .ws-hero-faq     { grid-area: faq; }
}

@media (min-width: 1024px) {
    .fenix-page-body .ws-hero-grid,
    .builder-section .ws-hero-grid { gap: 6rem; }
}

/* ============================================================
   nopCommerce Add to Cart Button widget (2026-05-17, Checkpoint B)
   Hydration component — fenix-nop-commerce.js enables the button.
   ============================================================ */
.fenix-nop-add-to-cart { margin: 1.5rem 0; }
/* Stepper injected by the hydrator when data-show-qty="1" — centred so it lines
   up with the button inside the .text-center skeleton. */
.fenix-nop-add-to-cart .fenix-nop-qty { justify-content: center; margin-bottom: 12px; }
.fenix-nop-add-to-cart__btn {
    background: var(--fenix-color-primary, var(--color-primary, #c9437f));
    color: #fff;
    border: 0;
    cursor: pointer;
    transition: background 0.16s ease, opacity 0.16s ease;
}
.fenix-nop-add-to-cart__btn:hover:not([disabled]) {
    background: var(--fenix-color-primary-hover, var(--color-primary-hover, #a82e6c));
}
.fenix-nop-add-to-cart__btn[disabled] { opacity: 0.55; cursor: default; }
/* Unconfigured / edit-mode hint — only visible in the builder; the
   RenderedHtmlSanitizer strips __edit-hint from the public snapshot. */
.fenix-nop-add-to-cart__empty {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 20px;
    border: 1px dashed var(--fenix-color-primary-light, var(--color-primary-light, #f4d6e3));
    border-radius: 12px;
    background: var(--color-primary-light-soft, var(--fenix-color-primary-light, #f4d6e3));
    color: #64748b;
}
.fenix-nop-add-to-cart__empty i {
    font-size: 22px;
    color: var(--fenix-color-primary, var(--color-primary, #c9437f));
}
.fenix-nop-add-to-cart__empty strong { color: #1e293b; font-size: 14px; }
.fenix-nop-add-to-cart__empty p { margin: 2px 0 0; font-size: 12.5px; }
.fenix-nop-add-to-cart__edit-hint {
    margin-top: 8px;
    font-size: 11.5px;
    color: #94a3b8;
    text-align: center;
}

/* ============================================================
   nopCommerce Product Widgets (2026-05-17)
   Gallery / Title / Price / Quantity / Buy Box — composable
   product-detail blocks. Styled to the Lumière reference.
   ============================================================ */

/* --- shared skeleton + states (picked-mode placeholders) --- */
.fenix-nop-product__skeleton {
    min-height: 1.4em;
    border-radius: 8px;
    background: linear-gradient(90deg, #f1f4f7 25%, #e8ecf1 37%, #f1f4f7 63%);
    background-size: 400% 100%;
    animation: fenix-nop-shimmer 1.4s ease infinite;
}
.fenix-nop-product__skeleton--title { min-height: 2.6em; }
@keyframes fenix-nop-shimmer {
    0%   { background-position: 100% 0; }
    100% { background-position: -100% 0; }
}
.fenix-nop-product__edit-hint {
    margin-top: 6px;
    font-size: 11.5px;
    color: #94a3b8;
}
.fenix-nop-product__error {
    font-size: 13px;
    color: #94a3b8;
    font-style: italic;
}

/* --- Product Gallery --- */
.fenix-nop-product-gallery__main {
    position: relative;
    border-radius: 20px;
    overflow: hidden;
    background: #eef4f7;
    aspect-ratio: 1 / 1;
}
.fenix-nop-product-gallery__main img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.fenix-nop-product-gallery__badge:empty { display: none; }
.fenix-nop-product-gallery__badge {
    position: absolute;
    top: 18px;
    right: 18px;
    padding: 8px 18px;
    border-radius: 999px;
    background: #ff8c42;
    color: #fff;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
}
.fenix-nop-product-gallery__thumbs {
    display: flex;
    gap: 12px;
    margin-top: 14px;
}
.fenix-nop-product-gallery__thumbs img {
    width: 76px;
    height: 76px;
    object-fit: cover;
    border-radius: 12px;
    border: 2px solid transparent;
    cursor: pointer;
    transition: border-color 0.15s ease;
}
.fenix-nop-product-gallery__thumbs img:hover { border-color: #cbd5e1; }
.fenix-nop-product-gallery__thumbs img.is-active { border-color: #1a2940; }
/* hide empty thumbnail slots (product has <3 images) */
.fenix-nop-product-gallery__thumbs img:not([src]),
.fenix-nop-product-gallery__thumbs img[src=""] { display: none; }

/* --- Product Title --- */
.fenix-nop-product-title__category {
    margin: 0 0 10px;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    color: #94a3b8;
}
.fenix-nop-product-title__category:empty { display: none; }
.fenix-nop-product-title__name {
    margin: 0 0 14px;
    font-size: clamp(2rem, 4vw, 3.2rem);
    line-height: 1.1;
    font-weight: 800;
    color: #1a2940;
}
.fenix-nop-product-title__rating {
    display: flex;
    align-items: center;
    gap: 10px;
}
.fenix-nop-product-title__stars { color: #ffc83d; font-size: 18px; letter-spacing: 2px; }
.fenix-nop-product-title__rating-text { font-size: 14px; color: #6c757d; }

/* --- Product Price --- */
.fenix-nop-product-price {
    display: flex;
    align-items: center;
    gap: 16px;
    flex-wrap: wrap;
}
.fenix-nop-product-price__old:empty { display: none; }
.fenix-nop-product-price__old {
    font-size: 22px;
    font-weight: 600;
    color: #94a3b8;
    text-decoration: line-through;
}
.fenix-nop-product-price__now {
    font-size: 40px;
    font-weight: 800;
    color: #1a2940;
}
.fenix-nop-product-price__save {
    padding: 7px 16px;
    border-radius: 999px;
    background: #ef4444;
    color: #fff;
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}
/* hide the save badge when savePercent resolved empty ("Save %") */
.fenix-nop-product-price__save:empty { display: none; }

/* --- Quantity stepper --- */
.fenix-nop-qty {
    display: flex;
    align-items: center;
    gap: 16px;
}
.fenix-nop-qty__label {
    font-size: 13px;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #1a2940;
}
.fenix-nop-qty__controls {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 6px;
    border-radius: 999px;
    background: #f1f4f7;
}
.fenix-nop-qty__btn {
    width: 38px;
    height: 38px;
    border: 0;
    border-radius: 50%;
    background: #1a2940;
    color: #fff;
    font-size: 18px;
    line-height: 1;
    cursor: pointer;
    transition: background 0.15s ease, opacity 0.15s ease;
}
.fenix-nop-qty__btn:hover { background: #2c3e50; }
.fenix-nop-qty__btn:disabled { opacity: 0.4; cursor: default; }
.fenix-nop-qty__value {
    width: 48px;
    border: 0;
    background: transparent;
    text-align: center;
    font-size: 16px;
    font-weight: 700;
    color: #1a2940;
}

/* --- Buy Box --- */
.fenix-nop-buy-box {
    display: flex;
    flex-direction: column;
    gap: 18px;
}
.fenix-nop-buy-box__actions {
    display: flex;
    gap: 14px;
    flex-wrap: wrap;
}
.fenix-nop-buy-box__cart,
.fenix-nop-buy-box__wishlist {
    flex: 1 1 200px;
    padding: 16px 28px;
    border-radius: 999px;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    cursor: pointer;
    transition: background 0.15s ease, color 0.15s ease, opacity 0.15s ease;
}
.fenix-nop-buy-box__cart {
    border: 2px solid #1a2940;
    background: #1a2940;
    color: #fff;
}
.fenix-nop-buy-box__cart:hover:not(:disabled) { background: #2c3e50; }
.fenix-nop-buy-box__wishlist {
    border: 2px solid #1a2940;
    background: transparent;
    color: #1a2940;
}
.fenix-nop-buy-box__wishlist:hover:not(:disabled) { background: #1a2940; color: #fff; }
.fenix-nop-buy-box__cart:disabled,
.fenix-nop-buy-box__wishlist:disabled { opacity: 0.5; cursor: default; }

/* ──────────────────────────────────────────────────────────────────────
   Grid utility backfill (2026-06-03). The compiled Tailwind bundles (public
   WebOptimizer .styles.css AND the builder's dist/output.css) were purged
   against the OLD pages' usage and ship only col-span-1..5 / no grid-cols-6..12.
   The editorial redesigns use lg:grid-cols-12 + lg:col-span-7/9, which then fell
   back to 'auto' — a col-span-9 text column collapsed to ~44px (letter-by-letter
   wrapping). This backfills the full responsive set, scoped to BOTH the public
   page (.fenix-page) and the builder canvas (#canvas), never leaking to Studio
   chrome. fenix-page.css is loaded by both surfaces.
   ────────────────────────────────────────────────────────────────────── */
/* base */
.fenix-page .grid-cols-1, #canvas .grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
.fenix-page .grid-cols-2, #canvas .grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
.fenix-page .grid-cols-3, #canvas .grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.fenix-page .grid-cols-4, #canvas .grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
.fenix-page .grid-cols-5, #canvas .grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
.fenix-page .grid-cols-6, #canvas .grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
.fenix-page .grid-cols-7, #canvas .grid-cols-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); }
.fenix-page .grid-cols-8, #canvas .grid-cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
.fenix-page .grid-cols-9, #canvas .grid-cols-9 { grid-template-columns: repeat(9, minmax(0, 1fr)); }
.fenix-page .grid-cols-10, #canvas .grid-cols-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); }
.fenix-page .grid-cols-11, #canvas .grid-cols-11 { grid-template-columns: repeat(11, minmax(0, 1fr)); }
.fenix-page .grid-cols-12, #canvas .grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
.fenix-page .col-span-1, #canvas .col-span-1 { grid-column: span 1 / span 1; }
.fenix-page .col-span-2, #canvas .col-span-2 { grid-column: span 2 / span 2; }
.fenix-page .col-span-3, #canvas .col-span-3 { grid-column: span 3 / span 3; }
.fenix-page .col-span-4, #canvas .col-span-4 { grid-column: span 4 / span 4; }
.fenix-page .col-span-5, #canvas .col-span-5 { grid-column: span 5 / span 5; }
.fenix-page .col-span-6, #canvas .col-span-6 { grid-column: span 6 / span 6; }
.fenix-page .col-span-7, #canvas .col-span-7 { grid-column: span 7 / span 7; }
.fenix-page .col-span-8, #canvas .col-span-8 { grid-column: span 8 / span 8; }
.fenix-page .col-span-9, #canvas .col-span-9 { grid-column: span 9 / span 9; }
.fenix-page .col-span-10, #canvas .col-span-10 { grid-column: span 10 / span 10; }
.fenix-page .col-span-11, #canvas .col-span-11 { grid-column: span 11 / span 11; }
.fenix-page .col-span-12, #canvas .col-span-12 { grid-column: span 12 / span 12; }
.fenix-page .col-span-full, #canvas .col-span-full { grid-column: 1 / -1; }
.fenix-page .col-start-1, #canvas .col-start-1 { grid-column-start: 1; }
.fenix-page .col-start-2, #canvas .col-start-2 { grid-column-start: 2; }
.fenix-page .col-start-3, #canvas .col-start-3 { grid-column-start: 3; }
.fenix-page .col-start-4, #canvas .col-start-4 { grid-column-start: 4; }
.fenix-page .col-start-5, #canvas .col-start-5 { grid-column-start: 5; }
.fenix-page .col-start-6, #canvas .col-start-6 { grid-column-start: 6; }
.fenix-page .col-start-7, #canvas .col-start-7 { grid-column-start: 7; }
.fenix-page .col-start-8, #canvas .col-start-8 { grid-column-start: 8; }
.fenix-page .col-start-9, #canvas .col-start-9 { grid-column-start: 9; }
.fenix-page .col-start-10, #canvas .col-start-10 { grid-column-start: 10; }
.fenix-page .col-start-11, #canvas .col-start-11 { grid-column-start: 11; }
.fenix-page .col-start-12, #canvas .col-start-12 { grid-column-start: 12; }
.fenix-page .col-start-13, #canvas .col-start-13 { grid-column-start: 13; }
@media (min-width: 640px) {
  .fenix-page .sm\:grid-cols-1, #canvas .sm\:grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-2, #canvas .sm\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-3, #canvas .sm\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-4, #canvas .sm\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-5, #canvas .sm\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-6, #canvas .sm\:grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-7, #canvas .sm\:grid-cols-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-8, #canvas .sm\:grid-cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-9, #canvas .sm\:grid-cols-9 { grid-template-columns: repeat(9, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-10, #canvas .sm\:grid-cols-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-11, #canvas .sm\:grid-cols-11 { grid-template-columns: repeat(11, minmax(0, 1fr)); }
  .fenix-page .sm\:grid-cols-12, #canvas .sm\:grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .fenix-page .sm\:col-span-1, #canvas .sm\:col-span-1 { grid-column: span 1 / span 1; }
  .fenix-page .sm\:col-span-2, #canvas .sm\:col-span-2 { grid-column: span 2 / span 2; }
  .fenix-page .sm\:col-span-3, #canvas .sm\:col-span-3 { grid-column: span 3 / span 3; }
  .fenix-page .sm\:col-span-4, #canvas .sm\:col-span-4 { grid-column: span 4 / span 4; }
  .fenix-page .sm\:col-span-5, #canvas .sm\:col-span-5 { grid-column: span 5 / span 5; }
  .fenix-page .sm\:col-span-6, #canvas .sm\:col-span-6 { grid-column: span 6 / span 6; }
  .fenix-page .sm\:col-span-7, #canvas .sm\:col-span-7 { grid-column: span 7 / span 7; }
  .fenix-page .sm\:col-span-8, #canvas .sm\:col-span-8 { grid-column: span 8 / span 8; }
  .fenix-page .sm\:col-span-9, #canvas .sm\:col-span-9 { grid-column: span 9 / span 9; }
  .fenix-page .sm\:col-span-10, #canvas .sm\:col-span-10 { grid-column: span 10 / span 10; }
  .fenix-page .sm\:col-span-11, #canvas .sm\:col-span-11 { grid-column: span 11 / span 11; }
  .fenix-page .sm\:col-span-12, #canvas .sm\:col-span-12 { grid-column: span 12 / span 12; }
  .fenix-page .sm\:col-span-full, #canvas .sm\:col-span-full { grid-column: 1 / -1; }
  .fenix-page .sm\:col-start-1, #canvas .sm\:col-start-1 { grid-column-start: 1; }
  .fenix-page .sm\:col-start-2, #canvas .sm\:col-start-2 { grid-column-start: 2; }
  .fenix-page .sm\:col-start-3, #canvas .sm\:col-start-3 { grid-column-start: 3; }
  .fenix-page .sm\:col-start-4, #canvas .sm\:col-start-4 { grid-column-start: 4; }
  .fenix-page .sm\:col-start-5, #canvas .sm\:col-start-5 { grid-column-start: 5; }
  .fenix-page .sm\:col-start-6, #canvas .sm\:col-start-6 { grid-column-start: 6; }
  .fenix-page .sm\:col-start-7, #canvas .sm\:col-start-7 { grid-column-start: 7; }
  .fenix-page .sm\:col-start-8, #canvas .sm\:col-start-8 { grid-column-start: 8; }
  .fenix-page .sm\:col-start-9, #canvas .sm\:col-start-9 { grid-column-start: 9; }
  .fenix-page .sm\:col-start-10, #canvas .sm\:col-start-10 { grid-column-start: 10; }
  .fenix-page .sm\:col-start-11, #canvas .sm\:col-start-11 { grid-column-start: 11; }
  .fenix-page .sm\:col-start-12, #canvas .sm\:col-start-12 { grid-column-start: 12; }
  .fenix-page .sm\:col-start-13, #canvas .sm\:col-start-13 { grid-column-start: 13; }
}
@media (min-width: 768px) {
  .fenix-page .md\:grid-cols-1, #canvas .md\:grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-2, #canvas .md\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-3, #canvas .md\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-4, #canvas .md\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-5, #canvas .md\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-6, #canvas .md\:grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-7, #canvas .md\:grid-cols-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-8, #canvas .md\:grid-cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-9, #canvas .md\:grid-cols-9 { grid-template-columns: repeat(9, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-10, #canvas .md\:grid-cols-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-11, #canvas .md\:grid-cols-11 { grid-template-columns: repeat(11, minmax(0, 1fr)); }
  .fenix-page .md\:grid-cols-12, #canvas .md\:grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .fenix-page .md\:col-span-1, #canvas .md\:col-span-1 { grid-column: span 1 / span 1; }
  .fenix-page .md\:col-span-2, #canvas .md\:col-span-2 { grid-column: span 2 / span 2; }
  .fenix-page .md\:col-span-3, #canvas .md\:col-span-3 { grid-column: span 3 / span 3; }
  .fenix-page .md\:col-span-4, #canvas .md\:col-span-4 { grid-column: span 4 / span 4; }
  .fenix-page .md\:col-span-5, #canvas .md\:col-span-5 { grid-column: span 5 / span 5; }
  .fenix-page .md\:col-span-6, #canvas .md\:col-span-6 { grid-column: span 6 / span 6; }
  .fenix-page .md\:col-span-7, #canvas .md\:col-span-7 { grid-column: span 7 / span 7; }
  .fenix-page .md\:col-span-8, #canvas .md\:col-span-8 { grid-column: span 8 / span 8; }
  .fenix-page .md\:col-span-9, #canvas .md\:col-span-9 { grid-column: span 9 / span 9; }
  .fenix-page .md\:col-span-10, #canvas .md\:col-span-10 { grid-column: span 10 / span 10; }
  .fenix-page .md\:col-span-11, #canvas .md\:col-span-11 { grid-column: span 11 / span 11; }
  .fenix-page .md\:col-span-12, #canvas .md\:col-span-12 { grid-column: span 12 / span 12; }
  .fenix-page .md\:col-span-full, #canvas .md\:col-span-full { grid-column: 1 / -1; }
  .fenix-page .md\:col-start-1, #canvas .md\:col-start-1 { grid-column-start: 1; }
  .fenix-page .md\:col-start-2, #canvas .md\:col-start-2 { grid-column-start: 2; }
  .fenix-page .md\:col-start-3, #canvas .md\:col-start-3 { grid-column-start: 3; }
  .fenix-page .md\:col-start-4, #canvas .md\:col-start-4 { grid-column-start: 4; }
  .fenix-page .md\:col-start-5, #canvas .md\:col-start-5 { grid-column-start: 5; }
  .fenix-page .md\:col-start-6, #canvas .md\:col-start-6 { grid-column-start: 6; }
  .fenix-page .md\:col-start-7, #canvas .md\:col-start-7 { grid-column-start: 7; }
  .fenix-page .md\:col-start-8, #canvas .md\:col-start-8 { grid-column-start: 8; }
  .fenix-page .md\:col-start-9, #canvas .md\:col-start-9 { grid-column-start: 9; }
  .fenix-page .md\:col-start-10, #canvas .md\:col-start-10 { grid-column-start: 10; }
  .fenix-page .md\:col-start-11, #canvas .md\:col-start-11 { grid-column-start: 11; }
  .fenix-page .md\:col-start-12, #canvas .md\:col-start-12 { grid-column-start: 12; }
  .fenix-page .md\:col-start-13, #canvas .md\:col-start-13 { grid-column-start: 13; }
}
@media (min-width: 1024px) {
  .fenix-page .lg\:grid-cols-1, #canvas .lg\:grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-2, #canvas .lg\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-3, #canvas .lg\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-4, #canvas .lg\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-5, #canvas .lg\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-6, #canvas .lg\:grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-7, #canvas .lg\:grid-cols-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-8, #canvas .lg\:grid-cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-9, #canvas .lg\:grid-cols-9 { grid-template-columns: repeat(9, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-10, #canvas .lg\:grid-cols-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-11, #canvas .lg\:grid-cols-11 { grid-template-columns: repeat(11, minmax(0, 1fr)); }
  .fenix-page .lg\:grid-cols-12, #canvas .lg\:grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .fenix-page .lg\:col-span-1, #canvas .lg\:col-span-1 { grid-column: span 1 / span 1; }
  .fenix-page .lg\:col-span-2, #canvas .lg\:col-span-2 { grid-column: span 2 / span 2; }
  .fenix-page .lg\:col-span-3, #canvas .lg\:col-span-3 { grid-column: span 3 / span 3; }
  .fenix-page .lg\:col-span-4, #canvas .lg\:col-span-4 { grid-column: span 4 / span 4; }
  .fenix-page .lg\:col-span-5, #canvas .lg\:col-span-5 { grid-column: span 5 / span 5; }
  .fenix-page .lg\:col-span-6, #canvas .lg\:col-span-6 { grid-column: span 6 / span 6; }
  .fenix-page .lg\:col-span-7, #canvas .lg\:col-span-7 { grid-column: span 7 / span 7; }
  .fenix-page .lg\:col-span-8, #canvas .lg\:col-span-8 { grid-column: span 8 / span 8; }
  .fenix-page .lg\:col-span-9, #canvas .lg\:col-span-9 { grid-column: span 9 / span 9; }
  .fenix-page .lg\:col-span-10, #canvas .lg\:col-span-10 { grid-column: span 10 / span 10; }
  .fenix-page .lg\:col-span-11, #canvas .lg\:col-span-11 { grid-column: span 11 / span 11; }
  .fenix-page .lg\:col-span-12, #canvas .lg\:col-span-12 { grid-column: span 12 / span 12; }
  .fenix-page .lg\:col-span-full, #canvas .lg\:col-span-full { grid-column: 1 / -1; }
  .fenix-page .lg\:col-start-1, #canvas .lg\:col-start-1 { grid-column-start: 1; }
  .fenix-page .lg\:col-start-2, #canvas .lg\:col-start-2 { grid-column-start: 2; }
  .fenix-page .lg\:col-start-3, #canvas .lg\:col-start-3 { grid-column-start: 3; }
  .fenix-page .lg\:col-start-4, #canvas .lg\:col-start-4 { grid-column-start: 4; }
  .fenix-page .lg\:col-start-5, #canvas .lg\:col-start-5 { grid-column-start: 5; }
  .fenix-page .lg\:col-start-6, #canvas .lg\:col-start-6 { grid-column-start: 6; }
  .fenix-page .lg\:col-start-7, #canvas .lg\:col-start-7 { grid-column-start: 7; }
  .fenix-page .lg\:col-start-8, #canvas .lg\:col-start-8 { grid-column-start: 8; }
  .fenix-page .lg\:col-start-9, #canvas .lg\:col-start-9 { grid-column-start: 9; }
  .fenix-page .lg\:col-start-10, #canvas .lg\:col-start-10 { grid-column-start: 10; }
  .fenix-page .lg\:col-start-11, #canvas .lg\:col-start-11 { grid-column-start: 11; }
  .fenix-page .lg\:col-start-12, #canvas .lg\:col-start-12 { grid-column-start: 12; }
  .fenix-page .lg\:col-start-13, #canvas .lg\:col-start-13 { grid-column-start: 13; }
}
@media (min-width: 1280px) {
  .fenix-page .xl\:grid-cols-1, #canvas .xl\:grid-cols-1 { grid-template-columns: repeat(1, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-2, #canvas .xl\:grid-cols-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-3, #canvas .xl\:grid-cols-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-4, #canvas .xl\:grid-cols-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-5, #canvas .xl\:grid-cols-5 { grid-template-columns: repeat(5, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-6, #canvas .xl\:grid-cols-6 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-7, #canvas .xl\:grid-cols-7 { grid-template-columns: repeat(7, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-8, #canvas .xl\:grid-cols-8 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-9, #canvas .xl\:grid-cols-9 { grid-template-columns: repeat(9, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-10, #canvas .xl\:grid-cols-10 { grid-template-columns: repeat(10, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-11, #canvas .xl\:grid-cols-11 { grid-template-columns: repeat(11, minmax(0, 1fr)); }
  .fenix-page .xl\:grid-cols-12, #canvas .xl\:grid-cols-12 { grid-template-columns: repeat(12, minmax(0, 1fr)); }
  .fenix-page .xl\:col-span-1, #canvas .xl\:col-span-1 { grid-column: span 1 / span 1; }
  .fenix-page .xl\:col-span-2, #canvas .xl\:col-span-2 { grid-column: span 2 / span 2; }
  .fenix-page .xl\:col-span-3, #canvas .xl\:col-span-3 { grid-column: span 3 / span 3; }
  .fenix-page .xl\:col-span-4, #canvas .xl\:col-span-4 { grid-column: span 4 / span 4; }
  .fenix-page .xl\:col-span-5, #canvas .xl\:col-span-5 { grid-column: span 5 / span 5; }
  .fenix-page .xl\:col-span-6, #canvas .xl\:col-span-6 { grid-column: span 6 / span 6; }
  .fenix-page .xl\:col-span-7, #canvas .xl\:col-span-7 { grid-column: span 7 / span 7; }
  .fenix-page .xl\:col-span-8, #canvas .xl\:col-span-8 { grid-column: span 8 / span 8; }
  .fenix-page .xl\:col-span-9, #canvas .xl\:col-span-9 { grid-column: span 9 / span 9; }
  .fenix-page .xl\:col-span-10, #canvas .xl\:col-span-10 { grid-column: span 10 / span 10; }
  .fenix-page .xl\:col-span-11, #canvas .xl\:col-span-11 { grid-column: span 11 / span 11; }
  .fenix-page .xl\:col-span-12, #canvas .xl\:col-span-12 { grid-column: span 12 / span 12; }
  .fenix-page .xl\:col-span-full, #canvas .xl\:col-span-full { grid-column: 1 / -1; }
  .fenix-page .xl\:col-start-1, #canvas .xl\:col-start-1 { grid-column-start: 1; }
  .fenix-page .xl\:col-start-2, #canvas .xl\:col-start-2 { grid-column-start: 2; }
  .fenix-page .xl\:col-start-3, #canvas .xl\:col-start-3 { grid-column-start: 3; }
  .fenix-page .xl\:col-start-4, #canvas .xl\:col-start-4 { grid-column-start: 4; }
  .fenix-page .xl\:col-start-5, #canvas .xl\:col-start-5 { grid-column-start: 5; }
  .fenix-page .xl\:col-start-6, #canvas .xl\:col-start-6 { grid-column-start: 6; }
  .fenix-page .xl\:col-start-7, #canvas .xl\:col-start-7 { grid-column-start: 7; }
  .fenix-page .xl\:col-start-8, #canvas .xl\:col-start-8 { grid-column-start: 8; }
  .fenix-page .xl\:col-start-9, #canvas .xl\:col-start-9 { grid-column-start: 9; }
  .fenix-page .xl\:col-start-10, #canvas .xl\:col-start-10 { grid-column-start: 10; }
  .fenix-page .xl\:col-start-11, #canvas .xl\:col-start-11 { grid-column-start: 11; }
  .fenix-page .xl\:col-start-12, #canvas .xl\:col-start-12 { grid-column-start: 12; }
.fenix-page .xl\:col-start-13, #canvas .xl\:col-start-13 { grid-column-start: 13; }
}

/* Large checklist badges should center against their label, even when AI output
   uses Tailwind's top-aligned `items-start` row utility. */
.fenix-page-body li.flex.items-start:has(> .w-12.h-12.rounded-full),
.fenix-page-body li.flex.items-start:has(> .w-14.h-14.rounded-full),
.fenix-page-body li.flex.items-start:has(> .w-16.h-16.rounded-full),
#canvas li.flex.items-start:has(> .w-12.h-12.rounded-full),
#canvas li.flex.items-start:has(> .w-14.h-14.rounded-full),
#canvas li.flex.items-start:has(> .w-16.h-16.rounded-full) {
  align-items: center;
}

/* ─── Section background: terracotta (#9D6F54) — East & Eversley band colour ── */
.bg-ee-terracotta { background-color: #9D6F54; color: #EFE6DC; }

/* Embed mode (?embed=1) — the page is rendered inside another page's dialog. _FenixLayout
   already drops the site chrome; this drops the navigation a page authored into its OWN
   content, which has nowhere useful to go inside a dialog: the breadcrumb would navigate the
   frame away from the terms, and the "On this page" chapter rail costs a third of the width
   to jump within a document the reader can simply scroll. Collapsing .va-reading-grid to one
   column stops the vacated column from leaving a gap. */
.fenix-page-host[data-fenix-embed="1"] [aria-label="Breadcrumb"] { display: none; }
.fenix-page-host[data-fenix-embed="1"] .va-toc { display: none; }
.fenix-page-host[data-fenix-embed="1"] .va-reading-grid { display: block; }

/* The page hero is sized for a full browser window; inside a dialog that headline eats the
   first screenful before a word of the terms shows. Scale the title and lede down — the
   dialog already carries its own heading, so this one only needs to name the document.
   The long selectors and the !important are load-bearing: a page's own section styles reach
   4 levels deep and BOTH the title and the lede are set with !important there
   (.fenix-page-host .fenix-page-body .vx-policy .x-lg-h1 => 60px !important), so anything
   shorter or unflagged here silently loses. */
.fenix-page-host[data-fenix-embed="1"] .fenix-page-body .fenix-section .x-lg-h1 {
  font-size: clamp(24px, 3vw, 30px) !important;
  margin-top: 10px;
}
.fenix-page-host[data-fenix-embed="1"] .fenix-page-body .fenix-section .x-lg-lede {
  font-size: 15px !important;
  line-height: 1.6 !important;
  margin-top: 10px;
}
/* Section headings come down with the title, or they end up LARGER than the page title they
   sit under (32px against 24px) and the document reads upside down. */
.fenix-page-host[data-fenix-embed="1"] .fenix-page-body .fenix-section .x-lg-body h2 {
  font-size: 22px !important;
}

/* ─── Campaign hero sticker ─────────────────────────────────────────────────
   The "floating" promo overlaid on a page's hero (Campaigns phase 2, 2026-09-12).
   Injected per request by FenixCampaignStickerInjector, which emits TWO copies:

     --overlay  absolutely positioned inside the first <section>   (>=768px)
     --band     a full-width strip immediately after that section  (<768px)

   Exactly one is ever displayed, so the phone never gets an overlay sitting on
   top of the product photography — the owner's call, 2026-09-12.

   Everything is type and CSS. No baked raster: the copy stays editable,
   translatable and readable by search engines and screen readers. */

.fenix-hero-sticker {
    --fx-sticker-bg: var(--fenix-color-primary, #db2777);
    --fx-sticker-text: #fff;
    --fx-sticker-accent: rgba(0, 0, 0, 0.28);
    --fx-sticker-rotate: 0deg;

    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-decoration: none;
    z-index: 3;                       /* above hero veils, below the header */

    /* A decorative sticker must not eat clicks on whatever it happens to sit over —
       heroes put their buy button exactly where an overlay lands. Only the linked
       variant takes the pointer back. */
    pointer-events: none;
}

a.fenix-hero-sticker { pointer-events: auto; }

.fenix-hero-sticker__paper {
    position: relative;               /* anchors the drawn motif and a "behind" artwork */
    overflow: hidden;                 /* keeps both inside the torn edge */
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    padding: 20px 28px;
    background: var(--fx-sticker-bg);
    color: var(--fx-sticker-text);
    text-align: center;
    line-height: 1.15;
}

.fenix-hero-sticker__eyebrow {
    color: var(--fx-sticker-eyebrow-text, var(--fx-sticker-text, #fff));
    font-size: 0.8125rem;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}

.fenix-hero-sticker__headline {
    font-size: clamp(1.75rem, 4vw, 3rem);
    font-weight: 800;
    letter-spacing: 0.02em;
}

.fenix-hero-sticker__subline {
    padding: 5px 14px;
    background: var(--fx-sticker-accent);
    /* Its own colour, defaulting to the sticker's: the box ground is picked independently,
       and gold-on-cream is unreadable where gold-on-deep-green is the intended pairing. */
    color: var(--fx-sticker-subline-text, var(--fx-sticker-text, #fff));
    font-size: 0.9375rem;
    font-weight: 600;
    letter-spacing: 0.04em;
}

.fenix-hero-sticker__footnote {
    font-size: 0.6875rem;
    letter-spacing: 0.02em;
    color: var(--fx-sticker-text);
    /* This line sits on the bare photo, not on the coloured block, so it needs its own
       contrast — a hero can be light or dark and the sticker cannot know which. */
    text-shadow: 0 1px 3px rgba(0, 0, 0, 0.65);
}

/* Styles — "card" is a clean panel, "torn" is the tilted torn-paper block. */
.fenix-hero-sticker[data-style="card"] .fenix-hero-sticker__paper {
    border-radius: 14px;
    box-shadow: 0 12px 32px -12px rgba(0, 0, 0, 0.45);
}

.fenix-hero-sticker[data-style="torn"] .fenix-hero-sticker__paper {
    /* Ragged top and bottom edges, drawn rather than photographed. */
    clip-path: polygon(
        0% 6%, 8% 2%, 19% 5%, 31% 1%, 44% 5%, 57% 1%, 69% 5%, 81% 2%, 92% 5%, 100% 2%,
        100% 95%, 90% 99%, 78% 95%, 66% 99%, 54% 96%, 41% 99%, 29% 95%, 17% 99%, 6% 96%, 0% 99%
    );
    padding: 30px 34px 34px;
}

.fenix-hero-sticker--overlay[data-style="torn"] {
    transform: rotate(var(--fx-sticker-rotate));
}

/* ── Desktop overlay: nine anchors on the hero ── */
.fenix-hero-sticker--overlay {
    position: absolute;
    max-width: min(360px, 42%);
}

.fenix-hero-sticker--overlay[data-anchor^="top-"]    { top: 6%; }
.fenix-hero-sticker--overlay[data-anchor^="middle-"] { top: 50%; }
.fenix-hero-sticker--overlay[data-anchor^="bottom-"] { bottom: 6%; }

.fenix-hero-sticker--overlay[data-anchor$="-left"]   { left: 5%; }
.fenix-hero-sticker--overlay[data-anchor$="-right"]  { right: 5%; }

/* Centre anchors set left:50% here and get their translate in the transform rules
   below, which must also carry the tilt — a bare translate would drop the rotation. */
.fenix-hero-sticker--overlay[data-anchor$="-centre"] { left: 50%; }

.fenix-hero-sticker--overlay[data-anchor="top-centre"],
.fenix-hero-sticker--overlay[data-anchor="bottom-centre"] {
    transform: translateX(-50%) rotate(var(--fx-sticker-rotate));
}

.fenix-hero-sticker--overlay[data-anchor="middle-left"],
.fenix-hero-sticker--overlay[data-anchor="middle-right"] {
    transform: translateY(-50%) rotate(var(--fx-sticker-rotate));
}

.fenix-hero-sticker--overlay[data-anchor="middle-centre"] {
    transform: translate(-50%, -50%) rotate(var(--fx-sticker-rotate));
}

/* ── Mobile band: below the hero, never over it ── */
.fenix-hero-sticker--band {
    display: none;
    width: 100%;
    padding: 18px 16px 20px;
    background: var(--fx-sticker-bg);
    box-sizing: border-box;
}

/* The band paints its own ground, so the paper inside it is transparent —
   otherwise a torn clip-path would cut a ragged hole in a solid strip, and the
   clip would eat the eyebrow and subline at narrow widths.

   The [data-style] here is NOT decorative: the rules it has to beat are
   .fenix-hero-sticker[data-style="torn"|"card"] .fenix-hero-sticker__paper, which
   carry one more attribute selector than a bare .--band descendant rule would. Drop
   it and the clip-path silently survives into the band. */
.fenix-hero-sticker--band[data-style] .fenix-hero-sticker__paper {
    clip-path: none;
    background: transparent;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
}

.fenix-hero-sticker--band[data-style] .fenix-hero-sticker__headline {
    font-size: clamp(1.5rem, 8vw, 2.25rem);
}

@media (max-width: 767px) {
    .fenix-hero-sticker--overlay { display: none; }
    .fenix-hero-sticker--band { display: flex; }
}

/* ── Drawn motif: the Mid-Autumn moon ──
   A circle, not an upload. It scales to any size, recolours with the block, adds
   no bytes and behaves the same on the mobile band. Artwork CSS genuinely cannot
   draw (a mooncake's stamped pattern) goes through __art instead. */
.fenix-hero-sticker__motif {
    position: absolute;
    top: 14%;
    left: 50%;
    width: 44%;
    aspect-ratio: 1;
    transform: translateX(-50%);
    border-radius: 50%;
    background: var(--fx-sticker-motif, var(--fx-sticker-text, #fff));
    opacity: 0.18;
    pointer-events: none;
}

/* ── Artwork ──
   behind = watermark under the copy · crest = above the eyebrow, in flow ·
   beside = a second column, so the block becomes a row. */
.fenix-hero-sticker__art {
    display: block;
    max-width: 100%;
    height: auto;
}

.fenix-hero-sticker[data-art="behind"] .fenix-hero-sticker__art {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    opacity: 0.22;
    pointer-events: none;
}

/* Crest sits first in flow already — it only needs to breathe. */
.fenix-hero-sticker[data-art="crest"] .fenix-hero-sticker__art {
    margin-bottom: 4px;
}

/* The copy column. In every placement but "beside" this is simply a column inside a
   column and changes nothing; in "beside" it is what keeps the three lines together as
   ONE flex item next to the artwork. */
.fenix-hero-sticker__copy {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 6px;
    min-width: 0;
}

.fenix-hero-sticker[data-art="beside"] .fenix-hero-sticker__paper {
    flex-direction: row;
    align-items: center;
    gap: 18px;
}

.fenix-hero-sticker[data-art="beside"] .fenix-hero-sticker__copy {
    align-items: flex-start;
    text-align: left;
}

.fenix-hero-sticker[data-art="beside"] .fenix-hero-sticker__art {
    flex: 0 0 auto;
}

/* A row needs more room than a stack, or the copy column is squeezed narrow enough to
   break mid-word — and Chinese, having no word boundaries, breaks per character. */
.fenix-hero-sticker--overlay[data-art="beside"] {
    max-width: min(520px, 60%);
}

@media (max-width: 767px) {
    /* A "beside" row is too wide for a phone band — stack it. */
    .fenix-hero-sticker--band[data-art="beside"] .fenix-hero-sticker__paper {
        flex-direction: column;
        gap: 10px;
    }
    /* Targets the COPY WRAPPER, not the individual lines — they stopped being direct
       flex children when the wrapper was introduced to fix the vertical-text bug. */
    .fenix-hero-sticker--band[data-art="beside"] .fenix-hero-sticker__copy {
        align-items: center;
        text-align: center;
    }
}

/* Preview marker on the hero sticker — same contract as the bar: only staff receive
   markup carrying data-preview. A dashed ring rather than a restyle, so what you are
   checking still looks like what will ship.

   On the ROOT, never the paper: the torn style clips the paper with clip-path, and a
   clip-path clips an outline too, so a ring on the paper is silently invisible on
   exactly the style that is the default. */
.fenix-hero-sticker[data-preview] {
    outline: 2px dashed rgba(255, 255, 255, 0.7);
    outline-offset: 6px;
}

/* The band paints a full-width strip, so a ring around it would run off the screen. */
.fenix-hero-sticker--band[data-preview] {
    outline: 0;
    box-shadow: inset 0 -3px 0 0 rgba(0, 0, 0, 0.28);
}

/* ─── PURE IMAGE MODE ─────────────────────────────────────────────────────
   The floating element IS the artwork: one picture on the hero, no block, no
   copy, no torn edge. The block-mode chrome is all keyed off the paper, so
   there is nothing to undo — only the band needs standing down, because a
   full-width coloured strip behind a finished graphic is exactly the chrome
   this mode exists to remove. */
.fenix-hero-sticker[data-mode="image"] {
    gap: 0;
}

.fenix-hero-sticker[data-mode="image"] .fenix-hero-sticker__art {
    /* A finished graphic usually carries its own shadow; a subtle one still helps
       it read as ON the photo rather than punched into it. */
    filter: drop-shadow(0 10px 24px rgba(0, 0, 0, 0.28));
}

.fenix-hero-sticker--overlay[data-mode="image"] {
    /* Sized by the artwork's own width, not the block-mode column cap. */
    max-width: none;
}

/* The chosen width arrives as max-width, so BOTH sides can be bounded and the
   intrinsic aspect still decides — a fixed width plus a height cap squashes the
   image instead of scaling it. */
.fenix-hero-sticker[data-mode="image"] .fenix-hero-sticker__art {
    width: auto;
    height: auto;
}

/* Cap the height as well as the width. Width alone is fine for a wide or square
   graphic and catastrophic for a tall one: a 1008x1464 portrait came out 340x494,
   62% of a phone screen — at which point it is not a promo, it is the page. */
.fenix-hero-sticker--overlay[data-mode="image"] .fenix-hero-sticker__art {
    max-height: 60vh;
}

/* On a phone the artwork becomes a centred band with NO ground of its own. */
.fenix-hero-sticker--band[data-mode="image"] {
    background: none;
    padding: 16px;
    align-items: center;
    box-shadow: none;
}

.fenix-hero-sticker--band[data-mode="image"] .fenix-hero-sticker__art {
    /* Composes THREE ceilings: the screen, a sane band maximum, and the width actually
       chosen (carried as --fx-art-w). A bare `!important` cap overrode the setting both
       ways — pick 120px and the phone still drew 340px, because the cap had become a
       floor as well as a ceiling. */
    max-width: min(100%, 340px, var(--fx-art-w, 340px)) !important;
    max-height: 34vh;
}
