/* The whole design, hand-written.

   The Hugo build got its chrome from Hextra, whose utilities are a purged
   Tailwind bundle — reproducing that would mean carrying a Node toolchain to
   render one page. This file is the same result stated directly: a masthead, a
   centred column, the contact card, a footer. Nothing is imported and nothing
   is generated, which is why there is no build step.

   Bronze #8C6239 and the card's #F1EEEA are carried over unchanged. Contrast on
   the card was measured, not chosen: ink 13.9:1, the label grey 5.9:1, and the
   bronze link 4.6:1, which clears AA but only just — so the link is never set
   smaller than the body. */

:root {
    color-scheme: light dark;

    --bv-bronze: #8C6239;
    --bv-bronze-hover: #5E3E22;
    --bv-card-bg: #F1EEEA;
    --bv-card-ink: #1F2328;
    --bv-card-label: #5E5A55;
    --bv-page-bg: #ffffff;
    --bv-page-ink: #1F2328;
    --bv-footer-bg: #f4f4f5;
    --bv-footer-ink: #52525b;
    --bv-navbar-height: 7rem;
}

/* Follows the OS, with no toggle: the system already knows, and a picker is one
   more control on a page whose whole point is that it has almost none. */
@media (prefers-color-scheme: dark) {
    :root {
        --bv-card-bg: #1c1c1f;
        --bv-card-ink: #e8e8ea;
        --bv-card-label: #a1a1aa;
        --bv-page-bg: #111113;
        --bv-page-ink: #e8e8ea;
        --bv-footer-bg: #17171a;
        --bv-footer-ink: #a1a1aa;
        --bv-bronze: #c79a63;
        --bv-bronze-hover: #dcb583;
    }
}

*,
*::before,
*::after {
    box-sizing: border-box;
}

html {
    -webkit-text-size-adjust: 100%;
}

body {
    margin: 0;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
    background: var(--bv-page-bg);
    color: var(--bv-page-ink);
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue",
        Arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji";
    line-height: 1.6;
}

/* Visible only when focused: a keyboard visitor gets a way past the masthead,
   and nobody else sees a thing. */
.bv-skip {
    position: absolute;
    left: -9999px;
    top: 0;
    z-index: 50;
    padding: 0.5rem 1rem;
    background: var(--bv-bronze);
    color: #fff;
    border-radius: 0 0 6px 0;
    text-decoration: none;
}

.bv-skip:focus-visible {
    left: 0;
}

/* --- Masthead ------------------------------------------------------------
   The lockup is 190x88, sized so the tile inside it lands on exactly 64px, the
   point below which the column in the mark stops resolving. The bar is sized
   from the art rather than the other way round. */
.bv-masthead {
    display: flex;
    align-items: center;
    height: var(--bv-navbar-height);
    padding: 0 1.5rem;
    box-shadow: 0 1px 0 rgb(0 0 0 / 6%);
}

.bv-masthead-link {
    display: inline-flex;
    align-items: center;
    text-decoration: none;
}

.bv-masthead-link:hover {
    opacity: 0.75;
}

.bv-masthead-mark {
    display: block;
    width: 190px;
    height: 88px;
}

/* The wordmark ships as two files, not one recoloured in CSS: it is artwork
   with its own dark variant. */
.bv-dark-only {
    display: none;
}

@media (prefers-color-scheme: dark) {
    .bv-light-only {
        display: none;
    }

    .bv-dark-only {
        display: block;
    }
}

main {
    flex: 1 0 auto;
}

/* --- Home ---------------------------------------------------------------- */
.bv-home {
    width: 100%;
    max-width: 46rem;
    margin: 0 auto;
    /* 6rem, not 3: the Hugo build got 3rem from this block and another 3rem
       from the theme's content wrapper. The sum is what the page looked like. */
    padding: 6rem 1.5rem 2rem;
    text-align: center;
}

/* The statement under the wordmark. `bv-home` centres its column; this one
   paragraph is set left behind the bronze edge instead, so it reads as
   something asserted rather than as a caption under the mark. Same 6px bronze
   border as the contact card and the table of contents; no filled ground,
   because a panel here would compete with the mark directly above it. */
