/* =========================================
   SHARED COLOR PALETTE
   Named here so future styles can reference one source of truth instead of
   retyping hex values. The app currently uses two blues in the wild -
   Bootstrap's default (--brand-blue) and a brighter accent (--accent-blue) -
   both are named as-is rather than unified, since picking one is a real
   design decision, not a refactor.
========================================= */
:root {
    --brand-blue: #0d6efd;
    --accent-blue: #3b82f6;
    --dark: #212529;
    --muted: #adb5bd;
    --success: #198754;
    --success-bright: #22c55e;
    --danger: #ef4444;
}

html, body {
    font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
}

a, .btn-link {
    color: #006bb7;
}

.btn-primary {
    color: #fff;
    background-color: #1b6ec2;
    border-color: #1861ac;
}

.btn:focus, .btn:active:focus, .btn-link.nav-link:focus, .form-control:focus, .form-check-input:focus {
    box-shadow: 0 0 0 0.1rem white, 0 0 0 0.25rem #258cfb;
}

.content {
    padding-top: 1.1rem;
}

h1:focus {
    outline: none;
}

.valid.modified:not([type=checkbox]) {
    outline: 1px solid #26b050;
}

.invalid {
    outline: 1px solid #e50000;
}

.validation-message {
    color: #e50000;
}

.blazor-error-boundary {
    background: url(data:image/svg+xml;base64,PHN2ZyB3aWR0aD0iNTYiIGhlaWdodD0iNDkiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIG92ZXJmbG93PSJoaWRkZW4iPjxkZWZzPjxjbGlwUGF0aCBpZD0iY2xpcDAiPjxyZWN0IHg9IjIzNSIgeT0iNTEiIHdpZHRoPSI1NiIgaGVpZ2h0PSI0OSIvPjwvY2xpcFBhdGg+PC9kZWZzPjxnIGNsaXAtcGF0aD0idXJsKCNjbGlwMCkiIHRyYW5zZm9ybT0idHJhbnNsYXRlKC0yMzUgLTUxKSI+PHBhdGggZD0iTTI2My41MDYgNTFDMjY0LjcxNyA1MSAyNjUuODEzIDUxLjQ4MzcgMjY2LjYwNiA1Mi4yNjU4TDI2Ny4wNTIgNTIuNzk4NyAyNjcuNTM5IDUzLjYyODMgMjkwLjE4NSA5Mi4xODMxIDI5MC41NDUgOTIuNzk1IDI5MC42NTYgOTIuOTk2QzI5MC44NzcgOTMuNTEzIDI5MSA5NC4wODE1IDI5MSA5NC42NzgyIDI5MSA5Ny4wNjUxIDI4OS4wMzggOTkgMjg2LjYxNyA5OUwyNDAuMzgzIDk5QzIzNy45NjMgOTkgMjM2IDk3LjA2NTEgMjM2IDk0LjY3ODIgMjM2IDk0LjM3OTkgMjM2LjAzMSA5NC4wODg2IDIzNi4wODkgOTMuODA3MkwyMzYuMzM4IDkzLjAxNjIgMjM2Ljg1OCA5Mi4xMzE0IDI1OS40NzMgNTMuNjI5NCAyNTkuOTYxIDUyLjc5ODUgMjYwLjQwNyA1Mi4yNjU4QzI2MS4yIDUxLjQ4MzcgMjYyLjI5NiA1MSAyNjMuNTA2IDUxWk0yNjMuNTg2IDY2LjAxODNDMjYwLjczNyA2Ni4wMTgzIDI1OS4zMTMgNjcuMTI0NSAyNTkuMzEzIDY5LjMzNyAyNTkuMzEzIDY5LjYxMDIgMjU5LjMzMiA2OS44NjA4IDI1OS4zNzEgNzAuMDg4N0wyNjEuNzk1IDg0LjAxNjEgMjY1LjM4IDg0LjAxNjEgMjY3LjgyMSA2OS43NDc1QzI2Ny44NiA2OS43MzA5IDI2Ny44NzkgNjkuNTg3NyAyNjcuODc5IDY5LjMxNzkgMjY3Ljg3OSA2Ny4xMTgyIDI2Ni40NDggNjYuMDE4MyAyNjMuNTg2IDY2LjAxODNaTTI2My41NzYgODYuMDU0N0MyNjEuMDQ5IDg2LjA1NDcgMjU5Ljc4NiA4Ny4zMDA1IDI1OS43ODYgODkuNzkyMSAyNTkuNzg2IDkyLjI4MzcgMjYxLjA0OSA5My41Mjk1IDI2My41NzYgOTMuNTI5NSAyNjYuMTE2IDkzLjUyOTUgMjY3LjM4NyA5Mi4yODM3IDI2Ny4zODcgODkuNzkyMSAyNjcuMzg3IDg3LjMwMDUgMjY2LjExNiA4Ni4wNTQ3IDI2My41NzYgODYuMDU0N1oiIGZpbGw9IiNGRkU1MDAiIGZpbGwtcnVsZT0iZXZlbm9kZCIvPjwvZz48L3N2Zz4=) no-repeat 1rem/1.8rem, #b32121;
    padding: 1rem 1rem 1rem 3.7rem;
    color: white;
}

    .blazor-error-boundary::after {
        content: "An error has occurred."
    }

.darker-border-checkbox.form-check-input {
    border-color: #929292;
}

