/* 10 — Sections
   Owns: default row rhythm, surface bands, shared section furniture
   Depends on: 01-tokens

   ── Property ownership (agreed 2026-09-05) ──────────────────
   The builder owns GEOMETRY: per-row padding, row and content width, column
   ratios, alignment. Rules here that set geometry are wrapped in :where() to
   sit at 0-1-0 so a PER-ROW setting from the BB editor wins.

   BB emits per-row padding into uploads/bb-plugin/cache/<id>-layout.css as
   `.fl-node-<id>.fl-row-default-height > .fl-row-content-wrap` (0-3-0), and
   that file loads at position 1, ahead of every child-theme file. Verified
   live 2026-09-05 by injecting exactly that selector as the FIRST stylesheet
   in <head> — earlier in source order than this file — and confirming it still
   won: the row took the injected 7px while untouched rows kept the 100px/60px
   from the rule below. So per-row settings beat us on specificity, not order,
   and an unwrapped selector here would have to out-specify 0-3-0 to break that.

   CAVEAT, and it is a real one: BB ALSO emits a global row-padding default as
   `.fl-row-content-wrap, .fl-builder-content > .fl-module-box { padding: 20px }`
   at 0-1-0. That ties with the :where() rule below and loses on source order,
   so THE ROW PADDING FIELD IN BB'S GLOBAL SETTINGS NO LONGER DOES ANYTHING.
   That is intended — the rhythm below is deliberately replacing it — but it
   fails silently, so change the rhythm here rather than in Global Settings.
   (An earlier note in this project recorded BB core as having no default row
   padding at all. That was wrong, and this comment supersedes it.)

   The CSS owns COLOUR and TYPOGRAPHY: those rules are deliberately NOT wrapped,
   and are meant to win. A colour picked in the BB editor is a raw hex in
   wp_postmeta that 01-tokens.css cannot see and that will not swap when this
   theme is cloned for another site. Set row backgrounds with a class from this
   file, never with the editor's colour picker. */

/* Rhythm, default-on for every content row rather than opt-in per row.
   Safe precisely because of the :where() above: a row with padding set in the
   builder overrides this silently. The failure mode is "a row I never thought
   about looks right", not "a row I forgot the class on has no padding". */
:where(.fl-page-content .fl-row) .fl-row-content-wrap {
    padding-block:  var(--section-padding);
    padding-inline: var(--section-padding-lr);
}

/* ── Surface bands ───────────────────────────────────────────
   Add a class to a row instead of picking a colour in the builder. A colour
   picked in the editor is a raw hex in wp_postmeta that 01-tokens.css cannot
   see and that will not travel when this theme is cloned; a class resolves
   through the token layer, so the whole site restyles from one file.

   Targets .fl-row-content-wrap because that is the element BB paints its own
   row background onto — set the class on the ROW, not the column.

   These tie BB's own per-row rule on specificity (both 0-2-0) and win on
   source order, since the builder's layout cache loads at position 1 and this
   file later. So a row that still has a colour set in the editor will LOOK
   right but carries a dead hex; clear the picker when adding the class.

   The tints in use on the site:
     --alt    #f6f5f2   the common off-white band
     --muted  #efeeea   one step darker, for a band next to an --alt one
     --dark   #01385b   navy;  also inverts its text, see below
     --accent #df0b29   brand red; also inverts its text, see below

   --accent is the LOUD one, and the only band here that competes with the
   buttons and eyebrows sitting on it rather than receding behind them. It is
   meant for a short band — the page-title strip it was added for — not for a
   row of content. Two of them in a row would each halve the other's effect. */
.rw-section--alt    > :is(.fl-row-content-wrap, .rw-band__inner) { background-color: var(--surface-alt); }
.rw-section--muted  > :is(.fl-row-content-wrap, .rw-band__inner) { background-color: var(--surface-muted); }
.rw-section--dark   > :is(.fl-row-content-wrap, .rw-band__inner) { background-color: var(--brand-dark); }
.rw-section--accent > :is(.fl-row-content-wrap, .rw-band__inner) { background-color: var(--accent); }