.bv-home .bv-lede {
    max-width: 42rem;
    margin: 0 auto 2.5rem;
    padding: 0.25rem 0 0.25rem 1.5rem;
    border-left: 6px solid var(--bv-bronze);
    text-align: left;
}

.bv-home img.bv-mark {
    /* Sized by width so the tile inside the lockup stays well above 64px. */
    width: min(380px, 80vw);
    height: auto;
    margin: 0 auto 2.5rem;
}

img.bv-mark.bv-light-only {
    display: block;
}

@media (prefers-color-scheme: dark) {
    img.bv-mark.bv-light-only {
        display: none;
    }

    img.bv-mark.bv-dark-only {
        display: block;
    }
}

/* Present for search and for screen readers, hidden from sight because the
   wordmark already sets the name in type. Not `display: none`, which would take
   it out of the accessibility tree and defeat the point of keeping it. */
.bv-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip-path: inset(50%);
    white-space: nowrap;
    border: 0;
}

/* --- The contact card ----------------------------------------------------
   One type size throughout. The label and the value are the same size on
   purpose: two sizes in a three-row card reads as a table of contents rather
   than a set of equal facts. */
.bv-card {
    max-width: 42rem;
    margin: 0 auto;
    padding: 2rem 2.25rem 2rem 2.5rem;
    text-align: left;
    background: var(--bv-card-bg);
    border-left: 6px solid var(--bv-bronze);
    border-radius: 10px;
}

.bv-card dl {
    margin: 0;
    display: grid;
    grid-template-columns: 8.5rem 1fr;
    gap: 1.15rem 2rem;
    align-items: baseline;
    font-size: 1.0625rem;
    line-height: 1.5;
}

.bv-card dt {
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bv-card-label);
}

.bv-card dd {
    margin: 0;
    color: var(--bv-card-ink);
}

