:root {
    color-scheme: light;
    --bg: #f6f7f5;
    --surface: #ffffff;
    --ink: #17211f;
    --muted: #5b6763;
    --line: #d9dfdc;
    --accent: #0f766e;
    --accent-ink: #ffffff;
    --warn: #b45309;
}

* {
    box-sizing: border-box;
}

body {
    margin: 0;
    background: var(--bg);
    color: var(--ink);
    font-family: "Avenir Next", "Segoe UI", ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, sans-serif;
    font-size: 16px;
    line-height: 1.5;
}

a {
    color: inherit;
}

.topbar {
    position: sticky;
    top: 0;
    z-index: 10;
    display: flex;
    align-items: center;
    gap: 20px;
    min-height: 64px;
    padding: 12px 24px;
    /* Opaque: scrolled content must never ghost through the sticky header. */
    background: #fff;
    border-bottom: 1px solid var(--line);
}

.brand {
    flex: 0 0 auto;
    color: var(--accent);
    font-weight: 800;
    text-decoration: none;
}

.session-tools {
    margin-left: auto;
    display: flex;
    align-items: center;
    gap: 10px;
}

.session-user {
    color: var(--muted);
    font-size: 0.95rem;
    font-weight: 700;
}

/* Collapsible global menu (spec 4.c.5 per 14.b.40): the nav lives behind a
   hamburger toggle at every screen size so it never occupies the page. */
.menu {
    position: relative;
    flex: 0 0 auto;
}

.menu-toggle {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    min-height: 38px;
    padding: 6px 12px;
    border: 1px solid var(--line);
    border-radius: 6px;
    cursor: pointer;
    list-style: none;
    font-weight: 700;
    color: var(--ink);
    user-select: none;
}

.menu-toggle::-webkit-details-marker {
    display: none;
}

.menu-toggle:hover,
.menu-toggle:focus-visible,
.menu[open] .menu-toggle {
    background: #dff3ef;
    outline: none;
}

.menu-icon {
    display: inline-flex;
    flex-direction: column;
    justify-content: center;
    gap: 4px;
    width: 18px;
}

.menu-icon span {
    height: 2px;
    border-radius: 1px;
    background: currentColor;
}

.menu-panel {
    position: absolute;
    top: calc(100% + 8px);
    right: 0;
    z-index: 20;
    width: min(320px, calc(100vw - 24px));
    max-height: calc(100vh - 96px);
    overflow-y: auto;
    padding: 10px;
    background: #fff;
    border: 1px solid var(--line);
    border-radius: 10px;
    box-shadow: 0 10px 30px rgba(15, 45, 42, 0.16);
}

.nav {
    display: flex;
    flex-direction: column;
    gap: 2px;
}

.nav a {
    min-height: 38px;
    display: flex;
    align-items: center;
    padding: 6px 10px;
    border-radius: 6px;
    color: var(--muted);
    text-decoration: none;
}

.nav a.active,
.nav a:focus-visible,
.nav a:hover {
    background: #dff3ef;
    color: var(--ink);
    outline: none;
}

.menu-sub summary {
    min-height: 38px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 6px 10px;
    border-radius: 6px;
    color: var(--muted);
    font-weight: 700;
    cursor: pointer;
    list-style: none;
    user-select: none;
}

.menu-sub summary::-webkit-details-marker {
    display: none;
}

.menu-sub summary::after {
    content: "▾";
    font-size: 0.8rem;
}

.menu-sub[open] summary::after {
    content: "▴";
}

.menu-sub summary.active,
.menu-sub summary:focus-visible,
.menu-sub summary:hover {
    background: #dff3ef;
    color: var(--ink);
    outline: none;
}

.menu-sub-links {
    display: flex;
    flex-direction: column;
    gap: 2px;
    margin: 2px 0 4px;
    padding-left: 14px;
    border-left: 2px solid var(--line);
    margin-left: 10px;
}

.menu-session {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
    margin-top: 10px;
    padding: 10px 10px 4px;
    border-top: 1px solid var(--line);
}

.page {
    width: min(1120px, calc(100% - 32px));
    margin: 12px auto 40px;
}

.panel {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(240px, 420px);
    gap: 24px;
    align-items: end;
    padding: 12px 0;
    border-bottom: 1px solid var(--line);
}

.eyebrow {
    margin: 0 0 8px;
    color: var(--accent);
    font-size: 0.8rem;
    font-weight: 800;
    letter-spacing: 0;
    text-transform: uppercase;
}

h1,
h2 {
    margin: 0;
    line-height: 1.15;
}

h1 {
    font-size: 2rem;
}

h2 {
    font-size: 1.1rem;
    margin-bottom: 14px;
}

.lede {
    margin: 0;
    color: var(--muted);
}

.grid {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
    gap: 16px;
    margin-top: 20px;
}

.card,
.metric {
    margin-top: 20px;
    padding: 18px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
}

.metric {
    min-height: 112px;
}

.metric span {
    display: block;
    color: var(--muted);
    font-weight: 700;
}

.metric strong {
    display: block;
    margin-top: 8px;
    color: var(--accent);
    font-size: 2rem;
}

.stage-list {
    display: grid;
    gap: 10px;
    padding-left: 0;
    list-style: none;
}

.stage-list li {
    display: flex;
    gap: 10px;
    align-items: center;
}

.stage-list span,
.status {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-width: 28px;
    min-height: 28px;
    padding: 2px 8px;
    border-radius: 999px;
    background: #dff3ef;
    color: var(--accent);
    font-weight: 800;
}

.stage-list strong {
    margin-left: auto;
    color: var(--muted);
    font-size: 0.9rem;
}

.table-wrap {
    overflow-x: auto;
}

table {
    width: 100%;
    border-collapse: collapse;
}

th,
td {
    padding: 10px;
    border-bottom: 1px solid var(--line);
    text-align: left;
    vertical-align: top;
}

th {
    color: var(--muted);
    font-size: 0.86rem;
}

.auth-shell {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: 16px;
    margin-top: 24px;
}

.auth-card {
    margin-top: 0;
}

.form-stack {
    display: grid;
    gap: 14px;
}

.field {
    display: grid;
    gap: 6px;
    color: var(--muted);
    font-size: 0.95rem;
    font-weight: 700;
}

.field input {
    min-height: 44px;
    padding: 10px 12px;
    border: 1px solid var(--line);
    border-radius: 6px;
    font: inherit;
    color: var(--ink);
    background: #fff;
}

.field select {
    min-height: 44px;
    padding: 10px 12px;
    border: 1px solid var(--line);
    border-radius: 6px;
    font: inherit;
    color: var(--ink);
    background: #fff;
}

.checkbox-row {
    display: flex;
    align-items: flex-start;
    gap: 8px;
}

.checkbox-row input {
    flex: 0 0 auto;
    margin-top: 3px;
}

.button {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: 40px;
    padding: 8px 14px;
    border: 0;
    border-radius: 6px;
    background: var(--accent);
    color: var(--accent-ink);
    font: inherit;
    font-weight: 800;
    text-decoration: none;
    cursor: pointer;
}

.button-secondary {
    background: #dff3ef;
    color: var(--ink);
}

.button-danger {
    background: #a61b1b;
    color: #fff;
}

.button:disabled {
    cursor: not-allowed;
    opacity: 0.55;
}

.notice {
    margin: 0 0 14px;
    padding: 10px 12px;
    border-radius: 6px;
    font-weight: 700;
}

.notice-error {
    background: #fff3e8;
    color: var(--warn);
}

