/* ═══════════════════════════════════════════════════════════════════════════
   BWA Site Framework CSS  (auto-applied to every public tenant)
   ───────────────────────────────────────────────────────────────────────────
   This file contains site-architecture rules that EVERY BWA tenant needs
   identically — container max-widths, the .full-bleed escape, and the
   universal AI Block island plumbing (bleed, content-cap, pack-to-top,
   nested-island containment).
   
   Loaded by Primary.master.cs via EmitVersionedCssLink — AFTER brand-corpus-
   generated.css (so it can reference --bwa-* tokens) and BEFORE the tenant's
   custom.css (so per-tenant overrides win on the cascade).
   
   DO NOT add tenant-specific selectors here (e.g. .cj-*, .ws-*). Those stay
   in the tenant's own custom.css. The rule of thumb: if a fix or rule would
   benefit ALL tenants identically, it goes here. Anything else stays per-
   tenant.
   
   Extracted from:
     CJ custom.css lines 621-882 on 2026-06-04 (Phase A custom.css trim).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ──────────────────────────────────────────────────────────────────
   SITE WIDTH FRAMEWORK
   - Header & footer chrome cap:  1750px  (wider for nav / logo / cta)
   - Content section cap:         1600px  (page body, blocks, AI Block output)
   - Full-bleed escape:           .full-bleed makes a section's background
                                  span 100vw while inner content still
                                  centers at 1600px via a child .container
                                  or .full-bleed-inner.
   Bootstrap's stock .container caps at 1170px @>=1200; rules below
   override the cap for everything except .container-sm (kept at 1124px
   above) and .container-fluid (always 100%). Specificity layering: the
   generic .container rule sits at (0,1,0); header/footer rules sit at
   (0,1,1) so they win for chrome.
   ────────────────────────────────────────────────────────────────── */

/* Content cap — default for body sections / blocks */
@media (min-width: 1200px) {
  .container,
  .container-md,
  .container-lg,
  .container-xl {
    max-width: 1600px;
    width: 100%;
  }
}
@media (min-width: 1400px) {
  .container,
  .container-md,
  .container-lg,
  .container-xl,
  .container-xxl {
    max-width: 1600px;
    width: 100%;
  }
}

/* Header & footer chrome cap — beats the content rule above via
   higher selector specificity (descendant of header/footer). */
@media (min-width: 1200px) {
  header .container,
  header .container-md,
  header .container-lg,
  header .container-xl,
  header .container-xxl,
  footer .container,
  footer .container-md,
  footer .container-lg,
  footer .container-xl,
  footer .container-xxl,
  .getStartedCard > .container {
    max-width: 1750px;
    width: 100%;
  }
}

/* Full-bleed escape utility — drop on any section / div to make its
   background break out of the parent container and span the entire
   viewport. Inner content is reined back to 1600px by the nested
   .container or .full-bleed-inner so text never crosses the safe zone.

   Usage:
     <section class="full-bleed" style="background: #00267f;">
       <div class="container">...content stays centered at 1600px...</div>
     </section>

   For true edge-to-edge inner content (hero images, video, banners)
   omit the inner .container — content will go 100vw. */
.full-bleed {
  position: relative;
  left: 50%;
  right: 50%;
  margin-left: -50vw;
  margin-right: -50vw;
  width: 100vw;
  max-width: 100vw;
}
.full-bleed > .container,
.full-bleed > .full-bleed-inner {
  max-width: 1600px;
  width: 100%;
  margin-left: auto;
  margin-right: auto;
  padding-left: 24px;
  padding-right: 24px;
  box-sizing: border-box;
}

