* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    /* min-height (not height:100%) so the body grows past the viewport with its content —
       mirroring the editor's protected.css. A fixed height:100% on this flex-column body caps
       it at the viewport and collapses any zero-content child to 0px, which broke anime.js's
       onScroll viewport probe (a height:100lvh test div it appends to <body>): it measured the
       scroll container as 0-height and collapsed every scroll animation on the published page. */
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background-color: var(--bg-color, #fff);
    font-family: var(--font-family, Helvetica, sans-serif);
    font-size: var(--font-size, 1rem);
    line-height: var(--line-height, 1.5);
    color: var(--font-color, #000);
}

[data-frame-placement="body"] {
    position: fixed;
    inset: 0;
    width: 100%;
    height: 100%;
    z-index: 9999;
    overflow: hidden;
}

[data-frame-placement="portal"] {
    background-color: transparent;
}

[data-frame-placement="portal"] [data-gjs-type="wrapper"] {
    min-height: auto;
    display: block;
    background-color: transparent;
}

[data-frame-placement="body"] .frame-wrapper {
    width: 100%;
    height: 100%;
    display: flex;
    overflow: hidden;
}

/* Overlay frames. A body frame is a <dialog>: closed until the interactions
   runtime opens it, and described by attributes and custom properties its
   wrapper carries (OverlayMarkup), so this one static block serves every frame.
   Mirrored in the other stylesheet (page.css / the editor's protected.css). */
dialog.brks-overlay {
    margin: 0;
    padding: 0;
    border: 0;
    max-width: none;
    max-height: none;
    background: transparent;
    color: inherit;
}

dialog.brks-overlay::backdrop {
    background: var(--brks-overlay-backdrop, transparent);
}

/* A drawer and a modal are the panel itself: sized, and scrolling on their own.
   A custom overlay keeps the full-viewport box above. */
dialog.brks-overlay--drawer,
dialog.brks-overlay--modal {
    overflow: auto;
}

/* A drawer's height is set by the viewport or its size, so its content gets it
   as a definite height and resolves percentage heights against it. A modal is
   as tall as its content: it grows the wrapper instead. */
dialog.brks-overlay--drawer .frame-wrapper,
dialog.brks-overlay--modal .frame-wrapper {
    overflow: visible;
}

dialog.brks-overlay--modal .frame-wrapper {
    height: auto;
    min-height: 100%;
}

dialog.brks-overlay--drawer {
    width: var(--brks-overlay-size, auto);
    max-width: 100%;
}

dialog.brks-overlay--drawer[data-overlay-side="start"] {
    inset-inline-end: auto;
    --brks-overlay-from: -100% 0;
}

dialog.brks-overlay--drawer[data-overlay-side="end"] {
    inset-inline-start: auto;
    --brks-overlay-from: 100% 0;
}

dialog.brks-overlay--drawer[data-overlay-side="start"]:dir(rtl) {
    --brks-overlay-from: 100% 0;
}

dialog.brks-overlay--drawer[data-overlay-side="end"]:dir(rtl) {
    --brks-overlay-from: -100% 0;
}

dialog.brks-overlay--drawer[data-overlay-side="top"],
dialog.brks-overlay--drawer[data-overlay-side="bottom"] {
    width: 100%;
    height: var(--brks-overlay-size, auto);
    max-height: 100%;
}

dialog.brks-overlay--drawer[data-overlay-side="top"] {
    inset-block-end: auto;
    --brks-overlay-from: 0 -100%;
}

dialog.brks-overlay--drawer[data-overlay-side="bottom"] {
    inset-block-start: auto;
    --brks-overlay-from: 0 100%;
}

dialog.brks-overlay--modal {
    margin: auto;
    width: var(--brks-overlay-size, fit-content);
    max-width: calc(100% - 2rem);
    height: fit-content;
    max-height: calc(100% - 2rem);
}

/* Transitions are CSS alone: @starting-style for the entry, and a discrete
   transition of `display` and `overlay` so the exit plays before the dialog
   leaves. Where those are not supported it opens and closes without animating. */
dialog.brks-overlay[data-overlay-transition],
dialog.brks-overlay[data-overlay-transition]::backdrop {
    transition:
        opacity var(--brks-overlay-duration, 200ms) ease,
        translate var(--brks-overlay-duration, 200ms) ease,
        overlay var(--brks-overlay-duration, 200ms) allow-discrete,
        display var(--brks-overlay-duration, 200ms) allow-discrete;
}

dialog.brks-overlay[data-overlay-transition]::backdrop,
dialog.brks-overlay[data-overlay-transition="fade"],
dialog.brks-overlay[data-overlay-transition="slide"]:not([data-overlay-side]) {
    opacity: 0;
}

dialog.brks-overlay[data-overlay-transition="slide"] {
    translate: var(--brks-overlay-from, 0 1rem);
}

dialog.brks-overlay[data-overlay-transition][open],
dialog.brks-overlay[data-overlay-transition][open]::backdrop {
    opacity: 1;
    translate: 0 0;
}

@starting-style {
    dialog.brks-overlay[data-overlay-transition][open]::backdrop,
    dialog.brks-overlay[data-overlay-transition="fade"][open],
    dialog.brks-overlay[data-overlay-transition="slide"][open]:not([data-overlay-side]) {
        opacity: 0;
    }

    dialog.brks-overlay[data-overlay-transition="slide"][open] {
        translate: var(--brks-overlay-from, 0 1rem);
    }
}

@media (prefers-reduced-motion: reduce) {
    dialog.brks-overlay[data-overlay-transition],
    dialog.brks-overlay[data-overlay-transition]::backdrop {
        transition: none;
    }
}

/* The page behind a modal overlay does not scroll. The runtime pads it by the
   width of the scrollbar it loses, so the layout does not shift. */
html.brks-scroll-locked {
    overflow: hidden;
}

.hide {
    display: none;
}

img {
    max-width: 100%;
}

/* Image default: fill the container width and keep the real aspect ratio, so a
   published image is responsive (object-fit:cover crops cleanly once a fixed
   height/ratio is set for a banner). Plain images keep the CSS initial
   object-fit (fill). */
.brks-image {
    display: block;
    width: 100%;
    height: auto;
    max-height: 100%;
    object-fit: cover;
}

/* Video default: fill the container width with a stable 16:9 box so both the
   HTML5 <video> and the provider <iframe> render sensibly out of the box. */
.brks-video {
    display: block;
    width: 100%;
    height: auto;
    max-height: 100%;
    aspect-ratio: 16 / 9;
    object-fit: cover;
}

/* CMS module box: fill the container, since a module's own markup (a form) is
   sized by its parent and a flex parent would shrink the box to its content.
   `max-width` caps a width set in the Style Manager to the container. */
.brks-cms-module {
    width: 100%;
    max-width: 100%;
}

/* ===== Accordion ============================================================
   The page renders each header as a button inside a heading and each panel
   inside a region (Components/Accordion/*.php); the canvas draws the header and
   the panel as plain boxes, straight under the item. Both are written for here:
   the heading and the region carry no look of their own, so the boxes an author
   styles are the same ones in both places. An item shows its panel while it
   carries `brks-accordion__item--open` — set by the page and its runtime
   (Runtime/Accordion), and by the canvas as a DOM-only state. */
.brks-accordion {
    width: 100%;
    max-width: 100%;
    /* How far a box's content stands from its border. Set on every accordion, so
       one inside a boxed panel starts from its own style. */
    --brks-accordion-inset: 0px;
}

/* The look of the items. The border follows the theme's `--border-color`,
   `--border-width` and `--border-radius`, shared by every component that draws
   one; an accordion sets its own through a value class (Components/Accordion/
   accordionDesign.ts) on `--accordion-border-color`, `--accordion-border-width`
   and `--accordion-radius`, as it does `--accordion-gap`, `--accordion-duration`
   (read by the runtime) and `--accordion-caret-size`.

   Each of those starts unset on every accordion, so one inside a panel never
   inherits what the accordion around it sets. `:where()` keeps the reset below
   the value classes whichever stylesheet comes last. */
:where(.brks-accordion) {
    --accordion-border-color: initial;
    --accordion-border-width: initial;
    --accordion-radius: initial;
    --accordion-gap: initial;
    --accordion-duration: initial;
    --accordion-caret-size: initial;
}

.brks-accordion__item {
    border-bottom: var(--accordion-border-width, var(--border-width, 1px)) solid
        var(--accordion-border-color, var(--border-color, color-mix(in srgb, currentColor 20%, transparent)));
}

/* Child selectors: an accordion inside a panel keeps its own item style. */
.brks-accordion--plain > .brks-accordion__item {
    border-bottom: 0;
}

.brks-accordion--boxed {
    display: flex;
    flex-direction: column;
    gap: var(--accordion-gap, 0.5rem);
    --brks-accordion-inset: 1rem;
}

.brks-accordion--boxed > .brks-accordion__item {
    border: var(--accordion-border-width, var(--border-width, 1px)) solid
        var(--accordion-border-color, var(--border-color, color-mix(in srgb, currentColor 20%, transparent)));
    border-radius: var(--accordion-radius, var(--border-radius, 0.25rem));
}

.brks-accordion__heading {
    margin: 0;
    font: inherit;
}

.brks-accordion__header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    box-sizing: border-box;
    width: 100%;
    padding: 1rem var(--brks-accordion-inset);
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    font-weight: 600;
    text-align: start;
    cursor: pointer;
}