.notice-ok {
    background: #e7f8f0;
    color: #146c43;
}

/* Attention, not error and not success: a yellow the reader can't skim past
   (e.g. an assistance default auto-raised to cover a co-guardian, #79). */
.notice-warn {
    background: #fff4cc;
    color: #6b5900;
}

/* Orange "locked / read-only for a reason" banner — e.g. availability once
   Stage 3 has closed (#37): explains WHY an action is unavailable. */
.notice-locked {
    background: #ffe8d6;
    color: #9a3f00;
}

/* Dashboard activity feed + photo row (#128, spec 4.f). */
.dash-photos-head {
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 12px;
}

.dash-photos-all {
    color: var(--accent);
    font-weight: 700;
    font-size: 0.9rem;
    text-decoration: none;
    white-space: nowrap;
}

/* #132: a flex row let a few photos grow toward the old 132px cap and read
   as oversized. A grid with auto-fill keeps every tile a consistent small
   square and grows the column count with the card's real width, so phones
   land around 3-5 across and wider/desktop layouts fit more automatically —
   no viewport breakpoint needed. */
.dash-photo-row {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(76px, 1fr));
    gap: 10px;
    margin-top: 12px;
}

.dash-photo {
    aspect-ratio: 1 / 1;
    border-radius: 8px;
    overflow: hidden;
    background: #eef2f0;
    display: block;
}

.dash-photo img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.15s ease;
}

.dash-photo:hover img {
    transform: scale(1.04);
}

.dash-photo-more {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    background: #dff3ef;
    color: var(--accent);
    font-weight: 800;
    font-size: 1.05rem;
    text-decoration: none;
}

.dash-photo-more small {
    font-weight: 700;
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
}

.feed-list {
    list-style: none;
    margin: 12px 0 0;
    padding: 0;
    display: grid;
    gap: 4px;
}

.feed-list li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 9px 10px;
    border-radius: 8px;
    /* Without this the row cannot shrink below its own no-wrap content, so
       .feed-text never comes under pressure to ellipsize and the line widens
       the whole document instead (issue #150). A flex/grid item defaults to
       min-width: auto, which is a content-based minimum — the ellipsis rules
       on .feed-text are inert until the row is allowed to be narrower than
       its text. Measured: 1528px of document at a 390px viewport. */
    min-width: 0;
}

.feed-list li:nth-child(odd) {
    background: color-mix(in srgb, var(--line) 24%, transparent);
}

.feed-icon {
    width: 32px;
    height: 32px;
    border-radius: 999px;
    background: #dff3ef;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 0.95rem;
    flex-shrink: 0;
}

.feed-text {
    color: inherit;
    text-decoration: none;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.feed-text:hover {
    color: var(--accent);
}

.feed-time {
    margin-left: auto;
    color: var(--muted);
    font-size: 0.85rem;
    white-space: nowrap;
    flex-shrink: 0;
}

.dash-feed-empty {
    color: var(--muted);
    margin: 10px 0 0;
}

.push-manage-details {
    margin-top: 6px;
    font-weight: 400;
}

.push-manage-details summary {
    cursor: pointer;
    font-weight: 700;
}

.push-manage-instructions {
    margin-top: 6px;
}

.push-manage-instructions p {
    margin: 4px 0;
}

.copy-notice {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 10px;
}

.copy-notice a {
    overflow-wrap: anywhere;
}

.archived-row {
    opacity: 0.55;
}

.danger-zone {
    min-width: 280px;
}

.danger-zone summary {
    width: max-content;
    list-style: none;
}

.danger-zone summary::-webkit-details-marker {
    display: none;
}

.danger-panel {
    margin-top: 10px;
    padding: 14px;
    border: 2px solid #a61b1b;
    border-radius: 6px;
    background: #ffe5e5;
    color: #651313;
}

.danger-panel h3 {
    margin-top: 0;
}

@media (max-width: 720px) {
    /* The topbar stays a single row at every width now that the nav is
       collapsed behind the menu toggle (spec 4.c.5 per 14.b.40). */
    .topbar {
        gap: 10px;
        padding: 12px 16px;
    }

    .panel {
        grid-template-columns: 1fr;
    }

    /* #75: reclaim horizontal width on narrow viewports. The page gutter
       (16px/side) and card padding (18px/side) together eat ~68px per row on a
       phone, squeezing tables that already have to scroll to show every column.
       While width is scarce we shrink both, and let a scrolling table bleed to
       the card edges. Above this breakpoint the generous margins return
       (nothing here applies), so large screens keep the spacious look — the
       width is only sacrificed while it is actually in short supply. */
    .page {
        width: calc(100% - 16px); /* 8px gutter each side (was 16) */
    }

    .card,
    .metric {
        padding: 12px; /* was 18 */
    }

    /* A horizontally-scrolling table spans the full width of its card instead
       of sitting inside the card padding; the negative margins match the card
       padding above so it reaches the card's edges. th/td padding keeps cells
       off the very edge. */
    .card > .table-wrap {
        margin-left: -12px;
        margin-right: -12px;
    }

    /* Tighter cells fit more columns before the table has to scroll at all. */
    th,
    td {
        padding: 8px; /* was 10 */
    }
}

.admin-tabs {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    margin: 0 0 20px;
}

.admin-tabs a {
    min-height: 38px;
    display: inline-flex;
    align-items: center;
    padding: 6px 12px;
    border-radius: 6px;
    color: var(--muted);
    text-decoration: none;
    border: 1px solid transparent;
}

.admin-tabs a.active,
.admin-tabs a:focus-visible,
.admin-tabs a:hover {
    background: #dff3ef;
    color: var(--ink);
    outline: none;
}

.form-inline {
    /* flex-wrap keeps filter forms inside the viewport on phones (issue #13);
       .availability-toolbar/.admin-tabs/.inline-form already wrap the same way. */
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
    margin: 2px 4px 2px 0;
}

.availability-toolbar {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    margin-top: 20px;
}

.availability-toolbar fieldset {
    display: flex;
    align-items: center;
    gap: 8px;
    margin: 0;
    padding: 0;
    border: 0;
}

.availability-grid {
    display: grid;
    grid-template-columns: 1fr;
    gap: 16px;
    margin-top: 16px;
}

@media (min-width: 640px) {
    .availability-grid {
        grid-template-columns: repeat(2, 1fr);
    }
}

@media (min-width: 1024px) {
    .availability-grid {
        grid-template-columns: repeat(3, 1fr);
    }
}

.availability-month {
    padding: 14px;
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: 8px;
}

.availability-month h3 {
    margin: 0 0 10px;
    font-size: 1rem;
}

.availability-weekdays,
.availability-week {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 4px;
    text-align: center;
}

.availability-weekdays {
    margin-bottom: 4px;
    color: var(--muted);
    font-size: 0.78rem;
    font-weight: 700;
}

.availability-week {
    margin-bottom: 4px;
}

.availability-day {
    display: flex;
    flex-direction: column-reverse;
    align-items: center;
    justify-content: center;
    min-height: 36px;
    border-radius: 4px;
    font-size: 0.85rem;
    user-select: none;
    cursor: pointer;
    /* Drag-to-select must not scroll the page on touch (issue #22). */
    touch-action: none;
}

.availability-day:has(input:checked) {
    background: #fde7e0;
    color: var(--warn);
    font-weight: 700;
}

.availability-day.empty {
    cursor: default;
}

.availability-day.blocked {
    background: #fde7e0;
    color: var(--warn);
    font-weight: 700;
    border-radius: 4px;
}

.availability-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 20px;
}

