/* ============================================================================
   EMAIL GATE (v0.20.3.0) - Components/Shared/EmailGate.razor + EmailGateStage.razor,
   behaviour in Scripts/email-gate.ts (js/email-gate.js).

   What a signed-in account with an unproven address sees instead of the app: the
   board as it will be, behind frosted glass, and the six-digit prompt on top.

   Two decisions carry the whole design, everything else is the /login card's own
   vocabulary (08-auth.css) so the prompt reads as the same front door:

     1. The STAGE is blurred, not dimmed. A dark scrim says "something is in the
        way"; a blur says "this is yours, one step away". The layer is inert and
        aria-hidden - it is a promise, not a surface - so it needs no pointer or
        focus handling of its own.

     2. The DRUMS. The six cells are the streak chronometer's digit cells grown to
        fingertip size: the same dark face in both themes (47-local-clock.css), the
        same violet rim, the same mono digits. Each landing digit hits harder than
        the one before - the pop, the glow, the meter, the halo behind the card all
        read --hit (n/6, set on the drum in markup) and --egate-level (0..6, set on
        the root by the script) - so the sixth is an event, not a sixth keystroke.

   Motion law (23-motion.css): the script flips classes and writes the two custom
   properties; every transform, glow and shake is declared here and runs on the
   compositor. Reduced motion keeps every state colour and drops every movement.
   ============================================================================ */

.egate {
    position: relative;
    /* Above .modal-backdrop (200) and the notice rail; the gate outranks everything the
       page could raise, because there is no page. */
    --egate-z: 400;
}

/* ---- the stage: the board behind the glass ------------------------------ */
.egate-stage {
    min-height: 100vh;
    min-height: 100dvh;
    overflow: hidden;
    filter: blur(7px) saturate(0.85);
    transform: scale(1.015);          /* hides the blur's soft edge at the viewport rim */
    pointer-events: none;
    user-select: none;
}
/* The demo board is static markup wearing the product's classes: buttons became spans,
   so the few rules that assume a <button> are restated for the span. */
.egate-demo .horizon-tab,
.egate-demo .chip,
.egate-demo .calday { display: inline-flex; align-items: center; justify-content: center; }
.egate-demo .upgrade-btn { display: inline-flex; align-items: center; padding: 6px 16px; }

/* ---- the sky: the login aurora, fixed and clipped ------------------------
   Its own fixed layer under the veil so the 76vmax blooms never add scroll height to the
   card layer above, which has to scroll on a short phone with the keyboard up. */
.egate-sky {
    position: fixed;
    inset: 0;
    z-index: var(--egate-z);
    overflow: hidden;
    pointer-events: none;
    background:
        radial-gradient(800px 400px at 30% 0%, rgba(124, 58, 237, 0.16), transparent 60%),
        radial-gradient(600px 400px at 80% 100%, rgba(236, 72, 153, 0.12), transparent 60%),
        rgba(250, 247, 240, 0.38);
}
.egate-sky .login-aurora { position: absolute; inset: 0; z-index: 0; }
:root[data-theme="dark"] .egate-sky { background-color: rgba(15, 17, 22, 0.55); }

/* ---- the veil: the card layer ------------------------------------------- */
.egate-veil {
    position: fixed;
    inset: 0;
    z-index: calc(var(--egate-z) + 1);
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 20px;
    overflow-y: auto;
    overflow-x: hidden;
    -webkit-overflow-scrolling: touch;
}

