/* ============================================================================
   Blazor reconnect overlay.

   Blazor Server holds UI state in a SignalR circuit. When a phone sleeps, the
   user switches apps, or the network blips, the OS drops the WebSocket and the
   framework tells the user. That is unavoidable on Server render mode — no
   framework version removes it, because the connection genuinely did drop.

   What IS avoidable is how it looks and how often anyone sees it. Two things
   here do that work:

   1. THE DELAY. Blazor adds `components-reconnect-show` the instant the socket
      drops, and `components-reconnect-hide` the instant it comes back. When a
      phone wakes, that round trip is usually well under a second — so the stock
      overlay paints a scary "Attempting to reconnect to the server" and then
      vanishes, for a problem that already fixed itself. Revealing on a 2s
      animation delay means those successful reconnects show the user nothing at
      all. This is most of the fix.

   2. TERMINAL STATES SHOW IMMEDIATELY. `failed` and `rejected` are not
      transient, so they skip the delay and say something a congregant can act
      on. `rejected` also triggers an automatic reload — see js/reconnect.js.

   Supplying an element with id="components-reconnect-modal" makes Blazor use it
   instead of injecting its own (see App.razor). The framework then only toggles
   state classes on it; all presentation is ours. Class names are fixed by the
   framework and verified against the served blazor.web.js — do not rename them.

   States, in the order a drop actually walks through them:
     components-reconnect-show           socket dropped, retrying
     components-reconnect-retrying       added alongside `show` from attempt 2
     components-reconnect-paused         retries paused (backgrounded tab)
     components-reconnect-hide           recovered — the common case
     components-reconnect-failed         retries exhausted
     components-reconnect-resume-failed  same, but resuming a paused circuit
     components-reconnect-rejected       server no longer has the circuit
   ============================================================================ */

/* MudBlazor ships its own #components-reconnect-modal rules and marks
   `z-index` and `background-color` !important. Those two !importants below are
   answering that vendor stylesheet, which we can't edit — not papering over an
   inline style. Without them the overlay renders as an opaque full-page sheet
   (--mud-palette-background) instead of a scrim, which reads far more alarming
   for something that usually clears in under a second. Verified in the browser,
   not assumed. Same reason the button below is selected via the id. */
#components-reconnect-modal {
    position: fixed;
    inset: 0;
    /* Above every MudBlazor layer (dialog 1300, snackbar 1400, tooltip 1600).
       A dead circuit outranks anything painted underneath it. */
    z-index: 20000 !important;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    background-color: rgba(15, 23, 42, 0.38) !important;
    -webkit-backdrop-filter: blur(2px);
    backdrop-filter: blur(2px);
    /* Hidden until a state class opts in. `visibility` (not just opacity) so the
       overlay cannot swallow taps while invisible. */
    opacity: 0;
    visibility: hidden;
}

/* ── Reveal ───────────────────────────────────────────────────────────────── */

/* Transient states: wait 2s before showing anything. If `hide` lands first the
   animation is cancelled and the overlay never becomes visible. All three
   selectors share one identical animation value on purpose — `retrying` is
   ADDED alongside `show`, and a differing value would restart the delay. */
#components-reconnect-modal.components-reconnect-show,
#components-reconnect-modal.components-reconnect-retrying,
#components-reconnect-modal.components-reconnect-paused {
    animation: cu-reconnect-in 200ms ease-out 2000ms forwards;
}

/* Terminal states: no delay. Differing from the value above is what makes the
   animation restart at 0ms rather than inherit the pending 2s delay. */
#components-reconnect-modal.components-reconnect-failed,
#components-reconnect-modal.components-reconnect-resume-failed,
#components-reconnect-modal.components-reconnect-rejected {
    animation: cu-reconnect-in 200ms ease-out forwards;
}

#components-reconnect-modal.components-reconnect-hide {
    animation: none;
    opacity: 0;
    visibility: hidden;
}