.bv-card a {
    color: var(--bv-bronze);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.bv-card a:hover {
    color: var(--bv-bronze-hover);
}

/* One column on a narrow screen: an 8.5rem label column squeezes the address. */
@media (max-width: 34rem) {
    .bv-card {
        padding: 1.5rem 1.5rem 1.5rem 1.75rem;
    }

    .bv-card dl {
        grid-template-columns: 1fr;
        gap: 0.25rem;
    }

    .bv-card dt {
        margin-top: 1rem;
    }

    .bv-card dt:first-child {
        margin-top: 0;
    }
}

/* --- Error page ---------------------------------------------------------- */
.bv-error h1 {
    font-size: 3rem;
    margin: 0 0 0.5rem;
}

.bv-error p {
    margin: 0.25rem 0;
}

.bv-error-back {
    margin-top: 1.5rem;
}

.bv-error a {
    color: var(--bv-bronze);
    text-underline-offset: 3px;
}

/* --- Footer -------------------------------------------------------------- */
.bv-footer {
    flex-shrink: 0;
    background: var(--bv-footer-bg);
    color: var(--bv-footer-ink);
    padding: 3rem 1.5rem;
    font-size: 0.8125rem;
}

/* Left-aligned to the page, not centred under the content column — matching
   where the copyright has always sat. */
.bv-footer p {
    margin: 0;
    text-align: left;
}

/* --- Masthead nav --------------------------------------------------------
   Four links, right of the lockup, set in sentence case. It is not rendered at
   all under the holding page, so there is no "current page" state to design for
   beyond a hover: with this few destinations, an underline on the one you are
   already reading is noise. */
.bv-nav {
    margin-left: auto;
    display: flex;
    gap: 1.75rem;
    font-size: 0.9375rem;
}

.bv-nav a {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    color: var(--bv-page-ink);
    text-decoration: none;
    padding: 0.25rem 0;
    border-bottom: 2px solid transparent;
}

/* Sized in em so the glyph tracks the label rather than a fixed pixel size, and
   held at the bronze while the label sits at the page ink — the icon is the
   decoration, the word is the link. On hover both go bronze together. */
.bv-nav svg {
    width: 1.05em;
    height: 1.05em;
    flex: none;
    color: var(--bv-bronze);
}

.bv-nav a:hover svg {
    color: inherit;
}

.bv-nav a:hover {
    color: var(--bv-bronze);
    border-bottom-color: var(--bv-bronze);
}

.bv-nav a:focus-visible {
    outline: 2px solid var(--bv-bronze);
    outline-offset: 4px;
}

/* Five destinations with glyphs do not fit a phone. The words are what carry
   the meaning, so the glyphs are what goes: dropped rather than shrunk, because
   an icon small enough to fit here is an icon nobody can read. */
@media (max-width: 48rem) {
    .bv-nav svg {
        display: none;
    }

    .bv-nav a {
        gap: 0;
    }
}

@media (max-width: 30rem) {
    .bv-masthead {
        padding: 0 1rem;
    }

    .bv-nav {
        gap: 1rem;
        font-size: 0.8125rem;
    }
}

/* --- The lede and the one button on the site -----------------------------
   The lede is the sentence that says what the company is. It sits under the
   wordmark on the home page and under the h1 everywhere else, so it is sized
   relative to the body rather than to either heading. */
.bv-lede {
    font-size: 1.1875rem;
    line-height: 1.55;
    margin: 0 0 2rem;
}

/* Three of them, wrapping rather than shrinking: a button squeezed narrower
   than its label is worse than one on its own line. */
.bv-actions {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 1rem;
    margin: 0 0 3rem;
}

/* Square tiles: the icon sits on its own line above the label, which is what
   makes the shape work — a wide pill with a glyph tucked beside the text reads
   as a toolbar button, and these are destinations.

   Outlined at rest, bronze on the page ground. That is the same pairing as
   every link on the site and measures the same 4.6:1, so like the links it is
   never set smaller than the body text. */
.bv-button {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.7rem;
    width: 8.5rem;
    height: 8.5rem;
    padding: 1rem 0.75rem;
    background: transparent;
    color: var(--bv-bronze);
    border: 2px solid var(--bv-bronze);
    /* 10px, the same radius as the card, the tiers and the table of contents. */
    border-radius: 10px;
    text-decoration: none;
    text-align: center;
    font-size: 0.9375rem;
    line-height: 1.3;
    transition: background-color 120ms ease, color 120ms ease, box-shadow 120ms ease;
}

/* Fixed rather than em-sized: these sit alone above their label rather than
   beside it, so they answer to the tile instead of to the type. */
.bv-button svg {
    width: 2.125rem;
    height: 2.125rem;
    flex: none;
}

/* The inversion. The label takes the PAGE ground rather than a fixed white: in
   the light scheme that is white on bronze at 4.9:1, and in the dark scheme the
   bronze lightens to #c79a63, where white would fall to about 2:1 and the
   near-black page ink measures 8.0:1 instead. One declaration, both schemes.

   Focus gets the same treatment as hover, so a keyboard reaches the state a
   pointer does rather than a fainter version of it. */
.bv-button:hover,
.bv-button:focus-visible {
    background: var(--bv-bronze);
    color: var(--bv-page-bg);
    box-shadow: 0 0 0 4px rgb(140 98 57 / 18%), 0 6px 22px rgb(140 98 57 / 38%);
    outline: none;
}

@media (prefers-color-scheme: dark) {
    /* Struck from the lightened bronze, or it is a brown smudge on a near-black
       page rather than a glow. */
    .bv-button:hover,
    .bv-button:focus-visible {
        box-shadow: 0 0 0 4px rgb(199 154 99 / 22%), 0 6px 24px rgb(199 154 99 / 42%);
    }
}

/* Three 8.5rem tiles and two gaps need 27.5rem; below that they wrap two-and-one,
   which looks like a mistake. Shrink them instead so the row survives. */
@media (max-width: 30rem) {
    .bv-actions {
        gap: 0.65rem;
    }

    .bv-button {
        width: 6.75rem;
        height: 6.75rem;
        font-size: 0.875rem;
        gap: 0.5rem;
    }

    .bv-button svg {
        width: 1.75rem;
        height: 1.75rem;
    }
}

/* --- Interior pages ------------------------------------------------------
   `bv-home` is a centred column; these are the same column left-aligned, which
   is the whole difference between the front door and a page of prose. */
.bv-page,
.bv-prose {
    width: 100%;
    max-width: 46rem;
    margin: 0 auto;
    padding: 4rem 1.5rem 3rem;
}

.bv-page-head {
    text-align: center;
    margin-bottom: 3rem;
}

.bv-page-head h1 {
    margin: 0 0 1rem;
}

.bv-prose h1,
.bv-wide-head h1 {
    font-size: 2.25rem;
    line-height: 1.2;
    margin: 0 0 1rem;
}

.bv-prose h2 {
    font-size: 1.4375rem;
    line-height: 1.3;
    margin: 2.75rem 0 0.75rem;
    /* Long documents need the section starts to read as starts. A rule is
       quieter than a larger type size and survives dark mode better. */
    padding-top: 0.75rem;
    border-top: 1px solid rgb(140 98 57 / 22%);
}

.bv-prose h3 {
    font-size: 1.125rem;
    margin: 2rem 0 0.5rem;
}

.bv-prose p,
.bv-prose li,
.bv-wide-body p {
    font-size: 1.0625rem;
}

.bv-prose p,
.bv-wide-body p {
    margin: 0 0 1.1rem;
}

/* The last paragraph of a section sits against the laurel; the trailing margin
   double-counts the gap. */
.bv-wide-body p:last-child {
    margin-bottom: 0;
}

.bv-prose ul,
.bv-prose ol {
    margin: 0 0 1.1rem;
    padding-left: 1.35rem;
}

.bv-prose li {
    margin-bottom: 0.45rem;
}

/* Every container that holds running text styles its own links, and a page
   whose container was left out gets the browser's default blue — which is what
   happened to the wide pages until this selector named them. */
.bv-prose a,
.bv-wide-body a {
    color: var(--bv-bronze);
    text-decoration: underline;
    text-underline-offset: 3px;
}

.bv-prose a:hover,
.bv-wide-body a:hover {
    color: var(--bv-bronze-hover);
}

.bv-prose code {
    font-size: 0.9375em;
    padding: 0.1em 0.35em;
    border-radius: 4px;
    background: var(--bv-card-bg);
}

/* The h1 and the lede open a page; the rule above every other h2 would draw one
   across the top of the first section for no reason. */
.bv-prose > h2:first-of-type {
    border-top: 0;
}

/* --- The wide layout ------------------------------------------------------
   Used by /about and /open-source, and named for the shape rather than for
   either of them. `bv-prose` stops at 46rem because that is a comfortable
   measure for running text; this runs to 72rem and spends the difference on
   layout rather than on the line — the heading sits in a rail to the left and
   the body keeps its measure beside it. A 72rem line is unreadable however much
   room there is for it, which is the mistake a wide page usually makes.

   Type, links and anchor offsets are NOT restated here: they are declared once
   alongside `bv-prose` above, because a second copy is a copy that can drift. */
.bv-wide {
    width: 100%;
    max-width: 72rem;
    margin: 0 auto;
    padding: 4rem 1.5rem 3rem;
}

.bv-wide-head {
    max-width: 44rem;
    /* 100px. The headline is not a label on the first section, so it gets air
       rather than proximity — the laurels do the separating below it. */
    margin-bottom: 6.25rem;
}

.bv-wide-section {
    display: grid;
    grid-template-columns: 15rem minmax(0, 1fr);
    gap: 2.5rem;
}

/* In the rail, so it reads as a label on the section rather than as a line of
   the text. Bronze unless the section names another ink: /products gives each
   product its own accent so the mark and the name beside it read as one thing.
   A custom property rather than a more specific selector, so the override does
   not have to out-weigh this rule to win. */
.bv-wide-section > h2 {
    margin: 0;
    font-size: 1.375rem;
    line-height: 1.3;
    color: var(--bv-rail-ink, var(--bv-bronze));
}

/* A rail label may link — on /products it points at the product site. */
.bv-wide-section > h2 a {
    color: inherit;
    text-decoration: none;
}

.bv-wide-section > h2 a:hover {
    color: var(--bv-rail-ink-hover, var(--bv-bronze-hover));
    text-decoration: underline;
}

/* Wider than bv-prose's 46rem measure by a little, because the figure floats
   into it: at 44rem a 20rem inset leaves a column too narrow to read. */
.bv-wide-body {
    max-width: 47rem;
}

/* A card is not running text, so the reading measure does not apply to it: the
   body spans the whole column beside the rail. */
.bv-wide-full {
    max-width: none;
}

/* Inset, not stacked: the drawing is the argument, so it sits beside the
   paragraph making it. */
/* The laurel separator: the sprigs alone, centred, with no rule through them.
   They keep their drawn proportions at a fixed width rather than stretching to
   the column, because scaling an SVG to full width stretches the leaves too. */
.bv-divider {
    display: flex;
    justify-content: center;
    margin: 3.25rem 0;
    color: var(--bv-bronze);
}

.bv-laurel {
    display: block;
    width: 10rem;
    height: auto;
    flex: none;
}

.bv-figure {
    float: right;
    width: 20rem;
    max-width: 100%;
    margin: 0.35rem 0 1.25rem 2rem;
}

.bv-figure img {
    display: block;
    width: 100%;
    height: auto;
    border-radius: 10px;
    /* The drawing is graphite on near-white paper and carries no border of its
       own, so it would bleed into the page without one. */
    border: 1px solid rgb(140 98 57 / 25%);
}

/* Alternated down the page so the column of text does not always start at the
   same place. Left-floated figures need the margin on the other side. */
.bv-figure-left {
    float: left;
    margin: 0.35rem 2rem 1.25rem 0;
}

/* The column plate is portrait. At 20rem it would stand 33rem tall and push
   three paragraphs out of its own section, so it is set narrower. */
.bv-figure-tall {
    width: 14rem;
}

/* A 1400px sheet of near-white paper on a near-black page is a lamp. Held back
   rather than inverted: inverting a pencil drawing turns the paper into noise
   and the linework into something that looks like a photographic negative. */
@media (prefers-color-scheme: dark) {
    .bv-figure img {
        opacity: 0.82;
    }
}

/* The rail costs 15rem plus a 2.5rem gap. Below this there is not enough left
   for a 44rem measure beside it, so the heading goes back above its section and
   the figure stops floating — a floated 22rem figure in a 30rem column leaves a
   gutter three words across. */
@media (max-width: 62rem) {
    .bv-wide-head {
        margin-bottom: 3.5rem;
    }

    .bv-wide-section {
        grid-template-columns: minmax(0, 1fr);
        gap: 1rem;
    }

    .bv-product-main {
        flex-direction: column;
    }

    .bv-shots {
        flex: 1 1 auto;
        width: 100%;
    }

    .bv-figure,
    .bv-figure-left,
    .bv-figure-tall {
        float: none;
        width: 100%;
        margin: 0 0 1.5rem;
    }

    .bv-figure-tall {
        max-width: 22rem;
    }
}

/* --- Legal documents -----------------------------------------------------
   The effective date is the first thing a lawyer looks for and the first thing
   that goes stale, so it is set apart rather than folded into the lede. */
.bv-effective {
    margin: 0 0 1.75rem;
    font-size: 0.9375rem;
    color: var(--bv-card-label);
}

/* Hextra generated this; here it is hand-written per page, which is why it is
   styled to be scanned rather than read — it is a jump list, not content. */
.bv-toc {
    margin: 2.5rem 0;
    padding: 1.25rem 1.5rem;
    background: var(--bv-card-bg);
    border-left: 6px solid var(--bv-bronze);
    border-radius: 10px;
}

.bv-toc h2 {
    margin: 0 0 0.6rem;
    padding: 0;
    border: 0;
    font-size: 0.8125rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: var(--bv-card-label);
}

.bv-toc ol {
    margin: 0;
    padding-left: 1.25rem;
    font-size: 0.9375rem;
}

.bv-toc li {
    margin-bottom: 0.3rem;
}

.bv-toc ol ol {
    margin-top: 0.3rem;
    font-size: 1em;
}

/* A jump link lands the heading under the masthead unless the browser is told
   to leave room for it. */
.bv-prose [id],
.bv-wide [id] {
    scroll-margin-top: 1.5rem;
}

.bv-table {
    width: 100%;
    margin: 0 0 1.5rem;
    border-collapse: collapse;
    font-size: 1rem;
    text-align: left;
}

.bv-table th,
.bv-table td {
    padding: 0.7rem 0.9rem;
    border-bottom: 1px solid rgb(140 98 57 / 22%);
    vertical-align: top;
}

.bv-table thead th {
    font-size: 0.8125rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bv-card-label);
}