/* ---- the card: the /login card, with a halo that grows with the level ----- */
.egate-card {
    position: relative;
    z-index: 1;
    width: 100%;
    max-width: 440px;
    margin: auto;                     /* centres inside the scroll container in both axes */
    border: 1px solid transparent;
    background:
        linear-gradient(var(--chronos-card-bg), var(--chronos-card-bg)) padding-box,
        linear-gradient(150deg, rgba(191, 127, 255, 0.55), rgba(124, 58, 237, 0.2) 30%,
            rgba(236, 72, 153, 0.3) 65%, rgba(191, 127, 255, 0.5)) border-box;
    box-shadow:
        0 24px 60px rgba(17, 24, 39, 0.28),
        0 0 calc(30px + var(--egate-level, 0) * 14px)
            rgba(124, 58, 237, calc(0.12 + var(--egate-level, 0) * 0.08));
    transition: box-shadow var(--d3) var(--e-quart);
    animation: login-card-in 0.9s cubic-bezier(0.22, 0.9, 0.3, 1.2) both;
}
.egate-card > * {
    animation: login-block-in 0.55s cubic-bezier(0.22, 0.9, 0.36, 1) both;
}
.egate-card > :nth-child(1) { animation-delay: 0.20s; }
.egate-card > :nth-child(2) { animation-delay: 0.34s; }
.egate-card > :nth-child(3) { animation-delay: 0.46s; }
.egate-card > :nth-child(4) { animation-delay: 0.58s; }

.egate-card .auth-logo {
    position: relative;
    z-index: 1;
    animation: login-logo-in 0.8s cubic-bezier(0.18, 1.2, 0.4, 1) 0.15s both;
    filter: drop-shadow(0 0 14px rgba(124, 58, 237, 0.45));
}
.egate-title { font-family: var(--chronos-font-display); }
.egate-lede { max-width: 34ch; line-height: 1.5; }
/* anywhere, not break-all: a long address may break, a short one must stay one word - break-all
   split "reader@example.com" after "reade" on a card that had room for the whole thing. */
.egate-lede b { color: var(--chronos-fg-primary); font-weight: 600; overflow-wrap: anywhere; }

/* ---- the form ------------------------------------------------------------ */
.egate-form {
    display: flex;
    flex-direction: column;
    gap: 14px;
}

/* ---- the drums ----------------------------------------------------------- */
.egate-drums {
    position: relative;
    display: flex;
    justify-content: center;
    gap: 10px;
    /* the row itself kicks on each digit; --hit is copied here by the script */
    --hit: 0;
}
.egate-drum {
    width: 52px;
    height: 66px;
    padding: 0;
    border-radius: 12px;
    border: 1px solid rgba(139, 92, 246, 0.40);
    background:
        linear-gradient(180deg, rgba(255, 255, 255, 0.10) 0%, rgba(255, 255, 255, 0) 40%),
        radial-gradient(130% 100% at 12% 30%, rgba(168, 85, 247, 0.24), transparent 62%),
        linear-gradient(180deg, #241F35 0%, #14121F 58%, #1A1728 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.08),
        inset 0 -2px 5px rgba(0, 0, 0, 0.35),
        0 2px 10px rgba(124, 58, 237, 0.18);
    color: #F1ECFF;
    font-family: var(--chronos-font-mono);
    font-size: 28px;
    font-weight: 700;
    line-height: 1;
    text-align: center;
    font-variant-numeric: tabular-nums;
    text-shadow: 0 0 8px rgba(167, 139, 250, 0.35);
    caret-color: var(--chronos-lavender);
    outline: none;
    -webkit-appearance: none;
    appearance: none;
    transition: border-color var(--d2) var(--e-quart), box-shadow var(--d2) var(--e-quart),
                opacity var(--d2) var(--e-quart), color var(--d2) var(--e-quart);
}
/* Same answer as every text field on /login: the ring is drawn INSIDE the box. The soft
   outer bloom is the one thing allowed to cross the rim, because the drum is the
   instrument the whole prompt is about. */
.egate-drum:focus {
    border-color: var(--chronos-lavender);
    box-shadow:
        inset 0 0 0 1px var(--chronos-lavender),
        inset 0 -2px 5px rgba(0, 0, 0, 0.35),
        0 0 0 4px rgba(124, 58, 237, 0.16);
}
.egate-drum:focus-visible { outline: none; }
/* Landed: the rim goes solid and the glow scales with --hit, so the sixth drum burns
   brighter than the first even at rest. */
.egate-drum.is-filled {
    border-color: rgba(168, 85, 247, calc(0.55 + var(--hit, 0) * 0.45));
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.10),
        inset 0 -2px 5px rgba(0, 0, 0, 0.35),
        0 0 calc(8px + var(--hit, 0) * 22px) rgba(124, 58, 237, calc(0.25 + var(--hit, 0) * 0.45));
}
/* The landing itself: a pop whose height and reach are --hit. */
.egate-drum.is-hit { animation: egate-pop 360ms var(--e-spring); }
@keyframes egate-pop {
    0%   { transform: scale(1) translateY(0); }
    38%  { transform: scale(calc(1 + var(--hit, 0.2) * 0.30)) translateY(calc(var(--hit, 0.2) * -7px)); }
    100% { transform: scale(1) translateY(0); }
}
/* The row jumps with it, more each time. */
.egate-drums.is-kick { animation: egate-kick 320ms var(--e-spring); }
@keyframes egate-kick {
    0%   { transform: translateY(0); }
    40%  { transform: translateY(calc(var(--hit, 0) * -5px)); }
    100% { transform: translateY(0); }
}
/* The sixth: a ring leaves the row. */
.egate-drums::after {
    content: "";
    position: absolute;
    inset: -6px -10px;
    border-radius: 18px;
    border: 2px solid rgba(191, 127, 255, 0.7);
    opacity: 0;
    pointer-events: none;
}
.egate-drums.is-full::after { animation: egate-ring 620ms var(--e-quart); }
@keyframes egate-ring {
    0%   { opacity: 0.8; transform: scale(1); }
    100% { opacity: 0;   transform: scale(1.18); }
}