.brks-accordion__caret {
    --caret-size: var(--accordion-caret-size, 1em);
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.brks-accordion__caret.brks-caret--none {
    display: none;
}

/* The caret stays last in the markup; a child chain, so an accordion inside a
   panel keeps its own position. */
.brks-accordion--caret-start > .brks-accordion__item > .brks-accordion__header,
.brks-accordion--caret-start
    > .brks-accordion__item
    > .brks-accordion__heading
    > .brks-accordion__header {
    justify-content: flex-start;
}

.brks-accordion--caret-start > .brks-accordion__item > .brks-accordion__header > .brks-accordion__caret,
.brks-accordion--caret-start
    > .brks-accordion__item
    > .brks-accordion__heading
    > .brks-accordion__header
    > .brks-accordion__caret {
    order: -1;
}

.brks-accordion__panel {
    padding: 0 var(--brks-accordion-inset) 1rem;
}

.brks-accordion__item:not(.brks-accordion__item--open)
    > :is(.brks-accordion__region, .brks-accordion__panel) {
    display: none;
}

/* While the runtime slides a region, it stays displayed and clipped whichever
   state its item is already in. */
.brks-accordion__item > .brks-accordion__region.brks-accordion__region--animating {
    display: block;
    overflow: hidden;
}

/* Without scripting nothing can open a panel, so every panel shows. */
@media (scripting: none) {
    .brks-accordion__item:not(.brks-accordion__item--open) > .brks-accordion__region {
        display: block;
    }
}

/* ===== Tabs =================================================================
   The page renders a list of tabs, each holding its title, then each item with
   an empty toggle and its panel (Components/Tabs/*.php); as an accordion, the
   runtime (Runtime/Tabs) moves each title into its toggle and adds
   `brks-tabs--accordion`. The canvas draws the same structure (Components/Tabs/
   Tabs.ts), its list and toggles being elements of its own, so this section is
   the same in protected.css and page.css. The canvas puts its list last, and
   `order` puts it first. The title and the panel are the boxes an author
   styles; a tab in the list carries only the look the tabs' design settings
   give it (Components/Tabs/tabsDesign.ts): its colours by state, its corners.
   The active tab carries `brks-tabs__item--active`, and its tab in the list
   `brks-tabs__tab--active`.

   The line follows the theme's `--border-color` and `--border-width`, shared by
   every component that draws one, and the corners its `--border-radius`; tabs
   set their own through a value class on `--tabs-border-color`,
   `--tabs-border-width` and `--tabs-radius`, as they do `--tabs-gap`, their
   colours by state and `--tabs-duration` (read by the runtime). */
.brks-tabs {
    display: flex;
    flex-direction: column;
    width: 100%;
    max-width: 100%;
    --brks-tabs-line-width: var(--tabs-border-width, var(--border-width, 1px));
    --brks-tabs-line-color: var(
        --tabs-border-color,
        var(--border-color, color-mix(in srgb, currentColor 20%, transparent))
    );
    --brks-tabs-line: var(--brks-tabs-line-width) solid var(--brks-tabs-line-color);
    --brks-tabs-radius: var(--tabs-radius, var(--border-radius, 0.25rem));
}

/* Each of those starts unset on every tabs component, so tabs inside a panel
   never inherit what the tabs around them set. `:where()` keeps the reset below
   the value classes whichever stylesheet comes last. */
:where(.brks-tabs) {
    --tabs-border-color: initial;
    --tabs-border-width: initial;
    --tabs-radius: initial;
    --tabs-gap: initial;
    --tabs-bg: initial;
    --tabs-color: initial;
    --tabs-hover-color: initial;
    --tabs-hover-bg: initial;
    --tabs-active-color: initial;
    --tabs-active-bg: initial;
    --tabs-indicator-color: initial;
    --tabs-duration: initial;
}

.brks-tabs > .brks-tabs__list {
    order: -1;
}

.brks-tabs__tab,
.brks-tabs__toggle {
    display: block;
    margin: 0;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    font: inherit;
    text-align: start;
    cursor: pointer;
}

.brks-tabs__title {
    display: block;
    padding: 0.75rem 1rem;
}

.brks-tabs__panel {
    padding: 1rem 0;
}

/* Only the active tab shows its panel, as tabs and as an accordion. Child
   chains, so tabs inside a panel keep their own state. */
.brks-tabs > .brks-tabs__item:not(.brks-tabs__item--active) > .brks-tabs__panel {
    display: none;
}

/* While the runtime slides a panel open or closed, as an accordion, it stays
   displayed and clipped whichever state its tab is already in. */
.brks-tabs > .brks-tabs__item > .brks-tabs__panel.brks-tabs__panel--animating {
    display: block;
    box-sizing: border-box;
    overflow: hidden;
}

/* --- As tabs ---------------------------------------------------------------- */

.brks-tabs:not(.brks-tabs--accordion) > .brks-tabs__item > .brks-tabs__toggle {
    display: none;
}

.brks-tabs__list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--tabs-gap, 0);
    border-bottom: var(--brks-tabs-line);
}

/* A title wider than the tabs shrinks and wraps its words rather than overflow. */
.brks-tabs__list > .brks-tabs__tab {
    flex: 0 1 auto;
    min-width: 0;
    overflow-wrap: anywhere;
}

/* Scroll: the titles stay on one line, and the list scrolls. */
.brks-tabs--scroll > .brks-tabs__list {
    flex-wrap: nowrap;
    overflow-x: auto;
    scrollbar-width: thin;
}

.brks-tabs--scroll > .brks-tabs__list > .brks-tabs__tab {
    flex: none;
    white-space: nowrap;
}

/* The colours of a title by state. Set on the tab, so a colour an author gives
   the title itself wins. Hover and active fall back to the rest colours, and a
   title not shown is a shade lighter until the author picks its colour. The
   active title takes no hover: a click on it changes nothing. */
.brks-tabs:not(.brks-tabs--accordion) > .brks-tabs__list > .brks-tabs__tab {
    color: var(--tabs-color, color-mix(in srgb, currentColor 75%, transparent));
    background-color: var(--tabs-bg, transparent);
}

.brks-tabs:not(.brks-tabs--accordion)
    > .brks-tabs__list
    > .brks-tabs__tab:not(.brks-tabs__tab--active):hover {
    color: var(--tabs-hover-color, var(--tabs-color, currentColor));
    background-color: var(--tabs-hover-bg, var(--tabs-bg, transparent));
}

.brks-tabs:not(.brks-tabs--accordion) > .brks-tabs__list > .brks-tabs__tab--active {
    color: var(--tabs-active-color, var(--tabs-color, currentColor));
    background-color: var(--tabs-active-bg, var(--tabs-bg, transparent));
    cursor: default;
}

/* Aligned along the row (horizontal tabs only, Tabs.php adds the class). */
.brks-tabs--align-center > .brks-tabs__list {
    justify-content: safe center;
}

.brks-tabs--align-end > .brks-tabs__list {
    justify-content: safe flex-end;
}

.brks-tabs--align-stretch > .brks-tabs__list > .brks-tabs__tab {
    flex: 1 1 0;
    text-align: center;
}

.brks-tabs--align-stretch.brks-tabs--scroll > .brks-tabs__list > .brks-tabs__tab {
    flex: 1 0 auto;
}

/* Underline, the declared style: a line under the active title. */
.brks-tabs:not(.brks-tabs--accordion, .brks-tabs--boxed, .brks-tabs--pills)
    > .brks-tabs__list
    > .brks-tabs__tab
    > .brks-tabs__title {
    border-bottom: 2px solid transparent;
}

.brks-tabs:not(.brks-tabs--accordion, .brks-tabs--boxed, .brks-tabs--pills)
    > .brks-tabs__list
    > .brks-tabs__tab--active
    > .brks-tabs__title {
    border-bottom-color: var(--tabs-indicator-color, currentColor);
}

/* Boxed: the active title in a tab joined to its panel. The list's line is a
   shadow, below the tabs, so the active one's background hides it without
   reaching past a list that scrolls. */
.brks-tabs--boxed:not(.brks-tabs--accordion) > .brks-tabs__list {
    border-bottom: 0;
    box-shadow: inset 0 calc(-1 * var(--brks-tabs-line-width)) 0 var(--brks-tabs-line-color);
}

.brks-tabs--boxed:not(.brks-tabs--accordion) > .brks-tabs__list > .brks-tabs__tab {
    border: var(--brks-tabs-line-width) solid transparent;
    border-bottom: 0;
    border-radius: var(--brks-tabs-radius) var(--brks-tabs-radius) 0 0;
}

