/*
==========================================================
ZONE BAND — zone_band.css
==========================================================
WHAT IT IS:
A background container block for grouping multiple content
blocks under one continuous visual background zone.

WHAT IT DOES:
Renders a styled outer section with InnerBlocks support.
Two layout styles: full-width (100vw breakout) and contained
(max-width, rounded corners). Optional heading zone above
the inner blocks area. Gradient and glow variant treatments
are defined per-project in style.css §10 — not here.

HOW TO USE:
1. Add the Zone Band block to any page
2. In the Style tab: set Band Style and Section Variant
3. Drop content blocks inside the inner blocks area
4. Fill optional heading fields if the zone needs a title

All values use boilerplate CSS tokens from style.css.
==========================================================
*/


/* ── Base Block ───────────────────────────────────────────── */

.zone_band {
    position: relative;
    padding: var(--space-20) 0;
    background-color: var(--color-bg-dark);
    overflow: hidden;
}

/* Inner content wrap — structural wrapper for InnerBlocks drop zone */
.zone_band_content_wrap {}


/* ── Style Variants — AFTER base ─────────────────────────── */

/* Full-width: breakout math escapes any constrained parent */
.zone_band_style_full_width {
    width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
}

/* Contained: constrained to max-width, rounded corners */
.zone_band_style_contained {
    max-width: var(--max-width);
    margin-left: auto;
    margin-right: auto;
    border-radius: var(--radius-xl);
    box-shadow: var(--shadow-lg);
}


/* ── Custom Background Override ───────────────────────────── */

/* When band_bg color picker is set, suppress pseudo-element  */
/* gradient/glow layers so the solid color reads clean.       */
.zone_band_custom_bg::before,
.zone_band_custom_bg::after {
    display: none;
}


/* ── Section Variant — self-contained ────────────────────── */

.zone_band_variant_minimal {
    padding: var(--space-10) 0;
    background-color: transparent;
}

.zone_band_variant_dark {
    background-color: var(--color-bg-dark);
}


/* ── Section Variant Stubs — define per project in §10 ────── */

.zone_band_variant_gradient_1       { /* see style.css §10 */ }
.zone_band_variant_gradient_2       { /* see style.css §10 */ }
.zone_band_variant_gradient_3       { /* see style.css §10 */ }
.zone_band_variant_homepage_feature { /* see style.css §10 */ }
.zone_band_variant_inner_banner     { /* see style.css §10 */ }


/* ── Optional Heading ─────────────────────────────────────── */

.zone_band_header {
    text-align: center;
    margin-bottom: var(--space-10);
}

/* Correction pass 6 (2026-10-16): background changed from a semi-transparent
   black (rgba(0, 0, 0, 0.25)) to an opaque --color-bg-dark. The old overlay's
   actual visible color depended on whatever was behind it — fine against the
   section's own near-black default, but measured at a real 1.97:1 contrast
   ratio against its white text once Minimal + Theme Default put a light page
   background behind it (confirmed via real-browser luminance calculation, not
   estimated). An opaque, always-dark token makes the pill's contrast
   independent of the section background entirely, matching its description
   as a self-contained chip. */
.zone_band_pill {
    display: inline-flex;
    align-items: center;
    padding: 0.45rem 1rem;
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: var(--radius-full);
    background-color: var(--color-bg-dark);
    font-family: var(--font-accent);
    font-size: var(--text-xs);
    letter-spacing: 0.08em;
    color: var(--color-text-inverse);
    box-shadow: var(--shadow-sm);
    margin-bottom: var(--space-3);
}

.zone_band_eyebrow {
    font-family: var(--font-accent);
    font-size: var(--text-xs);
    font-weight: var(--weight-semi);
    text-transform: uppercase;
    letter-spacing: 0.14em;
    color: var(--color-accent);
    margin-bottom: var(--space-3);
}

.zone_band_heading {
    font-family: var(--font-heading);
    font-size: clamp(1.9rem, 3.2vw, 2.6rem);
    font-weight: var(--weight-bold);
    line-height: 1.1;
    letter-spacing: -0.02em;
    color: var(--color-text-inverse);
    margin: 0;
}

