/* /Components/AvatarImage.razor.rz.scp.css */
/* AvatarImage Component */

.avatar[b-jmb51z2h63] {
    border-radius: 50%;
    object-fit: cover;
    flex-shrink: 0;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-heading);
    font-weight: 700;
    color: white;
    overflow: hidden;
    border: 2px solid var(--glass-border);
}

/* Size variants */
.avatar.avatar-sm[b-jmb51z2h63] {
    width: 28px;
    height: 28px;
    font-size: 0.7rem;
}

.avatar.avatar-md[b-jmb51z2h63] {
    width: 48px;
    height: 48px;
    font-size: 1rem;
}

.avatar.avatar-lg[b-jmb51z2h63] {
    width: 80px;
    height: 80px;
    font-size: 1.6rem;
}

/* Initials variant */
.avatar-initials[b-jmb51z2h63] {
    user-select: none;
    letter-spacing: 0.02em;
}

/* Hover effect for clickable avatars */
.avatar-clickable[b-jmb51z2h63] {
    cursor: pointer;
    transition: opacity 0.2s, transform 0.2s;
}

.avatar-clickable:hover[b-jmb51z2h63] {
    opacity: 0.85;
    transform: scale(1.05);
}
/* /Components/FeedbackComponent.razor.rz.scp.css */
/* This widget is the occluder task 1129 was actually about. It was reported as "the floating chat
   button covers the ENTER key" and everyone (including the task) assumed GroupChat — but GroupChat
   is a full-width bar on the RIGHT, and this is the bottom-LEFT circular button with a chat-bubble
   icon that the report described. Measured with FloatingChatControlOcclusionTests, it covered
   controls in three of four games at realistic phone heights, in daily and free play as well as in
   group mode (it is not group-gated), because z-index 11000 outranks everything including the chat.

   `bottom` is now derived from --chat-h rather than being the magic 60px that happened to clear a
   40px bar with 20px to spare. The point is not the arithmetic — it is that this widget and the
   chat now describe ONE reserved band (--float-zone-h in app.css) that game layouts subtract, so a
   change to either widget cannot silently start covering gameplay again. */
.feedback-widget-container[b-e6k4zhr21t] {
    position: fixed;
    bottom: calc(var(--chat-h, 0px) + 20px);
    left: 20px;
    z-index: 11000;
}

.btn-feedback[b-e6k4zhr21t] {
    width: 3.5rem;
    height: 3.5rem;
    border-radius: 50%;
    background: var(--bg-color);
    color: var(--accent-primary);
    border: 2px solid var(--accent-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5rem;
    cursor: pointer;
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.3);
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    backdrop-filter: blur(var(--glass-blur-md));
}

.btn-feedback:hover[b-e6k4zhr21t] {
    transform: scale(1.1) rotate(-8deg);
    background: var(--glass-bg);
    box-shadow: 0 8px 25px rgba(59, 130, 246, 0.4);
}

/* On a phone every pixel of the band this sits in is taken out of the board's budget
   (--float-zone-h), so the widget pays its own way: 44px instead of 56px, tucked 10px above the
   chat bar rather than 20px. Still comfortably above the 44px minimum touch target. */
@media (max-width: 767px) {
    .feedback-widget-container[b-e6k4zhr21t] {
        bottom: calc(var(--chat-h, 0px) + 10px);
        left: 12px;
    }

    .btn-feedback[b-e6k4zhr21t] {
        width: 2.75rem;
        height: 2.75rem;
        font-size: 1.2rem;
    }
}

.feedback-modal-overlay[b-e6k4zhr21t] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(var(--glass-blur-md));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 11001;
}

.feedback-modal-content[b-e6k4zhr21t] {
    background: var(--surface-color);
    padding: 2rem;
    border-radius: 1.25rem;
    border: 1px solid var(--glass-border);
    max-width: 500px;
    width: 90%;
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5);
}

.feedback-tabs[b-e6k4zhr21t] {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1.25rem;
    border-bottom: 1px solid var(--glass-border);
}

.feedback-tab[b-e6k4zhr21t] {
    flex: 1;
    padding: 0.6rem 0.75rem;
    background: transparent;
    border: none;
    border-bottom: 2px solid transparent;
    color: var(--text-secondary, var(--text-primary));
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s ease;
}

.feedback-tab:hover[b-e6k4zhr21t] {
    color: var(--text-primary);
}

.feedback-tab.active[b-e6k4zhr21t] {
    color: var(--accent-primary);
    border-bottom-color: var(--accent-primary);
}

.feedback-modal-content h3[b-e6k4zhr21t] {
    margin-bottom: 0.5rem;
    color: var(--text-primary);
}

.feedback-modal-content textarea[b-e6k4zhr21t] {
    background: var(--glass-input-bg);
    border: 1px solid var(--glass-border);
    color: var(--text-primary);
}

.feedback-modal-content textarea:focus[b-e6k4zhr21t] {
    background: var(--glass-bg);
    border-color: var(--accent-primary);
    box-shadow: 0 0 0 0.25rem rgba(59, 130, 246, 0.25);
    outline: none;
}
/* /Components/GameOptionsPanel.razor.rz.scp.css */
.theme-dropdown[b-gkgocerfea] {
    position: relative;
    width: 100%;
}

.theme-dropdown-toggle[b-gkgocerfea] {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.3rem 0.6rem;
    background: var(--surface-color);
    color: var(--text-primary);
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-sm, 4px);
    font-size: 0.875rem;
    cursor: pointer;
    text-align: left;
}

.theme-dropdown-toggle:hover[b-gkgocerfea] {
    background: var(--surface-hover);
}

.theme-dropdown-chevron[b-gkgocerfea] {
    font-size: 0.7rem;
    opacity: 0.7;
    flex-shrink: 0;
    margin-left: 0.4rem;
}

.theme-dropdown-list[b-gkgocerfea] {
    background: var(--surface-color);
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-sm, 4px);
    overflow: hidden;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    margin-top: 2px;
}

.theme-dropdown-option[b-gkgocerfea] {
    display: block;
    width: 100%;
    padding: 0.35rem 0.6rem;
    background: transparent;
    color: var(--text-primary);
    border: none;
    font-size: 0.875rem;
    cursor: pointer;
    text-align: left;
}

.theme-dropdown-option:hover[b-gkgocerfea] {
    background: var(--surface-hover);
}

.theme-dropdown-option.selected[b-gkgocerfea] {
    color: var(--accent-primary);
    font-weight: 600;
}
/* /Components/GameWinOverlay.razor.rz.scp.css */
.streak-row[b-4noktlj03w] {
    display: flex;
    justify-content: center;
    gap: 1rem;
    flex-wrap: wrap;
    margin: 1rem 0 0.5rem;
}

.streak-badge[b-4noktlj03w] {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    background: var(--color-info-soft);
    border: 1px solid var(--glass-border);
    border-radius: 2rem;
    padding: 0.35rem 0.85rem;
    font-size: 0.9rem;
}

.streak-badge-group[b-4noktlj03w] {
    background: var(--color-success-soft, rgba(34,197,94,0.12));
}

.streak-fire[b-4noktlj03w] {
    font-size: 1.1rem;
}

.streak-num[b-4noktlj03w] {
    font-weight: 700;
    color: var(--text-primary);
    font-size: 1.05rem;
}

.streak-label[b-4noktlj03w] {
    color: var(--text-secondary);
    font-size: 0.8rem;
}
/* /Components/GroupChat.razor.rz.scp.css */
/* Group Chat — uses design tokens only, no hardcoded colors */

.group-chat-container[b-uqtejwadoa] {
    position: fixed;
    bottom: 0;
    right: 20px;
    width: 320px;
    background-color: var(--surface-color);
    border: 1px solid var(--border-color);
    border-bottom: none;
    border-radius: 8px 8px 0 0;
    box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.2);
    display: flex;
    flex-direction: column;
    z-index: 9999;
    font-family: var(--font-body);
    transition: height 0.3s ease;
}

.group-chat-container.expanded[b-uqtejwadoa] {
    height: 450px;
}

.group-chat-container:not(.expanded)[b-uqtejwadoa] {
    height: 40px;
    cursor: pointer;
}

