/* Phase 8 — content-renderer styles. Colours are OKLCH or per-tenant --brand-*
   tokens (never literal hex), per the styling standard. Layout-first; the visual
   identity comes from the tenant theme. */

.bsl-lesson__header {
    margin-block-end: 1.25rem;
}

.bsl-lesson__objectives {
    background: oklch(96% 0.01 250);
    border-inline-start: 3px solid var(--brand-primary, oklch(45% 0.13 250));
    border-radius: 0.25rem;
}

.bsl-lesson__objectives ul {
    margin: 0.25rem 0 0;
    padding-inline-start: 1.25rem;
}

.bsl-lesson__block + .bsl-lesson__block {
    margin-block-start: 0.5rem;
}

/* Prose. Typography-theme consumption: every rule reads its preset's --type-* variables
   (emitted per tenant by ThemeProvider when a theme is set) with fallbacks equal to the
   pre-theme rendering — browser-default heading sizes over the inherited body — so pages
   without a theme draw exactly as before. Per-node builder styles layer on top and win. */
.bsl-richtext {
    font-family: var(--type-body-family, var(--font-body, inherit));
    font-size: var(--type-body-size, 1em);
    font-weight: var(--type-body-weight, normal);
    font-style: var(--type-body-style, normal);
    letter-spacing: var(--type-body-ls, normal);
    color: var(--bsl-text, var(--type-body-colour, inherit));
    text-transform: var(--type-body-transform, none);
    text-decoration-line: var(--type-body-decoration, none);
}

.bsl-richtext :is(h1, h2, h3, h4, h5, h6) {
    margin-block: 1rem 0.5rem;
    font-family: var(--font-heading, inherit);
}

/* Block headings — a callout's, a checklist's, a quiz's — follow the typography theme's
   Heading 4 preset (decision 2026-10-23: H4 is the small heading at the body's size, so the
   owner tunes all of them from one row). Fallbacks equal the pre-theme look: the heading
   face, the body's size, bold. A callout's heading keeps the alert's severity colour. */
.bsl-block-heading {
    margin-block-end: 0.25rem;
    font-family: var(--type-h4-family, var(--font-heading, inherit));
    font-size: var(--type-h4-size, var(--type-body-size, 1em));
    font-weight: var(--type-h4-weight, 700);
    font-style: var(--type-h4-style, normal);
    line-height: var(--type-h4-lh, 1.3);
    letter-spacing: var(--type-h4-ls, normal);
    color: var(--bsl-text, var(--type-h4-colour, inherit));
    text-transform: var(--type-h4-transform, none);
    text-decoration-line: var(--type-h4-decoration, none);
}

.bsl-callout .bsl-block-heading {
    color: inherit;
}

/* Quiz single-answer options stack one per line, like the multi-select boxes. The class is
   MudRadioGroup's InputClass, so it sits on the inner .mud-radio-group that lays out the row
   (MudBlazor has no direction parameter; its Class would land on the outer wrapper). Four
   class selectors: MudBlazor sets the row with three
   (.mud-input-control.mud-input-control-boolean-input .mud-radio-group). */
.bsl-quiz .bsl-quiz__question .mud-radio-group.bsl-quiz__options {
    flex-direction: column;
    align-items: flex-start;
}

/* The prompt is semibold so the question stands out from its options; its number (Q1, Q2…)
   leads in bold, with a real space after it in the markup so the text reads "Q1. …" to a
   screen reader too. */
.bsl-quiz .bsl-quiz__prompt {
    font-weight: 600;
}

.bsl-quiz__number {
    margin-inline-end: 0.15rem;
    font-weight: 700;
}

.bsl-richtext h1 { font-family: var(--type-h1-family, var(--font-heading, inherit)); font-size: var(--type-h1-size, 2em); font-weight: var(--type-h1-weight, 700); font-style: var(--type-h1-style, normal); line-height: var(--type-h1-lh, 1.25); letter-spacing: var(--type-h1-ls, normal); color: var(--bsl-text, var(--type-h1-colour, inherit)); text-transform: var(--type-h1-transform, none); text-decoration-line: var(--type-h1-decoration, none); }
.bsl-richtext h2 { font-family: var(--type-h2-family, var(--font-heading, inherit)); font-size: var(--type-h2-size, 1.5em); font-weight: var(--type-h2-weight, 700); font-style: var(--type-h2-style, normal); line-height: var(--type-h2-lh, 1.25); letter-spacing: var(--type-h2-ls, normal); color: var(--bsl-text, var(--type-h2-colour, inherit)); text-transform: var(--type-h2-transform, none); text-decoration-line: var(--type-h2-decoration, none); }
.bsl-richtext h3 { font-family: var(--type-h3-family, var(--font-heading, inherit)); font-size: var(--type-h3-size, 1.17em); font-weight: var(--type-h3-weight, 700); font-style: var(--type-h3-style, normal); line-height: var(--type-h3-lh, 1.25); letter-spacing: var(--type-h3-ls, normal); color: var(--bsl-text, var(--type-h3-colour, inherit)); text-transform: var(--type-h3-transform, none); text-decoration-line: var(--type-h3-decoration, none); }
.bsl-richtext h4 { font-family: var(--type-h4-family, var(--font-heading, inherit)); font-size: var(--type-h4-size, 1em); font-weight: var(--type-h4-weight, 700); font-style: var(--type-h4-style, normal); line-height: var(--type-h4-lh, normal); letter-spacing: var(--type-h4-ls, normal); color: var(--bsl-text, var(--type-h4-colour, inherit)); text-transform: var(--type-h4-transform, none); text-decoration-line: var(--type-h4-decoration, none); }
.bsl-richtext h5 { font-family: var(--type-h5-family, var(--font-heading, inherit)); font-size: var(--type-h5-size, 0.83em); font-weight: var(--type-h5-weight, 700); font-style: var(--type-h5-style, normal); line-height: var(--type-h5-lh, normal); letter-spacing: var(--type-h5-ls, normal); color: var(--bsl-text, var(--type-h5-colour, inherit)); text-transform: var(--type-h5-transform, none); text-decoration-line: var(--type-h5-decoration, none); }
.bsl-richtext h6 { font-family: var(--type-h6-family, var(--font-heading, inherit)); font-size: var(--type-h6-size, 0.67em); font-weight: var(--type-h6-weight, 700); font-style: var(--type-h6-style, normal); line-height: var(--type-h6-lh, normal); letter-spacing: var(--type-h6-ls, normal); color: var(--bsl-text, var(--type-h6-colour, inherit)); text-transform: var(--type-h6-transform, none); text-decoration-line: var(--type-h6-decoration, none); }