.bv-address {
    margin: 1.5rem 0 0;
    padding: 1.25rem 1.5rem;
    background: var(--bv-card-bg);
    border-radius: 10px;
    font-style: normal;
    line-height: 1.7;
}

/* --- The contact list on About ------------------------------------------
   The same two columns as the card, without the card: on a page that already
   has a card's worth of chrome in the table of contents, a second panel reads
   as a second document. */
.bv-contact {
    display: grid;
    grid-template-columns: 11.5rem 1fr;
    gap: 0.6rem 1.5rem;
    margin: 0 0 1.5rem;
    font-size: 1.0625rem;
}

.bv-contact dt {
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: var(--bv-card-label);
    font-size: 0.9375rem;
}

.bv-contact dd {
    margin: 0;
}

@media (max-width: 34rem) {
    .bv-contact {
        grid-template-columns: 1fr;
        gap: 0.2rem;
    }

    .bv-contact dt {
        margin-top: 0.9rem;
    }

    .bv-contact dt:first-child {
        margin-top: 0;
    }
}

/* One product today, and the room below the card is held for what comes next
   rather than closed up: roughly the card's own height again. Set on the page
   rather than on the section because it is space the page is reserving, not a
   margin belonging to the card above it. */
.bv-products {
    padding-bottom: 13rem;
}

