:root {
    --primary: #0056b3;
    --primary-hover: #004494;
    --primary-light: rgba(0, 86, 179, 0.08);
    --primary-outline: rgba(0, 86, 179, 0.4);
    --success: #28a745;
    --success-hover: #218838;
    --alert: #dc3545;
    --alert-hover: #c82333;
    --alert-light: rgba(220, 53, 69, 0.08);
    --bg-body: #f4f7f6;
    --bg-card: #ffffff;
    --text-primary: #1a1a2e;
    --text-secondary: #5a6474;
    /* Darkened from #8e99a4, which measured 2.90:1 on a white card and failed AA
       everywhere it was used: every .settings-description and every .form-hint in
       the app. This is a text-only token, so raising its contrast is safe. */
    --text-muted: #63707e;   /* 5.06:1 on --bg-card AND 4.68:1 on --bg-surface; the
                                previous #6a7783 measured 4.46:1 on --bg-surface, which
                                is what every bento tile is built on. */

    /* Text-on-tint variants. --success / --alert are FILL colours (the green
       present disc, the red absent ring) and must keep their brand values, but the
       same hue used as TEXT on its own 8-10% tint measured 2.82:1 and 4.04:1. These
       are the accessible text versions; never use them as a fill. */
    --success-text: #1e7e34;
    --alert-text: #d12435;
    /* Blue for text on a card, and blue for a button fill, cannot be one value in
       dark mode: text needs to get lighter and a fill needs to get darker. */
    --primary-text: #0056b3;
    --primary-fill: #0056b3;
    --border-color: #dce1e6;
    --border-focus: var(--primary);
    --warn-text: #856404;
    --shadow-card: 0 4px 12px rgba(0, 0, 0, 0.08);
    --shadow-card-hover: 0 8px 24px rgba(0, 0, 0, 0.12);
    --shadow-btn: 0 2px 4px rgba(0, 0, 0, 0.1);
    --radius-sm: 8px;
    --radius-md: 12px;
    --radius-lg: 16px;
    --radius-xl: 20px;
    --radius-full: 50%;
    --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    --transition-fast: 150ms ease;
    --transition-base: 200ms ease;
    --transition-slow: 300ms ease;

    /* ---- Type scale: seven steps, replacing 23 ad-hoc sizes ---- */
    --fs-display: 3.25rem;   /* hero figures only: attendance %, alert count */
    --fs-h1: 1.875rem;
    --fs-h2: 1.375rem;
    --fs-h3: 1.0625rem;
    --fs-body: 1rem;
    --fs-sm: 0.875rem;
    --fs-label: 0.75rem;

    --lh-tight: 1.05;
    --track-display: -0.03em;
    --track-tight: -0.02em;
    --track-label: 0.06em;

    /* ---- Elevation: three levels, so importance is legible ---- */
    --elev-1: 0 1px 2px rgba(16, 24, 40, 0.04), 0 1px 3px rgba(16, 24, 40, 0.06);
    --elev-2: 0 4px 8px -2px rgba(16, 24, 40, 0.08), 0 2px 4px -2px rgba(16, 24, 40, 0.06);
    --elev-3: 0 16px 32px -8px rgba(16, 24, 40, 0.14), 0 4px 8px -4px rgba(16, 24, 40, 0.08);
    --hairline: rgba(16, 24, 40, 0.08);

    /* Warm-neutral card tint: kills the flat default-white look */
    --bg-surface: #fbfcfd;
}

/* ============ DARK THEME ============ */
[data-theme="dark"] {
    --primary: #3b82f6;
    --primary-hover: #2563eb;
    --primary-light: rgba(59, 130, 246, 0.16);
    --primary-outline: rgba(59, 130, 246, 0.5);
    --success: #34d399;
    --success-hover: #10b981;
    --alert: #f87171;
    --alert-hover: #ef4444;
    --alert-light: rgba(248, 113, 113, 0.14);
    --bg-body: #0f172a;
    --bg-card: #1e293b;
    --text-primary: #f1f5f9;
    --text-secondary: #94a3b8;
    /* #7c8798 measured 4.02:1 on the dark card. */
    --text-muted: #8791a1;
    --success-text: #34d399;
    /* #f87171 measured 4.34:1 on its own tint. */
    --alert-text: #f87b7b;
    /* #3b82f6 as text on the dark card measured 3.98:1, and as a button fill under
       a white label measured 3.68:1 — so the two roles need opposite corrections. */
    --primary-text: #5190f7;
    --primary-fill: #196cf4;
    --border-color: #334155;
    --warn-text: #fbbf24;
    --shadow-card: 0 4px 14px rgba(0, 0, 0, 0.45);
    --shadow-card-hover: 0 10px 28px rgba(0, 0, 0, 0.55);
    --shadow-btn: 0 2px 6px rgba(0, 0, 0, 0.35);

    --elev-1: 0 1px 2px rgba(0, 0, 0, 0.30);
    --elev-2: 0 4px 10px -2px rgba(0, 0, 0, 0.40);
    --elev-3: 0 18px 36px -10px rgba(0, 0, 0, 0.60), 0 4px 10px -4px rgba(0, 0, 0, 0.45);
    --hairline: rgba(255, 255, 255, 0.10);
    --bg-surface: #1b2637;
}

/* Hero figures: fixed-width digits so live counts never jitter as they update. */
.num {
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

/* Smooth cross-fade when switching themes */
body,
.app-header,
.card,
.tab-bar,
.tab-btn,
.form-input,
.role-card {
    transition: background-color var(--transition-base), border-color var(--transition-base), color var(--transition-base);
}

@media (prefers-reduced-motion: reduce) {
    body,
    .app-header,
    .card,
    .tab-bar,
    .tab-btn,
    .form-input,
    .role-card {
        transition: none;
    }
}

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

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

body {
    font-family: var(--font);
    background-color: var(--bg-body);
    color: var(--text-primary);
    line-height: 1.6;
    min-height: 100vh;
}

.icon-svg {
    display: inline-block;
    width: 1em;
    height: 1em;
    vertical-align: -0.15em;
    flex-shrink: 0;
}

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

.app-header {
    background: linear-gradient(135deg, var(--primary) 0%, #003d80 100%);
    color: #ffffff;
    padding: 0;
    position: sticky;
    top: 0;
    z-index: 100;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}

.header-inner {
    max-width: 960px;
    margin: 0 auto;
    padding: 0.75rem 1.5rem;
    display: flex;
    justify-content: space-between;
    align-items: center;
}

#main-nav {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: nowrap;
}

.header-brand {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.brand-icon {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    background: rgba(255, 255, 255, 0.2);
    border-radius: var(--radius-sm);
    font-size: 1.25rem;
    font-weight: 700;
}

.brand-logo-lg {
    display: flex;
    align-items: center;
    justify-content: center;
    margin: 0 auto 0.75rem;
}

/* Keep the shield body visible in dark mode (its default fill matches the dark background). */
[data-theme="dark"] .brand-logo-lg path[fill="#0f172a"] {
    fill: #1e293b;
}

.theme-toggle {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 38px;
    height: 38px;
    padding: 0;
    font-size: 1.15rem;
    color: #ffffff;
    background: rgba(255, 255, 255, 0.14);
    border: 1px solid rgba(255, 255, 255, 0.22);
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: background var(--transition-fast), transform var(--transition-fast);
}

.theme-toggle:hover {
    background: rgba(255, 255, 255, 0.26);
}

.theme-toggle:active {
    transform: scale(0.92);
}

.theme-toggle:focus-visible {
    outline: 3px solid rgba(255, 255, 255, 0.6);
    outline-offset: 2px;
}

.theme-toggle .icon-svg {
    transition: transform var(--transition-base);
}

/* Login-screen variant sits on a light card, so it needs dark-on-light styling */
.theme-toggle-login {
    position: absolute;
    top: 1rem;
    right: 1rem;
    color: var(--text-secondary);
    background: transparent;
    border: 1px solid var(--border-color);
}

.theme-toggle-login:hover {
    background: var(--primary-light);
    color: var(--primary);
}

.theme-toggle-login:focus-visible {
    outline: 3px solid var(--primary-outline);
}

.account-chip {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    background: rgba(255, 255, 255, 0.12);
    border: 1px solid rgba(255, 255, 255, 0.18);
    border-radius: var(--radius-sm);
    padding: 0.3rem 0.75rem 0.3rem 0.3rem;
    max-width: 220px;
}

.account-avatar {
    width: 26px;
    height: 26px;
    border-radius: var(--radius-sm);
    background: rgba(255, 255, 255, 0.28);
    color: #ffffff;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 700;
    font-size: 0.75rem;
    flex-shrink: 0;
}

.account-text {
    display: flex;
    flex-direction: column;
    line-height: 1.2;
    min-width: 0;
}

.account-role-badge {
    color: #ffffff;
    font-weight: 600;
    font-size: 0.75rem;
    text-transform: capitalize;
}

.account-id {
    color: rgba(255, 255, 255, 0.75);
    font-size: 0.688rem;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

@media (max-width: 560px) {
    .account-chip {
        max-width: 40px;
        padding: 0.3rem;
    }
    .account-text {
        display: none;
    }
}

.brand-title {
    font-size: 1.25rem;
    font-weight: 700;
    letter-spacing: -0.02em;
}

#app-container {
    max-width: 960px;
    margin: 0 auto;
    padding: 1.5rem;
    min-height: calc(100vh - 60px);
}

.app-container-centered {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
}

/* Keep entry-screen content above the background glows. */
#app-container {
    position: relative;
    z-index: 1;
}

/* Soft on-brand background glows for the login / role-selection screens.
   They sit in the page margins, well behind the solid card, so text
   contrast on the card is never affected. */
body.auth-glow::before,
body.auth-glow::after {
    content: "";
    position: fixed;
    border-radius: 50%;
    filter: blur(90px);
    pointer-events: none;
    z-index: 0;
}

body.auth-glow::before {
    width: 520px;
    height: 520px;
    top: -170px;
    right: -130px;
    background: radial-gradient(circle, rgba(37, 99, 235, 0.18), transparent 70%);
    animation: glowDriftA 16s ease-in-out infinite alternate;
}

body.auth-glow::after {
    width: 460px;
    height: 460px;
    bottom: -170px;
    left: -130px;
    background: radial-gradient(circle, rgba(34, 197, 94, 0.13), transparent 70%);
    animation: glowDriftB 20s ease-in-out infinite alternate;
}

[data-theme="dark"] body.auth-glow::before {
    background: radial-gradient(circle, rgba(59, 130, 246, 0.30), transparent 70%);
}

[data-theme="dark"] body.auth-glow::after {
    background: radial-gradient(circle, rgba(52, 211, 153, 0.16), transparent 70%);
}

@keyframes glowDriftA {
    from { transform: translate(0, 0); }
    to   { transform: translate(-40px, 40px); }
}

@keyframes glowDriftB {
    from { transform: translate(0, 0); }
    to   { transform: translate(40px, -30px); }
}

@media (prefers-reduced-motion: reduce) {
    body.auth-glow::before,
    body.auth-glow::after {
        animation: none;
    }
}

.app-container-wide {
    display: flex;
    flex-direction: column;
    align-items: stretch;
}

.card {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 2rem;
    width: 100%;
    max-width: 440px;
    transition: box-shadow var(--transition-base);
}

.card-relative {
    position: relative;
}

.card-lg {
    max-width: 720px;
}

.card-heading {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.25rem;
    letter-spacing: -0.02em;
}

.card-subtitle {
    font-size: 0.938rem;
    color: var(--text-secondary);
    margin-bottom: 1.75rem;
    line-height: 1.5;
}

.form-group {
    margin-bottom: 1rem;
}

.form-label {
    display: block;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
    margin-bottom: 0.375rem;
}

.form-input {
    width: 100%;
    padding: 0.75rem 1rem;
    font-family: var(--font);
    font-size: 1rem;
    color: var(--text-primary);
    background: var(--bg-card);
    border: 1.5px solid var(--border-color);
    border-radius: var(--radius-sm);
    transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
    -webkit-appearance: none;
    appearance: none;
}

.form-input::placeholder {
    color: var(--text-muted);
}

.form-input:focus {
    outline: none;
    border-color: var(--border-focus);
    box-shadow: 0 0 0 3px var(--primary-outline);
}

.btn {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.75rem 1.5rem;
    font-family: var(--font);
    font-size: 1rem;
    font-weight: 600;
    line-height: 1.5;
    color: #ffffff;
    /* --primary-fill, not --primary: the white label needs 4.5:1 against this. */
    background: var(--primary-fill);
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: all var(--transition-base);
    box-shadow: var(--shadow-btn);
    text-decoration: none;
    white-space: nowrap;
    -webkit-appearance: none;
    appearance: none;
}

.btn:hover {
    background: var(--primary-hover);
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.15);
    transform: translateY(-1px);
}

.btn:active {
    transform: translateY(0);
    box-shadow: var(--shadow-btn);
}

