/* =====================================================================
   Storefront theme.

   Flat and roomy, unlike the dense ERP shell: this is the public
   marketplace and it should read as a shop, not as an admin tool.
   Loaded instead of app.css, never alongside it.

   Two palettes. Dark is the default — it matches the rest of the group's
   presence and it is what the brand looks like — and a visitor can
   switch to light from the header. Every colour below is a token, and
   the dark block redefines the tokens ONLY. No rule anywhere else in
   this file names a colour directly, which is what makes the two themes
   impossible to drift apart: there is exactly one place to change.
   ===================================================================== */

:root,
[data-bb-theme="dark"] {
    --bb-bg:          #0e1014;
    --bb-surface:     #171a20;
    --bb-surface-2:   #1e222a;
    --bb-line:        #272c35;
    --bb-line-strong: #363c47;

    --bb-ink:         #eceef2;
    --bb-ink-2:       #a2a9b5;
    /* Not dimmer than this: --bb-ink-3 carries timestamps and stock
       counts at 12–13px, and it has to clear 4.5:1 on a card. */
    --bb-ink-3:       #868d99;

    /*
     * The AVR Crest identity: the logo is not one colour but a ramp,
     * deep royal blue on the left through cyan and teal to bright green
     * on the right. These five are the logo's own values.
     *
     *   #0E3E98  deep royal blue
     *   #156BB7  medium blue
     *   #1C92B5  cyan / aqua
     *   #3CB489  teal green
     *   #63D35C  bright green
     *
     * The gradient below runs the full length of that ramp, in the same
     * direction the mark does.
     */
    --bb-brand-1:     #0E3E98;
    --bb-brand-2:     #1C92B5;
    --bb-brand-3:     #63D35C;
    --bb-gradient:    linear-gradient(135deg, var(--bb-brand-1) 0%, var(--bb-brand-2) 55%, var(--bb-brand-3) 100%);
    /*
     * The same identity, deepened, for anything that carries text.
     * White on the logo's own cyan is 3.60:1 and on its bright green
     * about 2:1 — both well under AA — so buttons and tags ride these
     * stops instead. Worst point here is 5.17:1 against white.
     */
    --bb-gradient-cta: linear-gradient(135deg, #0E3E98 0%, #0F6E8A 55%, #1A7D46 100%);
    --bb-gradient-soft: linear-gradient(135deg, rgba(21, 107, 183, .18), rgba(60, 180, 137, .16));

    /*
     * Gradient TEXT, which needs the opposite treatment to a gradient
     * fill: the ink sits on the dark hero, so the stops go lighter, not
     * deeper. The brand ramp's blue end is 1.3:1 on the hero — invisible
     * — and the headline is the one line on the page nobody should have
     * to squint at. Worst point here is 7.9:1.
     */
    --bb-gradient-head: linear-gradient(135deg, #8AB6FF 0%, #6FD8E8 55%, #8CE99A 100%);
    --bb-gradient-head-fallback: #6FD8E8;

    /*
     * The accent is a FILL that carries white text — avatars, badges,
     * active chips. The logo's medium blue does that job at 5.50:1,
     * which is why it and not the cyan is the interface colour.
     *
     * Note the distinction from --bb-link below, which is text ON the
     * page and therefore has to go the other way, lighter.
     */
    --bb-accent:      #156BB7;
    --bb-accent-hover: #0E3E98;
    --bb-accent-ink:  #ffffff;
    --bb-accent-soft: rgba(28, 146, 181, .18);
    --bb-link:        #7FC4E8;

    /* The price is the number people scan a grid for, so it gets its
       own colour rather than sharing body ink — and the logo's bright
       green is both the most distinctive value in the palette and a
       comfortable 9.98:1 here. */
    --bb-price-ink:   #63D35C;

    /* Deliberately outside the brand ramp. A markdown has to read as
       different from everything else on the page, and a green "sale" on
       a green-and-blue site says nothing at all. */
    --bb-sale:        #ff5c7d;
    --bb-sale-ink:    #1a0d11;
    --bb-ok:          #3CB489;
    --bb-warn:        #e0a13a;
    --bb-info:        #6FB6E8;

    /* Tinted backgrounds for tags, alerts and status pills, each with
       the ink that stays legible on it. */
    --bb-sale-soft:   #3a1a24;   --bb-sale-soft-ink:  #ff8da5;
    --bb-ok-soft:     #0e2f26;   --bb-ok-soft-ink:    #64d8ac;
    --bb-warn-soft:   #362a13;   --bb-warn-soft-ink:  #efc177;
    --bb-info-soft:   #12283c;   --bb-info-soft-ink:  #93c6ec;
    --bb-mute-soft:   #23272f;   --bb-mute-soft-ink:  #aab1bd;

    /* Blue on the left, green on the right — the mark, spread across a
       hero. */
    --bb-hero-from:   #101F42;
    --bb-hero-to:     #0E3226;
    --bb-hero-glow:   radial-gradient(680px 340px at 12% -20%, rgba(21, 107, 183, .55), transparent 62%),
                      radial-gradient(560px 320px at 88% 120%, rgba(99, 211, 92, .30), transparent 60%);

    --bb-avatar:      #3a4049;
    --bb-avatar-ink:  #ffffff;

    --bb-footer-bg:   #0a0c0f;
    --bb-footer-ink:  #9aa1ad;
    --bb-footer-head: #ffffff;
    --bb-footer-line: #232830;
    --bb-footer-faint: #7f8794;

    --bb-radius:      14px;
    --bb-radius-sm:   9px;
    --bb-shadow:      0 1px 2px rgba(0, 0, 0, .35), 0 6px 20px rgba(0, 0, 0, .30);
    --bb-shadow-lift: 0 4px 10px rgba(0, 0, 0, .40), 0 16px 40px rgba(0, 0, 0, .45);

    --bb-max:         1180px;

    color-scheme: dark;
}

[data-bb-theme="light"] {
    --bb-bg:          #eef0f3;
    --bb-surface:     #ffffff;
    --bb-surface-2:   #f7f8fa;
    --bb-line:        #e4e7ec;
    --bb-line-strong: #d3d8e0;

    --bb-ink:         #14161a;
    --bb-ink-2:       #4a5058;
    /*
     * Tuned against the PAGE background, not the card. #8b929c gave
     * 3.14:1 on white; #6d7480 fixed the card but still only reached
     * 4.12:1 on the slightly grey page behind it, which is where most
     * of this text actually sits. This clears AA on both.
     */
    --bb-ink-3:       #626976;

    /* The same five logo values — the identity does not change with the
       theme, only what has to be deepened to stay readable on white. */
    --bb-brand-1:     #0E3E98;
    --bb-brand-2:     #1C92B5;
    --bb-brand-3:     #63D35C;
    --bb-gradient:    linear-gradient(135deg, var(--bb-brand-1) 0%, var(--bb-brand-2) 55%, var(--bb-brand-3) 100%);
    /*
     * The same identity, deepened, for anything that carries text.
     * Worst point 5.17:1 against white.
     */
    --bb-gradient-cta: linear-gradient(135deg, #0E3E98 0%, #0F6E8A 55%, #1A7D46 100%);
    --bb-gradient-soft: linear-gradient(135deg, rgba(21, 107, 183, .12), rgba(60, 180, 137, .12));

    /* On the pale hero the headline goes the other way — deeper, not
       lighter. The logo's own cyan manages 2.9:1 here; these stops
       bottom out at 6.06:1. */
    --bb-gradient-head: linear-gradient(135deg, #0E3E98 0%, #0F6E8A 55%, #14713F 100%);
    --bb-gradient-head-fallback: #0F6E8A;

    /* Deeper than the dark theme's accent: the medium blue that reads
       comfortably on near-black is too light to carry white text on
       white, so the light theme uses the deep royal blue. */
    --bb-accent:      #0E3E98;
    --bb-accent-hover: #0A2E73;
    --bb-accent-ink:  #ffffff;
    --bb-accent-soft: rgba(14, 62, 152, .10);
    --bb-link:        #0E3E98;

    /* The bright green is 1.9:1 on white — unreadable. The price keeps
       its green identity by going deep instead: 6.06:1. */
    --bb-price-ink:   #14713F;

    /* Was #f0325a: pretty, but 3.96:1 as a price on white and no better
       behind white button text. Still deliberately off-brand — see the
       dark block. */
    --bb-sale:        #d81b48;
    --bb-sale-ink:    #ffffff;
    --bb-ok:          #12785C;
    --bb-warn:        #b26b00;
    --bb-info:        #1b4b8f;

    --bb-sale-soft:   #ffe9ee;   --bb-sale-soft-ink:  #b31f42;
    --bb-ok-soft:     #e3f5ee;   --bb-ok-soft-ink:    #0b6349;
    --bb-warn-soft:   #fff4e0;   --bb-warn-soft-ink:  #8a5300;
    --bb-info-soft:   #e8f1fb;   --bb-info-soft-ink:  #14468a;
    --bb-mute-soft:   #e9ecef;   --bb-mute-soft-ink:  #3d434b;

    --bb-hero-from:   #E8F1FB;
    --bb-hero-to:     #E6F7EE;
    --bb-hero-glow:   radial-gradient(680px 340px at 12% -20%, rgba(21, 107, 183, .22), transparent 62%),
                      radial-gradient(560px 320px at 88% 120%, rgba(60, 180, 137, .20), transparent 60%);

    --bb-avatar:      #575c65;
    --bb-avatar-ink:  #ffffff;

    --bb-footer-bg:   #14161a;
    --bb-footer-ink:  #a8aeb8;
    --bb-footer-head: #ffffff;
    --bb-footer-line: #2a2e35;
    --bb-footer-faint: #838a95;

    --bb-shadow:      0 1px 2px rgba(16, 20, 27, .05), 0 6px 20px rgba(16, 20, 27, .05);
    --bb-shadow-lift: 0 4px 10px rgba(16, 20, 27, .07), 0 16px 40px rgba(16, 20, 27, .10);

    color-scheme: light;
}

/*
 * Fixed in BOTH themes, declared once.
 *
 * The logo chip has no fill. It used to be white on the theory that
 * uploaded logos are drawn for white paper — but this group's artwork
 * carries its own dark backgrounds, so the white tile framed every one
 * of them in a bright rectangle the page never asked for.
 *
 * The hairline stays: with dark artwork on a dark page it is the only
 * thing holding the row together. The monogram fallback now follows the
 * theme, since there is no fixed surface left for it to contrast with.
 */
:root {
    --bb-logo-chip:     transparent;
    --bb-logo-chip-ink: var(--bb-ink-2);

    /*
     * Slideshow and hero-video dots, fixed for the same reason: they sit
     * on top of the media, not on the page, so they take their contrast
     * from a photograph rather than from the palette behind it.
     */
    --bb-dot:      #ffffff;
    --bb-dot-idle: rgba(255, 255, 255, .45);

    /*
     * Text and scrim laid over a photograph — the About banner. Same
     * reasoning again: a photo does not change with the theme, so the
     * ink that sits on it must not either. White on a dark scrim is
     * legible over any picture somebody uploads, which is more than can
     * be said for anything that follows the palette.
     */
    --bb-onmedia-ink:   #ffffff;
    --bb-onmedia-ink-2: rgba(255, 255, 255, .88);
    --bb-onmedia-scrim: linear-gradient(to top,
                            rgba(0, 0, 0, .78) 0%,
                            rgba(0, 0, 0, .30) 55%,
                            transparent 100%);
}

/* ------------------------------------------------------------------ */
/* Base                                                                */
/* ------------------------------------------------------------------ */

body.bb {
    background: var(--bb-bg);
    color: var(--bb-ink);
    font-family: Inter, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
    font-size: 15px;
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
}

.bb a { color: inherit; text-decoration: none; }
.bb a:hover { color: var(--bb-link); }

/* Tokenised so a full-bleed child can cancel exactly this much. */
:root { --bb-shell-pad: 16px; }

.bb-shell { max-width: var(--bb-max); margin: 0 auto; padding: 0 var(--bb-shell-pad); }

.bb-mono { font-family: ui-monospace, SFMono-Regular, Menlo, monospace; }
.bb-muted { color: var(--bb-ink-2); }
.bb-faint { color: var(--bb-ink-3); }

.bb-card {
    background: var(--bb-surface);
    border-radius: var(--bb-radius);
    box-shadow: var(--bb-shadow);
}

.bb-section { margin: 22px 0; }

.bb-section-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
    flex-wrap: wrap;
}

.bb-section-head h2 {
    font-size: 1.15rem;
    font-weight: 700;
    margin: 0;
    letter-spacing: -.01em;
    display: flex;
    align-items: center;
    gap: 9px;
}

/* A short brand bar, so a heading reads as a section marker rather
   than as another line of bold text. */
.bb-section-head h2::before {
    content: '';
    width: 4px;
    height: 1.05em;
    border-radius: 999px;
    background: var(--bb-gradient);
    flex-shrink: 0;
}

/* ------------------------------------------------------------------ */
/* Buttons                                                             */
/* ------------------------------------------------------------------ */

.bb-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 7px;
    padding: 9px 18px;
    border-radius: 999px;
    border: 1px solid transparent;
    font-size: .86rem;
    font-weight: 600;
    line-height: 1.2;
    cursor: pointer;
    transition: background .15s ease, border-color .15s ease, transform .1s ease, opacity .15s ease;
    white-space: nowrap;
}

.bb-btn:active { transform: translateY(1px); }
.bb-btn:disabled, .bb-btn[disabled] { opacity: .5; cursor: not-allowed; }

/* Anchors styled as buttons need to out-specify the `.bb a` reset above,
   which is why every rule is repeated for `a.` — without it a link
   button inherits the page text colour and vanishes on a dark fill. */

.bb-btn-primary, .bb a.bb-btn-primary {
    background: var(--bb-gradient-cta);
    color: var(--bb-accent-ink);
    box-shadow: 0 2px 10px rgba(124, 58, 237, .28);
}
.bb-btn-primary:hover, .bb a.bb-btn-primary:hover {
    filter: brightness(1.08) saturate(1.05);
    color: var(--bb-accent-ink);
    box-shadow: 0 4px 16px rgba(124, 58, 237, .38);
}

.bb-btn-outline, .bb a.bb-btn-outline {
    background: transparent;
    border-color: var(--bb-line-strong);
    color: var(--bb-ink);
}
.bb-btn-outline:hover, .bb a.bb-btn-outline:hover { background: var(--bb-surface-2); color: var(--bb-ink); }

.bb-btn-ghost, .bb a.bb-btn-ghost { background: transparent; color: var(--bb-ink-2); }
.bb-btn-ghost:hover, .bb a.bb-btn-ghost:hover { background: var(--bb-surface-2); color: var(--bb-ink); }

.bb-btn-danger, .bb a.bb-btn-danger { background: var(--bb-sale); color: var(--bb-sale-ink); }
.bb-btn-danger:hover, .bb a.bb-btn-danger:hover { filter: brightness(1.08); color: var(--bb-sale-ink); }

.bb-btn-sm { padding: 6px 13px; font-size: .79rem; }
.bb-btn-lg { padding: 12px 26px; font-size: .95rem; }
.bb-btn-block { width: 100%; }

/* ------------------------------------------------------------------ */
/* Top bar and header                                                  */
/* ------------------------------------------------------------------ */

.bb-topbar {
    background: var(--bb-surface);
    border-bottom: 1px solid var(--bb-line);
    font-size: .76rem;
    color: var(--bb-ink-2);
}

.bb-topbar .bb-shell {
    display: flex;
    align-items: center;
    gap: 18px;
    min-height: 34px;
    flex-wrap: wrap;
}

.bb-topbar a:hover { color: var(--bb-ink); text-decoration: underline; }

.bb-theme-toggle {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 3px 10px;
    border: 1px solid var(--bb-line-strong);
    border-radius: 999px;
    background: transparent;
    color: var(--bb-ink-2);
    font-size: .74rem;
    font-weight: 600;
    line-height: 1.6;
    cursor: pointer;
    transition: background .15s ease, color .15s ease, border-color .15s ease;
}

.bb-theme-toggle:hover {
    background: var(--bb-surface-2);
    color: var(--bb-ink);
    border-color: var(--bb-ink-3);
}

.bb-theme-toggle:focus-visible {
    outline: 2px solid var(--bb-ink-2);
    outline-offset: 2px;
}

.bb-header {
    background: var(--bb-surface);
    border-bottom: 1px solid var(--bb-line);
    position: sticky;
    top: 0;
    z-index: 1030;
}

.bb-header .bb-shell {
    display: flex;
    align-items: center;
    gap: 14px;
    min-height: 62px;
}

.bb-logo {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-weight: 800;
    font-size: 1.06rem;
    letter-spacing: -.02em;
    flex-shrink: 0;
}

.bb-logo-mark {
    width: 26px;
    height: 26px;
    border-radius: 8px;
    background: var(--bb-gradient);
    color: var(--bb-accent-ink);
    display: grid;
    place-items: center;
    font-size: .82rem;
}

/* Search */
.bb-search { flex: 1 1 auto; position: relative; min-width: 0; }

.bb-search-form {
    display: flex;
    align-items: stretch;
    border: 1px solid var(--bb-line-strong);
    border-radius: 999px;
    background: var(--bb-surface);
    overflow: hidden;
}

.bb-search-form:focus-within { border-color: var(--bb-ink-3); }

.bb-search-branch {
    border: 0;
    background: var(--bb-surface-2);
    font-size: .8rem;
    color: var(--bb-ink-2);
    padding: 0 12px;
    max-width: 190px;
    border-right: 1px solid var(--bb-line);
    cursor: pointer;
}

.bb-search-input {
    border: 0;
    outline: 0;
    flex: 1 1 auto;
    padding: 9px 14px;
    font-size: .86rem;
    min-width: 0;
    background: transparent;
}

.bb-search-btn {
    border: 0;
    background: transparent;
    padding: 0 15px;
    color: var(--bb-ink-2);
    cursor: pointer;
}

.bb-suggest {
    position: absolute;
    top: calc(100% + 6px);
    left: 0;
    right: 0;
    background: var(--bb-surface);
    border-radius: var(--bb-radius-sm);
    box-shadow: var(--bb-shadow-lift);
    overflow: hidden;
    z-index: 40;
    display: none;
}

.bb-suggest.is-open { display: block; }

.bb-suggest a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 13px;
    font-size: .84rem;
    border-bottom: 1px solid var(--bb-line);
}

.bb-suggest a:last-child { border-bottom: 0; }
.bb-suggest a:hover { background: var(--bb-surface-2); }

.bb-suggest img {
    width: 32px; height: 32px; object-fit: cover;
    border-radius: 6px; background: var(--bb-surface-2);
}

/* Header actions */
.bb-actions { display: flex; align-items: center; gap: 4px; flex-shrink: 0; }

.bb-icon-btn {
    position: relative;
    width: 38px; height: 38px;
    display: grid; place-items: center;
    border-radius: 10px;
    color: var(--bb-ink-2);
    font-size: 1.08rem;
}

.bb-icon-btn:hover { background: var(--bb-surface-2); color: var(--bb-ink); }

.bb-badge-count {
    position: absolute;
    top: 3px; right: 2px;
    min-width: 17px; height: 17px;
    padding: 0 4px;
    border-radius: 999px;
    background: var(--bb-sale);
    color: var(--bb-accent-ink);
    font-size: .64rem;
    font-weight: 700;
    display: grid; place-items: center;
    line-height: 1;
}

/* ------------------------------------------------------------------ */
/* Hero                                                                */
/* ------------------------------------------------------------------ */

.bb-hero {
    background:
        var(--bb-hero-glow),
        linear-gradient(120deg, var(--bb-hero-from) 0%, var(--bb-hero-to) 100%);
    border-radius: var(--bb-radius);
    overflow: hidden;
    display: grid;
    grid-template-columns: 1.1fr .9fr;
    align-items: center;
    min-height: 230px;
    box-shadow: var(--bb-shadow);
}

.bb-hero-copy { padding: 34px 38px; }

.bb-hero-eyebrow {
    display: inline-block;
    font-size: .72rem;
    font-weight: 800;
    letter-spacing: .08em;
    text-transform: uppercase;
    color: var(--bb-accent-ink);
    background: var(--bb-gradient-cta);
    padding: 4px 11px;
    border-radius: 999px;
    margin-bottom: 10px;
}

.bb-hero h1 {
    font-size: 2.05rem;
    font-weight: 800;
    line-height: 1.14;
    letter-spacing: -.03em;
    margin: 0 0 10px;
}

.bb-hero h1 em {
    font-style: italic;
    /* The heading ramp, not the brand ramp — see the token. The fallback
       colour matters too: if background-clip is unsupported the word has
       to stay readable, not vanish. */
    color: var(--bb-gradient-head-fallback);
    background: var(--bb-gradient-head);
    -webkit-background-clip: text;
    background-clip: text;
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
    .bb-hero h1 em { color: transparent; }
}

.bb-hero p { color: var(--bb-ink-2); font-size: .9rem; margin: 0 0 18px; }

.bb-hero-art {
    align-self: stretch;
    background: var(--bb-gradient);
    display: grid;
    place-items: center;
    color: var(--bb-accent-ink);
    font-size: 3.4rem;
    /* Softens the hard edge between the wash and the block. */
    mask-image: linear-gradient(to right, transparent, black 22%);
    -webkit-mask-image: linear-gradient(to right, transparent, black 22%);
}

/*
 * The video panel.
 *
 * No mask here: a soft-edged video reads as a rendering fault rather
 * than a design, and the footage already has its own edges.
 */
.bb-hero-art-video {
    position: relative;
    overflow: hidden;
    background: var(--bb-surface-2);
    mask-image: none;
    -webkit-mask-image: none;
    min-height: 260px;
}

.bb-hero-art-video video,
.bb-hero-art-video iframe {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    /* Fill the panel whatever the clip's aspect ratio is, rather than
       letterboxing an arbitrary upload. */
    object-fit: cover;
    border: 0;
    display: block;
}

/* A brand-tinted veil, so the hero copy keeps its contrast against
   footage nobody has colour-graded for this layout. */
.bb-hero-art-veil {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background: linear-gradient(
        100deg,
        var(--bb-hero-to) 0%,
        rgba(124, 58, 237, .28) 38%,
        transparent 72%
    );
}

@media (max-width: 767.98px) {
    /*
     * Stacked under the copy, the panel takes the clip's own shape.
     *
     * A fixed 190px strip was both small and the wrong proportion, so
     * object-fit: cover trimmed the sides of a 16:9 clip to fill it.
     * An explicit 16:9 box shows the whole frame with nothing cropped,
     * and comes out taller into the bargain.
     *
     * width and align-self are spelled out so aspect-ratio can only be
     * resolved one way round: height FROM width. .bb-hero-art sets
     * align-self: stretch for the desktop layout, where the panel sits
     * beside the copy and has to match its height. Stretched, the item
     * also has a DEFINITE height, and WebKit will resolve the aspect
     * ratio from that instead — giving a box roughly half the column
     * wide with the hero gradient showing beside it. Blink resolves it
     * the way we meant, so this only ever appeared on an iPhone.
     *
     * Written as .bb-hero-art.bb-hero-art-video rather than relying on
     * source order: the plain .bb-hero-art rule further down this file
     * sets its own min-height at equal specificity and would otherwise
     * win simply by coming later.
     */
    .bb-hero-art.bb-hero-art-video {
        align-self: start;
        justify-self: stretch;
        width: 100%;
        min-height: 0;
        aspect-ratio: 16 / 9;
    }

    /*
     * The veil has to fade DOWNWARDS here.
     *
     * It exists to keep the hero copy readable over arbitrary footage,
     * and at 100deg it does that on the desktop layout, where the copy
     * sits to the left of the video. Stacked, that same angle lays an
     * almost opaque wash over the left 40% of the picture while the
     * copy it was protecting is somewhere above — so most of the video
     * was hidden behind a gradient guarding nothing.
     */
    .bb-hero-art-video .bb-hero-art-veil {
        background: linear-gradient(
            to bottom,
            var(--bb-hero-to) 0%,
            rgba(124, 58, 237, .20) 22%,
            transparent 52%
        );
    }
}

/*
 * On a phone the hero runs to both edges.
 *
 * A 16:9 clip can only get bigger by getting wider — its height is
 * decided by the panel width — and the 16px of shell padding either
 * side was the only thing left to give. Cancelling it is worth about a
 * fifth more picture, and a full-bleed hero is the right look on a
 * phone anyway.
 */
@media (max-width: 575.98px) {
    .bb-hero {
        margin-left: calc(-1 * var(--bb-shell-pad));
        margin-right: calc(-1 * var(--bb-shell-pad));
        border-radius: 0;
    }
}

/* Which clip is playing, when there is more than one. */
.bb-hero-dots {
    position: absolute;
    bottom: 12px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 7px;
    z-index: 2;
}

.bb-hero-dot,
.bb-collect-dot {
    width: 8px;
    height: 8px;
    padding: 0;
    border: 0;
    border-radius: 999px;
    background: var(--bb-dot-idle);
    cursor: pointer;
    transition: background .2s ease, width .2s ease;
}

.bb-hero-dot.is-active,
.bb-collect-dot.is-active {
    background: var(--bb-dot);
    width: 20px;
}

.bb-hero-dot:focus-visible,
.bb-collect-dot:focus-visible {
    outline: 2px solid var(--bb-dot);
    outline-offset: 2px;
}

/* ------------------------------------------------------------------ */
/* Collect in Store card                                               */
/* ------------------------------------------------------------------ */

.bb-collect {
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--bb-surface-2);
}