.bsl-richtext p {
    margin-block: 0.5rem;
    line-height: var(--type-body-lh, 1.6);
}

.bsl-richtext blockquote {
    font-family: var(--type-quote-family, inherit);
    font-size: var(--type-quote-size, 1em);
    font-weight: var(--type-quote-weight, normal);
    font-style: var(--type-quote-style, normal);
    line-height: var(--type-quote-lh, 1.6);
    letter-spacing: var(--type-quote-ls, normal);
    color: var(--bsl-text, var(--type-quote-colour, inherit));
    text-transform: var(--type-quote-transform, none);
    text-decoration-line: var(--type-quote-decoration, none);
}

/* Code font applies to code blocks + inline code only — KaTeX keeps its own faces.
   The fallbacks reproduce the browser's monospace defaults (generic family, ~13px). */
.bsl-richtext :is(pre, code) {
    font-family: var(--type-code-family, var(--font-code, monospace));
    font-size: var(--type-code-size, 0.8125em);
    font-weight: var(--type-code-weight, normal);
    font-style: var(--type-code-style, normal);
    line-height: var(--type-code-lh, normal);
    letter-spacing: var(--type-code-ls, normal);
    color: var(--bsl-text, var(--type-code-colour, inherit));
    text-transform: var(--type-code-transform, none);
    text-decoration-line: var(--type-code-decoration, none);
}

.bsl-richtext pre code { font-size: 1em; }

.bsl-richtext :is(ul, ol) {
    padding-inline-start: 1.5rem;
}

.bsl-richtext a {
    color: var(--brand-primary, oklch(45% 0.13 250));
}

/* Standalone heading block (B2) — matches the prose heading rhythm and reads the same
   per-level presets as prose headings. */
.bsl-heading {
    margin-block: 1rem 0.5rem;
    font-family: var(--font-heading, inherit);
}

h2.bsl-heading, .bsl-faq__heading { font-family: var(--type-h2-family, var(--font-heading, inherit)); font-size: var(--type-h2-size, 1.5em); font-weight: var(--type-h2-weight, 700); font-style: var(--type-h2-style, normal); line-height: var(--type-h2-lh, 1.25); letter-spacing: var(--type-h2-ls, normal); color: var(--bsl-text, var(--type-h2-colour, inherit)); text-transform: var(--type-h2-transform, none); text-decoration-line: var(--type-h2-decoration, none); }
h3.bsl-heading { font-family: var(--type-h3-family, var(--font-heading, inherit)); font-size: var(--type-h3-size, 1.17em); font-weight: var(--type-h3-weight, 700); font-style: var(--type-h3-style, normal); line-height: var(--type-h3-lh, 1.25); letter-spacing: var(--type-h3-ls, normal); color: var(--bsl-text, var(--type-h3-colour, inherit)); text-transform: var(--type-h3-transform, none); text-decoration-line: var(--type-h3-decoration, none); }
h4.bsl-heading { font-family: var(--type-h4-family, var(--font-heading, inherit)); font-size: var(--type-h4-size, 1em); font-weight: var(--type-h4-weight, 700); font-style: var(--type-h4-style, normal); line-height: var(--type-h4-lh, 1.25); letter-spacing: var(--type-h4-ls, normal); color: var(--bsl-text, var(--type-h4-colour, inherit)); text-transform: var(--type-h4-transform, none); text-decoration-line: var(--type-h4-decoration, none); }

/* Figures (image / video) */
.bsl-figure {
    margin-inline: 0;
    text-align: center;
}

.bsl-figure__img {
    max-width: 100%;
    height: auto;
    border-radius: 0.375rem;
}

.bsl-figure__caption {
    margin-block-start: 0.375rem;
    font-family: var(--type-caption-family, inherit);
    font-size: var(--type-caption-size, 0.875rem);
    font-weight: var(--type-caption-weight, normal);
    font-style: var(--type-caption-style, normal);
    line-height: var(--type-caption-lh, normal);
    letter-spacing: var(--type-caption-ls, normal);
    color: var(--bsl-text, var(--type-caption-colour, oklch(50% 0.01 250)));
    text-transform: var(--type-caption-transform, none);
    text-decoration-line: var(--type-caption-decoration, none);
}

.bsl-figure__labels {
    margin-block-start: 0.5rem;
    text-align: start;
    padding-inline-start: 1.25rem;
}

/* Hotspot pins: the wrapper carries the block's width mode and the image fills it,
   so percentage pin positions track the image box exactly. */
.bsl-figure__hotwrap {
    position: relative;
    display: inline-block;
    max-width: 100%;
}

.bsl-figure__hotwrap .bsl-figure__img {
    display: block;
    width: 100%;
}

/* A spot is a pin and its tip, centred on the pin's point. */
.bsl-figure__spot {
    position: absolute;
    transform: translate(-50%, -50%);
    line-height: 1;
}

.bsl-figure__spot:hover,
.bsl-figure__spot:focus-within {
    z-index: 2;
}

.bsl-figure__pin {
    display: grid;
    place-items: center;
    min-width: 1.375rem;
    height: 1.375rem;
    padding-inline: 0.25rem;
    border-radius: 999px;
    background: var(--brand-primary);
    color: var(--on-brand, white);
    border: 2px solid color-mix(in oklch, var(--brand-primary), transparent 55%);
    font-family: inherit;
    font-size: 0.75rem;
    font-weight: 700;
    line-height: 1;
    cursor: pointer;
}

.bsl-figure__pin:focus-visible {
    outline: 2px solid var(--brand-primary);
    outline-offset: 2px;
}

/* The tip: the hotspot's label and note, shown while its pin is pointed at, tapped or
   focused. Above the pin by default; below near the top edge; aligned to the pin near a side. */
.bsl-figure__tip {
    display: none;
    position: absolute;
    left: 50%;
    bottom: calc(100% + 0.4rem);
    transform: translateX(-50%);
    width: max-content;
    max-width: min(16rem, 70vw);
    padding: 0.4rem 0.6rem;
    border-radius: 0.375rem;
    background: var(--ink, var(--mud-palette-text-primary));
    color: var(--surface, var(--mud-palette-surface));
    font-size: 0.8125rem;
    font-weight: 400;
    line-height: 1.35;
    text-align: start;
    white-space: normal;
    pointer-events: none;
}

.bsl-figure__spot:hover .bsl-figure__tip,
.bsl-figure__spot:focus-within .bsl-figure__tip {
    display: block;
}

.bsl-figure__spot--below .bsl-figure__tip {
    bottom: auto;
    top: calc(100% + 0.4rem);
}

.bsl-figure__spot--start .bsl-figure__tip {
    left: 0;
    transform: none;
}

.bsl-figure__spot--end .bsl-figure__tip {
    left: auto;
    right: 0;
    transform: none;
}