.visually-hidden {
    position: absolute;
    width: 1px;
    height: 1px;
    margin: -1px;
    padding: 0;
    overflow: hidden;
    clip: rect(0 0 0 0);
    white-space: nowrap;
    border: 0;
}

.density-track {
    display: inline-block;
    width: 4.5em;
    height: 0.7em;
    vertical-align: middle;
    background: var(--line);
    border-radius: 0.35em;
    overflow: hidden;
}

.density-bar {
    display: block;
    height: 100%;
    border-radius: 0.35em;
}

.warning-icon {
    color: var(--warn, #b3541e);
    cursor: help;
}

.histogram {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.histogram li {
    display: grid;
    grid-template-columns: 90px 1fr 40px;
    align-items: center;
    gap: 10px;
}

.histogram-bar-wrap {
    background: #eee;
    border-radius: 4px;
    overflow: hidden;
    height: 14px;
}

.histogram-bar {
    display: block;
    height: 100%;
    background: var(--accent, #2c6e49);
}

.histogram-count {
    text-align: right;
}

/* Stage 5 Grocery Planning */
.inline-form {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-right: 1rem;
}
.grocery-progress {
    font-weight: 600;
}
.grocery-item-layout {
    display: grid;
    gap: 1rem;
    grid-template-columns: 1fr;
}
@media (min-width: 720px) {
    .grocery-item-layout {
        grid-template-columns: 3fr 2fr;
    }
}
.checkbox-inline {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    margin-right: 0.75rem;
}

/* Stage 7 attendance banner (spec 7.g.12.b) */
.attendance-banner {
    background: #fef3c7;
    border-bottom: 2px solid #f59e0b;
    padding: 0.6rem 1rem;
    font-size: 0.95rem;
}
.attendance-banner-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 0.5rem;
    margin-top: 0.4rem;
}
.attendance-banner-name {
    font-weight: 600;
    min-width: 10rem;
}
.attendance-banner details,
.attendance-review-row details {
    display: inline-block;
}

/* Header notification bell (spec 8.c.9) */
.notification-bell { position: relative; text-decoration: none; font-size: 1.1rem; padding: 0.25rem 0.4rem; border-radius: 6px; }
.notification-bell:focus-visible { outline: 3px solid #0f766e; outline-offset: 2px; }
.notification-bell .badge {
    position: absolute; top: -0.3rem; right: -0.4rem;
    background: #b91c1c; color: #fff; font-size: 0.7rem; font-weight: 700;
    border-radius: 999px; padding: 0 0.35rem; min-width: 1.1rem; text-align: center; line-height: 1.1rem;
}
.notification-inbox li.unread { font-weight: 600; }
.notification-inbox li { display: flex; gap: 0.6rem; align-items: baseline; padding: 0.35rem 0; }
.notification-inbox time { color: #6b7280; font-size: 0.85rem; white-space: nowrap; }

/* Accessibility: keyboard skip link (spec 3.f) */
.skip-link { position: absolute; left: -9999px; top: 0; background: #0f766e; color: #fff; padding: 0.5rem 1rem; z-index: 100; border-radius: 0 0 6px 0; }
.skip-link:focus { left: 0; }

/* Readable forms (issue #4, spec 14.b.16.c): one field per line; option
   groups vertically aligned with the control and label on the same row. */
form > label {
    display: block;
    margin: 0 0 14px;
    font-weight: 600;
    color: var(--ink);
}
form > label > input:not([type="checkbox"]):not([type="radio"]),
form > label > select,
form > label > textarea {
    display: block;
    width: 100%;
    max-width: 30rem;
    margin-top: 6px;
    min-height: 44px;
    padding: 10px 12px;
    border: 1px solid var(--line);
    border-radius: 6px;
    font: inherit;
    font-weight: 400;
    color: var(--ink);
    background: #fff;
}
form > label > textarea { min-height: 90px; }
form fieldset {
    border: 1px solid var(--line);
    border-radius: 8px;
    padding: 10px 14px 12px;
    margin: 0 0 14px;
    max-width: 34rem;
}
form fieldset legend {
    font-weight: 700;
    padding: 0 6px;
}
form fieldset > label {
    display: flex;
    align-items: flex-start;
    gap: 10px;
    margin: 8px 0;
    font-weight: 400;
    color: var(--ink);
}
form fieldset > label input[type="radio"],
form fieldset > label input[type="checkbox"] {
    flex: none;
    width: 18px;
    height: 18px;
    margin-top: 2px;
    accent-color: #0f766e;
}
/* House picture (#158): upload and link fields stack, full width. */
form fieldset.house-image-fields > label {
    flex-direction: column;
    gap: 4px;
}
form fieldset.house-image-fields > label input {
    width: 100%;
    max-width: 100%;
}
/* Compact forms (table actions, filter rows) keep their inline layout. */
form.inline-form > label,
form.form-inline > label {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    margin: 0;
    font-weight: 400;
}
form.inline-form > label > input,
form.inline-form > label > select,
form.form-inline > label > input,
form.form-inline > label > select {
    display: inline-block;
    width: auto;
    margin-top: 0;
}

/* House thumbnails (issue #17) */
.house-thumbnail { max-width: 120px; max-height: 90px; border-radius: 6px; object-fit: cover; display: inline-block; }
.house-thumbnail-large { max-width: 320px; max-height: 220px; }

/* Family Tree dependents (issue #47): guardian self-service edits presented as
   touch-friendly cards with obvious, full-width edit affordances instead of
   tiny nested collapsibles buried under bulleted names. */
.dependent-list {
    list-style: none;
    margin: 0;
    padding: 0;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.dependent-card {
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 14px 16px;
    background: #fff;
}
.dependent-head {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
}
.dependent-name {
    font-weight: 700;
    font-size: 1.05rem;
}
.dependent-age {
    font-size: 0.72rem;
    font-weight: 700;
    color: var(--accent);
    background: #dff3ef;
    border-radius: 999px;
    padding: 3px 10px;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}
.dependent-guardians {
    margin: 8px 0 0;
    color: var(--muted);
}
.dependent-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 10px;
    margin-top: 14px;
}
/* Each disclosure grows to fill the row; on narrow screens they wrap to
   full-width taps. The summary reuses the .button look and toggles the form. */
.disclosure {
    flex: 1 1 14rem;
}
.disclosure > summary {
    width: 100%;
    list-style: none;
    user-select: none;
}
.disclosure > summary::-webkit-details-marker {
    display: none;
}
.disclosure[open] > summary {
    margin-bottom: 12px;
}
.disclosure-form {
    padding-top: 4px;
}
/* The readable one-field-per-line form rules already apply; keep the last
   control snug against the submit button. */
.disclosure-form > label {
    max-width: 100%;
}
.dependent-subhead {
    margin: 0 0 6px;
    font-weight: 700;
    color: var(--muted);
}
.guardian-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    margin: 0 0 16px;
}
.guardian-chips form {
    margin: 0;
}
.guardian-chip {
    gap: 8px;
}
.app-footer {
    padding: 16px;
    text-align: center;
}
.app-footer-version {
    font-size: 0.75rem;
    color: var(--muted);
}

/* Cricket darts scoreboard (issue #91). Two-column board with the target
   numbers down the middle; marks render as slash / X / circled-X. */
.darts-board {
    table-layout: fixed;
    text-align: center;
}
.darts-board th,
.darts-board td {
    text-align: center;
    vertical-align: middle;
}
.darts-board .darts-team {
    font-size: 1rem;
    color: var(--text, inherit);
    font-weight: 600;
}
.darts-board .darts-team.is-winner {
    color: var(--accent);
}
.darts-board .darts-number {
    width: 5rem;
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--muted);
    background: var(--bg);
}
.darts-board .darts-number-head {
    font-variant: small-caps;
    letter-spacing: 0.03em;
}
.darts-board .darts-cell {
    font-size: 1.9rem;
    line-height: 1;
    font-weight: 700;
    color: var(--accent);
}
.darts-board .darts-cell.is-closed {
    background: color-mix(in srgb, var(--accent) 12%, transparent);
}
.darts-board .darts-points strong {
    font-size: 1.3rem;
}

.darts-scorer {
    border: 1px solid var(--line);
    border-radius: 10px;
    padding: 12px;
    margin-bottom: 12px;
}
.darts-scorer legend {
    padding: 0 6px;
    font-weight: 600;
}
.darts-marks-picker {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    margin-bottom: 10px;
}
.darts-marks-picker label {
    display: inline-flex;
    align-items: center;
    gap: 4px;
}
.darts-target-buttons {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(3.2rem, 1fr));
    gap: 8px;
}
.darts-target-buttons form {
    margin: 0;
}
.darts-target-buttons .button {
    width: 100%;
}

/* Cricket darts — tap-the-scoreboard interaction (issue #91 rework). The cells
   are the scoring surface: each is a full-size button that adds one mark. */
.darts-board.is-tappable .darts-cell {
    padding: 0;
}
.darts-board.is-tappable .darts-cell form {
    margin: 0;
}
.darts-board.is-tappable .darts-cell button {
    display: block;
    width: 100%;
    min-height: 3rem;
    border: none;
    background: transparent;
    cursor: pointer;
    font-size: 1.9rem;
    line-height: 1;
    font-weight: 700;
    color: var(--accent);
    padding: 12px 6px;
    border-radius: 8px;
    transition: background-color 0.12s ease;
}
.darts-board.is-tappable .darts-cell button:hover,
.darts-board.is-tappable .darts-cell button:focus-visible {
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    outline: none;
}
.darts-board.is-tappable .darts-cell button:active {
    background: color-mix(in srgb, var(--accent) 26%, transparent);
}
.darts-cell.is-empty,
.darts-cell.is-empty button {
    color: var(--muted);
}
.darts-cell.is-turn button,
.darts-cell.is-turn span {
    box-shadow: inset 0 0 0 2px color-mix(in srgb, var(--accent) 45%, transparent);
    border-radius: 8px;
}
.darts-team.is-turn {
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.darts-team-name { font-weight: 700; }
.darts-team-points { display: inline-block; margin-top: 4px; }
.darts-team-points strong { font-size: 1.25rem; }
.darts-winner-badge[hidden] { display: none; }

.darts-activity li {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}
.darts-turn {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 8px;
}
.darts-turn .button.is-active {
    background: var(--accent);
    color: var(--accent-ink);
}

/* Darts turn tracking + hand-off modal (issue #91 rework). */
.darts-turn-banner {
    margin: 0 0 12px;
    padding: 10px 14px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--accent) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent) 35%, transparent);
    font-size: 1.05rem;
}
.darts-turn-flag {
    color: var(--accent);
    font-weight: 700;
    white-space: nowrap;
}
.darts-turn-flag[hidden] { display: none; }
.darts-endturn { width: 100%; }