.brks-tabs--boxed:not(.brks-tabs--accordion) > .brks-tabs__list > .brks-tabs__tab--active {
    border-color: var(--brks-tabs-line-color);
    background-color: var(--tabs-active-bg, var(--bg-color, #fff));
}

/* Pills: the active title filled, and no line. */
.brks-tabs--pills:not(.brks-tabs--accordion) > .brks-tabs__list {
    gap: var(--tabs-gap, 0.25rem);
    border: 0;
}

.brks-tabs--pills:not(.brks-tabs--accordion) > .brks-tabs__list > .brks-tabs__tab {
    border-radius: var(--brks-tabs-radius);
}

.brks-tabs--pills:not(.brks-tabs--accordion)
    > .brks-tabs__list
    > .brks-tabs__tab:not(.brks-tabs__tab--active):hover {
    background-color: var(
        --tabs-hover-bg,
        var(--tabs-bg, color-mix(in srgb, currentColor 5%, transparent))
    );
}

.brks-tabs--pills:not(.brks-tabs--accordion) > .brks-tabs__list > .brks-tabs__tab--active {
    background-color: var(--tabs-active-bg, color-mix(in srgb, currentColor 10%, transparent));
}

/* Vertical: the list beside the active panel, its line on the side. */
.brks-tabs--vertical:not(.brks-tabs--accordion) {
    flex-direction: row;
    align-items: flex-start;
}

/* The list takes at most half the width: a title that does not fit scrolls
   or wraps inside it, whichever the author picked. */
.brks-tabs--vertical:not(.brks-tabs--accordion) > .brks-tabs__list {
    flex: 0 1 auto;
    flex-direction: column;
    flex-wrap: nowrap;
    min-width: 0;
    max-width: 50%;
    border-bottom: 0;
    border-inline-end: var(--brks-tabs-line);
    overflow-x: auto;
}

.brks-tabs--vertical:not(.brks-tabs--accordion) > .brks-tabs__item--active {
    flex: 1;
    min-width: 0;
}

.brks-tabs--vertical:not(.brks-tabs--accordion) > .brks-tabs__item > .brks-tabs__panel {
    padding: 0 1rem;
}

.brks-tabs--vertical:not(.brks-tabs--accordion, .brks-tabs--boxed, .brks-tabs--pills)
    > .brks-tabs__list
    > .brks-tabs__tab
    > .brks-tabs__title {
    border-bottom: 0;
    border-inline-end: 2px solid transparent;
}

.brks-tabs--vertical:not(.brks-tabs--accordion, .brks-tabs--boxed, .brks-tabs--pills)
    > .brks-tabs__list
    > .brks-tabs__tab--active
    > .brks-tabs__title {
    border-inline-end-color: var(--tabs-indicator-color, currentColor);
}

.brks-tabs--vertical.brks-tabs--boxed:not(.brks-tabs--accordion) > .brks-tabs__list {
    border-inline-end: 0;
    box-shadow: inset calc(-1 * var(--brks-tabs-line-width)) 0 0 var(--brks-tabs-line-color);
}

.brks-tabs--vertical.brks-tabs--boxed:not(.brks-tabs--accordion):dir(rtl) > .brks-tabs__list {
    box-shadow: inset var(--brks-tabs-line-width) 0 0 var(--brks-tabs-line-color);
}

.brks-tabs--vertical.brks-tabs--boxed:not(.brks-tabs--accordion)
    > .brks-tabs__list
    > .brks-tabs__tab {
    border: var(--brks-tabs-line-width) solid transparent;
    border-inline-end: 0;
    border-radius: var(--brks-tabs-radius) 0 0 var(--brks-tabs-radius);
}

.brks-tabs--vertical.brks-tabs--boxed:not(.brks-tabs--accordion)
    > .brks-tabs__list
    > .brks-tabs__tab--active {
    border-color: var(--brks-tabs-line-color);
}

.brks-tabs--vertical.brks-tabs--boxed:not(.brks-tabs--accordion):dir(rtl)
    > .brks-tabs__list
    > .brks-tabs__tab {
    border-radius: 0 var(--brks-tabs-radius) var(--brks-tabs-radius) 0;
}

.brks-tabs--vertical.brks-tabs--pills:not(.brks-tabs--accordion) > .brks-tabs__list {
    border-inline-end: 0;
}

/* Measuring whether the titles fit, on one line and at their full width
   (Runtime/Tabs/layout.ts). After the rules above, which it overrides. */
.brks-tabs.brks-tabs--measuring:not(.brks-tabs--accordion) > .brks-tabs__list {
    flex-wrap: nowrap;
    max-width: none;
    overflow-x: hidden;
}

.brks-tabs.brks-tabs--measuring:not(.brks-tabs--accordion) > .brks-tabs__list > .brks-tabs__tab {
    flex: none;
    white-space: nowrap;
}

/* --- As an accordion -------------------------------------------------------- */

.brks-tabs--accordion > .brks-tabs__list {
    display: none;
}

.brks-tabs--accordion > .brks-tabs__item {
    border-bottom: var(--brks-tabs-line);
}

.brks-tabs--accordion > .brks-tabs__item > .brks-tabs__toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    width: 100%;
    font-weight: 600;
}

/* Lined up with the panel, as an accordion's header is. */
.brks-tabs--accordion > .brks-tabs__item > .brks-tabs__toggle > .brks-tabs__title {
    padding-inline: 0;
}

/* The chevron: down while closed, up while open. */
.brks-tabs--accordion > .brks-tabs__item > .brks-tabs__toggle::after {
    content: '';
    flex: none;
    width: 0.45em;
    height: 0.45em;
    margin-inline-end: 1rem;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: translateY(-25%) rotate(45deg);
    transition: transform 0.2s ease;
}

.brks-tabs--accordion > .brks-tabs__item--active > .brks-tabs__toggle::after {
    transform: translateY(25%) rotate(-135deg);
}

@media (prefers-reduced-motion: reduce) {
    .brks-tabs--accordion > .brks-tabs__item > .brks-tabs__toggle::after {
        transition: none;
    }
}

/* Without scripting nothing can switch a tab: every panel shows, under the
   list of titles. */
@media (scripting: none) {
    .brks-tabs > .brks-tabs__item > .brks-tabs__panel {
        display: block;
    }
}

/* ===== Carousel =============================================================
   The page renders the slides in a track inside a viewport, then the controls
   (Components/Carousel/*.php); the runtime (Runtime/Carousel) moves the track,
   fills the dots and adds `brks-carousel--playing` while the carousel rotates.
   The canvas draws the same structure (Components/Carousel/Carousel.ts), its
   controls being elements of its own, so this section is the same in
   protected.css and page.css.

   A rule the page adds per carousel sets `--brks-carousel-per-view` and
   `--brks-carousel-gap` at each breakpoint (`data-brks-carousel-layout`), and a
   slide takes its share of the track: laid out before any script runs. The
   slide is the box an author styles, so the gap is the track's, never the
   slide's padding. The controls sit over the viewport, the dots below it.

   The controls' design (Components/Carousel/carouselDesign.ts) is a class per
   choice, and a custom property per value, each falling back to the look below.
   A control hidden from a width down is hidden by a rule the page adds. */
.brks-carousel {
    position: relative;
    display: grid;
    width: 100%;
    max-width: 100%;
}

/* Each starts unset on every carousel, so a carousel inside a slide never
   inherits the layout or the design of the one around it. `:where()` keeps the
   reset below the rules that set them. */
:where(.brks-carousel) {
    --brks-carousel-per-view: initial;
    --brks-carousel-gap: initial;
    --carousel-arrow-size: initial;
    --carousel-arrow-radius: initial;
    --carousel-arrow-bg: initial;
    --carousel-arrow-color: initial;
    --carousel-arrow-hover-bg: initial;
    --carousel-arrow-hover-color: initial;
    --carousel-dot-size: initial;
    --carousel-dot-gap: initial;
    --carousel-dot-color: initial;
    --carousel-dot-active-color: initial;
}

.brks-carousel > .brks-carousel__viewport {
    grid-area: 1 / 1;
    overflow: hidden;
}

.brks-carousel > .brks-carousel__viewport > .brks-carousel__track {
    display: flex;
    gap: var(--brks-carousel-gap, 16px);
    touch-action: pan-y pinch-zoom;
}

.brks-carousel > .brks-carousel__viewport > .brks-carousel__track > .brks-carousel__slide {
    flex: 0 0
        calc(
            (100% - (var(--brks-carousel-per-view, 1) - 1) * var(--brks-carousel-gap, 16px)) /
                var(--brks-carousel-per-view, 1)
        );
    min-width: 0;
    box-sizing: border-box;
}

/* A gap only separates two slides: a looping track also needs one after the
   last, before the first comes round again. A fading one shows a slide at a time. */
.brks-carousel[data-brks-carousel='slide'][data-brks-carousel-loop]
    > .brks-carousel__viewport
    > .brks-carousel__track
    > .brks-carousel__slide:last-child {
    margin-inline-end: var(--brks-carousel-gap, 16px);
}

.brks-carousel[data-brks-carousel='fade'] > .brks-carousel__viewport > .brks-carousel__track {
    gap: 0;
}

/* The pause button looks like the arrows: the controls read as one set. */
.brks-carousel > .brks-carousel__prev,
.brks-carousel > .brks-carousel__next,
.brks-carousel > .brks-carousel__play {
    grid-area: 1 / 1;
    z-index: 1;
    display: grid;
    place-items: center;
    width: var(--carousel-arrow-size, 2.5rem);
    height: var(--carousel-arrow-size, 2.5rem);
    margin: 0.5rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--carousel-arrow-bg, rgb(255 255 255 / 0.85));
    box-shadow: 0 1px 3px rgb(0 0 0 / 0.25);
    color: var(--carousel-arrow-color, rgb(17 17 17));
    cursor: pointer;
}

.brks-carousel
    > :is(.brks-carousel__prev, .brks-carousel__next, .brks-carousel__play):hover:not(
        [aria-disabled='true']
    ) {
    background: var(--carousel-arrow-hover-bg, var(--carousel-arrow-bg, rgb(255 255 255 / 0.85)));
    color: var(--carousel-arrow-hover-color, var(--carousel-arrow-color, rgb(17 17 17)));
}

.brks-carousel.brks-carousel--arrows-square
    > :is(.brks-carousel__prev, .brks-carousel__next, .brks-carousel__play) {
    border-radius: var(--carousel-arrow-radius, 0.25rem);
}

/* An icon alone has no background, hovered or not. */
.brks-carousel.brks-carousel--arrows-plain
    > :is(.brks-carousel__prev, .brks-carousel__next, .brks-carousel__play),
.brks-carousel.brks-carousel--arrows-plain
    > :is(.brks-carousel__prev, .brks-carousel__next, .brks-carousel__play):hover {
    background: none;
    box-shadow: none;
}

.brks-carousel > .brks-carousel__prev {
    align-self: center;
    justify-self: start;
}

.brks-carousel > .brks-carousel__next {
    align-self: center;
    justify-self: end;
}

.brks-carousel > .brks-carousel__play {
    align-self: start;
    justify-self: end;
}

/* Beside the slides: a column each side of the viewport, which a hidden arrow
   leaves empty. */
.brks-carousel.brks-carousel--arrows-outside {
    grid-template-columns: auto minmax(0, 1fr) auto;
}

.brks-carousel.brks-carousel--arrows-outside > .brks-carousel__viewport,
.brks-carousel.brks-carousel--arrows-outside > .brks-carousel__play,
.brks-carousel.brks-carousel--arrows-outside > .brks-carousel__dots {
    grid-column: 2;
}

.brks-carousel.brks-carousel--arrows-outside > .brks-carousel__prev {
    grid-column: 1;
}

.brks-carousel.brks-carousel--arrows-outside > .brks-carousel__next {
    grid-column: 3;
}

/* Hidden while the slides fit a single view: there is nowhere to go, and nothing
   to rotate. */
.brks-carousel > .brks-carousel__play[hidden],
.brks-carousel > .brks-carousel__prev[hidden],
.brks-carousel > .brks-carousel__next[hidden],
.brks-carousel > .brks-carousel__dots[hidden] {
    display: none;
}

.brks-carousel > .brks-carousel__prev[aria-disabled='true'],
.brks-carousel > .brks-carousel__next[aria-disabled='true'] {
    opacity: 0.35;
    cursor: default;
}

/* The arrow drawn in the button's colour, half its size: the next one's glyph,
   mirrored for the previous one. A preset is an inline SVG, a custom icon a
   glyph of an icon font. */
.brks-carousel > :is(.brks-carousel__prev, .brks-carousel__next) > .brks-carousel__arrow {
    font-size: calc(var(--carousel-arrow-size, 2.5rem) / 2);
    line-height: 1;
}

.brks-carousel > :is(.brks-carousel__prev, .brks-carousel__next) > svg.brks-carousel__arrow {
    width: 1em;
    height: 1em;
}

.brks-carousel > .brks-carousel__prev > .brks-carousel__arrow {
    transform: scaleX(-1);
}

/* The play and pause signs, drawn in the button's colour. */
.brks-carousel > .brks-carousel__play::before {
    content: '';
    margin-inline-start: 0.15rem;
    border-style: solid;
    border-width: 0.4rem 0 0.4rem 0.65rem;
    border-color: transparent transparent transparent currentColor;
}