.bb-collect-slides {
    position: relative;
    /* A fixed ratio keeps the card the same height whatever people
       upload, so the row beside it does not jump around. */
    aspect-ratio: 4 / 3;
    background: var(--bb-gradient-soft);
    overflow: hidden;
    flex-shrink: 0;
}

.bb-collect-slide {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity .6s ease;
}

.bb-collect-slide.is-active { opacity: 1; }

.bb-collect-empty {
    display: grid;
    place-items: center;
    color: var(--bb-brand-2);
    font-size: 2.6rem;
}

.bb-collect-dots {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 6px;
    z-index: 2;
}

.bb-collect-copy {
    padding: 22px 24px 26px;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    flex: 1;
    justify-content: center;
}

.bb-collect-copy h3 {
    font-size: 1.3rem;
    font-weight: 800;
    margin: 0;
}

.bb-collect-copy p { font-size: .85rem; margin: 0; }

@media (prefers-reduced-motion: reduce) {
    .bb-collect-slide { transition: none; }
}

@media (max-width: 767.98px) {
    .bb-hero { grid-template-columns: 1fr; }
    .bb-hero-copy { padding: 24px 20px; }
    .bb-hero h1 { font-size: 1.5rem; }
    .bb-hero-art { min-height: 120px; font-size: 2.2rem; }
}