.btn:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.btn:disabled {
    opacity: 0.65;
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.btn-block {
    display: flex;
    width: 100%;
}

.btn-success {
    background: var(--success);
}

.btn-success:hover {
    background: var(--success-hover);
}

.btn-alert {
    background: var(--alert);
}

.btn-alert:hover {
    background: var(--alert-hover);
}

.btn-outline {
    background: transparent;
    /* Blue AS TEXT here, so it takes the text variant. */
    color: var(--primary-text);
    border: 1.5px solid var(--primary-text);
    box-shadow: none;
}

.btn-outline:hover {
    background: var(--primary-light);
    box-shadow: none;
    transform: none;
}

.btn-outline-light {
    background: rgba(255, 255, 255, 0.15);
    color: #ffffff;
    border: 1.5px solid rgba(255, 255, 255, 0.4);
    box-shadow: none;
}

.btn-outline-light:hover {
    background: rgba(255, 255, 255, 0.25);
    box-shadow: none;
    transform: none;
}

.btn-sm {
    padding: 0.5rem 1rem;
    font-size: 0.875rem;
}

.btn-lg {
    padding: 1rem 2rem;
    font-size: 1.125rem;
    border-radius: var(--radius-md);
}

.btn-google {
    background: #ffffff;
    color: #1a1a2e;
    border: 1.5px solid var(--border-color);
}

.btn-google:hover {
    background: #f1f3f4;
    border-color: #bcc3cc;
}

.btn-google:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.btn-stack {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.divider {
    display: flex;
    align-items: center;
    gap: 1rem;
    margin: 1.5rem 0;
    color: var(--text-muted);
    font-size: 0.813rem;
    font-weight: 500;
    text-transform: uppercase;
    letter-spacing: 0.05em;
}

.divider::before,
.divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: var(--border-color);
}

.spinner {
    width: 20px;
    height: 20px;
    border: 2.5px solid rgba(255, 255, 255, 0.3);
    border-top-color: #ffffff;
    border-radius: var(--radius-full);
    animation: spin 0.6s linear infinite;
}

.spinner-dark {
    border-color: rgba(0, 0, 0, 0.15);
    border-top-color: var(--primary);
}

.spinner-lg {
    width: 40px;
    height: 40px;
    border-width: 3.5px;
}

@keyframes spin {
    to { transform: rotate(360deg); }
}

.page-loader {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1rem;
    min-height: 60vh;
}

.loader-text {
    font-size: 0.938rem;
    color: var(--text-secondary);
    font-weight: 500;
}

.fade-in {
    animation: fadeIn var(--transition-slow) ease-out;
}

@keyframes fadeIn {
    from { opacity: 0; transform: translateY(8px); }
    to { opacity: 1; transform: translateY(0); }
}

.role-welcome {
    font-size: 0.938rem;
    font-weight: 700;
    color: var(--primary);
    margin: 0 0 0.25rem;
}

.role-grid {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    gap: 0.875rem;
    border: 0;
    padding: 0;
    margin: 0;
}

.role-card {
    position: relative;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.625rem;
    flex: 0 1 150px;
    padding: 1.5rem 1rem;
    background: var(--bg-card);
    border: 2px solid var(--border-color);
    border-radius: var(--radius-md);
    cursor: pointer;
    transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1),
                box-shadow 0.25s ease,
                border-color 0.2s ease,
                opacity 0.25s ease,
                background 0.2s ease;
    font-family: var(--font);
    font-size: 0.938rem;
    font-weight: 600;
    color: var(--text-primary);
    animation: roleCardIn 0.4s ease backwards;
}

