html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

h1:focus {
    outline: none;
}

a, .btn-link {
    color: #0071c1;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
  box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid red;
}

.validation-message {
    color: red;
}

#blazor-error-ui {
    color-scheme: light only;
    background: lightyellow;
    bottom: 0;
    box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.2);
    box-sizing: border-box;
    display: none;
    left: 0;
    padding: 0.6rem 1.25rem 0.7rem 1.25rem;
    position: fixed;
    width: 100%;
    z-index: 1000;
}

    #blazor-error-ui .dismiss {
        cursor: pointer;
        position: absolute;
        right: 0.75rem;
        top: 0.5rem;
    }

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

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

.loading-progress {
    position: absolute;
    display: block;
    width: 8rem;
    height: 8rem;
    inset: 20vh 0 auto 0;
    margin: 0 auto 0 auto;
}

    .loading-progress circle {
        fill: none;
        stroke: #e0e0e0;
        stroke-width: 0.6rem;
        transform-origin: 50% 50%;
        transform: rotate(-90deg);
    }

        .loading-progress circle:last-child {
            stroke: #1b6ec2;
            stroke-dasharray: calc(3.141 * var(--blazor-load-percentage, 0%) * 0.8), 500%;
            transition: stroke-dasharray 0.05s ease-in-out;
        }

.loading-progress-text {
    position: absolute;
    text-align: center;
    font-weight: bold;
    inset: calc(20vh + 3.25rem) 0 auto 0.2rem;
}

    .loading-progress-text:after {
        content: var(--blazor-load-percentage-text, "Loading");
    }