/* ------------------------------------------------------------------ */
/* Category strip                                                      */
/* ------------------------------------------------------------------ */

.bb-cats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(84px, 1fr));
    gap: 6px;
    padding: 16px 8px;
}

.bb-cat {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    padding: 8px 4px;
    border-radius: var(--bb-radius-sm);
    font-size: .76rem;
    color: var(--bb-ink-2);
    text-align: center;
}

.bb a.bb-cat { color: var(--bb-ink-2); }
.bb-cat:hover, .bb a.bb-cat:hover { background: var(--bb-surface-2); color: var(--bb-ink); }

.bb-cat-icon {
    width: 52px; height: 52px;
    border-radius: 50%;
    background: var(--bb-gradient-soft);
    display: grid; place-items: center;
    font-size: 1.3rem;
    color: var(--bb-brand-2);
    transition: background .18s ease, color .18s ease, transform .18s ease;
}

.bb-cat:hover .bb-cat-icon, .bb a.bb-cat:hover .bb-cat-icon {
    background: var(--bb-gradient);
    color: var(--bb-accent-ink);
    transform: translateY(-2px);
}

/* ------------------------------------------------------------------ */
/* Product cards                                                       */
/* ------------------------------------------------------------------ */

.bb-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(178px, 1fr));
    gap: 14px;
}

.bb-rail {
    display: grid;
    grid-auto-flow: column;
    grid-auto-columns: minmax(178px, 1fr);
    gap: 14px;
    overflow-x: auto;
    scroll-snap-type: x proximity;
    padding-bottom: 6px;
}

.bb-rail > * { scroll-snap-align: start; }

.bb-product {
    background: var(--bb-surface);
    border-radius: var(--bb-radius-sm);
    box-shadow: var(--bb-shadow);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    transition: box-shadow .15s ease, transform .15s ease;
    position: relative;
}

.bb-product:hover { box-shadow: var(--bb-shadow-lift); transform: translateY(-2px); }

.bb-product-media {
    position: relative;
    aspect-ratio: 1 / 1;
    background: var(--bb-surface-2);
    display: grid;
    place-items: center;
    overflow: hidden;
}

.bb-product-media img { width: 100%; height: 100%; object-fit: cover; }
.bb-product-media .bi { font-size: 2rem; color: var(--bb-line-strong); }