.role-card[data-role="parent"]    { --role-color: #2563eb; --role-soft: rgba(37, 99, 235, 0.10); }
.role-card[data-role="teacher"]   { --role-color: #4f46e5; --role-soft: rgba(79, 70, 229, 0.10); }
.role-card[data-role="coach"]     { --role-color: #d97706; --role-soft: rgba(217, 119, 6, 0.12); }
.role-card[data-role="principal"] { --role-color: #0891b2; --role-soft: rgba(8, 145, 178, 0.10); }
.role-card[data-role="admin"]     { --role-color: #7c3aed; --role-soft: rgba(124, 58, 237, 0.10); }

.role-card[data-role="parent"]    { animation-delay: 0.02s; }
.role-card[data-role="teacher"]   { animation-delay: 0.06s; }
.role-card[data-role="coach"]     { animation-delay: 0.10s; }
.role-card[data-role="principal"] { animation-delay: 0.14s; }
.role-card[data-role="admin"]     { animation-delay: 0.18s; }

@keyframes roleCardIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Dim the non-selected cards once a choice is made */
.role-grid:has(.role-card-input:checked) .role-card:not(:has(.role-card-input:checked)) {
    opacity: 0.45;
    transform: scale(0.97);
}

.role-card:hover {
    border-color: var(--role-color);
    transform: translateY(-5px);
    box-shadow: 0 12px 24px -8px var(--role-soft), 0 6px 12px -6px rgba(0, 0, 0, 0.12);
}

.role-card:hover .role-icon-badge {
    transform: scale(1.08);
}

.role-card:has(.role-card-input:focus-visible) {
    outline: 3px solid var(--role-color);
    outline-offset: 3px;
}

.role-card:has(.role-card-input:checked) {
    border-color: var(--role-color);
    background: var(--role-soft);
    box-shadow: 0 0 0 1px var(--role-color), 0 10px 22px -8px var(--role-soft);
}

.role-card:has(.role-card-input:checked)::after {
    content: '\2713';
    position: absolute;
    top: 8px;
    right: 8px;
    width: 22px;
    height: 22px;
    border-radius: 50%;
    background: var(--role-color);
    color: #ffffff;
    font-size: 0.75rem;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    line-height: 1;
    animation: checkPop 0.3s cubic-bezier(0.34, 1.56, 0.64, 1);
}

@keyframes checkPop {
    from { transform: scale(0); }
    to   { transform: scale(1); }
}

.role-icon-badge {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 54px;
    height: 54px;
    border-radius: var(--radius-md);
    font-size: 1.5rem;
    color: #ffffff;
    background: var(--role-color);
    box-shadow: 0 4px 10px -3px var(--role-soft);
    transition: transform 0.25s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.role-continue-btn {
    margin-top: 1.5rem;
    transition: opacity 0.25s ease, transform 0.15s ease;
}

.role-continue-btn:disabled {
    opacity: 0.45;
    cursor: not-allowed;
}

@media (prefers-reduced-motion: reduce) {
    .role-card,
    .role-icon-badge,
    .role-card:has(.role-card-input:checked)::after {
        animation: none;
        transition: border-color 0.2s ease, background 0.2s ease, opacity 0.2s ease;
    }
    .role-card:hover { transform: none; }
}

.alert-banner {
    padding: 0.75rem 1rem;
    border-radius: var(--radius-sm);
    font-size: 0.875rem;
    font-weight: 500;
    margin-bottom: 1rem;
}

.alert-error {
    background: var(--alert-light);
    color: var(--alert);
    border: 1px solid rgba(220, 53, 69, 0.2);
}

@media (max-width: 480px) {
    .card {
        padding: 1.5rem;
        border-radius: var(--radius-sm);
    }

    #app-container {
        padding: 1rem;
    }

    .role-card {
        flex-basis: 100%;
    }

    .card-heading {
        font-size: 1.25rem;
    }
}

.form-hint {
    font-size: 0.8rem;
    color: var(--text-muted);
    margin-top: 0.25rem;
}

.view-header {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 1.5rem 2rem;
    margin-bottom: 1rem;
}

.view-header-top {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.view-title {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-primary);
    letter-spacing: -0.02em;
}

.view-date {
    font-size: 0.875rem;
    color: var(--text-secondary);
    font-weight: 500;
}

.stats-bar {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(100px, 1fr));
    gap: 0.75rem;
}

.stat-chip {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 0.75rem 0.5rem;
    border-radius: var(--radius-sm);
    text-align: center;
}

.stat-value {
    font-size: 1.5rem;
    font-weight: 700;
    line-height: 1.2;
}

.stat-label {
    font-size: 0.75rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: 0.125rem;
}

.stat-present {
    background: rgba(40, 167, 69, 0.1);
    color: var(--success);
}

.stat-absent {
    background: var(--alert-light);
    color: var(--alert);
}

.stat-practice {
    background: rgba(0, 86, 179, 0.08);
    color: var(--primary);
}

.stat-total {
    background: rgba(90, 100, 116, 0.1);
    color: var(--text-secondary);
}

.search-bar {
    margin-bottom: 0.75rem;
}

.search-input {
    padding-left: 2.75rem;
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='18' height='18' viewBox='0 0 24 24' fill='none' stroke='%238e99a4' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='11' cy='11' r='8'%3E%3C/circle%3E%3Cline x1='21' y1='21' x2='16.65' y2='16.65'%3E%3C/line%3E%3C/svg%3E");
    background-repeat: no-repeat;
    background-position: 0.875rem center;
}

.grade-filter {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1rem;
    flex-wrap: wrap;
}

.filter-chip {
    padding: 0.4375rem 1rem;
    font-family: var(--font);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-secondary);
    background: var(--bg-card);
    border: 1.5px solid var(--border-color);
    border-radius: 100px;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.filter-chip:hover {
    border-color: var(--primary);
    color: var(--primary);
}

.filter-chip.active {
    background: var(--primary);
    color: #ffffff;
    border-color: var(--primary);
}

.filter-chip:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.student-list-container {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}

.student-list {
    display: flex;
    flex-direction: column;
}

.grade-divider {
    padding: 0.625rem 1.5rem;
    background: var(--bg-body);
    font-size: 0.75rem;
    font-weight: 700;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.06em;
    border-top: 1px solid var(--border-color);
    border-bottom: 1px solid var(--border-color);
}

.student-row {
    display: flex;
    align-items: center;
    padding: 0.875rem 1.5rem;
    border-bottom: 1px solid rgba(220, 225, 230, 0.6);
    transition: background var(--transition-fast);
}

.student-row:last-child {
    border-bottom: none;
}

.student-row:hover {
    background: rgba(0, 86, 179, 0.03);
}

.student-row.status-absent {
    background: rgba(220, 53, 69, 0.04);
}

.student-row.status-absent:hover {
    background: rgba(220, 53, 69, 0.07);
}

.student-row.status-practice {
    background: rgba(0, 86, 179, 0.04);
}

.student-label {
    display: flex;
    align-items: center;
    gap: 0.875rem;
    flex: 1;
    cursor: pointer;
    position: relative;
}

/* The native checkbox is invisible (the .checkmark span is what you see), but it
   must keep REAL, NON-ZERO BOUNDS. It was previously hidden with width:0;height:0,
   which left it in the accessibility tree with an empty bounding box. TalkBack
   orders linear navigation spatially, and it cannot derive a "next" element from a
   zero-area rect — so on Android, focusing a student row let you swipe left but
   never right. The register became a dead end escapable only through Controls
   navigation.

   It is now stretched transparently over the whole label — indicator plus name —
   which keeps the visual design identical, gives TalkBack a real rectangle to
   traverse, and makes the double-tap target the full row instead of a small dot.
   Never reintroduce width:0/height:0 on a focusable control. */
.student-checkbox {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    margin: 0;
    padding: 0;
    opacity: 0;
    cursor: pointer;
}

.checkmark {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 24px;
    height: 24px;
    min-width: 24px;
    border: 2px solid var(--border-color);
    border-radius: var(--radius-full);
    transition: all var(--transition-fast);
    background: var(--bg-card);
}

.checkmark::after {
    content: '';
    display: none;
    width: 6px;
    height: 11px;
    border: solid #ffffff;
    border-width: 0 2.5px 2.5px 0;
    transform: rotate(45deg);
    margin-top: -2px;
}

.student-label:hover .checkmark {
    border-color: var(--success);
}

.student-checkbox:checked + .checkmark {
    background: var(--success);
    border-color: var(--success);
}

.student-checkbox:checked + .checkmark::after {
    display: block;
}

.student-checkbox:disabled + .checkmark {
    background: var(--primary);
    border-color: var(--primary);
    opacity: 0.7;
}

.student-checkbox:disabled + .checkmark::after {
    display: block;
}

.student-checkbox:focus-visible + .checkmark {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.student-info {
    display: flex;
    flex-direction: column;
}

.student-name {
    font-size: 0.9375rem;
    font-weight: 600;
    color: var(--text-primary);
    line-height: 1.3;
}

.student-grade {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-weight: 500;
}

.student-status {
    font-size: 0.8125rem;
    font-weight: 600;
    margin-left: auto;
    padding-left: 1rem;
    white-space: nowrap;
}

.status-present-text {
    color: var(--success);
}

.status-absent-text {
    color: var(--alert);
}

.status-practice-text {
    color: var(--primary);
}

.practice-badge {
    font-size: 0.6875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.1875rem 0.5rem;
    background: rgba(0, 86, 179, 0.12);
    color: var(--primary);
    border-radius: 100px;
    margin-left: 0.5rem;
    white-space: nowrap;
}

.empty-state {
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 3rem 1.5rem;
}

.empty-text {
    font-size: 0.938rem;
    color: var(--text-muted);
    font-weight: 500;
}

@media (max-width: 600px) {
    .stats-bar {
        grid-template-columns: repeat(2, 1fr);
    }

    .view-header {
        padding: 1.25rem;
    }

    .student-row {
        padding: 0.75rem 1rem;
    }

    .grade-divider {
        padding: 0.5rem 1rem;
    }

    .view-header-top {
        flex-direction: column;
        gap: 0.25rem;
    }
}

.sport-tag {
    display: inline-block;
    font-size: 0.6875rem;
    font-weight: 600;
    color: var(--primary);
    background: rgba(0, 86, 179, 0.08);
    padding: 0.125rem 0.5rem;
    border-radius: 100px;
    margin-top: 0.125rem;
}

.submit-bar {
    position: sticky;
    bottom: 0;
    background: var(--bg-body);
    padding: 1rem 0;
    margin-top: 1rem;
    z-index: 50;
}

.submit-bar::before {
    content: '';
    position: absolute;
    top: -16px;
    left: 0;
    right: 0;
    height: 16px;
    background: linear-gradient(to top, var(--bg-body), transparent);
    pointer-events: none;
}

.alert-screen {
    width: 100%;
}

.alert-screen-header {
    text-align: center;
    padding: 2rem 1.5rem 1.5rem;
    background: linear-gradient(135deg, rgba(220, 53, 69, 0.08) 0%, rgba(220, 53, 69, 0.02) 100%);
    border-radius: var(--radius-md);
    margin-bottom: 1rem;
}

.alert-screen-icon {
    font-size: 3rem;
    line-height: 1;
    display: block;
    margin-bottom: 0.75rem;
}

.alert-screen-title {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--alert);
    margin-bottom: 0.375rem;
    letter-spacing: -0.02em;
}

.alert-screen-subtitle {
    font-size: 1rem;
    color: var(--text-secondary);
    font-weight: 500;
}

.alert-summary-bar {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.stat-mismatch {
    background: rgba(220, 53, 69, 0.1);
    color: var(--alert);
}

.mismatch-list {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.mismatch-card {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    border-left: 4px solid var(--alert);
    padding: 1.25rem 1.5rem;
}

.mismatch-header {
    display: flex;
    align-items: flex-start;
    gap: 0.875rem;
    margin-bottom: 1rem;
}

.mismatch-icon {
    font-size: 1.5rem;
    line-height: 1;
    flex-shrink: 0;
    margin-top: 0.125rem;
    color: var(--alert);
}

.mismatch-info {
    flex: 1;
}

.mismatch-name {
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.375rem;
}

.mismatch-detail {
    font-size: 0.8125rem;
    font-weight: 500;
    line-height: 1.5;
}

.mismatch-parent {
    color: var(--success);
}

.mismatch-teacher {
    color: var(--alert);
}

.mismatch-actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.btn-action {
    display: inline-flex;
    align-items: center;
    gap: 0.375rem;
    padding: 0.5rem 1rem;
    font-family: var(--font);
    font-size: 0.8125rem;
    font-weight: 600;
    border-radius: var(--radius-sm);
    text-decoration: none;
    transition: all var(--transition-fast);
    border: none;
    cursor: pointer;
}

.btn-call-parent {
    background: rgba(40, 167, 69, 0.1);
    color: var(--success);
}

.btn-call-parent:hover {
    background: rgba(40, 167, 69, 0.2);
}

.btn-call-principal {
    background: rgba(220, 53, 69, 0.1);
    color: var(--alert);
}

.btn-call-principal:hover {
    background: rgba(220, 53, 69, 0.2);
}

.btn-coach {
    background: rgba(0, 86, 179, 0.1);
    color: var(--primary);
}

.btn-coach:hover {
    background: rgba(0, 86, 179, 0.2);
}

.btn-action:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.success-screen {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 3rem 1.5rem;
    width: 100%;
}

.success-icon-wrap {
    width: 80px;
    height: 80px;
    border-radius: var(--radius-full);
    background: rgba(40, 167, 69, 0.12);
    display: flex;
    align-items: center;
    justify-content: center;
    margin-bottom: 1.5rem;
    animation: scaleIn 0.4s ease-out;
}

.success-icon {
    font-size: 2.5rem;
    color: var(--success);
    font-weight: 700;
}

@keyframes scaleIn {
    from { transform: scale(0); opacity: 0; }
    to { transform: scale(1); opacity: 1; }
}

.success-title {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.375rem;
}

.success-subtitle {
    font-size: 1rem;
    color: var(--text-secondary);
    margin-bottom: 1.5rem;
}

.success-stats {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.75rem;
    width: 100%;
    max-width: 320px;
}

@media (max-width: 600px) {
    .alert-summary-bar {
        grid-template-columns: 1fr 1fr 1fr;
    }

    .mismatch-card {
        padding: 1rem 1.25rem;
    }

    .mismatch-actions {
        flex-direction: column;
    }

    .btn-action {
        justify-content: center;
    }

    .alert-screen-title {
        font-size: 1.25rem;
    }
}

.tab-bar {
    display: flex;
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 0.25rem;
    gap: 0.25rem;
    margin-bottom: 1rem;
}

.tab-btn {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.25rem;
    padding: 0.75rem 0.5rem;
    font-family: var(--font);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-muted);
    background: transparent;
    border: none;
    border-radius: var(--radius-sm);
    cursor: pointer;
    transition: all var(--transition-fast);
}

.tab-btn:hover {
    color: var(--primary);
    background: var(--primary-light);
}

.tab-btn.active {
    color: #ffffff;
    background: var(--primary);
    box-shadow: var(--shadow-btn);
}

.tab-btn:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.tab-icon {
    font-size: 1.25rem;
    line-height: 1;
}

.tab-label {
    line-height: 1;
}

.history-sub-tabs,
.settings-sections {
    display: flex;
    gap: 0.5rem;
    margin-bottom: 1rem;
}

.sub-tab {
    padding: 0.4375rem 1rem;
    font-family: var(--font);
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-secondary);
    background: var(--bg-card);
    border: 1.5px solid var(--border-color);
    border-radius: 100px;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.sub-tab:hover {
    border-color: var(--primary);
    color: var(--primary);
}

.sub-tab.active {
    background: var(--primary);
    color: #ffffff;
    border-color: var(--primary);
}

.sub-tab:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.history-container,
.settings-container {
    width: 100%;
}

.month-section {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    margin-bottom: 0.5rem;
    overflow: hidden;
}

.month-section.month-empty {
    opacity: 0.5;
}

.month-header-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 1rem 1.25rem;
    font-family: var(--font);
    font-size: 1rem;
    font-weight: 600;
    color: var(--text-primary);
    background: transparent;
    border: none;
    cursor: pointer;
    transition: background var(--transition-fast);
}

.month-header-btn:hover:not([disabled]) {
    background: var(--primary-light);
}

.month-header-btn:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: -3px;
}

.month-header-btn[disabled] {
    cursor: default;
}

.month-name {
    font-weight: 700;
}

.month-meta {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.month-days {
    font-size: 0.8125rem;
    color: var(--text-muted);
    font-weight: 500;
}

.month-pct {
    font-size: 0.8125rem;
    font-weight: 700;
    padding: 0.125rem 0.5rem;
    border-radius: 100px;
}

.pct-good { background: rgba(40, 167, 69, 0.1); color: var(--success); }
.pct-warn { background: rgba(255, 193, 7, 0.18); color: var(--warn-text); }
.pct-bad { background: var(--alert-light); color: var(--alert); }

.month-no-data {
    font-size: 0.8125rem;
    color: var(--text-muted);
    font-style: italic;
}

.chevron {
    display: inline-block;
    width: 8px;
    height: 8px;
    border-right: 2px solid var(--text-muted);
    border-bottom: 2px solid var(--text-muted);
    transform: rotate(45deg);
    transition: transform var(--transition-fast);
    margin-left: 0.5rem;
}

.month-header-btn.expanded .chevron {
    transform: rotate(-135deg);
}

.month-body {
    border-top: 1px solid var(--border-color);
}

.day-row-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.75rem 1.25rem;
    font-family: var(--font);
    font-size: 0.875rem;
    color: var(--text-primary);
    background: transparent;
    border: none;
    border-bottom: 1px solid rgba(220, 225, 230, 0.5);
    cursor: pointer;
    transition: background var(--transition-fast);
}

.day-row-btn:hover {
    background: rgba(0, 86, 179, 0.03);
}

.day-row-btn:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: -3px;
}

.day-row-btn.expanded {
    background: var(--primary-light);
    font-weight: 600;
}

.day-label {
    font-weight: 500;
}

.day-stats {
    display: flex;
    gap: 0.5rem;
}

.day-stat {
    font-size: 0.75rem;
    font-weight: 700;
    padding: 0.125rem 0.4rem;
    border-radius: 4px;
}

.day-present { background: rgba(40, 167, 69, 0.1); color: var(--success); }
.day-absent { background: var(--alert-light); color: var(--alert); }
.day-practice { background: rgba(0, 86, 179, 0.08); color: var(--primary); }

.day-detail {
    background: var(--bg-body);
    border-bottom: 1px solid var(--border-color);
}

.day-student-row {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    padding: 0.5rem 1.5rem;
    font-size: 0.8125rem;
    border-bottom: 1px solid rgba(220, 225, 230, 0.4);
}

.day-student-row:last-child {
    border-bottom: none;
}

.day-dot {
    width: 10px;
    height: 10px;
    min-width: 10px;
    border-radius: var(--radius-full);
}

.dot-present { background: var(--success); }
.dot-absent { background: var(--alert); }
.dot-practice { background: var(--primary); }

.dot-present-text { color: var(--success); }
.dot-absent-text { color: var(--alert); }
.dot-practice-text { color: var(--primary); }

.day-student-name {
    flex: 1;
    font-weight: 500;
    color: var(--text-primary);
}

.day-student-status {
    font-weight: 600;
    font-size: 0.75rem;
}

.student-select-bar {
    margin-bottom: 1rem;
}

.student-history-card {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 1.5rem;
}

.student-history-name {
    font-size: 1.125rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 1rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.student-month-block {
    margin-bottom: 1rem;
    padding-bottom: 1rem;
    border-bottom: 1px solid var(--border-color);
}

.student-month-block:last-of-type {
    border-bottom: none;
    margin-bottom: 0.5rem;
}

.student-month-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 0.5rem;
}

.student-month-name {
    font-size: 0.875rem;
    font-weight: 700;
    color: var(--text-primary);
}

.student-month-stats {
    display: flex;
    gap: 0.375rem;
}

.cal-dots {
    display: flex;
    flex-wrap: wrap;
    gap: 0.25rem;
}

.cal-dot {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 28px;
    height: 28px;
    border-radius: 6px;
    font-size: 0.6875rem;
    font-weight: 700;
    cursor: default;
}

.cal-dot.dot-present { background: rgba(40, 167, 69, 0.15); color: var(--success); }
.cal-dot.dot-absent { background: rgba(220, 53, 69, 0.15); color: var(--alert); }
.cal-dot.dot-practice { background: rgba(0, 86, 179, 0.12); color: var(--primary); }

.student-summary {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(80px, 1fr));
    gap: 0.5rem;
    margin-top: 0.5rem;
}

.settings-toolbar {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 1rem;
}

.settings-count {
    font-size: 0.875rem;
    color: var(--text-secondary);
    font-weight: 500;
}

.student-form-card {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 1.5rem;
    margin-bottom: 1rem;
    border-left: 4px solid var(--primary);
}

.form-card-title {
    font-size: 1.0625rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 1rem;
}

.form-row-2 {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 0.75rem;
}

.form-actions {
    display: flex;
    gap: 0.5rem;
    margin-top: 1rem;
}

.settings-student-list {
    display: flex;
    flex-direction: column;
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    overflow: hidden;
}

.settings-student-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0.875rem 1.25rem;
    border-bottom: 1px solid rgba(220, 225, 230, 0.6);
    gap: 0.75rem;
}

.settings-student-row:last-child {
    border-bottom: none;
}

.settings-student-info {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    min-width: 0;
}

.settings-student-meta {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.student-phone {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-weight: 500;
}

.settings-student-actions {
    display: flex;
    gap: 0.375rem;
    flex-shrink: 0;
}

.settings-card {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 1.5rem;
}

.settings-section-title {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.375rem;
}

.settings-current-value {
    font-size: 0.875rem;
    color: var(--text-secondary);
    font-weight: 500;
}

.settings-description {
    font-size: 0.8125rem;
    color: var(--text-muted);
    margin-bottom: 0.75rem;
}

.settings-msg {
    margin-top: 0.75rem;
    padding: 0.5rem 0.75rem;
    border-radius: var(--radius-sm);
    font-size: 0.8125rem;
    font-weight: 600;
}

.reminder-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    margin-bottom: 0.75rem;
}

.reminder-item {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.625rem 0.875rem;
    background: var(--primary-light);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
}

.reminder-time {
    font-weight: 700;
    color: var(--text-primary);
    font-variant-numeric: tabular-nums;
}

.reminder-add-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.msg-success {
    background: rgba(40, 167, 69, 0.1);
    color: var(--success-text);
}

.msg-error {
    background: var(--alert-light);
    color: var(--alert-text);
}

/* "Works, but not as well as it should" — used where a reminder is armed but
   Android may deliver it late. Deliberately not red: nothing is broken, so it
   must not read as an alert. */
