/* BoosterBuddy shell.

   Mobile first: a volunteer signs up and counts a drawer on a phone, in the dark, at a
   football stadium. Everything here is sized for that and then allowed to grow. The
   breakpoint at 900px is where the menu stops being a disclosure and becomes a rail.

   No framework. Bootstrap was here and earned its keep on nothing — the whole of this
   file is smaller than the part of Bootstrap that was being used. */

:root {
    --bb-ink: #16202b;
    --bb-ink-soft: #55636f;
    --bb-ground: #f4f6f4;
    --bb-surface: #ffffff;
    --bb-line: #d9ded9;
    --bb-line-soft: #e9ece9;
    --bb-accent: #1f5c3d;
    --bb-accent-ink: #ffffff;
    --bb-accent-wash: #eaf2ec;
    --bb-warn: #8a5a00;
    --bb-warn-wash: #fdf5e6;
    --bb-danger: #9a2b21;
    --bb-danger-wash: #fdf1ef;
    --bb-good: #1f5c3d;
    --bb-good-wash: #e6f2ea;

    /* The header wears the accent unless a club dresses it apart — see the branding
       page. Declared as its own pair so that choice is one override, not a hunt. */
    --bb-header-bg: var(--bb-accent);
    --bb-header-ink: var(--bb-accent-ink);

    /* One stack for the whole application. A club may swap it on the branding page;
       every option is system fonts, so nothing ever downloads. */
    --bb-font: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

    /* 44px is the smallest thing a thumb hits reliably. Every control clears it. */
    --bb-touch: 2.75rem;

    /* The height of EVERY typed control — text, date, time, number, select, textarea —
       and of a button, so a row of mixed controls lines up instead of stepping. Change
       it here and the whole application moves together. */
    --bb-control: 2.75rem;
    --bb-radius: 0.5rem;
    --bb-rail: 15rem;
    /* What is left of the rail once it is collapsed: the reopen button and nothing
       else. A rail that shrinks to nothing takes its own way back with it. */
    --bb-rail-shut: 2.5rem;
    --bb-page: 78rem;
}

@media (prefers-color-scheme: dark) {
    :root {
        --bb-ink: #e8ece8;
        --bb-ink-soft: #a2aeaa;
        --bb-ground: #11161a;
        --bb-surface: #1a2126;
        --bb-line: #303a40;
        --bb-line-soft: #232c31;
        --bb-accent: #4b9e6f;
        --bb-accent-ink: #0d1412;
        --bb-accent-wash: #1b2b22;
        --bb-warn: #d9a442;
        --bb-warn-wash: #2a2317;
        --bb-danger: #f08b7f;
        --bb-danger-wash: #2c1c1a;
        --bb-good: #6fc294;
        --bb-good-wash: #17281f;
    }
}

* { box-sizing: border-box; }

body {
    margin: 0;
    background: var(--bb-ground);
    color: var(--bb-ink);
    font-family: var(--bb-font);
    font-size: 1rem;
    line-height: 1.5;
    min-height: 100vh;
    display: flex;
    flex-direction: column;
}

a { color: var(--bb-accent); }

.skip-link { position: absolute; left: -9999px; }
.skip-link:focus {
    left: 0.5rem;
    top: 0.5rem;
    z-index: 100;
    padding: 0.5rem 0.75rem;
    background: var(--bb-surface);
    border-radius: var(--bb-radius);
}

:focus-visible { outline: 3px solid var(--bb-accent); outline-offset: 2px; }

/* --- header ------------------------------------------------------------------- */

.bb-header {
    background: var(--bb-header-bg);
    color: var(--bb-header-ink);
    padding: env(safe-area-inset-top) 0 0;
}

.bb-header-inner {
    max-width: var(--bb-page);
    margin: 0 auto;
    padding: 0.625rem 1rem;
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 1rem;
    justify-content: space-between;
}

.bb-brand {
    color: inherit;
    text-decoration: none;
    font-weight: 650;
    font-size: 1.0625rem;
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
}
.bb-brand:hover { text-decoration: underline; }

/* The club's logo, beside its name. Height-capped rather than boxed, so a wide crest
   and a square badge both sit in the bar without stretching it. */
.bb-logo { display: block; height: 1.75rem; width: auto; max-width: 9rem; }

.bb-account { display: flex; align-items: center; gap: 0.75rem; font-size: 0.875rem; }

.bb-account-name {
    opacity: 0.9;
    max-width: 9rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.bb-account-link { color: inherit; text-decoration: underline; text-underline-offset: 0.2em; }
.bb-signout-form { margin: 0; }
.bb-linkbutton { background: none; border: 0; padding: 0; font: inherit; cursor: pointer; }

/* --- body: menu plus main ------------------------------------------------------ */

.bb-body {
    flex: 1;
    width: 100%;
    max-width: var(--bb-page);
    margin: 0 auto;
    padding: 0 1rem;
}

.bb-main { padding: 1.25rem 0 2.5rem; min-width: 0; }

.bb-footer {
    max-width: var(--bb-page);
    width: 100%;
    margin: 0 auto;
    padding: 1rem calc(1rem + env(safe-area-inset-left)) calc(1rem + env(safe-area-inset-bottom));
    border-top: 1px solid var(--bb-line);
    color: var(--bb-ink-soft);
    font-size: 0.8125rem;
    display: flex;
    gap: 1rem;
    justify-content: space-between;
}

/* --- the menu ------------------------------------------------------------------ */

.bb-menu { margin: 0.75rem 0 0; }

.bb-menu-button {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: var(--bb-touch);
    padding: 0.5rem 0.875rem;
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    font-weight: 600;
    cursor: pointer;
    list-style: none;
    user-select: none;
}
.bb-menu-button::-webkit-details-marker { display: none; }

/* A caret that turns, so the control says which way it is going to go. */
.bb-menu-button::before {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
    transition: transform 120ms ease;
}
.bb-menu[open] > .bb-menu-button::before { transform: rotate(-135deg); }

@media (prefers-reduced-motion: reduce) {
    .bb-menu-button::before { transition: none; }
}

/* Hidden until a wide screen with script — see the 900px block. On a phone the "Menu"
   disclosure already hides the menu, and two controls for one job is one too many. */
.bb-rail-toggle {
    display: none;
    align-items: center;
    gap: 0.5rem;
    width: 100%;
    min-height: 2.25rem;
    padding: 0.25rem 0.5rem;
    margin-bottom: 0.5rem;
    background: none;
    border: 1px solid transparent;
    border-radius: var(--bb-radius);
    color: var(--bb-ink-soft);
    font: inherit;
    font-size: 0.75rem;
    cursor: pointer;
}

.bb-rail-toggle:hover { background: var(--bb-ground); color: var(--bb-ink); }
.bb-rail-toggle:focus-visible { border-color: var(--bb-accent); }

/* A caret pointing the way the rail will go, so the control says what it does before
   it is pressed. */
.bb-rail-toggle::before {
    content: "";
    flex: none;
    width: 0.5rem;
    height: 0.5rem;
    border-left: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
    transition: transform 120ms ease;
}

@media (prefers-reduced-motion: reduce) {
    .bb-rail-toggle::before { transition: none; }
}

.bb-nav {
    margin-top: 0.5rem;
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    padding: 0.5rem;
}

.bb-nav ul { list-style: none; margin: 0; padding: 0; }

.bb-nav-section + .bb-nav-section { margin-top: 0.75rem; }

/* Every section is a <details>, so the heading is its <summary>: a real disclosure
   control that keyboards and screen readers already understand, rather than a heading
   with a click handler bolted on. */
.bb-nav-heading {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-ink-soft);
    margin: 0.5rem 0 0.25rem;
    padding: 0.25rem 0.625rem;
    font-weight: 700;

    display: flex;
    align-items: center;
    gap: 0.4rem;
    cursor: pointer;
    border-radius: 0.375rem;
    list-style: none;
}