/* ── Page-level horizontal overflow guard ──────────────────────────
   Every full-bleed rule below sizes to 100vw. `100vw` INCLUDES the vertical
   scrollbar, so on any page tall enough to scroll (i.e. nearly all of them) a
   bled section is ~15-17px wider than the available content width. The result:
   a permanent horizontal scrollbar, and chrome that sizes to 100% -- header and
   footer -- visibly stops short of the scrolled right edge while the bled
   section runs past it. That reads as "the header and footer aren't full bleed"
   when in fact they are correct and the bleed is too wide.

   THE CLIP GOES ON `body > form`, NOT ON `html`. This rule was
   `html { overflow-x: clip }` and that is measurably wrong on any tenant that
   locks scrolling by putting overflow on <body>. The UA propagates overflow
   from <body> to the viewport ONLY while the root element computes `visible`
   on BOTH axes. Put any overflow on <html> and propagation moves to the root,
   so a `body.no-scroll { height:100vh; overflow:hidden }` mobile-menu lock
   stops propagating and starts clipping the body box instead: the document
   collapses to one viewport and the scroll offset is clamped to 0. Measured in
   Chromium at 390x844 against CarJiffy's cascade -- document 3200px -> 844px,
   scrollY 2356 -> 0, and closing the menu strands the reader at the top of the
   page. The `hidden` fallback below breaks it identically, so there is no
   modern-browser escape. CarJiffy carries exactly that lock (CJPublic/css/
   custom.css `.no-scroll`, applied from custom.js on `.navbar-toggler`);
   BWA-Clean does not, which is the only reason the root-level version survived
   here. Do not move this back to `html`.

   Every public master in the estate puts <form runat="server"> as a direct
   child of <body>, and it wraps the whole page, so it is the correct clipping
   box: below the root, so body -> viewport propagation is untouched, and above
   every bled section. CarJiffy already relies on this exact pattern
   (`body > form { overflow-x: hidden }` in its custom.css) and its fixed header
   is unaffected by it.

   `clip` rather than `hidden`, deliberately: `overflow-x: hidden` with
   `overflow-y: visible` blockifies the other axis to `auto`, making the form a
   scroll container -- which breaks `position: sticky` descendants, and the
   dealer theme's header is sticky. `overflow-x: clip` leaves the y axis alone
   and creates no scroll container. The `hidden` fallback is only for engines
   without `clip`, where a working page beats a sticky one.

   This does not stop a wide table or code block from scrolling inside its own
   overflow container, which is where that belongs. */
body > form { overflow-x: clip; }

@supports not (overflow: clip) {
  body > form { overflow-x: hidden; }
}

/* AI Block island bleed — the canonical wrapper emitted by
   AIBlockIslandLoader is `<div class="bwa-ai-block-island"
   style="...overflow:hidden;">`. The inline `overflow:hidden` CLIPS
   any internal full-bleed attempt, so we bleed the island itself
   (rather than its inner section) and force overflow visible. This
   is the universal AI Block bleed and covers every cj-* / nebula-*
   block automatically, regardless of its inner markup.
   Inline `margin:24px 0` is preserved (we only override margin-left
   and margin-right). Inline `display:block` is preserved. To opt OUT
   for a specific block, add `.no-bleed` to the island wrapper. */
.bwa-ai-block-island:not(.no-bleed) {
  position: relative !important;
  left: 50% !important;
  right: 50% !important;
  margin-left: -50vw !important;
  margin-right: -50vw !important;
  width: 100vw !important;
  max-width: 100vw !important;
  overflow: visible !important;
}

/* Chrome containment — an island inside <header> or <footer> must NOT bleed.
   The bleed exists to break a block OUT of a capped content container. Chrome is
   already the full width of the page, so applying it there is not just redundant,
   it is the bug: left:50% + margin-left:-50vw + width:100vw makes the island wider
   than the content box by the vertical scrollbar and offset by half of it, so the
   footer's background stops short of the right edge and its inline overflow:hidden
   then clips the content. That reads as "the header and footer aren't full bleed"
   when the truth is the opposite -- they are, and the island inside them is wider.

   Specificity matters here: the bleed rule is `.bwa-ai-block-island:not(.no-bleed)`
   = (0,2,0), because :not() contributes its argument's weight. A plain
   `footer .bwa-ai-block-island` is only (0,1,1) and would LOSE. Repeating :not()
   takes this to (0,2,1) so it wins regardless of source order.

   overflow is forced visible because the loader sets overflow:hidden inline on the
   island, which would otherwise clip a footer laid out edge to edge. */