.zone_band_heading_accent {
    display: block;
    background: linear-gradient(135deg, var(--color-accent), var(--color-secondary));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

/* ── Section Background Mode (Batch 8F Round 1, extended in correction pass 5) ──
   .zone_band's base rule already defaults to a dark background
   (--color-bg-dark) with inverse heading text, above — that is "Theme
   Default" and needs no class at all. "Background" and "Alternate"
   resolve to light tokens (--color-bg / --color-bg-alt), so their
   classes flip the heading back to a normal (dark) color for
   legibility. "Dark" needs no override (already matches the existing
   default — see the Accent-mode note below for why Accent is not
   grouped with it). Custom mode's explicit Light/Dark text-treatment
   field drives .zone_band_text_light/.zone_band_text_dark the same
   way; .zone_band_text_dark needs no rule since it matches the
   existing default exactly. Minimal variant with no resolved background
   override (.zone_band_custom_bg absent — see zone_band.php: that class
   is added for every resolved $bg_color, including the legacy-fallback
   branch, which adds no mode/text class of its own) also needs the flip
   — Minimal's own CSS sets the section background to transparent, so
   with nothing else behind it the page's own light background shows
   through and an inverse-white heading would blend into it. The pill
   (its own dark chip background, independent of the section) is left
   untouched — it reads correctly against any section background on its
   own, confirmed including Minimal + Theme Default (below). */
.zone_band_bg_background .zone_band_heading,
.zone_band_bg_alt_background .zone_band_heading,
.zone_band_text_dark .zone_band_heading,
.zone_band_variant_minimal:not(.zone_band_custom_bg) .zone_band_heading {
    color: var(--color-primary);
}

/* ── Accent-mode contrast fix (live-test correction, 2026-10-16) ──
   Live testing found the eyebrow, the gradient accent-heading, and any
   nested InnerBlocks content all lose contrast specifically in Accent
   mode — a claim in the comment above ("the accent-colored eyebrow
   already reads correctly against any section background") turned out
   to be wrong for exactly this one case. Accent mode sets the panel's
   background to the literal same --color-accent the eyebrow's text and
   the heading-accent's gradient already use, and to the literal same
   --color-accent every un-styled link already uses (style.css §4d) —
   each blends into its own background. Grouped with
   .zone_band_text_light below, not just .zone_band_bg_accent: an editor
   who explicitly chose Light Text for a Custom background has already
   told us accent-toned elements won't read there either — the same
   signal, not a guess. .zone_band_bg_dark is deliberately NOT grouped
   here: accent-blue reads fine against --color-bg-dark (confirmed —
   this is a real color/background collision specific to Accent, not a
   general "any dark background" problem), and it was never reported
   as broken. */

.zone_band_bg_accent .zone_band_eyebrow,
.zone_band_text_light .zone_band_eyebrow {
    color: var(--color-text-inverse);
}

.zone_band_bg_accent .zone_band_heading_accent,
.zone_band_text_light .zone_band_heading_accent {
    /* Fully resets the gradient-clip-text effect rather than just
       changing its colors — a gradient that still had --color-accent
       as one of its two stops would keep reproducing the same
       collision at that end of the gradient. */
    background: none;
    -webkit-background-clip: border-box;
    background-clip: border-box;
    color: var(--color-text-inverse);
}

/* Nested InnerBlocks content — full state model (correction pass 4, extended in
   correction pass 5, 2026-10-16).
   .zone_band_content_wrap carries no color of its own in the base block rule, so core
   blocks dropped inside previously fell through to the global light-mode rules
   (style.css §4) regardless of the section's actual background. That rule happened to
   read correctly for Background and Alternate (both genuinely light, so dark global
   text was already right by coincidence, not by design) but was dark-on-dark for
   Theme Default and explicit Dark — both genuinely dark — until the base rule below
   was added; Accent was the one case already caught and fixed in the prior pass.

   Base rule below matches .zone_band's OWN default background (--color-bg-dark, the
   very first rule in this file) — with zero modifier classes the block IS dark, so
   nested content defaults to inverse text here. Each state that puts a genuinely LIGHT
   background behind the wrap gets an explicit override back to normal (dark) text:
   Background and Alternate Background (light tokens), Custom + Dark Text (the editor's
   explicit choice), and Minimal variant with no resolved background override present
   (.zone_band_custom_bg absent) — Minimal sets the section's own background to
   transparent (above), and with no resolved background override there's also no inline
   background-color from PHP, so the page's own (light) background shows through. The
   :not(.zone_band_custom_bg) guard (corrected in pass 5 — see zone_band.php) is the
   single, PHP-verified signal for "no inline background exists": that class is added
   for every resolved $bg_color, including the legacy-fallback branch (a pre-existing
   saved band_bg value from before this field existed), which adds no mode/text class of
   its own but still outputs an inline background — an earlier version of this guard
   checked only the three mode/text classes and was wrong for exactly that legacy case.
   Dark, Accent, and Custom + Light Text all rely on the inverse base rule unchanged —
   Accent and Light-Text needed their own extra fixes above for the eyebrow/accent-
   heading collision, but the content wrap's inverse color was already correct for them.

   p/li use "color: inherit" (not a literal value) for the same reason this pattern is
   used everywhere else in this project — the global p/li rules have real specificity
   and win over a merely-inherited color from an ancestor class. Headings and links get
   their own explicit color per state, matching the "No color" WYSIWYG heading pattern
   used throughout (e.g. Split View's .sv_col_body h1-h6 rules).

   WP core Button blocks are deliberately not touched by this model: their fill comes
   from a global, !important-protected rule (.wp-block-button__link, style.css §7a) that
   is sitewide, not scoped to this block — AGENTS.md's "no !important unless
   unavoidable" rule means matching it would need a second !important this task doesn't
   need, since the button's own text stays white and readable against its own fill
   regardless of what's behind it. That's a blending consideration, not an unreadable-
   text defect, so it's noted here rather than touched. */

/* Batch 8H §25 #10 (approved by Matt 2026-10-21): the color model below
   now styles ORDINARY WordPress content only — each plain block placed in
   the band (paragraph, heading, list, buttons, group…) and everything inside
   it. Our own blocks (<section>s on the page; data-type="acf/…" or the
   theme's .boilerplate_preview_toggle_wrap in the editor) are skipped, so
   they keep their own colors exactly as they look outside a band. Before
   this, ".zone_band_content_wrap h2" etc. reached into them and turned, for
   example, Split View's heading white on its own light background.
   The plain-block selector is wrapped in :where() so every rule keeps the
   same specificity it had before (e.g. "PLAIN h2" = 0,1,1). */
:where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) {
    color: var(--color-text-inverse-soft);
}