code {
    color: #c02d76;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}

/* ── Kiosk rotation container & corner logo ──────────────────────────────── */

.kiosk-rotation-container {
    position: relative;
}

/* Config-driven orientation overrides: these take precedence over @media queries
   so the admin-configured orientation is authoritative for paired devices.
   Standalone pages (no .kiosk-rotation-container) fall back to viewport media queries. */
.kiosk-rotation-container .kiosk-promo-levels {
    grid-template-columns: 1fr 1fr;
    column-gap: 3rem;
}
.kiosk-rotation-container.kiosk-portrait .kiosk-promo-levels {
    grid-template-columns: 1fr;
    column-gap: 0;
}

.kiosk-rotation-container .kiosk-promo-tiers {
    grid-template-columns: 1fr 1fr;
    column-gap: 3rem;
}
.kiosk-rotation-container.kiosk-portrait .kiosk-promo-tiers {
    grid-template-columns: 1fr;
    column-gap: 0;
}

.kiosk-rotation-container .kiosk-promo-value-hero .kiosk-hero-amount,
.kiosk-rotation-container .kiosk-promo-value-hero .kiosk-hero-time {
    font-size: 12vw;
}
.kiosk-rotation-container.kiosk-portrait .kiosk-promo-value-hero .kiosk-hero-amount,
.kiosk-rotation-container.kiosk-portrait .kiosk-promo-value-hero .kiosk-hero-time {
    font-size: 16vw;
}

/* ── Kiosk Waitlist Board ─────────────────────────────────────────────────── */

.kiosk-waitlist-header-logo {
    height: 2em;
    max-width: 40%;
    object-fit: contain;
    flex-shrink: 0;
}

.kiosk-board {
    display: flex;
    flex-wrap: nowrap;
    height: calc(100vh - var(--kiosk-chrome));
    overflow: hidden;
}

.kiosk-board-column {
    flex: 1;
    min-width: 0;
    display: flex;
    flex-direction: column;
    border-right: 1px solid var(--mud-palette-lines-default);
    overflow: hidden;
}

.kiosk-board-column:last-child {
    border-right: none;
}

.kiosk-board-scroll {
    flex: 1;
    overflow-y: auto;
    min-height: 0;
}

.kiosk-board-table td,
.kiosk-board-table th {
    font-size: 1.05em;
    padding-top: 0.6em;
    padding-bottom: 0.6em;
}

.kiosk-stale-row {
    opacity: 0.65;
}

.kiosk-checked-in {
    color: var(--mud-palette-success);
    white-space: nowrap;
}

.kiosk-not-checked-in {
    color: var(--mud-palette-text-secondary);
    white-space: nowrap;
}

.kiosk-board-center {
    display: flex;
    align-items: center;
    justify-content: center;
    height: calc(100vh - var(--kiosk-chrome));
}

.kiosk-board-center-column {
    flex-direction: column;
    gap: 0.5em;
}

/* Fit-to-fill: waitlist board scales to fill available space without clipping.
   --kiosk-rows (longest column entry count + header), --kiosk-cols,
   --kiosk-name-chars, --kiosk-status-chars, and --kiosk-header-chars are
   emitted by Blazor on the board wrapper. Takes the tighter of vertical and
   horizontal fit, saturates at the fit point. The horizontal divisor uses the
   wider of row width — player name plus the check-in Status column, at 1.05em
   body — and header-title width (at 1.25em h6). */
.kiosk-rotation-container .kiosk-board {
    font-size: max(1.05rem, calc(
        min(
            (100vh - var(--kiosk-chrome)) / (5 + var(--kiosk-rows, 1) * 2.4),
            100vw / var(--kiosk-cols, 1) / (4 + max((var(--kiosk-name-chars, 12) + var(--kiosk-status-chars, 0)) * 0.6, var(--kiosk-header-chars, 12) * 0.75))
        )
    ));
}

/* ── Kiosk promo board (dark treatment) ─────────────────────────────────── */

.kiosk-promo-dark {
    background: #121212;
    color: #f5f5f5;
    min-height: calc(100vh - var(--kiosk-chrome));
}

/* ADR-0188: logo band on top, title band under it. The two never share a line, so
   a headline long enough to fill the board's width cannot ride over the mark. */
.kiosk-promo-header {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 1.5em 1em 0.5em;
}

.kiosk-header-banner {
    display: flex;
    justify-content: center;
    align-items: center;
    width: 100%;
    /* In title units, not em, so the gap tracks the operator's text size rather than
       the ladder's fit-to-fill root — and stays the constant the fit below reserves. */
    margin-bottom: calc(var(--kiosk-title-size, 2.125rem) * 0.25);
}

.kiosk-header-logo {
    /* ADR-0186: keyed to the title, not the ladder root — a 20-tier board would
       otherwise pair a 60px logo with a 120px headline. 1.23 preserves the ratio the
       old 2.62em-of-root sizing produced against a 2.125em-of-root title.

       ADR-0188: the banner is the full board width, so the title-keyed width cap
       ADR-0187 added is gone — height is the only binding constraint and a wide mark
       runs as wide as it needs instead of letterboxing. 100% keeps it inside the board. */
    height: calc(var(--kiosk-title-size, 2.125rem) * 1.23);
    max-width: 100%;
    object-fit: contain;
}

.kiosk-promo-title {
    color: #f5f5f5 !important;
    font-weight: 700;
    /* ADR-0186: an absolute size the operator sets, not derived from the board's
       fit-to-fill root. The board picks name vs headline via --kiosk-title-size.
       !important beats MudBlazor's own .mud-typography-h4. */
    font-size: var(--kiosk-title-size, 2.125rem) !important;
}

.kiosk-promo-levels {
    display: grid;
    gap: 0;
    padding: 0.5em 2em 2em;
}

@media (orientation: landscape) {
    .kiosk-promo-levels {
        grid-template-columns: 1fr 1fr;
        column-gap: 3rem;
    }
}

@media (orientation: portrait) {
    .kiosk-promo-levels {
        grid-template-columns: 1fr;
    }
}

.kiosk-promo-level-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 0.5em 0.75em;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    font-size: 1.4em;
}

.kiosk-promo-level-time {
    font-weight: 500;
}

.kiosk-promo-level-value {
    font-weight: 700;
    font-size: 1.07em;
}

/* ── Kiosk promo board – Progressive tier ladder ─────────────────────────── */

.kiosk-promo-tiers {
    display: grid;
    gap: 0;
    padding: 0.5em 2em 2em;
}

@media (orientation: landscape) {
    .kiosk-promo-tiers {
        grid-template-columns: 1fr 1fr;
        column-gap: 3rem;
    }
}

@media (orientation: portrait) {
    .kiosk-promo-tiers {
        grid-template-columns: 1fr;
    }
}