header .bwa-ai-block-island:not(.no-bleed),
footer .bwa-ai-block-island:not(.no-bleed) {
  position: static !important;
  left: auto !important;
  right: auto !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
  width: 100% !important;
  max-width: 100% !important;
  overflow: visible !important;
}

/* Column containment — an island in a column that SHARES its row must stay in
   that column. The bleed breaks a block out of a capped full-width column; from
   a col-sm-4 it is 100vw wide from the column's centre and paints over the
   neighbouring column. BWA-Clean domain 3 (2026-09-28): the trade-in FAQ in a
   col-sm-4 covered the valuation form in the col-sm-8 beside it, and the
   used-inventory CTA in a col-sm-6 covered the newsletter signup.
   Below 768px the col-sm-* columns stack full width and the bleed applies again.
   Specificity: :is() takes its argument's (0,1,0), so this is (0,3,0) against
   the bleed rule's (0,2,0). */
@media (min-width: 768px) {
  :is(.col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6,
      .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11) > .bwa-ai-block-island:not(.no-bleed) {
    position: static !important;
    left: auto !important;
    right: auto !important;
    margin-left: 0 !important;
    margin-right: 0 !important;
    width: 100% !important;
    max-width: 100% !important;
  }
}

/* Nested-island / inside-dialog containment.
   When an AI block island is rendered INSIDE another island, a modal,
   a popover, an off-canvas drawer, or any aria-dialog, the 100vw
   bleed must NOT fire — otherwise the inner island escapes its
   containing dialog and paints across the entire viewport, breaking
   the dialog's visual frame and trapping clicks behind it. These
   selectors detect the nested-context and reset the island back to
   `position: static; width: 100%` (its natural in-flow size) so it
   stays inside whatever dialog wraps it.
   Containers checked:
     - Another .bwa-ai-block-island (nested AI blocks)
     - [role="dialog"] / [role="alertdialog"] (ARIA dialogs)
     - .modal, .modal-content, .modal-body (Bootstrap modals)
     - .popover, .tooltip (Bootstrap popover/tooltip)
     - .offcanvas (Bootstrap off-canvas drawer)
     - dialog (native HTML dialog element)
     - .ai-modal (BWA AI Content / AI Image / AI Block modals)
     - .aibp-edit-overlay (AI Block edit overlay's own wrapper) */
.bwa-ai-block-island .bwa-ai-block-island,
[role="dialog"] .bwa-ai-block-island,
[role="alertdialog"] .bwa-ai-block-island,
.modal .bwa-ai-block-island,
.modal-content .bwa-ai-block-island,
.modal-body .bwa-ai-block-island,
.popover .bwa-ai-block-island,
.tooltip .bwa-ai-block-island,
.offcanvas .bwa-ai-block-island,
dialog .bwa-ai-block-island,
.ai-modal .bwa-ai-block-island,
.aibp-edit-overlay .bwa-ai-block-island {
  position: static !important;
  left: auto !important;
  right: auto !important;
  margin-left: 0 !important;
  margin-right: 0 !important;
  width: 100% !important;
  max-width: 100% !important;
  overflow: hidden !important; /* re-clip so nothing escapes the dialog frame */
}

/* Content cap inside AI Block islands — the OUTER section/wrapper stays
   at 100vw so backgrounds (gradients, nebula canvas, hero images) paint
   edge-to-edge, but anything matching `*-inner` (the convention AI blocks
   use for their content wrapper) gets centered and capped at 1600px so
   readable text doesn't stretch the full viewport.
   Backgrounds typically live on direct children of the section
   (`.cj-nebula-bg`, `.cj-hero-bg`, etc.) which DO NOT match `*-inner`,
   so they keep their full-width behavior. */