:where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) p:where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)),
:where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) li:where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)) {
    color: inherit;
}

:where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container):is(h1, h2, h3, h4, h5, h6),
:where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) :is(h1, h2, h3, h4, h5, h6):where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)) {
    color: var(--color-text-inverse);
}

:where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) a:where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)) {
    color: var(--color-text-inverse);
}

:where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) a:hover:where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)) {
    color: var(--color-text-inverse-soft);
}

/* Our blocks nested deeper — inside a WordPress Group, Columns etc. (§25 #11).
   The plain block around them carries the band's text color, which they would
   inherit, and the descendant rules above reach any depth. So:
   - every rule above that styles elements INSIDE a plain block skips anything
     inside one of our blocks (the :where(:not(…)) part — zero specificity);
   - our blocks get back the page's normal text color (body uses
     --color-text), the same as they inherit outside a band. Wrapped in
     :where() (zero specificity) so any color a block sets on itself wins. */
:where(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap)) {
    color: var(--color-text);
}

/* Light backgrounds: Background, Alternate, Custom + Dark Text, and Minimal
   with nothing behind it (see the note above). */
:is(.zone_band_bg_background, .zone_band_bg_alt_background, .zone_band_text_dark, .zone_band_variant_minimal:not(.zone_band_custom_bg)) :where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) {
    color: var(--color-text);
}

:is(.zone_band_bg_background, .zone_band_bg_alt_background, .zone_band_text_dark, .zone_band_variant_minimal:not(.zone_band_custom_bg)) :where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) p:where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)),
:is(.zone_band_bg_background, .zone_band_bg_alt_background, .zone_band_text_dark, .zone_band_variant_minimal:not(.zone_band_custom_bg)) :where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) li:where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)) {
    color: inherit;
}