.rw-section--narrow > .fl-row-content-wrap {
    padding-block: var(--section-narrow-padding);
}

/* ── Page-title band ─────────────────────────────────────────
   The first row of an interior page: breadcrumbs and the <h1> on a full-bleed
   colour, above the content rows. Currently /video-production/.

   Named for the row's JOB, not its markup or its geometry, and that is the
   whole argument for the rename:

     `h1-`          names a tag that happens to be inside it today. A template
                    that renders the same band with an h2 would carry a class
                    that lies about its own contents.
     `-full-width-` restates something the builder already says: BB emits
                    .fl-row-full-width on this row, from the row's own Width
                    setting. Two sources of truth for one fact.
     `-row`         every .rw-section--* is a row; the prefix carries it.

   Role-naming also survives the thing most likely to change here. A photo or
   video background would rewrite every value in this rule and none of the
   name — whereas a class called "narrow" would have to be edited in the
   builder the day the padding stops being narrow.

   Padding is BLOCK ONLY. The inline padding stays on --section-padding-lr from
   the rhythm above, deliberately: the h1 has to line up with the copy in the
   rows beneath it, and a title band that indents differently from the page is
   visible the moment you scroll past it.

   Beaver Builder still wins if it is asked to. Per-row padding from the editor
   lands at 0-3-0 against this rule's 0-2-0, so setting a padding on this row in
   the builder silently overrides the line below (that is the ownership split
   at the top of this file, working as intended). This row has none set today —
   it was showing the 100px default rhythm — so the rule takes effect. */
.rw-section--page-title > .fl-row-content-wrap {
    padding-block: var(--section-narrow-padding);
}

/* THE SAME BAND, BUILT WITHOUT THE BUILDER, NEEDS A BIGGER NUMBER TO LOOK THE
   SAME — which is why this is a separate rule rather than another arm of the
   :is() above, and why it is not simply 60px.

   Inside Beaver Builder the heading is wrapped in a module, and BB pads every
   module by 20px from its own global default (`.fl-builder-content >
   .fl-module-box { padding: 20px }`, noted at the top of this file). So the
   visible space above the breadcrumbs on /video-production/ is the token PLUS
   that 20px — measured at 40px when the token was 20px. A shortcode-rendered
   band has no module, so the token is all there is, and at 40px it read 20px
   tighter than every other title band on the site.

   The calc keeps them matched rather than merely equal today: change
   --section-narrow-padding and both move together. It resolves to 60px at the
   current 40px token. */
.rw-section--page-title > .rw-band__inner {
    padding-block: calc(var(--section-narrow-padding) + 20px);
}

/* The h1 carries a margin-bottom from 02-base.css (30px when this was written,
   1rem since) which at the full 100px rhythm is invisible and at a narrow band
   is a noticeable share of the padding again — the band reads as less space
   above the text than below it, off-centre in a way that looks like a mistake
   rather than a choice. Zeroed on the last child so the padding is the only
   thing setting the band's depth.

   Scoped to .fl-html because that is the module wrapper the content sits in;
   :last-child so it keeps working if a standfirst paragraph is added under the
   heading later. */
.rw-section--page-title :is(.fl-html, .rw-band__content) > :last-child {
    margin-bottom: 0;
}