/* Inactive team's cells: visibly not scorable while it's not their turn. */
.darts-cell.is-inactive button {
    opacity: 0.4;
    cursor: not-allowed;
}
.darts-cell.is-inactive button:hover,
.darts-cell.is-inactive button:focus-visible {
    background: transparent;
}

/* Big "your turn" hand-off modal. */
.darts-modal {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background: color-mix(in srgb, #000 62%, transparent);
}
.darts-modal[hidden] { display: none; }
.darts-modal-inner {
    background: var(--surface);
    border-radius: 18px;
    padding: 36px 28px;
    max-width: 520px;
    width: 100%;
    text-align: center;
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
}
.darts-modal-eyebrow {
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-size: 0.8rem;
    color: var(--muted);
    margin: 0 0 8px;
}
.darts-modal-inner h2 {
    font-size: clamp(1.8rem, 6vw, 2.8rem);
    line-height: 1.1;
    margin: 0 0 12px;
    color: var(--accent);
}
.darts-modal-ok {
    margin-top: 18px;
    font-size: 1.1rem;
    padding: 14px 28px;
}

/* Darts win state (issue #91). */
.darts-win-banner {
    margin: 0 0 12px;
    padding: 12px 16px;
    border-radius: 10px;
    background: color-mix(in srgb, #f0ad4e 22%, transparent);
    border: 1px solid color-mix(in srgb, #f0ad4e 55%, transparent);
    font-size: 1.1rem;
}
.darts-win-banner[hidden] { display: none; }
.darts-modal-win .darts-modal-inner h2 { color: #b8860b; }
.darts-modal-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    justify-content: center;
    margin-top: 18px;
}
.darts-modal-actions form { margin: 0; }

.darts-help { margin: 12px 0 0; font-size: 0.9rem; }

/* Darts turn-alert modal controls (issue #91). */
.darts-modal-mute {
    display: inline-block;
    margin-top: 14px;
    background: none;
    border: none;
    color: var(--accent);
    font: inherit;
    cursor: pointer;
    text-decoration: underline;
}
.darts-modal-mute[hidden] { display: none; }
.darts-modal-hint { margin: 10px 0 0; font-size: 0.82rem; }

/* Darts +/- point stepper, per-turn delta, stats, finalize row (issue #91). */
.darts-cell-controls { display: flex; align-items: center; justify-content: center; gap: 6px; }
.darts-tap { display: block; width: 100%; min-height: 3rem; border: none; background: transparent; cursor: pointer; font-size: 1.9rem; line-height: 1; font-weight: 700; color: var(--accent); padding: 12px 6px; border-radius: 8px; }
.darts-tap:hover, .darts-tap:focus-visible { background: color-mix(in srgb, var(--accent) 14%, transparent); outline: none; }
.darts-step {
    min-width: 2rem; min-height: 2rem; border: 1px solid var(--line); border-radius: 8px;
    background: var(--surface); color: var(--accent); font-size: 1.3rem; font-weight: 700; line-height: 1; cursor: pointer;
}
.darts-step:hover:not(:disabled), .darts-step:focus-visible:not(:disabled) { background: color-mix(in srgb, var(--accent) 14%, transparent); }
.darts-step:disabled { opacity: 0.3; cursor: not-allowed; }
.darts-turn-delta { display: block; margin-top: 4px; font-size: 0.78rem; font-weight: 700; color: var(--accent); }
.darts-turn-delta[hidden] { display: none; }
.darts-stats { text-align: center; margin: 0 0 16px; font-variant-numeric: tabular-nums; }
.darts-finish { align-items: center; }
.darts-finish form { margin: 0; }
.darts-modal-score { font-size: 1.05rem; margin: 6px 0 0; }

.darts-activity-time { margin-left: 8px; font-size: 0.8rem; font-variant-numeric: tabular-nums; }
/* Activity grouped by turn — the turn number sits in the left margin. */
.darts-turn-group { display: grid; grid-template-columns: 3.2rem 1fr; gap: 12px; align-items: start; padding: 12px 0; border-top: 2px solid var(--line); }
.darts-turn-group:first-child { border-top: none; }
.darts-turn-label { text-align: center; color: var(--muted); font-size: 0.72rem; text-transform: uppercase; letter-spacing: 0.05em; line-height: 1.2; }
.darts-turn-label b { display: block; font-size: 1.5rem; color: var(--accent); }
.darts-turn-entries { margin: 0; }
/* Finalize + Abandon on one line with a small gap. */
.darts-finish { display: flex; flex-wrap: nowrap; align-items: center; gap: 10px; }
.darts-finish form { margin: 0; }

/* Larger throw line (team + number), smaller/greyer recorder + time (issue #91). */
.darts-act-line { display: flex; flex-direction: column; gap: 1px; }
.darts-act-main { font-size: 1.05rem; }
.darts-act-num { font-weight: 700; color: var(--accent); }
.darts-act-meta { font-size: 0.75rem; color: color-mix(in srgb, var(--muted) 80%, transparent); }
.darts-turn-elapsed { display: block; margin-top: 2px; font-size: 0.68rem; color: var(--muted); font-variant-numeric: tabular-nums; }

/* Individual player turn tracking in the team header (issue #91). */
.darts-up-player { display: inline-block; font-weight: 800; font-size: 1.15rem; color: var(--ink); }
.darts-roster { display: block; margin-top: 2px; font-size: 0.78rem; color: var(--muted); }
.darts-roster[hidden] { display: none; }
.darts-roster b { color: var(--accent); }
.darts-turn-controls { display: flex; gap: 8px; align-items: stretch; margin-top: 12px; }
.darts-backturn { white-space: nowrap; }

/* Volleyball (issue #121). Rally scoring: the two team panels ARE the input —
   tap the side that won the rally. Reuses the darts modal/activity styles. */
.vb-board { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.vb-panel {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    padding: 18px 10px 14px;
    border: 1px solid var(--line);
    border-radius: 14px;
    background: var(--surface);
    text-align: center;
    font: inherit;
    color: inherit;
}
.vb-panel.is-tappable {
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease;
}
.vb-panel.is-tappable:hover,
.vb-panel.is-tappable:focus-visible {
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    border-color: color-mix(in srgb, var(--accent) 45%, transparent);
    outline: none;
}
.vb-panel.is-tappable:active {
    background: color-mix(in srgb, var(--accent) 22%, transparent);
}
.vb-panel.is-winner {
    border-color: color-mix(in srgb, #f0ad4e 55%, transparent);
    background: color-mix(in srgb, #f0ad4e 12%, transparent);
}
.vb-team-name { font-weight: 800; font-size: 1.15rem; color: var(--ink); }
.vb-roster { font-size: 0.78rem; color: var(--muted); }
.vb-sets { font-size: 0.9rem; color: var(--accent); letter-spacing: 0.15em; }
.vb-sets-n { color: var(--muted); font-size: 0.78rem; letter-spacing: normal; }
.vb-score {
    font-size: clamp(3rem, 14vw, 5rem);
    font-weight: 800;
    line-height: 1;
    color: var(--accent);
    font-variant-numeric: tabular-nums;
}
.vb-serve { font-size: 0.9rem; font-weight: 700; color: var(--ink); }
.vb-serve[hidden] { display: none; }
.vb-point-badge {
    display: inline-block;
    padding: 2px 10px;
    border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 18%, transparent);
    color: var(--accent);
    font-size: 0.75rem;
    font-weight: 800;
    letter-spacing: 0.06em;
}
.vb-point-badge.is-match {
    background: color-mix(in srgb, #f0ad4e 25%, transparent);
    color: #b8860b;
}
.vb-badge-slot { min-height: 1.3rem; }
.vb-winner-badge[hidden] { display: none; }
.vb-tap-hint { font-size: 0.7rem; color: color-mix(in srgb, var(--muted) 70%, transparent); text-transform: uppercase; letter-spacing: 0.08em; }
.vb-sets-strip { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; margin-top: 12px; }
.vb-set-chip {
    padding: 4px 12px;
    border-radius: 999px;
    border: 1px solid var(--line);
    font-size: 0.85rem;
    color: var(--muted);
    font-variant-numeric: tabular-nums;
}
.vb-set-chip b { color: var(--ink); }
.vb-set-chip.is-live {
    border-color: color-mix(in srgb, var(--accent) 45%, transparent);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    color: var(--ink);
}

/* Game-start team/player picker (issue #89 rework). One big tap per player
   both marks them playing and picks their side — no separate checkbox plus
   a team dropdown. Mirrors the darts/volleyball tap-target sizing. */
.gs-team-names {
    display: flex;
    flex-wrap: wrap;
    align-items: flex-end;
    gap: 12px;
}
.gs-team-name-label {
    display: flex;
    flex-direction: column;
    gap: 4px;
    font-size: 0.85rem;
}
.gs-team-name-label[hidden] { display: none; }
.gs-team-name-label input { min-height: 40px; }
.gs-add-team { align-self: flex-start; margin-top: 4px; }

.gs-players legend { margin-bottom: 6px; }
.gs-player-row {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 10px;
    padding: 12px 0;
    border-top: 1px solid var(--line);
}
.gs-player-row:first-child { border-top: none; }
.gs-player-name {
    flex: 1 1 110px;
    font-weight: 700;
}
.gs-team-pills {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
}
.gs-team-pill {
    min-height: 44px;
    padding: 10px 18px;
    border: 1px solid var(--line);
    border-radius: 999px;
    background: var(--surface);
    color: var(--ink);
    font: inherit;
    font-weight: 700;
    cursor: pointer;
    transition: background-color 0.12s ease, border-color 0.12s ease, color 0.12s ease;
}
.gs-team-pill[hidden] { display: none; }
.gs-team-pill:hover,
.gs-team-pill:focus-visible {
    border-color: color-mix(in srgb, var(--accent) 55%, transparent);
    outline: none;
}
.gs-team-pill.is-active {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--accent-ink);
}
.gs-play-pill { min-width: 7rem; }

/* Cornhole (issue #93). Round entry: 0-4 bag pills per team + cancellation
   preview. Team panels/modals reuse the volleyball/darts styles. */
.ch-target { font-size: 0.85rem; }
.ch-entry-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 560px) { .ch-entry-grid { grid-template-columns: 1fr; } }
.ch-entry-team { border: 1px solid var(--line); border-radius: 12px; padding: 10px 12px; }
.ch-entry-team legend { font-weight: 800; padding: 0 6px; }
.ch-bag-row { display: flex; flex-direction: column; gap: 6px; margin: 8px 0; }
.ch-bag-label { font-size: 0.85rem; font-weight: 700; }
.ch-bag-pills { display: flex; flex-wrap: wrap; gap: 6px; }
.ch-bag-pill { min-width: 44px; padding: 10px 0; }
.ch-bag-error { margin: 4px 0 0; }
.ch-preview {
    margin: 12px 0;
    padding: 10px 14px;
    border-radius: 10px;
    background: color-mix(in srgb, var(--accent) 10%, transparent);
    border: 1px solid color-mix(in srgb, var(--accent) 30%, transparent);
    font-weight: 700;
    text-align: center;
}
.ch-submit { width: 100%; min-height: 48px; font-size: 1.05rem; }
.ch-net { font-weight: 700; color: var(--accent); }

/* Dashboard: latest gallery photo card (issue #119). */
.dash-photo-link { display: block; border-radius: 12px; overflow: hidden; }
.dash-photo { display: block; width: 100%; max-height: 340px; object-fit: cover; }
.dash-photo-hint { margin: 8px 0 0; font-size: 0.85rem; }

/* Trivial Pursuit board (issue #131). Panels reuse the .vb-panel shell; what
   is specific here is the six-wedge pip strip, the "up now" highlight, and the
   category buttons in the wedge colours. */
.tp-panel.is-up {
    border-color: color-mix(in srgb, var(--accent) 55%, transparent);
    background: color-mix(in srgb, var(--accent) 10%, transparent);
}
.tp-of { font-size: 0.35em; color: var(--muted); font-weight: 700; }
.tp-wedges { display: flex; gap: 6px; margin: 4px 0 2px; }
.tp-wedge {
    width: 16px;
    height: 16px;
    border-radius: 50%;
    border: 2px solid var(--line);
    background: transparent;
    opacity: 0.45;
}
.tp-wedge.is-held { opacity: 1; border-color: transparent; }
/* The six classic wedge colours; unheld wedges show only the outline. */
.tp-wedge-geography.is-held { background: #2f6fbf; }
.tp-wedge-entertainment.is-held { background: #d1478f; }
.tp-wedge-history.is-held { background: #d8b400; }
.tp-wedge-arts.is-held { background: #8a5a3b; }
.tp-wedge-science.is-held { background: #2e8b57; }
.tp-wedge-sports.is-held { background: #e07b28; }
.tp-up-badge { background: color-mix(in srgb, var(--accent) 20%, transparent); }
.tp-centre-badge { background: color-mix(in srgb, #f0ad4e 25%, transparent); }
.tp-categories { display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px; margin: 12px 0; }
@media (max-width: 480px) { .tp-categories { grid-template-columns: 1fr; } }
.tp-category { min-height: 52px; font-size: 1rem; border-left: 8px solid transparent; }
.tp-category.tp-wedge-geography { border-left-color: #2f6fbf; }
.tp-category.tp-wedge-entertainment { border-left-color: #d1478f; }
.tp-category.tp-wedge-history { border-left-color: #d8b400; }
.tp-category.tp-wedge-arts { border-left-color: #8a5a3b; }
.tp-category.tp-wedge-science { border-left-color: #2e8b57; }
.tp-category.tp-wedge-sports { border-left-color: #e07b28; }
.tp-centre-wrap { display: flex; flex-direction: column; gap: 8px; margin: 12px 0; }
.tp-centre { min-height: 52px; }
.tp-act-correct { color: #2e8b57; font-weight: 700; }
.tp-act-miss { color: var(--muted); font-weight: 700; }

/* --- Hell (issue #94) ------------------------------------------------------
   All-play card scoring. Reuses the darts modal/activity styles (.darts-modal,
   .darts-activity, .darts-turn-group) and adds the suite's first numeric
   keypad — deliberately large, because scores are punched in one-handed at a
   table rather than typed. */
.hell-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; flex-wrap: wrap; }
/* The round counter is the visual confirmation that the automatic advance
   happened, so it is large and it flashes on change (#94 feedback). */
.hell-round-badge { font-size: 1.05rem; margin: 0; }
.hell-round-badge strong { font-size: 2rem; font-weight: 800; font-variant-numeric: tabular-nums; margin-left: 4px; }
.hell-round-badge.is-advanced { animation: hell-advance 0.9s ease; }
@keyframes hell-advance {
    0% { color: var(--accent); transform: scale(1.18); }
    60% { color: var(--accent); transform: scale(1); }
    100% { color: inherit; transform: scale(1); }
}
/* States plainly how many scores are outstanding, so the automatic advance is
   predictable rather than surprising. */
.hell-awaiting { margin: 0; font-size: 0.9rem; color: var(--muted); max-width: 26rem; }
.hell-awaiting.is-warning { color: #b9540b; font-weight: 700; }
/* "Nobody went out": reviewing is the prominent action, saving the odd round
   the quiet one, so the buttons are deliberately not equal weight. */
.hell-review-list { font-size: 0.88rem; margin: 8px 0 0; }
.hell-review-actions { flex-wrap: wrap; }
.hell-board { margin-top: 10px; }
.hell-row { display: flex; align-items: center; gap: 12px; padding: 10px 0; border-bottom: 1px solid var(--line); }
.hell-row:last-child { border-bottom: 0; }
.hell-who { display: flex; flex-direction: column; flex: 1 1 auto; min-width: 0; }
.hell-name { font-weight: 700; }
.hell-meta { font-size: 0.82rem; }
.hell-total { font-size: 1.6rem; font-weight: 800; font-variant-numeric: tabular-nums; min-width: 3.2rem; text-align: right; }
.hell-row.is-out { opacity: 0.55; }
.hell-row.is-done .hell-total { color: var(--accent); }
.hell-enter { min-height: 44px; white-space: nowrap; }
.hell-round-controls { margin-top: 14px; display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }
.hell-add summary { cursor: pointer; min-height: 44px; display: flex; align-items: center; }
.hell-add form { display: flex; gap: 8px; margin-top: 8px; flex-wrap: wrap; }
.hell-help { margin-top: 10px; font-size: 0.86rem; }
.hell-standings li { display: flex; align-items: center; gap: 10px; padding: 6px 0; }
.hell-rank { font-weight: 800; color: var(--muted); min-width: 1.5rem; }
.hell-standings .hell-name { flex: 1 1 auto; }
.hell-standings .hell-total { font-size: 1.15rem; }
.hell-act-line { display: block; padding: 3px 0; font-size: 0.92rem; }

/* The keypad overlay. */
.hell-pad { position: fixed; inset: 0; z-index: 60; display: flex; align-items: center; justify-content: center;
    background: color-mix(in srgb, #000 55%, transparent); padding: 16px; }
.hell-pad[hidden] { display: none; }
.hell-pad-inner { background: var(--surface); border-radius: 14px; padding: 18px; width: min(420px, 100%);
    max-height: 100%; overflow-y: auto; box-shadow: 0 18px 50px rgba(0, 0, 0, 0.35); }
/* Entry-mode switch: pile+out vs. a straight score (#143). */
.hell-modes { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin: 12px 0 0;
    padding: 4px; border: 1px solid var(--line); border-radius: 10px; }
.hell-mode { min-height: 40px; font-size: 0.95rem; font-weight: 700; border: 0; border-radius: 7px;
    background: transparent; color: var(--muted); cursor: pointer; }
.hell-mode.is-active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: inherit; }
.hell-mode-note { font-size: 0.82rem; text-align: center; margin: -6px 0 10px; }
.hell-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin: 12px 0 6px; }
/* `display: grid` above would beat the hidden attribute's UA rule, so the
   inactive mode's field group needs saying explicitly. */
.hell-fields[hidden], .hell-mode-note[hidden] { display: none; }
.hell-field { display: flex; flex-direction: column; gap: 2px; padding: 10px; min-height: 64px;
    border: 2px solid var(--line); border-radius: 10px; background: transparent; color: inherit; cursor: pointer; }
/* The sign key is a control, not a value: quieter, and never "active". */
.hell-sign { align-items: center; justify-content: center; border-style: dashed; }
.hell-sign .hell-field-value { font-size: 1.8rem; color: var(--muted); }
/* "Went hell" — score mode's stand-in for a reported pile of 0 (#143). */
.hell-wenthell { display: flex; align-items: center; gap: 10px; width: 100%; min-height: 48px;
    margin: 4px 0 2px; padding: 8px 12px; text-align: left; font-size: 0.95rem; font-weight: 700;
    border: 2px solid var(--line); border-radius: 10px; background: transparent; color: inherit; cursor: pointer; }
.hell-wenthell[hidden] { display: none; }
.hell-wenthell-box { flex: 0 0 auto; width: 26px; height: 26px; border: 2px solid var(--line);
    border-radius: 6px; display: flex; align-items: center; justify-content: center;
    font-size: 1rem; color: transparent; }
.hell-wenthell.is-on { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 12%, transparent); }
.hell-wenthell.is-on .hell-wenthell-box { border-color: var(--accent); color: var(--accent); }
.hell-field.is-active { border-color: var(--accent); background: color-mix(in srgb, var(--accent) 10%, transparent); }
.hell-field-label { font-size: 0.78rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
.hell-field-value { font-size: 2.1rem; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
/* A digit that would exceed 13 / 52 is refused outright, with a nudge. */
.hell-field-value.is-refused { animation: hell-refuse 0.22s ease; color: #c0392b; }
@keyframes hell-refuse { 0%, 100% { transform: translateX(0); } 25% { transform: translateX(-5px); } 75% { transform: translateX(5px); } }
.hell-math { text-align: center; font-size: 1.15rem; font-weight: 700; font-variant-numeric: tabular-nums; margin: 8px 0 12px; }
.hell-keys { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.hell-key { min-height: 60px; font-size: 1.7rem; font-weight: 700; font-variant-numeric: tabular-nums;
    border: 1px solid var(--line); border-radius: 10px; background: var(--surface); color: inherit; cursor: pointer; }
.hell-key:active { background: color-mix(in srgb, var(--accent) 18%, transparent); }
.hell-key-fn { font-size: 1.3rem; color: var(--muted); }
/* Whose score this is. The pad reopens on player after player under
   "Save & Next", so the name is the anchor and is sized like one (#143). */
.hell-pad-name { font-size: clamp(1.9rem, 7vw, 2.6rem); line-height: 1.1;
    margin: 0 0 4px; color: var(--accent); overflow-wrap: anywhere; }
.hell-pad .darts-modal-actions { margin-top: 14px; }
/* Pressed once per player, so it gets its own full-width row and the solid
   treatment; Save stays for the one-off correction (#143). */
.hell-save-next { flex: 1 1 100%; min-height: 52px; font-size: 1.1rem; }
.hell-save-next[hidden] { display: none; }
/* Visually hidden, still announced. The class was already used on the Hell
   screen (the "Player joining" label, #94) but never actually defined, so it
   was rendering as visible text; the scoreboard's table captions need it to
   work, so it is defined here (#147). */
.sr-only {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}

/* The traditional scoreboard (#147): players as columns, rounds as rows. */
.hell-views { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin: 12px 0 4px;
    padding: 4px; border: 1px solid var(--line); border-radius: 10px; max-width: 22rem; }
.hell-view { min-height: 40px; font-size: 0.95rem; font-weight: 700; border: 0; border-radius: 7px;
    background: transparent; color: var(--muted); cursor: pointer; }
.hell-view.is-active { background: color-mix(in srgb, var(--accent) 16%, transparent); color: inherit; }
.hell-sb-wrap[hidden], .hell-board[hidden], .hell-round-controls[hidden], .hell-help[hidden] { display: none; }
/* Players x rounds gets wide fast, so the table scrolls inside its own box —
   the page body must never scroll sideways. */
.hell-sb-scroll { overflow-x: auto; margin-top: 10px; }
.hell-sb { border-collapse: separate; border-spacing: 0; width: auto; min-width: 100%; }
.hell-sb th, .hell-sb td { padding: 6px 10px; border-bottom: 1px solid var(--line); text-align: right;
    white-space: nowrap; vertical-align: top; }
/* The names header and the round column both stay put: a scoreboard you
   cannot match a number to a name in is useless. */
.hell-sb thead th { position: sticky; top: 0; z-index: 2; background: var(--surface);
    font-size: 0.86rem; color: var(--muted); }
.hell-sb-round, .hell-sb-corner { position: sticky; left: 0; z-index: 1; background: var(--surface);
    text-align: left; font-size: 0.86rem; color: var(--muted); }
.hell-sb-corner { z-index: 3; }
.hell-sb-who { font-weight: 800; color: var(--ink); }
.hell-sb-won { margin-left: 4px; color: var(--accent); }
.hell-sb-cell { font-variant-numeric: tabular-nums; }
/* The running total is the number people read, so it is the large one. */
.hell-sb-total { display: block; font-size: 1.25rem; font-weight: 800; line-height: 1.15; }
.hell-sb-note { display: block; font-size: 0.76rem; color: var(--muted); line-height: 1.3; }
/* Sign and colour both carry the meaning, so it survives without colour. */
.hell-sb-delta.is-up { color: #15803d; font-weight: 700; }
.hell-sb-delta.is-down { color: #b91c1c; font-weight: 700; }
.hell-sb-delta.is-flat { color: var(--muted); }
.hell-sb-rescue { color: var(--accent); }
.hell-sb-cell.is-absent .hell-sb-total { color: var(--muted); font-weight: 600; }
.hell-sb tfoot .hell-sb-final { border-top: 2px solid var(--line); }
.hell-sb tfoot .hell-sb-total { color: var(--accent); }
.hell-sb-empty { text-align: left; color: var(--muted); }

/* Correcting an already-played round (#146). Loud on purpose: writing to
   round 3 while the game is on round 7 must not be inferable only from a
   small number in the eyebrow. */
.hell-pad-past { margin: 0 0 10px; padding: 8px 10px; border-radius: 8px;
    background: color-mix(in srgb, var(--warn) 14%, transparent);
    border: 1px solid color-mix(in srgb, var(--warn) 45%, transparent);
    color: var(--warn); font-size: 0.88rem; font-weight: 700; }
.hell-pad-past[hidden] { display: none; }
.hell-pad.is-editing-past .hell-pad-inner { border-top: 4px solid var(--warn); }
@media (max-width: 380px) { .hell-key { min-height: 52px; font-size: 1.45rem; } }

/* Round history. Deliberately NOT .darts-turn-group — that is a two-column
   grid (narrow "Turn N" gutter + throws), which scattered Hell's per-player
   rows between the two columns on the first staging build. */
.hell-rounds { display: flex; flex-direction: column; gap: 4px; }
.hell-rd-group { padding: 12px 0; border-top: 2px solid var(--line); }
.hell-rd-group:first-child { border-top: none; }
.hell-rd-head { margin: 0 0 8px; font-size: 0.95rem; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.hell-rd-won { font-size: 0.82rem; font-weight: 500; color: var(--muted); }
.hell-rd-list { list-style: none; margin: 0; padding: 0; }
.hell-rd-row { display: grid; grid-template-columns: minmax(6rem, 1fr) auto; gap: 2px 12px; align-items: baseline; padding: 6px 0; border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent); }
.hell-rd-row:last-child { border-bottom: 0; }
.hell-rd-name { font-weight: 700; }
.hell-rd-detail { grid-column: 1; font-size: 0.82rem; }
.hell-rd-score { grid-column: 2; grid-row: 1 / span 2; text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.hell-rd-score strong { font-size: 1.15rem; }
.hell-rd-row.is-absent .hell-rd-name { font-weight: 500; color: var(--muted); }
/* A correctable row (#146): the button becomes the grid, because the layout
   above is a grid over the three spans and wrapping them would otherwise
   collapse it into a single cell. The <li> keeps only the divider. */
.hell-rd-row.is-editable { display: block; padding: 0; }
.hell-rd-edit { display: grid; grid-template-columns: minmax(6rem, 1fr) auto; gap: 2px 12px;
    align-items: baseline; width: 100%; min-height: 44px; padding: 8px 4px; text-align: left;
    background: transparent; border: 0; border-radius: 6px; color: inherit; font: inherit; cursor: pointer; }
.hell-rd-edit:hover, .hell-rd-edit:focus-visible {
    background: color-mix(in srgb, var(--accent) 9%, transparent); outline: none; }
.hell-rd-rescue { margin-left: 4px; background: color-mix(in srgb, #f0ad4e 28%, transparent); }

/* 8-Ball Pool (issue #92). Pool records one verdict per rack rather than a
   running score, so its screen is a result form: the two side panels are the
   first step (taller than volleyball's, since they carry no score), the
   optional details the second. .pool-verdict is the locked result. */
.vb-panel[data-pool-pick] { padding: 28px 10px 24px; gap: 6px; }
.pool-verdict h2 { margin: 2px 0 10px; font-size: 1.5rem; }
.pool-verdict-detail { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; margin: 0 0 10px; }
.pool-standings { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.pool-standings th, .pool-standings td { padding: 7px 8px; text-align: right; border-bottom: 1px solid color-mix(in srgb, var(--line) 55%, transparent); }
.pool-standings th:nth-child(2), .pool-standings td:nth-child(2) { text-align: left; width: 100%; }
.pool-standings tr:last-child td { border-bottom: 0; }
.pool-standings .pool-rank { color: var(--muted); font-size: 0.85rem; }
.pool-standings .pool-name { font-weight: 700; }

/* --- Lazy bracket (issue #90) ---------------------------------------------
   A suggestion, not a ranking: who is level with whom and therefore due a
   game. No score anywhere — the maintainer rejected a rating system outright.
   Read on a phone at a pool table, so everything here is sized for thumbs. */
.bracket-suggestion { font-size: clamp(1.3rem, 6vw, 1.7rem); font-weight: 700; margin: 6px 0 4px; line-height: 1.25; }

/* An always-open card, not a disclosure (#151) — so no toggle row, no caret,
   and no [open] state. The level blocks and player pills below are unchanged. */
.bracket-ladder-count { font-size: 0.85rem; margin: -6px 0 0; }

/* One block per level, never a comma-separated run-on line. */
.bracket-levels { display: flex; flex-direction: column; gap: 10px; padding: 4px 0 8px; }
.bracket-level { display: grid; grid-template-columns: 3.6rem 1fr; gap: 10px; align-items: start;
    padding: 10px 0; border-top: 1px solid color-mix(in srgb, var(--line) 55%, transparent); }
.bracket-level:first-child { border-top: 0; }
.bracket-level-head { margin: 0; display: flex; flex-direction: column; align-items: center; line-height: 1.05; }
.bracket-level-head strong { font-size: 1.6rem; font-variant-numeric: tabular-nums; }
.bracket-level-head span { font-size: 0.72rem; color: var(--muted); text-transform: uppercase; letter-spacing: 0.04em; }
/* Names wrap as pills rather than running off the edge of a phone. */
.bracket-level-players { display: flex; flex-wrap: wrap; gap: 8px; }
.bracket-player {
    display: inline-flex; flex-direction: column; justify-content: center;
    min-height: 44px; padding: 6px 12px; border: 1px solid var(--line); border-radius: 999px;
    background: color-mix(in srgb, var(--accent) 7%, transparent); font-weight: 600; line-height: 1.15;
}
.bracket-player small { font-weight: 400; font-size: 0.72rem; color: var(--muted); }
.bracket-ladder-note { font-size: 0.85rem; padding-bottom: 8px; }
@media (max-width: 380px) {
    .bracket-level { grid-template-columns: 2.9rem 1fr; gap: 8px; }
    .bracket-player { padding: 6px 10px; }
}

/* Dashboard games group (#118, spec 4.f.3) — live boards leading the activity
   feed. The boards are shrunken read-only copies of the real scoring screens:
   several sit side by side on one row, and nothing in them is interactive. */
.dash-games {
    margin: 12px 0 4px;
}

.dash-games-head {
    font-size: 0.72rem;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--muted);
    margin: 0 0 8px;
}

/* Auto-fit means one board goes full width on a phone, and three or four share
   a row on anything wider, without a media query per game. */
.dash-boards {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(148px, 1fr));
    gap: 8px;
}

.dash-board {
    display: block;
    padding: 8px 10px;
    border: 1px solid var(--line);
    border-radius: 10px;
    color: inherit;
    text-decoration: none;
    background: color-mix(in srgb, var(--line) 14%, transparent);
    /* Nothing inside a board may paint outside it. A board with more columns
       than fit used to render its last values on top of the neighbouring
       card (issue #149); this is the backstop that makes that impossible at
       any player count, independent of the sizing fixes below. */
    overflow: hidden;
}

/* Hell is the only ALL-PLAY game: one column per player where every other
   game has two, so it takes the full width of the grid rather than a cell
   sized for a two-team board (issue #149). */
.dash-board[data-game="hell"] {
    grid-column: 1 / -1;
}

.dash-board:hover {
    border-color: var(--accent);
}

.dash-board-head {
    display: flex;
    align-items: center;
    gap: 6px;
    margin-bottom: 6px;
}

.dash-board-icon {
    font-size: 0.95rem;
}

.dash-board-name {
    font-weight: 600;
    font-size: 0.82rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dash-board-grid {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.75rem;
    line-height: 1.35;
    font-variant-numeric: tabular-nums;
    /* Fixed layout shares the card's width between the columns instead of
       letting their content decide. Without it, enough columns push the
       table's intrinsic width past the card and it overflows (issue #149). */
    table-layout: fixed;
}

.dash-board-grid th,
.dash-board-grid td {
    padding: 0 2px;
    text-align: center;
    font-weight: 400;
    /* Ellipsis rather than overflow, now that fixed layout can hand a column
       less room than its content wants. */
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dash-board-grid thead th {
    font-size: 0.68rem;
    color: var(--muted);
    font-weight: 600;
    overflow: hidden;
    text-overflow: ellipsis;
    max-width: 72px;
}

/* The row label column (targets, sets, categories) stays narrow and quiet. */
.dash-board-grid tbody th,
.dash-board-grid tfoot th {
    text-align: left;
    color: var(--muted);
    font-size: 0.68rem;
    width: 2.6em;
}

.dash-board-grid tfoot th,
.dash-board-grid tfoot td {
    border-top: 1px solid var(--line);
    padding-top: 2px;
    font-weight: 700;
}

.dash-board-flag {
    display: block;
    font-size: 0.6rem;
    font-weight: 400;
    color: var(--accent);
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.dash-board-meta,
.dash-board-players {
    margin: 6px 0 0;
    font-size: 0.72rem;
    color: var(--muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.dash-board-players {
    color: inherit;
    font-weight: 600;
    font-size: 0.8rem;
}

.dash-games-recent {
    list-style: none;
    margin: 8px 0 0;
    padding: 0;
    display: grid;
    gap: 4px;
}

.dash-games-recent li {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 6px 10px;
    border-radius: 8px;
    font-size: 0.9rem;
    /* See .feed-list li — same defect, same fix (issue #150). This is the row
       that actually shipped it: an 8-player Hell result is one ~200-character
       no-wrap line. */
    min-width: 0;
}

.dash-games-recent .feed-icon {
    width: 26px;
    height: 26px;
    font-size: 0.85rem;
}