/* ---- the meter ----------------------------------------------------------- */
.egate-meter {
    display: grid;
    grid-template-columns: repeat(6, 1fr);
    gap: 6px;
    padding: 0 6px;
}
.egate-meter > span {
    height: 4px;
    border-radius: 2px;
    background: var(--chronos-outline);
    transition: background var(--d2) var(--e-quart), box-shadow var(--d2) var(--e-quart);
}
.egate-meter > span.is-lit {
    background: var(--chronos-violet);
    box-shadow: 0 0 8px rgba(124, 58, 237, 0.55);
}
.egate-meter > span.is-lit:nth-child(4) { background: var(--chronos-lavender); }
.egate-meter > span.is-lit:nth-child(5) { background: var(--chronos-lavender); box-shadow: 0 0 10px rgba(168, 85, 247, 0.7); }
.egate-meter > span.is-lit:nth-child(6) { background: var(--chronos-pink); box-shadow: 0 0 12px rgba(236, 72, 153, 0.7); }

/* ---- messages ------------------------------------------------------------ */
.egate-msg { margin: 0; text-align: center; }
.egate-msg-bad { font-weight: 500; }

/* ---- verdicts: the script adds one class to .egate --------------------- */
.egate.is-wrong .egate-drums { animation: egate-shake 420ms var(--e-quart); }
.egate.is-wrong .egate-drum {
    border-color: var(--chronos-red);
    box-shadow: inset 0 -2px 5px rgba(0, 0, 0, 0.35), 0 0 14px rgba(239, 68, 68, 0.45);
    color: #FECACA;
}
@keyframes egate-shake {
    10%, 90% { transform: translateX(-1px); }
    20%, 80% { transform: translateX(2px); }
    30%, 50%, 70% { transform: translateX(-4px); }
    40%, 60% { transform: translateX(4px); }
}
.egate.is-locked .egate-drum { opacity: 0.45; }
.egate.is-locked .egate-meter > span { background: var(--chronos-outline); box-shadow: none; }
.egate.is-done .egate-drum {
    border-color: #34D399;
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.10), 0 0 18px rgba(16, 185, 129, 0.45);
    color: #D1FAE5;
    text-shadow: 0 0 10px rgba(52, 211, 153, 0.6);
}
.egate.is-done .egate-meter > span { background: #34D399; box-shadow: 0 0 8px rgba(16, 185, 129, 0.55); }
.egate.is-done .egate-card { box-shadow: 0 24px 60px rgba(17, 24, 39, 0.28), 0 0 70px rgba(16, 185, 129, 0.35); }
.egate.is-busy .egate-drum { pointer-events: none; }

/* ---- the foot ------------------------------------------------------------ */
.egate-why { text-align: center; line-height: 1.5; margin: 0; }
/* The support address: same treatment as the sign-up consent links (.auth-legal a). */
.egate-why a { color: var(--chronos-violet); text-decoration: none; overflow-wrap: anywhere; }
.egate-why a:hover { text-decoration: underline; }
.egate-foot a { color: var(--chronos-fg-muted); }

/* ---- resend cooldown: the ghost button counts down ---------------------- */
.btn-ghost[data-egate-resend]:disabled {
    opacity: 0.55;
    cursor: default;
    font-variant-numeric: tabular-nums;
}
.btn-ghost[data-egate-resend]:disabled:hover { background: transparent; }

/* ---- /studio: the card inline, no stage, no fixed layers ----------------- */
.egate-preview .egate-veil {
    position: static;
    padding: 0;
    overflow: visible;
    display: block;
}
.egate-preview .egate-card { animation: none; margin: 0; }
.egate-preview .egate-card > * { animation: none; }
.egate-preview .egate-card .auth-logo { animation: none; }
.egate-preview .login-title .lt { animation: none; }
.egate-preview .login-sub { animation: none; }

/* ---- phone ---------------------------------------------------------------
   Six drums have to share 375px minus the card's own padding: 6 x 44 + 5 x 7 = 299.
   The card is pinned near the top instead of centred so the software keyboard, which
   takes the lower half of the visual viewport, never covers the drums the reader is
   typing into; the veil scrolls for whatever is left below. */
@media (max-width: 480px) {
    .egate-veil {
        align-items: flex-start;
        padding: max(18px, 6vh) 12px calc(18px + env(safe-area-inset-bottom, 0px));
    }
    .egate-card {
        margin: 0 auto;
        padding: 22px 16px 16px;
        gap: 14px;
        border-radius: 16px;
    }
    .egate-card .auth-header h1 { font-size: 20px; }
    .egate-drums { gap: 7px; }
    .egate-drum { width: 44px; height: 58px; font-size: 24px; border-radius: 10px; }
    .egate-drums::after { inset: -5px -7px; border-radius: 14px; }
    .egate-meter { padding: 0 2px; }
    .auth-actions:has([data-egate-resend]) { grid-template-columns: 1fr; }
    .egate-lede { max-width: none; }
    /* the blurred board is a phone board here: same single column the real one collapses to */
    .egate-stage { filter: blur(6px) saturate(0.85); }
}
/* Narrowest phones (320px): 6 x 40 + 5 x 6 = 270. */
@media (max-width: 340px) {
    .egate-drums { gap: 6px; }
    .egate-drum { width: 40px; height: 54px; font-size: 22px; }
}
/* A phone turned sideways, or a laptop with the window short: still reachable. */
@media (max-height: 560px) {
    .egate-veil { align-items: flex-start; }
    .egate-card { margin: 0 auto; }
}

/* ---- reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
    .egate-card, .egate-card > *, .egate-card .auth-logo,
    .egate .login-title .lt, .egate .login-sub,
    .egate-drum.is-hit, .egate-drums.is-kick, .egate-drums.is-full::after,
    .egate.is-wrong .egate-drums,
    .egate-sky .login-aurora::before, .egate-sky .login-aurora::after,
    .egate .login-logo-wrap::before, .egate .login-logo-wrap::after,
    .egate .login-title::after { animation: none !important; }
    .egate-card, .egate-drum, .egate-meter > span { transition: none; }
}