.bb-nav-heading::-webkit-details-marker { display: none; }
.bb-nav-heading:hover { background: var(--bb-ground); color: var(--bb-ink); }

/* A triangle that turns, drawn rather than typed so it inherits the text color and
   doesn't depend on an emoji font. */
.bb-nav-heading::before {
    content: "";
    width: 0;
    height: 0;
    border-left: 0.3rem solid currentColor;
    border-top: 0.25rem solid transparent;
    border-bottom: 0.25rem solid transparent;
    transition: transform 120ms ease;
}

.bb-nav-section[open] > .bb-nav-heading::before,
.bb-nav-folder[open] > .bb-nav-heading::before { transform: rotate(90deg); }

@media (prefers-reduced-motion: reduce) {
    .bb-nav-heading::before { transition: none; }
}

/* The Admin folder inside a section. Indented so it reads as belonging to the section
   above it, and set in the ordinary text case rather than the section's small caps —
   it is one entry among the links, not a second section. */
.bb-nav-folder { margin: 0.25rem 0 0 0.625rem; }

.bb-nav-subheading {
    text-transform: none;
    letter-spacing: 0;
    font-size: 0.8125rem;
    font-weight: 600;
    margin: 0;
}

.bb-nav-folder > .bb-nav-list { margin-left: 0.5rem; }

.bb-nav-home,
.bb-nav-link {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-height: var(--bb-touch);
    padding: 0.4rem 0.625rem;
    border-radius: 0.375rem;
    color: var(--bb-ink);
    text-decoration: none;
    font-size: 0.9375rem;
}

.bb-nav-home { font-weight: 600; }
.bb-nav-home:hover, .bb-nav-link:hover { background: var(--bb-ground); }

.bb-nav-home.is-current,
.bb-nav-link.is-current {
    background: var(--bb-accent-wash);
    color: var(--bb-accent);
    font-weight: 650;
}

/* Not a link yet. Muted rather than hidden, so the shape of the application is
   visible and nobody wastes a minute wondering why it won't click. */
.bb-nav-link.is-soon { color: var(--bb-ink-soft); cursor: default; }
.bb-nav-link.is-soon:hover { background: none; }

.bb-soon {
    margin-left: auto;
    font-size: 0.625rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    padding: 0.1rem 0.35rem;
    border: 1px solid var(--bb-line);
    border-radius: 0.75rem;
}

@media (min-width: 900px) {
    .bb-body {
        display: grid;
        grid-template-columns: var(--bb-rail) minmax(0, 1fr);
        gap: 1.5rem;
        align-items: start;
    }

    .bb-menu { margin: 1.25rem 0; position: sticky; top: 1rem; }

    /* With script, the rail is simply open and the button is noise. Without it, the
       button stays and the menu is a disclosure at every width — worse, and working. */
    .bb-js .bb-menu-button { display: none; }

    .bb-nav { margin-top: 0; }

    /* A signed-out page has no rail, so the content shouldn't be pushed into a column
       that isn't there. */
    .bb-signed-out .bb-body { display: block; }

    /* --- collapsing the rail ---------------------------------------------------

       Only offered where there is a rail to collapse and script to run it. On a phone
       the menu is already a disclosure, so a second control that does nearly the same
       thing would be two ways to hide one menu. */
    .bb-js .bb-rail-toggle { display: flex; }

    .bb-rail-collapsed .bb-body { grid-template-columns: var(--bb-rail-shut) minmax(0, 1fr); }
    .bb-rail-collapsed .bb-menu-panel { display: none; }

    /* Square, and the words drop out — the caret is the whole control at this width. */
    .bb-rail-collapsed .bb-rail-toggle { width: var(--bb-rail-shut); padding: 0; justify-content: center; }
    .bb-rail-collapsed .bb-rail-toggle-text { display: none; }
    .bb-rail-collapsed .bb-rail-toggle::before { transform: rotate(-45deg); }
}

/* --- page furniture ------------------------------------------------------------ */

.bb-page-head { margin-bottom: 1.25rem; }

h1 { font-size: 1.5rem; margin: 0 0 0.5rem; text-wrap: balance; }
h2 { font-size: 1.0625rem; margin: 0 0 0.75rem; }

.bb-lede { color: var(--bb-ink-soft); margin: 0; }

.bb-flash {
    background: var(--bb-good-wash);
    border: 1px solid var(--bb-good);
    color: var(--bb-good);
    border-radius: var(--bb-radius);
    padding: 0.75rem 1rem;
    margin-bottom: 1.25rem;
}

.bb-note { color: var(--bb-ink-soft); font-size: 0.8125rem; margin: 0.75rem 0 0; }
.bb-empty { color: var(--bb-ink-soft); margin: 0; }
.bb-warn { color: var(--bb-warn); font-size: 0.875rem; margin: 0.75rem 0 0; }

/* --- cards --------------------------------------------------------------------- */

.bb-card {
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    padding: 1.125rem;
}

.bb-card-narrow { max-width: 26rem; margin: 1rem auto; }

.bb-cards {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1rem;
}

@media (min-width: 640px) {
    .bb-cards { grid-template-columns: repeat(auto-fit, minmax(18rem, 1fr)); }
    .bb-card-wide { grid-column: 1 / -1; }
}

.bb-card-attention {
    border-color: var(--bb-warn);
    background: var(--bb-warn-wash);
}
.bb-card-attention h2 { color: var(--bb-warn); }

/* --- signed-out pages (sign in, register, reset) -------------------------------- */

/* One column, centered: masthead, then the form card, then the what-if links. Narrow
   on purpose — these pages ask for two fields, not a spreadsheet. */
.bb-auth { max-width: 26rem; margin: 1.5rem auto; }

.bb-auth-head { text-align: center; margin-bottom: 1.25rem; }

.bb-auth-head h1 { font-size: 1.375rem; margin-bottom: 0.25rem; }

/* Constrained on both axes so a club's wide wordmark and another's square crest both
   sit comfortably; object-fit keeps either undistorted. */
.bb-auth-logo {
    display: block;
    margin: 0 auto 0.75rem;
    max-width: 10rem;
    height: 4rem;
    object-fit: contain;
}

.bb-auth .bb-card { padding: 1.25rem; }

.bb-auth-aside { text-align: center; }

/* The register page wears the logo big — a parent arriving for the first time should
   recognize the club before being asked to type. How big is the club's choice:
   --bb-hero-size comes from the branding page (see ThemeCss.HeroSizes); unset means
   the width of the form. The larger sizes deliberately outgrow the form column, so
   the image centers itself on the page rather than in the column, and the viewport
   cap is what keeps a phone from scrolling sideways. */