.bwa-ai-block-island [class$="-inner"],
.bwa-ai-block-island [class$="-grid"],
.bwa-ai-block-island [class$="-content"],
.bwa-ai-block-island [class$="-wrap"],
.bwa-ai-block-island [class$="-wrapper"],
.bwa-ai-block-island [class$="-row"],
.bwa-ai-block-island [class$="-container"],
.bwa-ai-block-island [class*="-inner "],
.bwa-ai-block-island [class*="-content-cap"] {
  /* Inner content cap — reads from --bwa-content-cap CSS variable so
     the AI Block edit overlay's "Inner cap" dropdown can override per
     block by writing the var inline on the outer wrapper. 1600px is
     the default when no override is set. To disable the cap entirely
     for a block, set --bwa-content-cap: none on the wrapper.
     Selector list covers every common content-wrapper naming pattern:
       *-inner   (cj-commerce-inner)
       *-grid    (bento-grid, feature-grid)
       *-content (panel-content, card-content)
       *-wrap / *-wrapper (generic flex/grid wrappers)
       *-row     (feature-row, stats-row, button-row)
       *-container (semantic content containers, NOT bootstrap .container)
     Backgrounds typically use *-bg / *-background / *-overlay which
     don't match — so the cap binds inner content without strangling
     edge-to-edge gradients / canvases / images.
     NOTE: AIBlockIslandLoader.cs ALSO emits a `<style>` with the same
     selectors AFTER each block's scoped CSS (cascade-order + higher
     specificity tiebreak) so block-author hardcoded max-widths can't
     beat the editor's chosen cap. */
  max-width: var(--bwa-content-cap, 1600px) !important;
  margin-left: auto !important;
  margin-right: auto !important;
  /* DO NOT set width or padding here — preserve the block's own
     responsive padding (clamp()) and width:100% so it shrinks with
     the viewport on small screens. */
}

/* Same content cap for blocks that use a nested .container instead of
   an `*-inner` wrapper (BWA legacy pattern). */
.bwa-ai-block-island > section > .container,
.bwa-ai-block-island > article > .container,
.bwa-ai-block-island > div > .container {
  max-width: 1600px !important;
  margin-left: auto !important;
  margin-right: auto !important;
}

/* Explicit defensive cap on tab panels / content cards inside AI Block
   islands — these are the readable-content surfaces (paragraphs, lists,
   flow diagrams) that must stay contained even if a future CSS rule
   accidentally unbinds the parent inner-wrapper cap. Defaults to the
   same 1600px content rail; tighten per-block if a specific design
   needs narrower (e.g. long-form text panels at 1280px). */
.bwa-ai-block-island [class*="tab-panel"],
.bwa-ai-block-island [class*="panel-content"],
.bwa-ai-block-island [class*="card-body"],
.bwa-ai-block-island [class*="content-card"] {
  max-width: 1600px;
  margin-left: auto;
  margin-right: auto;
  box-sizing: border-box;
}

/* Pack-to-top override for AI block cards.
   AI-generated cards (article.g-card, .bento-card, .feature-card, etc.)
   commonly use `display: flex; flex-direction: column;` with one of
   these gap-creating patterns:
     - `justify-content: space-between` on the card
     - `margin-top: auto` on the last child (or steps list / CTA)
     - `flex: 1` on a middle element that grows to fill empty space
   When the parent grid stretches all cards to match the tallest
   sibling's height (typical `align-items: stretch` behaviour) and one
   card has shorter content than the tallest, the gap-creating pattern
   pushes the short card's content apart, leaving a visible empty band
   in the middle. This override packs the card's children to the top
   so the short card's content stays clustered against its header.
   Block authors who explicitly want bottom-anchored CTAs in equal-
   height cards can opt out by adding `.no-pack-top` to the card. */