.msg-warn {
    background: rgba(217, 119, 6, 0.12);
    color: var(--caution-text, #8a4b04);
}

[data-theme="dark"] .msg-warn {
    background: rgba(251, 191, 36, 0.14);
    color: #fcd34d;
}

@media (max-width: 600px) {
    .tab-bar {
        border-radius: var(--radius-sm);
    }

    .tab-btn {
        padding: 0.625rem 0.25rem;
        font-size: 0.75rem;
    }

    .tab-icon {
        font-size: 1.125rem;
    }

    .month-header-btn {
        padding: 0.875rem 1rem;
    }

    .day-row-btn {
        padding: 0.625rem 1rem;
    }

    .form-row-2 {
        grid-template-columns: 1fr;
    }

    .settings-student-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
    }

    .settings-student-actions {
        width: 100%;
    }

    .settings-student-actions .btn {
        flex: 1;
    }

    .cal-dot {
        width: 24px;
        height: 24px;
        font-size: 0.625rem;
    }
}

.parent-header {
    margin-bottom: 1rem;
}

.parent-children-list {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.parent-child-card {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 1.5rem;
    transition: all var(--transition-fast);
}

.parent-child-card.status-confirmed-yes {
    border-left: 4px solid var(--success);
}

.parent-child-card.status-confirmed-no {
    border-left: 4px solid var(--alert);
}

.child-card-name {
    font-size: 1.125rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.child-card-prompt {
    font-size: 1rem;
    color: var(--text-secondary);
    font-weight: 500;
    margin-bottom: 1rem;
}

.checkin-buttons {
    display: flex;
    gap: 0.75rem;
}

.btn-checkin {
    flex: 1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 1.5rem 1rem;
    border-radius: var(--radius-md);
    font-family: var(--font);
    font-weight: 700;
    font-size: 1rem;
    border: 2px solid transparent;
    cursor: pointer;
    transition: all var(--transition-fast);
}

.btn-yes {
    background: rgba(40, 167, 69, 0.1);
    color: var(--success);
    border-color: rgba(40, 167, 69, 0.3);
}

.btn-yes:hover {
    background: rgba(40, 167, 69, 0.18);
    border-color: var(--success);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(40, 167, 69, 0.2);
}

.btn-no {
    background: rgba(220, 53, 69, 0.08);
    color: var(--alert);
    border-color: rgba(220, 53, 69, 0.25);
}

.btn-no:hover {
    background: rgba(220, 53, 69, 0.15);
    border-color: var(--alert);
    transform: translateY(-2px);
    box-shadow: 0 4px 12px rgba(220, 53, 69, 0.2);
}

.btn-checkin:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.btn-checkin:active {
    transform: translateY(0);
}

.checkin-icon {
    font-size: 2.5rem;
    line-height: 1;
}

.checkin-text {
    font-size: 0.9375rem;
    line-height: 1.2;
}

.child-status-badge {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.875rem 1rem;
    border-radius: var(--radius-sm);
    margin-bottom: 0.75rem;
}

.child-status-badge.status-confirmed-yes {
    background: rgba(40, 167, 69, 0.08);
}

.child-status-badge.status-confirmed-no {
    background: rgba(220, 53, 69, 0.06);
}

.status-badge-icon {
    font-size: 1.5rem;
    line-height: 1;
    font-weight: 700;
}

.status-confirmed-yes .status-badge-icon { color: var(--success); }
.status-confirmed-no .status-badge-icon { color: var(--alert); }

.status-badge-info {
    display: flex;
    flex-direction: column;
}

.status-badge-text {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-primary);
}

.status-badge-time {
    font-size: 0.8125rem;
    color: var(--text-muted);
    font-weight: 500;
}

.child-teacher-status {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    font-size: 0.875rem;
    font-weight: 500;
    padding: 0.5rem 0;
    margin-bottom: 0.5rem;
}

.teacher-present { color: var(--success); }
.teacher-absent { color: var(--alert); }
.teacher-practice { color: var(--primary); }

.child-awaiting {
    font-size: 0.8125rem;
    color: var(--text-muted);
    font-style: italic;
    margin-bottom: 0.5rem;
}

.lock-msg {
    font-size: 0.8125rem;
    color: var(--text-muted);
    margin-bottom: 0.5rem;
    display: flex;
    align-items: center;
    gap: 0.375rem;
}

.btn-change-response {
    width: 100%;
    justify-content: center;
    display: flex;
    align-items: center;
    gap: 0.375rem;
}

@media (max-width: 480px) {
    .checkin-buttons {
        flex-direction: column;
    }

    .btn-checkin {
        padding: 1.25rem 1rem;
    }

    .checkin-icon {
        font-size: 2rem;
    }
}

.coach-status-collapse {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    margin-bottom: 0.75rem;
    overflow: hidden;
}

.coach-toggle-btn {
    width: 100%;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.875rem 1.25rem;
    font-family: var(--font);
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
    background: transparent;
    border: none;
    cursor: pointer;
    transition: background var(--transition-fast);
}

.coach-toggle-btn:hover {
    background: var(--primary-light);
}

.coach-toggle-btn:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: -3px;
}

.coach-toggle-label {
    flex: 1;
    text-align: left;
}

.coach-badge {
    font-size: 0.75rem;
    font-weight: 700;
    padding: 0.125rem 0.5rem;
    border-radius: 100px;
}

.badge-done {
    background: rgba(40, 167, 69, 0.1);
    color: var(--success);
}

.badge-partial {
    background: rgba(255, 193, 7, 0.15);
    color: var(--warn-text);
}

.badge-none {
    background: var(--alert-light);
    color: var(--alert);
}

.coach-toggle-btn .chevron {
    margin-left: 0;
}

.coach-toggle-btn.expanded .chevron {
    transform: rotate(-135deg);
}

.coach-status-panel {
    border-top: 1px solid var(--border-color);
    padding: 0.5rem 0;
}

.coach-sport-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.625rem 1.25rem;
}

.coach-sport-icon {
    font-size: 1rem;
    font-weight: 700;
    flex-shrink: 0;
}

.coach-done .coach-sport-icon {
    color: var(--success);
}

.coach-pending .coach-sport-icon {
    color: var(--text-muted);
}

.coach-sport-info {
    display: flex;
    flex-direction: column;
}

.coach-sport-name {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
}

.coach-sport-detail {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-weight: 500;
}

.coach-done .coach-sport-detail {
    color: var(--text-secondary);
}

.deadline-warning {
    display: flex;
    align-items: center;
    gap: 0.375rem;
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--warn-text);
    background: rgba(255, 193, 7, 0.12);
    padding: 0.5rem 1rem;
    border-radius: var(--radius-sm);
    margin-top: 0.75rem;
}

.coach-submitted-banner {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    background: rgba(40, 167, 69, 0.08);
    border: 1.5px solid rgba(40, 167, 69, 0.2);
    border-radius: var(--radius-md);
    padding: 1.25rem 1.5rem;
    margin-top: 1rem;
}

.submitted-icon {
    font-size: 1.5rem;
    color: var(--success);
    font-weight: 700;
}

.submitted-info {
    display: flex;
    flex-direction: column;
}

.submitted-text {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-primary);
}

.submitted-time {
    font-size: 0.8125rem;
    color: var(--text-muted);
    font-weight: 500;
}

.coach-info-row {
    display: flex;
    gap: 1.5rem;
    margin-top: 0.5rem;
    flex-wrap: wrap;
}

.principal-header {
    margin-bottom: 1rem;
}

.dash-stats-grid {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.dash-stat-card {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 1.25rem 1rem;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    transition: transform var(--transition-fast);
}

.dash-stat-card:hover {
    transform: translateY(-2px);
}

.dash-stat-value {
    font-size: 1.75rem;
    font-weight: 800;
    line-height: 1.2;
}

.dash-stat-label {
    font-size: 0.75rem;
    font-weight: 600;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.04em;
    margin-top: 0.25rem;
}

.dash-stat-present .dash-stat-value { color: var(--success); }
.dash-stat-absent .dash-stat-value { color: var(--alert); }
.dash-stat-practice .dash-stat-value { color: var(--primary); }

.dash-stat-rate .dash-stat-value { font-size: 2rem; }
.rate-high .dash-stat-value { color: var(--success); }
.rate-mid .dash-stat-value { color: var(--warn-text); }
.rate-low .dash-stat-value { color: var(--alert); }

.dash-section {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 1.25rem;
    margin-bottom: 1rem;
}

.dash-section-title {
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.dash-alert-badge {
    font-size: 0.6875rem;
    font-weight: 700;
    padding: 0.125rem 0.5rem;
    border-radius: 100px;
}

.badge-danger {
    background: var(--alert-light);
    color: var(--alert);
    animation: pulse-badge 2s ease-in-out infinite;
}

.badge-safe {
    background: rgba(40, 167, 69, 0.1);
    color: var(--success);
}

@keyframes pulse-badge {
    0%, 100% { opacity: 1; }
    50% { opacity: 0.6; }
}

.dash-coach-badge {
    font-size: 0.6875rem;
    font-weight: 700;
    padding: 0.125rem 0.5rem;
    border-radius: 100px;
    background: var(--primary-light);
    color: var(--primary);
}

.dash-alerts-list,
.dash-coach-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.principal-alert-card {
    background: rgba(220, 53, 69, 0.04);
    border: 1px solid rgba(220, 53, 69, 0.15);
    border-radius: var(--radius-sm);
    padding: 1rem;
    transition: all var(--transition-fast);
}

.principal-alert-card:hover {
    border-color: rgba(220, 53, 69, 0.35);
    box-shadow: 0 2px 8px rgba(220, 53, 69, 0.1);
}

.alert-resolved {
    background: rgba(40, 167, 69, 0.04);
    border-color: rgba(40, 167, 69, 0.15);
    opacity: 0.7;
}

.principal-alert-header {
    display: flex;
    align-items: flex-start;
    gap: 0.75rem;
    margin-bottom: 0.5rem;
}

.alert-icon-lg {
    font-size: 1.25rem;
    line-height: 1;
    flex-shrink: 0;
    color: var(--alert);
}

.alert-resolved .alert-icon-lg {
    color: var(--success);
}

.alert-info {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    flex: 1;
}

.alert-student-name {
    font-size: 0.9375rem;
    font-weight: 700;
    color: var(--text-primary);
    display: flex;
    align-items: center;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.alert-detail {
    font-size: 0.8125rem;
    color: var(--text-secondary);
    font-weight: 500;
}

.alert-actions {
    display: flex;
    gap: 0.5rem;
    flex-wrap: wrap;
    margin-top: 0.5rem;
    padding-top: 0.5rem;
    border-top: 1px solid rgba(0, 0, 0, 0.06);
}

.alerts-live-container {
    display: flex;
    flex-direction: column;
    gap: 0.75rem;
}

.alerts-summary {
    display: flex;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.alerts-group-title {
    font-size: 0.875rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    margin-bottom: 0.5rem;
}

.stat-alert .stat-value { color: var(--alert); }

.empty-alerts-state {
    text-align: center;
    padding: 3rem 1.5rem;
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
}

.empty-icon {
    font-size: 3rem;
    color: var(--success);
    display: block;
    margin-bottom: 0.75rem;
}

.empty-title {
    font-size: 1.25rem;
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.5rem;
}

.empty-desc {
    font-size: 0.875rem;
    color: var(--text-muted);
}

.empty-state {
    font-size: 0.8125rem;
    color: var(--text-muted);
    font-style: italic;
    padding: 0.5rem 0;
}

.history-month-accordion {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    margin-bottom: 0.75rem;
    overflow: hidden;
}

.history-month-summary {
    padding: 1rem 1.25rem;
    font-size: 0.9375rem;
    font-weight: 600;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    list-style: none;
    transition: background var(--transition-fast);
}

.history-month-summary:hover {
    background: var(--primary-light);
}

.history-month-summary::-webkit-details-marker {
    display: none;
}

.history-month-name {
    flex: 1;
}

.history-month-meta {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-weight: 500;
}

.attendance-badge {
    font-size: 0.75rem;
    font-weight: 700;
    padding: 0.125rem 0.5rem;
    border-radius: 100px;
}

.badge-high {
    background: rgba(40, 167, 69, 0.1);
    color: var(--success);
}

.badge-mid {
    background: rgba(255, 193, 7, 0.15);
    color: var(--warn-text);
}

.badge-low {
    background: var(--alert-light);
    color: var(--alert);
}

.history-month-body {
    border-top: 1px solid var(--border-color);
    padding: 0.5rem 0;
}

.history-day-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.5rem 1.25rem;
    font-size: 0.8125rem;
}

.history-day-row:not(:last-child) {
    border-bottom: 1px solid rgba(0, 0, 0, 0.04);
}

.history-day-label {
    width: 5rem;
    font-weight: 600;
    color: var(--text-primary);
    flex-shrink: 0;
}

.history-day-stat {
    font-weight: 500;
    min-width: 3rem;
    text-align: center;
}

.present-stat { color: var(--success); }
.absent-stat { color: var(--alert); }
.practice-stat { color: var(--primary); }

.history-day-rate {
    font-size: 0.75rem;
    font-weight: 700;
    padding: 0.0625rem 0.375rem;
    border-radius: 100px;
    margin-left: auto;
}

@media (max-width: 600px) {
    .dash-stats-grid {
        grid-template-columns: repeat(2, 1fr);
    }

    .dash-stat-value {
        font-size: 1.375rem;
    }

    .dash-stat-rate .dash-stat-value {
        font-size: 1.5rem;
    }

    .history-day-row {
        flex-wrap: wrap;
        gap: 0.375rem;
    }

    .history-day-label {
        width: 100%;
    }
}

.config-phone-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.config-phone-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.config-phone-label {
    min-width: 5.5rem;
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
}

.config-phone-input {
    flex: 1;
    max-width: 220px;
}

.admin-roster-container {
    display: flex;
    flex-direction: column;
}

.admin-roster-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.admin-roster-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    background: var(--bg-card);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-card);
    padding: 0.875rem 1.25rem;
    transition: all var(--transition-fast);
}

.admin-roster-row:hover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.roster-info {
    display: flex;
    flex-direction: column;
    gap: 0.125rem;
    flex: 1;
    min-width: 0;
}

.roster-phones {
    font-size: 0.75rem;
    color: var(--text-muted);
    font-weight: 500;
}

.roster-actions {
    display: flex;
    gap: 0.375rem;
    flex-shrink: 0;
}

.admin-form-card {
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
    padding: 1.25rem;
    margin-bottom: 1rem;
    border: 1.5px solid var(--primary-outline);
}

.admin-form-row {
    display: flex;
    gap: 0.75rem;
}

.admin-form-actions {
    display: flex;
    gap: 0.5rem;
    margin-top: 0.75rem;
}

.admin-roles-container {
    display: flex;
    flex-direction: column;
}

.admin-roles-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.admin-role-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    background: var(--bg-card);
    border-radius: var(--radius-sm);
    box-shadow: var(--shadow-card);
    padding: 0.875rem 1.25rem;
    transition: all var(--transition-fast);
}