.kiosk-promo-tier-row {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    padding: 0.5em 0.75em;
    border-bottom: 1px solid rgba(255,255,255,0.08);
    font-size: 1.4em;
}

.kiosk-promo-tier-position {
    font-weight: 500;
}

.kiosk-promo-tier-value {
    font-weight: 700;
    font-size: 1.07em;
}

.kiosk-row-past {
    opacity: 0.4;
    text-decoration: line-through;
}

.kiosk-row-next {
    font-weight: 700;
    border: 2px solid var(--cm-promo-highlight, var(--mud-palette-primary));
    border-radius: 6px;
    background: rgba(255,255,255,0.05);
}

.kiosk-promo-value-hero {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    flex: 1;
    padding: 2rem;
}

.kiosk-promo-value-hero .kiosk-hero-amount {
    font-weight: 800;
    line-height: 1;
    color: var(--cm-promo-highlight, var(--mud-palette-primary));
}

.kiosk-promo-value-hero .kiosk-hero-basis {
    font-size: 2em;
    font-weight: 500;
    opacity: 0.7;
    margin-top: 0.5rem;
}

/* The Current Level Board's draw time: read at the same weight as the dollar amount
   beside it, not as a dimmed caption. Shares the amount's font-size rule below
   rather than kiosk-hero-basis, which is sized and margined for a caption
   underneath the amount. */
.kiosk-promo-value-hero .kiosk-hero-time {
    font-weight: 500;
}

@media (orientation: landscape) {
    .kiosk-promo-value-hero .kiosk-hero-amount,
    .kiosk-promo-value-hero .kiosk-hero-time {
        font-size: 12vw;
    }
}

@media (orientation: portrait) {
    .kiosk-promo-value-hero .kiosk-hero-amount,
    .kiosk-promo-value-hero .kiosk-hero-time {
        font-size: 16vw;
    }
}

/* ── Current Level Board hero (two stacked lines) ────────────────────────── */

/* The Current Level Board stacks a draw time above the amount, so its hero is two
   full-size lines where every other value board renders one. Sizing them from the
   viewport's width alone ignores the header above them — which is an absolute block
   the operator sets, up to 2.78x a 120px headline — so on a viewport that is wide
   relative to its height the pair pushed past the bottom of the board's own
   100vh box and the page's background showed through underneath it. Cap the pair at
   the height the header leaves: two line boxes at line-height 1, the hero's 2rem
   padding block, and the header's own 2rem. 2.15 leaves the glyphs a little room.
   The 1rem floor mirrors the ladder fits — a header tall enough to drive the
   remainder negative must not invalidate the whole declaration. */
.kiosk-promo-value-hero.kiosk-current-level-hero {
    --kiosk-hero-fit: max(1rem, calc(
        (100vh - var(--kiosk-chrome, var(--mud-appbar-height)) - var(--kiosk-header-block) - 6rem) / 2.15
    ));
    min-height: 0;
    overflow: hidden;
}

/* Both lines share the amount's tight line box so the fit above is exact. */
.kiosk-promo-value-hero.kiosk-current-level-hero .kiosk-hero-time {
    line-height: 1;
}

@media (orientation: landscape) {
    .kiosk-promo-value-hero.kiosk-current-level-hero .kiosk-hero-amount,
    .kiosk-promo-value-hero.kiosk-current-level-hero .kiosk-hero-time {
        font-size: min(12vw, var(--kiosk-hero-fit));
    }
}

@media (orientation: portrait) {
    .kiosk-promo-value-hero.kiosk-current-level-hero .kiosk-hero-amount,
    .kiosk-promo-value-hero.kiosk-current-level-hero .kiosk-hero-time {
        font-size: min(16vw, var(--kiosk-hero-fit));
    }
}

/* Config-driven orientation, same precedence rule as the rest of the board: the
   paired device's configured orientation beats the viewport media query. */
.kiosk-rotation-container .kiosk-promo-value-hero.kiosk-current-level-hero .kiosk-hero-amount,
.kiosk-rotation-container .kiosk-promo-value-hero.kiosk-current-level-hero .kiosk-hero-time {
    font-size: min(12vw, var(--kiosk-hero-fit));
}