/* ── 50/50 split row ─────────────────────────────────────────
   A two-column row where one column is a full-bleed background image and the
   other holds the copy. Either side can be the image — nothing here cares
   about order.

   HOW TO BUILD ONE, in Beaver Builder:
     1. Row → Style → Width: Full Width, AND Content Width: Full Width.
        The second one is the effect: without it the columns stop at the
        centred container and nothing is full-bleed.
     2. Row → Advanced → CSS Class: rw-50-50
     3. Column group → Equal Heights: Yes.  ← the one people forget
     4. Two columns at 50%.
     5. On the image column: Style → Background → Photo, Size: Cover, pick a
        Position. Leave the column EMPTY.
     6. Put the copy in the other column. Nothing to add to it.

   STEP 3 IS NOT OPTIONAL and its failure is silent-ish. Without it .fl-col-group
   stays display: block, the columns do not stretch to a common height, and an
   EMPTY column has no height of its own — so the image column collapses to the
   1px .fl-col minimum and the photo never appears. The symptom is a row with
   copy on one side and nothing at all on the other. Equal Heights is BB's own
   feature (.fl-col-group-equal-height, fl-builder-layout.css:229) and it is not
   reimplemented here: a copy of its flex rules in this file is a copy that can
   drift from the plugin's.

   There is no class for the content column and none to say which side the
   image is on. BB already stamps .fl-col-bg-photo on a column with a photo
   background, so the columns identify themselves and cannot disagree with the
   markup — swap them in the builder and the padding follows the copy.

   The trade is that this keys on a BB internal. If a future BB drops that
   class the row degrades to "no padding on either column", which is visible at
   once rather than subtly wrong. A background VIDEO is not covered
   (.fl-col-bg-video) — add it to the :not() and the media query below if that
   is ever wanted, rather than putting a marker class on the content column.

   Widths are NOT set here despite the name. Beaver Builder owns column widths
   and writes them per node; a rule here would fight the builder for no gain,
   and a 60/40 built with this class works exactly as well. */
.rw-50-50 > .fl-row-content-wrap {
    padding: 0;
}

/* The copy column gets the rhythm back as its own padding, so a 50/50 row is
   the same height off the top as a normal row — the shared tokens are what
   keep it in step if the rhythm ever changes.

   Its text will NOT line up with the copy in the rows above and below: those
   sit inside the centred fixed-width container, this starts at the viewport
   edge. That is inherent to a full-bleed split, not a bug to fix here.

   :where() so the builder still wins. BB writes per-column padding as
   `.fl-node-<id> > .fl-col-content` at 0-2-0; this sits at 0-1-0, so setting a
   padding on the column in the editor overrides it, per the ownership split at
   the top of this file. */
:where(.rw-50-50 .fl-col:not(.fl-col-bg-photo)) > .fl-col-content {
    padding-block:  var(--section-padding);
    padding-inline: var(--section-padding-lr);
}

/* ── Stacked ─────────────────────────────────────────────────
   Below BB's small breakpoint the columns stop being flex items and two things
   break at once. Both are BB defaults that are right for a normal column and
   wrong for a full-bleed one, which is why they are undone here rather than
   left as two more settings to remember in the builder.

   768px is BB's small breakpoint on this site — its cached layout CSS emits
   max-width: 768px / 992px / 1200px. If those are changed in BB → Global
   Settings → Responsive, this has to move with them. */
@media (max-width: 768px) {

    /* 1. Height. The equal-height group reverts to display: block
       (fl-builder-layout-responsive.css:16), the stretch goes with it, and the
       empty image column collapses to nothing — the photo just disappears on a
       phone. Scoped to the media query on purpose: forcing a height on desktop
       could push the row taller than the copy it is supposed to match. */
    :where(.rw-50-50 .fl-col-bg-photo) > .fl-col-content {
        min-height: clamp(220px, 60vw, 380px);
    }

    /* 2. Width. BB caps a stacked column at
       `.fl-col-small:not(.fl-col-small-full-width) { max-width: 400px }` and
       centres it, which on a phone leaves the photo as a 400px block with gaps
       either side — the opposite of full-bleed. BB's own fix is the column's
       "Small Device Full Width" setting; done here instead so the class needs
       two builder settings rather than four, and so it cannot be half-applied
       to one column of the pair.

       0-3-0 against BB's 0-2-0, so this wins on specificity rather than on the
       load order of the builder's cache. */
    .rw-50-50 .fl-col.fl-col-small {
        max-width: none;
    }
}