.brks-carousel.brks-carousel--playing > .brks-carousel__play::before {
    width: 0.6rem;
    height: 0.75rem;
    margin: 0;
    box-sizing: border-box;
    border-width: 0 0.2rem;
    border-color: currentColor;
}

.brks-carousel > .brks-carousel__dots {
    grid-area: 2 / 1;
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: var(--carousel-dot-gap, 0.25rem);
    padding-block: 0.5rem;
}

.brks-carousel.brks-carousel--dots-start > .brks-carousel__dots {
    justify-content: flex-start;
}

.brks-carousel.brks-carousel--dots-end > .brks-carousel__dots {
    justify-content: flex-end;
}

/* Over the slides: at the bottom of the viewport, above what it shows. */
.brks-carousel.brks-carousel--dots-over > .brks-carousel__dots {
    grid-row: 1;
    align-self: end;
    z-index: 1;
    padding-inline: 0.5rem;
}

/* A dot is a 24px target at least, its mark smaller. */
.brks-carousel__dot {
    display: grid;
    place-items: center;
    min-width: 1.5rem;
    min-height: 1.5rem;
    padding: 0;
    border: 0;
    background: none;
    color: inherit;
    cursor: pointer;
}

.brks-carousel__dot::before {
    content: '';
    width: var(--carousel-dot-size, 0.625rem);
    height: var(--carousel-dot-size, 0.625rem);
    border-radius: 50%;
    background: var(--carousel-dot-color, color-mix(in srgb, currentColor 30%, transparent));
}

.brks-carousel__dot.brks-carousel__dot--active::before {
    background: var(--carousel-dot-active-color, currentColor);
}

/* Lines: a bar each, the active one twice as long. */
.brks-carousel.brks-carousel--dots-lines > .brks-carousel__dots > .brks-carousel__dot::before {
    width: calc(var(--carousel-dot-size, 0.625rem) * 2.4);
    height: calc(var(--carousel-dot-size, 0.625rem) * 0.4);
    border-radius: 999px;
}

.brks-carousel.brks-carousel--dots-lines
    > .brks-carousel__dots
    > .brks-carousel__dot.brks-carousel__dot--active::before {
    width: calc(var(--carousel-dot-size, 0.625rem) * 4.8);
}

@media (prefers-reduced-motion: no-preference) {
    .brks-carousel.brks-carousel--dots-lines > .brks-carousel__dots > .brks-carousel__dot::before {
        transition: width 0.2s ease;
    }
}

/* Read by a screen reader, never seen. */
.brks-carousel > .brks-carousel__live {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
}

/* Without scripts the track scrolls under the finger, and the controls, which
   would do nothing, are not shown. */
@media (scripting: none) {
    .brks-carousel > .brks-carousel__viewport {
        overflow-x: auto;
        scroll-snap-type: x mandatory;
    }

    .brks-carousel > .brks-carousel__viewport > .brks-carousel__track > .brks-carousel__slide {
        scroll-snap-align: start;
    }

    .brks-carousel > .brks-carousel__prev,
    .brks-carousel > .brks-carousel__next,
    .brks-carousel > .brks-carousel__play,
    .brks-carousel > .brks-carousel__dots {
        display: none;
    }
}

main {
    flex: 1;
    height: auto;
    display: flex;
    flex-direction: column;
    align-items: center;
}

section {
    position: relative;
    width: 100%;
    max-width: 100%;
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: var(--section-padding);
}

header {
    display: flex;
    flex-direction: column;
    align-items: center;
}

footer {
    display: flex;
    flex-direction: column;
    align-items: center;
    margin-top: auto;
}

.brks-menu {
    list-style: none;
    width: 100%;
    max-width: 100%;
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    /* Derived (active/hover colors). The defaults live in the consuming rules'
       var() fallbacks below, NOT as --menu-* declarations here — so a brks-menu-*
       value-signature class is the sole setter of each property (no equal-
       specificity battle). See docs/specs/derived-style-isolation.md (§6). */
}

/* Items share the height of the tallest one: once a label wraps, a centred row
   gave each item its own height, so hover backgrounds covered different boxes
   and each floating panel (`top: 100%` of its <li>) opened at a different line.
   The label stays centred inside, since the <a> fills the item and centres itself. */
.brks-menu.menu-horizontal {
    flex-direction: row;
    justify-content: space-evenly;
    align-items: stretch;
}

/* A menu never overflows its container: on a crowded bar an item shrinks and
   its label wraps. `min-width: 0` lifts the flex floor of "never narrower than my
   content" — a dropdown/zone <li> is `overflow: visible` (its panel escapes it),
   so without it that floor held and the label painted over the next item, while
   a plain item (`overflow: hidden`) was crushed instead. `max-width` caps a width
   set in the Style Manager to the bar. */
.brks-menu__item,
.brks-menu__title {
    width: 100%;
    min-width: 0;
    max-width: 100%;
    display: flex;
    align-items: center;
    border-radius: var(--menu-item-radius, 0.25rem);
    overflow: hidden;
    transition: all 300ms ease;
}

/* Only the bar's OWN items centre: a descendant combinator reached every item
   below the bar, down into a menu nested in a zone, and its `align-items` beat
   the inline-panel stretch there — an open dropdown shrank to its content and
   centred under a wide trigger. */
.brks-menu.menu-horizontal > .brks-menu__item,
.brks-menu.menu-horizontal > .brks-menu__title {
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
}

/* On a bar, an item is as wide as its label and the root's `justify-content`
   spaces them — the common navbar; items sharing the whole bar is an opt-in fill
   mode elsewhere. Sharing it by default made every item claim all of it, so a
   width set on one was shrunk away by its unsized neighbours. Only the bar's own
   items (a panel's still fill it), and `:where` keeps this at the base item's
   weight so a width from the Style Manager or a preset class still wins. */
:where(.brks-menu.menu-horizontal) > .brks-menu__item,
:where(.brks-menu.menu-horizontal) > .brks-menu__title {
    width: auto;
    flex: 0 1 auto;
}

/* Bar distribution (`brks-menu--justify-{mode}`, one per menu root, stamped by
   the editor and MenuSettings.php): where the bar's own items sit along it.
   `evenly` restates the default above. Keyed on the root element itself, so a
   menu nested in a zone keeps its own; a justify-content set in the Style
   Manager still wins (an id rule). */
.brks-menu--justify-start.menu-horizontal {
    justify-content: flex-start;
}

.brks-menu--justify-center.menu-horizontal {
    justify-content: center;
}

.brks-menu--justify-end.menu-horizontal {
    justify-content: flex-end;
}

.brks-menu--justify-between.menu-horizontal {
    justify-content: space-between;
}

.brks-menu--justify-evenly.menu-horizontal {
    justify-content: space-evenly;
}

/* Fill: the items share the whole bar in equal boxes. A zero basis is what
   makes them equal whatever their labels, so a width set on one item is not
   honoured in this mode; `min-width: 0` still lets a long label wrap. */
:where(.brks-menu--justify-fill.menu-horizontal) > .brks-menu__item,
:where(.brks-menu--justify-fill.menu-horizontal) > .brks-menu__title {
    flex: 1 1 0;
}

.brks-menu__title,
.brks-menu__item > a {
    padding: var(--menu-item-padding-y, 0.25rem) var(--menu-item-padding-x, 0.5rem);
}

/* The bar's own items only, like its centring: a panel's items — a dropdown's,
   or a menu nested in a zone — keep the base padding. */
.brks-menu.menu-horizontal > .brks-menu__title,
.brks-menu.menu-horizontal > .brks-menu__item > a {
    padding: var(--menu-item-padding-y, 0.35rem) var(--menu-item-padding-x, 0.5rem);
}

.brks-menu__title {
  overflow-wrap: anywhere;
  font-family: var(--subtitle-font-family, Helvetica, sans-serif);
  line-height: var(--subtitle-line-height, inherit);
  font-size: calc(var(--subtitle-font-size, 2rem) * 0.5);
  font-weight: bold;
}

/* `anywhere`, not `break-word`: only it lowers the min-content width, so a
   single word longer than its item breaks instead of holding the item open. */
.brks-menu__item > a {
    overflow-wrap: anywhere;
    display: flex;
    align-items: center;
    width: 100%;
    height: 100%;
    color: inherit;
    text-decoration: none;
}

.brks-menu.menu-horizontal .brks-menu__item > a {
    justify-content: center;
}

/* Rest-state item appearance (shared channels, inherited by every item —
   top-level AND inside dropdowns, since both are .brks-menu__item — via the
   --menu-item-* custom props on the root). Lower specificity than the :hover /
   .active rules below, so those still win. Defaults equal the previous hardcoded
   look: transparent bg, no border, and text inheriting the
   surrounding context (a menu in a dark section picks up its colour). */
.brks-menu__item {
    color: var(--menu-item-color, inherit);
    background-color: var(--menu-item-bg, transparent);
    border: var(--menu-item-border-width, 0) var(--menu-item-border-style, solid) var(--menu-item-border-color, transparent);
}

/* Titles are section headings: they take the shared item TEXT colour (so a
   custom item text applies to them too) but their BOX is their own. The item
   bg/border props are set on the menu root and inherit, so reading them here
   would turn every heading into a pill as soon as a menu picked an item
   background — hence --menu-title-*, which only a per-title override sets. The
   defaults are the box a title has always had (none), so an untouched menu is
   unchanged; a styled one can render its headings as badges. In a panel the
   panel-text rule below overrides the colour (it also lists .brks-menu__title). */
.brks-menu__title {
    color: var(--menu-item-color, inherit);
    background-color: var(--menu-title-bg, transparent);
    border: var(--menu-title-border-width, 0) var(--menu-title-border-style, solid) var(--menu-title-border-color, transparent);
}

