﻿/* ============================================================================================
   bit platform utilities demo - global stylesheet (the site kit)

   Every Utilities demo site shares this file byte for byte, together with theme.js, site.js and
   the chrome components in Client/Layout - the same Fluent 2 shell the Brouter demo is built on.
   What a demo has of its own (the styles of its live samples) lives in demo.css, written against
   the --bb-* names below. Change this file in one demo and copy it to the others.

   The site is built on Microsoft's Fluent 2 design language, expressed as three layers:

     1. --bit-clr-*   the Bit.BlazorUI Fluent palette, inlined verbatim from
                      BlazorUI/Bit.BlazorUI/Styles/Fluent/colors.fluent-*.scss and selected by the
                      same `bit-theme` attribute convention, so a value copied out of a
                      Bit.BlazorUI stylesheet lands here unchanged.
     2. --fl-*        the rest of the Fluent 2 token set - shape, elevation, type ramp, spacing,
                      motion, stroke - at the values the design system publishes. These are the
                      pieces that used to be Fluent 1 here (a 2px corner on everything,
                      regular-weight titles, one duration for the whole site) and they are what
                      makes the site read as Fluent 2 rather than as its predecessor.
     3. --bb-*        this site's own vocabulary, mapped onto the two layers above. Every page is
                      written against these names, so no page ever names a palette entry directly.

   A demo carries no dependency other than the library it demonstrates - pulling a component
   library in would blur which behavior is whose - so the Fluent surfaces below are reproduced in
   plain CSS.
   ============================================================================================ */

/* ============================================================================================
   1a. Palette - light
   ============================================================================================ */

:root,
:root[bit-theme="light"] {
    color-scheme: light;

    /* primary. Interaction moves the fill toward MORE contrast with the surface under it, so the
       states darken on these light surfaces; '-dis' is the tint the soft backgrounds use. */
    --bit-clr-pri: #1276C6;
    --bit-clr-pri-hover: #0B6AB4;
    --bit-clr-pri-active: #095A9B;
    --bit-clr-pri-text: #FFFFFF;
    --bit-clr-pri-dis: #DDEDFF;
    /* secondary - the bit orange */
    --bit-clr-sec: #FD7F36;
    --bit-clr-sec-dark: #B4520F;
    /* success / warning / error */
    --bit-clr-suc: #228422;
    --bit-clr-suc-dark: #0D5D0F;
    --bit-clr-suc-dis: #E0F1DF;
    --bit-clr-wrn: #EDAE12;
    --bit-clr-wrn-dark: #8A6200;
    --bit-clr-wrn-dis: #F7EED9;
    --bit-clr-err: #D2393B;
    --bit-clr-err-dark: #9D2225;
    --bit-clr-err-dis: #FFE4E1;
    /* foregrounds */
    --bit-clr-fg-pri: #1A1A1A;
    --bit-clr-fg-sec: #525252;
    --bit-clr-fg-ter: #6B6B6B;
    /* backgrounds */
    --bit-clr-bg-pri: #FFFFFF;
    --bit-clr-bg-pri-hover: #F5F5F5;
    --bit-clr-bg-sec: #F5F5F5;
    --bit-clr-bg-sec-hover: #EDEDED;
    --bit-clr-bg-ter: #EBEBEB;
    /* borders */
    --bit-clr-brd-pri: #707070;
    --bit-clr-brd-sec: #ADADAD;
    --bit-clr-brd-ter: #E0E0E0;

    /* Fluent 2's focus indicator is a neutral DOUBLE stroke, not a brand-colored ring: a hairline
       in the surface color with a heavier one outside it in the foreground color. Neutral is the
       point - it stays visible on a brand-filled button, where a brand ring would sink into the
       fill it sits on. */
    --fl-stroke-focus-inner: #FFFFFF;
    --fl-stroke-focus-outer: #000000;

    /* Elevation - Fluent 2's shadow ramp. Two shadows per level: a key light that gives the
       direction, and an ambient one that seats the surface on the page. */
    --fl-shadow-2: 0 1px 2px rgba(0, 0, 0, .14), 0 0 2px rgba(0, 0, 0, .12);
    --fl-shadow-4: 0 2px 4px rgba(0, 0, 0, .14), 0 0 2px rgba(0, 0, 0, .12);
    --fl-shadow-8: 0 4px 8px rgba(0, 0, 0, .14), 0 0 2px rgba(0, 0, 0, .12);
    --fl-shadow-16: 0 8px 16px rgba(0, 0, 0, .14), 0 0 2px rgba(0, 0, 0, .12);
    --fl-shadow-28: 0 14px 28px rgba(0, 0, 0, .24), 0 0 8px rgba(0, 0, 0, .20);
    --fl-shadow-64: 0 32px 64px rgba(0, 0, 0, .24), 0 0 8px rgba(0, 0, 0, .20);

    /* Code surface - GitHub's light syntax colors, which is what the samples were written
       against. */
    --bb-code-bg: #F6F8FA;
    --bb-code-fg: #1F2328;
    --bb-code-comment: #59636E;
    --bb-code-keyword: #0550AE;
    --bb-code-string: #953800;
    --bb-code-param: #116329;

    /* The landing hero's ground: two brand-tinted washes rather than a gradient sheet, so the
       color is felt at the edges and the type still sits on the flat surface color. */
    --bb-wash-primary: rgba(18, 118, 198, .10);
    --bb-wash-accent: rgba(253, 127, 54, .07);
    --bb-scrim: rgba(0, 0, 0, .40);
}

/* ============================================================================================
   1b. Palette - dark
   ============================================================================================ */

:root[bit-theme="dark"] {
    color-scheme: dark;

    /* On dark surfaces more contrast means lighter, so every interaction step inverts. */
    --bit-clr-pri: #4FA3F4;
    --bit-clr-pri-hover: #61AEFB;
    --bit-clr-pri-active: #7DBEFF;
    --bit-clr-pri-text: #0F1318;
    --bit-clr-pri-dis: #17273A;
    --bit-clr-sec: #F49666;
    --bit-clr-sec-dark: #FFB68C;
    --bit-clr-suc: #78B774;
    --bit-clr-suc-dark: #A0D49D;
    --bit-clr-suc-dis: #1B2A1B;
    --bit-clr-wrn: #F0BB52;
    --bit-clr-wrn-dark: #FFDA97;
    --bit-clr-wrn-dis: #2C2617;
    --bit-clr-err: #E67A73;
    --bit-clr-err-dark: #FEA199;
    --bit-clr-err-dis: #31201E;
    --bit-clr-fg-pri: #E6ECF2;
    --bit-clr-fg-sec: #B9BEC4;
    --bit-clr-fg-ter: #8E9398;
    --bit-clr-bg-pri: #0F1318;
    --bit-clr-bg-pri-hover: #171C22;
    --bit-clr-bg-sec: #15191E;
    --bit-clr-bg-sec-hover: #22272C;
    --bit-clr-bg-ter: #272C31;
    --bit-clr-brd-pri: #757B81;
    --bit-clr-brd-sec: #454C53;
    --bit-clr-brd-ter: #2B3138;

    --fl-stroke-focus-inner: #0F1318;
    --fl-stroke-focus-outer: #FFFFFF;

    /* A dark surface swallows a shadow, so Fluent 2 raises the alpha rather than the geometry -
       the elevation reads at the same distance without the blur turning into a halo. */
    --fl-shadow-2: 0 1px 2px rgba(0, 0, 0, .28), 0 0 2px rgba(0, 0, 0, .24);
    --fl-shadow-4: 0 2px 4px rgba(0, 0, 0, .28), 0 0 2px rgba(0, 0, 0, .24);
    --fl-shadow-8: 0 4px 8px rgba(0, 0, 0, .28), 0 0 2px rgba(0, 0, 0, .24);
    --fl-shadow-16: 0 8px 16px rgba(0, 0, 0, .28), 0 0 2px rgba(0, 0, 0, .24);
    --fl-shadow-28: 0 14px 28px rgba(0, 0, 0, .40), 0 0 8px rgba(0, 0, 0, .36);
    --fl-shadow-64: 0 32px 64px rgba(0, 0, 0, .40), 0 0 8px rgba(0, 0, 0, .36);

    --bb-code-bg: #0A0E13;
    --bb-code-fg: #E6EDF3;
    --bb-code-comment: #8E9398;
    --bb-code-keyword: #7DD3FC;
    --bb-code-string: #FBBF24;
    --bb-code-param: #86EFAC;

    --bb-wash-primary: rgba(79, 163, 244, .14);
    --bb-wash-accent: rgba(244, 150, 102, .08);
    --bb-scrim: rgba(0, 0, 0, .62);
}

/* ============================================================================================
   2. The rest of the Fluent 2 token set, and this site's vocabulary on top of it
   ============================================================================================ */