.admin-role-row:hover {
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
}

.role-row-self {
    border-left: 3px solid var(--primary);
}

.role-row-info {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex: 1;
    min-width: 0;
}

.role-row-icon {
    font-size: 1.25rem;
    flex-shrink: 0;
}

.role-row-details {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.role-row-uid {
    font-size: 0.8125rem;
    font-weight: 600;
    color: var(--text-primary);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.role-row-current {
    font-size: 0.75rem;
    color: var(--text-muted);
}

.role-row-action {
    flex-shrink: 0;
}

.role-select {
    width: auto;
    min-width: 7rem;
    padding: 0.375rem 0.5rem;
    font-size: 0.8125rem;
}

@media (max-width: 480px) {
    .config-phone-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.25rem;
    }

    .config-phone-input {
        max-width: 100%;
    }

    .admin-form-row {
        flex-direction: column;
    }

    .admin-roster-row,
    .admin-role-row {
        flex-direction: column;
        align-items: flex-start;
        gap: 0.5rem;
    }

    .roster-actions,
    .role-row-action {
        width: 100%;
    }

    .roster-actions {
        justify-content: flex-end;
    }
}

/* Update Checker */
.update-card {
    border: 1px solid var(--border-color);
}

.update-header {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-bottom: 1rem;
}

.update-icon-wrap {
    width: 44px;
    height: 44px;
    border-radius: var(--radius-sm);
    background: linear-gradient(135deg, var(--primary-light), rgba(0, 86, 179, 0.15));
    display: flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
}

.update-icon {
    font-size: 1.5rem;
    line-height: 1;
}

.update-version-label {
    font-size: 0.8125rem;
    color: var(--text-muted);
    margin: 0.125rem 0 0;
}

.btn-update-check {
    background: linear-gradient(135deg, var(--primary), #0070e0);
    color: #fff;
    border: none;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.875rem 1rem;
    font-weight: 600;
    transition: all var(--transition-fast);
}

.btn-update-check:hover:not(:disabled) {
    transform: translateY(-1px);
    box-shadow: 0 4px 16px rgba(0, 86, 179, 0.3);
}

.btn-update-unavailable {
    background: var(--bg-body);
    color: var(--text-muted);
    border: 1px dashed var(--border-color);
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.875rem 1rem;
    font-weight: 600;
    cursor: not-allowed;
    opacity: 0.8;
}

.btn-update-available {
    background: linear-gradient(135deg, #28a745, #20c997) !important;
    animation: update-pulse 2s infinite;
}

@keyframes update-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(40, 167, 69, 0.4); }
    50% { box-shadow: 0 0 0 8px rgba(40, 167, 69, 0); }
}

.update-btn-icon {
    font-size: 1.125rem;
    line-height: 1;
}

/* Update Info Panel (browser mode) */
.update-info-panel {
    margin-top: 0.75rem;
    background: rgba(0, 86, 179, 0.04);
    border: 1px solid rgba(0, 86, 179, 0.12);
    border-radius: var(--radius-sm);
    padding: 1rem;
}

.update-info-content {
    display: flex;
    gap: 0.75rem;
    align-items: flex-start;
}

.update-info-icon {
    font-size: 1.5rem;
    line-height: 1;
    flex-shrink: 0;
}

.update-info-title {
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 0.25rem;
    font-size: 0.9375rem;
}

.update-info-text {
    font-size: 0.8125rem;
    color: var(--text-secondary);
    margin: 0 0 0.375rem;
    line-height: 1.5;
}

/* Update Available Card */
.update-available-card {
    margin-top: 0.75rem;
    background: linear-gradient(135deg, rgba(40, 167, 69, 0.04), rgba(32, 201, 151, 0.06));
    border: 1px solid rgba(40, 167, 69, 0.2);
    border-radius: var(--radius-md);
    padding: 1.25rem;
}

.update-available-header {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin-bottom: 0.5rem;
}

.update-new-badge {
    font-size: 0.6875rem;
    font-weight: 800;
    text-transform: uppercase;
    letter-spacing: 0.05em;
    background: linear-gradient(135deg, #28a745, #20c997);
    color: #fff;
    padding: 0.125rem 0.5rem;
    border-radius: 4px;
}

.update-new-version {
    font-size: 1rem;
    font-weight: 700;
    color: var(--text-primary);
}

.update-available-text {
    font-size: 0.875rem;
    color: var(--text-secondary);
    margin: 0 0 1rem;
}

.update-actions {
    display: flex;
    flex-direction: column;
}

.btn-update-download {
    background: linear-gradient(135deg, #28a745, #20c997);
    color: #fff;
    border: none;
    font-weight: 700;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    padding: 0.875rem 1rem;
    text-decoration: none;
    transition: all var(--transition-fast);
}

.btn-update-download:hover {
    transform: translateY(-1px);
    box-shadow: 0 4px 16px rgba(40, 167, 69, 0.3);
}

/* Update Details Panel */
.update-details-panel {
    margin-top: 0.75rem;
    background: var(--bg-card);
    border: 1px solid var(--border-color);
    border-radius: var(--radius-sm);
    padding: 1rem;
}

.update-detail-row {
    display: flex;
    justify-content: space-between;
    align-items: center;
    padding: 0.5rem 0;
    border-bottom: 1px solid rgba(0, 0, 0, 0.04);
}

.update-detail-row:last-of-type {
    border-bottom: none;
}

.update-detail-label {
    font-size: 0.8125rem;
    color: var(--text-muted);
    font-weight: 500;
}

.update-detail-value {
    font-size: 0.875rem;
    font-weight: 600;
    color: var(--text-primary);
}

.update-detail-new {
    color: var(--success);
}

.update-changelog-section {
    margin-top: 0.75rem;
    padding-top: 0.75rem;
    border-top: 1px solid var(--border-color);
}

.update-changelog-title {
    font-size: 0.8125rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 0.5rem;
    text-transform: uppercase;
    letter-spacing: 0.03em;
}

.update-changelog {
    list-style: none;
    padding: 0;
    margin: 0;
}

.update-changelog li {
    font-size: 0.8125rem;
    color: var(--text-secondary);
    padding: 0.25rem 0 0.25rem 1.125rem;
    position: relative;
    line-height: 1.5;
}

.update-changelog li::before {
    content: '✦';
    position: absolute;
    left: 0;
    color: var(--success);
    font-size: 0.625rem;
    top: 0.4rem;
}

/* Up to Date */
.update-uptodate {
    margin-top: 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1rem;
    background: rgba(40, 167, 69, 0.06);
    border: 1px solid rgba(40, 167, 69, 0.15);
    border-radius: var(--radius-sm);
}

.update-uptodate-icon {
    font-size: 1.75rem;
    line-height: 1;
    flex-shrink: 0;
}

.update-uptodate-title {
    font-weight: 700;
    color: var(--success);
    margin: 0;
    font-size: 0.9375rem;
}

.update-uptodate-text {
    font-size: 0.8125rem;
    color: var(--text-secondary);
    margin: 0.125rem 0 0;
}

/* Update Error */
.update-error {
    margin-top: 0.75rem;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 1rem;
    background: rgba(220, 53, 69, 0.06);
    border: 1px solid rgba(220, 53, 69, 0.15);
    border-radius: var(--radius-sm);
}

.update-error-icon {
    font-size: 1.5rem;
    line-height: 1;
    flex-shrink: 0;
}

.update-error p {
    font-size: 0.8125rem;
    color: var(--text-secondary);
    margin: 0;
    line-height: 1.5;
}

/* ============ GLOBAL MOTION POLISH ============ */

/* Cards lift gently and their shadow deepens on hover for a tactile, modern feel. */
.settings-card,
.dash-stat-card,
.update-card {
    transition: transform var(--transition-base), box-shadow var(--transition-base),
                background-color var(--transition-base), border-color var(--transition-base);
}

.settings-card:hover,
.update-card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-card-hover);
}

/* All primary buttons share one springy press response. */
.btn:active {
    transform: scale(0.98);
}

/* Content fades in smoothly whenever a new view or tab is rendered. */
.fade-in {
    animation: fadeIn var(--transition-slow) cubic-bezier(0.22, 1, 0.36, 1);
}

/* Respect users who prefer reduced motion: keep essential fades instant,
   drop movement everywhere. This is an accessibility guarantee. */
@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
}

/* ============ SELF-DRAWING TICK ============ */
.tick-draw { display: inline-block; vertical-align: middle; }

.tick-draw .tick-circle {
    stroke-dasharray: 166;
    stroke-dashoffset: 166;
    animation: tickCircleDraw 0.5s cubic-bezier(0.65, 0, 0.45, 1) forwards;
}

.tick-draw .tick-check {
    stroke-dasharray: 48;
    stroke-dashoffset: 48;
    animation: tickCheckDraw 0.35s 0.4s cubic-bezier(0.65, 0, 0.45, 1) forwards;
}

@keyframes tickCircleDraw { to { stroke-dashoffset: 0; } }
@keyframes tickCheckDraw { to { stroke-dashoffset: 0; } }

@media (prefers-reduced-motion: reduce) {
    .tick-draw .tick-circle,
    .tick-draw .tick-check {
        animation: none;
        stroke-dashoffset: 0;
    }
}

/* ============ CONFIRM DIALOG ============ */
.modal-overlay {
    position: fixed;
    inset: 0;
    z-index: 1000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: rgba(15, 23, 42, 0.55);
    backdrop-filter: blur(2px);
    -webkit-backdrop-filter: blur(2px);
    opacity: 0;
    transition: opacity 0.18s ease;
}

.modal-overlay.modal-open { opacity: 1; }

.modal-dialog {
    width: 100%;
    max-width: 400px;
    background: var(--bg-card);
    color: var(--text-primary);
    border-radius: var(--radius-lg);
    box-shadow: 0 24px 60px rgba(0, 0, 0, 0.35);
    padding: 1.75rem;
    transform: translateY(12px) scale(0.98);
    transition: transform 0.2s cubic-bezier(0.34, 1.56, 0.64, 1);
}

.modal-overlay.modal-open .modal-dialog { transform: translateY(0) scale(1); }

.modal-title {
    font-size: 1.2rem;
    font-weight: 700;
    color: var(--text-primary);
    margin: 0 0 0.5rem;
}

.modal-message {
    font-size: 0.938rem;
    color: var(--text-secondary);
    line-height: 1.55;
    margin: 0 0 1.5rem;
}

.modal-actions {
    display: flex;
    gap: 0.75rem;
    justify-content: flex-end;
}

.modal-actions .btn { flex: 0 0 auto; min-width: 96px; }

.btn-danger {
    background: var(--alert);
    color: #ffffff;
}

.btn-danger:hover { background: var(--alert-hover); }

@media (max-width: 480px) {
    .modal-actions { flex-direction: column-reverse; }
    .modal-actions .btn { width: 100%; }
}

/* ============ SKELETON LOADERS ============ */
.skeleton {
    position: relative;
    overflow: hidden;
    background: var(--border-color);
    border-radius: var(--radius-sm);
}

.skeleton::after {
    content: '';
    position: absolute;
    inset: 0;
    transform: translateX(-100%);
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.28), transparent);
    animation: shimmer 1.3s infinite;
}