/* ── Bands outside Beaver Builder ────────────────────────────
   The band classes above were written against the builder's DOM: they paint
   and pad `> .fl-row-content-wrap`, because that is the element BB puts a row
   background on. A PHP template cannot honestly emit that class — it is a
   claim that Beaver Builder built the element — and, more practically, BB's
   `.fl-row-fixed-width { max-width: 1100px }` is written into a LAYOUT CACHE
   that only loads on pages which actually have a builder layout. The
   testimonials archive has none, so reusing BB's class names there would give
   an element with no width at all.

   So the two structural jobs get theme-owned names, and the band rules above
   accept either. The shapes mirror BB's exactly, because the reasons are the
   same ones:

     .rw-band__inner     full-bleed. Carries the background and the padding —
                         the .fl-row-content-wrap role.
     .rw-band__content   centred and capped — the .fl-row-content
                         .fl-row-fixed-width role.

     <div class="rw-section--page-title rw-section--accent">
       <div class="rw-band__inner">
         <div class="rw-band__content"> … </div>

   Emitted by [rw-h1-full-width-row] in
   rw/rw-shared-shortcodes/rw-shared-shortcodes.php.

   The inline padding is restated here rather than inherited: the default
   rhythm at the top of this file is scoped to `:where(.fl-page-content
   .fl-row) .fl-row-content-wrap`, which a band outside the builder does not
   match. Block padding still comes from the band class, so a --page-title band
   is the same height whichever way it was built. */
.rw-band__inner {
    padding-inline: var(--section-padding-lr);
}

.rw-band__content {
    max-width: var(--row-content-width);
    margin-inline: auto;
}

/* ── Testimonials archive ────────────────────────────────────
   /reviews/ is rendered by the rw-testimonials plugin's own template, not by
   the builder, so nothing was constraining it — the review grid ran the full
   width of the viewport while every other page stopped at 1100px.

   THE TWO ELEMENTS SPLIT THE JOB THE SAME WAY .rw-band__inner AND
   .rw-band__content DO, and that is not tidiness — it is the only way the two
   line up. Put the max-width and the padding on ONE element and they fight:
   box-sizing is border-box site-wide (base-4's reset), so max-width caps the
   BORDER box, and 1100px minus 60px of padding either side leaves 980px of
   content against the title band's 1100px. The reviews sat 120px narrower than
   the heading above them.

   So the wrapper pads and the container is capped, exactly as the band does
   it. Both now resolve to a 1100px content box sharing one edge.

   The wrapper staying full-bleed is unaffected: padding insets its CONTENTS,
   not its background, so it is still the element a future full-width band on
   this page would paint.

   Reaching into plugin markup from the theme is normally the wrong way round;
   it is right here because LAYOUT is the theme's job and the plugin
   deliberately ships no opinion about width — it styles neither class. */
.rw-testimonials-archive-wrapper {
    padding-inline: var(--section-padding-lr);
    padding-block: var(--section-padding);
}

.rw-testimonials-archive-wrapper .testimonials-container {
    max-width: var(--row-content-width);
    margin-inline: auto;
}

/* ── Review card overrides ───────────────────────────────────
   Two plugin defaults, and only these two. Everything else about the card is
   the plugin's to own — this file is not the place to restyle a component
   rw-testimonials ships complete.

   `body.` IS LOAD-BEARING. The plugin declares both of these at the identical
   `.post-type-archive-rw_testimonials .rw-masonry-grid-container .<thing>`,
   which is 0-3-0 — so a rule written the same way here would tie and be settled
   by which stylesheet the enqueue happened to emit second. The plugin and the
   theme both enqueue on wp_enqueue_scripts, so that order is not something to
   depend on. Naming the element the archive class actually sits on takes these
   to 0-3-1 and the question stops mattering.

   If review-card styling grows past a handful of rules it wants its own file
   (15-reviews.css); it is here for now because the container rules above are
   the only other thing on this page and the two belong together. */

/* The star row is a fixed-width box with overflow: hidden — the plugin's 103px
   is what decides how much of it shows. */
body.post-type-archive-rw_testimonials .rw-masonry-grid-container .rating-stars {
    width: 108px;
}