.bb-auth-hero .bb-auth-logo {
    width: var(--bb-hero-size, 100%);
    max-width: min(var(--bb-hero-size, 100%), 92vw);
    height: auto;
    max-height: none;
    margin-bottom: 1rem;
    position: relative;
    left: 50%;
    transform: translateX(-50%);
}

/* --- lists inside cards --------------------------------------------------------- */

.bb-list { list-style: none; margin: 0; padding: 0; }

.bb-list li {
    padding: 0.5rem 0;
    border-top: 1px solid var(--bb-line-soft);
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
}
.bb-list li:first-child { border-top: 0; padding-top: 0; }

.bb-list-main { font-weight: 600; display: flex; align-items: center; gap: 0.5rem; flex-wrap: wrap; }
.bb-list-sub { color: var(--bb-ink-soft); font-size: 0.8125rem; }

/* inline-block is load-bearing: width and height do nothing on an inline element, so
   without it this renders as nothing anywhere it isn't a flex item. */
.bb-dot {
    display: inline-block;
    vertical-align: middle;
    width: 0.625rem;
    height: 0.625rem;
    border-radius: 50%;
    flex: none;
    box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.15);
}

.bb-pill {
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.1rem 0.45rem;
    border-radius: 0.75rem;
}
.bb-pill-warn { background: var(--bb-warn-wash); color: var(--bb-warn); }
.bb-pill-good { background: var(--bb-good-wash); color: var(--bb-good); }

.bb-tasks { list-style: none; margin: 0; padding: 0; }
.bb-tasks li { padding: 0.5rem 0; border-top: 1px solid rgba(0, 0, 0, 0.08); }
.bb-tasks li:first-child { border-top: 0; padding-top: 0; }
.bb-tasks-detail { display: block; font-size: 0.875rem; color: var(--bb-ink-soft); }

/* --- figures -------------------------------------------------------------------- */

.bb-figures { display: flex; flex-wrap: wrap; gap: 1.25rem; }

.bb-figure { display: flex; flex-direction: column; }

.bb-figure-value {
    font-size: 1.375rem;
    font-weight: 650;
    /* Columns of money should line up even when the digits differ in width. */
    font-variant-numeric: tabular-nums;
}

.bb-figure-label { font-size: 0.75rem; color: var(--bb-ink-soft); }

/* --- a list of destinations ------------------------------------------------------ */

.bb-orglist {
    list-style: none;
    margin: 0;
    padding: 0;
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    background: var(--bb-surface);
    overflow: hidden;
}

.bb-orglist li {
    border-bottom: 1px solid var(--bb-line);
    color: var(--bb-ink-soft);
    padding: 0.75rem 1rem;
    min-height: var(--bb-touch);
    display: flex;
    align-items: center;
}
.bb-orglist li:last-child { border-bottom: 0; }
.bb-orglist li:has(a) { padding: 0; }

.bb-orglist a {
    display: flex;
    align-items: center;
    flex: 1;
    padding: 0.75rem 1rem;
    min-height: var(--bb-touch);
    color: var(--bb-ink);
    text-decoration: none;
    font-weight: 600;
}
.bb-orglist a:hover { background: var(--bb-ground); }

/* The admin area used to draw a second rail inside the first, with its own catalog. It
   is gone: setup lives in the one menu now, in the section it belongs to. */

/* --- tables --------------------------------------------------------------------- */

/* Wide content scrolls inside its own box. The page body never scrolls sideways —
   on a phone that turns every vertical swipe into a fight. */
.bb-table-wrap {
    overflow-x: auto;
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
}

.bb-table {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9375rem;
}

.bb-table th,
.bb-table td {
    text-align: left;
    padding: 0.625rem 0.875rem;
    vertical-align: top;
    border-top: 1px solid var(--bb-line-soft);
}

.bb-table thead th {
    border-top: 0;
    border-bottom: 1px solid var(--bb-line);
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-ink-soft);
    white-space: nowrap;
}

.bb-table td .bb-list-sub { display: block; }

.bb-table tr.is-inactive td { opacity: 0.55; }

.bb-num { text-align: right; font-variant-numeric: tabular-nums; }
.bb-table th.bb-num { text-align: right; }
.bb-nowrap { white-space: nowrap; }

.bb-row-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem 0.875rem;
    align-items: baseline;
}
.bb-row-actions form { margin: 0; }

.bb-link {
    color: var(--bb-accent);
    text-decoration: underline;
    text-underline-offset: 0.15em;
    font-size: 0.875rem;
}
.bb-link-danger { color: var(--bb-danger); }

.bb-visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
}

.bb-pill-quiet { background: var(--bb-line-soft); color: var(--bb-ink-soft); }

/* --- the calendar ---------------------------------------------------------------- */

.bb-month {
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-ink-soft);
    margin: 1.5rem 0 0.5rem;
}

.bb-events { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }

.bb-event {
    display: flex;
    align-items: stretch;
    gap: 0.75rem;
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    overflow: hidden;
}

/* The type's colour, as a stripe rather than a dot: at arm's length in a car park a
   6px bar is legible and a 10px circle is not. */
.bb-event-stripe { flex: none; width: 0.375rem; }

.bb-event-body { flex: 1; min-width: 0; padding: 0.75rem 0 0.75rem 0; }

.bb-event-title {
    display: block;
    font-weight: 650;
    color: var(--bb-ink);
    text-decoration: none;
    /* The whole row is the target on a phone, not just the words. */
    min-height: 1.5rem;
}
.bb-event-title:hover { text-decoration: underline; }

.bb-event-meta { color: var(--bb-ink-soft); font-size: 0.8125rem; }
.bb-event-note { font-size: 0.8125rem; margin-top: 0.25rem; }

.bb-event-tags {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    justify-content: center;
    gap: 0.25rem;
    padding: 0.75rem 0.875rem 0.75rem 0;
    flex: none;
}
.bb-event-tags form { margin: 0; }

.bb-event.is-cancelled .bb-event-title { text-decoration: line-through; }
.bb-event.is-cancelled { opacity: 0.75; }

/* The claim control on the sign-up list: a number and a button, side by side, both
   thumb-sized. */
.bb-event-claim { display: flex; align-items: center; padding: 0.75rem 0.875rem 0.75rem 0; flex: none; }
.bb-event-claim form { display: flex; gap: 0.5rem; align-items: center; margin: 0; }

/* The how-many select, thumb-sized like the button beside it. Named apart from the
   calendar's .bb-spots wrapper on purpose — sharing the class once made the calendar's
   minus/plus group inherit this box and tower over the sign-up button. */
.bb-spot-pick {
    min-height: var(--bb-touch);
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    background: var(--bb-surface);
    color: inherit;
    font-size: 1rem;
}

/* --- one event ------------------------------------------------------------------- */

.bb-shift { margin-bottom: 1rem; }

.bb-shift-head {
    display: flex;
    justify-content: space-between;
    align-items: flex-start;
    gap: 0.75rem;
}
.bb-shift-head h2, .bb-shift-head h3 { margin: 0 0 0.25rem; font-size: 1.0625rem; }
.bb-shift-head p { margin: 0; }

.bb-shift-form { margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--bb-line-soft); }

.bb-signed-up { font-weight: 600; color: var(--bb-good); margin: 0 0 0.75rem; }

.bb-roster { margin-top: 0.875rem; padding-top: 0.875rem; border-top: 1px solid var(--bb-line-soft); }
.bb-roster summary { cursor: pointer; font-weight: 600; font-size: 0.9375rem; min-height: 2rem; }