.bwa-ai-block-island article:not(.no-pack-top),
.bwa-ai-block-island [class*="-card"]:not(.no-pack-top),
.bwa-ai-block-island [class*="g-card"]:not(.no-pack-top) {
  justify-content: flex-start !important;
  align-content: flex-start !important;
}
.bwa-ai-block-island article:not(.no-pack-top) > *,
.bwa-ai-block-island [class*="-card"]:not(.no-pack-top) > *,
.bwa-ai-block-island [class*="g-card"]:not(.no-pack-top) > * {
  /* Cancel the `margin-top: auto` push pattern. `unset` resolves to
     `0` when nothing else sets margin-top, neutralising the auto-push;
     explicit block-author margins on specific children (e.g. via a
     `.steps { margin-top: 24px }` rule) still win because that rule
     fires AFTER this one only if specificity allows — and the block's
     selector usually has higher specificity than `[class*="-card"] > *`.
     `flex-grow: 0` cancels the `flex: 1` filler pattern (a spacer div
     or middle content area that grows to fill the stretched height,
     creating the hole). Combined, these two cancellations stop short
     cards from developing visible empty bands when they sit next to
     taller siblings in an `align-items: stretch` grid. */
  margin-top: unset !important;
  flex-grow: 0 !important;
}
.bwa-ai-block-island article:not(.no-pack-top) > *:first-child,
.bwa-ai-block-island [class*="-card"]:not(.no-pack-top) > *:first-child,
.bwa-ai-block-island [class*="g-card"]:not(.no-pack-top) > *:first-child {
  /* First child: explicit 0 so the header sits flush with the card top. */
  margin-top: 0 !important;
}

/* ──────────────────────────────────────────────────────────────────
   PLACEMENT GRID — framework-independent module widths
   ───────────────────────────────────────────────────────────────────
   The platform's module width system IS Bootstrap's grid: every Module
   ships a SpanList of col-12/9/8/6/4/3, every placement writes one of
   them into <Span>, and the core concatenates that onto the placement's
   wrapper div. Two independent failure modes, both measured:

   1. THE ROW PARENT NEVER EXISTS. The CMS renders every zone as
      <div id="…znCntrl…" class="" data-zonename="…"> whatever the
      layout's ZoneClass says — measured on domains 3 and 4 (2026-09-04),
      including the tenants' own Container.ascx ("row-fluid row"). A bare
      .col-N is flex:0 0 auto with a percentage width and NO flex parent,
      so the WIDTH applies and the LAYOUT never happens: a col-3/col-9
      pair renders stacked, full width each.

   2. BOOTSTRAP MAY BE ABSENT. On a theme that does not load
      bootstrap.min.css, col-sm-6 computed 1200px instead of 612px inside
      a 1200px parent. The width dropdown in Page Manager becomes
      decorative and nothing errors.

   The fix is a literal wrapper the CMS does not own — .bwa-zone-row, put
   by the layout around the zone Panel — plus the geometry below.

   SCOPE DISCIPLINE. Every rule here is scoped under .bwa-zone-row, which
   exists only where a layout places it. Nothing here is global, nothing
   resets a bare element, and nothing sets margin-inline or max-width —
   those are bleed-killers for any module that bleeds by its own class.
   A zone-wide @scope was tried three times (2026-08-27, 2026-09-04, and
   .225–.227) and reverted three times, because the zone hosts stock
   Bootstrap plugins whose class names are Tailwind utility names at
   different values. This is deliberately not that: plain additive
   utilities, no wrapper rule, no reset.
   ────────────────────────────────────────────────────────────────── */

/* The zone under the wrapper IS the grid row (ZoneClass does not render). */
.bwa-zone-row > [data-zonename] {
  display: flex;
  flex-wrap: wrap;
  margin-right: calc(-.5 * var(--bs-gutter-x, 1.5rem));
  margin-left: calc(-.5 * var(--bs-gutter-x, 1.5rem));
}
.bwa-zone-row > [data-zonename] > * {
  flex-shrink: 0;
  max-width: 100%;
  padding-right: calc(var(--bs-gutter-x, 1.5rem) * .5);
  padding-left: calc(var(--bs-gutter-x, 1.5rem) * .5);
}

/* Platform span scale, independent of Bootstrap. Same computed widths as
   .col-N, so the two agree wherever both are present. Inert today: nothing
   carries bwa-span-* until the converter writes it into the placement's
   ClassName. */