.kiosk-rotation-container.kiosk-portrait .kiosk-promo-value-hero.kiosk-current-level-hero .kiosk-hero-amount,
.kiosk-rotation-container.kiosk-portrait .kiosk-promo-value-hero.kiosk-current-level-hero .kiosk-hero-time {
    font-size: min(16vw, var(--kiosk-hero-fit));
}

/* The header block the ladder fit reserves, in title units. 1.3x is the title's own
   line box; a board carrying a logo adds the banner row above it — 1.23x for the mark
   plus the 0.25x gap under it (ADR-0188). Boards with no logo reserve neither. */
.kiosk-promo-dark {
    --kiosk-header-block: calc(var(--kiosk-title-size, 2.125rem) * 1.3);
}

.kiosk-promo-dark:has(.kiosk-header-banner) {
    --kiosk-header-block: calc(var(--kiosk-title-size, 2.125rem) * 2.78);
}

/* Fit-to-fill: ladder rows take whatever height the fixed header and footer leave
   (ADR-0186). The title and footnote are absolute pixel sizes the operator sets per
   board, so they come off the top as fixed blocks — --kiosk-header-block above,
   1.5x each footnote line — instead of being folded into the divisor. What
   remains is divided by the em-relative padding still in play (2em header + 2.5em
   ladder + 2em footer when present) plus 3.1em per row.

   --kiosk-rows, --kiosk-footnote-lines, --kiosk-footnote-pad, and --kiosk-title-size
   are emitted by Blazor on the board wrapper. Standalone pages emit no rows; the
   :has() scope and rotation-container selector keep them on plain fixed sizing. */
.kiosk-rotation-container .kiosk-promo-dark:has(.kiosk-promo-tiers),
.kiosk-rotation-container .kiosk-promo-dark:has(.kiosk-promo-levels) {
    font-size: max(1.05rem, calc(
        (100vh - var(--kiosk-chrome)
            - var(--kiosk-header-block)
            - var(--kiosk-footnote-lines, 0) * var(--kiosk-footer-size, 0.875rem) * 1.5)
        / (4.5 + var(--kiosk-rows, 1) * 3.1 + var(--kiosk-footnote-pad, 0))
    ));
}

.kiosk-rotation-container .kiosk-promo-footnote {
    overflow: hidden;
}

.kiosk-promo-footnote {
    text-align: center;
    padding: 0.5em 2em 1.5em;
    opacity: 0.7;
}

/* ADR-0186: every footnote line takes the operator's Footer size. Overrides the
   Typo.body2 rule the MudText inside carries. */
.kiosk-promo-footnote .mud-typography-body2 {
    font-size: var(--kiosk-footer-size, 0.875rem);
}

/* MudBlazor Typo override: rem → em so the waitlist board's column headers inherit
   from its fit-to-fill root. The promo title and footnote no longer need this — they
   carry the operator's absolute sizes (ADR-0186). */
.kiosk-rotation-container .mud-typography-h6 {
    font-size: 1.25em;
}

/* ── Room pinned header ───────────────────────────────────────────────────── */

/* Keeps the page title, banners, action buttons, and jump-to-table pills pinned
   below the fixed app bar while the table grid scrolls beneath them. */
.room-sticky-header {
    position: sticky;
    top: var(--mud-appbar-height);
    z-index: 1000; /* above the table grid, below the app bar (1100) and dialogs */
    background-color: var(--mud-palette-background);
    padding-top: 8px;
}

/* ── Poker Table ──────────────────────────────────────────────────────────── */

.poker-table-wrapper {
    position: relative;
    width: 680px;
    height: 370px;
    margin: 0 auto;
    overflow: visible;
}

/* Horizontal racetrack (stadium): wide straights with fully-rounded ends
   (border-radius = half the height). Geometry is mirrored by SeatLayout.cs. */