:root {
    /* ---------- Shape. Fluent 2's corner ramp, and the most visible difference from Fluent 1 -
       which rounded everything by the same 2px hairline. Controls take Medium, surfaces take
       Large, and anything that floats over the page takes XLarge. ---------- */
    --fl-radius-none: 0;
    --fl-radius-small: 2px;
    --fl-radius-medium: 4px;
    --fl-radius-large: 6px;
    --fl-radius-xlarge: 8px;
    --fl-radius-circular: 10000px;

    /* Bit.BlazorUI components read their own shape token, so publishing it keeps one dropped into
       this site rounded the way the site is. */
    --bit-shp-brd-radius: var(--fl-radius-medium);

    --bb-radius-sm: var(--fl-radius-small);
    --bb-radius: var(--fl-radius-medium);
    --bb-radius-lg: var(--fl-radius-large);
    --bb-radius-xl: var(--fl-radius-xlarge);
    --bb-radius-pill: var(--fl-radius-circular);

    /* ---------- Spacing. Fluent 2's scale; nothing on the site invents a value between two of
       these. ---------- */
    --fl-space-xxs: .125rem;
    --fl-space-xs: .25rem;
    --fl-space-s: .5rem;
    --fl-space-m: .75rem;
    --fl-space-l: 1rem;
    --fl-space-xl: 1.25rem;
    --fl-space-xxl: 1.5rem;
    --fl-space-xxxl: 2rem;

    /* ---------- Type ramp. Fluent 2 sizes AND weights its levels: titles are Semibold, which is
       exactly what separates its headings from Fluent 1's regular-weight ones. ---------- */
    --fl-font-size-100: .75rem;
    --fl-font-size-200: .875rem;
    --fl-font-size-300: 1rem;
    --fl-font-size-400: 1.25rem;
    --fl-font-size-500: 1.5rem;
    --fl-font-size-600: 1.75rem;
    --fl-font-size-700: 2rem;
    --fl-font-size-800: 2.5rem;
    --fl-font-size-900: 4rem;

    --fl-weight-regular: 400;
    --fl-weight-medium: 500;
    --fl-weight-semibold: 600;

    /* ---------- Motion. Fluent 2 publishes eight durations and a family of curves: entrances
       decelerate, exits accelerate, and anything that only changes color uses easyEase. -------- */
    --fl-duration-ultra-fast: 50ms;
    --fl-duration-faster: 100ms;
    --fl-duration-fast: 150ms;
    --fl-duration-normal: 200ms;
    --fl-duration-gentle: 250ms;
    --fl-duration-slow: 300ms;
    --fl-duration-slower: 400ms;

    --fl-curve-accelerate-min: cubic-bezier(.8, 0, .78, 1);
    --fl-curve-decelerate-max: cubic-bezier(.1, .9, .2, 1);
    --fl-curve-decelerate-mid: cubic-bezier(0, 0, 0, 1);
    --fl-curve-easy-ease: cubic-bezier(.33, 0, .67, 1);

    /* The motion names the site's own rules and every scoped stylesheet are written against. */
    --bb-motion-duration: var(--fl-duration-normal);
    --bb-motion-duration-short: var(--fl-duration-fast);
    --bb-motion-easing: var(--fl-curve-easy-ease);
    --bb-motion-enter: var(--fl-curve-decelerate-max);

    /* ---------- Roles ---------- */
    --bb-bg: var(--bit-clr-bg-sec);
    --bb-surface: var(--bit-clr-bg-pri);
    --bb-surface-hover: var(--bit-clr-bg-sec-hover);
    --bb-surface-2: var(--bit-clr-bg-ter);
    --bb-surface-sunken: var(--bit-clr-bg-sec);
    --bb-border: var(--bit-clr-brd-ter);
    --bb-border-strong: var(--bit-clr-brd-sec);
    /* An alias, not a fourth role: pages and scoped stylesheets written before the border roles
       were split still ask for this name, and it means what they meant - the quieter of the two. */
    --bb-border-soft: var(--bit-clr-brd-ter);
    --bb-text: var(--bit-clr-fg-pri);
    --bb-text-muted: var(--bit-clr-fg-sec);
    --bb-text-soft: var(--bit-clr-fg-ter);
    --bb-primary: var(--bit-clr-pri);
    --bb-primary-hover: var(--bit-clr-pri-hover);
    --bb-primary-active: var(--bit-clr-pri-active);
    --bb-primary-soft: var(--bit-clr-pri-dis);
    --bb-primary-text: var(--bit-clr-pri-text);
    --bb-accent: var(--bit-clr-sec);
    --bb-accent-text: var(--bit-clr-sec-dark);
    --bb-success: var(--bit-clr-suc);
    --bb-success-soft: var(--bit-clr-suc-dis);
    --bb-success-text: var(--bit-clr-suc-dark);
    --bb-warning: var(--bit-clr-wrn);
    --bb-warning-soft: var(--bit-clr-wrn-dis);
    --bb-warning-text: var(--bit-clr-wrn-dark);
    --bb-danger: var(--bit-clr-err);
    --bb-danger-soft: var(--bit-clr-err-dis);
    --bb-danger-text: var(--bit-clr-err-dark);

    --bb-shadow-card: var(--fl-shadow-2);
    --bb-shadow-raised: var(--fl-shadow-8);
    --bb-shadow-flyout: var(--fl-shadow-16);
    --bb-shadow-dialog: var(--fl-shadow-64);
    /* Alias for scoped stylesheets written against the old single elevation. */
    --bb-shadow: var(--fl-shadow-16);

    /* ---------- Chrome geometry. Published here because the header, the docs shell, the rail,
       the drawer and every heading's scroll-margin all have to agree on them. ---------- */
    --bb-header-height: 56px;
    --bb-nav-panel-width: 262px;
    --bb-rail-width: 232px;
    --bb-content-width: 1320px;
    --bb-measure: 74ch;

    /* Segoe UI Variable is Fluent 2's typeface; static Segoe UI is the fallback on Windows
       versions that do not ship it, and the platform stack takes over everywhere else. */
    --bb-font-sans: "Segoe UI Variable Text", "Segoe UI Variable Static Text", "Segoe UI",
                    "Segoe UI Web (West European)", -apple-system, BlinkMacSystemFont, Roboto,
                    "Helvetica Neue", Arial, sans-serif;
    --bb-font-display: "Segoe UI Variable Display", "Segoe UI Variable Static Display",
                       var(--bb-font-sans);
    --bb-mono: ui-monospace, "Cascadia Code", SFMono-Regular, "SF Mono", Menlo, Consolas,
               "Liberation Mono", monospace;
}

/* Fluent's own components collapse their motion under this preference; the site does the same at
   the token, so nothing downstream has to opt in individually. */
@media (prefers-reduced-motion: reduce) {
    :root {
        --fl-duration-ultra-fast: 1ms;
        --fl-duration-faster: 1ms;
        --fl-duration-fast: 1ms;
        --fl-duration-normal: 1ms;
        --fl-duration-gentle: 1ms;
        --fl-duration-slow: 1ms;
        --fl-duration-slower: 1ms;
    }
}

/* ============================================================================================
   3. Base
   ============================================================================================ */

*,
*::before,
*::after {
    box-sizing: border-box;
    -webkit-text-size-adjust: none;
    -webkit-tap-highlight-color: transparent;
}

html {
    /* Keep the viewport width constant whether or not the page scrolls (classic scrollbars eat
       layout width on Windows). Without this, navigating between a tall page and a short one
       resizes every element by ~17px, so even chrome pinned out of the view transition via
       view-transition-name picks up a visible resize animation on its own group. */
    scrollbar-gutter: stable;
    scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
    html {
        scroll-behavior: auto;
    }
}

html,
body {
    margin: 0;
    padding: 0;
    background: var(--bb-bg);
    color: var(--bb-text);
    font-family: var(--bb-font-sans);
    /* Fluent 2's Body2 - 16/22. The previous 15px was below the readable floor for a page whose
       job is long-form prose. */
    font-size: var(--fl-font-size-300);
    line-height: 1.5;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    text-rendering: optimizeLegibility;
}

/* Theme-driven thin scrollbars on the site's own chrome. The scrollbars inside a demo belong to
   whatever that demo renders and are deliberately left alone. */
html,
body,
.bb-docs-sidebar,
.bb-rail,
.bb-scroll,
pre {
    scrollbar-width: thin;
    scrollbar-color: var(--bit-clr-brd-sec) transparent;
}

::selection {
    background: var(--bb-primary-soft);
    color: var(--bb-primary-hover);
}