/* --- Products ------------------------------------------------------------
   One card per product, sitting in the body column of the wide layout with the
   product's name in the rail beside it. The card is a container rather than a
   link: it holds the product site, the source and the product's three legal
   documents, so the whole panel cannot be one anchor. */
/* Each product is themed by its own palette rather than by the site's bronze,
   so a card reads as belonging to the product it describes. A section sets the
   three tokens and everything inside it — rail label, border, ground, links —
   follows. Adding a second product means adding one block here.

   OpenChime's values are its own, copied from the accent it already ships
   (openchime, src/OpenChime.ControlPlane.Web/wwwroot/css/placeholder.css), which
   in turn are the two stops of the mark's gradient. Keeping them in step with
   that file is the point: an approximation here would be a second, wrong blue. */
.bv-product-openchime {
    --bv-product-accent: #1A5CC4;
    --bv-product-accent-hover: #12408B;
    --bv-rail-ink: var(--bv-product-accent);
    --bv-rail-ink-hover: var(--bv-product-accent-hover);
    /* The ground is derived, not picked: the accent laid over the page at the
       weight that gives the same lift bronze's #F1EEEA gives on white. */
    --bv-product-ground: color-mix(in srgb, var(--bv-product-accent) 7%, var(--bv-page-bg));
}