:is(.zone_band_bg_background, .zone_band_bg_alt_background, .zone_band_text_dark, .zone_band_variant_minimal:not(.zone_band_custom_bg)) :where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container):is(h1, h2, h3, h4, h5, h6),
:is(.zone_band_bg_background, .zone_band_bg_alt_background, .zone_band_text_dark, .zone_band_variant_minimal:not(.zone_band_custom_bg)) :where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) :is(h1, h2, h3, h4, h5, h6):where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)) {
    color: var(--color-primary);
}

:is(.zone_band_bg_background, .zone_band_bg_alt_background, .zone_band_text_dark, .zone_band_variant_minimal:not(.zone_band_custom_bg)) :where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) a:where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)) {
    color: var(--color-accent);
}

:is(.zone_band_bg_background, .zone_band_bg_alt_background, .zone_band_text_dark, .zone_band_variant_minimal:not(.zone_band_custom_bg)) :where(.zone_band_content_wrap > .acf-innerblocks-container, .zone_band_content_wrap) > :not(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap, .acf-innerblocks-container) a:hover:where(:not(.zone_band_content_wrap :is(section, [data-type^="acf/"], .boilerplate_preview_toggle_wrap) *)) {
    color: var(--color-accent-hover);
}

/* NOTE: there used to be a ".zone_band_header p { color: inherit; }" rule
   here, intended to stop the global p-color rule from leaking dark text into
   this dark-background header. But .zone_band_header only ever contains the
   pill and eyebrow <p> tags above (both already have their own deliberate
   color — never actual WYSIWYG body copy), and ".zone_band_header p" has
   higher specificity than the bare ".zone_band_pill"/".zone_band_eyebrow"
   class selectors, so it was silently overriding their intended colors with
   whatever this element happens to inherit instead. Removed — the pill and
   eyebrow's own color rules are already specific enough to beat the global
   p rule on their own. */


/* ── Responsive ───────────────────────────────────────────── */

@media (max-width: 768px) {

    .zone_band {
        padding: var(--space-12) 0;
    }

    .zone_band_header {
        margin-bottom: var(--space-8);
    }
}

@media (max-width: 480px) {

    .zone_band {
        padding: var(--space-10) 0;
    }

    .zone_band_style_contained {
        border-radius: 24px;
    }
}


/* ── Inner block containment ──────────────────────────────────── */

/* Zone band breaks out of main, losing main's 40px padding.
   Target the .wrapper class that every inner block uses for containment —
   double its horizontal padding so content sits at the expected 80px inset
   instead of the 40px that blocks get when placed directly inside main. */
.zone_band .wrapper {
    padding-left: calc(var(--wrapper-padding) * 2);
    padding-right: calc(var(--wrapper-padding) * 2);
}

@media (max-width: 480px) {
    .zone_band .wrapper {
        padding-left: var(--wrapper-padding);
        padding-right: var(--wrapper-padding);
    }
}


/* ── Editor overrides ─────────────────────────────────────────── */

/* Prevent full-width breakout from escaping the editor canvas */
.editor-styles-wrapper .zone_band_style_full_width {
    width: 100%;
    margin-left: 0;
    margin-right: 0;
}

/* Allow inner block toolbars to render outside the zone boundary */
.editor-styles-wrapper .zone_band {
    overflow: visible;
}


/* ══════════════════════════════════════════════════════════════════
   Batch 8H — Zone Band (BATCH_8_PLAN.md §25)
   ══════════════════════════════════════════════════════════════════ */

/* ── Space below the heading (approved fix Z2) ─────────────────────
   .zone_band_header's own margin-bottom (above) never applied: this
   file loads before style.css, whose .wrapper { margin: 0 auto } has the
   same specificity and wins on source order. The band-scoped selector
   restores the intended space (40px; 32px on tablets and phones). */
.zone_band .zone_band_header {
    margin-bottom: var(--space-10);
}

@media (max-width: 768px) {
    .zone_band .zone_band_header {
        margin-bottom: var(--space-8);
    }
}