.brks-menu__item:hover {
    color: var(--menu-hover-color, inherit);
    background-color: var(--menu-hover-bg, #ededed);
    border-color: var(--menu-hover-border-color, var(--menu-item-border-color, transparent));
    transition: all 300ms ease;
}

.brks-menu__item.active {
    color: var(--menu-active-color, inherit);
    background-color: var(--menu-active-bg, #ededed);
    border-color: var(--menu-active-border-color, var(--menu-item-border-color, transparent));
    transition: all 300ms ease;
}

.brks-menu__separator {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 0.25rem;
}

/* The visible rule is drawn as a BORDER (border-top when horizontal, border-left
   when vertical), not a filled background — so the line STYLE (solid/dashed/dotted/
   double/none) renders. `color: inherit` overrides the browser's non-inheriting
   <hr> grey so `currentColor` (the separatorColor default) tracks the surrounding
   text — item text on the bar, panel text inside a panel (the separator is listed
   in the panel-text rule for that). The --menu-sep-* custom props are the
   menu-global separator channels; each falls back to the previous hardcoded look
   (1px solid), so an untouched divider is unchanged. Thickness is the border
   weight, length the span along the axis. */
.brks-menu__separator > hr {
    border: 0;
    color: inherit;
    background: none;
    opacity: var(--menu-sep-opacity, 0.2);
    margin: 0;
}

.brks-menu__separator--horizontal {
    width: 100%;
}

.brks-menu__separator--horizontal > hr {
    width: var(--menu-sep-length, 100%);
    height: 0;
    border-top: var(--menu-sep-thickness, 1px) var(--menu-sep-style, solid)
        var(--menu-sep-color, currentColor);
}

.brks-menu__separator--vertical {
    align-self: stretch;
}

.brks-menu__separator--vertical > hr {
    width: 0;
    height: var(--menu-sep-length, 100%);
    min-height: 1rem;
    border-left: var(--menu-sep-thickness, 1px) var(--menu-sep-style, solid)
        var(--menu-sep-color, currentColor);
}

/* --- Dropdown submenus (multi-level) ---------------------------------------
   A dropdown item is `.brks-menu__item--has-submenu` wrapping a
   `.brks-menu__trigger` (the clickable head) and a `.brks-menu__submenu` panel.
   The DOM is identical in every mode; display is TWO orthogonal root classes set
   1:1 from the trigger's "Open submenu on" + "Submenu panel" traits —
   `brks-menu--trigger-{auto|hover|click}` × `brks-menu--panel-{auto|floating|
   accordion|expanded}` — with each `auto` resolved HERE in CSS via the
   `menu-horizontal` class (see the two axis sections below). A single dropdown
   overrides either axis via `brks-menu__item--{trigger|panel}-{value}`.
   No <details> — collapse is driven entirely by `.brks-menu__item--open`. Kept
   in lockstep with the editor canvas stylesheet
   (packages/editor/src/assets/protected.css). */

.brks-menu__item--has-submenu {
    position: relative;
    /* The base .brks-menu__item clips with overflow:hidden; a flyout must escape it. */
    overflow: visible;
    /* The rest-state bg/border go on the TRIGGER (the clickable head), not the
       <li> — it wraps the whole submenu, so styling it would paint/outline behind
       the children (same reasoning as the .active/:hover neutralisation below). */
    background-color: transparent;
    border: 0;
    /* And since it paints nothing, it must ANIMATE nothing. The <li> still carries
       a `color`, purely as the value the trigger inherits — and the trigger's hover
       colour is `var(--menu-hover-color, inherit)`. Left transitioning, the trigger
       was easing toward a target that was itself easing: the head's label took two
       chained 300ms curves to settle while its background, aiming at a fixed value,
       arrived on time. Measured in the preview at ~600ms against ~300ms for a plain
       item. Flipping the <li> instantly hands the trigger a fixed target, so one
       curve runs and the label lands with the background. */
    transition: none;
}

.brks-menu__trigger {
    cursor: pointer;
    border-radius: var(--menu-item-radius, 0.25rem);
    color: var(--menu-item-color, inherit);
    background-color: var(--menu-item-bg, transparent);
    border: var(--menu-item-border-width, 0) var(--menu-item-border-style, solid) var(--menu-item-border-color, transparent);
    transition: all 300ms ease;
}

/* The active/hover highlight of a dropdown lands on its TRIGGER only. The <li>
   contains the whole submenu, so tinting the item (the base .active/:hover
   rules) would repaint behind the children and they'd inherit the active text
   color — wrong for an active-trail ancestor like an open "About Us". Each
   child still highlights itself through its own item rules. */
.brks-menu__item--has-submenu.active,
.brks-menu__item--has-submenu:hover {
    color: inherit;
    background-color: transparent;
    /* Re-assert the rest rule's `transition: none` — `.brks-menu__item:hover`
       re-declares `all 300ms` at this same specificity, and would otherwise put the
       chained curve back for exactly the hover the fix is about. */
    transition: none;
}

/* A dropdown head takes the item text colour DIRECTLY, not by inheriting its
   <li>. A linked head is an <a>, so `.brks-menu__item > a { color: inherit }`
   (0,1,1) outranks the trigger's own (0,1,0) rule and made the head inherit the
   <li> — which the hover neutraliser above turns into the surrounding context
   the moment the pointer is anywhere inside the item, its panel included. With
   the highlight switched off that lit the head's LABEL while its background
   stayed at rest: the two halves of one item disagreeing. At (0,2,0) this wins
   over the <a> rule and still yields to the .active/:hover head rules below, so
   the highlighted look is unchanged. */
.brks-menu__item--has-submenu > .brks-menu__trigger {
    color: var(--menu-item-color, inherit);
}

.brks-menu__item--has-submenu.active > .brks-menu__trigger {
    color: var(--menu-active-color, inherit);
    background-color: var(--menu-active-bg, #ededed);
    border-color: var(--menu-active-border-color, var(--menu-item-border-color, transparent));
}

/* Hovering ANYWHERE in the dropdown lights its head — `:hover` on the <li>, not
   on the trigger. A panel is a DOM CHILD of its <li>, so keying this on the
   trigger's own `:hover` dropped the highlight the instant the pointer moved off
   the head into the panel it had just opened, and brought it back on the way out:
   two crossfades for one gesture, which read as a slow, doubled hover. The paint
   still lands on the TRIGGER (see the neutraliser above) — only the condition
   moves up to the item. That also keeps every head of an open flyout trail lit
   while you walk down it, and it means an inline accordion/expanded panel lights
   its section head while the pointer is on one of that section's children —
   which is why WHERE the condition sits is a menu option ("Keep parent
   highlighted ?", `brks-menu--head-hover-{within|self}`, mirrored in
   MenuSettings.php::rootClasses). Three selectors share one declaration block:
   every mode paints the same values, so a head matched by two of them is
   harmless.
     1. The default, held back from any menu switched to `self`. A menu saved
        before the option carries no class at all and lands here — on the
        behaviour it already had.
     2. `self`: the condition moves back onto the trigger itself.
     3. A nested menu on `within`, re-asserting inside a `self` outer bar. A
        mega-menu zone can hold a whole menu and every menu-level rule reaches
        its items through a descendant combinator, so the outer bar's choice
        crosses in. The mirror case (a `self` menu inside a `within` bar) needs
        no rule of its own: 1's guard already excludes it, whichever menu owns
        the class.
   The guard sits in `:where()` so the default keeps its (0,3,0) weight; 2 and 3
   rank above it — and above the `.active` head rule — on their own class count,
   which is what already made hover win over active in the default mode. */
.brks-menu__item--has-submenu:where(:not(.brks-menu--head-hover-self *)):hover
    > .brks-menu__trigger,
.brks-menu--head-hover-self .brks-menu__item--has-submenu > .brks-menu__trigger:hover,
.brks-menu .brks-menu--head-hover-within .brks-menu__item--has-submenu:hover > .brks-menu__trigger {
    color: var(--menu-hover-color, inherit);
    background-color: var(--menu-hover-bg, #ededed);
    border-color: var(--menu-hover-border-color, var(--menu-item-border-color, transparent));
}

/* ===== Caret (shared) ======================================================
   The open/close affordance of a disclosure (the kit's caret.ts, mirrored in
   CaretHelper.php): `brks-caret` holds its icon — an inline SVG preset or an
   icon-font glyph — and, when it swaps, its open icon. Its host sets the custom
   properties on the caret element itself, so a nested caret never inherits
   them: `--caret-size`, `--caret-base-turn` (where it points at rest),
   `--caret-open-turn` (how far a turning caret turns once open) and, while its
   disclosure is open, `--caret-is-open: 1` with the display switches of a
   swapping caret. An `aria-expanded` owner opens it by default; a host with
   other open states adds its own arms. The two-class selectors outrank the icon
   fonts' own single-class size and display. */
.brks-caret > .brks-caret__icon,
.brks-caret > .brks-caret__open-icon {
    flex-shrink: 0;
    font-size: var(--caret-size, 1em);
    line-height: 1;
    transform: rotate(var(--caret-base-turn, 0deg));
    transition: transform 200ms ease;
}

.brks-caret > svg {
    width: 1em;
    height: 1em;
}

.brks-caret--rotate > .brks-caret__icon {
    transform: rotate(calc(var(--caret-base-turn, 0deg) + var(--caret-open-turn, 180deg) * var(--caret-is-open, 0)));
}

/* A swapping caret shows one icon per state, as drawn: it never turns. */
.brks-caret--swap > .brks-caret__icon,
.brks-caret--swap > .brks-caret__open-icon {
    transform: none;
}

.brks-caret--swap > .brks-caret__icon {
    display: var(--caret-closed-display, block);
}

.brks-caret > .brks-caret__open-icon {
    display: var(--caret-open-display, none);
}

[aria-expanded="true"] > .brks-caret {
    --caret-is-open: 1;
    --caret-closed-display: none;
    --caret-open-display: block;
}

/* Caret — a REAL element, not a pseudo-element: it is the always-toggles click
   target (a linked trigger's label navigates instead; see breeks-menu.js). It is
   a shared `brks-caret` (above), which a head's settings resolve into; modes
   further down turn or hide it. Its size and gap from the label are the menu's
   `--menu-caret-*` channels (menuStyleChannels.ts). */
.brks-menu__caret {
    --caret-size: var(--menu-caret-size, 1em);
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    margin-left: var(--menu-caret-gap, 0.25em);
    padding: 0.3em;
    cursor: pointer;
}

/* Caret position, resolved per head into one class on its <li> (set on the menu,
   overridable per dropdown or zone; mirrored in MenuSettings.php::caretPositionClass).
   The caret element never moves in the markup — it stays after the label, the
   always-toggles click target — so each position is layout only: `order` puts it
   ahead, an auto margin pushes it to the far edge, a column stacks it over or
   under the label. `after` is the base above and has no class. Child combinators
   all the way down, so a head's position never reaches a nested head's caret. */
.brks-menu__item--caret-before > .brks-menu__trigger > .brks-menu__caret {
    order: -1;
    margin-left: 0;
    margin-right: var(--menu-caret-gap, 0.25em);
}

.brks-menu__item--caret-end > .brks-menu__trigger > .brks-menu__caret {
    margin-left: auto;
}

/* A wrapped label stays centred over or under its caret. */
.brks-menu__item--caret-above > .brks-menu__trigger,
.brks-menu__item--caret-below > .brks-menu__trigger {
    flex-direction: column;
    text-align: center;
}

.brks-menu__item--caret-above > .brks-menu__trigger > .brks-menu__caret,
.brks-menu__item--caret-below > .brks-menu__trigger > .brks-menu__caret {
    margin-left: 0;
}

.brks-menu__item--caret-above > .brks-menu__trigger > .brks-menu__caret {
    order: -1;
    margin-bottom: var(--menu-caret-gap, 0.25em);
}

.brks-menu__item--caret-below > .brks-menu__trigger > .brks-menu__caret {
    margin-top: var(--menu-caret-gap, 0.25em);
}

/* A head's caret opens with its panel: each arm is one of the reveal rules below
   (keyboard, `--open`, then the hover trigger axis with its nested-menu guard and
   per-item opt-in), aimed at the caret instead of the panel. */
.brks-menu__item--has-submenu:has(:focus-visible) > .brks-menu__trigger > .brks-caret,
.brks-menu__item--open > .brks-menu__trigger > .brks-caret,
.brks-menu--trigger-hover
    .brks-menu__item--has-submenu:not(.brks-menu__item--trigger-click):where(:not(.brks-menu .brks-menu *)):hover
    > .brks-menu__trigger > .brks-caret,
.brks-menu--trigger-auto.menu-horizontal
    .brks-menu__item--has-submenu:not(.brks-menu__item--trigger-click):where(:not(.brks-menu .brks-menu *)):hover
    > .brks-menu__trigger > .brks-caret,
.brks-menu .brks-menu--trigger-hover
    .brks-menu__item--has-submenu:not(.brks-menu__item--trigger-click):hover
    > .brks-menu__trigger > .brks-caret,
.brks-menu .brks-menu--trigger-auto.menu-horizontal
    .brks-menu__item--has-submenu:not(.brks-menu__item--trigger-click):hover
    > .brks-menu__trigger > .brks-caret,
.brks-menu .brks-menu__item--trigger-hover:hover > .brks-menu__trigger > .brks-caret {
    --caret-is-open: 1;
    --caret-closed-display: none;
    --caret-open-display: block;
}

/* No caret — on a label-only head only: a linked head's label navigates, so its
   caret is the one thing that opens its panel, and it keeps the chevron. */
.brks-menu__trigger:not([href]) > .brks-caret--none {
    display: none;
}

/* Shared: hidden until open, laid out as a vertical list. */
.brks-menu__submenu {
    list-style: none;
    margin: 0;
    padding: var(--menu-panel-padding, 0.25rem);
    display: none;
    flex-direction: column;
    gap: 0.25rem;
}

/* Revealed by KEYBOARD focus or an explicit `--open` (click / touch / editor /
   active-trail) — the flyout and collapsible modes. :has(:focus-visible), not
   :focus-within: a mouse click also focuses the trigger, and with :focus-within
   the panel stayed visibly open after a toggle-close until you clicked away. */
.brks-menu__item--has-submenu:has(:focus-visible) > .brks-menu__submenu,
.brks-menu__item--open > .brks-menu__submenu {
    display: flex;
}

/* Submenu display is TWO orthogonal axes, each a root class resolved in CSS (never
   a JS swap — one stable class per axis, keyed on `menu-horizontal` for `auto`):
     • TRIGGER (`brks-menu--trigger-{hover|click|auto}`) — WHAT reveals a panel.
     • PANEL   (`brks-menu--panel-{floating|accordion|expanded|auto}`) — HOW it lays out.
   `auto` resolves by direction: hover+floating on a horizontal bar (classic
   flyout), click+accordion on a vertical one (classic collapsible). A single
   dropdown overrides either axis via `brks-menu__item--{trigger|panel}-{value}`.
   Base reveals (keyboard `:has(:focus-visible)` and JS/touch `--open`, above)
   fire in EVERY mode; the trigger axis only ADDS hover. */

/* ===== TRIGGER axis: hover reveal ==========================================
   Explicit `hover`, OR `auto` on a horizontal bar. A single item can opt OUT with
   `--trigger-click` (excluded here) or opt IN with `--trigger-hover` (added
   below), so the axis is honored per item even against the menu default.

   `:where(:not(.brks-menu .brks-menu *))` stops the reveal from crossing INTO a
   nested menu — a mega-menu zone can hold a whole menu, and this rule reaches
   its items through a descendant combinator, so a nested menu set to `click`
   still dropped its panel on hover from the outer bar. Items inside a nested
   menu are picked back up by the block below, keyed on THEIR OWN root: between
   the two, the NEAREST menu root is the one that decides. Wrapped in `:where()`
   so the guard costs no specificity. */
.brks-menu--trigger-hover
    .brks-menu__item--has-submenu:not(.brks-menu__item--trigger-click):where(:not(.brks-menu .brks-menu *)):hover
    > .brks-menu__submenu,
.brks-menu--trigger-auto.menu-horizontal
    .brks-menu__item--has-submenu:not(.brks-menu__item--trigger-click):where(:not(.brks-menu .brks-menu *)):hover
    > .brks-menu__submenu {
    display: flex;
}

/* A nested menu's own reveal (see the guard above). Same two arms, matched from
   a root that itself sits inside a menu, so an inner menu's `--trigger-*` — or
   its absence, which is what `click` means in CSS — is what governs its own
   items. */
.brks-menu .brks-menu--trigger-hover
    .brks-menu__item--has-submenu:not(.brks-menu__item--trigger-click):hover
    > .brks-menu__submenu,
.brks-menu .brks-menu--trigger-auto.menu-horizontal
    .brks-menu__item--has-submenu:not(.brks-menu__item--trigger-click):hover
    > .brks-menu__submenu {
    display: flex;
}

/* Per-item opt-in: hover reveals THIS dropdown even under a click/auto-vertical
   menu. (Opt-out to click needs no rule — it is the `:not()` exclusion above.) */
.brks-menu .brks-menu__item--trigger-hover:hover > .brks-menu__submenu {
    display: flex;
}

/* ===== PANEL axis: floating ================================================
   Explicit `floating`, OR `auto` on a horizontal bar. */
.brks-menu--panel-floating .brks-menu__submenu,
.brks-menu--panel-auto.menu-horizontal .brks-menu__submenu {
    position: absolute;
    top: 0;
    left: 100%; /* nested panels fly to the side */
    z-index: 50;
    min-width: max-content;
}

/* Top level drops straight down under a horizontal bar. */
.brks-menu--panel-floating.menu-horizontal > .brks-menu__item--has-submenu > .brks-menu__submenu,
.brks-menu--panel-auto.menu-horizontal > .brks-menu__item--has-submenu > .brks-menu__submenu {
    top: 100%;
    left: 0;
}

/* Panel alignment (menu-global): WHERE a floating top-level panel opens
   relative to its trigger. `left` is the base (the rule above, left:0) so it
   needs no rule; `center`/`right` re-anchor. Scoped to FLOATING top-level
   panels on a horizontal bar (same guard as the base rule, so inline
   accordion/expanded panels are untouched), and EXCLUDING full/edge zones —
   those span the bar via their own width rules. The 2 :not()s also lift this
   to 0,7,0, above the base 0,4,0 so it wins WITHOUT beating the 0,4,0 zone
   full/edge rules (it no longer matches those items at all). */
.brks-menu--panel-align-center.brks-menu--panel-floating.menu-horizontal > .brks-menu__item--has-submenu:not(.brks-menu__item--zone-full):not(.brks-menu__item--zone-edge) > .brks-menu__submenu,
.brks-menu--panel-align-center.brks-menu--panel-auto.menu-horizontal > .brks-menu__item--has-submenu:not(.brks-menu__item--zone-full):not(.brks-menu__item--zone-edge) > .brks-menu__submenu {
    left: 50%;
    right: auto;
    transform: translateX(-50%);
}
.brks-menu--panel-align-right.brks-menu--panel-floating.menu-horizontal > .brks-menu__item--has-submenu:not(.brks-menu__item--zone-full):not(.brks-menu__item--zone-edge) > .brks-menu__submenu,
.brks-menu--panel-align-right.brks-menu--panel-auto.menu-horizontal > .brks-menu__item--has-submenu:not(.brks-menu__item--zone-full):not(.brks-menu__item--zone-edge) > .brks-menu__submenu {
    left: auto;
    right: 0;
}

/* Panel decoration at ZERO specificity (:where) so a user's own rule — even a
   single class, e.g. when the menu lives in a synced component like a header —
   overrides it with no specificity fight. */
:where(.brks-menu--panel-floating .brks-menu__submenu),
:where(.brks-menu--panel-auto.menu-horizontal .brks-menu__submenu) {
    background-color: var(--menu-panel-bg, var(--bg-color, #fff));
    border-radius: var(--menu-panel-radius, 0.25rem);
    box-shadow: var(--menu-panel-shadow, 0 0.5rem 1.5rem rgba(0, 0, 0, 0.15));
    border: var(--menu-panel-border-width, 0) var(--menu-panel-border-style, solid)
        var(--menu-panel-border-color, transparent);
}

/* Floating panels carry their own opaque background (--menu-panel-bg), so their
   text must stay legible ON that box — it must NOT inherit a dark surrounding
   context. Give them a panel-local text fallback of --font-color, scoped to the
   exact three conditions that also apply --menu-panel-bg (menu-global floating,
   auto on a horizontal bar, and a per-item floating override). Inline panels
   (accordion / expanded / auto-vertical) have no box and set nothing here, so
   their items fall through to `inherit` and track their context — which is what
   keeps an always-open submenu in a dark section from rendering dark-on-dark. The
   custom prop inherits from the panel container down to every descendant. */
:where(.brks-menu--panel-floating .brks-menu__submenu),
:where(.brks-menu--panel-auto.menu-horizontal .brks-menu__submenu),
:where(.brks-menu .brks-menu__item--panel-floating > .brks-menu__submenu) {
    --menu-panel-text-fallback: var(--font-color);
}

/* Panel text: item colour INSIDE a panel, so a floating panel's opaque
   background stays legible (companion to --menu-panel-bg). `:where()` keeps the
   item/title at the base item rule's specificity (0,1,0) — they win by source
   order for the REST state yet still yield to the higher-specificity :hover/.active
   rules above, so hover/active colours keep working inside panels. The trigger is
   matched one step tighter — `.brks-menu__item > .brks-menu__trigger` (0,2,0) —
   because a LINKED dropdown head is an <a>, and `.brks-menu__item > a { color: inherit }`
   (0,1,1) would otherwise win and make it inherit its <li>. That <li> turns dark
   when an ancestor is hovered (the has-submenu:hover neutraliser sets it to
   `inherit`), so on a dark panel the linked head went invisible once the pointer
   moved into its child panel; setting the head's colour directly fixes it while
   still yielding to the trigger's own 0,3,0 :hover/.active. Unset falls through to
   --menu-item-color, then to the panel-local --menu-panel-text-fallback: on a
   FLOATING panel that is --font-color (legible on the panel's own light box),
   while an INLINE panel leaves it unset so it resolves to `inherit` and tracks the
   surrounding context. The zone container carries the colour directly (last
   selector) so FREE content dropped inside a mega-menu zone — text/heading blocks
   that are none of the menu classes — inherits the panel text colour too. */
:where(.brks-menu__submenu) .brks-menu__item:where(:not(.brks-menu .brks-menu *)),
:where(.brks-menu__submenu) .brks-menu__title:where(:not(.brks-menu .brks-menu *)),
:where(.brks-menu__submenu) .brks-menu__item:where(:not(.brks-menu .brks-menu *)) > .brks-menu__trigger,
:where(.brks-menu__submenu) .brks-menu__separator:where(:not(.brks-menu .brks-menu *)),
:where(.brks-menu__zone) {
    color: var(--menu-panel-text, var(--menu-item-color, var(--menu-panel-text-fallback, inherit)));
}

/* `--menu-panel-text` inherits from the menu root DOWN, but the rule above
   matches items inside ANY panel — so a menu nested in a mega-menu zone, which
   sits inside the outer bar's panel, coloured its OWN bar items with its panel
   text (white on white: the items vanished). The `:where(:not(...))` guard above
   drops every item inside a nested menu, and this block hands them back keyed on
   a panel that belongs to the nested menu — two menus deep, so the outer bar's
   own zone panel (one deep) does not match. A nested menu's bar items are then
   left to the ordinary item rules and inherit the zone they sit in, which is
   what they did before anyone touched the panel channels. Guards at `:where()`
   so every specificity in the rule above is unchanged. */
:where(.brks-menu .brks-menu .brks-menu__submenu) .brks-menu__item,
:where(.brks-menu .brks-menu .brks-menu__submenu) .brks-menu__title,
:where(.brks-menu .brks-menu .brks-menu__submenu) .brks-menu__item > .brks-menu__trigger,
:where(.brks-menu .brks-menu .brks-menu__submenu) .brks-menu__separator {
    color: var(--menu-panel-text, var(--menu-item-color, var(--menu-panel-text-fallback, inherit)));
}

/* Side-flyout carets point right, at their panel, and keep pointing at it once
   it opens: nested panels always, plus an explicit floating panel on a vertical
   bar (its top level flies to the side too). */
.brks-menu--panel-floating .brks-menu__submenu .brks-menu__item--has-submenu > .brks-menu__trigger .brks-menu__caret,
.brks-menu--panel-auto.menu-horizontal .brks-menu__submenu .brks-menu__item--has-submenu > .brks-menu__trigger .brks-menu__caret,
.brks-menu--panel-floating:not(.menu-horizontal) > .brks-menu__item--has-submenu > .brks-menu__trigger .brks-menu__caret {
    --caret-base-turn: -90deg;
    --caret-open-turn: 0deg;
}

/* Submenu contents stay a left-aligned vertical list under a horizontal bar —
   in EVERY panel layout (floating panels, inline accordion/always-open, per-item
   overrides): the bar's centering rules would otherwise center-wrap the panel
   items. Vertical menus never center, so no counter-rule is needed there. */
.brks-menu.menu-horizontal .brks-menu__submenu .brks-menu__item,
.brks-menu.menu-horizontal .brks-menu__submenu .brks-menu__title {
    justify-content: flex-start;
    text-align: left;
}
.brks-menu.menu-horizontal .brks-menu__submenu .brks-menu__item > a,
.brks-menu.menu-horizontal .brks-menu__submenu .brks-menu__trigger {
    justify-content: flex-start;
}

/* ===== PANEL axis: accordion (inline) ======================================
   Explicit `accordion`, OR `auto` on a vertical bar. Declared AFTER floating and
   with `position: static` so it always wins — inline, never a side panel — even
   if a stale floating class ever lingered on the root. */
.brks-menu--panel-accordion .brks-menu__submenu,
.brks-menu--panel-auto:not(.menu-horizontal) .brks-menu__submenu {
    position: static;
    padding-left: 1rem;
}

/* Stack the submenu UNDER the trigger. The base .brks-menu__item is a flex ROW
   (align-items:center), which would otherwise lay the in-flow submenu out beside
   the trigger — the classic "opens to the side" bug for an inline accordion. */
.brks-menu--panel-accordion .brks-menu__item--has-submenu,
.brks-menu--panel-auto:not(.menu-horizontal) .brks-menu__item--has-submenu,
.brks-menu--panel-expanded .brks-menu__item--has-submenu {
    flex-direction: column;
    align-items: stretch;
}

/* ===== PANEL axis: expanded (inline, always visible) ======================= */
.brks-menu--panel-expanded .brks-menu__submenu {
    position: static;
    padding-left: 1rem;
    display: flex;
}

/* Under a horizontal bar, inline columns top-align: the bar's
   align-items:center would bulge unequal columns from the middle and float
   leaf items at mid-height — permanently for expanded (sitemap/footer
   columns), on every open/close for an accordion (items jump as the bar
   re-centers). Ditto for single-item overrides. `auto` needs no selector: on
   a horizontal bar it resolves to a floating panel. */
.brks-menu--panel-expanded.menu-horizontal,
.brks-menu--panel-accordion.menu-horizontal {
    align-items: flex-start;
}
.brks-menu.menu-horizontal .brks-menu__item--panel-expanded,
.brks-menu.menu-horizontal .brks-menu__item--panel-accordion {
    align-self: flex-start;
}

/* No toggle affordance when submenus are always open. */
.brks-menu--panel-expanded .brks-menu__item--has-submenu > .brks-menu__trigger .brks-menu__caret {
    display: none;
}

/* ===== Nested menu (inside a mega-menu zone) ===============================
   A zone's panel holds free content, so it can hold a whole MENU — the ordinary
   way to author a mega-menu column. Every menu-level rule above reaches its
   panels through a DESCENDANT combinator from the root, so the OUTER bar's
   panel axis crosses that boundary: `--panel-auto.menu-horizontal` (0,3,0) even
   out-specifies a nested menu's own `--panel-accordion` / `--panel-expanded`
   (0,2,0), which floated a submenu its author had asked to be always-open
   INLINE — it stayed open, but flew out beside its trigger.

   Re-assert the inline layouts one level deeper: (0,3,0) beats every leaking
   menu-level rule (they top out at 0,3,0 and this one is later in source), so
   the NEAREST menu root wins. Deliberately BEFORE the per-dropdown block below,
   which is (0,3,0) too — a single item's own override must still be the last
   word. Floating / auto-horizontal nested menus are absent on purpose: those
   DO want the floating treatment.

   `:where(:not(...))` on the auto-vertical arm keeps that selector at (0,3,0)
   like its two siblings — a bare `:not()` would count as a class, lift it to
   (0,4,0) and beat the per-dropdown override it must yield to. */
.brks-menu .brks-menu--panel-accordion .brks-menu__submenu,
.brks-menu .brks-menu--panel-auto:where(:not(.menu-horizontal)) .brks-menu__submenu,
.brks-menu .brks-menu--panel-expanded .brks-menu__submenu {
    position: static;
    top: auto;
    left: auto;
    min-width: 0;
}

/* The panel BOX crosses the boundary the same way, from the zero-specificity
   `:where()` decoration above — an inline nested panel inherited the outer
   bar's opaque background, radius, shadow and border (the `--menu-panel-*`
   custom props inherit into it too). Cleared at `:where()` as well, so this
   wins on source order alone and a user's own rule still beats both. */
:where(.brks-menu .brks-menu--panel-accordion .brks-menu__submenu),
:where(.brks-menu .brks-menu--panel-auto:not(.menu-horizontal) .brks-menu__submenu),
:where(.brks-menu .brks-menu--panel-expanded .brks-menu__submenu) {
    background-color: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

/* The mirror case: an INLINE outer menu reaching into a nested one that wants to
   FLOAT. `--panel-expanded` / `--panel-accordion` (0,2,0) tie with the nested
   menu's own floating rule (0,2,0) and win on source order, pinning a nested
   mega-menu flyout in the flow. Re-assert floating after the inline arms above,
   so the nested menu's own choice is the one that lands. The top-level
   drop-straight-down rule for a horizontal bar is (0,4,0) and still wins over
   this side-flyout default. */
.brks-menu .brks-menu--panel-floating .brks-menu__submenu {
    position: absolute;
    top: 0;
    left: 100%;
    z-index: 50;
    min-width: max-content;
}

/* ===== Per-dropdown PANEL override =========================================
   A single dropdown overrides its menu's panel layout via
   `brks-menu__item--panel-{value}` (the trigger's canvas "Submenu panel" trait,
   persisted in the per-placement overlay). Scoped `.brks-menu … > .brks-menu__submenu`
   — specificity (0,3,0) to beat the menu-level rules above, and `>` so it touches
   only this dropdown's own panel. Reveal is the TRIGGER axis above, not this. */

/* → accordion / expanded: inline panel, resetting any inherited floating look. */
.brks-menu .brks-menu__item--panel-accordion > .brks-menu__submenu,
.brks-menu .brks-menu__item--panel-expanded > .brks-menu__submenu {
    position: static;
    top: auto;
    left: auto;
    min-width: 0;
    padding-left: 1rem;
}

/* The panel BOX goes with it. The floating decoration is applied at `:where()`,
   and only `box-shadow` was being reset here — so a dropdown forced inline still
   sat on the floating panel's opaque card (its `--menu-panel-*` custom props
   inherit down from the menu root). Cleared at `:where()` too: a source-order
   win over the decoration that still yields to a user's own rule. */
:where(.brks-menu .brks-menu__item--panel-accordion > .brks-menu__submenu),
:where(.brks-menu .brks-menu__item--panel-expanded > .brks-menu__submenu) {
    background-color: transparent;
    border: 0;
    border-radius: 0;
    box-shadow: none;
}

/* Stack the submenu under the trigger (see the menu-level inline rule). */
.brks-menu .brks-menu__item--panel-accordion,
.brks-menu .brks-menu__item--panel-expanded {
    flex-direction: column;
    align-items: stretch;
}

/* An inline head points down and flips up once open, even inside a side flyout. */
.brks-menu .brks-menu__item--has-submenu.brks-menu__item--panel-accordion > .brks-menu__trigger > .brks-menu__caret.brks-caret {
    --caret-base-turn: 0deg;
    --caret-open-turn: 180deg;
}

/* → expanded: always open, no toggle caret. */
.brks-menu .brks-menu__item--panel-expanded > .brks-menu__submenu {
    display: flex;
}
.brks-menu .brks-menu__item--panel-expanded > .brks-menu__trigger .brks-menu__caret {
    display: none;
}

/* → floating: a floating panel even inside an otherwise inline menu. Resets the
   inline layouts' accordion indent back to the base panel padding — the mirror
   of the accordion/expanded overrides resetting the floating look above. */
.brks-menu .brks-menu__item--panel-floating > .brks-menu__submenu {
    position: absolute;
    top: 100%;
    left: 0;
    min-width: max-content;
    z-index: 50;
    padding-left: var(--menu-panel-padding, 0.25rem);
}
:where(.brks-menu .brks-menu__item--panel-floating > .brks-menu__submenu) {
    background-color: var(--menu-panel-bg, var(--bg-color, #fff));
    border-radius: var(--menu-panel-radius, 0.25rem);
    box-shadow: var(--menu-panel-shadow, 0 0.5rem 1.5rem rgba(0, 0, 0, 0.15));
    border: var(--menu-panel-border-width, 0) var(--menu-panel-border-style, solid)
        var(--menu-panel-border-color, transparent);
}

/* A mega-menu zone's panel is `.brks-menu__submenu.brks-menu__zone` — it reuses
   all the submenu reveal/positioning rules above, so it needs no base rule here.
   The editor-only :empty drop placeholder lives in protected.css and never ships
   to the published page. */

/* ===== Zone width axis (floating panel only) ================================
   A zone's panel holds FREE content, so unlike a link-list submenu it needs a
   predictable width instead of the shared `min-width: max-content`. Three modes,
   set on the menu and overridable per zone, resolved into a class on the zone <li>
   (mirrored in MenuSettings.php::zoneWidthClass):
     · dropdown — fixed `--menu-zone-width` (24rem), capped to 90vw, so an
       empty/narrow panel no longer collapses and a wide one no longer overflows
     · full (default) — spans the whole menu bar
     · edge  — full-bleed to the viewport (assumes a roughly centred bar)
   These only shape a FLOATING panel; an inline (accordion/expanded) zone stays in
   normal flow. `full`/`edge` reposition the panel against the menu ROOT, so the
   zone <li> drops to position:static and the root becomes the positioned ancestor
   (only when such a zone is present, via :has). Horizontal bars only. */

/* dropdown (the base, no class): fixed width for the floating zone panel. `min-width:0`
   overrides the shared floating `min-width: max-content` so the width is truly
   fixed — wide content wraps inside the panel instead of stretching it. */
.brks-menu--panel-floating .brks-menu__zone,
.brks-menu--panel-auto.menu-horizontal .brks-menu__zone,
.brks-menu .brks-menu__item--panel-floating > .brks-menu__zone {
    width: var(--menu-zone-width, 24rem);
    min-width: 0;
    max-width: 90vw;
}

/* full + edge: the panel resolves against the menu root, not its <li>. */
.brks-menu:has(> .brks-menu__item--zone-full),
.brks-menu:has(> .brks-menu__item--zone-edge) {
    position: relative;
}
.brks-menu__item--zone-full,
.brks-menu__item--zone-edge {
    position: static;
}

/* full: span the whole bar. Specificity matches the floating top-level rule
   (0,4,0) so its `left:0` is complemented by `right:0`, not lost. */
.brks-menu.menu-horizontal > .brks-menu__item--zone-full > .brks-menu__zone {
    left: 0;
    right: 0;
    width: auto;
    min-width: 0;
    max-width: none;
}

/* edge: full-bleed across the visible page. `breeks-menu.js` measures the bar's
   offset and the width inside the scrollbar; until then (or without JS) the
   full-bleed estimate — `100vw` from the menu's centre — stands in. */
.brks-menu.menu-horizontal > .brks-menu__item--zone-edge > .brks-menu__zone {
    left: var(--menu-edge-left, calc(50% - 50vw));
    right: auto;
    width: var(--menu-edge-width, 100vw);
    min-width: 0;
    max-width: none;
    margin-left: 0;
}

.brks-group {
    display: flex;
    flex-direction: column;
    align-items: start;
    width: 100%;
    max-width: var(--content-width, 1200px);
    margin: 0 auto;
    padding: var(--group-padding, 5px);
    gap: 0.5rem;
}

.brks-row {
    box-sizing: border-box;
    width: 100%;
    max-width: var(--content-width, 1200px);
    display: flex;
    /* Derived (stacking) — the brks-row--stack-* @media rules flip the -active
       layer to column/column-reverse at the chosen breakpoint. */
    flex-direction: var(--brks-row-direction-active, row);
    flex-wrap: wrap;
    justify-content: start;
    align-items: stretch;
    column-gap: var(--column-gap, 0);
    row-gap: var(--row-gap, 0.5rem);
    margin: 0 auto;
    padding: var(--row-padding, 5px);
}

.brks-col {
    display: flex;
    flex-direction: column;
    align-items: start;
    flex-shrink: 0;
    gap: 0.5rem;
    /* Derived (layout / responsive). Each property reads a layered var() ladder:
       the value-signature class (brks-cw-*, brks-cmin-*, brks-cmax-*, brks-cg-1)
       sets the base custom property; a media/state modifier sets the -active
       layer, which wins without !important. See derived-style-isolation.md. */
    flex-grow: var(--brks-col-grow-active, var(--brks-col-grow, 0));
    width: var(--brks-col-width-active, var(--brks-col-width, 100%));
    min-width: var(--brks-col-min-width-active, var(--brks-col-min-width, auto));
    max-width: var(--brks-col-max-width-active, var(--brks-col-max-width, 100%));
    padding: var(--column-padding, 5px);
}

.brks-separator {
    padding: 1rem;
}

.brks-link {
    display: inline-block;
    color: var(--links-color, #0066cc);
    text-decoration: var(--links-decoration, underline);
}

/* "Link anything" wrapper: a transparent <a> that carries the link but
   produces no box (display:contents), so the wrapped element keeps its own
   layout. color/text-decoration reset to inherit neutralizes the UA anchor
   styling that would otherwise cascade onto the wrapped content. */
.brks-linkwrap {
    display: contents;
    color: inherit;
    text-decoration: inherit;
}

h1.brks-title {
    color: var(--title-color, inherit);
    font-family: var(--title-font-family, Helvetica, sans-serif);
    font-size: var(--title-font-size, 2.5rem);
    line-height: var(--title-line-height, inherit);
}

h2.brks-title,
h3.brks-title,
h4.brks-title,
h5.brks-title,
h6.brks-title {
    color: var(--subtitle-color, inherit);
    font-family: var(--subtitle-font-family, Helvetica, sans-serif);
    line-height: var(--subtitle-line-height, inherit);
    font-size: var(--subtitle-font-size, 2rem);
}

h3.brks-title {
    font-size: calc(var(--subtitle-font-size, 2rem) * 0.8333);
}

h4.brks-title {
    font-size: calc(var(--subtitle-font-size, 2rem) * 0.6667);
}

h5.brks-title {
    font-size: calc(var(--subtitle-font-size, 2rem) * 0.5556);
}

h6.brks-title {
    font-size: calc(var(--subtitle-font-size, 2rem) * 0.5);
}

.brks-btn {
    display: inline-flex;
    justify-content: center;
    align-items: center;
    gap: .375rem;
    flex-wrap: nowrap;
    flex-shrink: 0;
    text-decoration: none;
    text-align: center;
    vertical-align: middle;
    color: var(--button-color);
    height: calc(var(--button-size) * 10);
    background-color: var(--button-bg-color);
    border-width: var(--button-border);
    border-style: var(--button-border-style);
    border-color: var(--button-border-color);
    border-radius: var(--button-border-radius);
    padding-inline: var(--button-padding);
    cursor: pointer;
}

.brks-btn .brks-icon {
    font-size: inherit;
}

.brks-btn:hover {
    color: var(--button-hover-color);
    background-color: var(--button-hover-bg-color);
    border: var(--button-hover-border) var(--button-hover-border-style) var(--button-hover-border-color);
    border-radius: var(--button-hover-border-radius);
}

.brks-icon {
    font-size: 2rem;
}

ul.brks-list, ol.brks-list {
    display: block;
    margin-block-start: 1em;
    margin-block-end: 1em;
    margin-inline-start: 0;
    margin-inline-end: 0;
    padding-inline-start: 40px;
}

/* Derived (bullet style). The brks-lst-* value-signature class sets
   --brks-list-style; the per-tag default lives in the var() fallback so the
   class is the sole setter. See docs/specs/derived-style-isolation.md (§5). */
ul.brks-list {
    list-style-type: var(--brks-list-style, disc);
}

ol.brks-list {
    list-style-type: var(--brks-list-style, decimal);
}

.brks-shape--container {
    position: relative;
    isolation: isolate;
}

.brks-shape {
    overflow: hidden;
    position: absolute;
    z-index: -1;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    max-width: 100%;
    /* The mask reveals the element's fill; this is the default the Style Manager
       overrides. The brks-shape--<id> signature class only sets mask-image. */
    background-color: currentColor;
    mask-repeat: no-repeat;
    mask-size: 100% 100%;
    mask-position: 0 0;
}

.brks-frame-portal {
    width: 100%;
}

/* What the renderer leaves where a node could not be rendered (RenderNotice.php).
   It only ever reaches the page in the CMS's debug mode, for whoever is building
   it — never a visitor. */
.brks-render-notice {
    box-sizing: border-box;
    flex: 1 1 100%;
    width: 100%;
    margin: 0.5rem 0;
    padding: 0.5rem 0.75rem;
    border-left: 4px solid #b45309;
    background: #fffbeb;
    color: #7c2d12;
    font: 14px/1.5 ui-monospace, monospace;
}

.brks-render-notice--error {
    border-left-color: #b91c1c;
    background: #fef2f2;
    color: #7f1d1d;
}