[data-theme="dark"] .skeleton::after {
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.07), transparent);
}

@keyframes shimmer { to { transform: translateX(100%); } }

.skeleton-list { display: flex; flex-direction: column; gap: 0.5rem; }

.skeleton-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.85rem 1rem;
    background: var(--bg-card);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-card);
}

.skeleton-avatar { width: 28px; height: 28px; border-radius: 50%; flex-shrink: 0; }
.skeleton-line { height: 14px; flex: 1; max-width: 240px; }
.skeleton-pill { width: 64px; height: 14px; margin-left: auto; }

@media (prefers-reduced-motion: reduce) {
    .skeleton::after { animation: none; }
}

/* ============================================================
   2026 REFRESH - "signal over decoration"
   Every device below carries information. Nothing here is
   ornament. Applied to: parent check-in, safety alert screen,
   principal dashboard, and the login / role-select entry screens.
   ============================================================ */

/* ---------- Status marks: legible without colour ----------
   present  = filled disc + tick
   absent   = hollow ring + cross
   practice = hollow ring + centre dot
   These survive greyscale photocopying and colour-blindness,
   so status is never carried by hue alone. */
.status-mark {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 1.625rem;
    height: 1.625rem;
    border-radius: 50%;
    border: 2px solid currentColor;
    flex-shrink: 0;
    line-height: 1;
}

.status-mark .icon-svg {
    width: 0.85em;
    height: 0.85em;
    stroke-width: 3;
}

.status-mark--present {
    background: var(--success);
    border-color: var(--success);
    color: #fff;
}

.status-mark--absent {
    background: transparent;
    border-color: var(--alert);
    color: var(--alert);
}

.status-mark--practice {
    background: transparent;
    border-color: var(--primary);
    color: var(--primary);
}

.status-mark--practice::after {
    content: "";
    width: 0.5rem;
    height: 0.5rem;
    border-radius: 50%;
    background: currentColor;
}

/* ---------- Photo 1: parent check-in ----------
   One question, set large, with the student name carrying the
   weight. The two answers become equal-width tiles with the
   status mark stacked above the label. */
.parent-child-card .child-card-name {
    font-size: var(--fs-h2);
    letter-spacing: var(--track-tight);
    margin-bottom: 0.75rem;
}

.parent-child-card .child-card-prompt {
    font-size: var(--fs-h1);
    font-weight: 700;
    line-height: 1.15;
    letter-spacing: var(--track-tight);
    color: var(--text-primary);
    margin-bottom: 1.5rem;
    text-wrap: balance;
}

.checkin-buttons {
    gap: 0.875rem;
}

.btn-checkin {
    gap: 0.75rem;
    padding: 1.75rem 1rem;
    border-radius: var(--radius-lg);
    border-width: 2px;
    box-shadow: var(--elev-1);
}

.btn-checkin .checkin-text {
    font-size: var(--fs-body);
    font-weight: 700;
    letter-spacing: var(--track-tight);
}

.btn-checkin .status-mark {
    width: 2.75rem;
    height: 2.75rem;
    border-width: 3px;
}

.btn-checkin .status-mark .icon-svg {
    width: 1.4rem;
    height: 1.4rem;
}

.btn-yes {
    background: rgba(40, 167, 69, 0.08);
    border-color: rgba(40, 167, 69, 0.35);
    color: #1b6e2f;
}

.btn-no {
    background: rgba(220, 53, 69, 0.06);
    border-color: rgba(220, 53, 69, 0.3);
    color: #a71d2a;
}

[data-theme="dark"] .btn-yes { color: var(--success); }
[data-theme="dark"] .btn-no  { color: var(--alert); }

/* ---------- Photo 2: the safety alert screen ----------
   Full-bleed tinted band with the alert count set at display
   size. This screen must look like nothing else in the app. */
.alert-hero {
    position: relative;
    border-radius: var(--radius-xl);
    padding: 2rem 1.75rem 1.75rem;
    margin-bottom: 1.125rem;
    background:
        radial-gradient(120% 140% at 100% 0%, rgba(220, 53, 69, 0.16) 0%, transparent 60%),
        linear-gradient(160deg, rgba(220, 53, 69, 0.12) 0%, rgba(220, 53, 69, 0.04) 100%);
    border: 1px solid rgba(220, 53, 69, 0.22);
    box-shadow: var(--elev-2);
    display: grid;
    grid-template-columns: auto 1fr;
    grid-template-areas:
        "count title"
        "count sub";
    column-gap: 1.25rem;
    align-items: center;
}

.alert-hero-count {
    grid-area: count;
    font-size: var(--fs-display);
    font-weight: 800;
    line-height: var(--lh-tight);
    letter-spacing: var(--track-display);
    color: var(--alert);
    align-self: center;
}

.alert-hero-title {
    grid-area: title;
    font-size: var(--fs-h2);
    font-weight: 700;
    letter-spacing: var(--track-tight);
    color: var(--text-primary);
    align-self: end;
}

.alert-hero-sub {
    grid-area: sub;
    font-size: var(--fs-sm);
    font-weight: 400;
    color: var(--text-secondary);
    line-height: 1.45;
    align-self: start;
    margin-top: 0.25rem;
}

.mismatch-card {
    border-left-width: 5px;
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-2);
    padding: 1.375rem 1.5rem;
}

.mismatch-card .mismatch-name {
    font-size: var(--fs-h3);
    letter-spacing: var(--track-tight);
    margin-bottom: 0.875rem;
}

/* The heart of the screen: the two contradicting facts, stacked,
   each with its own status mark so the conflict is visible at a
   glance and still readable in black and white. */
.mismatch-rows {
    display: flex;
    flex-direction: column;
    gap: 0.625rem;
    margin-bottom: 1.125rem;
}

.mismatch-row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    font-size: var(--fs-sm);
    font-weight: 400;
    color: var(--text-secondary);
    line-height: 1.4;
}

.mismatch-row strong {
    font-weight: 700;
    color: var(--text-primary);
}

.mismatch-row-time {
    color: var(--text-muted);
}

/* ---------- Photo 3: principal dashboard, bento grid ----------
   Tall hero tile for the rate, two small tiles top-right, one
   wide tile beneath. Each tile is a <section> with its own
   heading, so NVDA reads a clean list of regions. */
.bento {
    display: grid;
    grid-template-columns: 1.35fr 1fr 1fr;
    grid-template-areas:
        "rate present absent"
        "rate practice practice";
    gap: 0.875rem;
    margin-bottom: 1.125rem;
}

.bento-tile {
    background: var(--bg-surface);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-1);
    padding: 1.25rem 1.25rem 1.125rem;
    display: flex;
    flex-direction: column;
    justify-content: center;
    gap: 0.25rem;
    transition: box-shadow var(--transition-base);
}

.bento-tile:hover {
    box-shadow: var(--elev-2);
}

.bento-label {
    font-size: var(--fs-label);
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: var(--track-label);
    color: var(--text-muted);
    order: 2;
}

.bento-figure {
    font-size: var(--fs-h1);
    font-weight: 800;
    line-height: var(--lh-tight);
    letter-spacing: var(--track-tight);
    color: var(--text-primary);
    order: 1;
}

.bento-rate {
    grid-area: rate;
    box-shadow: var(--elev-3);
    padding: 1.75rem 1.5rem;
    gap: 0.5rem;
}

.bento-rate .bento-figure {
    font-size: var(--fs-display);
    letter-spacing: var(--track-display);
}

.bento-rate .bento-label {
    font-size: var(--fs-sm);
    text-transform: none;
    letter-spacing: 0;
    font-weight: 600;
    color: var(--text-secondary);
}

.bento-meta {
    order: 3;
    font-size: var(--fs-label);
    font-weight: 400;
    color: var(--text-muted);
    margin-top: 0.375rem;
}

.bento-present  { grid-area: present; }
.bento-absent   { grid-area: absent; }
.bento-practice { grid-area: practice; }

.bento-present  .bento-figure { color: var(--success-text); }  /* fill value measured 3.05:1 as text */
.bento-absent   .bento-figure { color: var(--alert-text); }    /* fill value measured 4.41:1 as text */
.bento-practice .bento-figure { color: var(--primary-text); }

.bento-rate.rate-high .bento-figure { color: var(--success); }
.bento-rate.rate-mid  .bento-figure { color: var(--warn-text); }
.bento-rate.rate-low  .bento-figure { color: var(--alert); }

@media (max-width: 640px) {
    .bento {
        grid-template-columns: 1fr 1fr;
        grid-template-areas:
            "rate rate"
            "present absent"
            "practice practice";
    }
    .bento-rate .bento-figure { font-size: 2.5rem; }
}

/* ---------- Entry screens: login + role select ----------
   Richer colour field than before, but the card stays opaque.
   No backdrop-filter: it costs contrast guarantees and stutters
   in the Android WebView. */
body.auth-glow::before {
    width: 640px;
    height: 640px;
    top: -200px;
    right: -160px;
    background: radial-gradient(circle, rgba(37, 99, 235, 0.26), transparent 68%);
}

body.auth-glow::after {
    width: 560px;
    height: 560px;
    bottom: -200px;
    left: -160px;
    /* Violet, not green: green is reserved for "present". */
    background: radial-gradient(circle, rgba(124, 58, 237, 0.20), transparent 70%);
}

[data-theme="dark"] body.auth-glow::before {
    background: radial-gradient(circle, rgba(59, 130, 246, 0.38), transparent 68%);
}

[data-theme="dark"] body.auth-glow::after {
    background: radial-gradient(circle, rgba(139, 92, 246, 0.26), transparent 70%);
}

body.auth-glow .card {
    background: var(--bg-card);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-xl);
    box-shadow: var(--elev-3);
}

body.auth-glow .card-heading {
    font-size: var(--fs-h1);
    letter-spacing: var(--track-tight);
}

body.auth-glow .card-subtitle {
    font-size: var(--fs-body);
    font-weight: 400;
}

.role-card {
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-1);
}

.role-card:hover {
    box-shadow: var(--elev-3);
}

/* ============================================================
   PREMIUM DEPTH PASS
   Glow, layered shadow, lit edges and spring feedback - the
   things that make an app feel expensive. The rule that keeps
   it accessible: light and colour live on SURFACES and EDGES,
   never underneath text. Contrast is therefore untouched.
   ============================================================ */

/* ---------- Lit edge + surface gradient ----------
   A 1px inner highlight along the top of every raised surface,
   reading as light falling from above. This is the detail that
   separates a flat rectangle from a physical-feeling card. */
.card,
.bento-tile,
.mismatch-card,
.alert-hero,
.view-header,
.dash-section,
.parent-child-card {
    /* Light mode: a white highlight on a white card is invisible, so depth
       comes from very subtle shading toward the BOTTOM instead. */
    background-image: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(16, 24, 40, 0.03) 100%);
    background-repeat: no-repeat;
}

[data-theme="dark"] .card,
[data-theme="dark"] .bento-tile,
[data-theme="dark"] .mismatch-card,
[data-theme="dark"] .alert-hero,
[data-theme="dark"] .view-header,
[data-theme="dark"] .dash-section,
[data-theme="dark"] .parent-child-card {
    background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0) 42%);
}

.card,
.bento-tile,
.mismatch-card {
    /* Light mode depth = crisp hairline ring + layered soft shadow. */
    box-shadow:
        0 0 0 1px var(--hairline),
        var(--elev-2);
}

[data-theme="dark"] .card,
[data-theme="dark"] .bento-tile,
[data-theme="dark"] .mismatch-card {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.06),
        var(--elev-2);
}

/* ---------- Ambient colour glow on the hero elements ----------
   A wide, soft, low-alpha coloured halo sitting behind the tile.
   Because it is a shadow it can never sit on top of text. */
.bento-rate {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.8),
        0 0 0 1px var(--hairline),
        0 18px 40px -12px rgba(37, 99, 235, 0.28),
        var(--elev-3);
}

.bento-rate.rate-high {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.8),
        0 0 0 1px var(--hairline),
        0 18px 40px -12px rgba(40, 167, 69, 0.32),
        var(--elev-3);
}

.bento-rate.rate-low {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.8),
        0 0 0 1px var(--hairline),
        0 18px 40px -12px rgba(220, 53, 69, 0.32),
        var(--elev-3);
}

.alert-hero {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.6),
        0 20px 48px -16px rgba(220, 53, 69, 0.45),
        var(--elev-2);
}

/* A soft radial bloom directly behind the big alert figure, so the
   number looks lit rather than printed. Sits under the digit only. */
.alert-hero-count {
    position: relative;
    isolation: isolate;
}

.alert-hero-count::before {
    content: "";
    position: absolute;
    inset: -35% -45%;
    background: radial-gradient(circle, rgba(220, 53, 69, 0.30) 0%, transparent 68%);
    filter: blur(14px);
    z-index: -1;
    pointer-events: none;
}

.mismatch-card {
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.7),
        0 10px 28px -12px rgba(220, 53, 69, 0.35),
        var(--elev-2);
}