.bb-product-body { padding: 11px 12px 13px; display: flex; flex-direction: column; gap: 5px; flex: 1 1 auto; }

.bb-product-name {
    font-size: .84rem;
    font-weight: 500;
    line-height: 1.32;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
    /* Reserve both lines so a one-line name does not shorten its card
       and leave the price row misaligned against its neighbours. */
    min-height: 2.64em;
}

.bb-price {
    font-size: .98rem;
    font-weight: 800;
    letter-spacing: -.01em;
    color: var(--bb-price-ink);
}
.bb-price-was { font-size: .74rem; color: var(--bb-ink-3); text-decoration: line-through; margin-left: 5px; }

.bb-meta { font-size: .71rem; color: var(--bb-ink-3); display: flex; align-items: center; gap: 5px; }

/* The stock line is the card's last row; pinning it to the bottom keeps
   every tile in a grid row ending on the same baseline. */
.bb-product-body > .bb-meta:last-child { margin-top: auto; }

.bb-heart {
    position: absolute;
    top: 8px; right: 8px;
    width: 30px; height: 30px;
    border-radius: 50%;
    border: 0;
    background: rgba(255, 255, 255, .92);
    box-shadow: 0 1px 4px rgba(16, 20, 27, .16);
    display: grid; place-items: center;
    color: var(--bb-ink-3);
    cursor: pointer;
    z-index: 2;
    font-size: .84rem;
}

.bb-heart:hover { color: var(--bb-sale); }
.bb-heart.is-saved { color: var(--bb-sale); }

.bb-tag {
    display: inline-flex;
    align-items: center;
    gap: 4px;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: .66rem;
    font-weight: 700;
    letter-spacing: .02em;
}

.bb-tag-sale { background: var(--bb-sale-soft); color: var(--bb-sale-soft-ink); }
.bb-tag-out  { background: var(--bb-mute-soft); color: var(--bb-ink-3); }
.bb-tag-low  { background: var(--bb-warn-soft); color: var(--bb-warn-soft-ink); }
.bb-tag-ok   { background: var(--bb-ok-soft); color: var(--bb-ok-soft-ink); }
.bb-tag-age  { background: var(--bb-accent); color: var(--bb-accent-ink); }

.bb-product-media .bb-tag { position: absolute; left: 8px; top: 8px; z-index: 2; }

/* Stock meter, as on the flash-sale cards */
.bb-meter { height: 5px; border-radius: 999px; background: var(--bb-surface-2); overflow: hidden; }
.bb-meter > span { display: block; height: 100%; border-radius: 999px; background: var(--bb-accent); }
.bb-meter.is-low > span { background: var(--bb-sale); }

/* Out-of-stock cards stay clickable but visibly inert */
.bb-product.is-out .bb-product-media img { opacity: .45; filter: grayscale(1); }

/* The product page's main image. Capped so the buy box stays above the
   fold on a narrow window instead of being pushed off by a square. */
.bb-product-hero {
    aspect-ratio: 1 / 1;
    max-height: 420px;
    border-radius: var(--bb-radius-sm);
}

/* ------------------------------------------------------------------ */
/* Chips / filters                                                     */
/* ------------------------------------------------------------------ */

.bb-chips { display: flex; gap: 8px; flex-wrap: wrap; }

.bb-chip {
    padding: 6px 14px;
    border-radius: 999px;
    border: 1px solid var(--bb-line-strong);
    background: var(--bb-surface);
    font-size: .79rem;
    font-weight: 500;
    color: var(--bb-ink-2);
    cursor: pointer;
}

.bb a.bb-chip { color: var(--bb-ink-2); }
.bb-chip:hover, .bb a.bb-chip:hover { background: var(--bb-surface-2); color: var(--bb-ink); }

.bb-chip.is-active, .bb a.bb-chip.is-active,
.bb a.bb-chip.is-active:hover {
    background: var(--bb-accent);
    border-color: var(--bb-accent);
    color: var(--bb-accent-ink);
}

/* ------------------------------------------------------------------ */
/* Forms                                                               */
/* ------------------------------------------------------------------ */

.bb-label {
    display: block;
    font-size: .78rem;
    font-weight: 600;
    color: var(--bb-ink-2);
    margin-bottom: 5px;
}

.bb-req { color: var(--bb-sale); }

.bb-input, .bb-select, .bb-textarea {
    width: 100%;
    padding: 9px 13px;
    border: 1px solid var(--bb-line-strong);
    border-radius: var(--bb-radius-sm);
    background: var(--bb-surface);
    font-size: .87rem;
    color: var(--bb-ink);
    font-family: inherit;
}

.bb-input:focus, .bb-select:focus, .bb-textarea:focus {
    outline: 0;
    border-color: var(--bb-ink);
    box-shadow: 0 0 0 3px rgba(20, 22, 26, .07);
}

.bb-input.is-invalid, .bb-select.is-invalid { border-color: var(--bb-sale); }

.bb-help { font-size: .74rem; color: var(--bb-ink-3); margin-top: 4px; }
.bb-error { font-size: .74rem; color: var(--bb-sale); margin-top: 4px; }

.bb-check { display: flex; align-items: flex-start; gap: 9px; font-size: .83rem; }
.bb-check input { margin-top: 3px; width: 16px; height: 16px; flex-shrink: 0; accent-color: var(--bb-accent); }

/* ------------------------------------------------------------------ */
/* Logo tiles — product brands and the group's companies               */
/* ------------------------------------------------------------------ */

.bb-brandtile {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 8px;
    text-align: center;
    flex: 0 0 auto;
}

/* Unfilled — see --bb-logo-chip for why the white tile went away. */
.bb-brandtile-chip {
    display: grid;
    place-items: center;
    background: var(--bb-logo-chip);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius-sm);
    overflow: hidden;
    transition: border-color .15s ease, transform .12s ease, box-shadow .15s ease;
}

.bb-brandtile-chip img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    /* Breathing room so a square logo does not touch the edges. */
    padding: 10%;
}

/*
 * Artwork only.
 *
 * No hairline and no inset, for logos that already carry their own
 * background — a frame there is just a box drawn around a box, and the
 * padding shrinks the logo to buy space the gap between tiles already
 * provides. object-fit keeps the aspect ratio, so a wordmark still gets
 * the full width of its tile without being stretched to fill it.
 */
.bb-brandtile-bare .bb-brandtile-chip {
    border: 0;
    background: none;
}

a.bb-brandtile-bare:hover .bb-brandtile-chip {
    border-color: transparent;
    box-shadow: none;
}

.bb-brandtile-initials {
    font-weight: 800;
    letter-spacing: .02em;
    color: var(--bb-logo-chip-ink);
}

a.bb-brandtile:hover .bb-brandtile-chip {
    border-color: var(--bb-ink-3);
    transform: translateY(-2px);
    box-shadow: var(--bb-shadow);
}