.chat-header[b-uqtejwadoa] {
    background-color: var(--accent-primary);
    color: var(--text-on-accent, #ffffff);
    padding: 10px 15px;
    border-radius: 8px 8px 0 0;
    font-weight: 600;
    display: flex;
    align-items: center;
    justify-content: space-between;
    height: 40px;
    box-sizing: border-box;
    user-select: none;
}

.chat-icon[b-uqtejwadoa] {
    margin-right: 8px;
}

.chat-title[b-uqtejwadoa] {
    flex-grow: 1;
}

.unread-badge[b-uqtejwadoa] {
    background-color: var(--color-error);
    color: white;
    font-size: 0.75rem;
    padding: 2px 6px;
    border-radius: 10px;
    font-weight: bold;
}

.chat-messages[b-uqtejwadoa] {
    flex-grow: 1;
    overflow-y: auto;
    padding: 15px;
    background-color: var(--bg-color);
    display: flex;
    flex-direction: column;
    gap: 12px;
}

.chat-empty[b-uqtejwadoa] {
    text-align: center;
    color: var(--text-secondary);
    font-size: 0.85rem;
    margin-top: 20px;
}

.chat-locked[b-uqtejwadoa] {
    text-align: center;
    color: var(--text-primary);
    font-size: 0.95rem;
    margin-top: auto;
    margin-bottom: auto;
    padding: 20px;
    background-color: var(--surface-color);
    border-radius: 8px;
    border: 1px dashed var(--border-color);
}

.chat-locked .locked-icon[b-uqtejwadoa] {
    font-size: 2rem;
    display: block;
    margin-bottom: 10px;
}

.chat-msg-row[b-uqtejwadoa] {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    max-width: 85%;
}

.chat-msg-row.my-msg[b-uqtejwadoa] {
    align-self: flex-end;
    align-items: flex-end;
}

.msg-meta[b-uqtejwadoa] {
    font-size: 0.75rem;
    color: var(--text-secondary);
    margin-bottom: 4px;
    display: flex;
    gap: 6px;
}

.chat-msg-row.my-msg .msg-meta[b-uqtejwadoa] {
    flex-direction: row-reverse;
}

.msg-sender[b-uqtejwadoa] {
    font-weight: 600;
    color: var(--text-primary);
}

.msg-bubble[b-uqtejwadoa] {
    background-color: var(--surface-color);
    color: var(--text-primary);
    padding: 8px 12px;
    border-radius: 12px;
    border-top-left-radius: 2px;
    font-size: 0.9rem;
    word-break: break-word;
    box-shadow: 0 1px 2px rgba(0, 0, 0, 0.1);
}

.chat-msg-row.my-msg .msg-bubble[b-uqtejwadoa] {
    background: var(--accent-primary);
    color: var(--text-on-accent, #ffffff);
    border-radius: 12px;
    border-top-right-radius: 2px;
    border-top-left-radius: 12px;
}

.chat-input-area[b-uqtejwadoa] {
    display: flex;
    padding: 10px;
    background-color: var(--surface-color);
    border-top: 1px solid var(--border-color);
    gap: 8px;
}

.chat-input[b-uqtejwadoa] {
    flex-grow: 1;
    padding: 8px 12px;
    border-radius: 20px;
    border: 1px solid var(--border-color);
    background-color: var(--bg-color);
    color: var(--text-primary);
    outline: none;
}

.chat-input:focus[b-uqtejwadoa] {
    border-color: var(--accent-primary);
}

.chat-send-btn[b-uqtejwadoa] {
    background-color: var(--accent-primary);
    color: var(--text-on-accent, white);
    border: none;
    border-radius: 20px;
    padding: 0 16px;
    font-weight: 600;
    cursor: pointer;
    transition: opacity 0.2s;
    flex-shrink: 0;
    min-width: 64px;
}

.chat-send-btn:disabled[b-uqtejwadoa] {
    opacity: 0.5;
    cursor: not-allowed;
}

.chat-send-btn:not(:disabled):hover[b-uqtejwadoa] {
    filter: brightness(1.1);
}

/* --- Inline vs Floating Modes --- */
.group-chat-container.floating-mode[b-uqtejwadoa] {
    position: fixed;
    bottom: 0;
    right: 20px;
}

.group-chat-container.inline-mode[b-uqtejwadoa] {
    position: relative;
    width: 100%;
    height: 100%;
    min-height: 400px;
    bottom: auto;
    right: auto;
    box-shadow: none;
    border: 1px solid var(--border-color);
    margin: 0;
    border-radius: 8px;
}

.group-chat-container.inline-mode .chat-header[b-uqtejwadoa] {
    cursor: default;
    border-radius: 8px 8px 0 0;
}

/* Use ::deep for dynamic HTML generated from Markdown */
[b-uqtejwadoa] .chat-game-link {
    color: var(--accent-primary);
    text-decoration: none;
    font-weight: 600;
    transition: filter 0.2s;
}

[b-uqtejwadoa] .chat-game-link:hover {
    text-decoration: underline;
    filter: brightness(1.2);
}

.chat-msg-row.my-msg[b-uqtejwadoa]  .chat-game-link {
    color: var(--text-on-accent, #ffffff);
    text-decoration: underline;
}

.completion-pill[b-uqtejwadoa] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    padding: 0.2rem 0.75rem;
    border-radius: 999px;
    background: var(--glass-bg, rgba(255,255,255,0.04));
    border: 1px solid var(--border-color);
    opacity: 0.5;
    font-size: 0.75rem;
    color: var(--text-secondary);
    align-self: center;
    max-width: 90%;
    margin: 0 auto;
}

.completion-name[b-uqtejwadoa] {
    font-weight: 600;
    color: var(--text-primary);
    opacity: 0.7;
}

.completion-text[b-uqtejwadoa] {
    flex-shrink: 0;
}

.completion-time[b-uqtejwadoa] {
    opacity: 0.5;
    flex-shrink: 0;
}

.completion-toggle[b-uqtejwadoa] {
    background: none;
    border: none;
    cursor: pointer;
    padding: 0 4px;
    font-size: 1rem;
    opacity: 0.7;
    line-height: 1;
}

.completion-toggle:hover[b-uqtejwadoa] {
    opacity: 1;
}

.chat-date-divider[b-uqtejwadoa] {
    text-align: center;
    border-bottom: 1px solid var(--border-color);
    line-height: 0.1em;
    margin: 15px 0 10px;
}

.chat-date-divider span[b-uqtejwadoa] {
    background: var(--bg-color);
    padding: 0 10px;
    font-size: 0.75rem;
    color: var(--text-secondary);
    font-weight: 600;
}

/* Mobile */
@media (max-width: 768px) {
    .group-chat-container.floating-mode[b-uqtejwadoa] {
        width: calc(100vw - 20px);
        right: 10px;
    }

    .group-chat-container.floating-mode.expanded[b-uqtejwadoa] {
        height: 60vh;
    }
}
/* /Components/GroupPuzzleUnavailable.razor.rz.scp.css */
/* Task 1078 — group-init failure panel. Sized to sit where the board would have been so the
   page does not collapse, but visually distinct from a board so it is never mistaken for one. */
.group-unavailable-panel[b-zz3bhu80oe] {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    text-align: center;
    gap: 0.75rem;
    max-width: 34rem;
    margin: 2rem auto;
    padding: 2.5rem 1.5rem;
    background: var(--glass-bg, rgba(255, 255, 255, 0.05));
    border: 1px solid var(--glass-border, rgba(255, 255, 255, 0.15));
    border-radius: 0.75rem;
}

.group-unavailable-icon[b-zz3bhu80oe] {
    font-size: 2.5rem;
    color: var(--bs-warning, #ffc107);
}

.group-unavailable-title[b-zz3bhu80oe] {
    font-size: 1.25rem;
    margin: 0;
    color: var(--text-primary, #fff);
}

.group-unavailable-body[b-zz3bhu80oe] {
    margin: 0;
    color: var(--text-secondary, rgba(255, 255, 255, 0.7));
}

.group-unavailable-actions[b-zz3bhu80oe] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.75rem;
    justify-content: center;
    margin-top: 0.5rem;
}
/* /Components/Launchpad.razor.rz.scp.css */
/* ==============================================================
   THE LAUNCHPAD (task 1162)
   ==============================================================
   Built from the SAME tokens as the marketing page it replaces for logged-in users
   (Pages/Home.razor.css): --surface-color cards on --glass-border, --font-heading for headings,
   --border-radius-lg corners, the gradient-clipped headline. A logged-in user must feel they are
   in the same product they just signed into, not a bootstrap table bolted onto it.

   SCOPING NOTE: the game tiles live in LaunchpadGameList.razor and are styled in
   LaunchpadGameList.razor.css, NOT here. Blazor's CSS isolation rewrites every rule to require
   this component's generated b-* attribute, which child-component markup does not carry — task
   1105 shipped exactly that bug (`.peer-avatar` styled only in LexGame.razor.css, so Lattice's
   identical markup rendered unstyled). Rules here stop at the wrappers this component renders. */

.lp[b-qdht7ki9ve] {
    max-width: 780px;
    margin: 0 auto;
    /* The floating chat + feedback FAB own the bottom band of a phone viewport and take the taps
       too (see app.css "THE FLOATING CHAT'S RESERVED ZONE"). --float-zone-h is that ownership
       written down; using the token means the last group row cannot end up underneath them. */
    padding: 1.5rem 0 calc(var(--float-zone-h, 0px) + 2rem);
}

/* ── Header ───────────────────────────────────────────── */
.lp-head[b-qdht7ki9ve] {
    margin-bottom: 1.75rem;
}

.lp-title[b-qdht7ki9ve] {
    font-family: var(--font-heading);
    font-size: clamp(1.75rem, 5vw, 2.5rem);
    font-weight: 800;
    letter-spacing: -0.02em;
    margin: 0 0 0.35rem;
    background: linear-gradient(135deg, var(--text-primary) 40%, var(--accent-primary) 140%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.lp-sub[b-qdht7ki9ve] {
    color: var(--text-secondary);
    font-size: 0.95rem;
    margin: 0;
}

/* ── Group rows ───────────────────────────────────────── */
.lp-groups[b-qdht7ki9ve] {
    display: flex;
    flex-direction: column;
    gap: 0.85rem;
}

.lp-group[b-qdht7ki9ve] {
    background: var(--surface-color);
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-lg);
    overflow: hidden;
    transition: border-color 0.2s;
}

.lp-group:hover[b-qdht7ki9ve] {
    border-color: var(--glass-border-bright);
}

.lp-row[b-qdht7ki9ve] {
    display: flex;
    align-items: center;
    gap: 0.85rem;
    padding: 0.9rem 1rem;
    /* min-width:0 on the flex child below is what actually lets long group names ellipsis instead
       of forcing the row wider than its card — the classic flexbox overflow. */
}

.lp-avatar[b-qdht7ki9ve] {
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--text-on-accent, #fff);
    background: linear-gradient(135deg, var(--accent-primary), #a855f7);
}

.lp-row-main[b-qdht7ki9ve] {
    flex: 1 1 auto;
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.15rem;
}

.lp-row-title[b-qdht7ki9ve] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    min-width: 0;
}

.lp-group-name[b-qdht7ki9ve] {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 1.05rem;
    color: var(--text-primary);
    text-decoration: none;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lp-group-name:hover[b-qdht7ki9ve] {
    color: var(--accent-primary);
}

.lp-streak[b-qdht7ki9ve] {
    flex: 0 0 auto;
    font-size: 0.75rem;
    font-weight: 600;
    padding: 0.1rem 0.4rem;
    border-radius: var(--border-radius-sm);
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    color: var(--text-secondary);
}

.lp-row-sub[b-qdht7ki9ve] {
    font-size: 0.82rem;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lp-highlight[b-qdht7ki9ve] {
    display: flex;
    align-items: center;
    gap: 0.35rem;
    margin-top: 0.2rem;
    font-size: 0.75rem;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lp-highlight-avatar[b-qdht7ki9ve] {
    width: 1.1rem;
    height: 1.1rem;
    border-radius: 50%;
    object-fit: cover;
    flex: 0 0 auto;
}

/* ── Play button ──────────────────────────────────────── */
.lp-play[b-qdht7ki9ve] {
    flex: 0 0 auto;
    display: flex;
    align-items: center;
    gap: 0.35rem;
    /* 44px is the tap target floor. This repo has measured real small-viewport breakage (task
       1149), and the Play button is THE control on this page — it must stay thumb-sized at 360px. */
    min-height: 44px;
    padding: 0 0.9rem;
    border: none;
    border-radius: 999px;
    background: var(--accent-primary);
    color: var(--text-on-accent, #fff);
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 0.9rem;
    cursor: pointer;
    transition: filter 0.15s, transform 0.15s;
}

.lp-play:hover[b-qdht7ki9ve] {
    filter: brightness(1.12);
}

.lp-play:active[b-qdht7ki9ve] {
    transform: scale(0.97);
}

.lp-play-badge[b-qdht7ki9ve] {
    min-width: 1.25rem;
    padding: 0 0.3rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.28);
    font-size: 0.72rem;
    line-height: 1.25rem;
    text-align: center;
}

/* Below 380px the word "Play" plus a badge plus a long group name is more than the row can hold
   without squeezing the name to nothing. The icon alone still reads as play, and aria-label
   carries the full meaning for assistive tech. */
@media (max-width: 379px) {
    .lp-play-text[b-qdht7ki9ve] {
        display: none;
    }
}

/* ── Solo group: games inline, no picker ──────────────── */
.lp-inline-games[b-qdht7ki9ve] {
    padding: 0 1rem 1rem;
    border-top: 1px solid var(--glass-border);
    margin-top: 0.1rem;
    padding-top: 0.85rem;
}

/* ── Drawer (the "quick side menu") ───────────────────── */
.lp-scrim[b-qdht7ki9ve] {
    position: fixed;
    inset: 0;
    background: rgba(2, 6, 23, 0.6);
    /* Above GroupChat (9999) and its scrim-less fixed bar, below the feedback FAB (11000) — see
       app.css's reserved-zone note for that stacking order. A drawer that the chat bar covers is
       exactly the occlusion bug tasks 1125/1129 already paid for twice. */
    z-index: 10400;
    animation: lp-fade-b-qdht7ki9ve 0.15s ease-out;
}

.lp-drawer[b-qdht7ki9ve] {
    position: fixed;
    top: 0;
    right: 0;
    bottom: 0;
    /* Bounded by construction: at 360px this is 331px, at 1440px it is 380px. There is no viewport
       at which a right-anchored drawer of this width can overflow horizontally. */
    width: min(380px, 92vw);
    display: flex;
    flex-direction: column;
    background: var(--surface-color);
    border-left: 1px solid var(--glass-border-bright);
    box-shadow: -12px 0 32px rgba(0, 0, 0, 0.45);
    z-index: 10500;
    animation: lp-slide-in-b-qdht7ki9ve 0.18s ease-out;
}

.lp-drawer-head[b-qdht7ki9ve] {
    display: flex;
    align-items: flex-start;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 1rem 1rem 0.75rem;
    border-bottom: 1px solid var(--glass-border);
}

.lp-drawer-eyebrow[b-qdht7ki9ve] {
    display: block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-secondary);
}

.lp-drawer-title[b-qdht7ki9ve] {
    font-family: var(--font-heading);
    font-size: 1.15rem;
    font-weight: 800;
    margin: 0.1rem 0 0;
    color: var(--text-primary);
    overflow-wrap: anywhere;
}

.lp-drawer-close[b-qdht7ki9ve] {
    flex: 0 0 auto;
    width: 44px;
    height: 44px;
    display: flex;
    align-items: center;
    justify-content: center;
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-md);
    background: var(--glass-bg);
    color: var(--text-secondary);
    cursor: pointer;
}

.lp-drawer-close:hover[b-qdht7ki9ve] {
    color: var(--text-primary);
    border-color: var(--glass-border-bright);
}

.lp-drawer-body[b-qdht7ki9ve] {
    flex: 1 1 auto;
    /* The picker must scroll rather than push its own footer off-screen: four tiles plus an extras
       row at 360x640 with the browser chrome up is genuinely taller than the viewport. */
    overflow-y: auto;
    padding: 0.85rem 1rem;
}

.lp-drawer-foot[b-qdht7ki9ve] {
    flex: 0 0 auto;
    border-top: 1px solid var(--glass-border);
    padding: 0.75rem 1rem calc(var(--float-zone-h, 0px) + 0.75rem);
}

.lp-lounge-link[b-qdht7ki9ve] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    min-height: 44px;
    border-radius: var(--border-radius-md);
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    color: var(--text-secondary);
    font-size: 0.88rem;
    font-weight: 600;
    text-decoration: none;
}

.lp-lounge-link:hover[b-qdht7ki9ve] {
    color: var(--text-primary);
    border-color: var(--glass-border-bright);
}

/* ── Empty state (a Kid with no guardian yet) ─────────── */
.lp-empty[b-qdht7ki9ve] {
    background: var(--surface-color);
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-lg);
    padding: 2rem 1.5rem;
    text-align: center;
}

.lp-empty-icon[b-qdht7ki9ve] {
    font-size: 2rem;
    color: var(--accent-primary);
    display: block;
    margin-bottom: 0.75rem;
}

.lp-empty h2[b-qdht7ki9ve] {
    font-family: var(--font-heading);
    font-size: 1.25rem;
    font-weight: 800;
    margin: 0 0 0.5rem;
    color: var(--text-primary);
}

.lp-empty p[b-qdht7ki9ve] {
    color: var(--text-secondary);
    font-size: 0.9rem;
    line-height: 1.6;
    max-width: 42ch;
    margin: 0 auto 1.25rem;
}

.lp-empty-games[b-qdht7ki9ve] {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    justify-content: center;
}

.lp-empty-game[b-qdht7ki9ve] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    min-height: 44px;
    padding: 0 0.9rem;
    border-radius: 999px;
    border: 1px solid var(--glass-border);
    background: var(--glass-bg);
    color: var(--text-primary);
    text-decoration: none;
    font-size: 0.85rem;
    font-weight: 600;
}

.lp-empty-game:hover[b-qdht7ki9ve] {
    border-color: var(--accent-primary);
    color: var(--accent-primary);
}

/* ── Loading skeleton ─────────────────────────────────── */
.lp-skeleton .lp-row-main[b-qdht7ki9ve] {
    gap: 0.4rem;
}

.lp-shimmer[b-qdht7ki9ve] {
    background: linear-gradient(90deg, var(--glass-bg) 25%, var(--glass-input-focus) 50%, var(--glass-bg) 75%);
    background-size: 200% 100%;
    animation: lp-shimmer-b-qdht7ki9ve 1.4s infinite linear;
    border-radius: var(--border-radius-sm);
}

.lp-shimmer-line[b-qdht7ki9ve] {
    height: 0.8rem;
    width: 60%;
}

.lp-shimmer-short[b-qdht7ki9ve] {
    width: 35%;
}

@keyframes lp-shimmer-b-qdht7ki9ve {
    to { background-position: -200% 0; }
}

@keyframes lp-fade-b-qdht7ki9ve {
    from { opacity: 0; }
}

@keyframes lp-slide-in-b-qdht7ki9ve {
    from { transform: translateX(100%); }
}

/* Respect a user who has asked the OS to stop moving things. */
@media (prefers-reduced-motion: reduce) {
    .lp-scrim[b-qdht7ki9ve],
    .lp-drawer[b-qdht7ki9ve],
    .lp-shimmer[b-qdht7ki9ve] {
        animation: none;
    }
}
/* /Components/LaunchpadGameList.razor.rz.scp.css */
/* The game tiles inside a launchpad picker (task 1162).

   These rules live HERE, in the child component's own stylesheet, and not in Launchpad.razor.css.
   Blazor CSS isolation rewrites every rule to require the generated b-* attribute of the component
   that owns the file, and that attribute is emitted only on markup THAT component rendered — so a
   `.lp-game` rule written in the parent's stylesheet would silently match nothing here. Task 1105
   shipped precisely that bug (`.peer-avatar` styled only in LexGame.razor.css, leaving Lattice's
   identical markup unstyled), and memory coterie-blazor-scoped-css-synthetic-element-blindness
   records the same mechanism from the test side. */

.lp-game-list[b-mt8u9g9a9s] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.lp-game[b-mt8u9g9a9s] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    width: 100%;
    /* 52px keeps every tile comfortably above the 44px tap floor at 360px, where the picker is a
       near-full-width drawer and these are the only targets on screen. */
    min-height: 52px;
    padding: 0.6rem 0.75rem;
    text-align: left;
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-left: 3px solid var(--lp-accent, var(--glass-border-bright));
    border-radius: var(--border-radius-md);
    color: var(--text-primary);
    font-family: inherit;
    cursor: pointer;
    transition: border-color 0.15s, background 0.15s, transform 0.15s;
}

button.lp-game:hover[b-mt8u9g9a9s] {
    background: var(--surface-hover);
    border-color: var(--glass-border-bright);
    border-left-color: var(--lp-accent, var(--accent-primary));
}

button.lp-game:active[b-mt8u9g9a9s] {
    transform: scale(0.99);
}

.lp-game-icon[b-mt8u9g9a9s] {
    flex: 0 0 auto;
    font-size: 1.15rem;
    color: var(--lp-accent, var(--text-secondary));
}

.lp-game-main[b-mt8u9g9a9s] {
    flex: 1 1 auto;
    /* Without min-width:0 a long "3 of 12 done · +2 more" meta line forces the tile wider than the
       drawer instead of ellipsising — the flexbox overflow that produces horizontal scroll. */
    min-width: 0;
    display: flex;
    flex-direction: column;
    gap: 0.1rem;
}

.lp-game-name[b-mt8u9g9a9s] {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 0.95rem;
    line-height: 1.2;
}

.lp-game-meta[b-mt8u9g9a9s] {
    display: flex;
    align-items: center;
    gap: 0.3rem;
    font-size: 0.74rem;
    color: var(--text-secondary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.lp-game-cta[b-mt8u9g9a9s] {
    flex: 0 0 auto;
    font-size: 0.8rem;
    font-weight: 700;
    color: var(--lp-accent, var(--accent-primary));
    white-space: nowrap;
}

/* ── State vocabulary ─────────────────────────────────────
   Deliberately the SAME colour language NavMenu has used since task 894: fresh is blue, in-play is
   purple, a group WIN is the diamond/teal, and a group that finished WITHOUT solving it is dimmed —
   which must look like neither a win nor a fresh puzzle. Two surfaces disagreeing about what "done"
   looks like is how 894's bug read as correct. */
.lp-state-new[b-mt8u9g9a9s] {
    --lp-accent: #3b82f6;
}

.lp-state-live[b-mt8u9g9a9s] {
    --lp-accent: #a855f7;
}

.lp-state-done[b-mt8u9g9a9s] {
    --lp-accent: #64748b;
}

.lp-state-groupwin[b-mt8u9g9a9s] {
    --lp-accent: #00f2fe;
}

.lp-state-spent[b-mt8u9g9a9s] {
    --lp-accent: #64748b;
    opacity: 0.75;
}

.lp-state-none[b-mt8u9g9a9s] {
    --lp-accent: #475569;
}

/* A tile with no puzzle behind it is not a control: no pointer, no hover, and visibly quieter than
   its playable neighbours. LaunchpadPresentation.IsPlayable is what decides this, and it reads
   State (never Status) — an Unavailable tile arrives with Status defaulted to NotPlayed. */
.lp-game-disabled[b-mt8u9g9a9s] {
    cursor: default;
    opacity: 0.55;
}

/* ── Extras ───────────────────────────────────────────── */
.lp-extras[b-mt8u9g9a9s] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    width: 100%;
    min-height: 44px;
    margin-top: 0.6rem;
    border: 1px dashed var(--glass-border-bright);
    border-radius: var(--border-radius-md);
    background: transparent;
    color: var(--text-secondary);
    font-size: 0.82rem;
    font-weight: 600;
    cursor: pointer;
}

.lp-extras:hover[b-mt8u9g9a9s] {
    color: var(--accent-primary);
    border-color: var(--accent-primary);
}

/* Shown INSTEAD of hiding the control, because here there is room to say why. Task 1145 had to
   hide NavMenu's equivalent "+" for anyone the server would refuse, since a nav rollup has no space
   for an explanation and a button that 403s on click is the pattern task 1134 is cleaning up. */
.lp-extras-locked[b-mt8u9g9a9s] {
    display: flex;
    align-items: flex-start;
    gap: 0.4rem;
    margin: 0.6rem 0 0;
    font-size: 0.75rem;
    line-height: 1.45;
    color: var(--text-secondary);
    opacity: 0.85;
}
/* /Components/LeaderboardPanel.razor.rz.scp.css */
/* LeaderboardPanel Component */

.lb-panel[b-qmiv80uc71] {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

/* ── Puzzle Type Tabs ───────────────────────────── */
.lb-tabs[b-qmiv80uc71] {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.lb-tab[b-qmiv80uc71] {
    background: var(--surface-color);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    color: var(--text-secondary);
    padding: 0.4rem 0.9rem;
    font-family: var(--font-body);
    font-size: 0.875rem;
    cursor: pointer;
    transition: background 0.15s, color 0.15s, border-color 0.15s;
    display: flex;
    align-items: center;
    gap: 0.35rem;
}

.lb-tab.active[b-qmiv80uc71] {
    background: var(--accent-primary);
    color: var(--text-on-accent);
    border-color: var(--accent-primary);
    font-weight: 600;
}

.lb-tab:hover:not(.active)[b-qmiv80uc71] {
    background: var(--surface-hover);
    color: var(--text-primary);
}

/* ── Time Window Buttons ────────────────────────── */
.lb-windows[b-qmiv80uc71] {
    display: flex;
    gap: 0.35rem;
    flex-wrap: wrap;
}

.lb-window-btn[b-qmiv80uc71] {
    background: transparent;
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-sm);
    color: var(--text-secondary);
    padding: 0.3rem 0.75rem;
    font-size: 0.8rem;
    cursor: pointer;
    transition: all 0.15s;
}

.lb-window-btn.active[b-qmiv80uc71] {
    background: var(--accent-secondary, var(--accent-primary));
    color: var(--text-on-accent);
    border-color: transparent;
    font-weight: 600;
}

.lb-window-btn:hover:not(.active)[b-qmiv80uc71] {
    background: var(--surface-hover);
    color: var(--text-primary);
}

/* ── Controls Row ────────────────────────────────── */
.lb-controls[b-qmiv80uc71] {
    display: flex;
    align-items: center;
    gap: 1.5rem;
    flex-wrap: wrap;
}

.lb-toggle[b-qmiv80uc71] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    cursor: pointer;
    user-select: none;
    font-size: 0.875rem;
    color: var(--text-secondary);
}

.lb-toggle input[b-qmiv80uc71] {
    display: none;
}

.lb-toggle-track[b-qmiv80uc71] {
    width: 36px;
    height: 20px;
    border-radius: 10px;
    background: var(--border-color);
    position: relative;
    transition: background 0.2s;
    flex-shrink: 0;
}

.lb-toggle-track[b-qmiv80uc71]::after {
    content: '';
    position: absolute;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    background: white;
    top: 3px;
    left: 3px;
    transition: transform 0.2s;
}

.lb-toggle input:checked~.lb-toggle-track[b-qmiv80uc71] {
    background: var(--accent-primary);
}

.lb-toggle input:checked~.lb-toggle-track[b-qmiv80uc71]::after {
    transform: translateX(16px);
}

.lb-metric-note[b-qmiv80uc71] {
    font-size: 0.8rem;
    color: var(--text-secondary);
    margin-left: auto;
}

/* ── Loading / Empty States ─────────────────────── */
.lb-loading[b-qmiv80uc71],
.lb-empty[b-qmiv80uc71] {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    padding: 2.5rem 1rem;
    color: var(--text-secondary);
    font-size: 0.95rem;
}

.lb-empty[b-qmiv80uc71] {
    flex-direction: column;
    gap: 0.5rem;
}

.lb-empty span[b-qmiv80uc71] {
    font-size: 2.5rem;
    opacity: 0.5;
}

/* ── Table ───────────────────────────────────────── */
.lb-table[b-qmiv80uc71] {
    width: 100%;
    border-collapse: collapse;
    font-size: 0.9rem;
}

.lb-table th[b-qmiv80uc71] {
    color: var(--text-secondary);
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.5rem 0.75rem;
    border-bottom: 1px solid var(--border-color);
    text-align: left;
}

.lb-table td[b-qmiv80uc71] {
    padding: 0.6rem 0.75rem;
    border-bottom: 1px solid var(--border-color);
    color: var(--text-primary);
    vertical-align: middle;
}

.lb-row[b-qmiv80uc71] {
    transition: background 0.1s;
}

.lb-row:hover[b-qmiv80uc71] {
    background: var(--surface-hover);
}

/* Handicapped / shadowed rows */
.lb-row.shadowed[b-qmiv80uc71] {
    opacity: 0.4;
    font-style: italic;
}

/* Rank badge */
.rank-badge[b-qmiv80uc71] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    font-weight: 700;
    font-size: 0.8rem;
}

.rank-badge.gold[b-qmiv80uc71] {
    background: rgba(255, 215, 0, 0.15);
    color: var(--rank-gold);
}

.rank-badge.silver[b-qmiv80uc71] {
    background: rgba(192, 192, 192, 0.15);
    color: var(--rank-silver);
}

.rank-badge.bronze[b-qmiv80uc71] {
    background: rgba(205, 127, 50, 0.12);
    color: var(--rank-bronze);
}

.rank-badge.plain[b-qmiv80uc71] {
    background: var(--surface-color);
    color: var(--text-secondary);
    font-size: 0.75rem;
}

.rank-badge.excluded[b-qmiv80uc71] {
    color: var(--text-secondary);
    font-size: 0.9rem;
}

/* Player column */
.col-player[b-qmiv80uc71] {
    display: flex;
    align-items: center;
    gap: 0.6rem;
}

.player-name[b-qmiv80uc71] {
    color: var(--text-primary);
    font-weight: 500;
}

/* Difficulty badge */
.diff-badge[b-qmiv80uc71] {
    padding: 0.15rem 0.5rem;
    border-radius: var(--border-radius-sm);
    font-size: 0.72rem;
    font-weight: 600;
    text-transform: uppercase;
}

.diff-0[b-qmiv80uc71] {
    background: rgba(16, 185, 129, 0.15);
    color: var(--rank-positive);
}

.diff-1[b-qmiv80uc71] {
    background: rgba(245, 158, 11, 0.15);
    color: var(--rank-neutral);
}

.diff-2[b-qmiv80uc71] {
    background: rgba(239, 68, 68, 0.15);
    color: var(--rank-negative);
}

/* Assist icons */
.assist-none[b-qmiv80uc71] {
    color: var(--rank-positive);
    font-size: 1rem;
}

.assist-used[b-qmiv80uc71] {
    color: var(--rank-neutral);
    font-size: 0.85rem;
}

/* Column sizing */
.col-rank[b-qmiv80uc71] {
    width: 48px;
    text-align: center;
}

.col-metric[b-qmiv80uc71] {
    width: 80px;
}

.col-actions[b-qmiv80uc71] {
    width: 72px;
}

.col-diff[b-qmiv80uc71] {
    width: 72px;
}

.col-assists[b-qmiv80uc71] {
    width: 72px;
}

.col-date[b-qmiv80uc71] {
    width: 80px;
    color: var(--text-secondary);
    font-size: 0.82rem;
}

@media (max-width: 640px) {

    .col-actions[b-qmiv80uc71],
    .col-date[b-qmiv80uc71] {
        display: none;
    }
}
/* /Components/PodiumPanel.razor.rz.scp.css */
.podium-panel[b-cf636wmm8o] {
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-radius: 0.75rem;
    padding: 0.6rem 0.75rem;
    backdrop-filter: blur(var(--glass-blur-sm));
    margin-bottom: 0.75rem;
}

.podium-title[b-cf636wmm8o] {
    font-size: 0.65rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    color: var(--text-muted);
    margin-bottom: 0.5rem;
}

.podium-entries[b-cf636wmm8o] {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.podium-entry[b-cf636wmm8o] {
    display: flex;
    align-items: center;
    gap: 0.4rem;
    font-size: 0.8rem;
}

.podium-badge[b-cf636wmm8o] {
    font-size: 1rem;
    flex-shrink: 0;
    width: 1.4rem;
    text-align: center;
}

.podium-name[b-cf636wmm8o] {
    flex: 1;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.podium-time[b-cf636wmm8o] {
    font-variant-numeric: tabular-nums;
    color: var(--text-muted);
    font-size: 0.75rem;
    flex-shrink: 0;
}

.podium-empty[b-cf636wmm8o] {
    color: var(--text-muted);
    flex: 1;
}

@media (max-width: 640px) {
    .podium-entries[b-cf636wmm8o] {
        flex-direction: row;
        gap: 0.5rem;
    }

    .podium-entry[b-cf636wmm8o] {
        flex: 1;
        flex-direction: column;
        align-items: center;
        gap: 0.15rem;
        text-align: center;
    }

    .podium-name[b-cf636wmm8o] {
        display: none;
    }

    .podium-badge[b-cf636wmm8o] {
        font-size: 1.2rem;
        width: auto;
    }

    .podium-time[b-cf636wmm8o] {
        font-size: 0.7rem;
    }
}
/* /Components/SyncProblemNotice.razor.rz.scp.css */
/*
    Tasks 1097 + 1099. Tuned to read as "heads up", not "catastrophe" — the player's board is
    intact and their work is not lost, so an alarming red panel would overstate the problem and
    train them to dread a message they mostly just need to read once.
*/
.sync-problem-notice[b-bbgbhm3qro] {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0.5rem auto;
    padding: 0.6rem 0.9rem;
    max-width: 34rem;

    border: 1px solid rgba(255, 193, 7, 0.45);
    border-radius: 0.5rem;
    background: rgba(255, 193, 7, 0.12);
    color: var(--text-primary, #f5f5f5);

    font-size: 0.9rem;
    line-height: 1.35;
    text-align: left;
}

.sync-problem-icon[b-bbgbhm3qro] {
    flex: 0 0 auto;
    font-size: 1.15rem;
    color: #ffc107;
}

.sync-problem-text[b-bbgbhm3qro] {
    flex: 1 1 auto;
}
/* /Components/UnderConstruction.razor.rz.scp.css */
.uc-shell[b-6qs59syne4] {
    min-height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-color, #0f172a);
    font-family: var(--font-body, 'Inter', sans-serif);
}

.uc-card[b-6qs59syne4] {
    text-align: center;
    max-width: 480px;
    padding: 3rem 2rem;
    background: var(--surface-color, #1e293b);
    border: 1px solid var(--glass-border, rgba(255,255,255,0.08));
    border-radius: var(--border-radius-lg, 1rem);
    box-shadow: 0 20px 50px rgba(0,0,0,0.4);
}

.uc-icon[b-6qs59syne4] {
    font-size: 4rem;
    margin-bottom: 1.25rem;
    display: block;
    filter: drop-shadow(0 0 12px rgba(59,130,246,0.4));
}

.uc-title[b-6qs59syne4] {
    font-family: var(--font-heading, 'Outfit', sans-serif);
    font-size: 2.5rem;
    font-weight: 800;
    color: var(--text-primary, #f8fafc);
    margin: 0 0 1rem;
    background: linear-gradient(to right, #60a5fa, #3b82f6);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.uc-body[b-6qs59syne4] {
    color: var(--text-secondary, #94a3b8);
    font-size: 1.05rem;
    line-height: 1.6;
    margin-bottom: 2rem;
}

.uc-signin-btn[b-6qs59syne4] {
    background: var(--accent-primary, #3b82f6);
    color: #fff;
    border: none;
    border-radius: var(--border-radius-md, 0.5rem);
    padding: 0.65rem 2rem;
    font-size: 1rem;
    font-weight: 600;
    cursor: pointer;
    transition: filter 0.2s ease;
}

.uc-signin-btn:hover[b-6qs59syne4] {
    filter: brightness(1.15);
}
/* /Layout/AdaptiveHomeLayout.razor.rz.scp.css */
/* Holds the viewport while the auth state resolves, so "/" does not flash blank on cold load.
   Deliberately empty of content — anything shown here would be shown to BOTH audiences and would
   have to be wrong for one of them. */
.home-authorizing[b-g8df9yl4na] {
    min-height: 100dvh;
    background: var(--bg-color, #0f172a);
}
/* /Layout/MainLayout.razor.rz.scp.css */
.api-unavailable-overlay[b-pbm29f0v7l] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
}

.api-unavailable-card[b-pbm29f0v7l] {
    background: var(--surface-color, #1e293b);
    border: 1px solid var(--glass-border, rgba(255,255,255,0.1));
    border-radius: 1rem;
    padding: 2.5rem 3rem;
    text-align: center;
    max-width: 360px;
    box-shadow: 0 20px 60px rgba(0,0,0,0.5);
}

.api-unavailable-card h2[b-pbm29f0v7l] {
    margin: 1rem 0 0.5rem;
    font-size: 1.5rem;
    color: var(--text-primary, #f8fafc);
}

.api-unavailable-card p[b-pbm29f0v7l] {
    color: var(--text-secondary, #94a3b8);
    font-size: 0.95rem;
    margin: 0;
}

.retry-countdown[b-pbm29f0v7l] {
    margin-top: 1rem !important;
    color: var(--accent-primary, #3b82f6) !important;
    font-size: 0.85rem !important;
}

.api-spinner[b-pbm29f0v7l] {
    width: 48px;
    height: 48px;
    border: 4px solid rgba(59, 130, 246, 0.2);
    border-top-color: var(--accent-primary, #3b82f6);
    border-radius: 50%;
    animation: api-spin-b-pbm29f0v7l 1s linear infinite;
    margin: 0 auto;
}

@keyframes api-spin-b-pbm29f0v7l {
    to { transform: rotate(360deg); }
}

.page[b-pbm29f0v7l] {
    position: relative;
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background-color: var(--bg-color);
    color: var(--text-primary);
    transition: background-color 0.3s ease, color 0.3s ease;
}

main[b-pbm29f0v7l] {
    flex: 1;
}

.sidebar[b-pbm29f0v7l] {
    background-color: var(--surface-color);
    border-right: 1px solid var(--border-color);
    z-index: 1050;
    transition: left 0.3s cubic-bezier(0.4, 0, 0.2, 1), transform 0.3s ease;
}

.sidebar.collapsed[b-pbm29f0v7l] {
    transform: translateX(-100%);
}

.sidebar.expanded[b-pbm29f0v7l] {
    transform: translateX(0);
}

.sidebar-overlay[b-pbm29f0v7l] {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.5);
    backdrop-filter: blur(var(--glass-blur-sm));
    z-index: 1040;
    animation: fadeIn-b-pbm29f0v7l 0.3s ease;
}

@keyframes fadeIn-b-pbm29f0v7l {
    from { opacity: 0; }
    to { opacity: 1; }
}

.navbar-toggler[b-pbm29f0v7l] {
    background: transparent;
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-sm);
    color: var(--text-primary);
    padding: 0.25rem 0.6rem;
    font-size: 1.25rem;
    cursor: pointer;
    display: flex;
    align-items: center;
    transition: all 0.2s ease;
}

.navbar-toggler:hover[b-pbm29f0v7l] {
    background: var(--glass-bg);
    border-color: var(--accent-primary);
}

.top-row[b-pbm29f0v7l] {
    background-color: var(--surface-color);
    border-bottom: 1px solid var(--border-color);
    justify-content: flex-end;
    height: var(--topnav-h, 3.5rem);
    display: flex;
    align-items: center;
    color: var(--text-primary);
}

.top-row[b-pbm29f0v7l]  a,
.top-row[b-pbm29f0v7l]  .btn-link {
    white-space: nowrap;
    margin-left: 1.5rem;
    text-decoration: none;
    color: var(--text-secondary);
}

.top-row[b-pbm29f0v7l]  a:hover,
.top-row[b-pbm29f0v7l]  .btn-link:hover {
    text-decoration: underline;
    color: var(--accent-primary);
}

.top-row[b-pbm29f0v7l]  a:first-child {
    overflow: hidden;
    text-overflow: ellipsis;
}

@media (max-width: 640.98px) {
    .sidebar[b-pbm29f0v7l] {
        position: fixed;
        top: 0;
        left: 0;
        bottom: 0;
        width: 280px;
        height: 100vh;
    }

    .sidebar.expanded[b-pbm29f0v7l] {
        box-shadow: 10px 0 25px rgba(0, 0, 0, 0.5);
    }

    .top-row[b-pbm29f0v7l] {
        justify-content: space-between;
    }

    .top-row[b-pbm29f0v7l]  a,
    .top-row[b-pbm29f0v7l]  .btn-link {
        margin-left: 0;
    }
}

@media (min-width: 641px) {
    .page[b-pbm29f0v7l] {
        flex-direction: row;
    }

    .sidebar[b-pbm29f0v7l] {
        width: var(--sidebar-w, 250px);
        height: 100vh;
        position: sticky;
        top: 0;
        transform: none !important;
        transition: none !important;
    }

    .navbar-toggler[b-pbm29f0v7l] {
        display: none !important;
    }

    .top-row[b-pbm29f0v7l] {
        position: sticky;
        top: 0;
        z-index: 1;
    }

    .top-row.auth[b-pbm29f0v7l]  a:first-child {
        flex: 1;
        text-align: right;
        width: 0;
    }

    .top-row[b-pbm29f0v7l],
    article[b-pbm29f0v7l] {
        padding-left: 2rem !important;
        padding-right: 1.5rem !important;
    }
}

/* ── Error boundary fallback ──────────────────────────── */
.error-page[b-pbm29f0v7l] {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 60vh;
    padding: 2rem;
}

.error-card[b-pbm29f0v7l] {
    text-align: center;
    max-width: 480px;
    width: 100%;
    padding: 3rem 2rem;
    background: var(--glass-bg, rgba(255,255,255,0.03));
    backdrop-filter: blur(12px);
    -webkit-backdrop-filter: blur(12px);
    border: 1px solid var(--glass-border, rgba(255,255,255,0.08));
    border-radius: 1.25rem;
    box-shadow: 0 20px 50px rgba(0,0,0,0.4);
}

.error-card-icon[b-pbm29f0v7l] {
    font-size: 3.5rem;
    margin-bottom: 1rem;
    color: var(--color-warning, #f59e0b);
    filter: drop-shadow(0 0 12px rgba(245,158,11,0.4));
    display: block;
}

.error-card h2[b-pbm29f0v7l] {
    font-size: 1.75rem;
    font-weight: 800;
    margin-bottom: 0.75rem;
    color: var(--text-primary, #f8fafc);
}

.error-card p[b-pbm29f0v7l] {
    color: var(--text-secondary, #94a3b8);
    margin-bottom: 1.5rem;
    font-size: 0.95rem;
}

.error-details[b-pbm29f0v7l] {
    text-align: left;
    background: rgba(0,0,0,0.3);
    border: 1px solid var(--glass-border, rgba(255,255,255,0.08));
    border-radius: 0.5rem;
    padding: 0.75rem 1rem;
    margin-bottom: 1.5rem;
    font-size: 0.8rem;
}

.error-details summary[b-pbm29f0v7l] {
    cursor: pointer;
    color: var(--text-secondary, #94a3b8);
    user-select: none;
}

.error-stack[b-pbm29f0v7l] {
    margin-top: 0.5rem;
    color: var(--color-error, #ef4444);
    white-space: pre-wrap;
    word-break: break-word;
    font-size: 0.75rem;
    max-height: 200px;
    overflow-y: auto;
}
/* /Layout/NavMenu.razor.rz.scp.css */
.login-streak-badge[b-p5wqa25pt0] {
    display: inline-block;
    margin-left: 0.4rem;
    font-size: 0.75rem;
    background: var(--color-info-soft);
    border-radius: 1rem;
    padding: 0.1rem 0.5rem;
    color: var(--text-primary);
    font-weight: 600;
    vertical-align: middle;
}

/* Brand logo */
.brand-icon[b-p5wqa25pt0] {
    width: 26px;
    height: 26px;
    border-radius: 5px;
    vertical-align: middle;
    margin-right: 0.4rem;
    margin-bottom: 2px;
    object-fit: cover;
}

/* ── The abbreviated launchpad (task 1162) ────────────────
   What used to live here was a per-group CARD containing four expandable game-type rollups, each
   with its own tally row, chevron and quick-add button — twenty collapsible panels for a user with
   five groups, which Kris called "pretty bad as 5 groups". All of it is gone, along with the
   .rollup-*, .quick-add-btn, .game-instance*, .game-link and .status-* rules that dressed it; the
   detail moved to the launchpad at "/" and the group lounge, both of which have room for it.

   What is left is ONE LINE PER GROUP. Deliberately the same visual weight as the Home and Account
   links above it, because that is what it now is: a navigation entry, not a dashboard. */
.nav-section-label[b-p5wqa25pt0] {
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.08em;
    font-weight: 700;
    color: var(--text-secondary);
    opacity: 0.75;
    margin: 1rem 0 0.35rem;
}

.group-line[b-p5wqa25pt0] {
    display: flex;
    align-items: center;
    cursor: pointer;
    /* 40px keeps a crew line a comfortable tap target in the mobile drawer without making five of
       them taller than the viewport. */
    min-height: 40px;
    border-radius: 8px;
}

/* A crew called "Martens Family Sunday Crew" must ellipsis, not push the badge off the panel. */
.group-line-name[b-p5wqa25pt0] {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    min-width: 0;
}

/* The count of games in this group still waiting on THIS user. Not a chat unread count — that
   badge was fed by a hardcoded `return 0` stub and has never rendered (see NavMenu's
   LoadGroupDataAsync). This one is derived from real state, so it is styled as information rather
   than as the alarm-red the old one claimed to be. */
.nav-waiting-badge[b-p5wqa25pt0] {
    flex-shrink: 0;
    background: rgba(var(--accent-primary-rgb, 59, 130, 246), 0.22);
    color: var(--text-primary);
    font-size: 0.7rem;
    font-weight: 700;
    min-width: 1.35rem;
}

.active-group-highlight[b-p5wqa25pt0] {
    background: rgba(var(--accent-primary-rgb, 59, 130, 246), 0.05);
    border-color: rgba(var(--accent-primary-rgb, 59, 130, 246), 0.2);
    box-shadow: 0 4px 15px rgba(0, 0, 0, 0.2), inset 0 0 0 1px rgba(var(--accent-primary-rgb, 59, 130, 246), 0.1);
}

/* Base Link Styles - ensure contrast across all themes using ::deep to reach NavLink output */
[b-p5wqa25pt0] .nav-link {
    color: var(--text-secondary) !important;
    transition: all 0.2s ease;
}

[b-p5wqa25pt0] .nav-link:hover {
    color: var(--text-primary) !important;
    background: rgba(255, 255, 255, 0.08) !important;
}

[b-p5wqa25pt0] .nav-link.active {
    color: var(--text-primary) !important;
    font-weight: 700 !important;
    background: rgba(var(--accent-primary-rgb, 59, 130, 246), 0.15) !important;
}



/* User Profile overrides for styling */
.nav-user-profile[b-p5wqa25pt0] {
    margin-top: auto;
    border-top: 1px solid var(--border-color);
    padding: 1rem;
    background: var(--surface-color);
    margin-bottom: 0.5rem;
}

.user-info[b-p5wqa25pt0] {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 12px;
}

.avatar[b-p5wqa25pt0] {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    background: var(--accent-primary);
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: bold;
    font-size: 1.2rem;
    box-shadow: 0 0 10px var(--accent-glow);
}

.details[b-p5wqa25pt0] {
    display: flex;
    flex-direction: column;
    overflow: hidden;
}

.details .name[b-p5wqa25pt0] {
    font-weight: bold;
    color: var(--text-primary);
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.details .persona[b-p5wqa25pt0] {
    font-size: 0.75rem;
    color: var(--text-secondary);
    text-transform: uppercase;
    letter-spacing: 1px;
}

.btn-logout[b-p5wqa25pt0] {
    width: 100%;
    background: var(--surface-hover);
    border: 1px solid var(--border-color);
    color: var(--text-secondary);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 8px;
    border-radius: 4px;
    transition: all 0.2s;
}

.btn-logout:hover[b-p5wqa25pt0] {
    background: var(--color-error-soft);
    border-color: rgba(239, 68, 68, 0.3);
    color: var(--color-error);
}
/* /Layout/PublicLayout.razor.rz.scp.css */
.public-layout[b-hwzr9zaofg] {
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    background-color: var(--bg-color);
    color: var(--text-primary);
    font-family: var(--font-body);
}

.public-header[b-hwzr9zaofg] {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem 2rem;
    border-bottom: 1px solid var(--glass-border);
    background: rgba(15, 23, 42, 0.8);
    backdrop-filter: blur(12px);
    position: sticky;
    top: 0;
    z-index: 100;
}

.public-brand[b-hwzr9zaofg] {
    font-family: var(--font-heading);
    font-size: 1.5rem;
    font-weight: 800;
    color: var(--text-primary);
    text-decoration: none;
    letter-spacing: -0.02em;
}

.public-brand:hover[b-hwzr9zaofg] {
    color: var(--accent-primary);
}

.public-main[b-hwzr9zaofg] {
    flex: 1;
}

.public-brand[b-hwzr9zaofg] {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.public-brand-icon[b-hwzr9zaofg] {
    width: 28px;
    height: 28px;
    border-radius: 6px;
    object-fit: cover;
}

/* Public error fallback */
.public-error[b-hwzr9zaofg] {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 50vh;
    padding: 2rem;
}

.public-error-card[b-hwzr9zaofg] {
    text-align: center;
    max-width: 440px;
    padding: 3rem 2rem;
    background: rgba(255,255,255,0.03);
    backdrop-filter: blur(12px);
    border: 1px solid rgba(255,255,255,0.08);
    border-radius: 1.25rem;
    box-shadow: 0 20px 50px rgba(0,0,0,0.4);
}

.public-error-icon[b-hwzr9zaofg] {
    font-size: 3rem;
    color: var(--color-warning, #f59e0b);
    display: block;
    margin-bottom: 1rem;
}

.public-error-card h2[b-hwzr9zaofg] {
    font-size: 1.75rem;
    font-weight: 800;
    color: var(--text-primary, #f8fafc);
    margin-bottom: 0.75rem;
}

.public-error-card p[b-hwzr9zaofg] {
    color: var(--text-secondary, #94a3b8);
    margin-bottom: 1.5rem;
}
/* /Pages/Account.razor.rz.scp.css */
/* Account Page — uses design tokens only, no hardcoded colors */

.streak-summary[b-2erfunx3s7] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1.25rem;
    padding: 0.75rem 1rem;
    background: var(--color-info-soft);
    border-radius: var(--border-radius-sm);
    border: 1px solid var(--glass-border);
}

.streak-fire-lg[b-2erfunx3s7] {
    font-size: 2rem;
}

.streak-count[b-2erfunx3s7] {
    font-size: 1.4rem;
    font-weight: 700;
    color: var(--text-primary);
}

.streak-desc[b-2erfunx3s7] {
    font-size: 0.9rem;
    color: var(--text-secondary);
}

.form-label[b-2erfunx3s7] {
    color: var(--text-secondary);
}

.text-secondary[b-2erfunx3s7] {
    color: var(--text-secondary);
}

.badge-tiny[b-2erfunx3s7] {
    font-size: 0.6rem;
}

.dashboard-page[b-2erfunx3s7] {
    padding: 2.5rem;
    background-color: var(--bg-color);
    min-height: 100vh;
    color: var(--text-primary);
}

.glass-card[b-2erfunx3s7] {
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur-lg));
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-lg);
    padding: 1.5rem;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    position: relative;
    overflow: hidden;
}

.dashboard-header[b-2erfunx3s7] {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    margin-bottom: 3rem;
}

.header-info h1[b-2erfunx3s7] {
    font-size: 3rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    margin: 0;
    color: var(--text-primary);
}

.badge-row[b-2erfunx3s7] {
    display: flex;
    gap: 0.75rem;
    margin-top: 0.5rem;
}

.bg-primary-soft[b-2erfunx3s7] {
    background: var(--color-info-soft);
    color: var(--color-info-text);
}

.bg-info-soft[b-2erfunx3s7] {
    background: var(--color-success-soft);
    color: var(--color-success-text);
}

.bg-warning-soft[b-2erfunx3s7] {
    background: var(--color-warning-soft);
    color: var(--color-warning-text);
}

.full-width[b-2erfunx3s7] {
    width: 100%;
}

.card-header-icon[b-2erfunx3s7] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1.25rem;
}

.card-header-icon span[b-2erfunx3s7] {
    font-size: 1.5rem;
    color: var(--accent-primary);
}

.subscription-benefits[b-2erfunx3s7] {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.subscription-benefits .benefit-item[b-2erfunx3s7] {
    display: flex;
    align-items: flex-start;
    gap: 0.5rem;
    padding: 0.6rem 0.75rem;
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-sm);
}

.subscription-benefits.subscribed .benefit-item[b-2erfunx3s7] {
    align-items: center;
    font-weight: 500;
}

.card-header-icon h3[b-2erfunx3s7] {
    margin: 0;
    font-size: 1.1rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-primary);
}

.card-help[b-2erfunx3s7] {
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin-bottom: 1.5rem;
}

.glass-input[b-2erfunx3s7] {
    background: var(--glass-input-bg);
    border: 1px solid var(--glass-border);
    color: var(--text-primary);
}

.glass-input:focus[b-2erfunx3s7] {
    background: var(--glass-input-focus);
    border-color: var(--accent-primary);
    color: var(--text-primary);
    box-shadow: none;
}

.glass-input option[b-2erfunx3s7] {
    background-color: var(--surface-color);
    color: var(--text-primary);
}

.danger-card[b-2erfunx3s7] {
    border-color: rgba(239, 68, 68, 0.3);
    background: var(--color-error-soft);
}

.text-danger-soft[b-2erfunx3s7] {
    color: var(--color-error-text);
}

.group-table[b-2erfunx3s7] {
    background-color: transparent !important;
    border-collapse: separate;
    border-spacing: 0 0.5rem;
}

.group-table thead th[b-2erfunx3s7] {
    color: var(--text-secondary);
    font-weight: 700;
    font-size: 0.75rem;
    text-transform: uppercase;
    letter-spacing: 0.1em;
    border: none;
    padding: 1rem 1.5rem;
}

.group-table tbody tr[b-2erfunx3s7] {
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    transition: all 0.2s ease;
    border-radius: var(--border-radius-md);
}

.group-table tbody tr:hover[b-2erfunx3s7] {
    background: var(--glass-input-focus);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.2);
}

.group-table td[b-2erfunx3s7] {
    color: var(--text-primary);
    vertical-align: middle;
    padding: 1.25rem 1.5rem;
    border: none;
}

/* Ensure no Bootstrap white backgrounds */
.table[b-2erfunx3s7] {
    --bs-table-bg: transparent !important;
    --bs-table-striped-bg: transparent !important;
    --bs-table-hover-bg: transparent !important;
    color: var(--text-primary) !important;
}

.btn-glass[b-2erfunx3s7] {
    background: var(--glass-input-bg);
    border: 1px solid var(--glass-border);
    color: var(--text-primary);
    font-weight: 600;
}

.btn-glass:hover[b-2erfunx3s7] {
    background: var(--glass-input-focus);
    border-color: var(--glass-border-bright);
    color: var(--text-primary);
}

.modal-overlay[b-2erfunx3s7] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(var(--glass-blur-sm));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
}

.modal-card[b-2erfunx3s7] {
    width: 100%;
    max-width: 400px;
}

.modal-actions[b-2erfunx3s7] {
    display: flex;
    justify-content: space-between;
    gap: 10px;
}

.modal-actions button[b-2erfunx3s7] {
    flex: 1;
}

/* Animations */
.animate-fade-in[b-2erfunx3s7] {
    animation: fadeIn-b-2erfunx3s7 0.6s ease-out;
}

.animate-slide-up[b-2erfunx3s7] {
    animation: slideUp-b-2erfunx3s7 0.8s ease-out;
}

.animate-scale[b-2erfunx3s7] {
    animation: scaleIn-b-2erfunx3s7 0.3s ease-out;
}

@keyframes fadeIn-b-2erfunx3s7 {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes slideUp-b-2erfunx3s7 {
    from {
        opacity: 0;
        transform: translateY(20px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes scaleIn-b-2erfunx3s7 {
    from {
        opacity: 0;
        transform: scale(0.95);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

/* Semantic status messages */
.msg-success[b-2erfunx3s7] {
    background: var(--color-success-soft);
    color: var(--color-success-text);
    border: 1px solid var(--color-success);
}

.msg-error[b-2erfunx3s7] {
    background: var(--color-error-soft);
    color: var(--color-error-text);
    border: 1px solid var(--color-error);
}

/* Build info footer (task 1125) — muted, selectable, purely informational; not a card so it
   does not compete visually with the actual account controls above it. */
.build-info-footer[b-2erfunx3s7] {
    padding-bottom: 1rem;
}

.build-info-line[b-2erfunx3s7] {
    font-size: 0.7rem;
    line-height: 1.4;
    color: var(--text-secondary);
    opacity: 0.7;
    user-select: text;
    -webkit-user-select: text;
}
/* /Pages/DomainGame.razor.rz.scp.css */
/* ==============================================================================================
   Domain (Queens) board layout + region-colour SKIN.

   SIZING MODEL — copied deliberately from SpanGame.razor.css (the fixed model, task 1028): size the
   CELL, not the box. --cell is the single scalar — the largest square that fits BOTH axes' budget,
   floored at a tappable minimum. Both tracks are repeat(N, var(--cell)) and the grid box is
   max-content, so the box is a CONSEQUENCE of the cells rather than a competing claim about them.
   Square cells are true BY CONSTRUCTION, so a cell can never overflow the board's own box.

   The board is ALWAYS square (N×N), so it does not need Span's non-square handling — but the
   inline-style rule is the same and load-bearing: the .razor emits ONLY --domain-cols/--domain-rows
   inline. grid-template-* lives HERE, in the scoped sheet. An inline grid-template would beat the
   sheet and reopen the exact Span bug. (The per-cell background-color IS inline — that is a colour,
   not track sizing, so it does not interact with this.)

   Unlike Span, Domain does NOT pan dense boards: N tops out at 13, which shrinks to fit even a 390px
   phone above the collapse floor, so Domain is held to the same fit contract as Grid/Lex/Lattice in
   BoardShrinkToFitTests (it is NOT excluded from No_cell_is_painted_outside_the_viewport).
   ============================================================================================== */

.game-controls[b-a3ko96s1q3] {
    gap: 0.4rem;
}

/* Desktop: fill game-layout and center the board in both axes. `safe` centering keeps the top-left
   of an overflowing board reachable (same rationale as Span — see its .board-section comment). */
.board-section[b-a3ko96s1q3] {
    display: flex;
    align-items: safe center;
    justify-content: safe center;
    flex: 1;
    align-self: stretch;
    /* --avail-w below reads 100cqw against this element, so the board learns its real available
       width from layout instead of restating every ancestor's padding. Safe to be a query
       container: this element's inline size is layout-driven in both viewports. */
    container-type: inline-size;
}

.domain-grid-wrapper[b-a3ko96s1q3] {
    width: 100%;
    max-width: 640px;
    background-color: transparent;
    margin: 0 auto;
    padding: 1.5rem;
    margin-bottom: 5rem;
}

.domain-grid[b-a3ko96s1q3] {
    display: grid;

    --grid-gap: 0.25rem;
    /* The floor below which a cell stops being a comfortable touch target. 1.6rem keeps even a 13×13
       board fitting a 390px phone (13 × 25.6px + gaps < the ~377px container). */
    --min-cell: 1.6rem;

    /* Width budget from the REAL container (task 1028 argument): 100cqw is .board-section's
       content-box inline size, after the sidebar and every ancestor's padding are already
       subtracted by layout. 640px is the wrapper's own max-width cap; 3rem is the wrapper's 1.5rem
       padding both sides. Desktop stays width-driven (the page may scroll), so height is
       deliberately unconstrained. */
    --avail-w: calc(min(100cqw, 640px) - 3rem);
    --avail-h: 100000px;

    --fit-cell: min(
        calc((var(--avail-w) - (var(--domain-cols, 7) - 1) * var(--grid-gap)) / var(--domain-cols, 7)),
        calc((var(--avail-h) - (var(--domain-rows, 7) - 1) * var(--grid-gap)) / var(--domain-rows, 7))
    );
    --cell: max(var(--fit-cell), var(--min-cell));

    grid-template-columns: repeat(var(--domain-cols, 7), var(--cell));
    grid-template-rows: repeat(var(--domain-rows, 7), var(--cell));
    /* The box follows the cells. Never the other way round. */
    width: max-content;
    height: max-content;
    margin-inline: auto;

    gap: var(--grid-gap);
    /* A subtle frame so the outer edge of the board reads as a board rather than floating tiles. */
    background: var(--glass-border, rgba(255, 255, 255, 0.15));
    padding: var(--grid-gap);
    border-radius: 0.4rem;
    position: relative;
    z-index: 5;
    touch-action: manipulation;
}

.domain-cell[b-a3ko96s1q3] {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    /* No aspect-ratio: both tracks are var(--cell), so the cell is square by construction. */
    border-radius: 0.15rem;
    cursor: pointer;
    user-select: none;
    /* No tap delay / double-tap zoom on iOS for the click target. */
    touch-action: manipulation;
    transition: box-shadow 0.15s ease, filter 0.15s ease;
}

.domain-cell:hover[b-a3ko96s1q3] {
    filter: brightness(1.08);
}

/* The crown / X glyph. A dark glyph with a strong white halo is legible on EVERY region fill in the
   palette (validated: no single flat glyph colour clears WCAG on all 13, but dark-glyph +
   white-outline does — the map-label technique), so it works in light and dark themes alike. */
.domain-mark[b-a3ko96s1q3] {
    font-size: calc(var(--cell, 1.6rem) * 0.62);
    line-height: 1;
    font-weight: 700;
    color: #141414;
    text-shadow:
        0 0 2px #fff, 0 0 2px #fff, 0 0 3px #fff,
        1px 0 0 #fff, -1px 0 0 #fff, 0 1px 0 #fff, 0 -1px 0 #fff;
    pointer-events: none;
}

.domain-queen[b-a3ko96s1q3] {
    font-size: calc(var(--cell, 1.6rem) * 0.66);
}

.domain-x[b-a3ko96s1q3] {
    /* The X is a scratch aid ("not here"), so it reads a touch lighter than a placed crown. */
    color: #2a2a2a;
    opacity: 0.72;
    font-size: calc(var(--cell, 1.6rem) * 0.5);
    font-weight: 800;
}

/* Live conflict highlighting: a queen breaking any constraint (shared row/col/region or touching
   another, incl. diagonally) gets a red ring + shake, the same immediate feedback Span gives an
   over-connected island. */
.domain-cell.conflict[b-a3ko96s1q3] {
    box-shadow: 0 0 0 3px #ef4444, 0 0 12px rgba(239, 68, 68, 0.7);
    z-index: 10;
    animation: domainConflictShake-b-a3ko96s1q3 0.4s ease;
}

@keyframes domainConflictShake-b-a3ko96s1q3 {
    0%, 100% { transform: translate(0); }
    25% { transform: translate(-2px, 1px); }
    50% { transform: translate(2px, -1px); }
    75% { transform: translate(-1px, 1px); }
}

/* Auto-mark assist overlay (task 1644, OFF by default — see AutoMarkAssistBit in DomainGame.razor).
   A faint dot in the cell's corner, DELIBERATELY lighter than the player's own bold manual X
   (.domain-mark/.domain-x above) so a manual X placed over an auto-blocked cell still reads as the
   player's own mark, not the assist's. ::after keeps it out of the flex-centred glyph slot .domain-mark
   occupies, so the two never fight for the same box. */
.domain-cell.auto-blocked[b-a3ko96s1q3]::after {
    content: "";
    position: absolute;
    top: 0.2rem;
    right: 0.2rem;
    width: calc(var(--cell, 1.6rem) * 0.12);
    height: calc(var(--cell, 1.6rem) * 0.12);
    border-radius: 50%;
    background: rgba(20, 20, 20, 0.32);
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.5);
    pointer-events: none;
}

/* ==============================================================================================
   SKIN: "Aurora" (default).  A palette of 13 CSS custom properties, --domain-region-0..12; a size-N
   board uses the first N. Applied as a class on .board-section, so ADDING A SKIN is a new CSS block
   plus a dictionary entry in DomainGame.razor — no logic changes (memory
   coterie-domain-region-colors-are-skins).

   ACCESSIBILITY (this default is the "hard part" the memory calls out — 13 categories is the edge of
   categorical distinguishability). Built with the dataviz categorical-palette method: farthest-point
   selection in perceptual (CIELAB) space under a colourblind-safe constraint, then validated with:
     • all-pairs CIEDE2000 under normal vision AND Machado-2009 simulated deuteranopia / protanopia /
       tritanopia (severity 1.0) — worst-case min ΔE2000 = 11.4 across all four conditions (every
       pair clears the ~10 JND, so ANY two regions stay distinct as neighbours, not just a ramp);
     • WCAG symbol contrast — a black glyph with a white halo (see .domain-mark) clears legibility on
       every fill, in light and dark themes.
   ============================================================================================== */
.board-section.domain-skin-aurora[b-a3ko96s1q3] {
    --domain-region-0:  #1818BF; /* deep blue */
    --domain-region-1:  #9B3B3B; /* brick */
    --domain-region-2:  #761FF9; /* violet */
    --domain-region-3:  #4E79A7; /* steel blue */
    --domain-region-4:  #AB782B; /* ochre */
    --domain-region-5:  #9E60FB; /* lavender-purple */
    --domain-region-6:  #FB607F; /* rose */
    --domain-region-7:  #2BABAB; /* teal */
    --domain-region-8:  #C29CFC; /* pale lilac */
    --domain-region-9:  #F9A21F; /* amber */
    --domain-region-10: #D1E3B5; /* pale green */
    --domain-region-11: #9CFCFC; /* ice cyan */
    --domain-region-12: #FBFB60; /* yellow */
}

/* ==============================================================================================
   SKIN: "Terra" (warm/earthy). Built with the SAME method as Aurora above (task 1643): farthest-point
   selection in CIELAB, candidates drawn from warm hue/lightness/saturation bins (terracotta, brick,
   ochre, olive/moss, umber, warm neutrals) rather than the full hue wheel, then a swap-based local
   search maximising the worst-case pairwise gap, then validated the same way — all-pairs CIEDE2000
   under normal vision AND Machado-2009 deuteranopia / protanopia / tritanopia (severity 1.0).
   Worst-case min ΔE2000 across all four conditions = 10.35 (still clears the ~10 JND, though a themed
   palette restricted to one hue family has structurally less room than Aurora's full-spectrum 11.4 —
   expect the closest pair here to read as "similar-but-distinct" rather than Aurora's clean separation).
   Symbol legibility is unchanged: the dark-glyph + white-halo technique in .domain-mark is fill-colour
   independent, so it is not re-validated per skin.
   ============================================================================================== */
.board-section.domain-skin-terra[b-a3ko96s1q3] {
    --domain-region-0:  #A92415; /* rust */
    --domain-region-1:  #33857B; /* pine teal */
    --domain-region-2:  #8B7A5E; /* stone taupe */
    --domain-region-3:  #2A6B58; /* forest green */
    --domain-region-4:  #B5ACA3; /* warm grey */
    --domain-region-5:  #E5A11C; /* amber gold */
    --domain-region-6:  #862C37; /* oxblood */
    --domain-region-7:  #59152A; /* deep maroon */
    --domain-region-8:  #AF8435; /* bronze ochre */
    --domain-region-9:  #E4C892; /* wheat */
    --domain-region-10: #D0401B; /* burnt orange */
    --domain-region-11: #DED7C2; /* sand */
    --domain-region-12: #AD9871; /* khaki tan */
}

/* ==============================================================================================
   SKIN: "Glacier" (cool/pastel). Same method as Aurora/Terra (task 1643): candidates drawn from cool
   hue bins (icy teal, sky blue, periwinkle, lavender, orchid, cool rose) at higher lightness / lower
   saturation for a pastel feel, plus a few deeper cool anchors so the palette has contrast range, then
   farthest-point selection + local-search refinement, validated the same all-pairs-CIEDE2000-under-
   normal-and-3-CVD-simulations way. Worst-case min ΔE2000 = 9.07 — this is the palette's honest
   ceiling: pastel-by-design colours sit closer together in CIELAB than a full-spectrum or dark palette
   can, so 9.07 (vs. the ~10 JND, and Aurora's 11.4) is the real cost of the pastel mood, not a
   validation shortfall. Every pair still clears ~9 ΔE, which stays discriminable, just not to Aurora's
   margin.
   ============================================================================================== */
.board-section.domain-skin-glacier[b-a3ko96s1q3] {
    --domain-region-0:  #547D97; /* slate blue */
    --domain-region-1:  #A595C3; /* dusty violet */
    --domain-region-2:  #141471; /* deep indigo */
    --domain-region-3:  #5F40D3; /* periwinkle violet */
    --domain-region-4:  #90D2B3; /* seafoam */
    --domain-region-5:  #C5556F; /* dusty rose */
    --domain-region-6:  #2B30A2; /* royal blue */
    --domain-region-7:  #234A70; /* deep teal-blue */
    --domain-region-8:  #D6C3D3; /* pale mauve */
    --domain-region-9:  #E4B1E8; /* orchid pink */
    --domain-region-10: #70AC9F; /* sage teal */
    --domain-region-11: #D5EAE0; /* pale mint */
    --domain-region-12: #A276D1; /* lavender */
}

/* ==============================================================================================
   SKIN: "Eclipse" (high-contrast/dark). Same method (task 1643): candidates span the FULL hue wheel
   like Aurora, but pulled toward lower lightness (20-48%) and higher saturation (55-95%) for a punchy,
   dark-mode-friendly feel, then farthest-point selection + local-search refinement, validated the same
   all-pairs-CIEDE2000-under-normal-and-3-CVD-simulations way. Worst-case min ΔE2000 = 11.4 across all
   four conditions, matching Aurora's margin — the darker/punchier constraint did not cost separation
   the way Glacier's pastel constraint did.
   ============================================================================================== */
.board-section.domain-skin-eclipse[b-a3ko96s1q3] {
    --domain-region-0:  #BC2A60; /* magenta rose */
    --domain-region-1:  #177E89; /* deep teal */
    --domain-region-2:  #B17F15; /* burnt gold */
    --domain-region-3:  #676705; /* olive drab */
    --domain-region-4:  #2E09EB; /* electric indigo */
    --domain-region-5:  #2843A0; /* navy */
    --domain-region-6:  #07E9E7; /* neon cyan */
    --domain-region-7:  #5A0C38; /* deep plum */
    --domain-region-8:  #DAC309; /* gold */
    --domain-region-9:  #2F0773; /* deep violet */
    --domain-region-10: #2EAEA2; /* teal */
    --domain-region-11: #D70614; /* crimson */
    --domain-region-12: #195839; /* dark green */
}

/* ==============================================================================================
   SKIN: "Carnival" (vibrant jewel tones). Same method (task 1643): candidates span the full hue wheel
   at high saturation (65-95%) and mid-bright lightness (38-62%) for a playful, energetic feel, then
   farthest-point selection + local-search refinement, validated the same all-pairs-CIEDE2000-under-
   normal-and-3-CVD-simulations way. Worst-case min ΔE2000 = 9.40 across all four conditions — clear of
   the closest safe margin but under Aurora's 11.4, the real cost of packing 13 saturated, similarly
   bright colours into one palette.
   ============================================================================================== */
.board-section.domain-skin-carnival[b-a3ko96s1q3] {
    --domain-region-0:  #AC6516; /* bronze orange */
    --domain-region-1:  #B2143B; /* crimson */
    --domain-region-2:  #0C06C9; /* royal blue */
    --domain-region-3:  #10E8F7; /* cyan */
    --domain-region-4:  #0D51F5; /* blue */
    --domain-region-5:  #D1291A; /* red-orange */
    --domain-region-6:  #DC9652; /* amber tan */
    --domain-region-7:  #E64196; /* pink magenta */
    --domain-region-8:  #F8F726; /* yellow */
    --domain-region-9:  #45A0E5; /* sky blue */
    --domain-region-10: #DBC535; /* gold-yellow */
    --domain-region-11: #2A77DC; /* azure */
    --domain-region-12: #BB1F9F; /* purple magenta */
}

/* === MOBILE: no-scroll viewport fill (mirrors Span's mobile block, minus the pan behaviour) ===
   The height condition (max-height:500px) covers landscape phones/Chromebooks, which are WIDER than
   767px but have no real vertical budget — the same reason Span added it (task 1401). */
@media (max-width: 767px), (max-height: 500px) {
    .app-container[b-a3ko96s1q3] {
        position: fixed;
        top: var(--topnav-h, 3.5rem);
        left: 0;
        right: 0;
        bottom: 0;
        height: auto;
        overflow: hidden;
        --chrome-h: calc(80px + var(--podium-h, 0px) + var(--float-zone-h, 0px) + env(safe-area-inset-bottom, 0px));
    }

    header[b-a3ko96s1q3] {
        padding: 0.35rem 0.75rem;
        gap: 0.25rem;
    }

    header h1[b-a3ko96s1q3] {
        font-size: 1rem;
    }

    [b-a3ko96s1q3] .toolbar-actions {
        gap: 0.4rem;
        flex-wrap: wrap;
        overflow-x: visible;
    }

    [b-a3ko96s1q3] .btn-primary,
    [b-a3ko96s1q3] .form-select,
    [b-a3ko96s1q3] .btn-sm {
        font-size: 0.75rem;
        padding: 0.2rem 0.45rem;
    }

    .game-layout[b-a3ko96s1q3] {
        flex: 1;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    .board-section[b-a3ko96s1q3] {
        flex: 1;
        min-height: 0;
        /* Domain shrinks to fit rather than panning (N ≤ 13 always fits), so overflow:auto here is a
           belt-and-braces backstop for the shortest viewports, not a design feature. */
        overflow: auto;
        -webkit-overflow-scrolling: touch;
        display: flex;
        align-items: safe center;
        justify-content: safe center;
        padding: 0;
    }

    .domain-grid-wrapper[b-a3ko96s1q3] {
        width: max-content;
        min-width: 100%;
        max-width: none;
        margin: 0 auto;
        padding: 0.5rem;
        box-sizing: border-box;
        display: flex;
        align-items: safe center;
        justify-content: safe center;
        overflow: visible;
    }

    /* Mobile keeps desktop's capped --avail-w AND --grid-gap and adds ONLY the height budget.
       This is the deliberate difference from Span: Domain SHRINKS to fit, it does not PAN, so it
       must never let the mobile board grow past its desktop-capped size — otherwise narrowing the
       viewport into the mobile band (e.g. 1280 -> 700) makes the board BIGGER, which is exactly
       what BoardShrinkToFitTests.Narrowing_the_viewport_costs_the_user_no_cells forbids (measured:
       an uncapped 100cqw mobile board rendered 95px cells at 700px vs 81px at the 1280 reference).
       Only the HEIGHT axis is a genuinely new mobile constraint, so only --avail-h is overridden. */
    .domain-grid[b-a3ko96s1q3] {
        --avail-h: calc(100dvh - var(--topnav-h, 3.5rem) - var(--chrome-h, 0px));
        flex: none;
    }
}

/* === THE 641-767px BAND: mobile game, but the sidebar is already in flow === */
/* MainLayout.razor.css switches .page to flex-direction:row with a 250px STICKY sidebar at
   min-width:641px, while the mobile block above runs until max-width:767px. Those two disagree
   for 127px. Domain makes .app-container `position: fixed` in that mobile block (same as Span),
   which takes it out of the flex row; a fixed box resolves left/right against the VIEWPORT, so
   without this override `left: 0` parks the board underneath the sidebar and 100cqw sizes it as
   if the sidebar were not there (measured task 1622: at 700px the board sat at x=50 under the
   250px sidebar, 200px/8-of-32-hit-points occluded).

   Mirrors SpanGame.razor.css's identical band block (task 1401/1028): we keep the fixed
   positioning — it stops iOS Safari rubber-banding the page body — and just tell it about the
   sidebar it is sharing the viewport with. No --avail-w override is needed here either: 100cqw
   already reads .board-section's real (sidebar-subtracted) inline size once .app-container is
   correctly offset, so the width budget self-corrects and BoardShrinkToFit's fit contract is
   unaffected by this change.

   var(--sidebar-w) is MainLayout.razor.css's sidebar width for this same min-width:641px range
   (app.css :root, task 939); if that number moves, this must move with it. */
@media (min-width: 641px) and (max-width: 767px),
       (min-width: 641px) and (max-height: 500px) {
    .app-container[b-a3ko96s1q3] {
        left: var(--sidebar-w, 250px);
    }
}
/* /Pages/GridGame.razor.rz.scp.css */
/* Game Control Buttons (Undo / Reset) */
.game-controls[b-3m1mc6p88i] {
    gap: 0.4rem;
}

.btn-icon[b-3m1mc6p88i] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border: 1px solid var(--glass-border);
    border-radius: 0.5rem;
    background: var(--glass-input-bg);
    color: var(--text-primary);
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.2s ease;
    backdrop-filter: blur(6px);
}

.btn-icon:hover:not(:disabled)[b-3m1mc6p88i] {
    background: var(--accent-primary);
    color: var(--bg-color);
    border-color: var(--accent-primary);
    transform: scale(1.08);
    box-shadow: 0 0 10px var(--accent-glow);
}

.btn-icon:active:not(:disabled)[b-3m1mc6p88i] {
    transform: scale(0.95);
}

.btn-icon:disabled[b-3m1mc6p88i] {
    opacity: 0.35;
    cursor: not-allowed;
}

/* Component Specific Styles */
.toolbar-actions[b-3m1mc6p88i] {
    display: flex;
    gap: 1rem;
    align-items: center;
}

.btn-theme[b-3m1mc6p88i] {
    background-color: var(--surface-color);
    color: var(--text-primary);
    border: 1px solid var(--border-color);
    padding: 0.5rem 1rem;
    border-radius: var(--border-radius-sm);
    cursor: pointer;
    font-family: var(--font-heading);
}

.btn-theme:hover[b-3m1mc6p88i] {
    background-color: var(--surface-hover);
}

/* THE CSS GRID BOARD */
.board-section[b-3m1mc6p88i] {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    width: 100%;
    min-height: 0;
    /* Allow flex shrink */
    overflow-y: auto;
    padding: 1rem 0;
}

.grid-grid[b-3m1mc6p88i] {
    display: grid;
    grid-template-columns: repeat(9, 1fr);
    grid-template-rows: repeat(9, 1fr);
    gap: 1px;
    background-color: var(--grid-line);
    border: 2px solid var(--grid-block-line);
    /* Box shadow ensures the grid is visible on light (kid) backgrounds */
    box-shadow: 0 2px 16px rgba(0, 0, 0, 0.12);
    width: 100%;
    /* Bound by the shorter of available height (minus chrome) and a hard cap so
       the board scales up on Chromebook/desktop instead of stranding empty space,
       but never grows taller than the viewport.

       --float-zone-h is part of that chrome (task 1129): the floating feedback FAB and chat bar own
       the bottom band of the viewport, and this budget is derived from 100dvh, which does not know
       that. Without subtracting it the board grew into the band and the FAB sat on the number pad —
       measured covering the '4' button at 443x660. Subtracting it here SHRINKS THE BOARD, which is
       the behaviour this rule already implements for every other piece of chrome; subtracting it
       from the container instead would have clipped the pad rather than resized the board. */
    max-width: min(calc(100dvh - 12rem - var(--float-zone-h, 0px)), 560px);
    aspect-ratio: 1 / 1;
    flex-shrink: 0;
}

/* Explicit borders for 3x3 blocks (replaces fragile nth-child logic) */
.grid-cell.border-right-thick[b-3m1mc6p88i] {
    border-right: 2px solid var(--grid-block-line);
}

.grid-cell.border-bottom-thick[b-3m1mc6p88i] {
    border-bottom: 2px solid var(--grid-block-line);
}

.grid-cell[b-3m1mc6p88i] {
    background-color: var(--cell-bg);
    color: var(--cell-text);
    display: flex;
    justify-content: center;
    align-items: center;
    font-size: clamp(1.2rem, 5vw, 2rem);
    font-family: var(--font-heading);
    font-weight: 500;
    cursor: pointer;
    user-select: none;
    transition: background-color 0.1s ease;
}

.grid-cell.kid-cell[b-3m1mc6p88i] {
    font-size: clamp(1.4rem, 5.5vw, 2.2rem);
    font-weight: 700;
}

.grid-cell.locked[b-3m1mc6p88i] {
    color: var(--cell-text-locked);
    font-weight: 700;
}

.grid-cell:hover:not(.locked)[b-3m1mc6p88i] {
    background-color: var(--surface-hover);
}

/* ==============================================================
   THEME PALETTES (Colors react to the selected Correctness Theme)
   ============================================================== */
.board-section.wf-theme-classic[b-3m1mc6p88i] {
    /* Classic inherits from the group theme's accent color */
    --local-error: var(--cell-text-error);
    --local-active-bg: var(--accent-primary);
    --local-active-text: var(--cell-text-active);
    --local-active-border: transparent;
    --local-active-shadow: 0 0 10px var(--accent-glow);
}

.board-section.wf-theme-neon[b-3m1mc6p88i] {
    --local-error: #f43f5e;
    --local-active-bg: transparent;
    --local-active-text: #38bdf8;
    --local-active-border: #38bdf8;
    --local-active-shadow: 0 0 10px rgba(56, 189, 248, 0.5), inset 0 0 10px rgba(56, 189, 248, 0.5);
}

.board-section.wf-theme-shapes[b-3m1mc6p88i] {
    --local-error: #fb923c;
    --local-active-bg: transparent;
    --local-active-text: var(--cell-text);
    --local-active-border: #4ade80;
    --local-active-shadow: none;
}

.board-section.wf-theme-kinetic[b-3m1mc6p88i] {
    --local-error: #fca5a5;
    --local-active-bg: transparent;
    --local-active-text: #22c55e;
    --local-active-border: transparent;
    --local-active-shadow: none;
}

.board-section.wf-theme-spectral[b-3m1mc6p88i] {
    --local-error: #f472b6;
    --local-active-bg: transparent;
    --local-active-text: #60a5fa;
    --local-active-border: transparent;
    --local-active-shadow: 0 0 15px #60a5fa;
}

.board-section .grid-cell.active[b-3m1mc6p88i] {
    background-color: var(--local-active-bg);
    color: var(--local-active-text);
    border: 2px solid var(--local-active-border, transparent);
    box-shadow: var(--local-active-shadow, none);
    transform: scale(1.02);
    z-index: 10;
}

.board-section .grid-cell.error[b-3m1mc6p88i] {
    color: var(--local-error);
    font-weight: bold;
}

/* Handicaps Styling */
.board-section .grid-cell.incorrect-placement[b-3m1mc6p88i] {
    color: #ef4444 !important;
}

/* --- THEME SPECIFIC ANIMATIONS FOR GRID --- */
@keyframes neonFlicker-b-3m1mc6p88i {

    0%,
    19%,
    21%,
    23%,
    25%,
    54%,
    56%,
    100% {
        opacity: 1;
        text-shadow: 0 0 8px #22c55e;
    }

    20%,
    24%,
    55% {
        opacity: 0.5;
        text-shadow: none;
    }
}

.board-section.wf-theme-kinetic .grid-cell.active[b-3m1mc6p88i] {
    animation: neonFlicker-b-3m1mc6p88i 3s infinite alternate;
}

@keyframes glitchShake-b-3m1mc6p88i {
    0% {
        transform: translate(0)
    }

    20% {
        transform: translate(-2px, 2px)
    }

    40% {
        transform: translate(-2px, -2px)
    }

    60% {
        transform: translate(2px, 2px)
    }

    80% {
        transform: translate(2px, -2px)
    }

    100% {
        transform: translate(0)
    }
}

.board-section.wf-theme-kinetic .grid-cell.error[b-3m1mc6p88i] {
    animation: glitchShake-b-3m1mc6p88i 0.4s infinite;
}

.board-section.wf-theme-shapes .grid-cell.active[b-3m1mc6p88i] {
    border-radius: 50%;
    transform: scale(0.9);
}

.grid-cell.completed-region[b-3m1mc6p88i] {
    animation: completed-fade-b-3m1mc6p88i 1.5s ease-out forwards;
}

@keyframes completed-fade-b-3m1mc6p88i {
    0% {
        background-color: rgba(255, 215, 0, 0.6);
    }

    100% {
        background-color: rgba(255, 215, 0, 0.05);
        /* Fades almost entirely away */
    }
}

.grid-grid.with-headers[b-3m1mc6p88i] {
    grid-template-columns: 30px repeat(9, 1fr);
    grid-template-rows: 30px repeat(9, 1fr);
    max-width: 530px;
}


.grid-header-cell[b-3m1mc6p88i] {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.65rem;
    color: var(--text-secondary);
    font-family: var(--font-body);
    text-align: center;
    background: transparent;
}

.grid-header-cell.row-header[b-3m1mc6p88i] {
    flex-direction: row;
    flex-wrap: wrap;
    padding-right: 2px;
    justify-content: flex-end;
}

.grid-header-cell.col-header[b-3m1mc6p88i] {
    flex-direction: column;
    justify-content: flex-end;
    padding-bottom: 2px;
}

.grid-possibles-grid[b-3m1mc6p88i] {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);
    width: 100%;
    height: 100%;
    padding: 2px;
}

.grid-possible-num[b-3m1mc6p88i] {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.55rem;
    color: var(--text-secondary);
    line-height: 1;
    font-weight: normal;
}

/* NUMPAD */
.numpad-section[b-3m1mc6p88i] {
    width: 100%;
    max-width: 500px;
    margin: 0 auto;
    padding: 0.5rem 0.5rem env(safe-area-inset-bottom, 0.5rem);
}

.numpad-header[b-3m1mc6p88i] {
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding-bottom: 0.4rem;
}

.numpad[b-3m1mc6p88i] {
    display: grid;
    grid-template-columns: repeat(5, 1fr);
    gap: 0.5rem;
}

.num-btn[b-3m1mc6p88i] {
    background-color: var(--surface-color);
    color: var(--text-primary);
    border: 1px solid var(--border-color);
    border-radius: var(--border-radius-md);
    font-size: 1.5rem;
    font-family: var(--font-heading);
    padding: 0.4rem 0 0.3rem;
    cursor: pointer;
    transition: transform 0.1s, background-color 0.2s;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 2px;
    min-height: 3.2rem;
}

.num-btn:active[b-3m1mc6p88i] {
    transform: scale(0.95);
    background-color: var(--accent-primary);
}

.erase-btn[b-3m1mc6p88i] {
    background-color: rgba(239, 68, 68, 0.1);
    color: var(--cell-text-error);
    border-color: rgba(239, 68, 68, 0.3);
}

/* Digit count badge — remaining placements for each digit */
.digit-remaining[b-3m1mc6p88i] {
    font-size: 0.5rem;
    color: var(--text-secondary);
    font-family: var(--font-body);
    line-height: 1;
    opacity: 0.45;
    letter-spacing: 0.02em;
}

.num-btn.digit-exhausted[b-3m1mc6p88i] {
    opacity: 0.25;
}

/* Notes mode toggle */
.notes-toggle.active[b-3m1mc6p88i] {
    background: var(--accent-primary);
    color: var(--bg-color);
    border-color: var(--accent-primary);
    box-shadow: 0 0 8px var(--accent-glow);
}

/* === MOBILE: no-scroll viewport fill === */
/* The top-row in MainLayout is var(--topnav-h); subtract it so the game fills exactly the
   remaining space. */
@media (max-width: 767px) {
    /* NOT reserved here — see `.grid-grid`'s max-width below, which is where Grid's size actually
       comes from. Shrinking this container instead just clips the number pad: measured at 443x660,
       5 of 10 number buttons went out of reach, which is worse than the single partly-covered
       button it was meant to fix. */
    .app-container[b-3m1mc6p88i] {
        height: calc(100dvh - var(--topnav-h, 3.5rem));
        overflow: hidden;
    }

    header[b-3m1mc6p88i] {
        padding: 0.35rem 0.75rem;
        gap: 0.25rem;
    }

    header h1[b-3m1mc6p88i] {
        font-size: 1rem;
    }

    [b-3m1mc6p88i] .toolbar-actions {
        gap: 0.4rem;
        flex-wrap: nowrap;
        overflow-x: auto;
    }

    [b-3m1mc6p88i] .btn-primary,
    [b-3m1mc6p88i] .form-select,
    [b-3m1mc6p88i] .btn-sm {
        font-size: 0.75rem;
        padding: 0.2rem 0.45rem;
    }

    .game-layout[b-3m1mc6p88i] {
        flex: 1;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
        padding-bottom: 0;
    }

    .board-section[b-3m1mc6p88i] {
        flex: 0 0 auto;
        display: flex;
        justify-content: center;
        width: 100%;
        overflow: hidden;
        padding: 0.25rem 0.5rem;
    }

    /* Mobile-first board sizing: the largest square that fits the SMALLER of
       available width and available height, so the numpad below is never pushed
       off-screen in landscape / short viewports. Chrome budget:
         var(--topnav-h) nav + ~80px game header + ~210px numpad + safe-area. */
    .grid-grid[b-3m1mc6p88i] {
        aspect-ratio: 1 / 1;
        width: min(
            calc(100vw - 1rem),
            calc(100dvh - var(--topnav-h, 3.5rem) - 80px - 210px - env(safe-area-inset-bottom, 0px))
        );
        max-width: 100%;
    }

    .grid-grid.with-headers[b-3m1mc6p88i] {
        max-width: 100%;
    }

    .numpad-section[b-3m1mc6p88i] {
        position: relative;
        flex-shrink: 0;
        padding: 0.2rem 0.5rem calc(env(safe-area-inset-bottom, 0px) + 40px + 0.2rem);
        border-top: 1px solid var(--glass-border);
        background: var(--bg-color);
    }

    .num-btn[b-3m1mc6p88i] {
        min-height: 2.6rem;
        font-size: 1.25rem;
        padding: 0.15rem 0;
        gap: 1px;
    }
}

/* === THE 641-767px BAND: mobile board sizing, but the sidebar is already in flow === */
/* MainLayout.razor.css switches .page to flex-direction: row with a var(--sidebar-w) STICKY
   sidebar at min-width: 641px, while the mobile rule above sizes .grid-grid off raw 100vw all the
   way until max-width: 767px. That is the same 127px dead band Span documents and fixes for its
   own board (SpanGame.razor.css, "THE 641-767px BAND", task 935): the sidebar is present but the
   game's mobile sizing does not know it. Grid never goes position:fixed (unlike Span), so it stays
   in normal flow — instead of the sidebar OCCLUDING the board, the mismatch shows up as flexbox
   shrinking the sidebar below its declared width to make room for a board sized for the FULL
   viewport (measured: sidebar squeezed to 161.9px instead of 250px, board overflowing the document
   by ~88px at 700px — task 937). Subtract the sidebar and the article's own horizontal padding
   (2rem + 1.5rem, applied at this same min-width:641px in MainLayout.razor.css) from the width
   budget so the board fits beside the REAL sidebar instead of the one it assumes. The extra 1rem
   past that 3.5rem is measured slack (border/rounding in the flex chain) — without it the sidebar
   still only recovered to 234px of its declared 250px; WITH it the sidebar measures exactly
   250.0px at 700px (verified via the harness, not derived on paper).
   var(--sidebar-w) / var(--topnav-h): app.css :root (task 939). If either literal moves, this must
   move with it. */
@media (min-width: 641px) and (max-width: 767px) {
    .grid-grid[b-3m1mc6p88i] {
        width: min(
            calc(100vw - var(--sidebar-w, 250px) - 4.5rem),
            calc(100dvh - var(--topnav-h, 3.5rem) - 80px - 210px - env(safe-area-inset-bottom, 0px))
        );
        max-width: 100%;
    }
}

/* Desktop: 3-column numpad, fixed width beside the board */
@media (min-width: 768px) {
    .numpad[b-3m1mc6p88i] {
        grid-template-columns: repeat(3, 1fr);
    }

    .numpad-section[b-3m1mc6p88i] {
        width: 300px;
    }
}

/* Region highlight — row, column, and 3×3 box of the selected cell */
.board-section .grid-cell.peer-cell:not(.active):not(.locked)[b-3m1mc6p88i] {
    background-color: var(--surface-hover);
}

.board-section .grid-cell.peer-cell.locked[b-3m1mc6p88i] {
    background-color: color-mix(in srgb, var(--surface-hover) 60%, var(--cell-bg) 40%);
}

/* User-entered pencil notes */
.grid-notes-grid[b-3m1mc6p88i] {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    grid-template-rows: repeat(3, 1fr);
    width: 100%;
    height: 100%;
    padding: 2px;
}

.grid-note-num[b-3m1mc6p88i] {
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.5rem;
    color: var(--accent-primary);
    line-height: 1;
    font-weight: 600;
}

.grid-note-num.empty[b-3m1mc6p88i] {
    visibility: hidden;
}

/* Win Overlay Styles */
.win-overlay[b-3m1mc6p88i] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
}

.win-card[b-3m1mc6p88i] {
    text-align: center;
    max-width: 450px;
    padding: 3rem 2rem;
    border: 1px solid rgba(255, 215, 0, 0.3);
    /* Gold tint */
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5), 0 0 20px rgba(255, 215, 0, 0.1);
}

.win-icon[b-3m1mc6p88i] {
    font-size: 4.5rem;
    color: var(--win-title-color);
    margin-bottom: 1rem;
    display: inline-block;
    filter: drop-shadow(0 0 10px rgba(255, 215, 0, 0.5));
}

.win-card h2[b-3m1mc6p88i] {
    font-size: 2.5rem;
    font-weight: 800;
    margin-bottom: 1rem;
    background: var(--win-title-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.win-card p[b-3m1mc6p88i] {
    font-size: 1.1rem;
    color: var(--text-secondary);
    margin-bottom: 2rem;
}

.win-actions[b-3m1mc6p88i] {
    display: flex;
    gap: 1rem;
    justify-content: center;
}

.animate-bounce-in[b-3m1mc6p88i] {
    animation: bounceIn-b-3m1mc6p88i 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.animate-fade-in[b-3m1mc6p88i] {
    animation: fadeIn-b-3m1mc6p88i 0.4s ease-out;
}

@keyframes bounceIn-b-3m1mc6p88i {
    0% {
        transform: scale(0.5);
        opacity: 0;
    }

    100% {
        transform: scale(1);
        opacity: 1;
    }
}

@keyframes fadeIn-b-3m1mc6p88i {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}
/* /Pages/GroupDashboard.razor.rz.scp.css */
/* Group Dashboard — uses design tokens only, no hardcoded colors */

.member-streak-badge[b-4yrnpsdg5s] {
    display: inline-block;
    margin-left: 0.4rem;
    font-size: 0.72rem;
    background: var(--color-info-soft);
    border-radius: 1rem;
    padding: 0.1rem 0.45rem;
    color: var(--text-primary);
    font-weight: 600;
    vertical-align: middle;
}

.dashboard-page[b-4yrnpsdg5s] {
    padding: 2.5rem;
    padding-bottom: 5rem;
    background-color: var(--bg-color);
    min-height: 100vh;
    color: var(--text-primary);
}

.glass-card[b-4yrnpsdg5s] {
    background: var(--glass-bg);
    backdrop-filter: blur(var(--glass-blur-lg));
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-lg);
    padding: 1.5rem;
    transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
    position: relative;
    overflow: hidden;
}

.glass-card:hover[b-4yrnpsdg5s] {
    border-color: var(--glass-border-bright);
    transform: translateY(-2px);
    box-shadow: 0 10px 30px -10px rgba(0, 0, 0, 0.4);
}

/* Header */
.dashboard-header[b-4yrnpsdg5s] {
    display: flex;
    justify-content: space-between;
    align-items: flex-end;
    margin-bottom: 3rem;
}

.header-info h1[b-4yrnpsdg5s] {
    font-size: 3rem;
    font-weight: 800;
    letter-spacing: -0.025em;
    margin: 0;
    color: var(--text-primary);
}

.badge-row[b-4yrnpsdg5s] {
    display: flex;
    gap: 0.75rem;
    margin-top: 0.5rem;
}

.bg-primary-soft[b-4yrnpsdg5s] {
    background: var(--color-info-soft);
    color: var(--color-info-text);
}

.bg-info-soft[b-4yrnpsdg5s] {
    background: var(--color-success-soft);
    color: var(--color-success-text);
}

.streak-badge[b-4yrnpsdg5s] {
    background: linear-gradient(135deg, rgba(251, 146, 60, 0.25), rgba(239, 68, 68, 0.2));
    color: #fb923c;
    border: 1px solid rgba(251, 146, 60, 0.4);
    font-weight: 700;
}

/* Grid Layout */
.content-mosaic[b-4yrnpsdg5s] {
    display: grid;
    grid-template-columns: repeat(12, 1fr);
    gap: 1.5rem;
    align-items: start;
}

.gen-card[b-4yrnpsdg5s] {
    grid-column: span 4;
}

.games-card[b-4yrnpsdg5s] {
    grid-column: span 5;
}

.members-card[b-4yrnpsdg5s] {
    grid-column: span 3;
}

.wide-card[b-4yrnpsdg5s] {
    grid-column: span 12;
    margin-top: 1.5rem;
}

.chat-card[b-4yrnpsdg5s] {
    min-height: 500px;
    padding: 0;
    display: flex;
    flex-direction: column;
}

.card-header-icon[b-4yrnpsdg5s] {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1.25rem;
}

.card-header-icon span[b-4yrnpsdg5s] {
    font-size: 1.5rem;
    color: var(--accent-primary);
}

.card-header-icon h3[b-4yrnpsdg5s] {
    margin: 0;
    font-size: 1.1rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    color: var(--text-primary);
}

.card-help[b-4yrnpsdg5s] {
    font-size: 0.85rem;
    color: var(--text-secondary);
    margin-bottom: 1.5rem;
}

/* Generation Buttons */
.gen-grid[b-4yrnpsdg5s] {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.625rem;
}

.gen-btn[b-4yrnpsdg5s] {
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
    border-radius: 0.75rem;
    padding: 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    text-align: left;
    color: var(--text-primary);
    transition: all 0.2s;
}

.gen-btn:hover:not(:disabled)[b-4yrnpsdg5s] {
    background: var(--color-info-soft);
    border-color: var(--accent-primary);
}

.gen-btn span.bi[b-4yrnpsdg5s] {
    font-size: 1.5rem;
    color: var(--accent-primary);
}

.btn-content[b-4yrnpsdg5s] {
    display: flex;
    flex-direction: column;
}

.btn-title[b-4yrnpsdg5s] {
    font-weight: 600;
    font-size: 1rem;
}

.btn-sub[b-4yrnpsdg5s] {
    font-size: 0.75rem;
    color: var(--text-secondary);
}

/* List Items */
.scroll-list[b-4yrnpsdg5s] {
    overflow-y: auto;
}

.lounge-item[b-4yrnpsdg5s] {
    display: flex;
    align-items: center;
    padding: 0.75rem 0;
    border-bottom: 1px solid var(--border-color);
    gap: 1rem;
}

.lounge-item:last-child[b-4yrnpsdg5s] {
    border-bottom: none;
}

.status-glow[b-4yrnpsdg5s] {
    width: 8px;
    height: 8px;
    border-radius: 50%;
    box-shadow: 0 0 10px currentColor;
}

.status-bronze[b-4yrnpsdg5s] {
    color: var(--rank-bronze);
    background: var(--rank-bronze);
}

.status-silver[b-4yrnpsdg5s] {
    color: var(--rank-silver);
    background: var(--rank-silver);
}

.status-blue[b-4yrnpsdg5s] {
    color: var(--badge-lex);
    background: var(--badge-lex);
}

.status-purple[b-4yrnpsdg5s] {
    color: var(--badge-grid);
    background: var(--badge-grid);
}

.status-red[b-4yrnpsdg5s] {
    color: var(--badge-span);
    background: var(--badge-span);
}

.status-diamond[b-4yrnpsdg5s] {
    color: var(--badge-lattice);
    background: var(--badge-lattice);
}

.status-gold[b-4yrnpsdg5s] {
    color: var(--badge-default);
    background: var(--badge-default);
}

.status-dimmed[b-4yrnpsdg5s] {
    color: var(--text-secondary);
    background: var(--text-secondary);
    opacity: 0.3;
    box-shadow: none;
}

.game-group-header[b-4yrnpsdg5s] {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin: 1rem 0 0.5rem;
    padding: 0.3rem 0.5rem;
    border-radius: var(--border-radius-sm);
    background: var(--glass-bg);
    border: 1px solid var(--glass-border);
}

.game-group-label[b-4yrnpsdg5s] {
    font-size: 0.75rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.06em;
    color: var(--text-primary);
}

.game-group-count[b-4yrnpsdg5s] {
    font-size: 0.72rem;
    font-weight: 600;
    color: var(--text-secondary);
}

.historical-divider[b-4yrnpsdg5s] {
    font-size: 0.65rem;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    font-weight: 600;
    color: var(--text-secondary);
    margin: 0.75rem 0 0.25rem 0.5rem;
}

.lounge-item-historical[b-4yrnpsdg5s] {
    opacity: 0.65;
}

.item-time[b-4yrnpsdg5s] {
    font-size: 0.75rem;
    color: var(--text-secondary);
    margin-left: 0.4rem;
}

.completion-row[b-4yrnpsdg5s] {
    display: flex;
    align-items: center;
    gap: 0.25rem;
    margin-top: 0.3rem;
    flex-wrap: wrap;
}

.completer-avatar[b-4yrnpsdg5s] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 20px;
    height: 20px;
    border-radius: 50%;
    background: var(--accent-primary);
    color: white;
    font-size: 0.65rem;
    font-weight: 700;
}

.completion-count[b-4yrnpsdg5s] {
    font-size: 0.72rem;
    color: var(--text-secondary);
    margin-left: 0.15rem;
}

.pulse-load-older[b-4yrnpsdg5s] {
    color: var(--text-secondary);
}

.item-info[b-4yrnpsdg5s] {
    flex-grow: 1;
    display: flex;
    flex-direction: column;
}

.item-name[b-4yrnpsdg5s] {
    font-weight: 600;
    font-size: 0.95rem;
}

.puzzle-number[b-4yrnpsdg5s] {
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--accent-primary);
    margin-right: 0.35rem;
    opacity: 0.8;
}

.item-status[b-4yrnpsdg5s] {
    font-size: 0.75rem;
    color: var(--text-secondary);
}

.member-item .avatar-small[b-4yrnpsdg5s] {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: var(--accent-primary);
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.75rem;
    color: white;
}

.member-label[b-4yrnpsdg5s] {
    font-size: 0.9rem;
    font-weight: 500;
}

/* Status Messages */
.status-msg[b-4yrnpsdg5s] {
    margin-top: 1rem;
    padding: 0.75rem;
    border-radius: 0.5rem;
    font-size: 1rem;
    display: flex;
    align-items: center;
}

.msg-info[b-4yrnpsdg5s] {
    background: var(--color-info-soft);
    color: var(--color-info-text);
}

.msg-success[b-4yrnpsdg5s] {
    background: var(--color-success-soft);
    color: var(--color-success-text);
}

.msg-error[b-4yrnpsdg5s] {
    background: var(--color-error-soft);
    color: var(--color-error-text);
}

/* Modal */
.modal-overlay[b-4yrnpsdg5s] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(var(--glass-blur-sm));
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 1000;
}

.modal-card[b-4yrnpsdg5s] {
    width: 100%;
    max-width: 400px;
}

.glass-input[b-4yrnpsdg5s],
.glass-select[b-4yrnpsdg5s] {
    background: var(--glass-input-bg);
    border: 1px solid var(--glass-border);
    color: var(--text-primary);
}

.glass-input[b-4yrnpsdg5s] {
    padding: 0.75rem 1rem;
}

.glass-select[b-4yrnpsdg5s] {
    padding: 0.25rem 2rem 0.25rem 0.5rem;
    font-size: 0.8rem;
}

.glass-select option[b-4yrnpsdg5s] {
    background: var(--surface-color);
    color: var(--text-primary);
}

.glass-input:focus[b-4yrnpsdg5s],
.glass-select:focus[b-4yrnpsdg5s] {
    background: var(--glass-input-focus);
    border-color: var(--accent-primary);
    box-shadow: none;
    color: var(--text-primary);
}

.btn-glass[b-4yrnpsdg5s] {
    background: var(--glass-input-bg);
    border: 1px solid var(--glass-border);
    color: var(--text-primary);
    backdrop-filter: blur(var(--glass-blur-md));
}

.btn-glass:hover[b-4yrnpsdg5s] {
    background: var(--glass-input-focus);
    border-color: var(--glass-border-bright);
    color: var(--text-primary);
}

/* Animations */
.animate-fade-in[b-4yrnpsdg5s] {
    animation: fadeIn-b-4yrnpsdg5s 0.6s ease-out;
}

.animate-slide-up[b-4yrnpsdg5s] {
    animation: slideUp-b-4yrnpsdg5s 0.8s ease-out;
}

.animate-pulse[b-4yrnpsdg5s] {
    animation: pulse-b-4yrnpsdg5s 2s infinite;
}

.animate-scale[b-4yrnpsdg5s] {
    animation: scaleIn-b-4yrnpsdg5s 0.3s ease-out;
}

@keyframes fadeIn-b-4yrnpsdg5s {
    from {
        opacity: 0;
    }

    to {
        opacity: 1;
    }
}

@keyframes slideUp-b-4yrnpsdg5s {
    from {
        opacity: 0;
        transform: translateY(20px);
    }

    to {
        opacity: 1;
        transform: translateY(0);
    }
}

@keyframes pulse-b-4yrnpsdg5s {

    0%,
    100% {
        opacity: 1;
    }

    50% {
        opacity: 0.7;
    }
}

@keyframes scaleIn-b-4yrnpsdg5s {
    from {
        opacity: 0;
        transform: scale(0.95);
    }

    to {
        opacity: 1;
        transform: scale(1);
    }
}

/* Skeleton Placeholder */
.skeleton-row[b-4yrnpsdg5s] {
    height: 12px;
    background: var(--surface-hover);
    margin-bottom: 1rem;
    border-radius: 4px;
    width: 80%;
}

.skeleton-row:nth-child(2)[b-4yrnpsdg5s] {
    width: 60%;
}

.skeleton-row:nth-child(3)[b-4yrnpsdg5s] {
    width: 70%;
}

/* Error / Loading states */
.error-container[b-4yrnpsdg5s],
.loading-overlay[b-4yrnpsdg5s] {
    display: flex;
    align-items: center;
    justify-content: center;
    min-height: 100vh;
}

.loading-overlay[b-4yrnpsdg5s] {
    flex-direction: column;
}

.error-card[b-4yrnpsdg5s] {
    text-align: center;
    max-width: 500px;
}

.error-icon[b-4yrnpsdg5s] {
    font-size: 4rem;
    color: var(--color-error);
    margin-bottom: 1.5rem;
}

/* Theme Manager — full-width panel above the mosaic */
.theme-manager[b-4yrnpsdg5s] {
    margin-bottom: 1.5rem;
}

.theme-gallery[b-4yrnpsdg5s] {
    display: flex;
    flex-wrap: wrap;
    gap: 1rem;
}

.theme-item[b-4yrnpsdg5s] {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    cursor: pointer;
    border: 2px solid transparent;
    border-radius: var(--border-radius-lg);
    padding: 0.5rem;
    transition: border-color 0.2s;
    width: 140px;
}

.theme-item:hover[b-4yrnpsdg5s] {
    border-color: var(--glass-border-bright);
}

.theme-item.active[b-4yrnpsdg5s] {
    border-color: var(--accent-primary);
}

.theme-preview[b-4yrnpsdg5s] {
    width: 100%;
    height: 72px;
    border-radius: 0.5rem;
    position: relative;
    overflow: hidden;
}

.accent-stripe[b-4yrnpsdg5s] {
    position: absolute;
    left: 0;
    top: 0;
    bottom: 0;
    width: 6px;
}

.surface-preview[b-4yrnpsdg5s] {
    position: absolute;
    right: 8px;
    top: 50%;
    transform: translateY(-50%);
    width: 60%;
    height: 40%;
    border-radius: 4px;
    opacity: 0.8;
}

.theme-info[b-4yrnpsdg5s] {
    display: flex;
    flex-direction: column;
    gap: 0.2rem;
}

.theme-name[b-4yrnpsdg5s] {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-primary);
}

.theme-meta[b-4yrnpsdg5s] {
    display: flex;
    align-items: center;
    gap: 0.25rem;
}

.small-badge[b-4yrnpsdg5s] {
    font-size: 0.65rem;
    padding: 0.1rem 0.4rem;
}

/* Mobile */
@media (max-width: 768px) {
    .dashboard-page[b-4yrnpsdg5s] {
        padding: 1rem;
    }

    .dashboard-header[b-4yrnpsdg5s] {
        flex-direction: column;
        align-items: flex-start;
        gap: 1rem;
        margin-bottom: 1.5rem;
    }

    .header-info h1[b-4yrnpsdg5s] {
        font-size: 1.75rem;
    }

    .header-actions[b-4yrnpsdg5s] {
        width: 100%;
        flex-wrap: wrap;
    }

    .header-actions .btn[b-4yrnpsdg5s] {
        flex: 1 1 calc(50% - 0.25rem);
        font-size: 0.8rem;
        padding: 0.4rem 0.6rem;
        white-space: nowrap;
        overflow: hidden;
        text-overflow: ellipsis;
    }

    .content-mosaic[b-4yrnpsdg5s] {
        grid-template-columns: 1fr;
        gap: 1rem;
    }

    .gen-card[b-4yrnpsdg5s],
    .games-card[b-4yrnpsdg5s],
    .members-card[b-4yrnpsdg5s],
    .wide-card[b-4yrnpsdg5s] {
        grid-column: span 1;
    }

    .wide-card[b-4yrnpsdg5s] {
        margin-top: 0;
    }

    .scroll-list[b-4yrnpsdg5s] {
        max-height: none;
    }

    .chat-card[b-4yrnpsdg5s] {
        min-height: 400px;
    }

    .modal-card[b-4yrnpsdg5s] {
        margin: 1rem;
        max-width: calc(100vw - 2rem);
    }
}
/* /Pages/Home.razor.rz.scp.css */
/* ── Coming Soon Banner ───────────────────────────────── */
.coming-soon-banner[b-tvjru1qawt] {
    background: linear-gradient(90deg, rgba(168, 85, 247, 0.15), rgba(59, 130, 246, 0.15));
    border-bottom: 1px solid rgba(168, 85, 247, 0.3);
    color: var(--text-primary);
    text-align: center;
    padding: 0.6rem 1rem;
    font-size: 0.9rem;
    font-family: var(--font-body);
}

/* ── Hero ─────────────────────────────────────────────── */
.hero[b-tvjru1qawt] {
    min-height: 85vh;
    display: flex;
    align-items: center;
    justify-content: center;
    text-align: center;
    padding: 4rem 2rem;
    background:
        radial-gradient(ellipse at 60% 40%, rgba(59, 130, 246, 0.12) 0%, transparent 60%),
        radial-gradient(ellipse at 20% 80%, rgba(168, 85, 247, 0.08) 0%, transparent 50%);
}

.hero-content[b-tvjru1qawt] {
    max-width: 720px;
}

.hero-headline[b-tvjru1qawt] {
    font-family: var(--font-heading);
    font-size: clamp(2.8rem, 7vw, 5rem);
    font-weight: 900;
    line-height: 1.1;
    letter-spacing: -0.03em;
    margin-bottom: 1.5rem;
    background: linear-gradient(135deg, #f8fafc 40%, #93c5fd 100%);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.hero-sub[b-tvjru1qawt] {
    font-size: clamp(1rem, 2.5vw, 1.25rem);
    color: var(--text-secondary);
    line-height: 1.7;
    margin-bottom: 2.5rem;
    max-width: 560px;
    margin-left: auto;
    margin-right: auto;
}

.hero-actions[b-tvjru1qawt] {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
}

/* ── Section shared ───────────────────────────────────── */
.section-title[b-tvjru1qawt] {
    font-family: var(--font-heading);
    font-size: clamp(1.5rem, 3vw, 2rem);
    font-weight: 800;
    text-align: center;
    margin-bottom: 0.75rem;
    color: var(--text-primary);
}

.section-sub[b-tvjru1qawt] {
    text-align: center;
    color: var(--text-secondary);
    margin-bottom: 2.5rem;
    font-size: 1rem;
}

/* ── Pillars ──────────────────────────────────────────── */
.pillars[b-tvjru1qawt] {
    padding: 5rem 2rem;
    background: var(--glass-bg);
    border-top: 1px solid var(--glass-border);
    border-bottom: 1px solid var(--glass-border);
}

.pillar-grid[b-tvjru1qawt] {
    display: flex;
    flex-wrap: wrap;
    gap: 1.5rem;
    justify-content: center;
    max-width: 1000px;
    margin: 0 auto;
}

.pillar-card[b-tvjru1qawt] {
    background: var(--surface-color);
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-lg);
    padding: 2rem 1.75rem;
    flex: 1 1 260px;
    max-width: 320px;
    transition: border-color 0.2s, transform 0.2s;
}

.pillar-card:hover[b-tvjru1qawt] {
    border-color: var(--glass-border-bright);
    transform: translateY(-2px);
}

.pillar-icon[b-tvjru1qawt] {
    font-size: 2.5rem;
    display: block;
    margin-bottom: 1rem;
}

.pillar-card h3[b-tvjru1qawt] {
    font-family: var(--font-heading);
    font-size: 1.1rem;
    font-weight: 700;
    margin-bottom: 0.75rem;
    color: var(--text-primary);
}

.pillar-card p[b-tvjru1qawt] {
    font-size: 0.9rem;
    color: var(--text-secondary);
    line-height: 1.65;
    margin: 0;
}

/* ── Games ────────────────────────────────────────────── */
.games[b-tvjru1qawt] {
    padding: 5rem 2rem;
}

.game-grid[b-tvjru1qawt] {
    display: flex;
    flex-wrap: wrap;
    gap: 1.25rem;
    justify-content: center;
    max-width: 900px;
    margin: 0 auto;
}

.game-card[b-tvjru1qawt] {
    display: flex;
    align-items: center;
    gap: 1rem;
    background: var(--surface-color);
    border: 1px solid var(--glass-border);
    border-left: 4px solid var(--game-color, var(--accent-primary));
    border-radius: var(--border-radius-lg);
    padding: 1.25rem 1.5rem;
    flex: 1 1 260px;
    max-width: 400px;
    text-decoration: none;
    color: var(--text-primary);
    transition: border-color 0.2s, transform 0.2s, box-shadow 0.2s;
}

.game-card:hover[b-tvjru1qawt] {
    border-color: var(--game-color, var(--accent-primary));
    transform: translateY(-2px);
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.3);
    color: var(--text-primary);
    text-decoration: none;
}

.game-icon[b-tvjru1qawt] {
    font-size: 2rem;
    flex-shrink: 0;
}

.game-info[b-tvjru1qawt] {
    display: flex;
    flex-direction: column;
    flex: 1;
    gap: 0.2rem;
}

.game-name[b-tvjru1qawt] {
    font-family: var(--font-heading);
    font-weight: 700;
    font-size: 1.1rem;
    color: var(--game-color, var(--accent-primary));
}

.game-tagline[b-tvjru1qawt] {
    font-size: 0.82rem;
    color: var(--text-secondary);
}

.game-cta[b-tvjru1qawt] {
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--game-color, var(--accent-primary));
    white-space: nowrap;
    flex-shrink: 0;
}

/* ── Footer ───────────────────────────────────────────── */
.public-footer[b-tvjru1qawt] {
    text-align: center;
    padding: 2rem;
    border-top: 1px solid var(--glass-border);
    color: var(--text-secondary);
    font-size: 0.8rem;
}

.version-footer-public[b-tvjru1qawt] {
    margin-top: 0.25rem;
    font-size: 0.7rem;
    opacity: 0.5;
    font-family: monospace;
}

/* ── Mobile ───────────────────────────────────────────── */
@media (max-width: 600px) {
    .hero[b-tvjru1qawt] {
        min-height: 70vh;
        padding: 3rem 1.25rem;
    }

    .pillars[b-tvjru1qawt],
    .games[b-tvjru1qawt] {
        padding: 3rem 1.25rem;
    }

    .pillar-card[b-tvjru1qawt],
    .game-card[b-tvjru1qawt] {
        max-width: 100%;
    }
}
/* /Pages/LatticeGame.razor.rz.scp.css */
/* ==============================================================
   THEME PALETTES (Lattice Correctness Theme)
   ============================================================== */
.ws-board-container.wf-theme-classic[b-solun4hkwj] {
    /* Classic inherits from the group theme's accent color */
    --local-active-bg: var(--ws-cell-active-bg);
    --local-active-text: var(--ws-cell-active-text);
    --local-found-bg: var(--accent-primary);
    --local-found-text: var(--ws-cell-found-text);
    --local-active-border: var(--ws-cell-active-bg);
    --local-found-border: var(--accent-primary);
    --local-found-shadow: none;
}

.ws-board-container.wf-theme-neon[b-solun4hkwj] {
    --local-active-bg: transparent;
    --local-active-text: #38bdf8;
    --local-active-border: #38bdf8;
    --local-found-bg: rgba(240, 171, 252, 0.25);
    --local-found-text: #f0abfc;
    --local-found-border: #f0abfc;
    --local-active-shadow: 0 0 10px rgba(56, 189, 248, 0.6), inset 0 0 10px rgba(56, 189, 248, 0.6);
    --local-found-shadow: 0 0 10px rgba(240, 171, 252, 0.6), inset 0 0 10px rgba(240, 171, 252, 0.6);
}

.ws-board-container.wf-theme-shapes[b-solun4hkwj] {
    --local-active-bg: #fb923c;
    --local-active-text: var(--bg-color);
    --local-active-border: #fb923c;
    --local-found-bg: #4ade80;
    --local-found-text: var(--bg-color);
    --local-found-border: #4ade80;
}

.ws-board-container.wf-theme-kinetic[b-solun4hkwj] {
    --local-active-bg: transparent;
    --local-active-text: #a855f7;
    --local-active-border: transparent;
    --local-found-bg: rgba(34, 197, 94, 0.3);
    --local-found-text: #22c55e;
    --local-found-border: transparent;
    --local-active-shadow: none;
    --local-found-shadow: none;
}

.ws-board-container.wf-theme-spectral[b-solun4hkwj] {
    --local-active-bg: transparent;
    --local-active-text: #f472b6;
    --local-active-border: transparent;
    --local-found-bg: rgba(96, 165, 250, 0.3);
    --local-found-text: #60a5fa;
    --local-found-border: transparent;
    --local-active-shadow: 0 0 15px #f472b6;
    --local-found-shadow: 0 0 15px #60a5fa;
}

[b-solun4hkwj] .ws-board-container .ws-cell.active {
    background: var(--local-active-bg, var(--ws-cell-active-bg)) !important;
    color: var(--local-active-text, var(--ws-cell-active-text)) !important;
    border-color: var(--local-active-border, var(--ws-cell-active-bg)) !important;
    box-shadow: var(--local-active-shadow, none) !important;
}

[b-solun4hkwj] .ws-board-container .ws-cell.found {
    background: var(--local-found-bg, var(--ws-cell-found-bg)) !important;
    color: var(--local-found-text, var(--ws-cell-found-text)) !important;
    border-color: var(--local-found-border, var(--ws-cell-found-bg)) !important;
    box-shadow:
        var(--gap-n, 0 0 0 0 transparent),
        var(--gap-s, 0 0 0 0 transparent),
        var(--gap-e, 0 0 0 0 transparent),
        var(--gap-w, 0 0 0 0 transparent),
        var(--local-found-shadow, none) !important;
    position: relative;
    z-index: 5; /* Sit above the grid lines */

    border-radius: 6px;
}

/* Directional connection rendering */
[b-solun4hkwj] .ws-board-container .ws-cell.found {
    /* Seamless Border Removal */
    border-top: calc(1px * (1 - var(--conn-n, 0))) solid var(--local-found-border, var(--ws-cell-found-bg)) !important;
    border-bottom: calc(1px * (1 - var(--conn-s, 0))) solid var(--local-found-border, var(--ws-cell-found-bg)) !important;
    border-right: calc(1px * (1 - var(--conn-e, 0))) solid var(--local-found-border, var(--ws-cell-found-bg)) !important;
    border-left: calc(1px * (1 - var(--conn-w, 0))) solid var(--local-found-border, var(--ws-cell-found-bg)) !important;

    /* Gap fill via box-shadow — extends color into the 4px grid gap without affecting cell layout size */
    --gap-fill: var(--local-found-bg, var(--ws-cell-found-bg));
    --gap-n: 0 calc(var(--conn-n, 0) * -4px) 0 0 var(--gap-fill);
    --gap-s: 0 calc(var(--conn-s, 0) * 4px) 0 0 var(--gap-fill);
    --gap-e: calc(var(--conn-e, 0) * 4px) 0 0 0 var(--gap-fill);
    --gap-w: calc(var(--conn-w, 0) * -4px) 0 0 0 var(--gap-fill);

    /* Standard Glow logic: composite shadows based on connections */
    --shadow-n: calc(var(--conn-n, 0) * 0) calc(var(--conn-n, 0) * -10px) 15px var(--local-found-shadow-color, rgba(0,0,0,0));
    --shadow-s: calc(var(--conn-s, 0) * 0) calc(var(--conn-s, 0) * 10px) 15px var(--local-found-shadow-color, rgba(0,0,0,0));
    --shadow-e: calc(var(--conn-e, 0) * 10px) 0 15px var(--local-found-shadow-color, rgba(0,0,0,0));
    --shadow-w: calc(var(--conn-w, 0) * -10px) 0 15px var(--local-found-shadow-color, rgba(0,0,0,0));
}

/* Diagonal connectors using pseudo-elements */
[b-solun4hkwj] .ws-board-container .ws-cell.found::after {
    content: '';
    position: absolute;
    background: inherit;
    z-index: -1;
    pointer-events: none;
}

/* NE Bridge */
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-ne: 1"]::after {
    width: 12px;
    height: 12px;
    top: -6px;
    right: -6px;
    transform: rotate(45deg);
    display: block;
}
/* SE Bridge */
/* Note: We only need one cell in the connection to draw the bridge */
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-se: 1"]::after {
    width: 12px;
    height: 12px;
    bottom: -6px;
    right: -6px;
    transform: rotate(45deg);
    display: block;
}

.ws-board-container.wf-theme-neon .ws-cell.found[b-solun4hkwj],
.ws-board-container.wf-theme-spectral .ws-cell.found[b-solun4hkwj] {
    --local-found-shadow-color: inherit;
    box-shadow:
        var(--gap-n, 0 0 0 0 transparent),
        var(--gap-s, 0 0 0 0 transparent),
        var(--gap-e, 0 0 0 0 transparent),
        var(--gap-w, 0 0 0 0 transparent),
        var(--shadow-n), var(--shadow-s), var(--shadow-e), var(--shadow-w) !important;
}

/* Corner radius removal — cardinal */
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-n: 1"] { border-top-left-radius: 0; border-top-right-radius: 0; }
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-s: 1"] { border-bottom-left-radius: 0; border-bottom-right-radius: 0; }
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-e: 1"] { border-top-right-radius: 0; border-bottom-right-radius: 0; }
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-w: 1"] { border-top-left-radius: 0; border-bottom-left-radius: 0; }
/* Corner radius removal — diagonal */
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-ne: 1"] { border-top-right-radius: 0; }
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-se: 1"] { border-bottom-right-radius: 0; }
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-sw: 1"] { border-bottom-left-radius: 0; }
[b-solun4hkwj] .ws-board-container .ws-cell.found[style*="--conn-nw: 1"] { border-top-left-radius: 0; }

/* Structural Theme Overrides */
[b-solun4hkwj] .ws-board-container.wf-theme-shapes .ws-cell {
    border-radius: 4px;
}

[b-solun4hkwj] .ws-board-container.wf-theme-shapes .ws-cell.active {
    border-radius: 50%;
    transform: scale(0.9);
}

[b-solun4hkwj] .ws-board-container.wf-theme-shapes .ws-cell.found {
    border-width: 2px !important;
}

@keyframes neonFlickerWs-b-solun4hkwj {

    0%,
    19%,
    21%,
    23%,
    25%,
    54%,
    56%,
    100% {
        opacity: 1;
        text-shadow: 0 0 8px #22c55e;
    }

    20%,
    24%,
    55% {
        opacity: 0.5;
        text-shadow: none;
    }
}

[b-solun4hkwj] .ws-board-container.wf-theme-kinetic .ws-cell.found {
    animation: neonFlickerWs-b-solun4hkwj 3s infinite alternate;
}

@keyframes glitchShakeWs-b-solun4hkwj {
    0% {
        transform: translate(0)
    }

    20% {
        transform: translate(-2px, 2px)
    }

    40% {
        transform: translate(-2px, -2px)
    }

    60% {
        transform: translate(2px, 2px)
    }

    80% {
        transform: translate(2px, -2px)
    }

    100% {
        transform: translate(0)
    }
}

[b-solun4hkwj] .ws-board-container.wf-theme-kinetic .ws-cell.active {
    animation: glitchShakeWs-b-solun4hkwj 0.4s infinite;
}

/* === MOBILE: compact header, board scrolls within fixed viewport === */
/* Task 1401: the second clause, `(max-height: 500px)`, is new — see the identical reasoning in
   SpanGame.razor.css's mobile block. `.app-container`'s BASE rule (app.css) is `height: 100vh`,
   which does not know it sits below the 56px `.top-row` (MainLayout), so at any width past 767px
   it claims 56px more than the space that is actually left, however tall the viewport is. Below
   767px wide the override two lines down corrects it; above 767px wide it never fired at all —
   including on a short/landscape viewport (Kris's reported 896x443), which is exactly the gap
   task 1106 named. 500px matches the threshold chosen for Span for the same reasons (see there). */
@media (max-width: 767px), (max-height: 500px) {
    /* Lattice is DELIBERATELY NOT given a --float-zone-h reservation (task 1129), and the reason is
       measured. It was the one game with ZERO control coverage at every width and height swept, so
       it has nothing to fix — and applying the reservation anyway made it strictly worse: because
       this container is `overflow: hidden`, shrinking it does not shrink the board, it CLIPS it.
       Measured at 443x660 the clipped-out-of-view cell count went from 12 to 34. Trading a
       non-existent occlusion for 22 unreachable cells is not a fix. See app.css. */
    .app-container[b-solun4hkwj] {
        height: calc(100dvh - var(--topnav-h, 3.5rem));
        overflow: hidden;
    }

    header[b-solun4hkwj] {
        padding: 0.35rem 0.75rem;
        gap: 0.25rem;
    }

    header h1[b-solun4hkwj] {
        font-size: 1rem;
    }

    [b-solun4hkwj] .toolbar-actions {
        gap: 0.4rem;
        flex-wrap: nowrap;
        overflow-x: auto;
    }

    [b-solun4hkwj] .btn-primary,
    [b-solun4hkwj] .form-select,
    [b-solun4hkwj] .btn-sm {
        font-size: 0.75rem;
        padding: 0.2rem 0.45rem;
    }

    /* Board section scrolls within the remaining space */
    .ws-board-container[b-solun4hkwj] {
        flex: 1;
        min-height: 0;
        overflow-y: auto;
    }
}

/* === THE 641-767px BAND: no longer needs a special case (task 1028) ===
   This block used to define --ws-avail-w as `calc(100vw - var(--sidebar-w) - 3.5rem)` for exactly
   this band, restating the sidebar width and article's horizontal padding so the C# CellSize
   formula could subtract them (task 937). Both the formula and the token are gone: .ws-grid is
   `width: 100%` of its real container, so the sidebar and every ancestor's padding are already
   accounted for by layout at EVERY width — including 768px and up, where the old token silently
   fell back to raw 100vw and the sidebar was not subtracted at all. There is nothing left to
   restate, so there is nothing left to drift. */
/* /Pages/LexGame.razor.rz.scp.css */
/* ==============================================================
   LEX LAYOUT TOKENS (task 1073)
   ==============================================================
   The one place the row's size budget is written down. Memory
   coterie-display-layer-truth-2026-07-16's structural finding was that this codebase has "no
   shared sizing model — there are four", and that "layout tokens essentially don't exist" while
   colour tokens are well done. These are Lex's; they are not a general solution, but they mean
   Lex's budget now has a single owner instead of being spread across three stylesheets.

   --wf-cols is overridden per-board by LexGame.razor (the target word length). The value here is
   only a fallback so the glyph rule cannot divide by zero if the markup ever stops emitting it. */
.wf-board-container[b-qqye1xt2m0] {
    --wf-cols: 5;
    --wf-gap: 8px;
    --wf-cell-max: 3.5rem;
    --wf-font-max: 2rem;

    /* Row chrome: the fixed-width furniture flanking the cells. Sums to ~80px in free play and
       ~136px in group mode (which adds .wf-row-solvers), against a 342-395px usable width on a
       390-443px phone — so at 10 letters the chrome alone was eating a third of the budget. */
    --wf-row-lead: 24px;      /* .wf-row-container::before, a centring counterweight */
    --wf-meter-w: 24px;       /* .spectral-meter-container */
    --wf-solvers-w: 40px;     /* .wf-row-solvers, group mode only */
    --wf-row-chrome-gap: 1rem;
}

/* Win/Loss Overlay Styles */
.win-overlay[b-qqye1xt2m0] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
}

.glass-card[b-qqye1xt2m0] {
    background: rgba(255, 255, 255, 0.03);
    backdrop-filter: blur(12px);
    border-radius: 1.25rem;
}

.win-card[b-qqye1xt2m0] {
    text-align: center;
    max-width: 450px;
    padding: 3rem 2rem;
    border: 1px solid rgba(255, 215, 0, 0.3);
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5), 0 0 20px rgba(255, 215, 0, 0.1);
}

.win-icon[b-qqye1xt2m0] {
    font-size: 4.5rem;
    color: var(--win-title-color);
    margin-bottom: 1rem;
    display: inline-block;
    filter: drop-shadow(0 0 10px rgba(255, 215, 0, 0.5));
}

.win-card h2[b-qqye1xt2m0] {
    font-size: 2.5rem;
    font-weight: 800;
    margin-bottom: 1rem;
    background: var(--win-title-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.win-card p[b-qqye1xt2m0] {
    font-size: 1.1rem;
    color: var(--text-secondary);
    margin-bottom: 2rem;
}

.win-actions[b-qqye1xt2m0] {
    display: flex;
    gap: 1rem;
    justify-content: center;
    flex-wrap: wrap;
}

.win-actions button[b-qqye1xt2m0] {
    white-space: nowrap;
}

.animate-bounce-in[b-qqye1xt2m0] {
    animation: bounceIn-b-qqye1xt2m0 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.animate-fade-in[b-qqye1xt2m0] {
    animation: fadeIn-b-qqye1xt2m0 0.4s ease-out;
}

@keyframes bounceIn-b-qqye1xt2m0 {
    0% {
        transform: scale(0.5);
        opacity: 0;
    }

    100% {
        transform: scale(1);
        opacity: 1;
    }
}

@keyframes fadeIn-b-qqye1xt2m0 {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}

/* Toast Notification */
.wf-toast[b-qqye1xt2m0] {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: var(--surface-color);
    color: var(--text-primary);
    padding: 1rem 2rem;
    border-radius: var(--border-radius-lg);
    font-size: 1.25rem;
    font-weight: 700;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.6);
    border: 2px solid var(--border-color);
    z-index: 9999;
    pointer-events: none;
    animation: toastFadeInOut-b-qqye1xt2m0 2s ease-in-out forwards;
}

@keyframes toastFadeInOut-b-qqye1xt2m0 {
    0% {
        opacity: 0;
        transform: translate(-50%, calc(-50% - 20px));
    }

    15% {
        opacity: 1;
        transform: translate(-50%, -50%);
    }

    85% {
        opacity: 1;
        transform: translate(-50%, -50%);
    }

    100% {
        opacity: 0;
        transform: translate(-50%, calc(-50% + 20px));
    }
}

/* Ghost Rows / Peer Progress */
.wf-row-container[b-qqye1xt2m0] {
    display: flex;
    align-items: center;
    gap: var(--wf-row-chrome-gap);
    position: relative;
    width: 100%;
    justify-content: center;
    /* Without this the container refuses to be narrower than its content's max-content width, and
       the cells' flex-shrink never gets a chance to fire. */
    min-width: 0;
}

.wf-row-container[b-qqye1xt2m0]::before {
    content: '';
    width: var(--wf-row-lead);
    flex-shrink: 0;
}

.spectral-meter-container[b-qqye1xt2m0] {
    display: flex;
    width: var(--wf-meter-w);
    flex-shrink: 0;
    height: 100%;
    align-items: center;
    justify-content: center;
    opacity: 0;
    transition: opacity 0.5s ease;
}

.spectral-meter[b-qqye1xt2m0] {
    width: 8px;
    height: 100%;
    max-height: 3.5rem;
    background: rgba(255, 255, 255, 0.05);
    border-radius: 4px;
    position: relative;
    overflow: hidden;
    box-shadow: inset 0 0 5px rgba(0, 0, 0, 0.5);
}

.spectral-meter-fill[b-qqye1xt2m0] {
    position: absolute;
    bottom: 0;
    left: 0;
    width: 100%;
    transition: height 0.8s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    border-radius: 4px;
    background: transparent;
    box-shadow: 0 0 10px transparent;
}

/* FIXED width, not min-width, and that difference is load-bearing (task 1073).
   The peer-avatar column is per-row: row 3 might have three finishers and row 4 none. With
   `min-width` the column GREW to fit its avatars, so rows on the same board carried different
   amounts of fixed chrome — and since the cells divide whatever is left, THE SAME BOARD RENDERED
   ROWS WITH DIFFERENT CELL WIDTHS. Pinning the width makes every row's chrome identical, so a
   board's columns line up regardless of who finished where. Asserted by LexRowFitTests'
   equal-cell-widths case, which injects avatars into some rows and not others. */
.wf-row-solvers[b-qqye1xt2m0] {
    display: flex;
    flex-wrap: nowrap;
    width: var(--wf-solvers-w);
    /* `min-width: 0` IS REQUIRED, and `width` alone does not work — measured. A flex item's default
       `min-width: auto` is the AUTOMATIC MINIMUM SIZE: it refuses to be narrower than its own
       min-content, which for three 28px avatars is ~68px. So `width: 40px` was silently ignored and
       the column still grew, producing exactly the ragged board this rule exists to prevent. The
       first attempt at this fix changed min-width to width, re-ran, and got byte-identical numbers
       to the broken version — the test caught a fix that had not actually fixed anything. */
    min-width: 0;
    flex-shrink: 0;
    height: 32px;
    align-items: center;
    /* Extra finishers overlap into the stack rather than widening the column or spilling out. */
    overflow: hidden;
}

/* The real "slight overlap". This was written as `gap: -8px`, which is INVALID CSS — gap rejects
   negative values, so the declaration was dropped and computed to 0. The comment described an
   effect that had never existed. Negative margin is how an overlapping avatar stack is actually
   done, and with the fixed width above it is what lets more than one finisher fit. */
.wf-row-solvers > * + *[b-qqye1xt2m0] {
    margin-left: -8px;
}

.user-avatar[b-qqye1xt2m0],
.peer-avatar[b-qqye1xt2m0] {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.7rem;
    font-weight: 700;
    color: white;
    cursor: help;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.4);
    border: 2px solid var(--wf-key-border);
    transition: transform 0.2s, z-index 0.2s;
    user-select: none;
    flex-shrink: 0;
}

.user-avatar:hover[b-qqye1xt2m0],
.peer-avatar:hover[b-qqye1xt2m0] {
    transform: scale(1.2);
    z-index: 50;
}

.user-avatar[b-qqye1xt2m0] {
    background: var(--wf-enter-bg);
    margin-left: 0;
}

.peer-avatar[b-qqye1xt2m0] {
    background: var(--wf-enter-disabled-bg);
    margin-left: -8px;
    /* Overlap */
}

.peer-avatar.is-viewing[b-qqye1xt2m0] {
    border: 2px solid var(--accent-primary) !important;
    box-shadow: 0 0 15px var(--accent-primary) !important;
    transform: scale(1.2) !important;
    z-index: 100;
}

.peer-avatar.clickable[b-qqye1xt2m0] {

    cursor: pointer;
    border-color: var(--accent-primary);
    box-shadow: 0 0 10px var(--accent-glow);
}

.avatar-img[b-qqye1xt2m0] {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    object-fit: cover;
}

.peer-avatar.failed[b-qqye1xt2m0] {
    border-color: #ef4444;
    position: relative;
    filter: grayscale(0.2);
}

.fail-indicator[b-qqye1xt2m0] {
    position: absolute;
    top: -4px;
    right: -4px;
    background: #ef4444;
    color: white;
    font-size: 0.6rem;
    width: 14px;
    height: 14px;
    border-radius: 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 5px rgba(239, 68, 68, 0.5);
    z-index: 5;
    border: 1px solid white;
}

/* ==============================================================
   ROW SIZING — THE SHRINK-TO-FIT CONTRACT (task 1073)
   ==============================================================
   Kris, on a 443px phone with the 7-letter word ABOUNDS: "I can't see the 1st box and I have to
   scroll. it should be shrinking to fit." The row was wider than the viewport and the leading
   column was clipped away, so a 7-letter board rendered as a plausible 6-letter one.

   MEASURED BEFORE THE FIX (LexRowFitTests, Chromium mobile emulation):
     10 letters @ 443px -> cells span [-94.5 .. 537.5], only 6 of 10 columns visible
      9 letters @ 443px -> [-62.5 .. 505.5], 7 of 9
      7 letters @ 443px -> [1.5 .. 441.5]  (fits by 1.5px in DAILY mode only — see below)
     10 letters @ 390px -> [-94.4 .. 484.4], 6 of 10

   WHY 7 LETTERS FITS HERE BUT NOT ON KRIS'S SCREEN: he was in GROUP mode, which renders a FOURTH
   flex child in every row (.wf-row-solvers, min-width 40px, plus another 1rem gap = 56px more
   chrome). The e2e harness cannot render group mode at all (task 1106), so the automated
   measurement understates his exact case by exactly that 56px — which is most of one column, and
   precisely the one column he could not see.

   THE MECHANISM: the cell width is NOT computed. It is SOLVED BY FLEXBOX.
   `flex: 1 1 0` + `min-width: 0` + `max-width` makes each cell take an equal share of whatever
   width the row actually has, capped at the desktop size. This is deliberately NOT a vw/clamp
   calculation: a vw formula has to hardcode how much page padding sits outside the grid (measured
   at 48px today), and would silently go wrong the moment any ancestor's padding changed. Letting
   the browser divide the real container cannot drift.

   Height comes from `aspect-ratio: 1/1`, which memory coterie-display-layer-truth-2026-07-16
   records as MEASURED to work in this codebase (fact 1: the Span islands are exactly square
   because aspect-ratio feeds the automatic minimum). `align-items: center` on the row is
   load-bearing — the flex default `stretch` would override the aspect-ratio height and produce
   rectangles.

   THE GLYPH IS THE ONE THING FLEXBOX CANNOT SOLVE. font-size has no access to a flex-solved
   width, so it is derived from the container's own inline size via container query units, using
   the --wf-cols the razor emits. That reproduces the same division flexbox performs, so the
   letter tracks the box instead of clipping inside it. `overflow: hidden` is the backstop for
   sub-pixel disagreement between the two, not the primary defence. */
.wf-grid-row[b-qqye1xt2m0] {
    display: flex;
    gap: var(--wf-gap);
    justify-content: center;
    align-items: center;
    /* Take the row's share of the container and allow it to be narrower than its content wants. */
    flex: 1 1 0;
    min-width: 0;
    /* Establishes the query container the glyph rule below measures against. */
    container-type: inline-size;
}

.wf-grid-row .wf-cell[b-qqye1xt2m0] {
    /* Equal share of the real available width, never wider than the desktop cell. */
    flex: 1 1 0;
    min-width: 0;
    width: auto;
    max-width: var(--wf-cell-max);
    height: auto;
    aspect-ratio: 1 / 1;
    /* The same division flexbox just did, expressed where font-size can reach it. */
    /* max(floor, ...) is a guard, not a preference: if the container query ever resolves to 0 —
       which it does the instant an ancestor collapses, as it did on the first run of this fix —
       the calc goes negative and font-size computes to 0px, i.e. an invisible letter in a visible
       box. That is the "failures render as emptiness" mode from memory
       coterie-display-layer-truth-2026-07-16. Better to render a too-large glyph, which is
       obvious, than an absent one, which is not. */

    /* Fallback for browsers without container query units (pre-Chrome 105 / Safari 16). They drop
       the `cqw` declaration below as unparseable, and WITHOUT this line the cascade would fall all
       the way back to the scoped `.wf-cell { font-size: 2rem }` — a 32px glyph in a 30px box. 1rem
       is small enough to fit the tightest cell this layout produces (30.6px at 10 letters/390px). */
    font-size: 1rem;
    font-size: max(
        0.75rem,
        min(
            var(--wf-font-max),
            calc((100cqw - (var(--wf-cols) - 1) * var(--wf-gap)) / var(--wf-cols) * 0.58)
        )
    );
    overflow: hidden;
}

/* Lex Grid & Cell Enhancements */
.wf-cell[b-qqye1xt2m0] {
    width: 3.5rem;
    height: 3.5rem;
    background: var(--wf-cell-bg);
    border: 1px solid var(--wf-cell-border);
    border-radius: var(--border-radius-sm);
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 2rem;
    font-weight: 700;
    color: var(--wf-text);
    text-transform: uppercase;
    transition: all 0.4s cubic-bezier(0.4, 0, 0.2, 1);
    box-shadow: inset 0 0 10px rgba(255, 255, 255, 0.02);
}

.wf-cell.active[b-qqye1xt2m0] {
    border: 2px solid var(--wf-cell-active-border);
    box-shadow: 0 0 15px var(--accent-glow);
    transform: translateY(-2px);
}

/* ==============================================================
   THEME PALETTES (Colors react to the selected Correctness Theme)
   ============================================================== */
.wf-board-container.wf-theme-classic[b-qqye1xt2m0] {
    /* Classic inherits from the group theme's accent color.
       If a group theme overrides --accent-primary, correct follows it.
       --wf-correct-bg / --wf-present-bg are the persona defaults. */
    --local-correct: var(--accent-primary);
    --local-present: var(--wf-present-bg);
    --local-correct-glow: var(--accent-glow);
    --local-present-glow: var(--wf-glow-present);
    --local-absent-text: rgba(255, 255, 255, 0.4);
}

.wf-board-container.wf-theme-neon[b-qqye1xt2m0] {
    /* Miami Vice / Synthwave */
    --local-correct: #f0abfc;
    /* Bright Pink */
    --local-present: #38bdf8;
    /* Sky Blue */
    --local-correct-glow: rgba(240, 171, 252, 0.6);
    --local-present-glow: rgba(56, 189, 248, 0.6);
    --local-absent-text: rgba(255, 255, 255, 0.3);
}

.wf-board-container.wf-theme-shapes[b-qqye1xt2m0] {
    /* High contrast, less garrish colors, focused on shapes */
    --local-correct: #4ade80;
    /* Soft Green */
    --local-present: #fb923c;
    /* Soft Orange */
    --local-correct-glow: transparent;
    --local-present-glow: transparent;
    --local-absent-text: rgba(255, 255, 255, 0.5);
}

.wf-board-container.wf-theme-kinetic[b-qqye1xt2m0] {
    /* The Matrix - Hacker Green and Purple */
    --local-correct: #22c55e;
    /* Hacker Green */
    --local-present: #a855f7;
    /* Purple */
    --local-correct-glow: #4ade80;
    --local-present-glow: #c084fc;
    --local-absent-text: rgba(255, 255, 255, 0.35);
}

.wf-board-container.wf-theme-spectral[b-qqye1xt2m0] {
    /* Deep space / Heatmap style */
    --local-correct: #60a5fa;
    /* Crisp Blue */
    --local-present: #f472b6;
    /* Soft Pink */
    --local-correct-glow: #93c5fd;
    --local-present-glow: #fbcfe8;
    --local-absent-text: rgba(255, 255, 255, 0.3);
}

/* --- THEME: Classic Arcade (Default) --- */
.wf-board-container.wf-theme-classic .wf-cell.correct[b-qqye1xt2m0] {
    background: var(--local-correct) !important;
    border-color: var(--local-correct) !important;
    color: white !important;
    box-shadow: 0 0 20px var(--local-correct-glow) !important;
    text-shadow: 0 0 8px rgba(255, 255, 255, 0.8);
    transform: scale(1.05);
}

.wf-board-container.wf-theme-classic .wf-cell.present[b-qqye1xt2m0] {
    background: var(--local-present) !important;
    border-color: var(--local-present) !important;
    color: #0f172a !important;
    box-shadow: 0 0 15px var(--local-present-glow) !important;
    transform: scale(1.02);
}

.wf-board-container.wf-theme-classic .wf-cell.absent[b-qqye1xt2m0] {
    background: var(--wf-absent-bg) !important;
    border-color: transparent !important;
    opacity: 0.4;
    transform: scale(0.95);
}

/* Legend Mini Cells */
.wf-cell.mini-cell[b-qqye1xt2m0] {
    width: 2rem !important;
    height: 2rem !important;
    font-size: 1rem !important;
    border-radius: 4px !important;
    margin: 0 !important;
    padding: 0 !important;
    box-shadow: none !important;
}

.wf-board-container.wf-theme-shapes .wf-cell.mini-cell.correct[b-qqye1xt2m0] {
    border-radius: 50% !important;
}

.wf-board-container.wf-theme-shapes .wf-cell.mini-cell.present[b-qqye1xt2m0] {
    transform: rotate(45deg) scale(0.85) !important;
    border-radius: 2px !important;
}

.wf-board-container.wf-theme-shapes .wf-cell.mini-cell.present[b-qqye1xt2m0]::before {
    content: '';
}

/* --- THEME: Neon Outline --- */
.wf-board-container.wf-theme-neon .wf-cell.correct[b-qqye1xt2m0] {
    background: transparent !important;
    border: 2px solid var(--local-correct) !important;
    color: var(--local-correct) !important;
    box-shadow: 0 0 15px var(--local-correct-glow), inset 0 0 15px var(--local-correct-glow) !important;
    text-shadow: 0 0 8px var(--local-correct-glow);
    transform: scale(1.05);
}

.wf-board-container.wf-theme-neon .wf-cell.present[b-qqye1xt2m0] {
    background: transparent !important;
    border: 2px solid var(--local-present) !important;
    color: var(--local-present) !important;
    box-shadow: 0 0 10px var(--local-present-glow), inset 0 0 10px var(--local-present-glow) !important;
    text-shadow: 0 0 8px var(--local-present-glow);
}

.wf-board-container.wf-theme-neon .wf-cell.absent[b-qqye1xt2m0] {
    background: transparent !important;
    border: 1px solid rgba(255, 255, 255, 0.1) !important;
    color: var(--local-absent-text) !important;
    opacity: 0.5;
}

/* --- THEME: Shape & Symbol --- */
.wf-board-container.wf-theme-shapes .wf-cell[b-qqye1xt2m0] {
    transition: all 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    /* Bouncy transition */
}

.wf-board-container.wf-theme-shapes .wf-cell.correct[b-qqye1xt2m0] {
    background: var(--surface-color) !important;
    border: 2px solid var(--local-correct) !important;
    color: var(--wf-text) !important;
    border-radius: 50% !important;
    /* Circle */
    transform: scale(1.1);
}

.wf-board-container.wf-theme-shapes .wf-cell.present[b-qqye1xt2m0] {
    background: var(--surface-color) !important;
    border: 2px solid var(--local-present) !important;
    border-radius: 4px !important;
    color: var(--wf-text) !important;
    transform: rotate(45deg) scale(0.85);
    /* Diamond shape */
}

/* Counter-rotate text for shapes mode present so letter is upright */
.wf-board-container.wf-theme-shapes .wf-cell.present[b-qqye1xt2m0]::before {
    content: '';
}

.wf-board-container.wf-theme-shapes .wf-cell.absent[b-qqye1xt2m0] {
    background: transparent !important;
    border: 1px dashed var(--glass-border) !important;
    opacity: 0.3;
    transform: scale(0.8);
}

/* --- THEME: The Matrix (Kinetic Typography) --- */
@keyframes neonFlicker-b-qqye1xt2m0 {

    0%,
    19%,
    21%,
    23%,
    25%,
    54%,
    56%,
    100% {
        opacity: 1;
        text-shadow: 0 0 8px var(--local-correct-glow);
    }

    20%,
    24%,
    55% {
        opacity: 0.5;
        text-shadow: none;
    }
}

@keyframes glitchShake-b-qqye1xt2m0 {
    0% {
        transform: translate(0)
    }

    20% {
        transform: translate(-2px, 2px)
    }

    40% {
        transform: translate(-2px, -2px)
    }

    60% {
        transform: translate(2px, 2px)
    }

    80% {
        transform: translate(2px, -2px)
    }

    100% {
        transform: translate(0)
    }
}

.wf-board-container.wf-theme-kinetic .wf-cell.correct[b-qqye1xt2m0] {
    background: transparent !important;
    border-color: transparent !important;
    color: var(--local-correct) !important;
    font-weight: 900;
    transform: scale(1.2);
    animation: neonFlicker-b-qqye1xt2m0 3s infinite alternate;
}

.wf-board-container.wf-theme-kinetic .wf-cell.present[b-qqye1xt2m0] {
    background: transparent !important;
    border-color: transparent !important;
    color: var(--local-present) !important;
    font-style: italic;
    animation: glitchShake-b-qqye1xt2m0 0.4s infinite;
}

.wf-board-container.wf-theme-kinetic .wf-cell.absent[b-qqye1xt2m0] {
    background: transparent !important;
    border-color: transparent !important;
    color: var(--local-absent-text) !important;
    filter: blur(0.6px);
}

/* --- THEME: Spectral Analysis --- */
.wf-board-container.wf-theme-spectral .wf-cell.correct[b-qqye1xt2m0] {
    background: transparent !important;
    border-color: transparent !important;
    color: var(--local-correct) !important;
    font-weight: 900;
    text-shadow: 0 0 15px var(--local-correct-glow);
}

.wf-board-container.wf-theme-spectral .wf-cell.present[b-qqye1xt2m0] {
    background: transparent !important;
    border-color: transparent !important;
    color: var(--local-present) !important;
    font-weight: 400;
    font-style: italic;
    opacity: 0.8;
}

.wf-board-container.wf-theme-spectral .wf-cell.absent[b-qqye1xt2m0] {
    background: transparent !important;
    border-color: transparent !important;
    color: var(--local-absent-text) !important;
}

/* Keyboard overrides for Spectral/Kinetic/Neon to keep keys visible but themed */
.wf-board-container.wf-theme-neon .wf-key.correct[b-qqye1xt2m0],
.wf-board-container.wf-theme-spectral .wf-key.correct[b-qqye1xt2m0],
.wf-board-container.wf-theme-kinetic .wf-key.correct[b-qqye1xt2m0],
.wf-board-container.wf-theme-shapes .wf-key.correct[b-qqye1xt2m0] {
    background: rgba(0, 0, 0, 0.2) !important;
    border-color: var(--local-correct) !important;
    color: var(--local-correct) !important;
}

.wf-board-container.wf-theme-neon .wf-key.present[b-qqye1xt2m0],
.wf-board-container.wf-theme-spectral .wf-key.present[b-qqye1xt2m0],
.wf-board-container.wf-theme-kinetic .wf-key.present[b-qqye1xt2m0],
.wf-board-container.wf-theme-shapes .wf-key.present[b-qqye1xt2m0] {
    background: rgba(0, 0, 0, 0.2) !important;
    border-color: var(--local-present) !important;
    color: var(--local-present) !important;
}

/* Row Solvers Enhancement */
.wf-row-solvers[b-qqye1xt2m0] {
    opacity: 0.8;
    transition: opacity 0.3s;
}

.wf-row-solvers:hover[b-qqye1xt2m0] {
    opacity: 1;
}

/* Keyboard Styling */
.wf-keyboard[b-qqye1xt2m0] {
    margin: 2.5rem auto 0;
    padding: 1.5rem;
    background: rgba(0, 0, 0, 0.2);
    border-radius: var(--border-radius-lg);
    backdrop-filter: blur(10px);
    border: 1px solid var(--glass-border);
    width: fit-content;
}

.wf-row[b-qqye1xt2m0] {
    display: flex;
    gap: 5px;
    margin-bottom: 5px;
    justify-content: center;
}

.wf-key[b-qqye1xt2m0] {
    min-width: 2.5rem;
    height: 3.5rem;
    background: var(--wf-key-bg);
    border: 1px solid var(--glass-border);
    border-radius: var(--border-radius-sm);
    color: var(--text-primary);
    font-weight: 700;
    transition: all 0.2s ease;
    display: flex;
    align-items: center;
    justify-content: center;
    cursor: pointer;
}

.wf-key:hover[b-qqye1xt2m0] {
    background: var(--surface-hover);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}

.wf-key.correct[b-qqye1xt2m0] {
    background: var(--local-correct, var(--accent-primary)) !important;
    border-color: var(--local-correct, var(--accent-primary)) !important;
    color: white !important;
    box-shadow: 0 0 10px var(--local-correct-glow, var(--accent-glow)) !important;
}

.wf-key.present[b-qqye1xt2m0] {
    background: var(--local-present, var(--wf-present-bg)) !important;
    border-color: var(--local-present, var(--wf-present-bg)) !important;
    color: #0f172a !important;
    box-shadow: 0 0 8px var(--local-present-glow, var(--wf-glow-present)) !important;
}

.wf-key.absent[b-qqye1xt2m0] {
    opacity: 0.3;
    background: var(--wf-absent-bg) !important;
}

.wf-key.wide[b-qqye1xt2m0] {
    min-width: 4rem;
    background: var(--accent-primary);
    border-color: var(--accent-primary);
    color: white;
}
/* Viewing Peer Solution Header */
.wf-viewing-header[b-qqye1xt2m0] {
    margin-top: 2.5rem;
    padding: 1.5rem 2rem;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 2rem;
    border: 1px solid var(--accent-primary);
    box-shadow: 0 0 20px rgba(59, 130, 246, 0.1);
    border-radius: var(--border-radius-lg);
}

.viewing-info[b-qqye1xt2m0] {
    font-size: 1.2rem;
    color: var(--text-primary);
}

.viewing-info strong[b-qqye1xt2m0] {
    color: var(--accent-primary);
}

@media (max-width: 600px) {
    .wf-viewing-header[b-qqye1xt2m0] {
        flex-direction: column;
        text-align: center;
        gap: 1rem;
    }
}

@media (max-width: 767px) {
    /* THE CHAT'S RESERVED ZONE COMES OUT OF THE CONTAINER, NOT OUT OF THE CONTENT (task 1129).
       See the `--chat-h` block in app.css for the contract.

       WHY THE PREVIOUS ATTEMPT COULD NOT HAVE WORKED. `.wf-keyboard` already carried
       `padding-bottom: calc(env(safe-area-inset-bottom) + 40px + 0.3rem)` — a 40px reservation for
       exactly this bar. It cannot help, because the padding is INSIDE a container that is a fixed
       height and `overflow: hidden`. Adding padding to clipped content does not move it up; it
       makes the content taller and pushes MORE of it past the clip. The reservation was actively
       counterproductive, and it is removed below.

       MEASURED (FloatingChatControlOcclusionTests, chat present):
         443x660 before -> 19 of 28 keys in the viewport at all, and 9 of those 19 FULLY covered by
                           the chat bar (the whole A-L row). The bottom row, ENTER and DEL, was not
                           merely covered — it was clipped out of existence by `overflow: hidden`.
       So the answer to "is ENTER untappable or just overlapped" is: on a short phone it is worse
       than either. `overflow-y: auto` makes a too-tall keyboard reachable instead of destroyed. */
    .app-container[b-qqye1xt2m0] {
        height: calc(100dvh - var(--topnav-h, 3.5rem) - var(--float-zone-h, 0px));
        overflow-x: hidden;
        overflow-y: auto;
    }

    header[b-qqye1xt2m0] {
        padding: 0.35rem 0.75rem;
        gap: 0.25rem;
    }

    header h1[b-qqye1xt2m0] {
        font-size: 1rem;
    }

    [b-qqye1xt2m0] .toolbar-actions {
        gap: 0.4rem;
        flex-wrap: nowrap;
        overflow-x: auto;
    }

    [b-qqye1xt2m0] .btn-primary,
    [b-qqye1xt2m0] .form-select,
    [b-qqye1xt2m0] .btn-sm {
        font-size: 0.75rem;
        padding: 0.2rem 0.45rem;
    }

    /* THE CHROME GIVES WAY BEFORE THE CELLS DO (task 1073).
       The old rule here was `width/height: clamp(2rem, 13vw, 3.5rem)` with a fixed
       `font-size: clamp(1.2rem, 4vw, 2rem)` — a cell that could not shrink below 2rem no matter
       how many columns there were, and a glyph that did not track it at all. It is gone; the
       cells now flex (see `.wf-grid-row .wf-cell`).

       What remains to do on a phone is give the cells more of the budget to divide. Measured, the
       usable width is 342px at a 390px viewport and 395px at 443px. The desktop chrome (80px free
       play / 136px group) left only 262px / 206px for ten columns, which forces a ~19px cell —
       below the legible floor LexRowFitTests asserts. Shrinking the chrome to 18px / 48px is what
       keeps a 10-letter row both fitting AND readable.

       The ::before counterweight goes to zero rather than shrinking: it exists purely to balance
       the meter so the cells sit optically centred, and on a phone the centring matters far less
       than the 24px. */
    .wf-board-container[b-qqye1xt2m0] {
        --wf-gap: 4px;
        --wf-row-lead: 0px;
        --wf-meter-w: 10px;
        --wf-solvers-w: 26px;
        --wf-row-chrome-gap: 4px;
    }

    .spectral-meter[b-qqye1xt2m0] {
        width: 6px;
    }

    .wf-keyboard[b-qqye1xt2m0] {
        /* The 40px chat reservation that used to live here is GONE — the container reserves it now
           (see .app-container above). Keeping it would double-count the bar and, worse, add height
           to content inside a clipping box, which is what buried the ENTER key in the first place.
           The safe-area inset stays: that is the device's notch/home-indicator, not the chat's. */
        padding: 0.3rem 0.3rem calc(env(safe-area-inset-bottom, 0px) + 0.3rem);
        margin-top: 0.4rem;
        width: 100%;
        box-sizing: border-box;
    }

    .wf-row[b-qqye1xt2m0] {
        gap: 4px;
        margin-bottom: 4px;
    }

    .wf-key[b-qqye1xt2m0] {
        flex: 1;
        min-width: 0;
        height: 2.6rem;
        font-size: 0.85rem;
    }

    .wf-key.wide[b-qqye1xt2m0] {
        flex: 1;
        min-width: 0;
        font-size: 0.75rem;
    }
}
/* /Pages/SpanGame.razor.rz.scp.css */
/* Game Control Buttons (Undo / Reset) */
.game-controls[b-pfr9g0hqjq] {
    gap: 0.4rem;
}

.btn-icon[b-pfr9g0hqjq] {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.25rem;
    height: 2.25rem;
    border: 1px solid var(--glass-border);
    border-radius: 0.5rem;
    background: var(--glass-input-bg);
    color: var(--text-primary);
    font-size: 1.1rem;
    cursor: pointer;
    transition: all 0.2s ease;
    backdrop-filter: blur(6px);
}

.btn-icon:hover:not(:disabled)[b-pfr9g0hqjq] {
    background: var(--accent-primary);
    color: var(--bg-color);
    border-color: var(--accent-primary);
    transform: scale(1.08);
    box-shadow: 0 0 10px var(--accent-glow);
}

.btn-icon:active:not(:disabled)[b-pfr9g0hqjq] {
    transform: scale(0.95);
}

.btn-icon:disabled[b-pfr9g0hqjq] {
    opacity: 0.35;
    cursor: not-allowed;
}

/* Desktop: fill game-layout and center the grid in both axes */
.board-section[b-pfr9g0hqjq] {
    display: flex;
    /* `safe center`, not `center` (task 1401). A short-but-wide viewport (a landscape phone or
       Chromebook, e.g. 896x443) is WIDER than 767px, so it never reaches the mobile block below —
       it gets THIS rule instead, with --avail-h: 100000px (no height budget; see .span-grid). When
       the board is taller than .board-section's real (viewport-bounded) height, plain `center`
       overflows it EQUALLY on both sides — and per the CSS box-alignment spec, unsafe centering
       makes only the TRAILING half of that overflow reachable by scrolling; the LEADING half is
       clipped at a scroll position that does not exist. Measured (tests/Coterie.E2E.Tests/
       ChromebookLandscapeLayoutTests.cs): at 896x443 the board's own box rendered at
       Y=-57 on load — the top ~57px of islands were already gone, with no scroll gesture that
       reaches them. `safe` keeps the START of the overflow pinned to the scroll origin instead, so
       the excess spills entirely on the reachable (bottom) side. This is the same fix
       `@media (max-width: 767px)` below already applies; the desktop/no-media-query state needs it
       too because "wide" and "short" are independent axes and this rule does not know which one
       let it through.

       BOTH KEYWORDS ARE HERE, BUT ONLY THE VERTICAL ONE IS DOING ANYTHING TODAY — say that
       precisely rather than implying `safe` is protecting both axes. Measured: at 896x501 (just
       above the media gate) plain `center` puts the board at Y=-28.0 with 8/24 hit-points behind
       the header; `safe` moves it to Y=+177.0. Horizontally, forcing a 1343px-wide grid into a
       526px `.board-section` gave a BIT-IDENTICAL X=330.0 under both `center` and `safe center` —
       because `.span-grid-wrapper` (the flex item actually being aligned) is capped
       `max-width: 600px` on desktop and floored `min-width: 100%` on mobile, so it can never be
       wider than its container in the first place; there is no horizontal overflow for `safe` to
       have an opinion about. That cap is asserted as an invariant by the adversarial hardening
       suite, so if it is ever lifted the loss of horizontal protection here fails a test rather
       than silently reopening this bug sideways — this comment is not the thing guarding that. */
    align-items: safe center;
    justify-content: safe center;
    flex: 1;
    align-self: stretch;
    /* THE WIDTH BUDGET'S SOURCE (task 1028). --avail-w below reads 100cqw against this element, so
       the board learns its real available width from layout instead of restating it.
       Safe to make a query container: this element's inline size is layout-driven in BOTH
       viewports (`flex: 1; align-self: stretch` on desktop, `flex: 1` in a column flex on mobile),
       never content-driven, so contain:inline-size cannot collapse it. It has no position:fixed
       descendants — the win overlay is a sibling — so contain:layout does not steal anyone's
       containing block. .span-grid-wrapper would NOT be safe: on mobile it is `width: max-content`
       by design, which is precisely the circular content-driven case containment breaks. */
    container-type: inline-size;
}

.span-grid-wrapper[b-pfr9g0hqjq] {
    width: 100%;
    max-width: 600px;
    background-color: transparent;
    margin: 0 auto;
    /* Task 1568: SpanGenerator now trims to a TIGHT island bounding box (no +1-cell margin), so
       an island always sits flush against row 0 / col 0 of the grid itself. The old phantom
       empty border used to supply the visual breathing room around the outermost islands; that
       margin is gone from the DATA now, so it is restored here instead, as real CSS padding on
       the wrapper — never as fake empty grid cells (which would just resurrect the same dead
       IsEdge/IsCorner bug this task exists to fix). Bumped from 1rem to 1.5rem to replace
       roughly what one trimmed-away cell used to provide at typical --cell sizes. */
    padding: 1.5rem;
    margin-bottom: 5rem;
}

/* ==============================================================
   BOARD SIZING — ONE MODEL, BOTH VIEWPORTS. Size the CELL, not the box.
   ==============================================================
   THE BUG THIS REPLACES (measured, not theorised — tests/Coterie.E2E.Tests):
   The old code declared the BOX and let `1fr` divide it among the tracks:
       width:  max(--fit-size, --min-size-w)
       height: max(--fit-size, --min-size-h)   [assumed a row costs min-cell + gap]
       grid-template-rows: repeat(N, 1fr)      [emitted INLINE from the .razor]
   But a row's REAL height came from the cell's WIDTH, via aspect-ratio: 1/1 feeding the
   automatic minimum of minmax(auto, 1fr). So the box's height and the cells' actual height
   were computed from DIFFERENT inputs and were free to disagree. On a 9x12 board they did:
   12 rows x 37.28px + 11 gaps x 5.6px = 509px of tracks inside a box that declared 451px.
   The declared height was a fiction and the board painted 58px outside its own box (a
   free-play 8x12 measured 122px) — on a SIX-ISLAND board the old comment swore "never scrolls".

   THE MODEL NOW: --cell is the single scalar. It is the largest square that fits BOTH axes'
   budget, floored at a tappable minimum. Both tracks are repeat(N, var(--cell)), and the box
   is max-content — i.e. the box is a CONSEQUENCE of the cells rather than a competing claim
   about them. Square cells are true BY CONSTRUCTION for every board shape, so the overflow is
   not "fixed", it is unrepresentable. Desktop and mobile now differ only in the two budget
   variables below, not in mechanism.

   INVARIANT, GUARDED BY THE HARNESS: tracks + gaps == the grid's declared box, on every board
   shape and both viewports. If you ever declare the box directly again, you reopen the bug. */
.span-grid[b-pfr9g0hqjq] {
    display: grid;

    --grid-gap: 0.65rem;
    /* The floor below which a cell stops being a comfortable touch target. */
    --min-cell: 2rem;

    /* THE WIDTH BUDGET NOW COMES FROM THE REAL CONTAINER (task 1028).
       This was `calc(min(100vw - var(--sidebar-w, 250px) - 7.5rem, 600px) - 2rem)`, where 7.5rem
       was 2rem + 1.5rem (article padding at min-width:641px) + 2rem + 2rem (.game-layout padding
       at min-width:768px). That formula was CORRECT and it fixed a real 114px spill at 768px
       (task 938) — but it only worked by restating four ancestors' padding plus the sidebar width
       inside the board's own stylesheet, in three separate places (here, the mobile block, and the
       641-767px band). Every one of those numbers is a standing invitation to drift: change a
       padding in MainLayout.razor.css or app.css and the board silently oversizes again, exactly
       as it did before 938, with nothing pointing back here.

       100cqw is .board-section's CONTENT-box inline size — the width the board actually has, after
       the sidebar and every ancestor's padding have already been subtracted BY LAYOUT. It cannot
       disagree with the page, because it is measured from the page. This is the Lex argument
       (task 1073) applied to the width axis instead of the glyph.

       What remains here is local and self-owned rather than inherited guesswork:
         600px — .span-grid-wrapper's own max-width, a deliberate design cap on board size.
         2rem  — .span-grid-wrapper's own 1rem padding, both sides.
       Desktop stays WIDTH-driven (the page may scroll vertically), so the height budget is
       deliberately unconstrained. */
    --avail-w: calc(min(100cqw, 600px) - 2rem);
    --avail-h: 100000px;

    /* The largest square cell that fits each axis' budget once gaps are paid for. */
    --fit-cell: min(
        calc((var(--avail-w) - (var(--span-cols, 10) - 1) * var(--grid-gap)) / var(--span-cols, 10)),
        calc((var(--avail-h) - (var(--span-rows, 10) - 1) * var(--grid-gap)) / var(--span-rows, 10))
    );
    --cell: max(var(--fit-cell), var(--min-cell));

    grid-template-columns: repeat(var(--span-cols, 10), var(--cell));
    grid-template-rows: repeat(var(--span-rows, 10), var(--cell));
    /* The box follows the cells. Never the other way round. */
    width: max-content;
    height: max-content;
    margin-inline: auto;

    gap: var(--grid-gap);
    position: relative;
    z-index: 5;
    touch-action: manipulation;
}

.span-cell[b-pfr9g0hqjq] {
    position: relative;
    display: flex;
    justify-content: center;
    align-items: center;
    background-color: transparent;
    /* Empty cells are invisible */
    /* No aspect-ratio here: both tracks are var(--cell), so the cell is square by
       construction. The old aspect-ratio: 1/1 was what silently drove rows past the height
       the box had declared for them. */
    /* No tap delay / double-tap zoom on iOS for the click target. */
    touch-action: manipulation;
}

.island[b-pfr9g0hqjq] {
    width: 100%;
    height: 100%;
    border-radius: 50%;
    background-color: var(--island-bg);
    color: var(--island-text);
    /* Both derive from --cell, so they track the REAL cell size on every board and viewport.
       They used to key off vw, which is the same one-axis blindness as the sizing bug: a 25-wide
       board on desktop got a ~14px cell with a 3px border and a font clamped up to 27px — a 27px
       glyph in a 14px circle. 0.5 is not arbitrary: it is the ratio desktop already resolved to
       (27.2px font in a 53.88px cell) on the boards that looked right. */
    border: max(1px, calc(var(--cell, 2rem) * 0.06)) solid var(--island-border);
    display: flex;
    justify-content: center;
    align-items: center;
    font-family: var(--font-heading);
    font-weight: 800;
    font-size: calc(var(--cell, 2rem) * 0.5);
    cursor: pointer;
    z-index: 10;
    transition: all 0.2s cubic-bezier(0.175, 0.885, 0.32, 1.275);
    user-select: none;
    box-shadow: 0 4px 8px rgba(0,0,0,0.3);
    touch-action: manipulation;
}

/* ==============================================================
   THEME PALETTES (Colors react to the selected Correctness Theme)
   ============================================================== */
.board-section.wf-theme-classic[b-pfr9g0hqjq] {
    /* Classic inherits from the group theme's accent color */
    --local-island-active-bg: var(--accent-primary);
    --local-island-satisfied-bg: var(--island-bg-satisfied);
    --local-island-error-bg: var(--island-bg-error);
    --local-island-active-glow: var(--accent-glow);
    --local-island-satisfied-glow: rgba(16, 185, 129, 0.4);
    --local-island-error-glow: rgba(239, 68, 68, 0.4);
}

.board-section.wf-theme-neon[b-pfr9g0hqjq] {
    --local-island-active-bg: transparent;
    --local-island-satisfied-bg: transparent;
    --local-island-error-bg: transparent;
    --local-island-error-border: #f43f5e;
    --local-island-active-glow: rgba(56, 189, 248, 0.6);
    --local-island-satisfied-glow: rgba(240, 171, 252, 0.6);
    --local-island-error-glow: rgba(244, 63, 94, 0.6);
}

.board-section.wf-theme-shapes[b-pfr9g0hqjq] {
    --local-island-active-bg: #4ade80;
    --local-island-satisfied-bg: #4ade80;
    --local-island-error-bg: #fb923c;
    --local-island-error-border: #fb923c;
    --local-island-active-glow: transparent;
    --local-island-satisfied-glow: rgba(74, 222, 128, 0.3);
    --local-island-error-glow: rgba(251, 146, 60, 0.3);
}

.board-section.wf-theme-kinetic[b-pfr9g0hqjq] {
    --local-island-active-bg: transparent;
    --local-island-satisfied-bg: transparent;
    --local-island-error-bg: transparent;
    --local-island-error-border: #ef4444;
    --local-island-active-glow: transparent;
    --local-island-satisfied-glow: 0 0 12px #a855f7;
    --local-island-error-glow: 0 0 12px #ef4444;
}

.board-section.wf-theme-spectral[b-pfr9g0hqjq] {
    --local-island-active-bg: transparent;
    --local-island-satisfied-bg: transparent;
    --local-island-error-bg: transparent;
    --local-island-error-border: #f472b6;
    --local-island-active-glow: rgba(96, 165, 250, 0.8);
    --local-island-satisfied-glow: 0 0 15px #f472b6;
    --local-island-error-glow: 0 0 15px #f472b6;
}

.board-section .island.active[b-pfr9g0hqjq] {
    background-color: var(--local-island-active-bg, var(--island-bg-active));
    border-color: var(--local-island-active-border, var(--island-text));
    color: white;
    transform: scale(1.1);
    box-shadow: 0 0 15px var(--local-island-active-glow, var(--accent-glow));
    z-index: 20;
}

.board-section .island.hovered:not(.active):not(.potential-neighbor)[b-pfr9g0hqjq] {
    border-color: var(--local-island-active-border, var(--accent-primary));
    transform: scale(1.05);
    box-shadow: 0 0 8px var(--local-island-active-glow, var(--accent-glow));
}

.board-section .island.potential-neighbor[b-pfr9g0hqjq] {
    border-color: var(--accent-secondary, #fbbf24);
    box-shadow: 0 0 12px var(--accent-secondary-glow, rgba(251, 191, 36, 0.4));
    animation: potentialPulse-b-pfr9g0hqjq 2s infinite;
}

@keyframes potentialPulse-b-pfr9g0hqjq {
    0%, 100% { transform: scale(1); opacity: 1; }
    50% { transform: scale(1.03); opacity: 0.8; }
}

/* Connection Ring Visual Effect */
.board-section .island.hovered[b-pfr9g0hqjq]::after,
.board-section .island.active[b-pfr9g0hqjq]::after {
    content: '';
    position: absolute;
    inset: -10px;
    border: 3px solid var(--local-island-active-glow, var(--accent-primary));
    border-radius: 50%;
    animation: connectionPulse-b-pfr9g0hqjq 1.2s infinite;
    pointer-events: none;
    opacity: 0.8;
}

@keyframes connectionPulse-b-pfr9g0hqjq {
    0% {
        transform: scale(0.9);
        opacity: 0.8;
    }
    100% {
        transform: scale(1.4);
        opacity: 0;
    }
}

.board-section .island.satisfied[b-pfr9g0hqjq] {
    background-color: var(--local-island-satisfied-bg, var(--island-bg-satisfied));
    border-color: var(--local-island-satisfied-border, var(--island-bg-satisfied));
    box-shadow: var(--local-island-satisfied-glow, none);
    color: white;
}

.board-section .island.error[b-pfr9g0hqjq] {
    background-color: var(--local-island-error-bg, var(--island-bg-error));
    border-color: var(--local-island-error-border, var(--island-bg-error));
    box-shadow: var(--local-island-error-glow, none);
    color: white;
}

/* --- THEME SPECIFIC ANIMATIONS --- */
@keyframes neonFlicker-b-pfr9g0hqjq {

    0%,
    19%,
    21%,
    23%,
    25%,
    54%,
    56%,
    100% {
        opacity: 1;
        box-shadow: 0 0 8px #22c55e, inset 0 0 8px #22c55e;
    }

    20%,
    24%,
    55% {
        opacity: 0.5;
        box-shadow: none;
    }
}

.board-section.wf-theme-kinetic .island.active[b-pfr9g0hqjq] {
    animation: neonFlicker-b-pfr9g0hqjq 3s infinite alternate;
}

@keyframes glitchShake-b-pfr9g0hqjq {
    0% {
        transform: translate(0)
    }

    20% {
        transform: translate(-2px, 2px)
    }

    40% {
        transform: translate(-2px, -2px)
    }

    60% {
        transform: translate(2px, 2px)
    }

    80% {
        transform: translate(2px, -2px)
    }

    100% {
        transform: translate(0)
    }
}

.board-section.wf-theme-kinetic .island.error[b-pfr9g0hqjq] {
    animation: glitchShake-b-pfr9g0hqjq 0.4s infinite;
}

.board-section.wf-theme-shapes .island.active[b-pfr9g0hqjq] {
    border-radius: 4px;
    transform: scale(1.1) rotate(45deg);
}

.board-section.wf-theme-shapes .island.satisfied[b-pfr9g0hqjq] {
    border-radius: 50%;
}

.board-section.wf-theme-shapes .island.error[b-pfr9g0hqjq] {
    border-radius: 4px;
}

/* Span */
.bridge[b-pfr9g0hqjq] {
    position: absolute;
    background-color: var(--bridge-line);
    z-index: 5;
    pointer-events: none;
}

.bridge.horizontal[b-pfr9g0hqjq] {
    height: 4px;
    width: calc(100% + var(--grid-gap) + 2px);
    left: calc(-1 * (var(--grid-gap) + 2px) / 2);
    top: 50%;
    transform: translateY(-50%);
}

.bridge.horizontal.double[b-pfr9g0hqjq] {
    height: 8px;
    background: linear-gradient(
        to bottom,
        var(--bridge-line) 0,
        var(--bridge-line) 2px,
        transparent 2px,
        transparent 6px,
        var(--bridge-line) 6px,
        var(--bridge-line) 8px
    );
}

.bridge.vertical[b-pfr9g0hqjq] {
    width: 4px;
    height: calc(100% + var(--grid-gap) + 2px);
    top: calc(-1 * (var(--grid-gap) + 2px) / 2);
    left: 50%;
    transform: translateX(-50%);
}

.bridge.vertical.double[b-pfr9g0hqjq] {
    width: 8px;
    background: linear-gradient(
        to right,
        var(--bridge-line) 0,
        var(--bridge-line) 2px,
        transparent 2px,
        transparent 6px,
        var(--bridge-line) 6px,
        var(--bridge-line) 8px
    );
}

/* Win Overlay Styles */
.win-overlay[b-pfr9g0hqjq] {
    position: fixed;
    inset: 0;
    background: rgba(0, 0, 0, 0.7);
    backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 9999;
}

.glass-card[b-pfr9g0hqjq] {
    background: rgba(255, 255, 255, 0.03);
    backdrop-filter: blur(12px);
    border-radius: 1.25rem;
}

.win-card[b-pfr9g0hqjq] {
    text-align: center;
    max-width: 450px;
    padding: 3rem 2rem;
    border: 1px solid rgba(255, 215, 0, 0.3);
    /* Gold tint */
    box-shadow: 0 20px 50px rgba(0, 0, 0, 0.5), 0 0 20px rgba(255, 215, 0, 0.1);
}

.win-icon[b-pfr9g0hqjq] {
    font-size: 4.5rem;
    color: var(--win-title-color);
    margin-bottom: 1rem;
    display: inline-block;
    filter: drop-shadow(0 0 10px rgba(255, 215, 0, 0.5));
}

.win-card h2[b-pfr9g0hqjq] {
    font-size: 2.5rem;
    font-weight: 800;
    margin-bottom: 1rem;
    background: var(--win-title-gradient);
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
}

.win-card p[b-pfr9g0hqjq] {
    font-size: 1.1rem;
    color: var(--text-secondary);
    margin-bottom: 2rem;
}

.win-actions[b-pfr9g0hqjq] {
    display: flex;
    gap: 1rem;
    justify-content: center;
}

.animate-bounce-in[b-pfr9g0hqjq] {
    animation: bounceIn-b-pfr9g0hqjq 0.6s cubic-bezier(0.175, 0.885, 0.32, 1.275);
}

.animate-fade-in[b-pfr9g0hqjq] {
    animation: fadeIn-b-pfr9g0hqjq 0.4s ease-out;
}

@keyframes bounceIn-b-pfr9g0hqjq {
    0% {
        transform: scale(0.5);
        opacity: 0;
    }

    100% {
        transform: scale(1);
        opacity: 1;
    }
}

@keyframes fadeIn-b-pfr9g0hqjq {
    0% {
        opacity: 0;
    }

    100% {
        opacity: 1;
    }
}
/* Adjacent (Internal Gap) Spans */
.adjacent-bridge[b-pfr9g0hqjq] {
    position: absolute;
    background-color: var(--bridge-line);
    z-index: 5;
    pointer-events: none;
}

.adjacent-bridge.right[b-pfr9g0hqjq] {
    height: 4px;
    width: var(--grid-gap);
    left: 100%;
    top: 50%;
    transform: translateY(-50%);
}

.adjacent-bridge.right.double[b-pfr9g0hqjq] {
    height: 8px;
    background: linear-gradient(
        to bottom,
        var(--bridge-line) 0,
        var(--bridge-line) 2px,
        transparent 2px,
        transparent 6px,
        var(--bridge-line) 6px,
        var(--bridge-line) 8px
    );
}

.adjacent-bridge.down[b-pfr9g0hqjq] {
    width: 4px;
    height: var(--grid-gap);
    top: 100%;
    left: 50%;
    transform: translateX(-50%);
}

.adjacent-bridge.down.double[b-pfr9g0hqjq] {
    width: 8px;
    background: linear-gradient(
        to right,
        var(--bridge-line) 0,
        var(--bridge-line) 2px,
        transparent 2px,
        transparent 6px,
        var(--bridge-line) 6px,
        var(--bridge-line) 8px
    );
}

/* === MOBILE: no-scroll viewport fill === */
/* Task 1401: the second clause, `(max-height: 500px)`, is new. WHY A HEIGHT CONDITION TOO.
   `max-width: 767px` alone is a WIDTH gate, and a landscape phone/Chromebook (e.g. 896x443,
   Kris's reported case) is WIDER than that even though it is exactly the kind of viewport this
   block exists to serve: no real vertical budget. Without the OR, that viewport falls through to
   the desktop rule above, which sets `--avail-h: 100000px` — an intentionally UNBOUNDED height
   budget meant for tall desktop windows that can scroll the whole page — so the board is sized
   only from its width and can end up far taller than the actual viewport. 500px is comfortably
   above every measured short/landscape case (443, 390) and comfortably below an ordinary desktop
   window (even a small laptop's browser viewport is normally >=700px tall), so this should not
   fire on a legitimate wide desktop window. See ChromebookLandscapeLayoutTests.cs for the
   measurement that motivated this. */
@media (max-width: 767px), (max-height: 500px) {
    .app-container[b-pfr9g0hqjq] {
        /* Fixed positioning locks the game to the viewport so the page body
           cannot be scrolled (rubber-band or otherwise) on iOS Safari. */
        position: fixed;
        top: var(--topnav-h, 3.5rem);   /* sits immediately below the top-row nav bar */
        left: 0;
        right: 0;
        /* NOT inset by --float-zone-h. Span's container is `position: fixed` with `overflow: hidden`
           specifically so the page cannot rubber-band on iOS, which means insetting it CLIPS the
           board rather than resizing it — measured at 443x660, 18 islands went out of reach. The
           reservation belongs in --chrome-h below, which is the budget the board is actually sized
           from. */
        bottom: 0;
        height: auto;  /* let top/bottom define the height */
        overflow: hidden;
        /*
         * Chrome budget (subtracted from 100dvh when computing board size):
         *   80px  — game header (compact two-row mobile layout)
         *   --podium-h — podium strip in group mode (0px solo, 120px group)
         *   --float-zone-h — the floating feedback FAB + chat bar's reserved band
         *   env() — iOS home-indicator safe area
         *
         * --float-zone-h REPLACES the bare 40px that used to be written here for the chat bar
         * (task 1129). The old number covered the chat and knew nothing about the feedback FAB,
         * which is the widget that was actually sitting on the board — measured with an island
         * fully covered at 390x700 and 443x750. Deriving it from the shared token means both
         * widgets are accounted for, and a change to either cannot silently start covering the
         * islands again.
         */
        --chrome-h: calc(80px + var(--podium-h, 0px) + var(--float-zone-h, 0px) + env(safe-area-inset-bottom, 0px));
    }

    header[b-pfr9g0hqjq] {
        padding: 0.35rem 0.75rem;
        gap: 0.25rem;
    }

    header h1[b-pfr9g0hqjq] {
        font-size: 1rem;
    }

    [b-pfr9g0hqjq] .toolbar-actions {
        gap: 0.4rem;
        flex-wrap: wrap;
        overflow-x: visible;
    }

    [b-pfr9g0hqjq] .btn-primary,
    [b-pfr9g0hqjq] .form-select,
    [b-pfr9g0hqjq] .btn-sm {
        font-size: 0.75rem;
        padding: 0.2rem 0.45rem;
    }

    .game-layout[b-pfr9g0hqjq] {
        flex: 1;
        min-height: 0;
        display: flex;
        flex-direction: column;
        overflow: hidden;
    }

    .board-section[b-pfr9g0hqjq] {
        flex: 1;
        min-height: 0;
        /* Allow the board to scroll/pan in BOTH axes — dense boards (20x20,
           25x25) cannot fit a phone, so every cell must remain reachable
           rather than being clipped. */
        overflow: auto;
        -webkit-overflow-scrolling: touch;
        display: flex;
        /* `safe` keeps the top-left of an overflowing board reachable: plain
           center alignment would push the overflow off the scrollable origin,
           making the first rows/columns unreachable. */
        align-items: safe center;
        justify-content: safe center;
        padding: 0;
    }

    .span-grid-wrapper[b-pfr9g0hqjq] {
        /* Shrink-wrap the (possibly oversized) grid so the wrapper itself is as
           wide/tall as the board. That makes the board-section's overflow:auto
           actually scrollable; min-width:100% keeps a fit-on-screen board
           centered. NEVER clip. */
        width: max-content;
        min-width: 100%;
        max-width: none;
        margin: 0 auto;
        /* Task 1568: bumped from 0.4rem alongside the desktop padding above, same reasoning —
           replacing breathing room the tight trim no longer supplies via phantom cells. Kept
           smaller than desktop's 1.5rem: mobile is already budget-constrained (see --avail-w/
           --avail-h below) and a large padding here eats directly into --cell's fit budget. */
        padding: 0.6rem;
        box-sizing: border-box;
        display: flex;
        align-items: safe center;
        justify-content: safe center;
        overflow: visible;
    }

    /* Mobile differs from desktop ONLY in these budgets — the sizing MECHANISM is shared (see
       the .span-grid rule above). Both axes are real constraints on a phone, so --fit-cell's
       min() has something to choose between; on desktop the height budget is unconstrained.
         --avail-w: the real container (see .board-section) minus the wrapper's own 0.4rem padding
                    either side. Was `calc(100vw - 0.8rem)`; 100cqw is the same number on a
                    full-bleed phone AND stays correct in the 641-767px band, where the container
                    is inset by the sidebar and 100vw was not (see the band block below).
         --avail-h: the viewport minus the top nav (var(--topnav-h)) and --chrome-h (header +
                    podium + float zone + safe area), which .app-container defines above.
       The HEIGHT axis stays an explicit budget and that is not an oversight: CSS can read a
       container's inline size (cqw) but not a usable block size here, since every ancestor up to
       .app-container is auto-height. So the width axis is now measured and the height axis is
       still declared. Say that plainly rather than claim the whole formula is drift-proof.
       A board too dense to fit keeps tappable cells (the --min-cell floor wins) and overflows
       into .board-section's scroll, rather than being crushed to a few px or clipped. */
    .span-grid[b-pfr9g0hqjq] {
        --grid-gap: 0.35rem;
        --avail-w: calc(100cqw - 0.8rem);
        --avail-h: calc(100dvh - var(--topnav-h, 3.5rem) - var(--chrome-h, 0px));
        flex: none;
    }

    .board-section .island.hovered[b-pfr9g0hqjq]::after,
    .board-section .island.active[b-pfr9g0hqjq]::after {
        display: none;
    }

    .board-section .island.active[b-pfr9g0hqjq] {
        transform: scale(1.05);
    }
}

/* === THE 641-767px BAND: mobile game, but the sidebar is already in flow === */
/* MainLayout.razor.css switches .page to flex-direction:row with a 250px STICKY sidebar at
   min-width:641px, while the mobile block above runs until max-width:767px. Those two disagree
   for 127px, and Span is the only game that notices: alone among the four it makes
   .app-container `position: fixed`, which takes it out of that flex row. A fixed box resolves
   left/right against the VIEWPORT, so `left: 0` parks the board underneath the sidebar
   (z-index 1050 vs the grid's 5) and `--avail-w: 100vw` sizes it as if the sidebar were not
   there. Grid/Lex/Lattice keep .app-container in flow, so the flex row shifts them clear and
   they never hit this.

   We keep the fixed positioning — it exists to stop iOS Safari rubber-banding the page body,
   and un-fixing it here would dump a 100vw-wide board into a 450px column and overflow the
   document instead. We just tell it about the sidebar it is sharing the viewport with.

   var(--sidebar-w) is MainLayout.razor.css's sidebar width for this same min-width:641px range
   (app.css :root, task 939); if that number moves, this must move with it.

   Task 1401's second clause, `(min-width: 641px) and (max-height: 500px)`, mirrors the OR added to
   the mobile block above: whenever the fixed-position rule fires because the viewport is SHORT
   rather than narrow, the sidebar may still be present (it persists from 641px up with no upper
   width bound) and `.app-container` still needs the same offset, for the same reason. */
@media (min-width: 641px) and (max-width: 767px),
       (min-width: 641px) and (max-height: 500px) {
    .app-container[b-pfr9g0hqjq] {
        left: var(--sidebar-w, 250px);
    }

    /* The --avail-w override that used to live here is GONE (task 1028). It read
       `calc(100vw - var(--sidebar-w, 250px) - 0.8rem)` — a third copy of the sidebar width. It is
       now redundant rather than merely tidied away: `left: var(--sidebar-w)` above already insets
       the fixed container, so .board-section's inline size is ALREADY viewport-minus-sidebar, and
       the mobile block's `100cqw` reads exactly that. The sidebar is subtracted once, by the rule
       that actually moves the box, instead of twice by two rules that had to agree. */
}