.bsl-attribution {
    display: block;
    margin-block-start: 0.25rem;
    color: oklch(55% 0.01 250);
    font-size: 0.75rem;
}

/* Video — responsive 16:9 embeds */
.bsl-video {
    width: 100%;
    border-radius: 0.375rem;
}

.bsl-video--embed {
    position: relative;
    padding-block-end: 56.25%;
    height: 0;
    overflow: hidden;
}

.bsl-video--embed iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
}

/* Video review 2026-10-06: the transcript folds out beneath the player; a linked video's
   credit reads like an asset's attribution. */
/* Embed (2026-10-13): a self-contained HTML page in a sandboxed frame. The box is the authored
   height (--bsl-embed-height) or 16:9; the frame fills it. Until the learner clicks, a cover
   takes the pointer so wheel and touch scroll the lesson rather than the page inside (a 3D
   scene zooms on wheel); the cover returns when the pointer leaves (bslContentRenderer.js). */
.bsl-embed {
    position: relative;
    width: 100%;
    height: var(--bsl-embed-height, auto);
    aspect-ratio: 16 / 9;
    overflow: hidden;
    border-radius: 0.375rem;
    background: color-mix(in oklch, var(--line, var(--mud-palette-lines-default)) 50%, transparent);
}

.bsl-embed--sized {
    aspect-ratio: auto;
}

.bsl-embed__frame {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    border: 0;
    display: block;
}

.bsl-embed__cover {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    padding: 0.75rem;
    border: 0;
    background: transparent;
    color: inherit;
    cursor: pointer;
    font: inherit;
}

.bsl-embed__cover-label {
    padding: 0.375rem 0.75rem;
    border-radius: 999px;
    font-size: 0.8125rem;
    line-height: 1.2;
    color: var(--on-brand, white);
    background: color-mix(in oklch, var(--brand-primary, var(--mud-palette-primary)) 85%, transparent);
    pointer-events: none;
}

.bsl-embed--active .bsl-embed__cover {
    display: none;
}

/* The shield is invisible (2026-10-15): the page beneath is what the learner sees, and the
   "Click to interact" hint appears only while the pointer is over it, or on keyboard focus. */
.bsl-embed__cover {
    background: transparent;
}

.bsl-embed__cover .bsl-embed__cover-label {
    opacity: 0;
    transition: opacity 160ms ease-out;
}

.bsl-embed__cover:hover .bsl-embed__cover-label,
.bsl-embed__cover:focus-visible .bsl-embed__cover-label {
    opacity: 1;
}

/* A dotLottie animation (user call 2026-10-13) plays in place on a canvas that fills the same
   box; the box shows nothing of its own behind it, so a transparent animation sits on the
   lesson, not on a tinted panel. */
.bsl-embed--lottie {
    background: transparent;
}

.bsl-embed__lottie {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    display: block;
    touch-action: manipulation;
}

.bsl-video__transcript {
    margin-block-start: 0.5rem;
    font-size: 0.875rem;
}

.bsl-video__transcript > summary {
    cursor: pointer;
    color: var(--brand-primary, inherit);
    font-weight: 600;
}

.bsl-video__transcript-text {
    margin-block-start: 0.375rem;
    padding-inline-start: 0.75rem;
    border-inline-start: 2px solid color-mix(in oklch, var(--brand-primary, currentColor) 35%, transparent);
    white-space: pre-line;
    line-height: 1.5;
}

/* Equation — centred by default, but an authored Style › Text align (the node's --bsl-ta)
   moves the equation with its glossary rather than the glossary alone (lesson-blocks review
   2026-09-23, batch B). KaTeX's own .katex-display centres itself, so it defers too. */
.bsl-equation__display {
    overflow-x: auto;
    padding-block: 0.5rem;
    text-align: var(--bsl-ta, center);
    /* A displayed equation is set larger than the text around it, as the design draws it
       (26px over 16px body with KaTeX's own 1.21em). At body size the hairline bars of "="
       sat a pixel apart on the zoomed builder canvas and read as a minus (user report
       2026-10-01). */
    font-size: 1.35em;
}

.bsl-equation__display .katex-display {
    text-align: inherit;
}

/* Editing-surface placeholder for a text the author has not typed yet (the builder canvas
   cascades BslEditing; the learner surface never renders one). */
.bsl-placeholder {
    color: oklch(55% 0.01 250);
    font-style: italic;
}

/* ── Link block (decisions 2026-09-29): one inline link in the brand colour, an arrow after
   it, underlined on hover, with a focus ring. Style › Colour › Text paints the LINK (lifted
   from the node's own --bsl-color, as the Button does), so unset it is the brand primary the
   inspector row shows. A link to a lesson the learner cannot open yet is plain text with a
   padlock and the reason under it. */
.bsl-node--block:has(.bsl-link) {
    --bsl-link-color: var(--bsl-color);
}

.bsl-link {
    margin: 0;
}

.bsl-link__anchor {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--bsl-link-color, var(--brand-primary, var(--mud-palette-primary)));
    font-weight: 600;
    text-decoration: none;
    border-radius: 0.25rem;
}

.bsl-link__anchor:hover {
    text-decoration: underline;
    text-underline-offset: 0.2em;
}

.bsl-link__anchor:focus-visible {
    outline: 2px solid var(--bsl-link-color, var(--brand-primary, var(--mud-palette-primary)));
    outline-offset: 2px;
}

.bsl-link__icon.mud-icon-root {
    font-size: 1.1em;
}

.bsl-link__locked {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--ink-soft, var(--mud-palette-text-secondary));
    font-weight: 600;
}

.bsl-link__reason {
    display: block;
    margin-top: 0.15rem;
    font-size: 0.85rem;
    color: var(--ink-faint, var(--mud-palette-text-secondary));
}

.bsl-equation__glossary {
    margin: 0;
    display: grid;
    gap: 0.25rem 0.75rem;
}

.bsl-equation__var {
    display: flex;
    gap: 0.5rem;
}

.bsl-equation__var dt {
    font-weight: 600;
    min-width: 2.5rem;
}

.bsl-equation__var dd {
    margin: 0;
    color: oklch(40% 0.01 250);
}

/* Phase 9a — the layout tree. Layout-only (no authored colour); spacing/columns come from
   per-node CSS custom properties set inline by LayoutStyle. The lesson body is a query
   container so per-breakpoint overrides (9b) respond to its width, not the viewport. */
.bsl-lesson__blocks {
    container-type: inline-size;
}