.bb-brandtile-caption {
    font-size: .76rem;
    font-weight: 600;
    color: var(--bb-ink-2);
    max-width: 100%;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

a.bb-brandtile:hover .bb-brandtile-caption { color: var(--bb-ink); }

/*
 * Sizes stepped up across the board. At 46px a real wordmark — which is
 * what most of these are, not a square icon — shrinks to an unreadable
 * smudge, and the padding inside the chip eats it further.
 */
.bb-brandtile-sm .bb-brandtile-chip { width: 72px;  height: 72px; }
.bb-brandtile-sm .bb-brandtile-initials { font-size: 1.15rem; }
.bb-brandtile-sm .bb-brandtile-caption  { max-width: 104px; font-size: .74rem; }

.bb-brandtile-md .bb-brandtile-chip { width: 104px; height: 104px; }
.bb-brandtile-md .bb-brandtile-initials { font-size: 1.7rem; }
.bb-brandtile-md .bb-brandtile-caption  { max-width: 120px; }

.bb-brandtile-lg .bb-brandtile-chip { width: 132px; height: 132px; }
.bb-brandtile-lg .bb-brandtile-initials { font-size: 2.1rem; }
.bb-brandtile-lg .bb-brandtile-caption  { max-width: 156px; }

/* A wordmark is wider than it is tall, so the chip stops being a square
   where the logo is the point rather than the row's rhythm. */
.bb-brandtile-wide .bb-brandtile-chip {
    width: 152px;
    height: 84px;
}

.bb-brandtile-wide .bb-brandtile-chip img { padding: 12px 16px; }
.bb-brandtile-wide .bb-brandtile-initials { font-size: 1.6rem; }
.bb-brandtile-wide .bb-brandtile-caption  { max-width: 152px; }

/*
 * The bare inset override, deliberately AFTER every size variant.
 *
 * Each size sets its own img padding at the same specificity as this
 * rule, so declaring it up with the other .bb-brandtile-bare styles
 * loses to whichever size rule happens to come later in the file — the
 * frame disappears but the logo stays inset, which looks like the
 * change half worked.
 */
.bb-brandtile-bare .bb-brandtile-chip img { padding: 0; }

/*
 * A bare tile is sized by HEIGHT, not by a fixed box.
 *
 * Real logo artwork does not share an aspect ratio. Measured on the
 * live shop these run from 1.0 (a 1024x1024 square) to 3.6 (a 324x90
 * banner), and a fixed 152x84 box punished both extremes: the square
 * shrank to 84x84 to fit the HEIGHT, using 55% of the tile's width,
 * while the banner shrank to 152x42 to fit the WIDTH, using half its
 * height. Nothing was ever cropped — object-fit is contain — but a
 * logo rendered at half size reads as cut off, which is what it was
 * reported as.
 *
 * Normalising on a common height is how a logo strip is meant to work:
 * every mark gets the same optical weight and its natural width, so
 * none of them is scaled down to accommodate the shape of another.
 * max-width still caps the very wide banners, and object-fit keeps
 * those letterboxed rather than stretched.
 *
 * Framed tiles keep the fixed box on purpose — a grid of mismatched
 * supplier artwork needs the uniformity that this trades away.
 */
.bb-brandtile-bare {
    --bb-tile-h:   104px;
    --bb-tile-max: 176px;
}

.bb-brandtile-bare .bb-brandtile-chip {
    width: auto;
    height: var(--bb-tile-h);
    /*
     * A floor, because an image that has not loaded yet has no
     * intrinsic width: with width:auto the tile collapses to nothing
     * and the row — or worse, the marquee track, whose animation is a
     * percentage of its own width — is laid out wrong until the
     * pictures arrive.
     */
    min-width: var(--bb-tile-h);
    max-width: var(--bb-tile-max);
}

/*
 * The height is repeated in absolute units rather than given as 100%.
 * A percentage height does not resolve while the browser is working
 * out the image's intrinsic width, so height:100% here means the tile
 * measures zero wide however big the logo is.
 */
.bb-brandtile-bare .bb-brandtile-chip img {
    width: auto;
    height: var(--bb-tile-h);
    max-width: var(--bb-tile-max);
}

@media (max-width: 575.98px) {
    .bb-brandtile-bare {
        --bb-tile-h:   78px;
        --bb-tile-max: 132px;
    }
}

/* A horizontal, swipeable row of logos. */
.bb-brandrail {
    display: flex;
    gap: 18px;
    overflow-x: auto;
    padding: 4px 2px 8px;
    scroll-snap-type: x proximity;
    -webkit-overflow-scrolling: touch;
}

.bb-brandrail .bb-brandtile { scroll-snap-align: start; }

.bb-brandrail::-webkit-scrollbar { height: 6px; }
.bb-brandrail::-webkit-scrollbar-thumb {
    background: var(--bb-line-strong);
    border-radius: 999px;
}

/*
 * The brand marquee, above the hero.
 *
 * A stacked block rather than a label beside a row: the marquee needs
 * the full width of the column to run in, and an inline label would eat
 * into it and shift where the logos enter and leave.
 */
.bb-hero-companies {
    padding: 14px 0 18px;
}

/* ------------------------------------------------------------------ */
/* Brand marquee                                                       */
/* ------------------------------------------------------------------ */

/*
 * The group strip sits in the content column, not across the window.
 *
 * The rule and the padding live on the inner shell rather than the
 * section so the divider ends where every other section's content ends
 * — a full-bleed hairline over a 1180px strip reads as a wider band
 * than it is.
 */
.bb-groupstrip {
    margin-top: 26px;
}

.bb-groupstrip .bb-shell {
    border-top: 1px solid var(--bb-line);
    padding-top: 26px;
    padding-bottom: 6px;
}

/* A static row of logos, centred and free to wrap. */
.bb-logorow {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: center;
    gap: 14px;
}

.bb-strip-label {
    font-size: .68rem;
    font-weight: 800;
    letter-spacing: .16em;
    text-transform: uppercase;
    color: var(--bb-ink-3);
    margin-bottom: 14px;
    text-align: center;
}

.bb-marquee {
    overflow: hidden;
    /* Fades both ends so logos enter and leave rather than being
       chopped off at the viewport edge. */
    mask-image: linear-gradient(to right, transparent, black 8%, black 92%, transparent);
    -webkit-mask-image: linear-gradient(to right, transparent, black 8%, black 92%, transparent);
}

.bb-marquee-track {
    display: flex;
    align-items: flex-start;
    gap: 34px;
    width: max-content;
    animation: bb-marquee 42s linear infinite;
}

/* Pausing on hover is what makes it usable: these are links, and a
   moving target cannot be clicked. */
.bb-marquee:hover .bb-marquee-track,
.bb-marquee:focus-within .bb-marquee-track {
    animation-play-state: paused;
}

@keyframes bb-marquee {
    from { transform: translateX(0); }
    /* The track is duplicated, so shifting by half returns it to an
       identical frame and the loop is seamless. */
    to   { transform: translateX(-50%); }
}

@media (prefers-reduced-motion: reduce) {
    .bb-marquee-track {
        animation: none;
        width: 100%;
        overflow-x: auto;
        justify-content: center;
        flex-wrap: wrap;
        gap: 20px;
    }
}

/* The company credit strip above the footer. */
.bb-group-strip {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 14px 26px;
    padding: 20px 0 4px;
}

.bb-group-strip-label {
    width: 100%;
    text-align: center;
    font-size: .72rem;
    font-weight: 700;
    letter-spacing: .12em;
    text-transform: uppercase;
    /* ink-3 is tuned for 12–13px body metadata; at 11.5px uppercase it
       came to 4.12:1, so this one steps up a level. */
    color: var(--bb-ink-2);
    margin-bottom: 4px;
}

/* ------------------------------------------------------------------ */
/* The company filter on the shop directory                            */
/* ------------------------------------------------------------------ */

/*
 * A row of logos that filters the directory below it.
 *
 * Framed as a panel rather than left loose on the page: these tiles do
 * something when pressed, and a bare logo strip — which the site uses
 * twice already, purely as credit — gives no hint of that. The panel,
 * the pointer cursor and the pressed state are the three things saying
 * this row is a control.
 */
.bb-companyfilter {
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    padding: 18px 16px 14px;
    margin-bottom: 6px;
}

.bb-companyfilter .bb-logorow {
    gap: 10px;
}

.bb-cfilter {
    padding: 8px 12px;
    border: 1px solid transparent;
    border-radius: var(--bb-radius-sm);
    cursor: pointer;
    transition: border-color .15s ease, background .15s ease;
}

a.bb-cfilter:hover {
    background: var(--bb-surface-2);
    border-color: var(--bb-line-strong);
}

/* The chosen company, held down. */
.bb-cfilter.is-active {
    background: var(--bb-accent-soft);
    border-color: var(--bb-accent);
}

.bb-cfilter.is-active .bb-brandtile-caption {
    color: var(--bb-ink);
}

/*
 * A company with no shopfront of its own is still shown — it is part of
 * the group — but it is not a link, so it is dimmed and left alone
 * rather than offering a press that could only produce an empty page.
 */
.bb-cfilter.is-empty {
    opacity: .45;
    cursor: default;
}

/* The way back to everything, sized to sit level with the logo tiles. */
.bb-cfilter-all {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    align-self: stretch;
    padding: 0 16px;
    border: 1px dashed var(--bb-line-strong);
    border-radius: var(--bb-radius-sm);
    font-size: .84rem;
    font-weight: 700;
    color: var(--bb-ink-2);
    text-decoration: none;
    transition: border-color .15s ease, background .15s ease, color .15s ease;
}

.bb-cfilter-all:hover {
    background: var(--bb-surface-2);
    color: var(--bb-ink);
}

.bb-cfilter-all.is-active {
    background: var(--bb-accent-soft);
    border-style: solid;
    border-color: var(--bb-accent);
    color: var(--bb-ink);
}

/* Company heading on the shops page. */
.bb-company-head {
    display: flex;
    align-items: center;
    gap: 12px;
    margin: 26px 0 12px;
}

.bb-company-head h3 {
    font-size: 1rem;
    font-weight: 700;
    margin: 0;
}

.bb-company-head .bb-faint { font-size: .76rem; }

@media (max-width: 575.98px) {
    .bb-brandtile-md .bb-brandtile-chip { width: 64px; height: 64px; }
    .bb-brandtile-lg .bb-brandtile-chip { width: 78px; height: 78px; }
    .bb-brandrail { gap: 12px; }
}

/* ------------------------------------------------------------------ */
/* Alerts                                                              */
/* ------------------------------------------------------------------ */

.bb-alert {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    padding: 12px 15px;
    border-radius: var(--bb-radius-sm);
    font-size: .85rem;
    margin-bottom: 14px;
}

.bb-alert-info    { background: var(--bb-info-soft); color: var(--bb-info-soft-ink); }
.bb-alert-success { background: var(--bb-ok-soft); color: var(--bb-ok-soft-ink); }
.bb-alert-warn    { background: var(--bb-warn-soft); color: var(--bb-warn-soft-ink); }
.bb-alert-danger  { background: var(--bb-sale-soft); color: var(--bb-sale-soft-ink); }

/* ------------------------------------------------------------------ */
/* Banner and ad slots                                                 */
/* ------------------------------------------------------------------ */

/*
 * Deliberately un-opinionated about height.
 *
 * The operator uploads whatever they have, and a fixed height would
 * either crop the message off a tall banner or letterbox a wide one
 * into a grey band. The image sets the height; the slot just frames it.
 * The stacking below is what a rotating slot needs, and it only applies
 * once there is more than one banner in it.
 */
.bb-banner-slot {
    position: relative;
    margin: 22px 0;
    border-radius: var(--bb-radius);
    overflow: hidden;
    background: var(--bb-surface-2);
    box-shadow: var(--bb-shadow);
}

.bb-banner img,
.bb-banner video {
    display: block;      /* Kills the inline-element gap under the image. */
    width: 100%;
    height: auto;
    object-fit: cover;
}

.bb-banner-link { display: block; }

/* A rotating slot stacks its banners; a single one is left in flow so
   the slot keeps the natural height of the picture. */
.bb-banner-slot[data-banner-rotate] { display: grid; }

.bb-banner-slot[data-banner-rotate] .bb-banner {
    grid-area: 1 / 1;
    opacity: 0;
    transition: opacity .6s ease;
    pointer-events: none;
}

.bb-banner-slot[data-banner-rotate] .bb-banner.is-active {
    opacity: 1;
    pointer-events: auto;
}

.bb-banner-caption {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 26px 16px 12px;
    font-size: .84rem;
    font-weight: 600;
    /* Fixed ink on a fixed scrim: the picture underneath is the same in
       both themes, so the text over it must be too. */
    color: var(--bb-onmedia-ink);
    background: var(--bb-onmedia-scrim);
}

.bb-banner-dots {
    position: absolute;
    bottom: 10px;
    left: 50%;
    transform: translateX(-50%);
    display: flex;
    gap: 6px;
    z-index: 2;
}

.bb-banner-dot {
    width: 8px;
    height: 8px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: var(--bb-dot-idle);
    cursor: pointer;
}

.bb-banner-dot.is-active { background: var(--bb-dot); }

/* Motion is decoration here. Somebody who has asked their system not to
   animate still gets every banner — the dots switch between them. */
@media (prefers-reduced-motion: reduce) {
    .bb-banner-slot[data-banner-rotate] .bb-banner { transition: none; }
}

/* ------------------------------------------------------------------ */
/* Branch map                                                          */
/* ------------------------------------------------------------------ */

.bb-map {
    height: 420px;
    width: 100%;
    /* Leaflet paints its own container; without this the corners of the
       card show through as light squares in dark mode. */
    background: var(--bb-surface-2);
}

@media (max-width: 575.98px) {
    .bb-map { height: 320px; }
}

/*
 * OpenStreetMap only ships a light tile set. Inverting it is the
 * standard trick and costs nothing; the hue rotation puts the greens and
 * blues back the right way round after the invert flips them.
 *
 * Applied to the tiles ONLY — the pins and popups are ours and already
 * follow the palette, so inverting those too would undo them.
 */
[data-bb-theme="dark"] .bb-map .leaflet-tile-pane {
    filter: invert(1) hue-rotate(180deg) brightness(.92) contrast(.9);
}

.bb-map-pin-dot {
    display: block;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--bb-accent);
    /* onmedia, not surface: the ring sits on a map tile, and the tiles
       are the same picture in both themes. A ring that followed the
       palette would vanish into the light tiles on the light theme. */
    border: 3px solid var(--bb-onmedia-ink);
    box-shadow: 0 1px 6px rgba(0, 0, 0, .45);
}