@keyframes cu-reconnect-in {
    from { opacity: 0; visibility: visible; }
    to   { opacity: 1; visibility: visible; }
}

/* ── Card ─────────────────────────────────────────────────────────────────── */

.cu-reconnect-card {
    background: var(--church-surface, #fff);
    color: var(--church-text, #0f172a);
    border-radius: 16px;
    box-shadow: 0 12px 40px rgba(0, 0, 0, 0.18);
    padding: 28px 26px;
    width: 100%;
    max-width: 340px;
    text-align: center;
}

.cu-reconnect-spinner {
    width: 34px;
    height: 34px;
    margin: 0 auto 16px;
    border-radius: 50%;
    border: 3px solid var(--church-border-light, #e2e8f0);
    border-top-color: var(--church-primary, #2563eb);
    animation: cu-reconnect-spin 800ms linear infinite;
}

@keyframes cu-reconnect-spin {
    to { transform: rotate(360deg); }
}

.cu-reconnect-title {
    margin: 0;
    font-size: 1.0625rem;
    font-weight: 700;
    letter-spacing: -0.01em;
}

.cu-reconnect-sub {
    margin: 6px 0 0;
    font-size: 0.9375rem;
    line-height: 1.45;
    color: var(--church-text-secondary, #475569);
}

/* Selected via the id, not the class alone: MudBlazor's `#components-reconnect-modal
   button` rule (specificity 1,0,1) outranks a bare `.cu-reconnect-btn` (0,1,0) and
   would otherwise impose UPPERCASE, 14px text and 40px vertical margins. Its margins
   are !important, so ours have to be too. */
#components-reconnect-modal .cu-reconnect-btn {
    margin: 18px 0 0 !important;
    /* 44px min touch target. */
    min-height: 44px;
    padding: 0 22px;
    width: 100%;
    border: none;
    border-radius: 10px;
    background: var(--church-primary, #2563eb);
    color: var(--church-on-primary, #fff);
    font-size: 1rem;
    font-weight: 600;
    font-family: inherit;
    text-transform: none;
    letter-spacing: normal;
    line-height: 1.2;
    cursor: pointer;
}

#components-reconnect-modal .cu-reconnect-btn:hover { filter: brightness(0.94); }
#components-reconnect-modal .cu-reconnect-btn:focus-visible { outline: 3px solid #fff; outline-offset: 2px; }

/* ── Which copy shows for which state ─────────────────────────────────────── */

/* Default: the waiting treatment. The failure copy and the button stay out of
   the accessibility tree until they apply. */
.cu-reconnect-lost,
#components-reconnect-modal .cu-reconnect-btn {
    display: none;
}

#components-reconnect-modal.components-reconnect-failed .cu-reconnect-spinner,
#components-reconnect-modal.components-reconnect-resume-failed .cu-reconnect-spinner,
#components-reconnect-modal.components-reconnect-failed .cu-reconnect-waiting,
#components-reconnect-modal.components-reconnect-resume-failed .cu-reconnect-waiting {
    display: none;
}

#components-reconnect-modal.components-reconnect-failed .cu-reconnect-lost,
#components-reconnect-modal.components-reconnect-resume-failed .cu-reconnect-lost,
#components-reconnect-modal.components-reconnect-failed .cu-reconnect-btn,
#components-reconnect-modal.components-reconnect-resume-failed .cu-reconnect-btn {
    display: block;
}

@media (prefers-reduced-motion: reduce) {
    .cu-reconnect-spinner { animation-duration: 2s; }
    #components-reconnect-modal.components-reconnect-show,
    #components-reconnect-modal.components-reconnect-retrying,
    #components-reconnect-modal.components-reconnect-paused,
    #components-reconnect-modal.components-reconnect-failed,
    #components-reconnect-modal.components-reconnect-resume-failed,
    #components-reconnect-modal.components-reconnect-rejected {
        animation-duration: 1ms;
    }
}
