/* ==========================================================================
   splash.css — the app's one animated splash.

   TWO MOMENTS, ONE PICTURE
     boot    the installed app is opening. iOS has just shown the static
             launch image (images/splash/*.png) and Android the manifest's
             background_color; this takes over the instant the document paints.
     signin  credentials are on their way to the server.

   WHY THE ODD NUMBERS
     Every size below is a fraction of `--pe-u` (the viewport's short side) and
     the fractions are lifted from generate_splash_icons.py, which drew the
     static PNGs: icon 0.15, wordmark 0.04, tagline 0.42x the wordmark, dots at
     0.12x, centre at 38% of the height. Same geometry, same gradient, same
     colours — so the hand-off from Apple's static image to this one is a frame
     the user cannot see, and then the dots start moving.
     Change a number here only alongside that script, or the two drift apart.

   Colours are the fixed brand constants (identical in light and dark, exactly
   like the launch image), read from tokens.css when the page has it and
   falling back to the literal so this works on surfaces that don't.
   ========================================================================== */

.pe-splash,
html.pe-splash-boot::before {
    /* #0D1F45 is BG_DARK in the generator; the rest are the brand tokens. */
    background: linear-gradient(180deg,
                var(--brand-navy-deep, #0D1F45) 0%,
                var(--brand-navy, #173269) 100%);
}

/* Painted from the <head>, before <body> exists, so the app never flashes
   white between the launch image and the splash. Removed with the splash. */
html.pe-splash-boot::before {
    content: "";
    position: fixed;
    inset: 0;
    z-index: 2147483000;
}

.pe-splash {
    position: fixed;
    inset: 0;
    z-index: 2147483001;
    overflow: hidden;
    /* The short side of the viewport — the generator's min(width, height). */
    --pe-u: min(100vw, 100vh);
    --pe-icon: calc(var(--pe-u) * 0.15);
    --pe-name: calc(var(--pe-u) * 0.04);
    --pe-tag: calc(var(--pe-name) * 0.42);
    --pe-dot: calc(var(--pe-name) * 0.24);   /* diameter; the generator's radius x2 */
    font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
    opacity: 1;
    transition: opacity 0.35s ease;
}
.pe-splash.is-leaving { opacity: 0; pointer-events: none; }
.pe-splash[hidden] { display: none; }

/* Nothing scrolls under the splash. */
body.pe-splash-open { overflow: hidden; }

/* The two barely-there circles the generator bleeds off the corners. */
.pe-splash::before,
.pe-splash::after {
    content: "";
    position: absolute;
    border-radius: 50%;
    background: color-mix(in srgb, var(--brand-sky, #7ACEFF) 2.4%, transparent);
    pointer-events: none;
}
.pe-splash::before {
    width: calc(var(--pe-u) * 0.35);
    height: calc(var(--pe-u) * 0.35);
    top: calc(var(--pe-u) * -0.175);
    right: calc(var(--pe-u) * -0.175);
}
.pe-splash::after {
    width: calc(var(--pe-u) * 0.47);
    height: calc(var(--pe-u) * 0.29);
    left: calc(var(--pe-u) * -0.117);
    bottom: calc(var(--pe-u) * -0.117);
}

/* --- the mark: centred at 38% of the height, exactly as the PNG ---------- */
.pe-splash-mark {
    position: absolute;
    top: 38%;
    left: 50%;
    width: var(--pe-icon);
    height: var(--pe-icon);
    transform: translate(-50%, -50%);
    animation: peSplashBreathe 2.8s ease-in-out infinite;
    filter: drop-shadow(0 0 calc(var(--pe-u) * 0.05)
            color-mix(in srgb, var(--brand-sky, #7ACEFF) 22%, transparent));
}

/* --- wordmark, tagline, dots -------------------------------------------- */
.pe-splash-copy {
    position: absolute;
    top: calc(38% + var(--pe-icon) * 0.55);
    left: 50%;
    transform: translateX(-50%);
    width: 100%;
    text-align: center;
    line-height: 1;
}
.pe-splash-name {
    font-size: var(--pe-name);
    font-weight: 700;
    letter-spacing: 0.01em;
    color: #fff;
    white-space: nowrap;
}
.pe-splash-name em {
    font-style: normal;
    margin-inline-start: 0.1em;
    color: var(--brand-sky, #7ACEFF);
}
.pe-splash-tag {
    margin-top: calc(var(--pe-tag) * 0.6);
    font-size: var(--pe-tag);
    color: color-mix(in srgb, #fff 40%, transparent);
}
.pe-splash-dots {
    display: flex;
    justify-content: center;
    gap: calc(var(--pe-dot) * 0.5);
    margin-top: calc(var(--pe-name) * 1.2);
}
.pe-splash-dots span {
    width: var(--pe-dot);
    height: var(--pe-dot);
    min-width: 3px;
    min-height: 3px;
    border-radius: 50%;
    background: var(--brand-sky, #7ACEFF);
    opacity: 0.24;
    animation: peSplashDot 1.25s ease-in-out infinite;
}
.pe-splash-dots span:nth-child(2) { animation-delay: 0.16s; }
.pe-splash-dots span:nth-child(3) { animation-delay: 0.32s; }

/* --- sign-in only: the staged status line -------------------------------
   Stacked in one grid cell so a stage change cross-fades in place instead of
   reflowing the column. Hidden entirely while the app is booting, where the
   dots say everything there is to say. */
.pe-splash-status {
    display: none;
    margin-top: calc(var(--pe-name) * 1.1);
    min-height: 1.5em;
    font-size: calc(var(--pe-name) * 0.5);
    color: color-mix(in srgb, #fff 72%, transparent);
}
.pe-splash--signin .pe-splash-status { display: grid; }
.pe-splash-msg {
    grid-area: 1 / 1;
    padding: 0 6vw;
    opacity: 0;
    transform: translateY(6px);
    transition: opacity 0.35s ease, transform 0.35s ease;
}
.pe-splash-msg.is-on {
    opacity: 1;
    transform: none;
}

.pe-splash-foot {
    position: absolute;
    top: 95%;
    left: 0;
    right: 0;
    text-align: center;
    font-size: calc(var(--pe-name) * 0.35);
    color: color-mix(in srgb, #fff 16%, transparent);
}

@keyframes peSplashBreathe {
    0%, 100% { transform: translate(-50%, -50%) scale(1); }
    50%      { transform: translate(-50%, -50%) scale(1.05); }
}
@keyframes peSplashDot {
    0%, 100% { opacity: 0.24; transform: scale(1); }
    50%      { opacity: 1;    transform: scale(1.25); }
}

/* Landscape phones: 38% of a short height puts the lockup under the fold of
   the copy, so pull the whole composition up a little. */
@media (orientation: landscape) and (max-height: 480px) {
    .pe-splash { --pe-icon: calc(var(--pe-u) * 0.26); --pe-name: calc(var(--pe-u) * 0.07); }
    .pe-splash-mark { top: 30%; }
    .pe-splash-copy { top: calc(30% + var(--pe-icon) * 0.55); }
    .pe-splash-foot { display: none; }
}

/* Motion-sensitive users keep the splash — it simply stops moving. */
@media (prefers-reduced-motion: reduce) {
    .pe-splash,
    .pe-splash-mark,
    .pe-splash-dots span,
    .pe-splash-msg {
        animation: none;
        transition: none;
    }
    .pe-splash-mark { transform: translate(-50%, -50%); }
    .pe-splash-dots span:nth-child(2) { opacity: 0.47; }
}