/* line-height is the change; the plugin sets none here so the author block was
   inheriting the body's, which is loose for three or four short stacked lines.

   font-weight RESTATES the plugin's current default rather than changing it.
   Deliberate: the card's name is meant to be the bold line whatever
   rw-testimonials does next, and a weight the theme depends on should not live
   only in a plugin it does not control. It is redundant today. */
body.post-type-archive-rw_testimonials .rw-masonry-grid-container .rw-testimonial-author {
    font-weight: 700;
    line-height: 1.4;
}

/* The source filters hovered to var(--rw-primary), which the plugin defines as
   #10B2C7 — a teal, and nothing to do with this site. The theme's --rw-*
   mapping block in 01-tokens.css is commented out deliberately (see the note
   there; do not re-enable it without asking), so the plugin's own palette is
   what the buttons were reaching for.

   Repointed to --accent rather than repointing the token, because --rw-primary
   also drives sliders, pagers and the sidebar widget; this is the one control
   that was asked about. Filled accent with white text, i.e. the same gesture
   .btn-primary makes, so a hovered filter reads as the same kind of button as
   everything else on the site.

   :focus-visible is paired with :hover — the plugin styles only :hover, and a
   control that answers a pointer but not a keyboard is an inconsistency this
   theme does not have anywhere else.

   0-3-2 against the plugin's 0-3-1, so it wins on specificity rather than on
   enqueue order. */
body.post-type-archive-rw_testimonials .filter-button-group button:hover,
body.post-type-archive-rw_testimonials .filter-button-group button:focus-visible {
    border-color: var(--accent);
    background-color: var(--accent);
    color: var(--white);
}

/* Selected filter, added once the plugin started emitting `is-active`
   (rw-testimonials 1.2.5, assets/js/isotope_init.js). Same accent fill as the
   hover above, which is the plugin's own intent — its rule pairs
   `.is-active` with `.is-active:hover` so selection and hover read as one
   state — just pointed at this site's palette instead of the plugin's teal
   --rw-primary. font-weight is the plugin's and stays there.

   THE :hover CLAUSE IS NOT OPTIONAL. The plugin's `.is-active:hover` is 0-4-1,
   which beats the 0-3-2 hover rule above on class count, so without it the
   teal came back the moment the cursor crossed the selected button. Repeating
   the declarations at 0-4-2 is what settles it.

   Same `body.` prefix and the same reason as the card overrides further up:
   0-3-2 / 0-4-2 against the plugin's 0-3-1 / 0-4-1, so this wins on
   specificity and not on which stylesheet the enqueue happened to emit last. */
body.post-type-archive-rw_testimonials .filter-button-group button.is-active,
body.post-type-archive-rw_testimonials .filter-button-group button.is-active:hover {
    border-color: var(--accent);
    background-color: var(--accent);
    color: var(--white);
}

/* ── Section furniture ───────────────────────────────────────
   Shared, not hero-specific: .rw-eyebrow is already in the markup of the second
   home row as well. */
.rw-eyebrow {
    margin: 0 0 var(--spacing-lg);
    font-family: var(--font-display);
    font-weight: 600;
    font-size: clamp(0.8rem, 0.73rem + 0.3vw, 0.9rem);
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--accent);
}

.rw-eyebrow--center { text-align: center; }

/* ── Breadcrumbs ─────────────────────────────────────────────
   The trail above the <h1> in the page-title band. Markup comes from SEOPress's
   [wpseo_breadcrumb] inside a .rw-breadcrumbs wrapper:

     <div class="rw-breadcrumbs">
       <nav aria-label="breadcrumb">
         <ol class="breadcrumb">
           <li class="breadcrumb-item"><a href="/"><span>Home</span></a></li>
           <li class="breadcrumb-item active" aria-current="page"><span>…</span></li>
         </ol>
       </nav>
     </div>

   The list reset and the " » " separator are NOT here and must not be
   duplicated here: SEOPress prints them itself, in a <style> block in <head>
   (.breadcrumb, .breadcrumb li, .breadcrumb li::after). This file only sizes
   and spaces the trail. If the separator ever changes, that is the plugin's
   setting, not a bug in this rule.

   The hairline is deliberately white at 10%: this trail only ever appears in
   the page-title band, which is --accent or --brand-dark, and a light rule on
   a dark band is the only version of this that is quiet enough. If breadcrumbs
   are ever added to a LIGHT row it will vanish there — swap the colour for
   `color-mix(in srgb, currentColor 10%, transparent)`, which follows whatever
   the band sets the text to. Not done pre-emptively: it is a heavier mechanism
   than today's single use needs. */