/* The type scale per breakpoint (user call 2026-09-29). A theme emits every preset's size
   three times — desktop, and again under the tablet and phone ratios (TypographyCss) — as
   plain declarations, because canvases inline them and a declaration cannot hold an
   @container rule. These two rules do the swapping, by the width of the page's container
   (never the window), so a canvas at the Tablet or Mobile width previews what a visitor
   sees. Without a theme the -tablet/-phone variables do not exist, the swap resolves to
   nothing, and each consumer's own fallback draws as before. Widths match
   TypographyCss.TabletMaxWidthPx / PhoneMaxWidthPx. */
@container (max-width: 1024px) {
    .bsl-node,
    .bsl-lesson__block {
        --type-display-size: var(--type-display-size-tablet);
        --type-h1-size: var(--type-h1-size-tablet);
        --type-h2-size: var(--type-h2-size-tablet);
        --type-h3-size: var(--type-h3-size-tablet);
        --type-h4-size: var(--type-h4-size-tablet);
        --type-h5-size: var(--type-h5-size-tablet);
        --type-h6-size: var(--type-h6-size-tablet);
        --type-body-size: var(--type-body-size-tablet);
        --type-lead-size: var(--type-lead-size-tablet);
        --type-caption-size: var(--type-caption-size-tablet);
        --type-quote-size: var(--type-quote-size-tablet);
        --type-code-size: var(--type-code-size-tablet);
    }
}

@container (max-width: 640px) {
    .bsl-node,
    .bsl-lesson__block {
        --type-display-size: var(--type-display-size-phone);
        --type-h1-size: var(--type-h1-size-phone);
        --type-h2-size: var(--type-h2-size-phone);
        --type-h3-size: var(--type-h3-size-phone);
        --type-h4-size: var(--type-h4-size-phone);
        --type-h5-size: var(--type-h5-size-phone);
        --type-h6-size: var(--type-h6-size-phone);
        --type-body-size: var(--type-body-size-phone);
        --type-lead-size: var(--type-lead-size-phone);
        --type-caption-size: var(--type-caption-size-phone);
        --type-quote-size: var(--type-quote-size-phone);
        --type-code-size: var(--type-code-size-phone);
    }
}

/* The per-node layout values are custom properties set inline on the node (LayoutStyle.
   NodeCss) and read by the rules below. Registered as NON-inheriting: as plain custom
   properties they cascaded into every descendant, so a Section's Justify shrank the
   columns of the Rows inside it, its Align/gap/padding/margin leaked into nested nodes,
   and a node only escaped by setting its own value (user report 2026-09-09: a 1·2·1
   header Row "crammed in the centre"). A node without a value now gets the rule's
   fallback, as intended. */
@property --bsl-align { syntax: "*"; inherits: false; }
@property --bsl-justify { syntax: "*"; inherits: false; }
@property --bsl-gap { syntax: "*"; inherits: false; }
@property --bsl-pad { syntax: "*"; inherits: false; }
@property --bsl-mar { syntax: "*"; inherits: false; }
@property --bsl-cols { syntax: "*"; inherits: false; }
@property --bsl-span { syntax: "*"; inherits: false; }
/* The node's authored colours, readable by that node only (LayoutStyle emits them beside
   color / background). Non-inheriting so a Section's background never leaks into a Button. */
@property --bsl-color { syntax: "*"; inherits: false; }
@property --bsl-bg { syntax: "*"; inherits: false; }
/* --bsl-text is the same Text colour but INHERITING (deliberately unregistered): text that
   carries a colour of its own — a theme preset's, or the Copyright line's muted ink — reads
   it first, so the nearest node with a Style › Text colour wins over the theme
   (2026-09-28: a white heading on a dark band drew in the Heading 2 preset's colour). */
/* The node's authored border and radius, likewise node-scoped (2026-09-26): a block that
   paints its own card lifts them onto the card and leaves the node without an outline. */
@property --bsl-border { syntax: "*"; inherits: false; }
@property --bsl-radius { syntax: "*"; inherits: false; }

/* Effects (2026-09-29). The three shadows an author can pick (Style › Effects › Shadow):
   black at low alpha, two layers each, so they sit on any surface. LayoutStyle writes
   box-shadow: var(--bsl-shadow-…) on the node, and the same value as node-scoped
   --bsl-shadow for the blocks that paint their own surface. */
:root {
    --bsl-shadow-sm: 0 1px 2px color-mix(in oklch, oklch(0% 0 0), transparent 90%),
        0 1px 3px color-mix(in oklch, oklch(0% 0 0), transparent 88%);
    --bsl-shadow-md: 0 2px 4px color-mix(in oklch, oklch(0% 0 0), transparent 92%),
        0 6px 16px color-mix(in oklch, oklch(0% 0 0), transparent 88%);
    --bsl-shadow-lg: 0 4px 8px color-mix(in oklch, oklch(0% 0 0), transparent 92%),
        0 16px 40px color-mix(in oklch, oklch(0% 0 0), transparent 84%);
}

@property --bsl-shadow { syntax: "*"; inherits: false; }

/* The Document card (Style › Border and Colour drive the CARD, user call 2026-09-26): the
   node's border and radius are lifted onto the card — unset, the card keeps its own 1px
   line and 4px corners, which the inspector shows as the placeholders — and the node wears
   no second outline. Icon and Open button colours are the block's own fields (--bsl-doc-*,
   set inline on the card); unset they paint the ink, as they always did. */
.bsl-node--block:has(.bsl-document) {
    --bsl-doc-border: var(--bsl-border);
    --bsl-doc-radius: var(--bsl-radius);
    --bsl-doc-shadow: var(--bsl-shadow);
    border: none;
    box-shadow: none;
}

.bsl-document.mud-paper-outlined {
    border: var(--bsl-doc-border, 1px solid var(--mud-palette-lines-default));
    border-radius: var(--bsl-doc-radius, var(--mud-default-borderradius, 4px));
    box-shadow: var(--bsl-doc-shadow, none);
}

.bsl-document__icon {
    color: var(--bsl-doc-icon, currentColor);
}

.bsl-document__open.mud-button-outlined {
    color: var(--bsl-doc-button, var(--mud-palette-text-primary));
    border-color: var(--bsl-doc-button, var(--mud-palette-text-primary));
}

.bsl-node {
    padding: var(--bsl-pad, 0);
    margin: var(--bsl-mar, 0);
    min-width: 0;
}

/* In a layout the space between blocks is the AUTHOR'S — the container's Gap and the node's
   Margin — and nothing else (user call 2026-09-29). A heading, a paragraph and a divider each
   brought a margin of their own, which stacked on top of the Gap: the only way to a design's
   spacing was a negative Margin on the block. A block's content now starts and ends flush
   with its node; the rhythm INSIDE a Rich text (between its paragraphs) is untouched, and so
   is prose outside a layout. */