.bb-inline-form { display: flex; gap: 0.5rem; align-items: center; margin-top: 0.25rem; flex-wrap: wrap; }
.bb-inline-form input {
    flex: 1 1 10rem;
    min-height: 2.25rem;
    padding: 0.25rem 0.5rem;
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    background: var(--bb-surface);
    color: inherit;
    font-size: 0.875rem;
}

/* --- attendance -------------------------------------------------------------------- */

.bb-attendance { margin-bottom: 0.75rem; }
.bb-attendance.is-here { border-left: 4px solid var(--bb-good); }
.bb-attendance p { margin: 0; }
.bb-adjust { margin-top: 0.75rem; padding-top: 0.75rem; border-top: 1px solid var(--bb-line-soft); }

/* --- the check-in landing page ------------------------------------------------------ */

/* Held at arm's length, one-handed, in the dark. Everything here is bigger than it
   would be anywhere else on purpose. */
.bb-checkin { text-align: center; }

.bb-button-big { min-height: 4rem; font-size: 1.125rem; }

.bb-checkin-result { padding: 1.5rem 1rem; border-radius: var(--bb-radius); margin-bottom: 1rem; }
.bb-checkin-good { background: var(--bb-good-wash); color: var(--bb-good); }
.bb-checkin-bad { background: var(--bb-danger-wash); color: var(--bb-danger); }
.bb-checkin-big { font-size: 1.5rem; font-weight: 700; margin: 0 0 0.375rem; }
.bb-checkin-result p:last-child { margin: 0; }

/* --- print: the call sheet ----------------------------------------------------------- */

@media print {
    .bb-header, .bb-footer, .bb-menu, .bb-noprint, .skip-link { display: none !important; }
    .bb-body { display: block; max-width: none; padding: 0; }
    body { background: #fff; color: #000; }
    .bb-card { border: 0; border-bottom: 1px solid #999; border-radius: 0; padding: 0.5rem 0; }
    .bb-sheet { break-inside: avoid; }
    .bb-sheet-table a { color: #000; text-decoration: none; }
}

/* --- forms ---------------------------------------------------------------------- */

.bb-form { display: flex; flex-direction: column; gap: 1rem; }

/* Fields side by side once there is room, stacked on a phone. */
.bb-row { display: flex; flex-wrap: wrap; gap: 0 1rem; }
.bb-row > .bb-field { flex: 1 1 12rem; }
.bb-row > .bb-field-short { flex: 0 1 7rem; }

/* Wide enough for the longest option plus the arrow. "every other week" in a 7rem box
   was clipped to "every oth…", which reads as a bug in the data rather than a box. */
.bb-row > .bb-field-wide { flex: 0 1 12rem; }

.bb-filter {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem 1rem;
    align-items: flex-end;
    margin-bottom: 1rem;
}
.bb-filter .bb-field { flex: 1 1 16rem; margin-bottom: 0; }
.bb-filter .bb-check { margin-bottom: 0.5rem; }

/* A checkbox with a heading and explanation beside it, rather than a bare label. */
.bb-check-block { align-items: flex-start; padding: 0.375rem 0; }
.bb-check-block label { display: block; cursor: pointer; }
.bb-check-block .bb-hint { margin-top: 0.1rem; }
.bb-hint-implied { font-style: italic; }

.bb-actions-inline { display: flex; flex-wrap: wrap; gap: 0.75rem; align-items: center; }
.bb-button-inline { width: auto; }
.bb-button-danger { color: var(--bb-danger); border-color: var(--bb-danger); }

/* On a solid button the danger form fills red; the quiet form above keeps its outline.
   The ink token already flips with the theme, so the label stays readable on both. */
.bb-button.bb-button-danger:not(.bb-button-quiet) {
    background: var(--bb-danger);
    color: var(--bb-accent-ink);
}

.bb-card-good { border-color: var(--bb-good); background: var(--bb-good-wash); }
.bb-flash-quiet { background: var(--bb-surface); border-color: var(--bb-line); color: var(--bb-ink-soft); }

/* A link to be copied rather than clicked, so it is selectable and monospaced. */
.bb-copyfield {
    width: 100%;
    min-height: var(--bb-touch);
    padding: 0.5rem 0.625rem;
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    background: var(--bb-surface);
    color: inherit;
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
}

.bb-inline-details { display: inline-block; }
.bb-inline-details summary { cursor: pointer; list-style: none; }
.bb-inline-details summary::-webkit-details-marker { display: none; }
.bb-inline-details .bb-copyfield { margin-top: 0.35rem; min-width: 18rem; }

/* --- forms, continued ------------------------------------------------------------ */

.bb-field { margin-bottom: 1rem; }

.bb-field label { display: block; font-weight: 600; font-size: 0.875rem; margin-bottom: 0.25rem; }

/* EVERY control that takes typed input, everywhere in the application.

   This used to list four input types by name, so `text`, `password`, `email` and `tel`
   were styled and `date`, `time`, `number` and everything else fell through to the
   browser's defaults — a different height, a different font, a different border, sitting
   in the same row as the ones that had been styled. A form with a date picker beside a
   dropdown beside a number box looked like three different applications.

   So it is written the other way round: everything is a control unless it is one of the
   few things that genuinely isn't. Checkboxes and radios have their own size, hidden
   fields have none, and files and ranges are drawn by the browser in a way there is no
   point fighting.

   Deliberately NOT scoped to .bb-field. Inputs live in table cells too — the wizard's
   dates, the journal's lines, the cash count — and a rule that only reached form fields
   would leave the grids looking like the old problem. */
input:not([type="checkbox"]):not([type="radio"]):not([type="hidden"]):not([type="file"]):not([type="range"]):not([type="submit"]):not([type="button"]),
select,
textarea {
    min-height: var(--bb-control);
    padding: 0.5rem 0.625rem;
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    background: var(--bb-surface);
    color: inherit;
    /* Under 16px iOS Safari zooms the whole page on focus and never zooms back. */
    font-size: 1rem;
    font-family: inherit;
    /* Safari draws date and time inputs at their own intrinsic height and ignores the
       padding unless this is said. Without it they are two pixels shorter than a text
       box beside them, which is exactly the kind of thing that looks like nothing and
       reads as sloppy. */
    -webkit-appearance: none;
    appearance: none;
}

/* The arrow has to come back — appearance:none takes it with the rest. Drawn rather than
   an image so it follows the text colour into dark mode. */
select {
    background-image:
        linear-gradient(45deg, transparent 50%, currentColor 50%),
        linear-gradient(135deg, currentColor 50%, transparent 50%);
    background-position:
        calc(100% - 1.05rem) calc(50% + 0.1rem),
        calc(100% - 0.7rem) calc(50% + 0.1rem);
    background-size: 0.35rem 0.35rem, 0.35rem 0.35rem;
    background-repeat: no-repeat;
    /* Room for the arrow, so a long option doesn't run under it. */
    padding-right: 2rem;
}

textarea { min-height: calc(var(--bb-control) * 2); }

/* A field fills its column; a control in a table cell is sized by the cell. */
.bb-field input,
.bb-field select,
.bb-field textarea { width: 100%; }

.bb-hint { display: block; color: var(--bb-ink-soft); font-size: 0.8125rem; margin-top: 0.25rem; }

.bb-check { display: flex; align-items: flex-start; gap: 0.5rem; margin-bottom: 0.75rem; }
.bb-check input { margin-top: 0.3rem; width: 1.05rem; height: 1.05rem; }
.bb-check label { font-weight: 400; }

.bb-button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--bb-touch);
    width: 100%;
    padding: 0.5rem 1rem;
    border: 0;
    border-radius: var(--bb-radius);
    background: var(--bb-accent);
    color: var(--bb-accent-ink);
    font: inherit;
    font-weight: 600;
    text-decoration: none;
    cursor: pointer;
}
.bb-button:hover { filter: brightness(1.08); }
.bb-button[disabled] { opacity: 0.6; cursor: not-allowed; }

.bb-button-quiet { background: transparent; color: var(--bb-accent); border: 1px solid var(--bb-line); }

.bb-actions { margin-top: 1.25rem; }

.bb-aside {
    margin-top: 1.25rem;
    padding-top: 1rem;
    border-top: 1px solid var(--bb-line);
    font-size: 0.875rem;
    color: var(--bb-ink-soft);
}

/* For a card that stacks several unrelated jobs — the account page — each heading after
   the first carries this, so the same rule the aside draws marks every change of subject. */
.bb-section-break {
    margin-top: 1.75rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--bb-line);
}