/* Leaflet's popup chrome is white and hard-coded; these override it so a
   popup does not glare on a dark page. */
.bb-map-popup .leaflet-popup-content-wrapper,
.bb-map-popup .leaflet-popup-tip {
    background: var(--bb-surface);
    color: var(--bb-ink);
    border-radius: var(--bb-radius-sm);
    box-shadow: var(--bb-shadow-lift);
}
.bb-map-popup .leaflet-popup-content {
    margin: 12px 14px;
    font-size: .84rem;
    line-height: 1.5;
}
.bb-map-popup .leaflet-popup-close-button { color: var(--bb-ink-3); }

.bb-map-photo {
    width: 100%;
    height: 96px;
    object-fit: cover;
    border-radius: 7px;
    margin-bottom: 8px;
    display: block;
}
.bb-map-name    { font-weight: 700; font-size: .9rem; }
.bb-map-company { color: var(--bb-ink-3); font-size: .74rem; margin-bottom: 4px; }
.bb-map-address { color: var(--bb-ink-2); font-size: .78rem; }
.bb-map-hours   { color: var(--bb-ok); font-size: .78rem; font-weight: 600; margin-top: 4px; }
.bb-map-hours.is-shut { color: var(--bb-ink-3); font-weight: 500; }

.bb-map-links {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 8px;
    padding-top: 8px;
    border-top: 1px solid var(--bb-line);
}
.bb-map-links a {
    font-size: .78rem;
    font-weight: 600;
    color: var(--bb-link);
    text-decoration: none;
}
.bb-map-links a:hover { text-decoration: underline; }

/* ------------------------------------------------------------------ */
/* About page                                                          */
/* ------------------------------------------------------------------ */

/*
 * The banner works with or without a picture.
 *
 * With one, the image fills it and a scrim carries the words. Without
 * one, the same box becomes a brand-gradient panel — so an operator who
 * has not uploaded anything yet gets a finished-looking page rather than
 * a grey rectangle, and the layout does not shift when they do.
 */
.bb-about-hero {
    position: relative;
    overflow: hidden;
    border-radius: var(--bb-radius);
    margin-bottom: 16px;
    min-height: 190px;
    display: flex;
    align-items: flex-end;
    background: var(--bb-surface);
}
.bb-about-hero.is-blank {
    background: var(--bb-gradient-cta);
}
.bb-about-hero img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
}
/* The scrim only exists over a photo; on the blank panel the gradient
   already gives the text something to sit on. */
.bb-about-hero:not(.is-blank)::after {
    content: '';
    position: absolute;
    inset: 0;
    background: var(--bb-onmedia-scrim);
}
.bb-about-hero-copy {
    position: relative;
    z-index: 1;
    padding: 26px 24px 22px;
    color: var(--bb-onmedia-ink);
}
.bb-about-hero-copy h1 {
    font-size: 1.7rem;
    font-weight: 800;
    letter-spacing: -.02em;
    margin: 0 0 6px;
    color: inherit;
}
.bb-about-hero-copy p {
    margin: 0;
    font-size: .92rem;
    max-width: 56ch;
    color: var(--bb-onmedia-ink-2);
}

@media (max-width: 575.98px) {
    .bb-about-hero { min-height: 150px; }
    .bb-about-hero-copy { padding: 18px 16px 16px; }
    .bb-about-hero-copy h1 { font-size: 1.3rem; }
    .bb-about-hero-copy p  { font-size: .84rem; }
}

.bb-about-value {
    display: flex;
    gap: 10px;
    height: 100%;
    padding: 12px;
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius-sm);
    background: var(--bb-surface-2);
}
.bb-about-value-icon {
    flex: none;
    width: 30px;
    height: 30px;
    border-radius: 9px;
    display: grid;
    place-items: center;
    font-size: .88rem;
    color: var(--bb-accent-ink);
    background: var(--bb-gradient-cta);
}
.bb-about-value-title {
    font-size: .87rem;
    font-weight: 650;
    margin-bottom: 2px;
}

/* auto-fit rather than a fixed count: three photos should fill the row,
   and so should four. */
.bb-about-gallery {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
    gap: 10px;
}
.bb-about-gallery figure {
    margin: 0;
    aspect-ratio: 4 / 3;
    overflow: hidden;
    border-radius: var(--bb-radius-sm);
    background: var(--bb-surface-2);
}
.bb-about-gallery img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* The mission / vision tiles. The brand ramp as a fill, at a size where
   the gradient actually reads as a gradient. */
.bb-about-icon {
    width: 42px;
    height: 42px;
    margin-bottom: 12px;
    border-radius: 12px;
    display: grid;
    place-items: center;
    font-size: 1.15rem;
    color: var(--bb-accent-ink);
    background: var(--bb-gradient-cta);
}

/* Maintenance banner — super admins only, above everything else.
   Sticky rather than inline: it has to stay true as you scroll, because
   the whole point is that the page under it is not what visitors see. */
.bb-maintenance-bar {
    position: sticky;
    top: 0;
    z-index: 60;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 16px;
    background: var(--bb-warn-soft);
    color: var(--bb-warn-soft-ink);
    border-bottom: 1px solid var(--bb-warn);
    font-size: .82rem;
}
.bb-maintenance-bar a {
    margin-left: auto;
    flex: none;
    color: inherit;
    font-weight: 700;
    text-decoration: underline;
}

/* ------------------------------------------------------------------ */
/* Quantity stepper                                                    */
/* ------------------------------------------------------------------ */

.bb-qty {
    display: inline-flex;
    align-items: center;
    border: 1px solid var(--bb-line-strong);
    border-radius: 999px;
    overflow: hidden;
}

.bb-qty button {
    border: 0;
    background: transparent;
    width: 32px; height: 32px;
    color: var(--bb-ink-2);
    cursor: pointer;
}

.bb-qty button:hover:not(:disabled) { background: var(--bb-surface-2); color: var(--bb-ink); }
.bb-qty button:disabled { opacity: .35; cursor: not-allowed; }

.bb-qty input {
    width: 42px;
    border: 0;
    text-align: center;
    font-size: .85rem;
    font-weight: 600;
    background: transparent;
    -moz-appearance: textfield;
}

.bb-qty input::-webkit-outer-spin-button,
.bb-qty input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* ------------------------------------------------------------------ */
/* Tables (cart, reservation lines)                                    */
/* ------------------------------------------------------------------ */

.bb-line {
    display: grid;
    grid-template-columns: 72px 1fr auto;
    gap: 14px;
    padding: 14px 0;
    border-bottom: 1px solid var(--bb-line);
    align-items: center;
}

.bb-line:last-child { border-bottom: 0; }

.bb-line-media {
    width: 72px; height: 72px;
    border-radius: var(--bb-radius-sm);
    background: var(--bb-surface-2);
    overflow: hidden;
    display: grid; place-items: center;
}

.bb-line-media img { width: 100%; height: 100%; object-fit: cover; }

@media (max-width: 575.98px) {
    .bb-line { grid-template-columns: 56px 1fr; }
    .bb-line-media { width: 56px; height: 56px; }
    .bb-line > :last-child { grid-column: 1 / -1; }
}

/* ------------------------------------------------------------------ */
/* Status pills                                                        */
/* ------------------------------------------------------------------ */

.bb-status {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 4px 11px;
    border-radius: 999px;
    font-size: .74rem;
    font-weight: 600;
}

.bb-status::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }

.bb-status-pending   { background: var(--bb-warn-soft); color: var(--bb-warn-soft-ink); }
.bb-status-confirmed { background: var(--bb-info-soft); color: var(--bb-info-soft-ink); }
.bb-status-ready     { background: var(--bb-ok-soft); color: var(--bb-ok-soft-ink); }
.bb-status-completed { background: var(--bb-mute-soft); color: var(--bb-mute-soft-ink); }
.bb-status-cancelled { background: var(--bb-sale-soft); color: var(--bb-sale-soft-ink); }

/* Progress rail on the tracking page */
.bb-steps { display: flex; gap: 0; margin: 18px 0; }
.bb-step { flex: 1; text-align: center; position: relative; font-size: .76rem; color: var(--bb-ink-3); }