.bsl-node--block .bsl-heading,
.bsl-node--block .bsl-divider {
    margin-block: 0;
}

.bsl-node--block .bsl-richtext > :first-child {
    margin-block-start: 0;
}

.bsl-node--block .bsl-richtext > :last-child {
    margin-block-end: 0;
}

/* Layout contract (errata 2026-09-09 clarified it):
   · Section and Column are vertical flex stacks. Align = how their children line up
     HORIZONTALLY (start · centre · end · stretch); Justify = how children are DISTRIBUTED
     vertically when the box is taller than its content (incl. space-between/around).
   · Row is a CSS grid of N equal columns. Align = how the columns line up VERTICALLY;
     Justify = how each column's content sits horizontally inside its track
     (start · centre · end — the space-* values have no meaning per cell and are not offered).
   · Padding/margin apply to every node via --bsl-pad/--bsl-mar and never conflict with
     alignment: padding is inside the box, alignment positions the box. */
.bsl-section {
    --bsl-box: 1080px; /* the Boxed content-width column (Section → Content width) */
    display: flex;
    flex-direction: column;
    gap: var(--bsl-gap, 1.5rem);
    align-items: var(--bsl-align, stretch);
    justify-content: var(--bsl-justify, start);
}

.bsl-row {
    display: grid;
    grid-template-columns: repeat(var(--bsl-cols, 1), minmax(0, 1fr));
    gap: var(--bsl-gap, 1rem);
    align-items: var(--bsl-align, stretch);
    justify-items: var(--bsl-justify, stretch);
    /* A Row always fills its container's width (less the container's padding and the
       Row's own margin): it brings its own column tracks, so a parent Section/Column set
       to Align centre/start/end must not shrink-wrap it — that centred a header's Row at
       the width of its content and crammed the tracks together (user call 2026-09-09).
       The parent's Align still positions ordinary blocks. */
    align-self: stretch;
}

/* A Column spans at most the tracks its Row has (--bsl-tracks, inherited from the Row): a
   wide Column in a Row a breakpoint drops to one column used to add a second, empty track
   and a gap beside it (2026-09-29). */
.bsl-col {
    grid-column: span min(var(--bsl-span, 1), var(--bsl-tracks, 12));
    display: flex;
    flex-direction: column;
    gap: var(--bsl-gap, 1rem);
    align-items: var(--bsl-align, stretch);
    justify-content: var(--bsl-justify, start);
}

/* Responsive by default (§12): rows collapse to a single column on narrow containers,
   even when the author never opens the Tablet/Mobile breakpoints — unless a breakpoint
   override sets Columns (LayoutStyle emits --bsl-cols-narrow), which wins (Batch B). */
@container (max-width: 640px) {
    .bsl-row {
        grid-template-columns: repeat(var(--bsl-cols-narrow, 1), minmax(0, 1fr));
    }

    .bsl-row > .bsl-col {
        grid-column: span min(var(--bsl-span, 1), var(--bsl-cols-narrow, 1));
    }
}

/* ── Landing-page widgets (Hero / CourseList / Header) ─────────────────────────
   Rendered on the org surface in the org's brand tokens; MudBlazor palette vars are
   the in-builder fallbacks. Runtime values (image URL, overlay, min-height) arrive as
   custom properties on the element. */

.bsl-hero {
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: var(--hero-min-h, 360px);
    border-radius: 1rem;
    overflow: hidden;
    background-image: var(--hero-image, none);
    background-size: cover;
    background-position: var(--hero-pos, center);
    /* Centred by default; the node's Style › Text align (LayoutStyle emits --bsl-ta and the
       matching flex placement --bsl-place) moves the text block left or right. */
    text-align: var(--bsl-ta, center);
    justify-content: var(--bsl-place, center);
}

.bsl-hero--fallback {
    background-image: linear-gradient(120deg,
        var(--brand-primary, var(--mud-palette-primary)),
        color-mix(in oklch, var(--brand-primary, var(--mud-palette-primary)), var(--brand-accent, var(--mud-palette-secondary)) 55%));
}

.bsl-hero__overlay {
    position: absolute;
    inset: 0;
    background: color-mix(in oklch, var(--brand-primary, var(--mud-palette-primary)), transparent var(--hero-overlay, 55%));
}

.bsl-hero__inner {
    position: relative;
    padding: 2.5rem 1.5rem;
    max-width: 46rem;
    color: var(--on-brand, white);
}

/* The hero heading is the page's h1: it takes the Heading 1 preset's family, weight and
   style, and keeps its own fluid size and the hero's text colour. */
.bsl-hero__heading {
    margin: 0;
    font-family: var(--type-h1-family, var(--font-heading, inherit));
    font-weight: var(--type-h1-weight, 700);
    font-style: var(--type-h1-style, normal);
    font-size: clamp(1.8rem, 4.5cqi, 3rem); /* cqi, not vw: follows the container, so the canvas previews the real size */
    line-height: 1.1;
    letter-spacing: -0.02em;
}

.bsl-hero__sub {
    margin: 1rem 0 0;
    font-size: 1.1rem;
    opacity: 0.92;
}

.bsl-hero__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: var(--bsl-place, center);
    margin-top: 1.5rem;
}

/* Dark text for pale images (Batch B): ink instead of white, and a white tint instead of
   the brand tint so the picture still fades behind the words. */
.bsl-hero--dark-text .bsl-hero__inner {
    color: var(--ink, #1a1a1a);
}

.bsl-hero--dark-text .bsl-hero__overlay {
    /* a tint at the authored strength, not an opaque sheet (audit item 149) */
    background: color-mix(in oklch, var(--on-brand, white), transparent var(--hero-overlay, 55%));
}

.bsl-hero__cta {
    display: inline-flex;
    padding: 0.7rem 1.4rem;
    border-radius: 0.6rem;
    border: 2px solid transparent;
    background: var(--brand-accent, var(--mud-palette-secondary));
    color: var(--on-brand, white);
    font-weight: 700;
    text-decoration: none;
}

.bsl-hero__cta:hover {
    background: color-mix(in oklch, var(--brand-accent, var(--mud-palette-secondary)), var(--on-brand, white) 14%);
}

/* The second button is OUTLINED. These rules sit after the base rules above on purpose: they
   have the same specificity, so written first they lost and the second button drew filled
   (2026-09-29). The base button carries a transparent border so both are the same size. */
.bsl-hero__cta--secondary {
    background: transparent;
    border-color: currentColor;
}

.bsl-hero__cta--secondary:hover {
    background: color-mix(in oklch, currentColor, transparent 86%);
}

.bsl-courselist__heading {
    margin: 0 0 1rem;
    font-size: 1.4rem;
    letter-spacing: -0.01em;
}

.bsl-courselist--grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 1rem;
}