/* --- validation ------------------------------------------------------------------ */

.bb-errors {
    background: var(--bb-danger-wash);
    border: 1px solid var(--bb-danger);
    border-radius: var(--bb-radius);
    color: var(--bb-danger);
    padding: 0.75rem 1rem;
    margin-bottom: 1.25rem;
}
.bb-errors ul { margin: 0; padding-left: 1.1rem; }
.bb-errors li + li { margin-top: 0.25rem; }

/* The validation summary tag helper renders its box whether or not there is anything
   in it. Without this every page loads showing an empty red rectangle. */
.bb-errors.validation-summary-valid { display: none; }

.field-validation-error {
    display: block;
    color: var(--bb-danger);
    font-size: 0.8125rem;
    margin-top: 0.25rem;
}
.input-validation-error { border-color: var(--bb-danger) !important; }

.bb-color { padding: 0.25rem; min-height: var(--bb-touch); }

/* --- counting a drawer ------------------------------------------------------------

   Ten boxes, thumb-sized, in the order money comes out of a till. On a phone this is
   two columns; on a desktop it spreads out. The running total is deliberately big:
   it is the number the person counting is watching. */

.bb-denoms {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(7rem, 1fr));
    gap: 0.625rem;
}

.bb-denom { display: flex; align-items: center; gap: 0.5rem; }

.bb-denom label {
    flex: 0 0 2.75rem;
    font-weight: 650;
    font-variant-numeric: tabular-nums;
    text-align: right;
}

.bb-denom-input {
    flex: 1;
    min-width: 0;
    min-height: var(--bb-touch);
    padding: 0.5rem;
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    background: var(--bb-surface);
    color: inherit;
    font-size: 1.125rem;
    text-align: center;
    font-variant-numeric: tabular-nums;
}

.bb-counted {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    margin-top: 1rem;
    padding-top: 0.875rem;
    border-top: 1px solid var(--bb-line);
}

.bb-counted-label { color: var(--bb-ink-soft); font-size: 0.875rem; }

.bb-counted-value {
    font-size: 1.75rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
}

/* The row's own dollars, beside the box of counted notes. */
.bb-denom-value {
    flex: 0 0 4.5rem;
    text-align: right;
    font-size: 0.875rem;
    color: var(--bb-ink-soft);
    font-variant-numeric: tabular-nums;
}

/* One itemized check: who signed it, its number, the dollars, a note. */
.bb-check-rows { display: flex; flex-direction: column; gap: 0.5rem; margin: 0.75rem 0; }

.bb-check-row {
    display: grid;
    grid-template-columns: 2fr 1fr 1fr 2fr;
    gap: 0.5rem;
}

@media (max-width: 40rem) {
    .bb-check-row { grid-template-columns: 1fr 1fr; }
}

/* A money box wears its dollar sign, so an amount never reads as a plain number. */
.bb-money { display: flex; align-items: center; gap: 0.375rem; min-width: 0; }
.bb-money input { flex: 1; min-width: 0; }
.bb-money-sign { color: var(--bb-ink-soft); font-weight: 650; }

/* A cash call-out has no check number, so its row is three cells wide. */
.bb-callout-row { grid-template-columns: 2fr 1fr 2fr; }

@media (max-width: 40rem) {
    .bb-callout-row { grid-template-columns: 1fr 1fr; }
}

/* The add-a-row buttons drive script; without script the spare rows are the answer. */
#add-check, #add-callout { display: none; }
.bb-js #add-check, .bb-js #add-callout { display: inline-flex; }

/* A setup destination that isn't built yet, on the setup index. Same muted treatment as
   the rail, so the two agree about what exists. */
.bb-setup-soon {
    display: flex;
    flex-direction: column;
    flex: 1;
    padding: 0.75rem 1rem;
    color: var(--bb-ink-soft);
}
.bb-setup-soon .bb-soon { margin-left: 0; align-self: flex-start; margin-top: 0.25rem; }

/* --- an editor on its own page ---------------------------------------------------- */

/* Breadcrumb back to the list. One level, because that is all there is. */
.bb-crumbs {
    display: flex;
    gap: 0.4rem;
    align-items: baseline;
    font-size: 0.8125rem;
    color: var(--bb-ink-soft);
    margin-bottom: 0.75rem;
}
.bb-crumbs a { color: var(--bb-ink-soft); }

/* A form with one subject doesn't want the full page width — a 60rem-wide text box is
   harder to read, not easier. */
.bb-form-narrow { max-width: 34rem; }

.bb-color-row { display: flex; gap: 0.75rem; align-items: stretch; }

.bb-color-sample {
    flex: 1;
    display: flex;
    gap: 0.75rem;
    align-items: center;
    padding: 0.5rem 0.75rem;
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    overflow: hidden;
}
.bb-color-sample .bb-event-stripe { align-self: stretch; min-height: 2.25rem; border-radius: 2px; }

/* The event-type palette, down one column. Full-height so the row reads as that color
   rather than as a row with a mark on it — the same shape the schedule uses. */
.bb-swatch-cell { width: 0.5rem; padding: 0 !important; }

.bb-swatch {
    display: block;
    width: 0.5rem;
    min-height: 2.75rem;
    height: 100%;
}

.bb-hex {
    font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
    font-size: 0.8125rem;
    color: var(--bb-ink-soft);
    margin-left: 0.375rem;
}

/* --- the shared button row ---------------------------------------------------------

   Every editor ends with the same three. Defined once in _FormActions.cshtml and styled
   once here, so wording, order and appearance are one change rather than several. */

.bb-form-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.625rem;
    align-items: center;
}

/* On a phone the buttons go full width and stack, because a row of three at 44px each
   does not fit and half-width buttons are hard to hit accurately. No reordering needed:
   Save is already first. */
@media (max-width: 30rem) {
    .bb-form-actions { flex-direction: column; align-items: stretch; }
    .bb-form-actions .bb-button-inline { width: 100%; }
}

.bb-form-actions-note { max-width: 34rem; }