.form-floating > .form-control-plaintext::placeholder, .form-floating > .form-control::placeholder {
    color: var(--bs-secondary-color);
    text-align: end;
}

.form-floating > .form-control-plaintext:focus::placeholder, .form-floating > .form-control:focus::placeholder {
    text-align: start;
}


.app-layout {
    display: flex;
    height: 100vh;
    width: 100vw;
    overflow: hidden;
}

.main-content {
    flex-grow: 1; /* Takes up the remaining horizontal space */
    overflow-y: auto; /* Adds a scrollbar to the content if it gets too long */
    background-color: #f8f9fa;
}

.content-wrapper {
    padding: 2rem;
}


/* The semi-transparent screen that covers the old page */
.global-loading-overlay {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background-color: rgba(255, 255, 255, 0.7); /* A slight white frost effect */
    z-index: 9999; /* Keeps it on top of everything else */
    /* Flexbox to center the spinner */
    display: flex;
    flex-direction: column;
    justify-content: center;
    align-items: center;
    font-size: 1.2rem;
    color: #3b82f6; /* Matching your UI blue */
    font-weight: bold;
}

/* The animated spinning circle */
.spinner {
    border: 4px solid rgba(59, 130, 246, 0.2);
    border-top: 4px solid #3b82f6;
    border-radius: 50%;
    width: 50px;
    height: 50px;
    animation: spin 0.8s linear infinite;
    margin-bottom: 15px;
}

@keyframes spin {
    0% {
        transform: rotate(0deg);
    }

    100% {
        transform: rotate(360deg);
    }
}

/* =========================================
   SHARED FULLSCREEN IMAGE MODAL
   Used by WeekRemember, WeekTestPlay, and Memorial/Event's image zoom.
   Was previously copy-pasted with minor variations in each page's own
   .razor.css - one definition here now.
========================================= */
.image-modal-overlay {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.85);
    backdrop-filter: blur(5px);
    z-index: 9999;
    display: flex;
    justify-content: center;
    align-items: center;
    animation: fadeInModal 0.2s ease-out forwards;
}

.image-modal-content {
    max-width: 90vw;
    max-height: 90vh;
    border-radius: 12px;
    box-shadow: 0 10px 40px rgba(0,0,0,0.5);
    object-fit: contain;
    animation: zoomInImage 0.3s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
}

.image-modal-close {
    position: absolute;
    top: 20px;
    right: 30px;
    background: rgba(255, 255, 255, 0.2);
    border: none;
    color: white;
    font-size: 1.5rem;
    width: 45px;
    height: 45px;
    border-radius: 50%;
    cursor: pointer;
    display: flex;
    justify-content: center;
    align-items: center;
    transition: background 0.2s;
}

    .image-modal-close:hover {
        background: rgba(255, 255, 255, 0.4);
    }

@keyframes fadeInModal {
    0% { opacity: 0; }
    100% { opacity: 1; }
}

@keyframes zoomInImage {
    0% { transform: scale(0.8); opacity: 0; }
    100% { transform: scale(1); opacity: 1; }
}

/* =========================================
   SIMPLE CONFIRMATION MODAL
   Used by WeekTest.razor's "Start Early?" prompt. This was missing
   entirely before - the .simple-modal-* classes were referenced in markup
   with no matching CSS anywhere, so the dialog rendered unstyled.
========================================= */
.simple-modal-backdrop {
    position: fixed;
    top: 0;
    left: 0;
    width: 100vw;
    height: 100vh;
    background-color: rgba(0, 0, 0, 0.5);
    z-index: 9999;
}

.simple-modal-content {
    position: fixed;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    background: #ffffff;
    border-radius: 16px;
    padding: 2rem;
    max-width: 90vw;
    width: 420px;
    text-align: center;
    z-index: 10000;
    box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}

/* =========================================
   "TAP TO RESPOND" HINT
   Used by Memorial/Event's timeline continue button, and now WeekRemember.
========================================= */
.bounce-hint {
    animation: bounceDown 2s infinite;
    opacity: 0.8;
}

@keyframes bounceDown {
    0%, 20%, 50%, 80%, 100% {
        transform: translateY(0);
    }

    40% {
        transform: translateY(-5px);
    }

    60% {
        transform: translateY(-3px);
    }
}

/* ---------------------------------------------------------------------------
   QR codes (event links, memorial and challenge share panels)

   Generated server-side by QrCode.ForUrl as inline SVG carrying a viewBox, so
   the code scales to whatever box it's given. That matters because a longer URL
   needs more modules - the svg's own dimensions grow with the link, and only
   the container decides how big it actually renders.

   Sizing lives on the wrapper rather than the svg so the white quiet zone a
   scanner needs stays inside the border.
   --------------------------------------------------------------------------- */
.qr-frame {
    /* These sit inside d-flex centering wrappers, and a flex item shrinks below its width by
       default - which collapsed the code to the width of its own padding while the height held.
       Never shrink; on a narrow phone fall back to the available width instead. */
    flex: 0 0 auto;
    max-width: 100%;
    aspect-ratio: 1 / 1;
}

.qr-frame svg {
    width: 100%;
    height: 100%;
    display: block;
}

/* Beside an event link - small enough that several sit in a row. */
.qr-frame-sm { width: 152px; height: 152px; }

/* The share panel's single code, meant to be scanned across a table. */
.qr-frame-lg { width: 200px; height: 200px; }