.bsl-courselist--row {
    display: flex;
    gap: 1rem;
    overflow-x: auto;
    padding-bottom: 0.5rem;
}

.bsl-courselist--row .bsl-courselist__card,
.bsl-courselist--row .bsl-courselist__skeleton {
    flex: 0 0 220px;
}

.bsl-courselist__card {
    display: flex;
    flex-direction: column;
    border: 1px solid var(--line, var(--mud-palette-lines-default));
    border-radius: 0.8rem;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    background: var(--surface, var(--mud-palette-surface));
    transition: transform var(--motion-base, 200ms) var(--ease-out, ease);
}

.bsl-courselist__card:hover {
    transform: translateY(-3px);
    border-color: color-mix(in oklch, var(--brand-primary, var(--mud-palette-primary)), transparent 55%);
}

.bsl-courselist__cover {
    display: block;
    width: 100%;
    height: 120px;
    object-fit: cover;
}

.bsl-courselist__cover--fallback {
    display: grid;
    place-items: center;
    font-size: 2rem;
    font-weight: 800;
    color: var(--on-brand, white);
    background: linear-gradient(120deg,
        var(--brand-primary, var(--mud-palette-primary)),
        color-mix(in oklch, var(--brand-primary, var(--mud-palette-primary)), var(--brand-accent, var(--mud-palette-secondary)) 55%));
}

/* The card's text, then its price at the BOTTOM (user call 2026-09-29): the body fills what
   is left of the card and the price is pushed to its foot, so the prices of a row of cards
   line up however long each summary runs. The price used to sit beside the text, centred. */
.bsl-courselist__body {
    flex: 1;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    padding: 0.8rem 1rem;
}

.bsl-courselist__text {
    display: block;
}

.bsl-courselist__title {
    font-weight: 700;
}

.bsl-courselist__summary {
    display: block;
    margin-top: 0.3rem;
    font-size: 0.85rem;
    color: var(--ink-faint, var(--mud-palette-text-secondary));
}

.bsl-courselist__meta {
    display: block;
    margin-top: 0.3rem;
    font-size: 0.78rem;
    color: var(--ink-faint, var(--mud-palette-text-secondary));
}

.bsl-courselist__viewall {
    display: inline-block;
    margin-top: 1rem;
    font-weight: 700;
    text-decoration: none;
    color: var(--brand-primary, var(--mud-palette-primary));
}

.bsl-courselist__price {
    margin-top: auto;
    font-weight: 800;
    font-size: 0.82rem;
    white-space: nowrap;
    color: var(--brand-primary, var(--mud-palette-primary));
}

.bsl-courselist__skeleton {
    height: 160px;
    border-radius: 0.8rem;
    border: 1px dashed var(--line, var(--mud-palette-lines-default));
    background: color-mix(in oklch, var(--surface-muted, var(--mud-palette-background-gray)), transparent 30%);
}

.bsl-courselist__skeletons {
    margin-bottom: 0.6rem;
}

.bsl-courselist__note {
    color: var(--ink-faint, var(--mud-palette-text-secondary));
    font-size: 0.9rem;
    font-style: italic;
    margin: 0;
}

/* The author's Empty message: page copy, not an author note — body text in the muted ink. */
.bsl-courselist__empty {
    color: var(--ink-soft, var(--mud-palette-text-secondary));
    margin: 0;
}

/* The signed-in learner on the live site header (site chrome). */
/* Nav links widget (site chrome): authored links in a wrapping row — a header's menu — or,
   with Direction › Vertical (2026-09-21), a list: a column of footer links under a Heading.
   The list follows Style › Text align through the same --bsl-place the other blocks use. */
.bsl-navlinks {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 1.1rem;
}

.bsl-navlinks--vertical {
    flex-direction: column;
    flex-wrap: nowrap;
    align-items: var(--bsl-place, flex-start);
    gap: 0.45rem;
}

.bsl-navlinks__link {
    white-space: nowrap;
    text-decoration: none;
    color: inherit;
    font-weight: 600;
}

.bsl-navlinks--vertical .bsl-navlinks__link {
    white-space: normal;
}

.bsl-navlinks__link:hover {
    color: var(--brand-primary, var(--mud-palette-primary));
}

/* Mobile menu (2026-09-22): a horizontal Nav links with the switch on folds behind a menu
   button on a narrow container. A native <details>, so the static org pages open it without
   script. Wide: the <details> is out of the way and the row of links shows, as before. */
.bsl-navlinks__menu {
    display: none;
}

.bsl-navlinks__toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 2.75rem; /* a 44px touch target */
    min-height: 2.75rem;
    list-style: none;
    cursor: pointer;
    color: inherit;
    border-radius: 0.55rem;
}

.bsl-navlinks__toggle::-webkit-details-marker {
    display: none;
}

.bsl-navlinks__toggle:hover,
.bsl-navlinks__menu[open] > .bsl-navlinks__toggle {
    color: var(--brand-primary, var(--mud-palette-primary));
}

.bsl-navlinks__toggle:focus-visible {
    outline: 2px solid var(--brand-primary, var(--mud-palette-primary));
    outline-offset: 2px;
}

/* The panel hangs under its containing block — the site header on a live page (full width),
   the Nav links' own node on the builder canvas (so it never grows narrower than 14rem and
   opens leftwards from the button). */
.bsl-navlinks__panel {
    position: absolute;
    z-index: 30;
    top: 100%;
    right: 0;
    box-sizing: border-box;
    width: max(100%, 14rem);
    display: flex;
    flex-direction: column;
    padding: 0.5rem 1rem 0.9rem;
    text-align: start;
    color: var(--ink, var(--mud-palette-text-primary));
    background: var(--surface, var(--mud-palette-surface));
    border-block: 1px solid var(--line, var(--mud-palette-lines-default));
    box-shadow: 0 12px 24px oklch(0% 0 0 / 0.12);
}

.bsl-navlinks__menu-link {
    display: block;
    padding: 0.75rem 0;
    text-decoration: none;
    color: inherit;
    font-weight: 600;
}

.bsl-navlinks__menu-link:hover {
    color: var(--brand-primary, var(--mud-palette-primary));
}

/* Sign in/out at the foot of the panel, under a divider. */
.bsl-navlinks__account {
    margin-top: 0.5rem;
    padding-top: 0.9rem;
    border-top: 1px solid var(--line, var(--mud-palette-lines-default));
}