/* ---------- Spring feedback: the "responsive" feel ---------- */
.bento-tile,
.btn-checkin,
.mismatch-card,
.role-card,
.btn-action {
    transition:
        transform 0.28s cubic-bezier(0.34, 1.56, 0.64, 1),
        box-shadow 0.28s cubic-bezier(0.22, 1, 0.36, 1),
        border-color 0.2s ease,
        background-color 0.2s ease;
    will-change: transform;
}

.bento-tile:hover {
    transform: translateY(-4px);
}

.bento-rate:hover {
    transform: translateY(-5px) scale(1.008);
}

.btn-checkin:hover {
    transform: translateY(-4px);
}

.mismatch-card:hover {
    transform: translateY(-3px);
}

.btn-action:hover {
    transform: translateY(-2px);
}

/* Press states - the tactile half of "responsive" */
.bento-tile:active,
.mismatch-card:active { transform: translateY(-1px) scale(0.995); }
.btn-checkin:active   { transform: translateY(0) scale(0.97); }
.btn-action:active    { transform: translateY(0) scale(0.96); }
.role-card:active     { transform: translateY(-2px) scale(0.98); }

/* ---------- Glowing focus ring ----------
   Keeps the solid high-contrast outline for visibility, adds a
   soft halo so it reads as designed rather than as a default. */
.btn-checkin:focus-visible,
.btn-action:focus-visible,
.bento-tile:focus-visible {
    outline: 3px solid var(--primary);
    outline-offset: 3px;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.75),
        0 0 0 6px var(--primary-light),
        var(--elev-3);
}

/* ---------- Staggered entrance ---------- */
@keyframes tileRise {
    from { opacity: 0; transform: translateY(14px) scale(0.985); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.bento-tile {
    animation: tileRise 0.5s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

.bento-rate     { animation-delay: 0.02s; }
.bento-present  { animation-delay: 0.08s; }
.bento-absent   { animation-delay: 0.13s; }
.bento-practice { animation-delay: 0.18s; }

.mismatch-list .mismatch-card {
    animation: tileRise 0.45s cubic-bezier(0.22, 1, 0.36, 1) backwards;
}

.mismatch-list .mismatch-card:nth-child(1) { animation-delay: 0.06s; }
.mismatch-list .mismatch-card:nth-child(2) { animation-delay: 0.12s; }
.mismatch-list .mismatch-card:nth-child(3) { animation-delay: 0.18s; }
.mismatch-list .mismatch-card:nth-child(4) { animation-delay: 0.24s; }
.mismatch-list .mismatch-card:nth-child(n+5) { animation-delay: 0.3s; }

/* ---------- Alert screen: slow breathing halo ----------
   Deliberately slow and low-amplitude. Fast pulsing on a safety
   screen is stressful and is a vestibular trigger. */
@keyframes alertBreathe {
    0%, 100% { box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), 0 20px 48px -16px rgba(220,53,69,0.40), var(--elev-2); }
    50%      { box-shadow: inset 0 1px 0 rgba(255,255,255,0.6), 0 24px 60px -14px rgba(220,53,69,0.62), var(--elev-2); }
}

.alert-hero {
    animation: alertBreathe 4.5s ease-in-out infinite;
}

/* ---------- Every motion above, switched off on request ---------- */
@media (prefers-reduced-motion: reduce) {
    .bento-tile,
    .btn-checkin,
    .mismatch-card,
    .role-card,
    .btn-action {
        transition: border-color 0.2s ease, background-color 0.2s ease;
        will-change: auto;
    }

    .bento-tile:hover,
    .bento-rate:hover,
    .btn-checkin:hover,
    .mismatch-card:hover,
    .btn-action:hover,
    .bento-tile:active,
    .mismatch-card:active,
    .btn-checkin:active,
    .btn-action:active,
    .role-card:active {
        transform: none;
    }

    .bento-tile,
    .mismatch-list .mismatch-card,
    .alert-hero {
        animation: none;
    }
}

/* The login/role card sits inside body.auth-glow, whose rule has higher
   specificity than plain .card, so the depth treatment must be restated
   here or it gets reset by that shorthand background. */
body.auth-glow .card {
    background-color: var(--bg-card);
    background-image: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(16, 24, 40, 0.03) 100%);
    box-shadow:
        0 0 0 1px var(--hairline),
        0 24px 56px -18px rgba(37, 99, 235, 0.28),
        var(--elev-3);
}

[data-theme="dark"] body.auth-glow .card {
    background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.06) 0%, rgba(255, 255, 255, 0) 45%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.08),
        0 24px 60px -18px rgba(59, 130, 246, 0.38),
        var(--elev-3);
}

/* ---------- Call-action buttons: contrast-corrected ----------
   These used the raw status colours as TEXT on their own tinted
   fills, which measured ~2.9:1 (parent) and ~4.2:1 (principal) -
   both below the WCAG AA 4.5:1 minimum. Darkened to pass while
   keeping the same colour identity. */
.btn-call-parent { color: #1b6e2f; }
.btn-call-principal { color: #a71d2a; }

.btn-teacher {
    background: rgba(79, 70, 229, 0.12);
    color: #4338ca;
}

.btn-teacher:hover {
    background: rgba(79, 70, 229, 0.22);
}

[data-theme="dark"] .btn-call-parent { color: var(--success); }
[data-theme="dark"] .btn-call-principal { color: var(--alert); }
[data-theme="dark"] .btn-teacher { color: #a5b4fc; }

/* ============================================================
   TEACHER REGISTER - brought in line with the rest of the app.
   This is the screen a teacher uses every morning and the one a
   judge will spend longest in, so it gets the same type scale,
   depth and status-shape language as the three hero screens.
   ============================================================ */

/* ---------- Header + stats ---------- */
.view-header {
    background: var(--bg-surface);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-2);
    padding: 1.5rem 1.5rem 1.25rem;
}

.view-title {
    font-size: var(--fs-h2);
    letter-spacing: var(--track-tight);
}

.view-date {
    font-size: var(--fs-sm);
    font-weight: 400;
}

.stats-bar {
    gap: 0.625rem;
}

.stat-chip {
    border-radius: var(--radius-md);
    border: 1px solid transparent;
    padding: 0.875rem 0.5rem;
}

.stat-value {
    font-size: 1.75rem;
    font-weight: 800;
    letter-spacing: var(--track-tight);
    font-variant-numeric: tabular-nums;
    font-feature-settings: "tnum" 1;
}

.stat-label {
    font-size: var(--fs-label);
    letter-spacing: var(--track-label);
}

.stat-present { border-color: rgba(40, 167, 69, 0.22); }
.stat-absent  { border-color: rgba(220, 53, 69, 0.22); }
.stat-total   { border-color: var(--hairline); }

/* ---------- Proportion bar ----------
   A slim present/absent/practice ratio directly under the counts.
   It carries information the numbers alone do not: the shape of
   the day at a glance. Widths are set inline from the live tally. */
.attendance-ratio {
    display: flex;
    height: 8px;
    margin-top: 1rem;
    border-radius: 999px;
    overflow: hidden;
    background: var(--border-color);
}

.attendance-ratio span {
    display: block;
    height: 100%;
    transition: width 0.45s cubic-bezier(0.22, 1, 0.36, 1);
}

.ratio-present  { background: var(--success); }
.ratio-practice { background: var(--primary); }
.ratio-absent   { background: var(--alert); }

@media (prefers-reduced-motion: reduce) {
    .attendance-ratio span { transition: none; }
}

/* ---------- The list ---------- */
.student-list-container {
    background: var(--bg-surface);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-2);
    /* Let the final row scroll clear of the sticky submit bar. */
    padding-bottom: 0.25rem;
}

.student-row {
    padding: 0.9375rem 1.25rem;
    border-bottom: 1px solid var(--hairline);
    transition: background var(--transition-fast);
}

.student-name {
    font-size: var(--fs-body);
    font-weight: 600;
    letter-spacing: -0.01em;
}

.student-status {
    font-size: var(--fs-label);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--track-label);
}

/* ---------- Status shapes, matching the rest of the app ----------
   present = filled green disc + white tick   (checkbox checked)
   absent  = hollow red ring + red cross      (checkbox unchecked)
   Previously the unchecked state was a blank grey circle, which
   carried no meaning and did not match the alert or check-in
   screens. Now the register speaks the same visual language. */
.checkmark {
    width: 26px;
    height: 26px;
    min-width: 26px;
    position: relative;
}

.student-checkbox:not(:checked) + .checkmark {
    border-color: var(--alert);
    background: transparent;
}

.student-checkbox:not(:checked) + .checkmark::after {
    display: block;
    width: 13px;
    height: 13px;
    border: none;
    transform: none;
    margin: 0;
    background-color: var(--alert);
    -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='4' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center / contain no-repeat;
    mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='4' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center / contain no-repeat;
}

.student-label:hover .checkmark {
    border-color: var(--success);
}

.student-checkbox:not(:checked) ~ .student-info .student-name {
    color: var(--text-secondary);
}

/* Tactile feedback on the row itself */
.student-label:active .checkmark {
    transform: scale(0.9);
}

@media (prefers-reduced-motion: reduce) {
    .student-label:active .checkmark { transform: none; }
}

/* ---------- Search ---------- */
.search-input {
    border-radius: var(--radius-md);
    box-shadow: var(--elev-1);
}

/* ---------- Sticky submit bar ----------
   Given a real edge so it reads as a fixed control surface rather
   than a button floating over the content that scrolls behind it. */
.submit-bar {
    border-top: 1px solid var(--hairline);
    padding: 0.875rem 0 1rem;
    background: var(--bg-body);
}

.submit-bar::before {
    top: -24px;
    height: 24px;
}

/* Give scrolling content room to clear the bar. */
.mismatch-list {
    padding-bottom: 0.5rem;
}

/* ---------- Coach submissions panel ---------- */
.coach-toggle-btn {
    border-radius: var(--radius-md);
    box-shadow: var(--elev-1);
}

.coach-status-collapse {
    margin-bottom: 1rem;
}

/* ---------- Header: stop the brand name wrapping ----------
   On a 360px phone the logo, theme button, account chip and Log Out
   squeezed the flex row until "Tick Mark" broke onto two lines. The
   brand must never wrap - it appears in every screenshot. */
.brand-title {
    white-space: nowrap;
}

.header-brand {
    flex-shrink: 0;
}

@media (max-width: 480px) {
    .header-inner {
        padding: 0.625rem 0.875rem;
    }
    #main-nav {
        gap: 0.5rem;
    }
    .brand-icon {
        width: 32px;
        height: 32px;
    }
    .brand-title {
        font-size: 1.125rem;
    }
    #btn-logout {
        padding: 0.375rem 0.625rem;
        font-size: 0.8125rem;
    }
}

/* The safety number gets the strongest treatment on the dashboard. */
.bento-unaccounted .bento-figure { color: var(--alert); }

.bento-unaccounted.has-alerts {
    border-color: rgba(220, 53, 69, 0.35);
    box-shadow:
        0 0 0 1px rgba(220, 53, 69, 0.25),
        0 14px 32px -12px rgba(220, 53, 69, 0.40),
        var(--elev-2);
}

.bento-inschool .bento-figure { color: var(--success); }

/* ---------- Alert screen: stop "Edit Attendance" burying the calls ----------
   The submit bar is position:sticky, so on a phone it pinned itself over the
   first alert card - covering "Call Parent", the single most important control
   on the whole screen, with a secondary action. A safety alert must put
   calling first, so on this screen the button sits inline at the end. */
.alert-screen .submit-bar {
    position: static;
    margin-top: 1.25rem;
    padding: 0;
    border-top: none;
    background: transparent;
}

.alert-screen .submit-bar::before {
    display: none;
}

/* ---------- Attendance rate: the "caution" band ----------
   --warn-text (#856404) is Bootstrap's warning TEXT colour, sized for small
   text on a yellow fill. At the 3.25rem display size of the dashboard's
   headline figure it reads as muddy brown and looks like a rendering fault.
   A clear orange reads unambiguously as caution and holds ~5.9:1 on the
   card surface. Dark mode keeps the existing amber, which works on navy. */
:root {
    --rate-mid: #c2410c;
}

[data-theme="dark"] {
    --rate-mid: #fbbf24;
}

.bento-rate.rate-mid .bento-figure {
    color: var(--rate-mid);
}

/* ---------- Admin: Sports & Coaches ---------- */
.config-phone-row {
    padding: 0.5rem 0;
    border-bottom: 1px solid var(--hairline);
}

.config-phone-row:last-child {
    border-bottom: none;
}

.btn-remove-sport {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    min-width: 36px;
    margin-left: auto;
    border: 1px solid transparent;
    border-radius: var(--radius-sm);
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast),
                border-color var(--transition-fast);
}

.btn-remove-sport:hover {
    background: rgba(220, 53, 69, 0.10);
    border-color: rgba(220, 53, 69, 0.30);
    color: var(--alert);
}

.btn-remove-sport:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.sport-add-block {
    margin-top: 1.25rem;
    padding-top: 1.25rem;
    border-top: 1px solid var(--hairline);
}

.sport-add-title {
    font-size: var(--fs-h3);
    font-weight: 700;
    color: var(--text-primary);
    margin-bottom: 0.75rem;
}