.rw-breadcrumbs {
    font-size: clamp(0.75rem, 0.7rem + 0.25vw, 0.875rem);
    width: max-content;
    margin-top: 10px;
    padding-top: 10px;
    border-top: 1px solid rgba(255, 255, 255, 0.2);
}

/* No underline at rest, underline on hover — the reverse of a body link,
   because a trail of underlined words reads as a row of buttons and competes
   with the <h1> right beneath it.

   Both selectors are deeper than they look, ON PURPOSE. The dark-band rules at
   the foot of this file style `a:not(.btn):not(.rw-grid-item *)` at 0-2-1 and
   its hover pair at 0-3-1; matching the markup down to the `li` lands these at
   0-2-2 and 0-3-2, which beats both OUTRIGHT rather than tying and relying on
   these lines sitting later in the file. Order-independent, so moving this
   block cannot silently restore the underline.

   The hover rule is not redundant with the band's: the band would restore the
   underline on hover anyway, but only inside a dark band. Stated here, the
   behaviour travels if this trail is ever used somewhere else. */
.rw-breadcrumbs .breadcrumb li a {
    text-decoration: none;
}

.rw-breadcrumbs .breadcrumb li a:is(:hover, :focus) {
    text-decoration: underline;
}

/* ── CTA actions row ─────────────────────────────────────────
   A row of buttons under centred section copy. Same job as
   .rw-hero__actions in 11-hero.css — lay the buttons out in a row that wraps
   on narrow screens — but centred rather than left-aligned, because the copy
   it sits under is centred. Currently the "Let's Make Something" band.

     <h2 class="text-center">Let's Make Something</h2>
     <p  class="text-center">Whether you need a camera package…</p>
     <div class="rw-cta__actions">
       <a class="btn btn-primary"         href="/get-a-quote/">Get a quote</a>
       <a class="btn btn-outline-neutral" href="/gear-rentals/">Browse Gear</a>
     </div>

   Declared here rather than sharing a rule with .rw-hero__actions, even
   though the two differ by one line. 11-hero.css loads AFTER this file, so a
   shared selector would have to live here and be extended there — which makes
   a section-level file the owner of hero markup and inverts the layer order
   the numbering exists to enforce. Three declarations restated is the cheaper
   of the two problems.

   `text-align: center` on the parent would NOT do this job: these are flex
   items once the row is a flex container, and text-align does not position
   them. It also would not survive the buttons wrapping.

   flex-wrap + justify-content together are what make the wrap case right —
   below ~480px the two buttons stack, and each wrapped line stays centred
   rather than the second button hanging left under the first. */
.rw-cta__actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--gutter);
}