@container (max-width: 640px) {
    .bsl-navlinks--menu {
        justify-content: flex-end;
    }

    .bsl-navlinks--menu > .bsl-navlinks__link {
        display: none;
    }

    .bsl-navlinks--menu > .bsl-navlinks__menu {
        display: block;
    }

    /* The header stays ONE line — [logo …] [menu] — rather than stacking like other Rows:
       the first track takes the room, the rest hug their content, and the 1·2·1 spans of a
       wide header no longer apply. */
    .bsl-row:has(> .bsl-col .bsl-navlinks--menu) {
        grid-template-columns: minmax(0, 1fr) auto;
        align-items: center;
    }

    .bsl-row:has(> .bsl-col .bsl-navlinks--menu) > .bsl-col {
        grid-column: auto;
    }

    /* The menu carries the region's Sign in/out, so the standalone block steps aside — and
       with it a Column that held nothing else, or it would leave an empty second line. */
    .bsl-section:has(.bsl-navlinks--menu-signin) .bsl-node--signin {
        display: none;
    }

    .bsl-row:has(.bsl-navlinks--menu-signin) > .bsl-col:has(> .bsl-node--signin):not(:has(> .bsl-node:not(.bsl-node--signin))) {
        display: none;
    }
}

/* Sign-in widget (site chrome): the button, or the signed-in learner + sign-out. */
.bsl-signin__button {
    display: inline-block;
    white-space: nowrap; /* never "Sign / in" in a narrow column */
    text-decoration: none;
    font-weight: 700;
    color: var(--on-brand, white);
    background: var(--brand-primary, var(--mud-palette-primary));
    padding: 0.45rem 0.9rem;
    border-radius: 0.55rem;
}

.bsl-signin--in {
    display: inline-flex;
    align-items: center;
    gap: 0.9rem;
}

.bsl-signin__learner {
    color: var(--ink-soft, inherit);
    font-weight: 600;
}

.bsl-signin__signout {
    display: inline;
    margin: 0;
}

.bsl-signin__link {
    border: 0;
    background: none;
    padding: 0;
    font: inherit;
    font-weight: 600;
    color: inherit;
    cursor: pointer;
}

.bsl-signin__link:hover {
    color: var(--brand-primary, var(--mud-palette-primary));
}

/* Copyright block (BlockKind.Footer; 2026-09-21): what is left of the old all-in-one footer
   widget — a quiet text line. Its colour is the nearest Style › Text colour when one is set
   (its own node's, or the footer band's), else muted ink. */
.bsl-copyright {
    margin: 0;
    font-size: 0.875rem;
    color: var(--bsl-text, var(--ink-soft, var(--mud-palette-text-secondary)));
}

/* Social media block (2026-09-21): the org's profiles as brand icons, icons with names, or
   names. The glyphs are drawn in currentColor, so Style › Text colour colours them; the row
   follows Style › Text align through --bsl-place. */