a {
    color: var(--bb-primary);
    text-decoration: none;
    transition: color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

a:hover {
    color: var(--bb-primary-hover);
    text-decoration: underline;
    text-underline-offset: .18em;
}

img,
svg {
    max-width: 100%;
}

/* One focus indicator for the whole site, drawn the Fluent 2 way: a hairline in the surface
   color hugging the control, and a heavier neutral stroke outside it. Written as an outline plus
   a ring shadow so it follows the control's own corner radius and never displaces layout.

   Not on elements with tabindex="-1": those are focused by script, never by Tab. The page heading
   <FocusOnNavigate Selector="h1"> (Routes.razor) moves focus to after every navigation, so
   assistive technology announces the new page, is one; the <main> the skip link lands on is
   another; a library's own dialog or popover container is a third. A ring there would say "you are
   on a control", which none of them is - and on a library's container the ring's shadow would
   also replace the elevation the library draws. :where() keeps the exclusion from adding
   specificity, so a field's own focus style (section 7b) still wins over this one. */
:focus-visible:where(:not([tabindex="-1"])) {
    outline: 2px solid var(--fl-stroke-focus-outer);
    outline-offset: 1px;
    box-shadow: 0 0 0 1px var(--fl-stroke-focus-inner);
}

[tabindex="-1"]:focus-visible:where(h1, h2, h3, h4, h5, h6, main, article, section) {
    outline: none;
}

/* The first thing in the tab order: a keyboard reader lands on it before the nav and can jump
   straight past the chrome. Off-screen until focused, never display:none - a hidden element is
   not focusable at all. */
.bb-skip-link {
    position: fixed;
    top: .5rem;
    left: .5rem;
    z-index: 1200;
    transform: translateY(calc(-100% - 1rem));
    padding: .5rem .875rem;
    border-radius: var(--bb-radius);
    background: var(--bb-primary);
    color: var(--bb-primary-text);
    font-size: var(--fl-font-size-200);
    font-weight: var(--fl-weight-semibold);
    transition: transform var(--bb-motion-duration) var(--bb-motion-enter);
}

/* The elevation is only drawn once the link is on screen: parked above the viewport, its shadow
   would still reach a few pixels down into the corner of the header. */
.bb-skip-link:focus-visible {
    transform: translateY(0);
    color: var(--bb-primary-text);
    text-decoration: none;
    box-shadow: var(--bb-shadow-flyout);
}

/* ============================================================================================
   4. Typography - Fluent 2's ramp. Titles carry weight as well as size, which is the difference
   between this ramp and Fluent 1's.
   ============================================================================================ */

h1,
h2,
h3,
h4,
h5,
h6 {
    color: var(--bb-text);
    font-family: var(--bb-font-display);
    font-weight: var(--fl-weight-semibold);
    margin: 0 0 .5rem;
    letter-spacing: -.01em;
    text-wrap: balance;
}

/* Title1 */
h1 {
    font-size: var(--fl-font-size-700);
    line-height: 1.25;
    letter-spacing: -.02em;
}

/* Title3 */
h2 {
    font-size: var(--fl-font-size-500);
    line-height: 1.33;
}

/* Subtitle1 */
h3 {
    font-size: var(--fl-font-size-400);
    line-height: 1.4;
}

/* Subtitle2 */
h4 {
    font-size: var(--fl-font-size-300);
    line-height: 1.5;
}

h5,
h6 {
    font-size: var(--fl-font-size-200);
    line-height: 1.43;
}

@media (max-width: 600px) {
    h1 { font-size: var(--fl-font-size-600); }
    h2 { font-size: var(--fl-font-size-400); }
    h3 { font-size: var(--fl-font-size-300); }
}

p {
    margin: 0 0 .75rem;
}

strong,
b {
    font-weight: var(--fl-weight-semibold);
}

/* No ligatures: Cascadia Code would draw `=>` and `!=` as single glyphs, and code on this site is
   read in order to be typed - the reader should see the characters they will type. */
code,
kbd,
pre,
samp {
    font-family: var(--bb-mono);
    font-variant-ligatures: none;
}

/* Inline code. Quieter than the old brand-tinted pill: in a docs paragraph half the nouns are
   identifiers, and colouring every one of them turns the prose into a link farm. */
code {
    font-size: .875em;
    background: var(--bb-surface-sunken);
    border: 1px solid var(--bb-border);
    color: var(--bb-text);
    padding: .0625rem .3125rem;
    border-radius: var(--bb-radius);
    overflow-wrap: anywhere;
}

/* Inside a link, though, it takes the link's color - otherwise the one word that IS the link
   looks like the one word that is not. */
a code {
    color: inherit;
    border-color: color-mix(in srgb, currentColor 30%, transparent);
    background: var(--bb-primary-soft);
}

/* A key on the keyboard, drawn as one. */
kbd {
    display: inline-block;
    min-width: 1.5rem;
    padding: .125rem .375rem;
    font-size: .75rem;
    line-height: 1.25;
    text-align: center;
    color: var(--bb-text-muted);
    background: var(--bb-surface);
    border: 1px solid var(--bb-border-strong);
    border-bottom-width: 2px;
    border-radius: var(--bb-radius);
}

hr {
    border: 0;
    border-top: 1px solid var(--bb-border);
    margin: 2rem 0;
}

/* ============================================================================================
   5. Layout - header band, content band, footer.
   ============================================================================================ */

.page {
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

.bb-site-content {
    flex: 1;
    width: 100%;
    background: var(--bb-bg);
}

main {
    width: 100%;
    max-width: var(--bb-content-width);
    margin: 0 auto;
    padding: 2.5rem 2rem 5rem;
}

@media (max-width: 960px) {
    main {
        padding: 2rem 1.5rem 3.5rem;
    }
}

@media (max-width: 600px) {
    main {
        padding: 1.5rem 1rem 3rem;
    }
}

article {
    width: 100%;
    min-width: 0;
}

/* The landing page is the one page built from full-bleed bands rather than from a column of
   content, so it opts out of the container and lays its own gutters out instead. */
main:has(.bb-landing) {
    max-width: none;
    padding: 0;
}

/* ============================================================================================
   6. Page intro - the title block every page opens with.
   ============================================================================================ */

.bb-intro {
    margin-bottom: 2.5rem;
}

.bb-intro .bb-overline {
    color: var(--bb-primary);
    margin-bottom: .5rem;
}

.bb-intro h1 {
    overflow-wrap: anywhere;
    margin-bottom: .75rem;
}

.bb-intro .bb-subtitle {
    color: var(--bb-text-muted);
    font-size: var(--fl-font-size-300);
    line-height: 1.6;
    max-width: var(--bb-measure);
    margin: 0;
}

/* ============================================================================================
   7. Buttons - Fluent 2's Primary / Secondary / Subtle variants.
   ============================================================================================ */

.btn,
button.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: .375rem;
    /* Fluent 2's medium control height, and a touch target that clears the 44px guidance once the
       0.25rem of vertical rhythm around it is counted. */
    min-height: 2rem;
    padding: .3125rem .75rem;
    font-family: inherit;
    font-size: var(--fl-font-size-200);
    font-weight: var(--fl-weight-semibold);
    line-height: 1.43;
    border-radius: var(--bb-radius);
    border: 1px solid transparent;
    background: var(--bb-surface);
    color: var(--bb-text);
    cursor: pointer;
    text-decoration: none;
    white-space: nowrap;
    transition: background var(--bb-motion-duration-short) var(--bb-motion-easing),
                border-color var(--bb-motion-duration-short) var(--bb-motion-easing),
                color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

.btn:hover {
    text-decoration: none;
}

.btn svg {
    width: 1em;
    height: 1em;
    flex: none;
}

.btn[disabled],
.btn:disabled {
    cursor: not-allowed;
    opacity: .45;
}

/* Primary - the filled brand button. */
.btn-primary,
button.btn-primary {
    background: var(--bb-primary);
    color: var(--bb-primary-text);
    border-color: var(--bb-primary);
}

.btn-primary:hover,
button.btn-primary:hover {
    background: var(--bb-primary-hover);
    border-color: var(--bb-primary-hover);
    color: var(--bb-primary-text);
}

.btn-primary:active,
button.btn-primary:active {
    background: var(--bb-primary-active);
    border-color: var(--bb-primary-active);
}

/* Secondary - Fluent 2's default button: a neutral surface with a neutral stroke. This is the
   variant most of the site's "go and look at this" links want, which is why it, rather than the
   brand outline, is what a bare `.btn` already looks like. */
.btn-secondary,
button.btn-secondary {
    background: var(--bb-surface);
    color: var(--bb-text);
    border-color: var(--bb-border-strong);
}

.btn-secondary:hover,
button.btn-secondary:hover {
    background: var(--bb-surface-hover);
    color: var(--bb-text);
}

/* Outline - the brand-stroked variant the pages use for their "go and try this" links. */
.btn-outline,
button.btn-outline {
    background: transparent;
    color: var(--bb-primary);
    border-color: color-mix(in srgb, var(--bb-primary) 45%, transparent);
}

.btn-outline:hover,
button.btn-outline:hover {
    color: var(--bb-primary-hover);
    background: var(--bb-primary-soft);
    border-color: var(--bb-primary);
}

/* Large - the landing page's calls to action. Restated for <button>: `button.btn` above outranks a
   lone class, and would otherwise keep a large button at the medium size. */
.bb-btn-lg,
button.bb-btn-lg {
    min-height: 2.75rem;
    padding: .625rem 1.25rem;
    font-size: var(--fl-font-size-300);
    border-radius: var(--bb-radius-lg);
}

/* An icon-only button: square, quiet, and sized for a finger. */
.bb-icon-btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    flex: none;
    border: 1px solid transparent;
    border-radius: var(--bb-radius);
    background: transparent;
    color: var(--bb-text-muted);
    cursor: pointer;
    transition: background var(--bb-motion-duration-short) var(--bb-motion-easing),
                color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

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

.bb-icon-btn svg {
    width: 18px;
    height: 18px;
}

/* A row of "try it" links under a paragraph. */
.bb-try {
    display: flex;
    flex-wrap: wrap;
    gap: .5rem;
    margin: .25rem 0 1.25rem;
}

/* ============================================================================================
   7b. Form controls - Fluent 2's Input, Textarea and Select.

   The signature of a Fluent 2 field is the bottom stroke: a neutral hairline all round, a heavier
   line along the bottom edge, and on focus that bottom line thickens into the brand color while
   the rest of the border stays put. Applied to the elements themselves rather than to a class,
   because the demo pages render plain inputs - a design system that only reaches markup written
   for it is not a design system.

   Only the inputs a reader TYPES into are fields. A slider, a color well, a file picker or a
   checkbox is not, and dressing one up as a text box changes its size as it gains and loses focus
   - which moves everything below it. Section 26 gives the other input types the brand accent
   instead.

   Every selector here is wrapped in :where(), so the resting look has no specificity at all and the
   states carry only their pseudo-class: a library that draws its own fields (a forms library, a
   canvas text editor, a palette's search box) wins with a single class, at rest, on hover and on
   focus, and a demo restyles a field the same way. The focus rule still outranks the site-wide
   focus ring in section 3, by coming after it at the same weight.
   ============================================================================================ */

:where(input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="url"], input[type="tel"], input[type="password"], input[type="number"], input[type="date"], input[type="datetime-local"], input[type="time"], input[type="month"], input[type="week"], textarea, select, .form-control) {
    width: auto;
    max-width: 100%;
    min-height: 2rem;
    padding: .3125rem .625rem;
    font-family: inherit;
    font-size: var(--fl-font-size-200);
    line-height: 1.43;
    color: var(--bb-text);
    background: var(--bb-surface);
    border: 1px solid var(--bb-border-strong);
    border-bottom-color: var(--bb-text-soft);
    border-radius: var(--bb-radius);
    transition: border-color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

:where(textarea) {
    width: 100%;
    padding: .5rem .625rem;
    line-height: 1.6;
    resize: vertical;
}

:where(input, textarea)::placeholder {
    color: var(--bb-text-soft);
}

:where(input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="url"], input[type="tel"], input[type="password"], input[type="number"], input[type="date"], input[type="datetime-local"], input[type="time"], input[type="month"], input[type="week"], textarea, select, .form-control):hover:where(:not(:disabled)) {
    border-color: var(--bb-text-soft);
}

/* Focus: the brand underline, and no ring - the moving line IS the indicator here, which is what
   Fluent 2 does for a field. Everything else on the site keeps the neutral double ring. */
:where(input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="url"], input[type="tel"], input[type="password"], input[type="number"], input[type="date"], input[type="datetime-local"], input[type="time"], input[type="month"], input[type="week"], textarea, select, .form-control):focus-visible {
    outline: none;
    box-shadow: none;
    border-color: var(--bb-border-strong);
    border-bottom: 2px solid var(--bb-primary);
    /* The border grew by a pixel, so the padding gives it back and the text does not jump. */
    padding-bottom: calc(.3125rem - 1px);
}

:where(textarea):focus-visible {
    padding-bottom: calc(.5rem - 1px);
}

:where(input:not([type]), input[type="text"], input[type="search"], input[type="email"], input[type="url"], input[type="tel"], input[type="password"], input[type="number"], input[type="date"], input[type="datetime-local"], input[type="time"], input[type="month"], input[type="week"], textarea, select, .form-control):disabled {
    color: var(--bb-text-soft);
    background: var(--bb-surface-sunken);
    cursor: not-allowed;
}

/* A search input's native clear button is drawn by the UA in its own color; hiding it lets the
   field look the same in every browser. */
input[type="search"]::-webkit-search-decoration,
input[type="search"]::-webkit-search-cancel-button {
    -webkit-appearance: none;
}

/* ============================================================================================
   8. Cards and sections

   `.bb-card` plays two roles on this site, and the difference is structural rather than a class
   the author has to remember:

     - inside a grid or a flex stack it is a TILE, and gets Fluent's card chrome: a raised
       surface, a hairline and elevation 2;
     - standing on its own in the docs column it is a SECTION of a document, and gets none of
       that. Thirty bordered boxes stacked down a reference page is a filing cabinet, not a
       document - the heading and the space around it are what separate one section from the
       next, exactly as they do in print.

   Every documentation page is written as a stack of `.bb-card`s, so this one distinction is what
   turns them into prose without a single page being edited.
   ============================================================================================ */