/* ══ Dark bands ══════════════════════════════════════════════
   "Dark" here means ANY band dark enough to need light text on it — the navy
   and the brand red both qualify. Three ways in, and they are not the same
   thing:

     .rw-section--dark   paints the navy AND inverts. One class, use this.
     .rw-section--accent paints the red  AND inverts. One class, use this.
     .rw-dark-bg         inverts only, paints nothing. For a row whose
                         background is something this file cannot supply —
                         today the gradient on the "we travel anywhere" band,
                         and any future photo or video background.

   Do NOT pair a painting class with .rw-dark-bg: the paint classes already
   carry the inversion, so the second class does nothing but suggest to the
   next reader that it is load-bearing.

   Everything below applies to all three. That is not laziness — every rule
   here resolves to white or to an off-white, and both backgrounds take those
   identically. The one place red and navy genuinely differ is .btn-primary,
   which is itself red; that divergence is handled at the end of this block.

   ── The specificity contract, which is the whole design here ──

   Every rule below is wrapped in :where(), so the dark-band selector
   contributes NOTHING and each rule scores only what its own subject scores:
   `:where(...) p` is 0-0-1, exactly as if it were a bare `p`. It beats the
   base styles in 02-base.css purely on source order, because this file is
   enqueued after that one.

   That handles components that state their own colours: .rw-card--image h3
   (0-2-1) stays near-black and .rw-card--text p (0-2-1) stays muted, both
   outranking the inversion without 12-cards.css having to know this file
   exists.

   It is NOT sufficient on its own, which is worth knowing before trusting it
   again. Measured 2026-09-12 with a card grid forced into a dark band: the
   <p> in .rw-card--image has no colour rule in 12-cards.css (only the h3 and
   the list items do), and two cards on the home page carry no variant class
   at all — their h3 and paragraphs are styled by nothing. Every one of those
   inherited the inversion and turned white INSIDE a white panel. Specificity
   only protects what someone remembered to state.

   So the inversion is also stopped at the card's edge, structurally, with
   :not(.rw-grid-item *) on each rule that sets a text colour. A card is a
   light island: it brings its own white panel, so the text on it must stay
   dark whatever the band underneath is doing. This is a property of the
   panel, not of any one card variant, which is why it is expressed once here
   rather than as a colour on every element of every variant.

   :not() with a complex selector is Selectors Level 4 — confirmed supported
   in this browser via CSS.supports('selector(p:not(.x *))'), and available
   everywhere since Safari 16.4. Note it raises each rule to 0-1-1, because
   :not() takes the specificity of its argument.

   The remaining trade: a blanket inversion is still easy to outrank by
   accident. That is the right way round — a component that knows its own
   colours SHOULD beat a band it happens to sit in — but anything added here
   must be checked against the components that will sit in these rows, not
   just against 02-base.css. Check it in a real dark row, not by reading.

   Verified 2026-09-12 that no Beaver Builder module CSS on this site sets a
   text colour, so nothing of BB's silently outranks these. If a module ever
   gets a colour set in the editor, it will win, and that is again correct:
   an explicit per-module choice should beat the band. */

/* Headings. All six, not just the three that carry a colour in 02-base.css —
   h4-h6 inherit from body there, and inheriting --text on navy is the same
   invisibility as an explicit one. */
:where(.rw-dark-bg, .rw-section--dark, .rw-section--accent) :is(h1, h2, h3, h4, h5, h6):not(.rw-grid-item *) {
    color: var(--white);
}

/* Body copy and loose list text. `li` is included because a plain list in a
   row is content like any other; a list inside a card is not affected, since
   .rw-card--content li (0-1-1) outranks this. */
:where(.rw-dark-bg, .rw-section--dark, .rw-section--accent) :is(p, li, blockquote, dd, dt, figcaption, address):not(.rw-grid-item *) {
    color: var(--white);
}

/* Links.
   02-base.css sends every anchor to --brand (#014f7f), which on --brand-dark
   (#01385b) is very nearly the background itself — a link in a dark band was
   effectively invisible. White plus a permanent underline instead: the
   underline is doing the work colour normally does, since there is no second
   colour here that stays legible on navy AND reads as a link.

   --accent is deliberately NOT used. Red #df0b29 on navy #01385b is two dark
   colours against each other; it looks like the brand but cannot be read.
   Accent still earns its place in these bands as a BUTTON fill, where it sits
   on its own light-on-dark background — see .btn-primary, untouched below. */
:where(.rw-dark-bg, .rw-section--dark, .rw-section--accent) a:not(.btn):not(.rw-grid-item *) {
    color: var(--white);
    text-decoration: underline;
}

:where(.rw-dark-bg, .rw-section--dark, .rw-section--accent) a:not(.btn):not(.rw-grid-item *):is(:hover, :focus) {
    color: var(--surface-alt);
    text-decoration: underline;
}