/* --- the grid ----------------------------------------------------------------------

   A <table class="bb-grid"> is still a table: screen readers announce rows and columns,
   and it degrades to something readable with script blocked. What the class adds is
   sortable headers (server-side, see SortHeaderTagHelper) and drag-to-resize columns
   (grid.js). Both are enhancements on top of markup that works without them. */

/* Fixed layout is what makes a set width actually stick — with the default auto layout
   the browser renegotiates every column from the content and ignores what was dragged. */
.bb-grid { table-layout: fixed; }

.bb-grid th { position: relative; user-select: none; }

.bb-grid th,
.bb-grid td {
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Cells that stack a label over a sub-line need to wrap rather than clip. */
.bb-grid td { white-space: normal; }

.bb-sortable { padding: 0 !important; }

.bb-sort-link {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.625rem 0.875rem;
    color: inherit;
    text-decoration: none;
    font: inherit;
    /* The whole header cell is the target, not just the words. */
    min-height: var(--bb-touch);
}
.bb-sort-link:hover { background: var(--bb-ground); }

.bb-sort-arrow { font-size: 0.75rem; line-height: 1; }
.bb-sort-arrow.is-idle { opacity: 0; transition: opacity 100ms ease; }
.bb-sortable:hover .bb-sort-arrow.is-idle { opacity: 0.45; }

@media (prefers-reduced-motion: reduce) {
    .bb-sort-arrow.is-idle { transition: none; }
}

/* The drag handle. Wide enough to hit, invisible until the pointer is near it. */
.bb-grid-handle {
    position: absolute;
    top: 0;
    right: 0;
    width: 0.75rem;
    height: 100%;
    cursor: col-resize;
    touch-action: none;
}
.bb-grid-handle::after {
    content: "";
    position: absolute;
    top: 20%;
    right: 0.3125rem;
    width: 2px;
    height: 60%;
    background: var(--bb-line);
    opacity: 0;
}
.bb-grid th:hover .bb-grid-handle::after { opacity: 1; }

/* While dragging, stop the pointer selecting text across the whole page. */
body.bb-resizing { user-select: none; cursor: col-resize; }
body.bb-resizing .bb-grid-handle::after { opacity: 1; }

/* --- a page heading with its action beside it --------------------------------------- */

.bb-page-head-row {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 1rem;
    flex-wrap: wrap;
}
.bb-page-head-row .bb-page-head { margin-bottom: 0; flex: 1 1 16rem; }

/* A row, not a stack: the stock button's width: 100% wins the cascade over
   .bb-button-inline (it comes later at the same specificity), so with more than one
   action here they each stretched and piled up. Sized to their labels instead. */
.bb-page-head-row .bb-head-action {
    flex: none;
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}
.bb-page-head-row .bb-head-action .bb-button { width: auto; }

/* --- report filters ---------------------------------------------------------------- */

/* A row of preset ranges and two date boxes. Presets first because "this fiscal year" is
   what somebody means nine times out of ten. */
.bb-filter {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem 0.75rem;
    margin: 0 0 1.25rem;
    padding: 0.75rem;
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
}

.bb-filter label,
.bb-filter-label { font-size: 0.875rem; color: var(--bb-ink-soft); }

.bb-filter select,
.bb-filter input { min-height: var(--bb-touch); }

.bb-chip {
    display: inline-flex;
    align-items: center;
    min-height: 2rem;
    padding: 0.25rem 0.75rem;
    border: 1px solid var(--bb-line);
    border-radius: 1rem;
    color: var(--bb-ink);
    text-decoration: none;
    font-size: 0.875rem;
}

.bb-chip:hover { background: var(--bb-ground); }

.bb-chip.is-current {
    background: var(--bb-accent-wash);
    border-color: var(--bb-accent);
    color: var(--bb-accent);
    font-weight: 650;
}

/* --- the acknowledgment letter -------------------------------------------------------- */

/* A document somebody prints and posts, so it is set like one: a measured line length,
   generous leading, and nothing on the page that isn't part of the letter. */
.bb-letter {
    background: var(--bb-surface);
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    padding: 2rem;
    margin: 0 0 1.5rem;
    max-width: 42rem;
    line-height: 1.7;
}

.bb-letter p { margin: 0 0 1rem; }

.bb-letter-head { margin-bottom: 2rem; }
.bb-letter-head p { margin: 0; color: var(--bb-ink-soft); font-size: 0.9375rem; }
.bb-letter-club { font-weight: 650; color: var(--bb-ink) !important; font-size: 1.0625rem !important; }

.bb-letter-date { color: var(--bb-ink-soft); }
.bb-letter-to { font-style: normal; margin: 0 0 1.5rem; }
.bb-letter-sign { margin-top: 2rem !important; font-weight: 650; }
.bb-letter-ref { color: var(--bb-ink-soft); font-size: 0.8125rem; margin-top: 2rem !important; }

@media print {
    .bb-letter { border: 0; padding: 0; max-width: none; }
}

/* --- the audit trail ------------------------------------------------------------------ */

.bb-audit { margin-bottom: 1rem; }

.bb-audit-head {
    display: flex;
    flex-wrap: wrap;
    align-items: start;
    justify-content: space-between;
    gap: 0.5rem 1rem;
    margin-bottom: 0.75rem;
}

.bb-audit-head h2 { margin: 0; }

.bb-audit-table {
    font-weight: 400;
    color: var(--bb-ink-soft);
    font-size: 0.9375rem;
}

/* Recorded values, shown as recorded. Monospace because these are stored strings being
   compared character by character, and a proportional font hides a trailing space. */
.bb-audit-value {
    font-family: ui-monospace, SFMono-Regular, "Cascadia Mono", Consolas, monospace;
    font-size: 0.8125rem;
    word-break: break-word;
}

.bb-audit-old { color: var(--bb-ink-soft); text-decoration: line-through; }

/* --- the month calendar ------------------------------------------------------------

   Two layouts, one page, chosen by width alone. The wide one is the seven-column grid
   with the events drawn inside the day. The narrow one is a small month — day number
   plus a dot per event — over an agenda of the days that have anything on them.

   Seven columns wide enough to hold a sign-up button do not fit on a phone. That was
   tried, and the result was either a horizontal scrollbar or a button too small to hit.
   The dots carry "how busy is the 14th" at a glance, which is what the grid was for, and
   the agenda underneath carries everything else. */

.bb-cal-small { display: block; }
.bb-cal-wide { display: none; }

@media (min-width: 60rem) {
    .bb-cal-small { display: none; }
    .bb-cal-wide { display: block; }
}

/* The month being looked at, on its own line over the steering wheel, centered so it
   reads as the title of the grid below rather than a label on any one button. */
.bb-cal-month {
    text-align: center;
    font-size: 1.375rem;
    margin: 0 0 0.625rem;
}

/* Three buttons, one line, always — the row is the calendar's steering wheel and a
   wrapped month button reads as a different control. Tighter padding than the stock
   button so all three fit beside each other on the narrowest phone. */
.bb-cal-nav {
    display: flex;
    gap: 0.375rem;
    flex-wrap: nowrap;
    margin: 0 0 1rem;
}
.bb-cal-nav .bb-button {
    padding: 0.5rem 0.625rem;
    white-space: nowrap;
}

/* --- the small month ---------------------------------------------------------------- */

.bb-cal-mini {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
    margin-bottom: 1.25rem;
}

.bb-cal-mini th {
    width: 14.28%;
    padding: 0.25rem 0;
    font-size: 0.75rem;
    color: var(--bb-ink-soft);
    font-weight: 600;
    text-align: center;
}

.bb-cal-mini td {
    width: 14.28%;
    border: 1px solid var(--bb-line-soft);
    padding: 0.25rem 0;
    text-align: center;
    vertical-align: top;
    /* Every cell the same height whether or not it has dots, so the weeks line up. */
    height: 2.5rem;
}

.bb-cal-mini a { display: block; color: inherit; text-decoration: none; }

.bb-cal-dots { display: block; line-height: 1; min-height: 0.5rem; margin-top: 0.15rem; }

.bb-cal-dot {
    display: inline-block;
    width: 0.375rem;
    height: 0.375rem;
    border-radius: 50%;
    margin: 0 0.05rem;
}

.bb-cal-dayhead {
    font-size: 0.875rem;
    font-weight: 650;
    border-bottom: 1px solid var(--bb-line);
    padding-bottom: 0.25rem;
    margin: 1.25rem 0 0.5rem;
    /* An anchored heading shouldn't land flush against the top of the viewport. */
    scroll-margin-top: 1rem;
}

.bb-cal-dayhead.is-today { color: var(--bb-accent); }

/* --- the wide grid ------------------------------------------------------------------ */

.bb-cal-grid {
    width: 100%;
    table-layout: fixed;
    border-collapse: collapse;
}

.bb-cal-grid th {
    width: 14.28%;
    padding: 0.375rem 0.5rem;
    text-align: left;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--bb-ink-soft);
    border-bottom: 1px solid var(--bb-line);
}