/* ── Ordinary WordPress blocks inside the band (approved fix Z3) ───
   Paragraphs, headings, lists, buttons, images etc. dropped inside the
   band previously ran edge to edge. They now get the same content width
   and side space as the band's heading (which uses the band's doubled
   .wrapper padding above, single on small phones).
   - Uses max-width + auto side margins (no padding), so a block's own
     background stays inside its own box.
   - Our own blocks are skipped: on the page they are <section>s with
     their own .wrapper; in the editor they carry data-type="acf/…" or
     sit in the theme's .boilerplate_preview_toggle_wrap (js/editor-
     preview-toggle.js). Their full-width backgrounds and widths are
     unchanged.
   - .alignfull blocks are skipped too.
   - Inner blocks sit in ACF's .acf-innerblocks-container (page and
     editor); the second selector covers markup without it. */
.zone_band {
    --zb-gutter: calc(var(--wrapper-padding) * 2);
}

@media (max-width: 480px) {
    .zone_band {
        --zb-gutter: var(--wrapper-padding);
    }
}

.zone_band_content_wrap > .acf-innerblocks-container > :not(section):not([data-type^="acf/"]):not(.boilerplate_preview_toggle_wrap):not(.alignfull),
.zone_band_content_wrap > :not(.acf-innerblocks-container):not(section):not([data-type^="acf/"]):not(.boilerplate_preview_toggle_wrap):not(.alignfull) {
    box-sizing: border-box;
    max-width: min(calc(100% - 2 * var(--zb-gutter)), calc(var(--max-width) - 2 * var(--zb-gutter)));
    margin-left: auto;
    margin-right: auto;
}


/* ── Background photo ──────────────────────────────────────────────
   Optional photo behind the whole band (inline background-image from
   zone_band.php; the background color stays underneath as a fallback).
   "Photo darkening" is a see-through layer over the photo. Heading and
   content sit above it. Only bands with a photo get these rules, so
   every other band is unchanged. No fixed/parallax background. */
.zone_band_overlay {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

.zone_band_has_photo > .zone_band_header,
.zone_band_has_photo > .zone_band_inner,
.zone_band_has_photo > .bp_section_id_note {
    position: relative;
    z-index: 1;
}


/* ── Space above / below the content (shared foundation) ───────────
   Space INSIDE the band, set by "Space above the content" / "Space below
   the content" (None / Small / Normal / Large). Normal adds no class and
   keeps the band's usual space (80px; 48px tablets; 40px phones —
   Minimal 40px on computers). Shared token scale, reused by future
   blocks (Guides/BLOCK_EDITOR_UI_GUIDE.md):
     None 0 · Small 40 / 32 / 24 · Large 128 / 80 / 64
     (computers / up to 768px / up to 480px).
   Two classes beat the base, Minimal and breakpoint rules above. */
.zone_band.zone_band_space_top_none      { padding-top: 0; }
.zone_band.zone_band_space_top_small     { padding-top: var(--space-10); }
.zone_band.zone_band_space_top_large     { padding-top: calc(var(--space-16) * 2); }
.zone_band.zone_band_space_bottom_none   { padding-bottom: 0; }
.zone_band.zone_band_space_bottom_small  { padding-bottom: var(--space-10); }
.zone_band.zone_band_space_bottom_large  { padding-bottom: calc(var(--space-16) * 2); }

@media (max-width: 768px) {
    .zone_band.zone_band_space_top_small    { padding-top: var(--space-8); }
    .zone_band.zone_band_space_top_large    { padding-top: var(--space-20); }
    .zone_band.zone_band_space_bottom_small { padding-bottom: var(--space-8); }
    .zone_band.zone_band_space_bottom_large { padding-bottom: var(--space-20); }
}

@media (max-width: 480px) {
    .zone_band.zone_band_space_top_small    { padding-top: var(--space-6); }
    .zone_band.zone_band_space_top_large    { padding-top: var(--space-16); }
    .zone_band.zone_band_space_bottom_small { padding-bottom: var(--space-6); }
    .zone_band.zone_band_space_bottom_large { padding-bottom: var(--space-16); }
}