/* The light stop of the gradient, which is the one that reads on a dark page —
   and a heavier mix, because a 7% tint disappears against near-black. */
@media (prefers-color-scheme: dark) {
    .bv-product-openchime {
        --bv-product-accent: #3D8BFF;
        --bv-product-accent-hover: #6FAAFF;
        --bv-product-ground: color-mix(in srgb, var(--bv-product-accent) 10%, var(--bv-page-bg));
    }
}

/* An image rather than one of the site's inline glyphs, because it brings its
   own colour and must not take the page's. */
.bv-product-mark {
    width: 1.6rem;
    height: 1.6rem;
    vertical-align: -0.3rem;
    margin-right: 0.5rem;
}

.bv-product-card {
    padding: 1.75rem 2rem;
    background: var(--bv-product-ground, var(--bv-card-bg));
    border-left: 6px solid var(--bv-product-accent, var(--bv-bronze));
    border-radius: 10px;
    color: var(--bv-card-ink);
}

.bv-product-card p {
    margin: 0 0 1.1rem;
    font-size: 1rem;
}

.bv-product-card a {
    color: var(--bv-product-accent, var(--bv-bronze));
    text-decoration-thickness: 1px;
    text-underline-offset: 2px;
}

.bv-product-card a:hover {
    color: var(--bv-product-accent-hover, var(--bv-bronze-hover));
}