.bb-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-card);
    padding: 1.25rem;
    margin-bottom: 1rem;
    color: var(--bb-text-muted);
}

/* `anywhere` lets one long identifier in a heading (a type name, say) break rather than push a
   phone-width page sideways: it lowers the title text's min-content width, which is what a flex
   item is not allowed to shrink below. A title that fits never breaks. */
.bb-card-title {
    display: flex;
    align-items: center;
    gap: .5rem;
    overflow-wrap: anywhere;
    font-size: var(--fl-font-size-300);
    font-weight: var(--fl-weight-semibold);
    line-height: 1.5;
    color: var(--bb-text);
    margin: 0 0 .375rem;
}

.bb-card-desc {
    color: var(--bb-text-muted);
    font-size: var(--fl-font-size-200);
    line-height: 1.6;
    margin: 0 0 1rem;
}

.bb-card-desc:last-child {
    margin-bottom: 0;
}

/* A tile the whole of which is a link. */
a.bb-card {
    display: block;
    color: var(--bb-text-muted);
    transition: border-color var(--bb-motion-duration-short) var(--bb-motion-easing),
                box-shadow var(--bb-motion-duration-short) var(--bb-motion-easing);
}

a.bb-card:hover {
    text-decoration: none;
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-raised);
}

.bb-grid {
    display: grid;
    /* min() on the track floor rather than a bare 280px: below that width a fixed minimum makes
       the track wider than its own container and the page picks up a horizontal scrollbar. */
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
    gap: 1rem;
    margin-bottom: 1rem;
}

/* Tiles in a grid are laid out as columns so their footer links line up along the bottom edge
   regardless of how much prose each one carries above them. */
.bb-grid > .bb-card {
    display: flex;
    flex-direction: column;
    margin-bottom: 0;
}

/* The trailing call to action is pushed to the bottom of its tile rather than the prose above it
   being stretched: `margin-top: auto` lines the buttons up along one baseline across the row
   whatever each tile has to say, and a tile that ends in a list instead keeps that list directly
   under the sentence introducing it. */
.bb-grid > .bb-card > .btn:last-child,
.bb-grid > .bb-card > .bb-try:last-child {
    align-self: flex-start;
    margin-top: auto;
    margin-bottom: 0;
}

.bb-flex {
    display: flex;
    flex-direction: column;
    gap: 1rem;
    margin-bottom: 1rem;
}

.bb-flex > .bb-card {
    margin-bottom: 0;
}

/* A band on the landing page and other full-width pages. */
.bb-section {
    margin-bottom: 3rem;
}

.bb-section-sub {
    color: var(--bb-text-muted);
    max-width: var(--bb-measure);
    margin-bottom: 1.5rem;
}

/* ============================================================================================
   9. Documentation prose - the flattening described above, scoped to the docs column.
   ============================================================================================ */

/* A section of the document: no frame, no fill, no elevation. What separates one section from the
   next is the space between them and the hairline under each heading - the same two devices a
   printed reference uses, and the reason a page of thirty of them still reads as one document. */
.bb-docs-content > .bb-card {
    background: none;
    border: 0;
    border-radius: 0;
    box-shadow: none;
    padding: 0;
    margin: 0 0 2.5rem;
    color: var(--bb-text-muted);
}

/* Restated for the grids and stacks INSIDE a docs page - a "find your topic" grid is still a set
   of tiles, and the rule above would have flattened those too. */
.bb-docs-content .bb-grid > .bb-card,
.bb-docs-content .bb-flex > .bb-card,
.bb-docs-content .bb-card .bb-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-card);
    padding: 1.25rem;
    margin-bottom: 0;
}

/* A flattened section's title is a document heading, so it takes Fluent's Title3 rather than the
   card title's Subtitle2 - the level below the page's own H1. */
.bb-docs-content > .bb-card > .bb-card-title {
    font-size: var(--fl-font-size-500);
    font-weight: var(--fl-weight-semibold);
    line-height: 1.33;
    letter-spacing: -.01em;
    margin: 0 0 .75rem;
    padding-bottom: .625rem;
    border-bottom: 1px solid var(--bb-border);
    scroll-margin-top: calc(var(--bb-header-height) + 1.5rem);
}

/* The prose of a section, and the only thing on the page held to the reading measure. The column
   itself is uncapped (see DocsLayout.razor.css) so code samples and API tables get its full width;
   holding the line length here rather than there is what lets both be true at once. */
.bb-docs-content > .bb-card > .bb-card-desc,
.bb-docs-content > .bb-card > p,
.bb-docs-content > p {
    font-size: var(--fl-font-size-300);
    line-height: 1.65;
    max-width: var(--bb-measure);
    margin-bottom: 1rem;
}

/* The dot in front of a section heading. It is not always decoration - a live sample can use it
   as a status light - so it stays, but at the larger heading size it is drawn as a marker in the
   margin rather than as a bullet crowding the first word. */
.bb-docs-content > .bb-card > .bb-card-title > .bb-dot {
    width: 10px;
    height: 10px;
    margin-inline-end: .125rem;
}

/* An H2 in the docs column groups several sections under it - the API reference and the FAQ are
   both built that way - so it has to outrank the section headings underneath it on both counts a
   heading is ranked by: it is a step larger, and its rule is the brand's rather than a hairline.
   The page's own H1, the H2 parts and the H3 sections then run 32 / 28 / 24, which is three
   consecutive steps of Fluent's ramp and no invented sizes. */
.bb-docs-content > h2 {
    font-size: var(--fl-font-size-600);
    margin: 3.5rem 0 1.5rem;
    padding-bottom: .5rem;
    border-bottom: 2px solid var(--bb-primary);
}

.bb-docs-content > h2:first-child {
    margin-top: 0;
}

/* The anchor link site.js hangs off every section heading: invisible until the heading is hovered
   or the link itself is focused, so it never competes with the title. */
.bb-anchor {
    display: inline-flex;
    align-items: center;
    margin-inline-start: .4rem;
    color: var(--bb-text-soft);
    font-weight: var(--fl-weight-regular);
    opacity: 0;
    transition: opacity var(--bb-motion-duration-short) var(--bb-motion-easing);
}

.bb-anchor svg {
    width: 15px;
    height: 15px;
}

:is(h1, h2, h3, .bb-card-title):hover > .bb-anchor,
.bb-anchor:focus-visible {
    opacity: 1;
}

.bb-anchor:hover {
    color: var(--bb-primary);
    text-decoration: none;
}

/* ============================================================================================
   10. Lists
   ============================================================================================ */

.bb-link-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 1px;
}

.bb-link-list li {
    display: flex;
    align-items: center;
}

.bb-link-list a {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    width: 100%;
    padding: .375rem .5rem;
    border-radius: var(--bb-radius);
    font-size: var(--fl-font-size-200);
    line-height: 1.5;
    color: var(--bb-primary);
    text-decoration: none;
    transition: background var(--bb-motion-duration-short) var(--bb-motion-easing),
                color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

.bb-link-list a:hover {
    background: var(--bb-surface-hover);
    color: var(--bb-primary-hover);
    text-decoration: none;
}

.bb-link-list a.active {
    background: var(--bb-primary-soft);
    color: var(--bb-primary-hover);
    font-weight: var(--fl-weight-semibold);
}

/* Prose-style list: items mix text with inline links and code. */
.bb-detail-list {
    margin: 0 0 1rem;
    padding-inline-start: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: .375rem;
    color: var(--bb-text-muted);
    font-size: var(--fl-font-size-200);
    line-height: 1.65;
}

.bb-docs-content > .bb-card .bb-detail-list {
    font-size: var(--fl-font-size-300);
    max-width: var(--bb-measure);
}

.bb-detail-list::marker,
.bb-detail-list li::marker {
    color: var(--bb-text-soft);
}

/* ============================================================================================
   11. Badges - Fluent 2's Badge, in its tinted "filled-light" appearance.
   ============================================================================================ */

.bb-badge {
    display: inline-flex;
    align-items: center;
    gap: .25rem;
    font-size: var(--fl-font-size-100);
    font-weight: var(--fl-weight-semibold);
    line-height: 1.25;
    padding: .1875rem .5rem;
    border-radius: var(--bb-radius-pill);
    letter-spacing: .01em;
    background: var(--bb-primary-soft);
    color: var(--bb-primary-hover);
    white-space: nowrap;
}

.bb-badge.bb-badge-warn {
    background: var(--bb-warning-soft);
    color: var(--bb-warning-text);
}

.bb-badge.bb-badge-danger {
    background: var(--bb-danger-soft);
    color: var(--bb-danger-text);
}

.bb-badge.bb-badge-success {
    background: var(--bb-success-soft);
    color: var(--bb-success-text);
}

/* Fluent's Overline: the small, spaced, uppercase label that sits over a group. */
.bb-overline {
    display: block;
    font-size: var(--fl-font-size-100);
    font-weight: var(--fl-weight-semibold);
    line-height: 1.33;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bb-text-soft);
    margin: 0;
}

/* ============================================================================================
   12. Status dots
   ============================================================================================ */

.bb-dot {
    width: 8px;
    height: 8px;
    border-radius: var(--bb-radius-pill);
    background: var(--bb-text-soft);
    flex: none;
}

.bb-dot-primary { background: var(--bb-primary); }
.bb-dot-success { background: var(--bb-success); }
.bb-dot-warning { background: var(--bb-warning); }
.bb-dot-danger { background: var(--bb-danger); }

/* ============================================================================================
   13. Tables
   ============================================================================================ */

.bb-table,
.table {
    width: 100%;
    border-collapse: separate;
    border-spacing: 0;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
    font-size: var(--fl-font-size-200);
    line-height: 1.5;
    margin-bottom: 1.25rem;
}

.bb-table thead th,
.table thead th {
    text-align: start;
    padding: .625rem .875rem;
    background: var(--bb-surface-sunken);
    border-bottom: 1px solid var(--bb-border);
    color: var(--bb-text-muted);
    font-weight: var(--fl-weight-semibold);
    font-size: var(--fl-font-size-100);
    text-transform: uppercase;
    letter-spacing: .05em;
    white-space: nowrap;
}