.bb-cal-grid td {
    width: 14.28%;
    border: 1px solid var(--bb-line-soft);
    vertical-align: top;
    padding: 0.25rem;
    /* Tall enough that an empty week still reads as a week. */
    height: 7rem;
}

.bb-cal-day { font-weight: 650; font-size: 0.8125rem; color: var(--bb-ink-soft); }

.bb-cal-grid td.is-outside,
.bb-cal-mini td.is-outside { background: var(--bb-line-soft); }

.bb-cal-grid td.is-outside .bb-cal-day,
.bb-cal-mini td.is-outside { opacity: 0.55; }

.bb-cal-grid td.is-today,
.bb-cal-mini td.is-today { outline: 2px solid var(--bb-accent); outline-offset: -2px; }

.bb-cal-grid td.is-today .bb-cal-day,
.bb-cal-mini td.is-today .bb-cal-day { color: var(--bb-accent); }

/* --- one event, at either size ------------------------------------------------------ */

.bb-cal-event {
    border-left: 3px solid var(--bb-line);
    background: var(--bb-surface);
    border-radius: 0 var(--bb-radius) var(--bb-radius) 0;
    padding: 0.25rem 0.375rem;
    margin-top: 0.25rem;
    font-size: 0.75rem;
    line-height: 1.3;
}

.bb-cal-event.is-roomy {
    padding: 0.625rem 0.75rem;
    font-size: 0.875rem;
    border: 1px solid var(--bb-line);
    border-left-width: 4px;
    border-radius: var(--bb-radius);
}

.bb-cal-event.is-cancelled { opacity: 0.7; }
.bb-cal-event.is-cancelled .bb-cal-title { text-decoration: line-through; }

.bb-cal-time { font-weight: 650; }
.bb-cal-title { display: block; color: var(--bb-ink); text-decoration: none; font-weight: 600; }
.bb-cal-title:hover { text-decoration: underline; }
.bb-cal-where { color: var(--bb-ink-soft); }
.bb-cal-note { color: var(--bb-ink-soft); margin-top: 0.15rem; }

/* --- the sign-up controls ----------------------------------------------------------- */

.bb-signup { display: grid; gap: 0.375rem; margin-top: 0.375rem; }
.bb-signup-tight { gap: 0.25rem; margin-top: 0.25rem; }

.bb-shift { display: flex; flex-wrap: wrap; align-items: center; gap: 0.375rem; }
.bb-shift form { margin: 0; }

.bb-shift-name { flex: 1 1 6rem; min-width: 0; }

/* On its own line under the name: "when am I needed" reads as part of the shift, not
   as a decoration squeezed beside it in a grid cell. */
.bb-shift-when { display: block; color: var(--bb-ink-soft); font-size: 0.8125rem; }
.bb-shift-left { color: var(--bb-ink-soft); margin-left: 0.375rem; }

.bb-shift-roster {
    flex-basis: 100%;
    color: var(--bb-ink-soft);
    font-size: 0.75rem;
}

.bb-shift.is-mine { background: var(--bb-accent-wash); border-radius: var(--bb-radius); }

/* In a grid cell the button carries its own count and has to stay on one line — a
   wrapped "sign up (3)" is what made the cell twice as tall as its neighbours. */
.bb-signup-tight .bb-button-small { white-space: nowrap; }

.bb-button-small {
    width: auto;
    min-height: 1.75rem;
    padding: 0.15rem 0.5rem;
    font-size: 0.75rem;
}

/* Roomy layouts get a properly thumb-sized button; the grid is mouse territory. */
.bb-cal-event.is-roomy .bb-button-small {
    min-height: 2.25rem;
    padding: 0.375rem 0.875rem;
    font-size: 0.875rem;
}

.bb-spots { display: inline-flex; align-items: center; gap: 0.25rem; }

.bb-spot-button {
    min-width: 1.75rem;
    min-height: 1.75rem;
    border: 1px solid var(--bb-line);
    background: var(--bb-surface);
    color: var(--bb-ink);
    border-radius: var(--bb-radius);
    font-size: 0.875rem;
    line-height: 1;
    cursor: pointer;
}

.bb-spot-button:disabled { opacity: 0.4; cursor: default; }

.bb-cal-event.is-roomy .bb-spot-button { min-width: 2.25rem; min-height: 2.25rem; }

.bb-spot-state { color: var(--bb-good); font-weight: 650; white-space: nowrap; }

/* The publish-from-the-month button on a draft block. */
.bb-cal-publish { margin-top: 0.375rem; }

/* --- the key ------------------------------------------------------------------------ */

.bb-cal-key {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem 1rem;
    align-items: center;
    margin-top: 0.75rem;
    font-size: 0.8125rem;
    color: var(--bb-ink-soft);
}

/* Each entry is a filter toggle, so it is a button — but drawn as the quiet label it
   always was until pressed. The border is there from the start, transparent, so pressing
   one doesn't nudge its neighbours. */
.bb-cal-key-item {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    background: none;
    border: 1px solid transparent;
    border-radius: var(--bb-radius);
    padding: 0.25rem 0.5rem;
    font: inherit;
    font-size: inherit;
    color: inherit;
    cursor: pointer;
}
.bb-cal-key-item:hover { border-color: var(--bb-line); }
.bb-cal-key-item.is-on {
    border-color: var(--bb-accent);
    background: var(--bb-accent-wash);
    color: var(--bb-ink);
}

.bb-cal-key-swatch {
    display: inline-block;
    width: 0.875rem;
    height: 0.875rem;
    border-radius: 0.2rem;
}

/* What the key's filter takes off the month — tiles, dots, and whole emptied days.
   !important because the dots and tiles set their own display. */