.bwa-span-12 { flex: 0 0 auto; width: 100%; }
.bwa-span-9  { flex: 0 0 auto; width: 75%; }
.bwa-span-8  { flex: 0 0 auto; width: 66.66666667%; }
.bwa-span-6  { flex: 0 0 auto; width: 50%; }
.bwa-span-4  { flex: 0 0 auto; width: 33.33333333%; }
.bwa-span-3  { flex: 0 0 auto; width: 25%; }

/* The same geometry derived from the col-* the core ALREADY puts on every
   placement wrapper, so pages authored before bwa-span-* exists are correct
   too — including on a domain that never loads Bootstrap. Matched with
   [class~=] because the wrapper is routinely multi-class: the core renders
   e.g. class="span-12 col-12 dt-overlap". */
.bwa-zone-row > [data-zonename] > [class~="col-12"] { flex: 0 0 auto; width: 100%; }
.bwa-zone-row > [data-zonename] > [class~="col-9"]  { flex: 0 0 auto; width: 75%; }
.bwa-zone-row > [data-zonename] > [class~="col-8"]  { flex: 0 0 auto; width: 66.66666667%; }
.bwa-zone-row > [data-zonename] > [class~="col-6"]  { flex: 0 0 auto; width: 50%; }
.bwa-zone-row > [data-zonename] > [class~="col-4"]  { flex: 0 0 auto; width: 33.33333333%; }
.bwa-zone-row > [data-zonename] > [class~="col-3"]  { flex: 0 0 auto; width: 25%; }

/* Half the estate registers its SpanList as col-sm-* instead of col-* (both
   conventions are live in install SQL). Bootstrap's col-sm-N is full width
   BELOW the sm breakpoint and N/12 above it — reproduce that exactly, or a
   phone layout that used to stack would start sitting two-up. */
.bwa-zone-row > [data-zonename] > [class*="col-sm-"] { flex: 0 0 auto; width: 100%; }

@media (min-width: 576px) {
  .bwa-zone-row > [data-zonename] > [class~="col-sm-12"] { width: 100%; }
  .bwa-zone-row > [data-zonename] > [class~="col-sm-9"]  { width: 75%; }
  .bwa-zone-row > [data-zonename] > [class~="col-sm-8"]  { width: 66.66666667%; }
  .bwa-zone-row > [data-zonename] > [class~="col-sm-6"]  { width: 50%; }
  .bwa-zone-row > [data-zonename] > [class~="col-sm-4"]  { width: 33.33333333%; }
  .bwa-zone-row > [data-zonename] > [class~="col-sm-3"]  { width: 25%; }
}


/* ──────────────────────────────────────────────────────────────────
   BS5 GRID SPANS BEAT THE CONTENT CAP (2026-09-27)
   A placement's width control IS Bootstrap's grid: the platform renders a Span of col-N as the
   wrapper class col-sm-N. The corpus's cap rule
     .bwa-cap-content:not(.bwa-bleed){max-width:var(--bwa-cap);width:100%;margin:auto}
   (brand-corpus-generated-N.css) outranks .col-sm-N's width, so a capped placement set to 50%
   rendered 100% wide and the admin's grid control did nothing - measured on BWA-Clean domain 3:
   Testimonials and TradeIn at col-6 each rendered 1200px and stacked. A partial span keeps its
   grid width (and the grid's left alignment); the cap still bounds it via max-width, and a full
   span (col-sm-12) is untouched. Anchored on [data-zonename] so it outranks the cap rule.
   ────────────────────────────────────────────────────────────────── */