.bv-product-links,
.bv-product-legal {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    font-size: 0.9375rem;
}

/* The card's two columns: the description on the left, the screenshots on the
   right. The legal foot stays outside this and spans the whole card. Both
   columns are given a basis rather than a width so they share the interior
   evenly and reflow together. */
.bv-product-main {
    display: flex;
    gap: 2rem;
    align-items: flex-start;
}

.bv-product-text {
    flex: 1 1 21rem;
    min-width: 0;
}

/* --- The screenshot carousel ---------------------------------------------
   An ordinary carousel — one picture at a time, an arrow on each side, dots
   beneath — with no script behind it. The viewport is a native horizontal
   scroller with mandatory snap points, so swipe, trackpad and the arrow keys
   are the browser's own behaviour; the arrows are anchors pointing at the
   neighbouring slide's id, and the dots at their own. Nothing here animates a
   transform or tracks an index.

   The one thing it cannot do is close the full-size overlay on Escape, which
   needs a key listener. The close link and the browser's Back button do. */
.bv-shots {
    flex: 0 1 23rem;
    min-width: 0;
}

/* A frame, so the pictures inside read as one component rather than as loose
   images. Overflow is hidden vertically to keep the arrows clipped to it. */
.bv-shots-viewport {
    position: relative;
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    border-radius: 10px;
    border: 1px solid color-mix(in srgb, var(--bv-product-accent, var(--bv-bronze)) 30%, transparent);
    background: var(--bv-page-bg);
    /* The strip scrolls, so it is focusable; the scrollbar itself is noise
       under a picture that already has arrows and dots. */
    scrollbar-width: none;
}

.bv-shots-viewport::-webkit-scrollbar {
    display: none;
}

.bv-shots-viewport:focus-visible {
    outline: 2px solid var(--bv-product-accent, var(--bv-bronze));
    outline-offset: 3px;
}

/* Full width and hard snapping: one slide fills the frame and no neighbour
   peeks in, which is what makes it read as a carousel rather than a strip. */
.bv-shot {
    position: relative;
    flex: 0 0 100%;
    scroll-snap-align: start;
    scroll-snap-stop: always;
}

.bv-shot-open {
    display: block;
    cursor: zoom-in;
}

.bv-shot img {
    display: block;
    width: 100%;
    height: auto;
}

/* Overlaid on the picture, vertically centred, one on each edge. Round, dark
   and translucent so they sit on any screenshot without a colour clashing. */
.bv-shot-arrow {
    position: absolute;
    top: 50%;
    translate: 0 -50%;
    display: grid;
    place-items: center;
    width: 2.25rem;
    height: 2.25rem;
    border-radius: 50%;
    background: rgb(0 0 0 / 45%);
    color: #fff;
    text-decoration: none;
}

.bv-shot-arrow svg {
    width: 1.25rem;
    height: 1.25rem;
}

.bv-shot-arrow:hover,
.bv-shot-arrow:focus-visible {
    background: var(--bv-product-accent, var(--bv-bronze));
    color: #fff;
}

.bv-shot-prev {
    left: 0.5rem;
}

.bv-shot-next {
    right: 0.5rem;
}