.bb-cal-filtered { display: none !important; }

/* --- the series wizard ---------------------------------------------------------------- */

/* Where you are and what is left. A list rather than a bar: a bar says how far along you
   are, a list says what is still coming, and the second is the useful one. */
.bb-steps {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem 1.25rem;
    list-style: none;
    margin: 0 0 1.25rem;
    padding: 0;
    font-size: 0.8125rem;
    color: var(--bb-ink-soft);
}

.bb-steps li { display: flex; align-items: center; gap: 0.5rem; }
.bb-steps .is-current { color: var(--bb-ink); font-weight: 650; }

.bb-step-number {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.5rem;
    height: 1.5rem;
    border-radius: 50%;
    border: 1px solid var(--bb-line);
    font-size: 0.75rem;
}

.bb-steps .is-current .bb-step-number {
    background: var(--bb-accent);
    border-color: var(--bb-accent);
    color: var(--bb-accent-ink);
}

.bb-steps .is-done .bb-step-number { border-color: var(--bb-accent); color: var(--bb-accent); }

/* Seven tick boxes in a row, thumb-sized, so picking Friday and Saturday is two taps. */
.bb-days { display: flex; flex-wrap: wrap; gap: 0.375rem; }

.bb-day {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    min-height: var(--bb-touch);
    padding: 0.25rem 0.625rem;
    border: 1px solid var(--bb-line);
    border-radius: var(--bb-radius);
    background: var(--bb-surface);
    cursor: pointer;
    user-select: none;
}

.bb-day:has(input:checked) {
    border-color: var(--bb-accent);
    background: var(--bb-accent-wash);
    font-weight: 650;
}

.bb-field-indent { margin-left: 1.75rem; }

/* Term above, value below — a summary is read down, not across. */
.bb-summary { margin: 0; display: grid; gap: 0.75rem; }
.bb-summary dt {
    font-size: 0.6875rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--bb-ink-soft);
}
.bb-summary dd { margin: 0.15rem 0 0; }

.bb-preview > summary { cursor: pointer; }
.bb-preview .bb-cal-mini { max-width: 22rem; margin-bottom: 1rem; }

/* The dates about to be created, and the ones that land on something already booked. */
.bb-cal-mini td.is-planned {
    background: var(--bb-accent-wash);
    font-weight: 650;
}

.bb-cal-mini td.is-clash {
    background: var(--bb-warn-wash);
    outline: 2px solid var(--bb-warn);
    outline-offset: -2px;
}

/* Edit and Delete on a schedule row. Sits under the pills rather than beside them, so a
   narrow screen stacks instead of squeezing the title. */
.bb-event-actions {
    display: flex;
    gap: 0.75rem;
    align-items: center;
    font-size: 0.8125rem;
    margin-top: 0.25rem;
}

.bb-event-actions form { margin: 0; }

/* A number in a grid cell: narrow, right-aligned, and without the spinner, which at this
   width covers the digits it is meant to help with. */
.bb-num-input {
    width: 5rem;
    text-align: right;
    -moz-appearance: textfield;
}

.bb-num-input::-webkit-outer-spin-button,
.bb-num-input::-webkit-inner-spin-button { -webkit-appearance: none; margin: 0; }

/* A date or time in a grid cell is sized by its content rather than stretched. */
.bb-grid input[type="date"] { width: 9.5rem; }
.bb-grid input[type="time"] { width: 7.5rem; }

/* --- column widths in a grid --------------------------------------------------------

   THE PROBLEM: `.bb-table` is table-layout:auto, where a width on a <th> is a suggestion
   the browser is free to overrule based on content. So a tick-box column ends up as wide
   as the word in its heading, a date column gets squeezed by a long title beside it, and
   dragging a column handle only sort of works — grid.js writes a pixel width that auto
   layout then renegotiates.

   THE FIX: opt a grid into `bb-grid-sized` and give each heading a width class. Under
   fixed layout the first row's widths are obeyed exactly, the browser stops measuring
   every cell (so a long grid renders faster), and the drag handles finally do what they
   look like they do.

   Sized in rem against what the column HOLDS, not against its heading — a heading is
   uppercase 11px and is never the widest thing in the column. Leave exactly one column
   without a class and it absorbs whatever is left over; that should be the one carrying
   the longest text. */

.bb-grid-sized { table-layout: fixed; }

/* A heading may be wider than its column now, so it has to be allowed to wrap rather
   than force the column open. */
.bb-grid-sized thead th { white-space: normal; }

.bb-w-tick    { width: 3rem; }      /* a checkbox, and nothing else */
.bb-w-day     { width: 4.5rem; }    /* "Wed" */
.bb-w-num     { width: 6rem; }      /* a headcount, a quantity */
.bb-w-money   { width: 8rem; }      /* $1,234.56 with room for the minus */
.bb-w-time    { width: 8.5rem; }    /* a time picker with its own chrome */
.bb-w-code    { width: 9rem; }      /* CONCESS, 4110, SYSCO */
.bb-w-date    { width: 11rem; }     /* a date picker with its own chrome */
.bb-w-actions { width: 9rem; }      /* Edit and Delete side by side */

/* Under fixed layout a cell that can't fit its content spills. Anything that is a
   sentence rather than a value should wrap instead. */
.bb-grid-sized td { overflow-wrap: anywhere; }

/* …except the ones that must not be broken mid-value. */
.bb-grid-sized .bb-nowrap,
.bb-grid-sized td.bb-num { overflow-wrap: normal; }

/* The month previews in the series wizard, side by side while there is room. */
.bb-months { display: flex; flex-wrap: wrap; gap: 1.25rem; }
.bb-month-block { flex: 0 0 auto; }
.bb-month-block .bb-cal-mini { width: 15rem; }
.bb-month-block .bb-month { margin-top: 0; }

.bb-cal-key-swatch.bb-swatch-planned { background: var(--bb-accent-wash); border: 1px solid var(--bb-accent); }
.bb-cal-key-swatch.bb-swatch-clash { background: var(--bb-warn-wash); border: 1px solid var(--bb-warn); }

/* A field that doesn't apply to what has been chosen — see fields.js. Dimmed rather than
   hidden, because the point is to teach the rule: you can see the box, and see that this
   kind of account has no use for it. */
.is-not-applicable { opacity: 0.55; }
.is-not-applicable label { cursor: default; }

:disabled { cursor: not-allowed; background: var(--bb-line-soft); }

/* A code picker's label, with its "Add" opposite. The label keeps its own weight and the
   Add is quiet — it is there for the once in twenty times the code is missing, and should
   not compete with the field itself. */
.bb-label-row {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.75rem;
}

.bb-label-row label { margin-bottom: 0.25rem; }

.bb-add-code {
    font-size: 0.8125rem;
    font-weight: 600;
    white-space: nowrap;
    /* Clears the thumb target without pushing the label off its baseline. */
    padding: 0.15rem 0.25rem;
    margin: -0.15rem -0.25rem 0 0;
}

.bb-add-code::after {
    content: "";
    display: inline-block;
    width: 0.5rem;
    height: 0.5rem;
    margin-left: 0.3rem;
    border-top: 1.5px solid currentColor;
    border-right: 1.5px solid currentColor;
    /* The arrow that means "this opens somewhere else", so a new tab is not a surprise. */
    transform: translateY(-0.05rem) rotate(45deg);
}