.bsl-social {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: var(--bsl-place, flex-start);
    gap: 0.6rem 0.9rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

.bsl-social__item {
    display: inline-flex;
}

.bsl-social__link {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: inherit;
    text-decoration: none;
    font-weight: 600;
    font-size: 0.875rem;
    transition: color var(--motion-fast, 120ms) var(--ease-out, ease);
}

.bsl-social__link:hover {
    color: var(--brand-primary, var(--mud-palette-primary));
}

.bsl-social__icon {
    flex: none;
    width: 1.25rem;
    height: 1.25rem;
}

/* Icon-only links get a finger-sized target around the glyph. */
.bsl-social--icons .bsl-social__link {
    padding: 0.2rem;
}

/* "Powered by Quorcel" strip (2026-09-21): the fixed last line of an org site's footer — not
   a block, so nothing an author styles reaches it. Quorcel's neutral ink on the page surface,
   hairline above, centred. */
.bsl-poweredby {
    display: flex;
    justify-content: center;
    padding: 0.6rem 1.2rem;
    border-top: 1px solid var(--line, var(--mud-palette-lines-default));
    font-size: 0.78rem;
    color: var(--ink-faint, var(--mud-palette-text-secondary));
}

/* Logo widget (landing pages): the org's stored logo at the authored width; the empty
   fallback shows the org name so the block still reads on an unbranded site. */
.bsl-logo__home {
    display: inline-block;
    vertical-align: top; /* no descender gap under the image: the block is as tall as the logo */
    color: inherit;
    text-decoration: none;
}

.bsl-logo {
    display: block;
    height: auto;
}

.bsl-logo--empty {
    font-weight: 700;
    font-size: 1.25rem;
    color: var(--ink, inherit);
}

/* ── Batch C landing blocks (2026-09-16): Button · Feature cards · Testimonial · FAQ ·
   Divider · Stats. Org brand tokens with MudBlazor palette fallbacks, like the widgets above. */

.bsl-button-wrap {
    margin: 0;
    text-align: var(--bsl-ta, left);
}

/* A Button is an intrinsic-width control, not a full-width band: the Style tab's Text and
   Background colours paint the BUTTON (lifted here from the node's own --bsl-color /
   --bsl-bg into inheriting --bsl-btn-* properties) and the node around it stays transparent
   (user call 2026-09-17). Padding / margin / alignment on the node still place the button. */
.bsl-node--block:has(.bsl-button-wrap) {
    --bsl-btn-color: var(--bsl-color);
    --bsl-btn-bg: var(--bsl-bg);
    --bsl-btn-shadow: var(--bsl-shadow);
    background: transparent;
    box-shadow: none;
}

.bsl-button {
    display: inline-flex;
    align-items: center;
    padding: 0.7rem 1.4rem;
    border-radius: 0.6rem;
    border: 2px solid transparent;
    background: var(--bsl-btn-bg, var(--brand-accent, var(--mud-palette-secondary)));
    box-shadow: var(--bsl-btn-shadow, none);
    color: var(--bsl-btn-color, var(--on-brand, white));
    font-weight: 700;
    text-decoration: none;
}

.bsl-button--secondary {
    background: var(--bsl-btn-bg, transparent);
    border-color: currentColor;
    color: var(--bsl-btn-color, var(--brand-primary, var(--mud-palette-primary)));
}

.bsl-button--link {
    padding: 0;
    background: var(--bsl-btn-bg, transparent);
    color: var(--bsl-btn-color, var(--brand-primary, var(--mud-palette-primary)));
}

.bsl-button:hover {
    filter: brightness(1.08);
}

/* The FAQ heading is an h2 and reads the H2 preset (family, size, weight, colour …) with the
   Heading block above — the Organisation / Course Theme governs it (2026-09-18). */
.bsl-faq__heading {
    margin: 0 0 1rem;
}


/* ── Icon block (2026-09-17): a curated icon (inline SVG in currentColor, so the node's
   Style › Text colour colours it) or an emoji, at the authored size; sits in the text
   alignment like the Button. Icon + Heading + Text in a styled Column = a feature card. */
.bsl-icon-wrap {
    margin: 0;
    line-height: 1;
    text-align: var(--bsl-ta, left);
}

.bsl-icon {
    display: inline-block;
    vertical-align: top; /* no baseline gap: the block is as tall as the icon */
    font-size: var(--bsl-icon-size, 2rem);
    line-height: 1;
}

.bsl-icon--svg svg {
    display: block;
    width: 1em;
    height: 1em;
}

/* Testimonials side by side are the same height (user call 2026-09-29): a Row stretches its
   Columns to the tallest, and the card fills its Column rather than hugging its own quote. A
   Column holding other blocks too shares the spare room with the card only. The builder
   canvas wraps a block's preview in one more element, so that wrapper passes the height on. */
.bsl-col > .bsl-node--block:has(.bsl-testimonial) {
    flex: 1;
}

.bsl-col > .bsl-node--block:has(.bsl-testimonial),
.bsl-col > .bsl-node--block > :has(> .bsl-testimonial) {
    display: flex;
    flex-direction: column;
}

.bsl-col > .bsl-node--block > :has(> .bsl-testimonial),
.bsl-col > .bsl-node--block .bsl-testimonial {
    flex: 1;
}

.bsl-testimonial {
    margin: 0;
    padding: 1.6rem 1.8rem;
    border-left: 4px solid var(--brand-accent, var(--mud-palette-secondary));
    border-radius: 0 1rem 1rem 0;
    background: var(--surface-muted, var(--mud-palette-background-gray));
}

.bsl-testimonial__quote {
    margin: 0 0 1rem;
    font-size: 1.15rem;
    line-height: 1.5;
}

.bsl-testimonial__quote::before {
    content: "“";
}

.bsl-testimonial__quote::after {
    content: "”";
}

.bsl-testimonial__by {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    font-size: 0.9rem;
}

.bsl-testimonial__photo {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    object-fit: cover;
}

.bsl-testimonial__name {
    font-weight: 700;
}

.bsl-testimonial__role {
    color: var(--ink-faint, var(--mud-palette-text-secondary));
}

/* An FAQ item is a hairline-separated row: a generous, hoverable question line with the
   product's chevron at its end (turned over when open), and the answer beneath in readable
   measure. Colours (Alan, 2026-09-18): Style › Colour offers Title / Question / Answer (and
   Background) for an FAQ in place of Text — --bsl-faq-title/-q/-a on the section; unset, the
   theme's H2 colour, the inherited ink, brand primary for the chevron and ink-soft for answers. */
.bsl-faq .bsl-faq__heading {
    color: var(--bsl-faq-title, var(--bsl-text, var(--type-h2-colour, inherit)));
}

.bsl-faq__item {
    border-top: 1px solid var(--line, var(--mud-palette-lines-default));
}

.bsl-faq__item:last-child {
    border-bottom: 1px solid var(--line, var(--mud-palette-lines-default));
}

.bsl-faq__q {
    cursor: pointer;
    font-weight: 700;
    list-style: none;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    padding: 0.9rem 0;
    color: var(--bsl-faq-q, inherit);
    transition: color var(--motion-fast, 120ms) var(--ease-out, ease);
}

.bsl-faq__q:hover {
    color: var(--bsl-faq-q, var(--brand-primary, var(--mud-palette-primary)));
}

.bsl-faq__q::-webkit-details-marker {
    display: none;
}

.bsl-faq__q-text {
    flex: 1;
    min-width: 0;
}

.bsl-faq__chevron {
    flex: none;
    display: inline-flex;
    width: 1.5rem;
    height: 1.5rem;
    color: var(--bsl-faq-q, var(--brand-primary, var(--mud-palette-primary)));
    transition: transform var(--motion-fast, 120ms) var(--ease-out, ease);
}

.bsl-faq__chevron svg {
    width: 100%;
    height: 100%;
}

.bsl-faq__item[open] .bsl-faq__chevron {
    transform: rotate(180deg);
}

.bsl-faq__a {
    margin: 0 0 1rem;
    max-width: 70ch;
    line-height: 1.6;
    color: var(--bsl-faq-a, var(--ink-soft, var(--mud-palette-text-secondary)));
}

/* The line takes the nearest Style › Text colour (the divider's own, or the band's around
   it), so a divider on a dark band is not drawn in the light theme's hairline (2026-09-29). */
.bsl-divider {
    border: 0;
    border-top: 2px solid var(--bsl-text, var(--line, var(--mud-palette-lines-default)));
    margin: 0.5rem 0;
}

.bsl-divider--dashed {
    border-top-style: dashed;
}

.bsl-divider--dotted {
    border-top-style: dotted;
}

/* Stats: the numbers and their labels are coloured in Style › Colour (Value / Label, in
   place of Text — Alan, 2026-09-21) through --bsl-stats-value / -label on the list; unset,
   the numbers are brand primary and the labels muted ink (--ink-soft, a colour the picker
   offers, so the unset row can show it). */
.bsl-stats {
    display: flex;
    flex-wrap: wrap;
    justify-content: var(--bsl-place, center);
    gap: 1.5rem 3rem;
    margin: 0;
}

/* The number is drawn above its label but comes second in the markup, hence column-reverse —
   which packs from the BOTTOM. When one label of a row wraps, that stat is taller and the
   others dropped to the foot of the row, their numbers out of line (user report 2026-09-29).
   flex-end is the top of a reversed column: every number of a row sits on one line. */
.bsl-stats__item {
    display: flex;
    flex-direction: column-reverse;
    justify-content: flex-end;
    align-items: center;
    text-align: center;
}

/* On a narrow container the stats wrap onto several rows. As a wrapping flex row each row was
   centred on its own, so a stat sat a little left or right of the one under it (user report
   2026-09-29). A grid of equal tracks keeps the columns in line; empty tracks collapse, so
   one or two stats still sit in the middle. */
@container (max-width: 640px) {
    .bsl-stats {
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
        justify-items: var(--bsl-place, center);
        gap: 1.5rem 1rem;
    }
}

.bsl-stats__value {
    margin: 0;
    /* cqi, not vw: the size follows the page's container, so the builder's phone canvas
       draws the number a phone draws, not the one the browser window's width gives. */
    font-size: clamp(1.8rem, 3.5cqi, 2.6rem);
    font-weight: 800;
    line-height: 1.1;
    color: var(--bsl-stats-value, var(--brand-primary, var(--mud-palette-primary)));
}

.bsl-stats__label {
    font-size: 0.85rem;
    font-weight: 400; /* a <dt> is bold in the host reset; the label is the quiet line */
    color: var(--bsl-stats-label, var(--ink-soft, var(--mud-palette-text-secondary)));
}