.bb-step::before {
    content: '';
    display: block;
    height: 3px;
    background: var(--bb-line);
    margin-bottom: 10px;
}

.bb-step:first-child::before { border-radius: 999px 0 0 999px; }
.bb-step:last-child::before  { border-radius: 0 999px 999px 0; }
.bb-step.is-done::before { background: var(--bb-ok); }
.bb-step.is-done { color: var(--bb-ok); font-weight: 600; }
.bb-step.is-cancelled::before { background: var(--bb-sale); }
.bb-step.is-cancelled { color: var(--bb-sale); font-weight: 600; }

/* ------------------------------------------------------------------ */
/* Store cards                                                         */
/* ------------------------------------------------------------------ */

.bb-store {
    background: var(--bb-surface);
    border-radius: var(--bb-radius-sm);
    box-shadow: var(--bb-shadow);
    padding: 14px;
}

.bb-store-head { display: flex; align-items: center; gap: 10px; margin-bottom: 12px; }

.bb-store-avatar {
    width: 34px; height: 34px;
    border-radius: 50%;
    background: var(--bb-accent);
    color: var(--bb-accent-ink);
    display: grid; place-items: center;
    font-size: .82rem;
    font-weight: 700;
    flex-shrink: 0;
}

.bb-store-mini { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }

.bb-store-mini-item { text-align: center; font-size: .7rem; color: var(--bb-ink-2); }

.bb-store-mini-item span {
    display: block;
    aspect-ratio: 1;
    border-radius: 7px;
    background: var(--bb-surface-2);
    margin-bottom: 4px;
    overflow: hidden;
    display: grid; place-items: center;
}

.bb-store-mini-item img { width: 100%; height: 100%; object-fit: cover; }

/* ------------------------------------------------------------------ */
/* Quote band + footer                                                 */
/* ------------------------------------------------------------------ */

.bb-quote {
    background: var(--bb-avatar);
    color: var(--bb-avatar-ink);
    text-align: center;
    padding: 44px 16px;
    font-size: 1.5rem;
    font-weight: 700;
    font-style: italic;
    letter-spacing: -.01em;
}

.bb-footer { background: var(--bb-footer-bg); color: var(--bb-footer-ink); padding: 34px 0 0; font-size: .82rem; }
.bb-footer h6 { color: var(--bb-footer-head); font-size: .82rem; font-weight: 700; margin: 0 0 12px; }
.bb-footer a { color: var(--bb-footer-ink); display: block; padding: 3px 0; }
.bb-footer a:hover { color: var(--bb-footer-head); }

.bb-footer-grid {
    display: grid;
    grid-template-columns: 1.4fr repeat(4, 1fr);
    gap: 26px;
    padding-bottom: 28px;
}

@media (max-width: 767.98px) {
    .bb-footer-grid { grid-template-columns: repeat(2, 1fr); }
}

.bb-footer-bottom {
    border-top: 1px solid var(--bb-footer-line);
    padding: 14px 0;
    text-align: center;
    font-size: .76rem;
    color: var(--bb-footer-faint);
}

.bb-social { display: flex; gap: 10px; margin-top: 14px; }
.bb-social a { font-size: 1rem; }

/* ------------------------------------------------------------------ */
/* Age gate                                                            */
/* ------------------------------------------------------------------ */

.bb-agegate {
    position: fixed;
    inset: 0;
    z-index: 2000;
    background: rgba(14, 16, 20, .88);
    backdrop-filter: blur(4px);
    display: grid;
    place-items: center;
    padding: 20px;
}

.bb-agegate-card {
    background: var(--bb-surface);
    border-radius: var(--bb-radius);
    max-width: 420px;
    width: 100%;
    padding: 30px 28px;
    text-align: center;
    box-shadow: var(--bb-shadow-lift);
}

.bb-agegate-mark {
    width: 60px; height: 60px;
    border-radius: 50%;
    background: var(--bb-accent);
    color: var(--bb-accent-ink);
    display: grid; place-items: center;
    font-size: 1.2rem;
    font-weight: 800;
    margin: 0 auto 16px;
}

/* ------------------------------------------------------------------ */
/* "Where are you located?"                                            */
/* ------------------------------------------------------------------ */

/*
 * Shares the age gate's scrim deliberately — it is the second panel of
 * one entry sequence, and a different backdrop would read as a
 * different kind of interruption.
 */
.bb-picker {
    position: fixed;
    inset: 0;
    z-index: 1990;
    background: rgba(14, 16, 20, .88);
    backdrop-filter: blur(4px);
    display: grid;
    place-items: center;
    padding: 20px;
}

.bb-picker-card {
    background: var(--bb-surface);
    border-radius: var(--bb-radius);
    box-shadow: var(--bb-shadow-lift);
    width: 100%;
    max-width: 880px;
    /* Never taller than the window: the list scrolls, the dialog does
       not, so the filters and the Choose buttons stay reachable. */
    max-height: min(90vh, 760px);
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.bb-picker-head {
    padding: 24px 26px 0;
}

.bb-picker-head h2 {
    font-size: 1.25rem;
    font-weight: 700;
    margin: 0 0 6px;
}

.bb-picker-head p {
    font-size: .85rem;
    line-height: 1.6;
    margin: 0;
}

.bb-picker-filters {
    display: flex;
    gap: 8px;
    flex-wrap: wrap;
    padding: 16px 26px;
}

.bb-picker-search {
    position: relative;
    flex: 1 1 240px;
}

.bb-picker-search i {
    position: absolute;
    left: 12px;
    top: 50%;
    transform: translateY(-50%);
    color: var(--bb-ink-3);
    pointer-events: none;
}

.bb-picker-search input,
.bb-picker-filters select {
    width: 100%;
    background: var(--bb-surface-2);
    border: 1px solid var(--bb-line);
    color: var(--bb-ink);
    border-radius: var(--bb-radius-sm);
    padding: 10px 12px;
    font-size: .88rem;
}

.bb-picker-search input { padding-left: 34px; }

.bb-picker-filters select { flex: 0 1 180px; width: auto; }

.bb-picker-search input:focus,
.bb-picker-filters select:focus {
    outline: 2px solid var(--bb-accent);
    outline-offset: 1px;
}

.bb-picker-body {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 16px;
    padding: 0 26px;
    min-height: 0;   /* Lets the list scroll inside a grid row. */
    flex: 1;
}

.bb-picker-map {
    height: 100%;
    min-height: 260px;
    border-radius: var(--bb-radius-sm);
    background: var(--bb-surface-2);
    overflow: hidden;
}

.bb-picker-list {
    display: flex;
    flex-direction: column;   /* So "nearest first" can reorder by CSS order. */
    gap: 8px;
    overflow-y: auto;
    min-height: 0;
    padding-right: 4px;
}

.bb-picker-shop {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 14px;
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius-sm);
    background: var(--bb-surface-2);
    transition: border-color .15s ease, transform .15s ease;
}

.bb-picker-shop:hover  { border-color: var(--bb-accent); }
.bb-picker-shop.is-current { border-color: var(--bb-ok); }

/* Where a map pin drops you. */
.bb-picker-shop.is-focus {
    border-color: var(--bb-accent);
    box-shadow: 0 0 0 2px var(--bb-accent-soft);
}

/*
 * The shopfront photo on a row.
 *
 * Fixed size whether or not there is a picture, so a list where most
 * branches have no photo yet does not step in and out as you scroll.
 */
.bb-picker-shop-photo {
    width: 54px;
    height: 54px;
    flex: 0 0 54px;
    border-radius: var(--bb-radius-sm);
    object-fit: cover;
    background: var(--bb-surface);
}

/* Stands in for a figure when prices are private. Deliberately quieter
   than a price: it is a note, not a number. */
.bb-price-hidden {
    font-weight: 600;
    font-size: .92rem;
    color: var(--bb-ink-2);
}

/* "Go back later", under the assistant's composer. */
.bb-ai-goback {
    padding: 0 14px 4px;
    margin: 0;
}

.bb-picker-shop-photo.is-blank {
    display: grid;
    place-items: center;
    color: var(--bb-ink-3);
    font-size: 1.2rem;
    border: 1px dashed var(--bb-line);
}

.bb-picker-shop-main { min-width: 0; flex: 1; }

.bb-picker-shop-name {
    font-size: .92rem;
    font-weight: 650;
    display: flex;
    align-items: center;
    gap: 6px;
    flex-wrap: wrap;
}

.bb-picker-shop-meta {
    font-size: .76rem;
    color: var(--bb-ink-2);
    margin-top: 2px;
}

.bb-picker-empty {
    padding: 24px 12px;
    text-align: center;
    font-size: .85rem;
    color: var(--bb-ink-3);
}

.bb-picker-foot {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 16px 26px;
    border-top: 1px solid var(--bb-line);
    margin-top: 16px;
    font-size: .8rem;
}

/*
 * On a phone the map becomes a strip above the list rather than half the
 * dialog. It is orientation, not the main event — the list is what gets
 * tapped, and it needs the height.
 */
@media (max-width: 760px) {
    .bb-picker { padding: 0; }

    .bb-picker-card {
        max-width: none;
        max-height: 100vh;
        height: 100vh;
        border-radius: 0;
    }

    /*
     * One scrolling column, not a grid with a scrolling pane inside it.
     *
     * Stacking the map above a list that scrolls on its own means the
     * heading, the filters and the map all claim their height first and
     * the list gets whatever is left — which on a short screen was
     * sixteen pixels, putting every shop below the fold with nothing to
     * suggest they were there. Scrolling the whole body lets the map
     * move out of the way as somebody reads down, which is what they
     * want it to do anyway.
     */
    .bb-picker-body {
        display: block;
        overflow-y: auto;
        -webkit-overflow-scrolling: touch;
    }

    .bb-picker-map {
        height: 180px;
        min-height: 0;
        margin-bottom: 12px;
    }

    .bb-picker-list {
        overflow: visible;
        padding-right: 0;
    }

    /* Town and location side by side; the search keeps its own row. */
    .bb-picker-filters select { flex: 1 1 auto; }
    .bb-picker-filters .bb-btn { flex: 1 1 auto; }
}