.bb-table td,
.table td {
    padding: .625rem .875rem;
    border-top: 1px solid var(--bb-border);
    vertical-align: top;
    color: var(--bb-text-muted);
}

.bb-table tbody tr:first-child td,
.table tbody tr:first-child td {
    border-top: 0;
}

.bb-table tbody tr:hover td,
.table tbody tr:hover td {
    background: var(--bb-surface-hover);
}

/* The identifier column: monospaced and in the foreground color, because it is the thing the
   reader is scanning for. */
.bb-table td:first-child {
    font-family: var(--bb-mono);
    font-size: .9em;
    color: var(--bb-text);
}

/* A table's used width can never fall below the sum of its columns' MIN-CONTENT widths, so a
   single unbreakable cell anywhere in it sizes the whole table - and, since these tables are
   full-width, overflows whatever holds them. Making one column breakable is therefore not a fix:
   it has to be every cell, headers included, which is also why the identifier column above cannot
   be `white-space: nowrap`.

   `anywhere` and not `break-word`: the two wrap identically at a given width, but only `anywhere`
   lowers the intrinsic minimum - and the intrinsic minimum is the number the table is sized from,
   so `break-word` here would look fixed and still overflow. Neither breaks a word that already
   fits, so this costs nothing at widths where the table was fine. */
.bb-table th,
.bb-table td,
.table th,
.table td {
    overflow-wrap: anywhere;
}

/* A column of buttons rather than of prose: `width: 1%` in an auto-layout table reads as "give
   this column its minimum", so the button keeps its label on one line and every pixel the column
   does not need goes to the text columns instead of squeezing them. This is the one place the
   cells' `overflow-wrap: anywhere` must not reach - a broken button label is worse than a wide
   column, and a button's minimum is small enough to afford. A key column - the names of tools,
   members or options a reader scans for - takes the same treatment for the same reason: a name
   broken letter by letter cannot be scanned. Inside .bb-scroll a table that no longer fits
   scrolls on its own. */
.bb-table .bb-table-key,
.bb-table .bb-table-action {
    width: 1%;
    white-space: nowrap;
    overflow-wrap: normal;
}

/* A wide table on a narrow screen scrolls inside its own box rather than widening the page. */
.bb-scroll {
    overflow-x: auto;
    margin-bottom: 1.25rem;
}

.bb-scroll > .bb-table,
.bb-scroll > .table {
    margin-bottom: 0;
}

/* ============================================================================================
   14. Definition list - the label/value readout the live samples use.
   ============================================================================================ */

.bb-params {
    display: grid;
    grid-template-columns: max-content minmax(0, 1fr);
    gap: 0;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-card);
    padding: 0;
    overflow: hidden;
    font-size: var(--fl-font-size-200);
    margin: 0 0 1.25rem;
}

.bb-params dt {
    color: var(--bb-text-muted);
    font-weight: var(--fl-weight-semibold);
    text-transform: uppercase;
    font-size: var(--fl-font-size-100);
    letter-spacing: .05em;
    padding: .5rem .875rem;
    background: var(--bb-surface-sunken);
    border-top: 1px solid var(--bb-border);
    display: flex;
    align-items: center;
}

.bb-params dd {
    margin: 0;
    padding: .5rem .875rem;
    border-top: 1px solid var(--bb-border);
    font-family: var(--bb-mono);
    font-size: .9em;
    color: var(--bb-text);
    overflow-wrap: anywhere;
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: .25rem;
}

.bb-params > dt:first-of-type,
.bb-params > dt:first-of-type + dd {
    border-top: 0;
}

/* ============================================================================================
   15. Notes - Fluent 2's MessageBar: an icon-less tinted band with the role's color as its
   leading rule.
   ============================================================================================ */

.bb-note {
    border: 1px solid color-mix(in srgb, var(--bb-primary) 30%, transparent);
    border-inline-start: 3px solid var(--bb-primary);
    background: var(--bb-primary-soft);
    color: var(--bb-text);
    border-radius: var(--bb-radius-lg);
    padding: .75rem 1rem;
    font-size: var(--fl-font-size-200);
    line-height: 1.65;
    margin: 0 0 1.25rem;
}

.bb-note > :last-child {
    margin-bottom: 0;
}

.bb-note code {
    background: color-mix(in srgb, var(--bb-surface) 60%, transparent);
}

.bb-note-warn {
    border-color: color-mix(in srgb, var(--bb-warning) 40%, transparent);
    border-inline-start-color: var(--bb-warning);
    background: var(--bb-warning-soft);
}

.bb-note-danger {
    border-color: color-mix(in srgb, var(--bb-danger) 40%, transparent);
    border-inline-start-color: var(--bb-danger);
    background: var(--bb-danger-soft);
}

.bb-note-success {
    border-color: color-mix(in srgb, var(--bb-success) 40%, transparent);
    border-inline-start-color: var(--bb-success);
    background: var(--bb-success-soft);
}

.bb-docs-content .bb-note {
    font-size: var(--fl-font-size-300);
    max-width: var(--bb-measure);
}

/* ============================================================================================
   16. Code samples
   ============================================================================================ */

.bb-code {
    position: relative;
    background: var(--bb-code-bg);
    color: var(--bb-code-fg);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    padding: .875rem 3rem .875rem 1rem;
    font-family: var(--bb-mono);
    font-size: .8125rem;
    line-height: 1.7;
    overflow-x: auto;
    margin: 0 0 1.25rem;
    white-space: pre;
    tab-size: 4;
}

.bb-code::-webkit-scrollbar { width: 8px; }
.bb-code::-webkit-scrollbar:horizontal { height: 8px; }
.bb-code::-webkit-scrollbar-track { background-color: transparent; }
.bb-code::-webkit-scrollbar-thumb { border-radius: 8px; background-color: var(--bit-clr-brd-sec); }
.bb-code::-webkit-scrollbar-button { display: none; }

.bb-code .c { color: var(--bb-code-comment); font-style: italic; }  /* comment */
.bb-code .k { color: var(--bb-code-keyword); }                      /* keyword / tag */
.bb-code .s { color: var(--bb-code-string); }                       /* string / template */
.bb-code .p { color: var(--bb-code-param); }                        /* parameter */

/* A <code> inside a code block is part of the block, not an inline identifier: it drops the chip
   that inline code is drawn as and takes the block's own color and size. */
pre code {
    padding: 0;
    border: 0;
    border-radius: 0;
    background: none;
    color: inherit;
    font-size: inherit;
    overflow-wrap: normal;
}

/* The copy button site.js appends to every code block. Always visible rather than
   hover-revealed: on a touch screen there is no hover, and the button is the only way to take the
   sample. It is appended INTO the <pre> rather than wrapped around it, which is what keeps Blazor
   from ever diffing over it - the render tree's shape for the element never changes, so the node
   added here is simply never visited. */
.bb-copy-btn {
    position: absolute;
    top: .5rem;
    inset-inline-end: .5rem;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 30px;
    height: 30px;
    padding: 0;
    border: 1px solid transparent;
    border-radius: var(--bb-radius);
    background: color-mix(in srgb, var(--bb-code-bg) 85%, transparent);
    color: var(--bb-text-soft);
    cursor: pointer;
    transition: color var(--bb-motion-duration-short) var(--bb-motion-easing),
                background var(--bb-motion-duration-short) var(--bb-motion-easing),
                border-color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

.bb-copy-btn:hover {
    color: var(--bb-primary);
    border-color: var(--bb-border-strong);
    background: var(--bb-surface);
}

.bb-copy-btn svg {
    width: 15px;
    height: 15px;
}

.bb-copy-btn.bb-copied {
    color: var(--bb-success);
    border-color: var(--bb-success);
    background: var(--bb-surface);
}

/* ============================================================================================
   17. Empty state
   ============================================================================================ */

.bb-empty {
    background: var(--bb-surface);
    border: 1px dashed var(--bb-border-strong);
    border-radius: var(--bb-radius-lg);
    padding: 2rem 1.5rem;
    text-align: center;
    color: var(--bb-text-muted);
    font-size: var(--fl-font-size-200);
    margin-bottom: 1rem;
}

/* ============================================================================================
   18. Error pages
   ============================================================================================ */

.bb-error {
    text-align: center;
    padding: 4rem 1.5rem;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-xl);
    box-shadow: var(--bb-shadow-card);
}

.bb-error h1 {
    font-size: var(--fl-font-size-900);
    font-weight: var(--fl-weight-semibold);
    letter-spacing: -.04em;
    margin: 0;
    line-height: 1;
}

.bb-error.bb-error-404 h1 { color: var(--bb-text-soft); }
.bb-error.bb-error-403 h1 { color: var(--bb-warning); }

.bb-error p {
    color: var(--bb-text-muted);
    max-width: 46ch;
    margin: .75rem auto 1.5rem;
}

.bb-error-actions {
    justify-content: center;
    margin-bottom: 1.5rem;
}

.bb-error-hint {
    font-size: var(--fl-font-size-200);
    color: var(--bb-text-soft);
    margin-bottom: 0;
}

/* ============================================================================================
   19. Docs pager (DocsPager, rendered by DocsLayout)
   ============================================================================================ */

.bb-pager {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 1rem;
    margin-top: 3rem;
}

.bb-pager-link {
    display: flex;
    flex-direction: column;
    gap: .25rem;
    padding: .875rem 1rem;
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    background: var(--bb-surface);
    box-shadow: var(--bb-shadow-card);
    text-decoration: none;
    min-width: 0;
    transition: border-color var(--bb-motion-duration-short) var(--bb-motion-easing),
                box-shadow var(--bb-motion-duration-short) var(--bb-motion-easing);
}

.bb-pager-link:hover {
    border-color: var(--bb-primary);
    box-shadow: var(--bb-shadow-raised);
    text-decoration: none;
}

.bb-pager-next {
    grid-column: 2;
    text-align: end;
    align-items: flex-end;
}

.bb-pager-label {
    font-size: var(--fl-font-size-100);
    text-transform: uppercase;
    letter-spacing: .06em;
    font-weight: var(--fl-weight-semibold);
    color: var(--bb-text-soft);
}