/* Dots, not numbers: five is few enough that position alone is legible. */
.bv-shots-dots {
    display: flex;
    justify-content: center;
    gap: 0.5rem;
    margin-top: 0.85rem;
}

.bv-shots-dots a {
    width: 0.5625rem;
    height: 0.5625rem;
    border-radius: 50%;
    background: color-mix(in srgb, var(--bv-product-accent, var(--bv-bronze)) 30%, transparent);
}

.bv-shots-dots a:hover,
.bv-shots-dots a:focus-visible {
    background: var(--bv-product-accent, var(--bv-bronze));
}

/* The dot for the slide currently addressed by the URL, filled rather than
   tinted. `:has` reaches back up from the targeted slide to the matching dot,
   which is the one thing a carousel needs an index for and the only way to get
   it without one. The first dot is filled when nothing is addressed yet. */
.bv-shots:has(#oc-shot-1:target) .bv-shots-dots a:nth-child(1),
.bv-shots:has(#oc-shot-2:target) .bv-shots-dots a:nth-child(2),
.bv-shots:has(#oc-shot-3:target) .bv-shots-dots a:nth-child(3),
.bv-shots:has(#oc-shot-4:target) .bv-shots-dots a:nth-child(4),
.bv-shots:has(#oc-shot-5:target) .bv-shots-dots a:nth-child(5),
.bv-shots:not(:has(.bv-shot:target)) .bv-shots-dots a:first-child {
    background: var(--bv-product-accent, var(--bv-bronze));
}

/* The full-size overlay. Hidden means `display: none`, which also keeps it out
   of the accessibility tree, so nothing needs announcing or hiding by hand. */
.bv-lightbox {
    display: none;
}

.bv-lightbox:target {
    display: grid;
    place-items: center;
    position: fixed;
    inset: 0;
    z-index: 50;
    padding: 2rem;
    background: rgb(0 0 0 / 78%);
}

/* The backdrop is the close target: anywhere outside the plate dismisses it. */
.bv-lightbox-close {
    position: absolute;
    inset: 0;
    cursor: zoom-out;
}

/* Capped at the captures' own width: blowing a 1024px screenshot up to fill a
   wide display would only show it soft. */
.bv-lightbox img {
    position: relative;
    max-width: min(92vw, 1024px);
    max-height: 88vh;
    width: auto;
    height: auto;
    border-radius: 10px;
}

/* The foot of the card: quieter than the product links above it, and set apart
   by space rather than by a rule. */
.bv-product-legal {
    margin-top: 1.5rem;
    font-size: 0.875rem;
}

.bv-product-legal a {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.bv-product-legal svg {
    width: 1.15em;
    height: 1.15em;
    flex: none;
}

/* The three ways to run OpenChime. Not links, so not cards — panels.
   The minimum is 11rem rather than something roomier so that all three fit
   across the 46rem column: at 14rem auto-fit gives two, and the third tier
   drops to its own row looking like an afterthought rather than the paid one. */
.bv-tiers {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
    gap: 1.25rem;
    margin: 0 0 1.75rem;
}

.bv-tier {
    padding: 1.25rem 1.4rem;
    background: var(--bv-card-bg);
    border-radius: 10px;
}

.bv-tier h3 {
    margin: 0 0 0.4rem;
    font-size: 1.0625rem;
}

.bv-tier p {
    margin: 0;
    font-size: 0.9375rem;
}

/* --- Footer legal --------------------------------------------------------
   Reference material someone goes looking for, which is why it is here and not
   in the masthead. Suppressed under the holding page along with the nav. */
.bv-footer-legal {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.5rem;
    margin: 0 0 1rem;
}

.bv-footer-legal a {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    color: var(--bv-footer-ink);
    text-decoration: underline;
    text-underline-offset: 3px;
}

/* Small, and sized in em so they follow the footer's 0.8125rem type rather
   than standing over it. The underline belongs to the words, so the glyph is
   pulled out of it. */
.bv-footer-legal svg {
    width: 1.25em;
    height: 1.25em;
    flex: none;
    text-decoration: none;
}

.bv-footer-legal a:hover {
    color: var(--bv-bronze);
}