/* Eyebrow. Same reasoning as links: --accent on navy is unreadable. It keeps
   its drawn dot, which takes currentColor and follows this automatically. */
:where(.rw-dark-bg, .rw-section--dark, .rw-section--accent) .rw-eyebrow {
    color: var(--white);
}

/* Outline buttons.
   .btn-outline-neutral is --black text on a --border-strong outline, built for
   a light background. On navy it is near-black on dark blue — the "Browse
   Gear" button in the CTA band was effectively unreadable. Inverted to the
   same IDEA rather than a different button: a quiet outline that fills on
   hover, reading as secondary next to .btn-primary exactly as it does on
   light rows.

   .btn-outline-primary gets the same treatment for the same reason — --brand
   on --brand-dark has almost no contrast. It is unused in a dark band today;
   included so the pair cannot diverge later.

   .btn-primary is untouched on the NAVY band on purpose: accent red on navy is
   strong and readable, and it should stay the loudest thing there. On the red
   band it is the one thing that cannot stay as it is — see below. */
:where(.rw-dark-bg, .rw-section--dark, .rw-section--accent) :is(.btn-outline-neutral, .btn-outline-primary):not(.rw-grid-item *) {
    border-color: var(--white);
    color: var(--white);
}

:where(.rw-dark-bg, .rw-section--dark, .rw-section--accent) :is(.btn-outline-neutral, .btn-outline-primary):not(.rw-grid-item *):is(:hover, :focus) {
    background-color: var(--white);
    border-color: var(--white);
    color: var(--brand-dark);
}

/* Focus rings. 02-base.css draws .btn:focus-visible against a light page; on
   navy that ring needs to be the light colour instead or it disappears. */
:where(.rw-dark-bg, .rw-section--dark, .rw-section--accent) .btn:not(.rw-grid-item *):focus-visible {
    outline-color: var(--white);
}

/* The one rule the red band does NOT share with the navy one.
   .btn-primary is --accent on --accent: an invisible button, white label
   floating on the band. The two swap — white fill, red label — which keeps it
   the loudest element in the row for the same reason it is on navy, by being
   the only thing with a filled background.

   Scoped to .rw-section--accent alone, NOT to .rw-dark-bg: a row using that
   class supplies its own background, which this file cannot see and which is
   very unlikely to be exactly this red.

   0-2-0 against .btn-primary's 0-1-0 in 02-base.css, and :where() keeps the
   band out of the count, so this needs the hover pair restated — the base
   .btn-primary:hover is 0-2-0 too and would otherwise take the fill back to
   --accent-dark on the first mouseover. */
:where(.rw-section--accent) .btn-primary:not(.rw-grid-item *) {
    background-color: var(--white);
    border-color: var(--white);
    color: var(--accent);
}

:where(.rw-section--accent) .btn-primary:not(.rw-grid-item *):is(:hover, :focus) {
    background-color: var(--surface-alt);
    border-color: var(--surface-alt);
    color: var(--accent-dark);
}

/* Cards stay a light island on a dark band. The :not() above keeps the
   inversion out; this says what the inside of the panel inherits instead, so
   an element no variant has styled — the bare .rw-grid-item cards on the home
   page have exactly that — lands on --text rather than on whatever the band
   would have given it. Belt to the :not()'s braces, and it keeps working if a
   future band ever sets `color` on the row itself. */
:where(.rw-dark-bg, .rw-section--dark, .rw-section--accent) .rw-grid-item {
    color: var(--text);
}

/* Decorative lead-in dot. Drawn rather than typed as a "•" so screen readers
   don't announce it — the eyebrow text carries its own "·" separators, which
   are content and stay in the markup. */
.rw-eyebrow::before {
    content: "";
    display: inline-block;
    width: 0.4em;
    height: 0.4em;
    margin-right: 0.6em;
    border-radius: 50%;
    background-color: currentColor;
    vertical-align: 0.15em;
}