/*
 * A short window — a phone in landscape, or a small laptop with the
 * browser chrome taking half of it. The explanation is the first thing
 * to go: the heading already says what is being asked.
 */
@media (max-height: 620px) {
    .bb-picker-head p { display: none; }
    .bb-picker-head   { padding-top: 18px; }
    .bb-picker-map    { height: 140px; }
    .bb-picker-filters, .bb-picker-foot { padding-top: 12px; padding-bottom: 12px; }
}

/* ------------------------------------------------------------------ */
/* Account shell                                                       */
/* ------------------------------------------------------------------ */

.bb-account { display: grid; grid-template-columns: 232px 1fr; gap: 18px; align-items: start; }

@media (max-width: 767.98px) { .bb-account { grid-template-columns: 1fr; } }

.bb-account-nav { padding: 8px; }

.bb-account-nav a {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 9px 13px;
    border-radius: var(--bb-radius-sm);
    font-size: .85rem;
    color: var(--bb-ink-2);
}

.bb-account-nav a:hover { background: var(--bb-surface-2); color: var(--bb-ink); }
.bb-account-nav a.is-active { background: var(--bb-accent); color: var(--bb-accent-ink); font-weight: 600; }

.bb-stat { padding: 16px 18px; }
.bb-stat-label { font-size: .74rem; color: var(--bb-ink-3); text-transform: uppercase; letter-spacing: .06em; }
.bb-stat-value { font-size: 1.5rem; font-weight: 800; letter-spacing: -.02em; margin-top: 3px; }

/* ------------------------------------------------------------------ */
/* Utility                                                             */
/* ------------------------------------------------------------------ */

.bb-empty { text-align: center; padding: 46px 20px; color: var(--bb-ink-3); }
.bb-empty .bi { font-size: 2.2rem; display: block; margin-bottom: 10px; opacity: .55; }

.bb-divider { height: 1px; background: var(--bb-line); margin: 16px 0; }

.bb-sticky { position: sticky; top: 78px; }


/* ------------------------------------------------------------------ */
/* Colour utilities                                                    */
/* ------------------------------------------------------------------ */

/*
 * Gradient text, for headings only.
 *
 * Deliberately not offered for body copy: gradient text cannot be
 * contrast-checked meaningfully across its own run, so it belongs on
 * large type where the bar is 3:1 and the shape carries the reading.
 */
.bb-gradient-text {
    color: var(--bb-gradient-head-fallback);
    background: var(--bb-gradient-head);
    -webkit-background-clip: text;
    background-clip: text;
}

@supports (-webkit-background-clip: text) or (background-clip: text) {
    .bb-gradient-text { color: transparent; }
}

.bb-accent-text { color: var(--bb-link); }
.bb-brand-text  { color: var(--bb-brand-2); }

/* A tinted panel for callouts that should feel like the brand without
   shouting. */
.bb-tint {
    background: var(--bb-gradient-soft);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
}

/* ------------------------------------------------------------------ */
/* AI assistant                                                        */
/* ------------------------------------------------------------------ */

/* Visible to a screen reader, not to the eye. Used for the icon
   buttons in the assistant, which are glyphs with no text. */
.bb-sr {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/*
 * Below the age gate's 2000 on purpose: the gate is a block, and a chat
 * launcher floating over it would invite a conversation the visitor has
 * not yet earned. The panel only renders past the gate anyway — this is
 * the belt to that braces.
 */
.bb-ai-launcher {
    position: fixed;
    right: 18px;
    bottom: 18px;
    z-index: 1500;
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 11px 18px;
    border: 0;
    border-radius: 999px;
    background: var(--bb-gradient-cta);
    color: var(--bb-accent-ink);
    font-size: .87rem;
    font-weight: 700;
    cursor: pointer;
    box-shadow: var(--bb-shadow-lift);
    transition: transform .12s ease, box-shadow .15s ease;
}

.bb-ai-launcher:hover { transform: translateY(-2px); }
.bb-ai-launcher[hidden] { display: none; }

.bb-ai {
    position: fixed;
    right: 18px;
    bottom: 18px;
    /*
     * Above the shop chooser (1990), below the age gate (2000).
     *
     * The chooser hands over to the assistant, so the panel has to open
     * on top of it — at its old 1501 it opened underneath and looked
     * like the button had done nothing. Still under the age gate,
     * because nothing outranks that.
     */
    z-index: 1995;
    width: min(380px, calc(100vw - 36px));
    /* Capped against the viewport so the composer never lands under a
       phone's browser chrome. */
    max-height: min(560px, calc(100vh - 96px));
    display: flex;
    flex-direction: column;
    overflow: hidden;
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    box-shadow: var(--bb-shadow-lift);
}

.bb-ai[hidden] { display: none; }

.bb-ai-head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    padding: 12px 14px;
    background: var(--bb-gradient-cta);
    color: var(--bb-accent-ink);
}

.bb-ai-name { font-weight: 800; font-size: .95rem; }
.bb-ai-sub  { font-size: .72rem; opacity: .85; }

.bb-ai-head-actions { display: flex; gap: 4px; }

.bb-ai-icon {
    border: 0;
    background: rgba(255, 255, 255, .16);
    color: var(--bb-accent-ink);
    width: 30px;
    height: 30px;
    border-radius: 8px;
    cursor: pointer;
    display: grid;
    place-items: center;
}

.bb-ai-icon:hover { background: rgba(255, 255, 255, .28); }

.bb-ai-log {
    flex: 1 1 auto;
    overflow-y: auto;
    padding: 14px;
    display: flex;
    flex-direction: column;
    gap: 10px;
    background: var(--bb-bg);
}

.bb-ai-msg {
    max-width: 85%;
    padding: 9px 12px;
    border-radius: 14px;
    font-size: .86rem;
    line-height: 1.5;
    /* Replies arrive as plain text with real line breaks in them. */
    white-space: pre-line;
    overflow-wrap: anywhere;
}

.bb-ai-msg.is-agent {
    align-self: flex-start;
    background: var(--bb-surface-2);
    color: var(--bb-ink);
    border-bottom-left-radius: 4px;
}

.bb-ai-msg.is-you {
    align-self: flex-end;
    background: var(--bb-accent);
    color: var(--bb-accent-ink);
    border-bottom-right-radius: 4px;
}

.bb-ai-msg.is-problem {
    align-self: flex-start;
    background: var(--bb-warn-soft);
    color: var(--bb-warn-soft-ink);
}

/* Links the agent includes in a reply. */
.bb-ai-msg a { color: inherit; text-decoration: underline; }

.bb-ai-typing {
    align-self: flex-start;
    display: inline-flex;
    gap: 4px;
    padding: 11px 14px;
    background: var(--bb-surface-2);
    border-radius: 14px;
}

.bb-ai-typing span {
    width: 6px;
    height: 6px;
    border-radius: 50%;
    background: var(--bb-ink-3);
    animation: bb-ai-blink 1.2s infinite ease-in-out;
}

.bb-ai-typing span:nth-child(2) { animation-delay: .18s; }
.bb-ai-typing span:nth-child(3) { animation-delay: .36s; }

@keyframes bb-ai-blink {
    0%, 80%, 100% { opacity: .25; }
    40%           { opacity: 1; }
}

.bb-ai-form {
    display: flex;
    align-items: center;
    gap: 8px;
    padding: 10px;
    border-top: 1px solid var(--bb-line);
    background: var(--bb-surface);
}

.bb-ai-form input {
    flex: 1 1 auto;
    min-width: 0;
    padding: 9px 12px;
    border: 1px solid var(--bb-line);
    border-radius: 999px;
    background: var(--bb-bg);
    color: var(--bb-ink);
    font-size: .87rem;
}

.bb-ai-form input:focus {
    outline: 2px solid var(--bb-accent);
    outline-offset: 1px;
}

.bb-ai-send {
    flex: 0 0 auto;
    width: 38px;
    height: 38px;
    border: 0;
    border-radius: 50%;
    background: var(--bb-accent);
    color: var(--bb-accent-ink);
    cursor: pointer;
    display: grid;
    place-items: center;
}

.bb-ai-send:disabled { opacity: .5; cursor: default; }

.bb-ai-foot {
    margin: 0;
    padding: 8px 12px 10px;
    font-size: .68rem;
    line-height: 1.45;
    color: var(--bb-ink-3);
    background: var(--bb-surface);
    text-align: center;
}

/* On a phone the panel takes the screen — a 380px card on a 375px
   viewport is a card with nowhere to sit. */
@media (max-width: 575.98px) {
    .bb-ai {
        right: 0;
        bottom: 0;
        width: 100vw;
        max-height: 82vh;
        border-radius: var(--bb-radius) var(--bb-radius) 0 0;
        border-left: 0;
        border-right: 0;
        border-bottom: 0;
    }

    .bb-ai-launcher { right: 12px; bottom: 12px; }
}

@media (prefers-reduced-motion: reduce) {
    .bb-ai-launcher { transition: none; }
    .bb-ai-typing span { animation: none; opacity: .6; }
}

@media print {
    .bb-header, .bb-topbar, .bb-footer, .bb-quote, .bb-btn { display: none !important; }
    .bb-ai, .bb-ai-launcher { display: none !important; }

    /* Printing is always light, whatever the visitor is browsing in:
       nobody wants a reservation slip that empties a toner cartridge. */
    body.bb, [data-bb-theme="dark"] body.bb {
        background: #fff;
        color: #14161a;
    }

    .bb-card, .bb-surface { background: #fff !important; box-shadow: none !important; }
}