@media (min-width: 576px) {
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-1 { width: 8.33333333%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-2 { width: 16.66666667%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-3 { width: 25%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-4 { width: 33.33333333%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-5 { width: 41.66666667%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-6 { width: 50%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-7 { width: 58.33333333%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-8 { width: 66.66666667%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-9 { width: 75%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-10 { width: 83.33333333%; margin-left: 0; margin-right: 0; }
  [data-zonename] > :is(.bwa-cap-narrow,.bwa-cap-content,.bwa-cap-wide):not(.bwa-bleed).col-sm-11 { width: 91.66666667%; margin-left: 0; margin-right: 0; }
}


/* ──────────────────────────────────────────────────────────────────
   BAND GROUNDS (2026-09-27)
   A design pack states each band's ground (data-ground on the band). A WebStudio import carries
   the grounds that read under any plugin into the placement's ClassName beside its cap:
     bwa-ground-ruled  a rule above the band (the design's 3px ink rule) with the band's inset
     bwa-ground-boxed  the band as a card: hairline border, card radius, page surface
     bwa-ground-tint   the band on the secondary surface
     bwa-ground-page   the band on the page surface
   Dark grounds (inverse / brand) are not carried onto plugin bands: plugins paint their own light
   surfaces, so the band keeps the page ground. Every colour is a corpus role, so the band follows
   the site's brand. Anchored on [data-zonename] like the span rules above.
   ────────────────────────────────────────────────────────────────── */
[data-zonename] > .bwa-ground-ruled {
  border-top: 3px solid var(--bwa-color-ink-1, #201f1d);
  padding-top: var(--bwa-band-inset-block, 56px);
  padding-bottom: var(--bwa-band-inset-block, 56px);
}
[data-zonename] > .bwa-ground-ruled + .bwa-ground-ruled { border-top: 0; }
[data-zonename] > .bwa-ground-boxed {
  border: 1px solid var(--bwa-color-line, var(--bwa-color-bg-3, #d7d3d3));
  border-radius: var(--bwa-radius-card, var(--bwa-radius-md, 10px));
  background-color: var(--bwa-color-bg-1, #f3f2f2);
  overflow: hidden;
}
[data-zonename] > .bwa-ground-tint {
  background-color: var(--bwa-color-bg-2, #eae9e9);
  padding-top: var(--bwa-band-inset-block, 56px);
  padding-bottom: var(--bwa-band-inset-block, 56px);
}
/* A full-width tint band runs edge to edge while its content keeps the cap, the way the design
   paints it (`box-shadow: 0 0 0 100vmax` clipped to the band's own height). Capped, the stats
   band on trade-in, about and financing read as a grey box (2026-09-28). */
[data-zonename] > .col-sm-12.bwa-ground-tint {
  box-shadow: 0 0 0 100vmax var(--bwa-color-bg-2, #eae9e9);
  clip-path: inset(0 -100vmax);
}
[data-zonename] > .bwa-ground-page { background-color: var(--bwa-color-bg-1, #f3f2f2); }
/* A band whose plugin rendered nothing leaves no ground behind. CountdownTimer hides itself until
   the dealer sets its end date; on the specials page its column still drew the 3px rule and 112px of
   padding across an empty band (BWA-Clean domain 3, 2026-09-28). */
[data-zonename] > [class*="bwa-ground-"]:not(:has(*)) { display: none; }

/* Dark grounds. The band publishes the ink for the copy that sits DIRECTLY on it (a section
   heading, its lede, a "view all" link) as --bwa-band-ink / -muted / -line; a plugin opts in by
   reading those for its band-level copy, and its own surfaces (cards, panels) keep their own ink.
   WebStudio only emits these classes for a plugin that reads the band ink, so a plugin that has
   not opted in is never put on a dark ground with dark copy. */
[data-zonename] > .bwa-ground-inverse {
  --bwa-band-ink: var(--bwa-color-bg-1, #f3f2f2);
  background-color: var(--bwa-color-ink-1, #201f1d);
}
[data-zonename] > .bwa-ground-brand {
  --bwa-band-ink: var(--bwa-color-on-primary, #ffffff);
  background-color: var(--bwa-color-primary, #7d5411);
}
[data-zonename] > :is(.bwa-ground-inverse, .bwa-ground-brand) {
  --bwa-band-ink-muted: color-mix(in srgb, var(--bwa-band-ink) 74%, transparent);
  --bwa-band-line: color-mix(in srgb, var(--bwa-band-ink) 34%, transparent);
  color: var(--bwa-band-ink);
  padding-top: var(--bwa-band-inset-block, 56px);
  padding-bottom: var(--bwa-band-inset-block, 56px);
  padding-left: var(--bwa-band-inset-inline, 24px);
  padding-right: var(--bwa-band-inset-inline, 24px);
}