.sport-add-row {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

.sport-add-row .form-input {
    flex: 1;
    max-width: 260px;
}

.sport-add-row .btn {
    flex-shrink: 0;
}

@media (max-width: 480px) {
    .config-phone-input {
        max-width: none;
    }
    .sport-add-row .form-input {
        max-width: none;
    }
}

/* ---------- Restored draft notice ----------
   Shown when the register reopens with unsubmitted marks recovered from this
   device. Deliberately informational blue, not green or red - nothing has
   been submitted yet, and it must not read as a success or an alert. */
.draft-restored-notice {
    display: flex;
    align-items: center;
    gap: 0.625rem;
    margin: 0.875rem 0 0;
    padding: 0.75rem 1rem;
    border: 1px solid rgba(0, 86, 179, 0.25);
    border-radius: var(--radius-md);
    background: rgba(0, 86, 179, 0.06);
    color: var(--text-primary);
    font-size: var(--fs-sm);
    line-height: 1.45;
}

.draft-restored-notice svg {
    flex-shrink: 0;
    color: var(--primary);
}

/* ---------- Accounts shown by name, not by uid ---------- */
.role-row-name {
    font-size: var(--fs-body);
    font-weight: 600;
    color: var(--text-primary);
    line-height: 1.3;
}

/* An account with no name is a gap an admin should notice and fix. */
.role-row-unnamed {
    color: var(--text-muted);
    font-style: italic;
    font-weight: 500;
}

.role-row-contact {
    font-size: var(--fs-label);
    color: var(--text-muted);
    word-break: break-all;
}

.btn-rename-user {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 36px;
    height: 36px;
    min-width: 36px;
    border: 1px solid var(--hairline);
    border-radius: var(--radius-sm);
    background: var(--bg-surface);
    color: var(--text-secondary);
    cursor: pointer;
    transition: background var(--transition-fast), color var(--transition-fast),
                border-color var(--transition-fast);
}

.btn-rename-user:hover {
    background: rgba(0, 86, 179, 0.08);
    border-color: rgba(0, 86, 179, 0.35);
    color: var(--primary);
}

.btn-rename-user:focus-visible {
    outline: 3px solid var(--primary-outline);
    outline-offset: 2px;
}

.role-row-action {
    display: flex;
    align-items: center;
    gap: 0.5rem;
}

/* Name field on the first-run setup screen */
.setup-name-group {
    text-align: left;
    margin-bottom: 1.25rem;
}

/* ==========================================================================
   App PIN lock screen
   Full-screen, above everything, with the app behind it made inert. Uses the
   same shield mark and type scale as the login screen so it reads as part of
   Tick Mark rather than a system dialog.
   ========================================================================== */
.pin-lock {
    position: fixed;
    inset: 0;
    z-index: 2000;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 1.5rem;
    background: var(--bg-body);
    /* Opaque on purpose: the register behind this may show student names, and a
       translucent lock screen would leak them to whoever picked up the phone. */
}

body.pin-locked {
    overflow: hidden;
}

.pin-lock-card {
    width: 100%;
    max-width: 380px;
    background: var(--bg-card);
    border: 1px solid var(--hairline);
    border-radius: var(--radius-lg);
    box-shadow: var(--elev-3);
    padding: 2rem 1.75rem;
    text-align: center;
}

.pin-lock-logo {
    display: flex;
    justify-content: center;
    margin-bottom: 1rem;
}

.pin-lock-title {
    font-size: var(--fs-h2);
    font-weight: 700;
    letter-spacing: var(--track-tight);
    margin: 0 0 0.375rem;
    color: var(--text-primary);
}

.pin-lock-subtitle {
    font-size: var(--fs-body);
    color: var(--text-secondary);
    margin: 0 0 1.5rem;
}

/* Wide letter spacing and a large face, because entering a PIN by touch on a
   phone is a precision task and the digits are masked. */
.pin-lock-input {
    text-align: center;
    font-size: 1.75rem;
    letter-spacing: 0.5em;
    text-indent: 0.5em;
    padding-block: 0.75rem;
}

.pin-lock-msg {
    margin-top: 1rem;
    padding: 0.75rem;
    border-radius: var(--radius-md);
    font-size: var(--fs-sm);
    font-weight: 600;
}

.pin-lock-msg-error {
    background: var(--alert-light);
    color: var(--alert-text);
}

/* Very light tint. --primary-text over a 10% blue wash measured 4.26:1 in dark
   mode and 4.42:1 at 6%; the wash is decorative, so it gives way to the text.
   Measured 4.54:1 dark / 6.76:1 light at 3%. */
.pin-lock-msg-info {
    background: rgba(37, 99, 235, 0.03);
    color: var(--primary-text);
}

.pin-lock-signout {
    margin-top: 1.25rem;
    width: 100%;
}

/* ---------- Shared PIN settings card ---------- */
.pin-card-status {
    display: inline-flex;
    align-items: center;
    gap: 0.5rem;
    font-size: var(--fs-sm);
    font-weight: 600;
    color: var(--text-secondary);
    margin-bottom: 1rem;
}

/* The dot is decorative; the words "PIN is on" / "PIN is off" next to it carry
   the meaning, so this never depends on colour alone. */
.pin-card-dot {
    width: 10px;
    height: 10px;
    border-radius: var(--radius-full);
}

.pin-card-dot.is-on {
    background: var(--success);
}

.pin-card-dot.is-off {
    background: transparent;
    border: 2px solid var(--text-secondary);
}

.pin-card-actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Coach squad: the add-a-student picker sits beside its button on wide screens
   and stacks on a phone. */
.squad-add-row {
    display: flex;
    align-items: flex-end;
    gap: 0.75rem;
    flex-wrap: wrap;
    margin-top: 1rem;
}

.squad-add-row .btn {
    flex-shrink: 0;
}

@media (max-width: 480px) {
    .squad-add-row { align-items: stretch; }
    .squad-add-row .btn { width: 100%; }
}

/* Launch update notice. Sits between the header and the view container so a
   dashboard re-render cannot wipe it. Quiet by design — it is unsolicited, so
   it uses the caution treatment rather than the alert red. */
.update-banner {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    flex-wrap: wrap;
    max-width: 1100px;
    margin: 0.75rem auto 0;
    padding: 0.7rem 0.9rem;
    border: 1px solid var(--hairline);
    border-left: 3px solid var(--primary-fill);
    border-radius: var(--radius-md);
    background: var(--bg-card);
    box-shadow: var(--elev-1);
}

.update-banner-icon {
    display: inline-flex;
    color: var(--primary-text);
    flex-shrink: 0;
}

.update-banner-text {
    flex: 1 1 12rem;
    margin: 0;
    font-size: var(--fs-sm);
    color: var(--text-primary);
}

.update-banner-action { flex-shrink: 0; }

.update-banner-dismiss {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2rem;
    height: 2rem;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--text-muted);
    cursor: pointer;
    flex-shrink: 0;
}

.update-banner-dismiss:hover { background: var(--primary-light); color: var(--text-primary); }
.update-banner-dismiss:focus-visible { outline: 2px solid var(--primary-fill); outline-offset: 2px; }

@media (max-width: 480px) {
    .update-banner { margin-left: 0.75rem; margin-right: 0.75rem; }
    .update-banner-text { flex-basis: 100%; }
}

/* ============================================================
   Dashboard depth pass
   ------------------------------------------------------------
   The login screen was the best-looking surface in the app and the
   dashboards were noticeably flatter. This carries the same visual
   language across without touching a single line of view markup:
   an ambient field tinted to the role accent, and the login card's
   layered depth applied to the dashboard's own containers.

   Two rules held throughout:
     - every card stays fully OPAQUE (var(--bg-card) / --bg-surface),
       so the glows can never sit behind text and erode contrast;
     - green and red are never used as a role tint. They mean
       present and absent, and nothing else.
   ============================================================ */

body[data-role]::before,
body[data-role]::after {
    content: "";
    position: fixed;
    border-radius: 50%;
    filter: blur(100px);
    pointer-events: none;
    z-index: 0;
}

body[data-role]::before {
    width: 560px;
    height: 560px;
    top: -200px;
    right: -170px;
}

body[data-role]::after {
    width: 460px;
    height: 460px;
    bottom: -190px;
    left: -160px;
    background: radial-gradient(circle, rgba(100, 116, 139, 0.10), transparent 72%);
}

/* Deliberately weaker than the login screen's field (0.18/0.30). A dashboard
   is a working surface that is read for minutes at a time, not a five-second
   entry screen, so the colour sits further back. */
body[data-role="teacher"]::before   { background: radial-gradient(circle, rgba(79, 70, 229, 0.13), transparent 72%); }
body[data-role="principal"]::before { background: radial-gradient(circle, rgba(13, 148, 136, 0.13), transparent 72%); }
body[data-role="parent"]::before    { background: radial-gradient(circle, rgba(37, 99, 235, 0.13), transparent 72%); }
body[data-role="coach"]::before     { background: radial-gradient(circle, rgba(217, 119, 6, 0.12), transparent 72%); }
body[data-role="admin"]::before     { background: radial-gradient(circle, rgba(124, 58, 237, 0.13), transparent 72%); }

[data-theme="dark"] body[data-role="teacher"]::before   { background: radial-gradient(circle, rgba(129, 140, 248, 0.22), transparent 72%); }
[data-theme="dark"] body[data-role="principal"]::before { background: radial-gradient(circle, rgba(45, 212, 191, 0.20), transparent 72%); }
[data-theme="dark"] body[data-role="parent"]::before    { background: radial-gradient(circle, rgba(59, 130, 246, 0.24), transparent 72%); }
[data-theme="dark"] body[data-role="coach"]::before     { background: radial-gradient(circle, rgba(251, 191, 36, 0.18), transparent 72%); }
[data-theme="dark"] body[data-role="admin"]::before     { background: radial-gradient(circle, rgba(167, 139, 250, 0.22), transparent 72%); }
[data-theme="dark"] body[data-role]::after              { background: radial-gradient(circle, rgba(148, 163, 184, 0.10), transparent 72%); }

/* The view must sit above the ambient field. */
#app-container { position: relative; z-index: 1; }

/* --- containers: flat --shadow-card -> the login card's layered depth --- */
.dash-section,
.student-list-container,
.settings-card {
    border: 1px solid var(--hairline);
    border-radius: var(--radius-lg);
    background-color: var(--bg-card);
    background-image: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(16, 24, 40, 0.022) 100%);
    box-shadow: 0 0 0 1px var(--hairline), var(--elev-2);
}

[data-theme="dark"] .dash-section,
[data-theme="dark"] .student-list-container,
[data-theme="dark"] .settings-card {
    /* Inset top highlight = a lit edge catching light from above. This is what
       gives the dark theme its sense of a physical panel rather than a flat fill. */
    background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.055) 0%, rgba(255, 255, 255, 0) 42%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.07), var(--elev-2);
}

/* --- bento tiles: lift, and let the hero tile carry real weight --- */
.bento-tile {
    background-image: linear-gradient(180deg, rgba(255, 255, 255, 0) 0%, rgba(16, 24, 40, 0.025) 100%);
    box-shadow: 0 0 0 1px var(--hairline), var(--elev-2);
}

[data-theme="dark"] .bento-tile {
    background-image: linear-gradient(180deg, rgba(255, 255, 255, 0.05) 0%, rgba(255, 255, 255, 0) 45%);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06), var(--elev-2);
}

.bento-rate { box-shadow: 0 0 0 1px var(--hairline), var(--elev-3); }
[data-theme="dark"] .bento-rate { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.08), var(--elev-3); }

.bento-tile:hover { box-shadow: 0 0 0 1px var(--hairline), var(--elev-3); }
[data-theme="dark"] .bento-tile:hover { box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.09), var(--elev-3); }

/* --- headings: the type scale was defined but these were not using it --- */
.dash-section-title,
.settings-section-title {
    letter-spacing: var(--track-tight);
}

@media (prefers-reduced-motion: reduce) {
    .bento-tile { transition: none; }
}

/* ============================================================
   Touch targets — WCAG 2.5.5 / platform minimum is 44x44 CSS px.
   Measured at 375px wide; every figure below is what the audit read.
   ============================================================ */

/* THE IMPORTANT ONE. .student-row is `align-items: center`, so .student-label
   sat at its content height — 20.8px inside a 51.8px row. The checkbox is
   `position:absolute; inset:0` against that label, so the ACTUAL tappable area
   for marking a student was 20.8px tall, with a ~15px dead strip above and below
   where taps did nothing. The teacher does this 40 times.

   The fix is to move the positioning context up to the row so the checkbox
   resolves against the ROW's padding box and covers all 51.8px of it. Stretching
   the label instead does not work: `align-self: stretch` fills the row's CONTENT
   box, leaving its 0.875rem vertical padding still dead, and adding a min-height
   on top of that padding inflated every row from 51.8px to 75px. */
.student-row {
    position: relative;
}

.student-label {
    position: static;
}

/* Primary navigation in every role, tapped constantly. */
.tab-btn {
    min-height: 44px;
}

/* 37px measured. "Call Parent" on a red alert card is an emergency action and
   was the smallest target in the app. */
.btn-sm {
    min-height: 44px;
}