.bb-pager-title {
    font-weight: var(--fl-weight-semibold);
    font-size: var(--fl-font-size-200);
    color: var(--bb-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 100%;
}

/* ============================================================================================
   20. "On this page" rail - built by site.js from whatever headings the current page rendered,
   so no docs page had to be edited to gain one.
   ============================================================================================ */

.bb-rail {
    position: sticky;
    top: calc(var(--bb-header-height) + 1.75rem);
    flex: 0 0 var(--bb-rail-width);
    height: fit-content;
    max-height: calc(100vh - var(--bb-header-height) - 3.5rem);
    overflow: auto;
    padding: 0 .5rem 2rem 0;
    /* Persistent chrome: keep it out of the page's view transition, like the header. */
    view-transition-name: bb-rail;
}

.bb-rail:empty {
    padding: 0;
}

.bb-rail-title {
    display: block;
    font-size: var(--fl-font-size-100);
    font-weight: var(--fl-weight-semibold);
    line-height: 1.33;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bb-text-soft);
    margin: 0 0 .5rem;
    padding-inline-start: .75rem;
}

.bb-rail ul {
    list-style: none;
    padding: 0;
    margin: 0;
    border-inline-start: 1px solid var(--bb-border);
}

.bb-rail li {
    position: relative;
    padding: .1875rem .75rem;
    overflow-wrap: anywhere;
}

.bb-rail li.bb-rail-sub {
    padding-inline-start: 1.5rem;
}

.bb-rail a {
    display: block;
    font-size: var(--fl-font-size-200);
    line-height: 1.5;
    color: var(--bb-text-muted);
    text-decoration: none;
    transition: color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

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

/* The current section: its entry takes the brand color and some weight, and its stretch of the
   spine lights up in the same color - drawn as an overlay on the list's own hairline so active
   and inactive entries keep exactly the same geometry. */
.bb-rail li.bb-active::before {
    content: "";
    position: absolute;
    top: 0;
    bottom: 0;
    width: 2px;
    inset-inline-start: -1px;
    border-radius: var(--bb-radius-pill);
    background: var(--bb-primary);
}

.bb-rail li.bb-active a {
    color: var(--bb-primary);
    font-weight: var(--fl-weight-semibold);
}

.bb-rail-top {
    display: inline-flex;
    align-items: center;
    gap: .375rem;
    margin: 1rem 0 0 .75rem;
    padding: 0;
    border: 0;
    background: none;
    color: var(--bb-text-muted);
    font-family: inherit;
    font-size: var(--fl-font-size-200);
    cursor: pointer;
}

.bb-rail-top:hover {
    color: var(--bb-primary);
}

.bb-rail-top svg {
    width: 14px;
    height: 14px;
}

/* A page whose samples need the width - a canvas, a board, a wide grid - gives up the rail: any
   element with .bb-page-wide in the page turns the docs grid into two columns. Global rather than
   in DocsLayout.razor.css because the marker lives in the page, outside that component's scope;
   `div.` outranks the scoped rule, and the narrow-width rules below still take over. */
div.bb-docs:has(.bb-docs-content .bb-page-wide) {
    grid-template-columns: var(--bb-nav-panel-width) minmax(0, 1fr);
}

div.bb-docs:has(.bb-docs-content .bb-page-wide) > .bb-rail {
    display: none;
}

/* Anchored headings need clearance for the sticky header when something scrolls to them. */
:target,
.bb-docs-content [id],
article [id] {
    scroll-margin-top: calc(var(--bb-header-height) + 1.5rem);
}

/* ============================================================================================
   21. Theme toggle - lives here rather than in Header.razor.css because the sun/moon swap keys
   off the bit-theme attribute on <html>, which a scoped-CSS selector cannot reach.
   ============================================================================================ */

.bb-theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 32px;
    height: 32px;
    padding: 0;
    flex: none;
    border: 1px solid transparent;
    border-radius: var(--bb-radius);
    background: transparent;
    color: var(--bb-text-muted);
    cursor: pointer;
    transition: background var(--bb-motion-duration-short) var(--bb-motion-easing),
                color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

.bb-theme-toggle:hover {
    background: var(--bb-surface-hover);
    color: var(--bb-text);
}

.bb-theme-toggle svg {
    width: 18px;
    height: 18px;
}

.bb-theme-toggle .bb-icon-moon { display: none; }

:root[bit-theme="dark"] .bb-theme-toggle .bb-icon-sun { display: none; }
:root[bit-theme="dark"] .bb-theme-toggle .bb-icon-moon { display: block; }

/* ============================================================================================
   22. Narrow viewports - the handful of components whose desktop shape does not survive a phone.
   Everything here earns its place by preventing horizontal overflow, which is the one layout
   failure a reader cannot work around: a page wider than the screen makes every line of prose on
   it require sideways scrolling to finish.
   ============================================================================================ */

/* Tighter cells buy back some of the width the wrapping spends, so each column holds a few more
   characters before it has to break a word - which is what keeps the breaks landing between words
   rather than inside them. The wrapping itself is unconditional (see `overflow-wrap` on the
   cells): these tables sit in the docs column, whose width comes from the sidebar and rail
   flanking it rather than from the viewport, so a viewport breakpoint is the wrong axis to hang
   it on - it leaves the table overflowing on a wide screen with a narrow content column. */
@media (max-width: 760px) {
    .bb-table th,
    .bb-table td,
    .table th,
    .table td {
        padding: .5rem .5rem;
        font-size: .8125rem;
    }
}

/* Docs prose runs to long identifiers, package names and URLs; in a phone-width column any one of
   them is wider than the line, so they are allowed to break rather than to overflow. */
@media (max-width: 960px) {
    .bb-card,
    .bb-intro,
    .bb-detail-list {
        overflow-wrap: break-word;
    }
}

/* ============================================================================================
   23. Forced colors (Windows high contrast)

   In this mode the OS replaces every color the page chose, and a surface that was distinguished
   ONLY by its fill becomes invisible. Everything on this site that relies on a tint to say
   something - the selected nav row, the active rail entry, a tinted note - gets a border here so
   the same distinction survives being repainted.
   ============================================================================================ */

@media (forced-colors: active) {
    .bb-card,
    .bb-note,
    .bb-code,
    .bb-params,
    .bb-badge,
    .bb-pager-link,
    .btn {
        border: 1px solid CanvasText;
    }

    /* The dots and the rail's active marker are painted shapes with no text in them, so they
       would come back as blocks of the canvas color and disappear. */
    .bb-dot,
    .bb-rail li.bb-active::before {
        forced-color-adjust: none;
        background: LinkText;
    }

    :focus-visible:where(:not([tabindex="-1"])) {
        outline: 2px solid CanvasText;
    }
}

/* ============================================================================================
   24. Print

   A reference page is printed, or saved to PDF, more often than any other kind of web page. What
   is dropped is everything that is navigation rather than content - it cannot be followed on
   paper - and what is added is the one thing paper cannot carry: the address behind each link.
   ============================================================================================ */

@media print {
    :root {
        --bb-header-height: 0px;
    }

    html,
    body {
        background: #fff;
        color: #000;
        font-size: 11pt;
    }

    .bb-header,
    .bb-footer,
    .bb-rail,
    .bb-docs-sidebar,
    .bb-docs-topbar,
    .bb-pager,
    .bb-docs-foot,
    .bb-skip-link,
    .bb-copy-btn,
    .bb-anchor,
    .bb-try,
    .bb-hero-actions {
        display: none !important;
    }

    main,
    .bb-docs,
    .bb-docs-content,
    .bb-landing > section {
        display: block;
        max-width: none;
        padding: 0;
        margin: 0;
        background: none;
    }

    .bb-card,
    .bb-note,
    .bb-code,
    .bb-table,
    .bb-params {
        background: none;
        box-shadow: none;
        border-color: #999;
        /* A section split across a page break loses the connection between its heading and its
           content, which on a reference page is the whole of what it says. */
        break-inside: avoid;
    }

    .bb-code {
        white-space: pre-wrap;
        overflow: visible;
    }

    h1,
    h2,
    h3 {
        break-after: avoid;
    }

    /* On paper a link is just underlined words unless the address comes with it. Only external
       and absolute ones: printing "(#install)" after every in-page anchor is noise. */
    a[href^="http"]::after {
        content: " (" attr(href) ")";
        font-size: .85em;
        color: #555;
        word-break: break-all;
    }
}

@media (max-width: 600px) {
    /* Two pager cards side by side leave neither enough room for its title, and the ellipsis then
       hides the very thing the link is there to name. */
    .bb-pager {
        grid-template-columns: minmax(0, 1fr);
    }

    .bb-pager-next {
        grid-column: 1;
        text-align: start;
        align-items: flex-start;
    }

    /* A label column sized to its own content plus a value column cannot both fit. Stacked, the
       value gets a full line - which is what it needs, since these are URLs, identifiers and
       serialized state. */
    .bb-params {
        grid-template-columns: minmax(0, 1fr);
    }

    .bb-params dd {
        border-top: 0;
    }

    .bb-params > dt:first-of-type + dd {
        border-top: 0;
    }

    .bb-error {
        padding: 3rem 1rem;
    }

    .bb-error h1 {
        font-size: var(--fl-font-size-800);
    }
}

/* ============================================================================================
   25. Blazor framework UI - the unhandled-error bar and the error boundary's fallback, drawn as
   Fluent's danger MessageBar rather than the template's yellow strip.
   ============================================================================================ */

#blazor-error-ui {
    position: fixed;
    inset-inline: 0;
    bottom: 0;
    z-index: 1300;
    display: none;
    padding: .75rem 3rem .75rem 1.25rem;
    background: var(--bb-danger-soft);
    color: var(--bb-text);
    border-top: 1px solid color-mix(in srgb, var(--bb-danger) 40%, transparent);
    box-shadow: var(--bb-shadow-flyout);
    font-size: var(--fl-font-size-200);
    line-height: 1.5;
}

#blazor-error-ui .reload {
    margin-inline-start: .5rem;
    font-weight: var(--fl-weight-semibold);
}

#blazor-error-ui .dismiss {
    position: absolute;
    top: .625rem;
    inset-inline-end: 1rem;
    cursor: pointer;
}

.blazor-error-boundary {
    border: 1px solid color-mix(in srgb, var(--bb-danger) 40%, transparent);
    border-inline-start: 3px solid var(--bb-danger);
    background: var(--bb-danger-soft);
    color: var(--bb-danger-text);
    border-radius: var(--bb-radius-lg);
    padding: .75rem 1rem;
    margin: 0 0 1.25rem;
    font-size: var(--fl-font-size-200);
}

.blazor-error-boundary::after {
    content: "An error has occurred.";
}

/* ============================================================================================
   26. Live samples - the pieces a demo page builds its interactive examples from. A docs section
   (.bb-card) loses its frame in the docs column; a sample keeps it, because it is a thing on the
   page rather than a passage of it.
   ============================================================================================ */