.poker-table-felt {
    position: absolute;
    left: 60px;
    top: 70px;
    width: 560px;
    height: 220px;
    background: radial-gradient(ellipse at center, #2d7a2d 0%, #1a4d1a 100%);
    border-radius: 110px;
    border: 8px solid #5d3a1a;
    box-shadow: 0 4px 20px rgba(0,0,0,0.5);
    cursor: pointer;
}

.poker-dealer-marker {
    position: absolute;
    width: 80px;
    height: 80px;
    z-index: 1;
    pointer-events: none;
}

.poker-dealer-inner {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    display: flex;
    justify-content: center;
    align-items: center;
    background: #5d3a1a;
    border: 2px solid #8b6914;
    color: #f0d080;
    font-size: 11px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.5px;
    user-select: none;
}

.poker-seat {
    position: absolute;
    width: 96px;
    height: 96px;
    cursor: pointer;
    z-index: 1;
}

.poker-seat-inner {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    text-align: center;
    padding: 4px;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
    user-select: none;
}

.poker-seat.seat-empty .poker-seat-inner {
    background: var(--cm-empty-seat-bg, #BDBDBD);
    border: 2px dashed rgba(255,255,255,0.4);
    color: var(--cm-empty-seat-text, rgba(255,255,255,0.7));
}

.poker-seat.seat-occupied .poker-seat-inner {
    background: var(--cm-occupied-seat-bg, #FFFFFF);
    border: 2px solid var(--mud-palette-primary);
    color: var(--cm-occupied-seat-text, var(--mud-palette-text-primary));
    box-shadow: 0 2px 6px rgba(0,0,0,0.3);
}

.poker-seat.seat-selected .poker-seat-inner {
    background: var(--cm-occupied-seat-bg, #FFFFFF);
    border: 2px solid var(--mud-palette-primary);
    outline: 2px solid var(--mud-palette-primary);
    color: var(--cm-occupied-seat-text, var(--mud-palette-text-primary));
    box-shadow: 0 2px 8px rgba(0,0,0,0.4);
}

.poker-seat.seat-selectable:hover .poker-seat-inner {
    transform: scale(1.1);
    box-shadow: 0 3px 10px rgba(0,0,0,0.5);
}

.poker-seat-number {
    font-size: 10px;
    font-weight: bold;
    line-height: 1;
    margin-bottom: 2px;
    opacity: 0.7;
}

.cm-promo-amount {
    color: var(--cm-promo-highlight, var(--mud-palette-primary));
}

.tier-next {
    color: var(--cm-promo-highlight, var(--mud-palette-primary));
}

.poker-seat-player {
    font-size: 11px;
    font-weight: 600;
    line-height: 1.2;
    max-width: 86px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.poker-seat-membership {
    font-size: 9px;
    font-weight: 500;
    line-height: 1.1;
    margin-top: 1px;
    opacity: 0.75;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    max-width: 86px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.membership-tier-pill {
    display: inline-block;
    font-size: 8px;
    font-weight: 700;
    line-height: 1;
    padding: 2px 5px;
    border-radius: 6px;
    text-transform: uppercase;
    letter-spacing: 0.3px;
    max-width: 86px;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.poker-seat-chips {
    font-size: 10px;
    font-weight: 700;
    line-height: 1.1;
    margin-top: 2px;
}

.seat-chips-alert {
    color: var(--mud-palette-error);
}

/* --- Club Settings hours: clock dialog sizing ------------------------------
   The weekly-hours tables use narrow time-picker inputs. Setting that width on
   the MudTimePicker root also constrained its dialog-variant clock popup, so
   the clock opened very small with a horizontal scrollbar. Apply the narrow
   width to the input only, and guarantee the clock dialog renders the full
   clock face (260px) without horizontal overflow. The :has() guard scopes the
   dialog rule to time pickers (those containing a clock) so date pickers are
   unaffected. */
.club-hours-timepicker .mud-input-control {
    width: 110px;
}

.mud-picker-content:has(.mud-picker-time-clock) {
    min-width: 328px;
    overflow-x: hidden;
}

.poker-seat.seat-drag-source {
    opacity: 0.4;
}

.poker-seat.seat-valid-target .poker-seat-inner {
    box-shadow: 0 0 8px 3px rgba(76, 175, 80, 0.6);
    border-color: #4CAF50;
}

.poker-seat.drop-hover .poker-seat-inner {
    box-shadow: 0 0 12px 5px rgba(76, 175, 80, 0.9);
    border-color: #4CAF50;
    transform: scale(1.1);
}

.poker-seat-label {
    font-size: 10px;
    opacity: 0.6;
    line-height: 1;
}

/* ── Detail Drawer ────────────────────────────────────────────────────────── */

/*
 * MudBlazor colours list-item icons with --mud-palette-action-default (a dark
 * rgba tuned for its default white drawer). Our drawer backgrounds are dark, so
 * the icons all but disappear. Inherit the drawer's text colour instead, which
 * the theme already derives from the drawer background.
 */
.mud-drawer .mud-list-item-icon {
    color: inherit;
}

/* ── QR flyers ────────────────────────────────────────────────────────────── */

/*
 * Every QR flyer variant (registration, member, ...) has its own route on the
 * empty layout, so printing it prints only the flyer. Sizes are in inches/points
 * so the artwork fills one letter page regardless of the browser's
 * screen-to-print scaling.
 */

.qr-flyer-actions {
    padding: 1rem;
    text-align: center;
}

.qr-flyer {
    box-sizing: border-box;
    width: 8.5in;
    height: 11in;
    max-width: 100%;
    margin: 0 auto;
    padding: 0.5in;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    background: #fff;
    color: #000;
}

/*
 * Full-bleed to the physical page edge, undoing .qr-flyer's own padding, so it
 * reads as a band across the sheet rather than an inset banner.
 */
.qr-flyer-band {
    box-sizing: border-box;
    width: calc(100% + 1in);
    margin: -0.5in -0.5in 0.3in;
    padding: 0.2in 0;
    font-size: 28pt;
    font-weight: 700;
    letter-spacing: 0.08em;
    text-transform: uppercase;
}

/*
 * Fill vs outline, not two colors: a venue printing in monochrome collapses
 * any two colors into the same gray, but a solid fill next to an empty
 * outline stays distinct.
 */
.qr-flyer-band-solid {
    background: #000;
    color: #fff;
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
}

.qr-flyer-band-outlined {
    background: none;
    border: 3pt solid #000;
    color: #000;
}

.qr-flyer-name {
    margin: 0 0 0.3in;
    font-size: 48pt;
    line-height: 1.1;
    font-weight: 700;
    max-width: 100%;
    overflow-wrap: break-word;
}

.qr-flyer-logo {
    max-height: 2in;
    max-width: 6in;
    object-fit: contain;
    margin-bottom: 0.35in;
}

.qr-flyer-qr {
    width: 4.5in;
    height: 4.5in;
    max-width: 100%;
    object-fit: contain;
    /* Keep the QR modules square-edged when the 250px PNG is scaled up. */
    image-rendering: pixelated;
}

.qr-flyer-instruction {
    margin: 0.3in 0 0;
    font-size: 24pt;
    font-weight: 500;
}

.qr-flyer-fallback {
    margin: 0.1in 0 0;
    font-size: 16pt;
}

@media print {
    @page {
        size: letter portrait;
        margin: 0;
    }

    html, body {
        margin: 0;
        padding: 0;
    }

    .qr-flyer-actions {
        display: none !important;
    }

    .qr-flyer {
        width: 100%;
        height: 100vh;
        margin: 0;
        /* A page box rounded up by a fraction spills into a blank second sheet. */
        overflow: hidden;
        page-break-after: avoid;
        break-after: avoid;
    }
}

.mud-charts-gridlines-yaxis,
.mud-charts-gridlines-xaxis-lines {
    stroke-dasharray: 4 4;
}

.promo-row-inactive {
    opacity: 0.6;
}

/* Floor staff are plausibly on phones/tablets, so the app bar's environment badge
   shortens its wording under a narrow app bar rather than ever being hidden. */
.environment-badge-short {
    display: none;
}

.empty-layout-environment-bar {
    display: flex;
    justify-content: flex-end;
    padding: 8px 16px 0;
}

/* Same shortening rule for the Room Floor heading's environment suffix — a long
   club name plus the full suffix would wrap the sticky header on a phone. */
.room-heading-environment-short {
    display: none;
}

@media (max-width: 600px) {
    .environment-badge-full {
        display: none;
    }

    .environment-badge-short {
        display: inline;
    }

    .room-heading-environment-full {
        display: none;
    }

    .room-heading-environment-short {
        display: inline;
    }
}