/* The stage a live sample runs on: a raised surface with an optional title bar. */
.bb-demo {
    position: relative;
    min-width: 0;
    margin: 0 0 1.25rem;
    padding: 1.25rem;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-xl);
    box-shadow: var(--bb-shadow-card);
    color: var(--bb-text);
}

.bb-demo > :last-child {
    margin-bottom: 0;
}

/* The title bar: the sample's name at the start, its controls (reset, a mode switch) at the end. */
.bb-demo-bar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem .75rem;
    min-height: 2.75rem;
    margin: -1.25rem -1.25rem 1.25rem;
    padding: .375rem .75rem .375rem 1rem;
    background: var(--bb-surface-sunken);
    border-bottom: 1px solid var(--bb-border);
    border-radius: calc(var(--bb-radius-xl) - 1px) calc(var(--bb-radius-xl) - 1px) 0 0;
}

.bb-demo-label {
    margin-inline-end: auto;
    font-size: var(--fl-font-size-100);
    font-weight: var(--fl-weight-semibold);
    line-height: 1.33;
    letter-spacing: .06em;
    text-transform: uppercase;
    color: var(--bb-text-soft);
}

/* A recessed area inside a sample - a canvas, a drop zone, a tray of items. */
.bb-stage {
    min-width: 0;
    padding: 1rem;
    background: var(--bb-bg);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
}

/* Side-by-side panes that stack once the column is too narrow for two. */
.bb-split {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
    gap: 1rem;
    margin: 0 0 1.25rem;
}

.bb-split > * {
    min-width: 0;
}

/* A row of controls above or below a sample. */
.bb-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: .5rem;
    margin: 0 0 1rem;
}

.bb-toolbar > .bb-spacer {
    flex: 1;
}

/* A labelled control: the label above, Fluent's Field arrangement. */
.bb-field {
    display: inline-flex;
    flex-direction: column;
    gap: .25rem;
    min-width: 0;
    font-size: var(--fl-font-size-200);
    font-weight: var(--fl-weight-semibold);
    color: var(--bb-text);
}

.bb-field > small,
.bb-field-hint {
    font-size: var(--fl-font-size-100);
    font-weight: var(--fl-weight-regular);
    color: var(--bb-text-soft);
}

.bb-fields {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: .75rem 1rem;
    margin: 0 0 1rem;
}

/* A checkbox or a radio with its label to the side. */
.bb-check {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    font-size: var(--fl-font-size-200);
    color: var(--bb-text);
    cursor: pointer;
}

:where(input[type="checkbox"], input[type="radio"], input[type="range"], progress) {
    accent-color: var(--bb-primary);
}

/* Zero specificity like the fields above: a library's own switch or checkbox keeps its size. */
:where(input[type="checkbox"], input[type="radio"]) {
    width: 1rem;
    height: 1rem;
    margin: 0;
    flex: none;
}

/* Fluent's segmented toggle group: one choice out of a few, shown all at once. */
.bb-segmented {
    display: inline-flex;
    flex-wrap: wrap;
    gap: 2px;
    padding: 2px;
    background: var(--bb-surface-sunken);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius);
}

.bb-segmented > button {
    min-height: 1.75rem;
    padding: .1875rem .75rem;
    border: 0;
    border-radius: calc(var(--bb-radius) - 1px);
    background: transparent;
    color: var(--bb-text-muted);
    font-family: inherit;
    font-size: var(--fl-font-size-200);
    font-weight: var(--fl-weight-medium);
    cursor: pointer;
    transition: background var(--bb-motion-duration-short) var(--bb-motion-easing),
                color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

.bb-segmented > button:hover {
    color: var(--bb-text);
    background: var(--bb-surface-hover);
}

.bb-segmented > button.active,
.bb-segmented > button[aria-pressed="true"],
.bb-segmented > button[aria-checked="true"] {
    background: var(--bb-surface);
    color: var(--bb-primary);
    font-weight: var(--fl-weight-semibold);
    box-shadow: var(--bb-shadow-card);
}

/* Fluent's TabList: the selected tab is marked by a brand rule under its label. */
.bb-tabs {
    display: flex;
    gap: .25rem;
    margin: 0 0 1rem;
    border-bottom: 1px solid var(--bb-border);
    overflow-x: auto;
    scrollbar-width: thin;
}

.bb-tabs > button,
.bb-tabs > a {
    position: relative;
    flex: none;
    padding: .5rem .75rem;
    border: 0;
    background: none;
    color: var(--bb-text-muted);
    font-family: inherit;
    font-size: var(--fl-font-size-200);
    font-weight: var(--fl-weight-medium);
    white-space: nowrap;
    text-decoration: none;
    cursor: pointer;
}

.bb-tabs > button:hover,
.bb-tabs > a:hover {
    color: var(--bb-text);
    text-decoration: none;
}

.bb-tabs > .active,
.bb-tabs > [aria-selected="true"] {
    color: var(--bb-text);
    font-weight: var(--fl-weight-semibold);
}

.bb-tabs > .active::after,
.bb-tabs > [aria-selected="true"]::after {
    content: "";
    position: absolute;
    inset-inline: .75rem;
    bottom: 0;
    height: 3px;
    border-radius: var(--bb-radius-pill);
    background: var(--bb-primary);
}

/* A running log of what a sample did - events, calls, timings. The box scrolls rather than
   pushing the page down. */
.bb-log {
    max-height: 16rem;
    margin: 0 0 1.25rem;
    padding: .75rem 1rem;
    overflow: auto;
    background: var(--bb-code-bg);
    color: var(--bb-code-fg);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    font-family: var(--bb-mono);
    font-size: .8125rem;
    line-height: 1.6;
    scrollbar-width: thin;
}

.bb-log-empty {
    color: var(--bb-code-comment);
}

.bb-log-line {
    overflow-wrap: anywhere;
}

/* Numbers a sample measured: one hairline grid, like the landing page's proof strip. The rules
   between cells are the cells' own outlines meeting in the 1px gap, not the container's color
   showing through it: when the cells wrap with room to spare, the empty end of the last row stays
   the surface color instead of turning into a grey block. Outlines paint above the siblings next
   to them, and the container's overflow clips them at its own frame. */
.bb-stats {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(150px, 100%), 1fr));
    gap: 1px;
    margin: 0 0 1.25rem;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    overflow: hidden;
}

.bb-stat {
    display: flex;
    flex-direction: column;
    gap: .125rem;
    min-width: 0;
    padding: .875rem 1rem;
    background: var(--bb-surface);
    outline: 1px solid var(--bb-border);
}

.bb-stat-value {
    font-size: var(--fl-font-size-500);
    font-weight: var(--fl-weight-semibold);
    line-height: 1.2;
    color: var(--bb-text);
    font-variant-numeric: tabular-nums;
    overflow-wrap: anywhere;
}

.bb-stat-label {
    font-size: var(--fl-font-size-100);
    font-weight: var(--fl-weight-semibold);
    letter-spacing: .05em;
    text-transform: uppercase;
    color: var(--bb-text-soft);
}

/* Fluent's Spinner, for a sample that is waiting on something. */
.bb-spinner {
    display: inline-block;
    width: 1rem;
    height: 1rem;
    flex: none;
    border: 2px solid var(--bb-primary-soft);
    border-top-color: var(--bb-primary);
    border-radius: var(--bb-radius-pill);
    animation: bb-spin .8s linear infinite;
    vertical-align: middle;
}

@keyframes bb-spin {
    to { transform: rotate(360deg); }
}

@media (prefers-reduced-motion: reduce) {
    .bb-spinner {
        animation-duration: 2.4s;
    }
}

/* A "view the source of this sample" disclosure: a quiet button that opens a code block. */
.bb-source {
    margin: 0 0 1.25rem;
}

.bb-source > .bb-code,
.bb-source > pre {
    margin-top: .75rem;
    max-height: 32rem;
}

.bb-source-file {
    margin: .875rem 0 -.25rem;
    font-family: var(--bb-mono);
    font-size: var(--fl-font-size-100);
    font-weight: var(--fl-weight-semibold);
    color: var(--bb-text-muted);
}

/* Small text helpers. */
.bb-muted { color: var(--bb-text-muted); }
.bb-soft { color: var(--bb-text-soft); }
.bb-mono { font-family: var(--bb-mono); }
.bb-nowrap { white-space: nowrap; }

/* ============================================================================================
   27. Landing page - the home page of every demo is a stack of full-bleed bands: every other band
   drops to the secondary surface and is fenced by the same hairline the rest of the site's chrome
   uses, so the sections separate without a single drop shadow between them.

   Hero (.bb-hero) -> proof strip (.bb-proof) -> capability grid -> code walkthrough
   (.bb-walkthrough) -> comparison table (.bb-compare) -> persona tiles -> FAQ (.bb-faq) -> final
   call to action (.bb-final-cta). Each band is a <section> directly inside .bb-landing.
   ============================================================================================ */

.bb-landing {
    display: flex;
    flex-direction: column;
}

/* Full-width background, centred content, no wrapper element: the gutter grows to whatever is
   left once the content cap is taken, and never falls below the minimum. */
.bb-landing > section {
    width: 100%;
    padding-block: 5rem;
    padding-inline: max(1.5rem, calc((100% - var(--bb-content-width)) / 2));
    background: var(--bb-surface);
}

.bb-landing > section:nth-child(even) {
    background: var(--bb-bg);
    border-block: 1px solid var(--bb-border);
}

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

/* Two brand-tinted washes rather than a gradient sheet, so the color is felt at the corners and
   the type still sits on the flat surface color underneath. */
.bb-hero {
    position: relative;
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    gap: 3rem;
    align-items: center;
    padding-block: 6rem 5rem;
    background:
        radial-gradient(58rem 30rem at 12% -10%, var(--bb-wash-primary), transparent 60%),
        radial-gradient(46rem 26rem at 92% 8%, var(--bb-wash-accent), transparent 60%),
        var(--bb-surface);
}

.bb-hero-eyebrow {
    display: inline-flex;
    align-items: center;
    gap: .5rem;
    font-size: .75rem;
    font-weight: 600;
    letter-spacing: .02em;
    color: var(--bb-text-muted);
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    padding: .3125rem .75rem;
    border-radius: var(--bb-radius-pill);
    box-shadow: var(--bb-shadow-card);
    margin-bottom: 1.5rem;
}

/* The one place on the site that outsizes the type ramp: a landing hero is the single screen
   where the title is the whole message. */
.bb-hero-copy h1 {
    font-family: var(--bb-font-display);
    font-size: clamp(2.5rem, 5.2vw, 4rem);
    font-weight: 600;
    line-height: 1.08;
    letter-spacing: -.035em;
    margin-bottom: 1rem;
}

.bb-hero-accent {
    background: linear-gradient(96deg, var(--bb-primary), var(--bb-accent));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
}

/* The gradient IS the text here: forced colors drops the background image, and transparent text
   over nothing is a hole in the headline. The system's own text color takes over instead. */
@media (forced-colors: active) {
    .bb-hero-accent {
        background: none;
        color: CanvasText;
    }
}

.bb-hero-sub {
    color: var(--bb-text-muted);
    font-size: 1.0625rem;
    line-height: 1.65;
    margin-bottom: 1.75rem;
    max-width: 36rem;
}

.bb-hero-install {
    max-width: 34rem;
    background: var(--bb-code-bg);
}

.bb-hero-actions {
    display: flex;
    flex-wrap: wrap;
    gap: .625rem;
    margin-top: 1.5rem;
}

.bb-hero-code {
    min-width: 0;
}

/* ---------- The window frame around the hero sample ----------

   The hero's code sample sits in a window - a title bar with the file name or the address it
   belongs to. It is decoration with a job: it says what the sample is FOR before a single line of
   it has been read. */
.bb-browser {
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-xl);
    background: var(--bb-code-bg);
    box-shadow: var(--bb-shadow-flyout);
    overflow: hidden;
}

.bb-browser-bar {
    display: flex;
    align-items: center;
    gap: .75rem;
    padding: .5rem .75rem;
    background: var(--bb-surface-sunken);
    border-bottom: 1px solid var(--bb-border);
}

.bb-browser-dots {
    display: flex;
    gap: .375rem;
    flex: none;
}

.bb-browser-dots i {
    width: 9px;
    height: 9px;
    border-radius: var(--bb-radius-pill);
    background: var(--bb-border-strong);
}

.bb-browser-url {
    display: flex;
    align-items: center;
    gap: .4375rem;
    flex: 1;
    min-width: 0;
    padding: .1875rem .625rem;
    border-radius: var(--bb-radius-pill);
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    font-family: var(--bb-mono);
    font-size: .75rem;
    color: var(--bb-text-soft);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.bb-browser-url svg {
    width: 11px;
    height: 11px;
    flex: none;
    color: var(--bb-success);
}

.bb-browser-url strong {
    color: var(--bb-text);
    font-weight: 600;
}

/* The sample fills the frame, so it drops the frame it would otherwise draw for itself. */
.bb-browser .bb-code {
    margin: 0;
    border: 0;
    border-radius: 0;
    background: transparent;
    max-height: 26rem;
}

/* ---------- Proof strip ----------

   A single hairline grid: the rules between cells are drawn in the 1px gap, so the four claims
   read as one row of facts rather than as four more cards. It is also the one child of the stack that is a
   control rather than a band, so it opts out of the full-bleed treatment and keeps the
   container's gutters. */
.bb-landing > section.bb-proof {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(min(200px, 100%), 1fr));
    gap: 1px;
    width: min(100% - 3rem, var(--bb-content-width));
    margin: 3.5rem auto;
    padding: 0;
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-card);
    overflow: hidden;
}

/* The rules between the facts are the cells' outlines - see .bb-stats for why. */
.bb-proof > div {
    background: var(--bb-surface);
    outline: 1px solid var(--bb-border);
    padding: 1.25rem 1.5rem;
    display: flex;
    flex-direction: column;
    gap: .25rem;
}

.bb-proof strong {
    color: var(--bb-text);
    font-size: .9375rem;
    font-weight: 600;
}

.bb-proof span {
    color: var(--bb-text-muted);
    font-size: .8125rem;
    line-height: 1.6;
}

/* ---------- Sections ---------- */

.bb-section {
    margin-bottom: 0;
}

.bb-section > .bb-overline {
    color: var(--bb-primary);
    margin-bottom: .625rem;
}

.bb-section h2 {
    font-size: clamp(1.5rem, 2.6vw, 2rem);
    font-weight: 600;
    letter-spacing: -.02em;
    margin-bottom: .75rem;
}

.bb-section-sub {
    color: var(--bb-text-muted);
    font-size: 1.0625rem;
    line-height: 1.6;
    max-width: var(--bb-measure);
    margin-bottom: 2rem;
}

/* ---------- Walkthrough ---------- */

.bb-walkthrough {
    display: flex;
    flex-direction: column;
    gap: 3rem;
    margin-top: 2rem;
}

.bb-walkthrough-row {
    display: grid;
    grid-template-columns: minmax(0, 2fr) minmax(0, 3fr);
    gap: 2.5rem;
    align-items: center;
}

/* Alternating sides, so three consecutive rows do not read as a list of three identical blocks. */
.bb-walkthrough-row:nth-child(even) .bb-walkthrough-copy {
    order: 2;
}

.bb-step {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    margin-bottom: .875rem;
    border-radius: var(--bb-radius-pill);
    background: var(--bb-primary-soft);
    color: var(--bb-primary-hover);
    font-family: var(--bb-mono);
    font-size: .75rem;
    font-weight: 600;
}

.bb-walkthrough-copy h3 {
    font-size: 1.25rem;
    margin-bottom: .5rem;
}

.bb-walkthrough-copy p {
    color: var(--bb-text-muted);
    line-height: 1.7;
    margin-bottom: .75rem;
}

.bb-walkthrough-copy a {
    font-weight: 600;
    font-size: .9375rem;
}

.bb-walkthrough-row .bb-code {
    margin: 0;
    box-shadow: var(--bb-shadow-card);
}

/* ---------- Comparison ---------- */

/* The capability column is prose rather than an identifier, so it opts out of the monospace the
   table gives its first column by default. */
.bb-compare td:first-child {
    font-family: inherit;
    font-size: inherit;
    font-weight: 500;
    color: var(--bb-text);
}

.bb-compare td:last-child {
    color: var(--bb-text);
}

/* ---------- FAQ ---------- */

.bb-faq {
    display: flex;
    flex-direction: column;
    gap: .625rem;
    max-width: 54rem;
}

.bb-faq details {
    background: var(--bb-surface);
    border: 1px solid var(--bb-border);
    border-radius: var(--bb-radius-lg);
    box-shadow: var(--bb-shadow-card);
    padding: .875rem 1.125rem;
    transition: border-color var(--bb-motion-duration-short) var(--bb-motion-easing);
}

.bb-faq details[open] {
    border-color: var(--bb-border-strong);
}

.bb-faq summary {
    display: flex;
    align-items: baseline;
    gap: .75rem;
    cursor: pointer;
    font-weight: 600;
    color: var(--bb-text);
    list-style: none;
}

.bb-faq summary::-webkit-details-marker {
    display: none;
}

/* A chevron drawn from two borders, so it rotates rather than swapping glyphs - one element,
   no icon font, and the open state is a 200ms turn instead of a jump. */
.bb-faq summary::before {
    content: "";
    flex: 0 0 auto;
    width: .4rem;
    height: .4rem;
    border-right: .125rem solid var(--bb-primary);
    border-bottom: .125rem solid var(--bb-primary);
    transform: translateY(-.15rem) rotate(-45deg);
    transition: transform var(--bb-motion-duration) var(--bb-motion-easing);
}

.bb-faq summary:hover {
    color: var(--bb-primary);
}

.bb-faq details[open] summary::before {
    transform: translateY(-.25rem) rotate(45deg);
}

.bb-faq details[open] summary {
    margin-bottom: .625rem;
}

.bb-faq details[open] p {
    padding-inline-start: 1.15rem;
}

.bb-faq p {
    color: var(--bb-text-muted);
    line-height: 1.7;
    margin: 0;
}

.bb-faq-more {
    color: var(--bb-text-muted);
    margin-top: 1.25rem;
}

/* ---------- Final CTA ---------- */

.bb-final-cta {
    text-align: center;
}

.bb-final-cta h2 {
    font-size: clamp(1.5rem, 2.6vw, 2rem);
    font-weight: 600;
    letter-spacing: -.02em;
    margin-bottom: .75rem;
}

.bb-final-cta .bb-section-sub {
    margin-inline: auto;
    margin-bottom: 1.75rem;
}

/* Centre the install line and the buttons. Shrink-to-fit is what centres the block, and the cap
   is what stops it shrink-to-fitting past the edge of a narrow screen. */
.bb-final-cta .bb-hero-install {
    display: inline-block;
    max-width: 100%;
    text-align: left;
    margin-bottom: 0;
}

.bb-final-cta .bb-hero-actions {
    justify-content: center;
}

/* ---------- Responsive ---------- */

@media (max-width: 1100px) {
    .bb-hero {
        grid-template-columns: minmax(0, 1fr);
        gap: 2.5rem;
        padding-block: 4rem 3.5rem;
    }

    /* minmax(0, 1fr), never a bare 1fr: `1fr` is shorthand for minmax(AUTO, 1fr), and that auto
       minimum stops the track shrinking below its widest item's min-content. The copy column
       holds a `pre` of install commands whose min-content is its longest line - about 370px - so
       a bare 1fr pins the hero to that width, pushes the page past the viewport and gives the
       whole document a horizontal scrollbar. */
    .bb-walkthrough-row {
        grid-template-columns: minmax(0, 1fr);
        gap: 1.5rem;
    }

    .bb-walkthrough-row:nth-child(even) .bb-walkthrough-copy {
        order: 0;
    }
}

@media (max-width: 960px) {
    .bb-landing > section {
        padding-block: 3.5rem;
    }

    .bb-landing > section.bb-proof {
        margin-block: 2.5rem;
        width: min(100% - 2.5rem, var(--bb-content-width));
    }
}

@media (max-width: 600px) {
    .bb-landing > section {
        padding-block: 3rem;
        padding-inline: 1rem;
    }

    .bb-landing > section.bb-proof {
        width: calc(100% - 2rem);
    }

    .bb-hero {
        padding-block: 3rem;
    }

    .bb-hero-sub {
        font-size: 1rem;
    }

    .bb-section-sub {
        font-size: 1rem;
    }

    /* The frame is chrome around the sample, and on a phone the sample needs the pixels more. */
    .bb-browser-bar {
        display: none;
    }

    .bb-hero-actions .btn {
        flex: 1 1 auto;
    }
}
