/**
 * Auth View Styles
 * Login and signup forms with premium aesthetic
 */

/* Auth View Container */
#auth-view {
    display: none;
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    /* Cover the WHOLE viewport, but reserve the fixed legal-footer strip as
       padding rather than by ending early. Centring the card against the full
       height pushed "Continue with Google" under the 50px footer on a
       landscape phone — the button was visible and enabled, but the footer
       owned its centre and swallowed every tap. Ending the element above the
       footer fixed the tap but left the lobby art showing through the strip;
       padding reserves the same space while the background still fills the
       screen. The strip height is measured live by legal-footer-fit.js.
       overflow-y keeps the card reachable if it ever outgrows the space. */
    bottom: 0;
    padding-bottom: var(--legal-footer-h, 40px);
    background: linear-gradient(135deg, #0a0a1a 0%, #1a1a3a 50%, #0a0a1a 100%);
    justify-content: center;
    /* NOT `align-items: center`. Centring a flex item that is taller than its
       scroll container pushes the item's top ABOVE the scroll origin, where it
       is unreachable — on a landscape phone that silently ate the logo and the
       title. `margin: auto` on the card centres it identically while leaving
       every edge scrollable. */
    align-items: flex-start;
    overflow-y: auto;
    overflow-x: hidden;
    /* viewport-fit=cover puts the page under the notch; keep the card out of it. */
    padding-left: var(--mf-safe-left, 0px);
    padding-right: var(--mf-safe-right, 0px);
    box-sizing: border-box;
    z-index: 1000;
}

/* Auth Styles */

/* User Controls - Fixed at top left, mirrors language-selector on right */
.user-controls {
    position: fixed;
    top: 0.75rem;
    left: 1rem;
    /* HIDDEN UNTIL A LOBBY PATH REVEALS IT — this is the whole account gate.
       Everything in this strip is account-scoped, and the code has always been
       written as if this rule existed: `index.html` says the Quests pill "lives
       inside #user-controls, which is hidden by CSS and revealed with
       `display: flex` only on the authenticated path", and
       `questsButtonAuthGate.test.js` rests its entire contract on it. It did
       not exist. The base was `flex`, so the strip painted from the very first
       frame and every child was held back only by its own inline
       `display: none` — which is why removing the Quests pill's inline style
       (correctly: the clear that was supposed to run never did) left it as the
       one control with no guard at all.

       Reported as "while lobby was loading all buttons and ui elements didnt
       appear, except the quests buttn". Measured with no auth stub of any kind,
       recorder installed at document start: WebKit 932x300 painted
       `#user-controls` and `#lobby-quests-btn` at 251ms, over `#app-loading`,
       and held them past 900ms; Chromium at 123ms; desktop never showed it
       because `lobby.css` hides the pill and only the phone gate promotes it.

       Both reveal paths already set `display: flex` inline — `proceedToLobby`
       in main.js and returning to the lobby in lobby.js — and every path into a
       game or the auth card already sets `none`, so the strip is now symmetric
       and arrives as one piece. Contract:
       tests/e2e-playwright/lobby-chrome-load-order.spec.js. */
    display: none;
    align-items: center;
    gap: 0.5rem;
    height: 30px;
    z-index: 9999;
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

.user-controls > * {
    height: 30px;
    margin: 0;
    box-sizing: border-box;
}

.user-username {
    color: rgba(255, 255, 255, 0.85);
    font-size: 0.78rem;
    line-height: 1;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.15);
    padding: 0 0.85rem;
    height: 30px;
    border-radius: 999px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    max-width: min(14rem, 42vw);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
}

.user-stardust {
    -webkit-appearance: none;
    appearance: none;
    color: #b99adc;
    font-size: 0.8rem;
    font-weight: 600;
    font-family: inherit;
    line-height: 1;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(138, 100, 200, 0.35);
    padding: 0 0.8rem;
    height: 30px;
    min-width: 3.2rem;
    border-radius: 999px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    margin: 0;
    cursor: pointer;
    gap: 0.3em;
    transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}

/* The Stardust glyph leads the number — the same drawing the store's balance
   pill and pack prices use, so the chip and the store it opens agree. A
   pseudo-element, because `FX.setCountDisplay` writes the chip's text and
   would wipe a child node on every count animation frame. Sized a hair
   under the old ☆ character's advance so the chip's width is unchanged. */
.user-stardust::before {
    content: '';
    flex: none;
    width: 0.95em;
    height: 0.95em;
    background: var(--mf-stardust-glyph) center / contain no-repeat;
}

.user-stardust:hover:not([disabled]) {
    color: #d5baff;
    background: rgba(30, 17, 47, 0.88);
    border-color: rgba(185, 154, 220, 0.68);
    box-shadow: 0 4px 14px rgba(52, 24, 82, 0.45);
}

.user-stardust:focus-visible {
    outline: 2px solid #ead9ff;
    outline-offset: 2px;
}

.signout-btn {
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(255, 255, 255, 0.15);
    color: white;
    padding: 0 0.85rem;
    height: 30px;
    border-radius: 999px;
    cursor: pointer;
    font-size: 0.8rem;
    line-height: 1;
    transition: all 0.2s ease;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    box-sizing: border-box;
}

.signout-btn:hover {
    background: rgba(30, 30, 50, 0.85);
    border-color: rgba(255, 255, 255, 0.25);
    transform: translateY(-1px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.4);
}

@media (max-width: 1100px) {
    .user-controls {
        max-width: calc(100vw - 13rem);
        height: auto;
        flex-wrap: wrap;
        align-content: flex-start;
    }
}

@media (max-width: 480px) {
    .user-controls {
        top: 0.5rem;
        height: auto;
        max-width: calc(100vw - 9rem);
        flex-wrap: wrap;
        align-content: flex-start;
    }
}

/* Hide user controls during game - only show in lobby */
#game-view~.user-controls,
body.game-active .user-controls {
    display: none;
}

/* Auth Card */
.auth-card {
    background: rgba(20, 20, 40, 0.9);
    border: 1px solid rgba(138, 100, 200, 0.3);
    border-radius: 16px;
    padding: 40px;
    width: 100%;
    max-width: 400px;
    /* pairs with #auth-view's flex-start: centres, but stays scrollable */
    margin: auto;
    box-shadow:
        0 20px 60px rgba(0, 0, 0, 0.5),
        0 0 40px rgba(138, 100, 200, 0.1),
        inset 0 1px 0 rgba(255, 255, 255, 0.05);
    -webkit-backdrop-filter: blur(20px);
    backdrop-filter: blur(20px);
}

/* Auth Logo */
.auth-logo {
    display: block;
    max-width: 200px;
    margin: 0 auto 30px;
}

/* Auth Title */
.auth-title {
    font-family: 'Cinzel', serif;
    font-size: 1.8rem;
    color: #e8d5b7;
    text-align: center;
    margin: 0 0 30px;
    text-shadow: 0 2px 10px rgba(138, 100, 200, 0.3);
}

/* Form Container */
.auth-form {
    display: flex;
    flex-direction: column;
    gap: 20px;
}

/* Form Groups */
.form-group {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.form-group label {
    font-family: 'Spectral', serif;
    font-size: 0.9rem;
    color: #a0a0c0;
    text-transform: uppercase;
    letter-spacing: 1px;
}

/* Input Fields */
.auth-input {
    background: rgba(0, 0, 0, 0.4);
    border: 1px solid rgba(138, 100, 200, 0.2);
    border-radius: 8px;
    padding: 14px 16px;
    font-family: 'Spectral', serif;
    font-size: 1rem;
    color: #e0e0f0;
    transition: all 0.3s ease;
}

.auth-input:focus {
    outline: none;
    border-color: rgba(138, 100, 200, 0.6);
    box-shadow: 0 0 15px rgba(138, 100, 200, 0.2);
}

.auth-input::placeholder {
    color: #606080;
}

/* Auth Button */
.auth-btn {
    background: linear-gradient(135deg, #6b4e9e 0%, #8a64c8 50%, #6b4e9e 100%);
    border: none;
    border-radius: 8px;
    padding: 16px 24px;
    font-family: 'Cinzel', serif;
    font-size: 1rem;
    font-weight: 600;
    color: #ffffff;
    cursor: pointer;
    transition: all 0.3s ease;
    text-transform: uppercase;
    letter-spacing: 2px;
    margin-top: 10px;
}

.auth-btn:hover:not(:disabled) {
    background: linear-gradient(135deg, #7b5eae 0%, #9a74d8 50%, #7b5eae 100%);
    box-shadow: 0 5px 20px rgba(138, 100, 200, 0.4);
    transform: translateY(-2px);
}

.auth-btn:active:not(:disabled) {
    transform: translateY(0);
}

.auth-btn:disabled {
    opacity: 0.6;
    cursor: not-allowed;
}

/* Continue with Google — follows Google's official brand guidelines
   (https://developers.google.com/identity/branding-guidelines). The button
   has to read as a real, trusted Google sign-in entry point, so we override
   the .auth-btn purple-gradient + Cinzel-uppercase styling with the official
   light-theme spec: white background, neutral border, sentence-case Roboto
   text, and a flex layout that keeps the four-color G logo locked next to
   the label. */
.auth-btn-google {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 12px;
    background: #ffffff;
    color: #1f1f1f;
    border: 1px solid #747775;
    border-radius: 4px;
    padding: 10px 16px;
    min-height: 40px;
    font-family: 'Roboto', -apple-system, BlinkMacSystemFont, 'Segoe UI', Arial, sans-serif;
    font-size: 14px;
    font-weight: 500;
    letter-spacing: 0.25px;
    text-transform: none;
    box-shadow: none;
    transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease;
    margin-top: 0;
}

.auth-btn-google:hover:not(:disabled) {
    background: #f8f9fa;
    color: #1f1f1f;
    border-color: #5f6368;
    box-shadow: 0 1px 3px rgba(60, 64, 67, 0.16);
    transform: none;
}

.auth-btn-google:active:not(:disabled) {
    background: #f1f3f4;
    color: #1f1f1f;
    border-color: #5f6368;
    transform: none;
}

.auth-btn-google:focus-visible {
    outline: 2px solid #4285f4;
    outline-offset: 2px;
}

.auth-btn-google svg {
    flex-shrink: 0;
    width: 18px;
    height: 18px;
}

.auth-oauth-buttons {
    display: flex;
    flex-direction: column;
    gap: 12px;
}

/* Auth Links */
.auth-links {
    text-align: center;
    margin-top: 20px;
}

.auth-link {
    color: #8a64c8;
    text-decoration: none;
    font-family: 'Spectral', serif;
    font-size: 0.95rem;
    transition: color 0.3s ease;
}

.auth-link:hover {
    color: #b094e0;
    text-decoration: underline;
}

/* Error Message */
.auth-error {
    display: none;
    background: rgba(200, 50, 50, 0.2);
    border: 1px solid rgba(200, 50, 50, 0.4);
    border-radius: 8px;
    padding: 12px 16px;
    color: #ff8080;
    font-family: 'Spectral', serif;
    font-size: 0.9rem;
    text-align: center;
}

/* Loading Spinner */
.auth-loading {
    display: none;
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background: rgba(10, 10, 26, 0.8);
    justify-content: center;
    align-items: center;
    border-radius: 16px;
}

.auth-spinner {
    width: 40px;
    height: 40px;
    border: 3px solid rgba(138, 100, 200, 0.2);
    border-top-color: #8a64c8;
    border-radius: 50%;
    animation: auth-spin 1s linear infinite;
}

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

/* Divider */
.auth-divider {
    display: flex;
    align-items: center;
    gap: 15px;
    color: #606080;
    font-size: 0.85rem;
    margin: 10px 0;
}

.auth-divider::before,
.auth-divider::after {
    content: '';
    flex: 1;
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(138, 100, 200, 0.3), transparent);
}

/* Responsive */
@media (max-width: 480px) {
    .auth-card {
        margin: 20px;
        padding: 30px 25px;
    }

    .auth-title {
        font-size: 1.5rem;
    }
}

/* ------------------------------------------------------------------ */
/* Guest tutorial sign-in moment                                       */
/* Injected onto the sign-in card when an anonymous player finishes or  */
/* skips the play-first tutorial ("Keep your cards. Save your story.").  */
/* ------------------------------------------------------------------ */
.auth-guest-teaser {
    margin: -14px 0 24px;
    text-align: center;
}

.auth-guest-teaser-line {
    font-family: 'Spectral', serif;
    font-size: 0.98rem;
    line-height: 1.5;
    color: #cdbde8;
    margin: 0;
}

.auth-guest-notice {
    font-family: 'Spectral', serif;
    font-size: 0.9rem;
    color: #e8d5b7;
    text-align: center;
    margin: 0 0 18px;
    padding: 10px 14px;
    border-radius: 10px;
    background: rgba(200, 160, 90, 0.12);
    border: 1px solid rgba(200, 160, 90, 0.28);
}

.auth-guest-replay {
    display: block;
    width: 100%;
    margin: 18px auto 0;
    padding: 10px 16px;
    background: transparent;
    border: none;
    color: #9f86c9;
    font-family: 'Spectral', serif;
    font-size: 0.92rem;
    letter-spacing: 0.3px;
    text-decoration: underline;
    text-underline-offset: 3px;
    cursor: pointer;
    transition: color 0.18s ease;
}

.auth-guest-replay:hover,
.auth-guest-replay:focus-visible {
    color: #d3c0f0;
    outline: none;
}

/* ---------------------------------------------------------------------------
   SHORT VIEWPORTS — the sign-in card must fit WITHOUT scrolling.

   A landscape phone hands the page far less height than its screen suggests:
   an iPhone 15 Pro Max is 430pt tall, but Safari's URL bar and tab strip leave
   the page ~300pt, and the legal bar claims 50 of those. At the shipped sizes
   the guest card ("Keep your cards. Save your story." + teaser + Continue with
   Google + replay link) laid out ~394px tall in a 250px strip: the logo and
   title were pushed off the top and the replay link sat under the legal bar.

   These tiers are height-driven, because the constraint is purely vertical —
   the same squeeze hits a short desktop window. Everything shrinks
   proportionally so the card still reads as the same card.
   Locked by tests/e2e-playwright/mobile-viewport-fit.spec.js.
   --------------------------------------------------------------------------- */
@media (max-height: 620px) {
    .auth-card { padding: 22px 26px; }
    .auth-logo { max-width: 132px; margin-bottom: 14px; }
    .auth-title { font-size: 1.35rem; margin-bottom: 14px; }
    /* the base rule pulls the teaser up under a 1.8rem title with a -14px
       margin; at these reduced title sizes that pull collides with it. */
    .auth-guest-teaser { margin: -6px 0 12px; }
    .auth-guest-notice { margin-bottom: 12px; padding: 8px 12px; font-size: 0.85rem; }
    .auth-guest-replay { margin-top: 10px; }
}

@media (max-height: 480px) {
    .auth-card { padding: 10px 18px; max-width: 360px; }
    .auth-logo { max-width: 88px; margin-bottom: 4px; }
    .auth-title { font-size: 1rem; margin-bottom: 4px; line-height: 1.18; }
    .auth-guest-teaser { margin: 0 0 4px; font-size: 0.78rem; line-height: 1.3; }
    .auth-guest-notice { margin-bottom: 5px; padding: 5px 10px; font-size: 0.76rem; line-height: 1.3; }
    .auth-guest-replay { margin-top: 2px; padding: 4px 12px; font-size: 0.83rem; }
    .auth-btn-google { min-height: 40px; padding: 8px 14px; }
}

/* ============================================================
   MOONLIGHT — a lit dial and a bare percentage, no words at all.
   ============================================================
   It inherits the strip's grammar exactly (30px, pill, blur, tabular
   numerals) and diverges on ONE thing: hue. Stardust is plum; Moonlight is
   cold silver. Two adjacent lavender currency pills is where a rail turns to
   soup, and cold white also refuses to read as money — which is the point.
   Moonlight is a state of the world, not a second wallet. */
.user-moonlight {
    -webkit-appearance: none;
    appearance: none;
    color: #dfe4ff;
    font-size: 0.8rem;
    font-weight: 650;
    font-family: inherit;
    line-height: 1;
    background: rgba(0, 0, 0, 0.75);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(178, 190, 235, 0.32);
    padding: 0 0.7rem;
    height: 30px;
    border-radius: 999px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 0.42rem;
    box-sizing: border-box;
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
    margin: 0;
    cursor: pointer;
    transition: border-color 0.2s ease, background-color 0.2s ease, box-shadow 0.2s ease;
}

.user-moonlight[hidden] { display: none; }

.user-moonlight:hover:not([disabled]) {
    background: rgba(20, 24, 44, 0.88);
    border-color: rgba(210, 220, 255, 0.6);
}

/* SEGMENTS. Ten pips that go out one at a time — countable at a glance
   without reading the number beside them.

   The shipped design before this was a 20px lunar dial, and the owner rejected
   it for reasons the pips answer directly: its unlit face was `#241d38`, dark
   purple on a near-black pill, so at a low value the chip simply disappeared;
   it was the same size and shape as its neighbours, so it read as a third
   currency; and nothing happened on hover, so there was no sign it was a
   control at all. An unlit pip here is a VISIBLE OBJECT rather than a hole, the
   row is long where the neighbours are round, and hovering brightens the lit
   pips. */
.moonlight-track {
    display: inline-flex;
    align-items: center;
    gap: 3px;
    /* Anything beyond ONE cycle — an upgrade, a Refill on a live balance, a
       grant — glows around the whole row. Abundance, never overflow, and it
       cannot be confused with a pip. */
    border-radius: 3px;
    box-shadow: 0 0 calc(var(--moonlight-halo, 0) * 9px) rgba(var(--moonlight-glow), 0.6);
    transition: box-shadow 420ms ease;
}

.moonlight-seg {
    width: 7px;
    height: 13px;
    border-radius: 2px;
    /* Light enough to stay an object on the dark pill at every value. This is
       the specific failure the dial had. */
    background: rgba(150, 165, 215, 0.22);
    transition: background 200ms ease, box-shadow 200ms ease;
}

/* TIER COLOUR. One pair of tokens per plan, so every state below — armed,
   overcharged, hover — is a modifier of the tier's own hue rather than a
   competing colour. A state that repainted the bar in another tier's colour
   would make the tier unreadable. */
.user-moonlight {
    --moonlight-lit-a: #f4f6ff;
    --moonlight-lit-b: #c8d3ff;
    --moonlight-glow: 200, 211, 255;
}

/* STORYTELLER OWNS A HUE, not a brightness. This used to be #ffffff -> #a9beff
   against free's #f4f6ff -> #c8d3ff: hue 226 against hue 225, six points of
   lightness apart. Two tiers that differ only in how pale they are read as the
   same tier at a 20px pill, which is exactly what the tier signal exists to
   prevent. Indigo-violet separates from free's blue-silver and from manga's
   gold, and stays in the night palette without borrowing Stardust's plum
   (#b99adc, hue 271) — Moonlight must never read as the currency. */
.user-moonlight.is-tier-storyteller {
    --moonlight-lit-a: #f0edff;
    --moonlight-lit-b: #8a7dff;
    --moonlight-glow: 138, 125, 255;
}

.user-moonlight.is-tier-manga {
    --moonlight-lit-a: #fff8e6;
    --moonlight-lit-b: #e9cd8f;
    --moonlight-glow: 233, 205, 143;
}

.user-moonlight.is-tier-storyteller { border-color: rgba(138, 125, 255, 0.5); }
.user-moonlight.is-tier-manga { border-color: rgba(233, 205, 143, 0.5); }

.moonlight-seg.is-lit {
    background: linear-gradient(180deg, var(--moonlight-lit-a), var(--moonlight-lit-b));
    box-shadow: 0 0 5px rgba(var(--moonlight-glow), 0.5);
}

/* The control answers the pointer, so it reads as a button rather than a
   readout. */
.user-moonlight:hover:not([disabled]) .moonlight-seg.is-lit {
    box-shadow: 0 0 8px rgba(var(--moonlight-glow), 0.85);
}

/* ARMED is a brightness, not a repaint: on the Manga tier a hue change would
   be invisible against the tier's own gold. */
.user-moonlight.is-manga-armed .moonlight-seg.is-lit {
    filter: brightness(1.18);
    box-shadow: 0 0 8px rgba(var(--moonlight-glow), 0.8);
}

/* OVERCHARGED — above one full cycle. Ten lit pips already say "full", so a
   surplus needs its own language rather than a number nobody can see. The row
   turns warm gold, the glow doubles, and it breathes slowly at a strength that
   tracks the surplus. It reads as abundance; nothing here is a warning. */
/* THE SURPLUS PAINTS ONLY ITS OWN PIPS — a second pass over the same ten.
   At 140% four are charged and six are ordinary; at 200% all ten are. It keeps
   the tier's colour and goes white-hot at the top of the pip, so it reads as
   MORE OF YOUR OWN plan rather than as somebody else's. */
.user-moonlight .moonlight-seg.is-lit.is-surplus {
    /* The WHOLE pip sits at the light end of the tier ramp, not just its top
       stop — against a neighbour running `lit-a -> lit-b` that is a real step
       rather than a shade. Plus a taller glow and the pulse. */
    background: linear-gradient(180deg, #ffffff, var(--moonlight-lit-a));
    box-shadow:
        0 0 10px rgba(var(--moonlight-glow), 1),
        inset 0 0 0 1px rgba(255, 255, 255, 0.85);
    animation: moonlight-overcharge 2.6s ease-in-out infinite;
}

/* Each pip lags the one before it, so the surplus reads as a current running
   along the row rather than lamps blinking together. */
.user-moonlight .moonlight-seg.is-surplus:nth-child(2n) { animation-delay: 0.18s; }
.user-moonlight .moonlight-seg.is-surplus:nth-child(3n) { animation-delay: 0.36s; }

.user-moonlight.is-overcharged .moonlight-track {
    box-shadow: 0 0 calc(6px + var(--moonlight-halo, 0) * 10px) rgba(var(--moonlight-glow), 0.7);
}

.user-moonlight.is-overcharged .moonlight-value { color: var(--moonlight-lit-a); }

@keyframes moonlight-overcharge {
    0%, 100% { filter: brightness(1); }
    50% { filter: brightness(calc(1 + var(--moonlight-halo, 0) * 0.35)); }
}

/* Reduced motion keeps the colour and the glow — the STATE is information —
   and drops only the pulse. */
@media (prefers-reduced-motion: reduce) {
    .user-moonlight .moonlight-seg.is-surplus { animation: none; }
}

/* UNKNOWN is its own state and is NEVER an empty row: a failed read must not
   render as zero in front of a player who has plenty. Every pip sits at a
   neutral half-light, which is a shape no real value produces. */
.user-moonlight.is-unknown { opacity: 0.4; }
.user-moonlight.is-unknown .moonlight-seg {
    background: rgba(180, 192, 235, 0.4);
    box-shadow: none;
}

/* The number never yields. It is the value the chip exists to report, it has
   no ellipsis and nothing clips it, so any width taken off it is width its ink
   spends outside the pill. The dial above absorbs instead. */
.moonlight-value {
    flex: 0 0 auto;
    letter-spacing: 0.01em;
}

/* THE EXPANDED CARD — the only surface in this whole system with more than two
   lines, and the only one where a duel count appears. It explains; it never
   sells and never gates. Anchored under the chip and clamped into the viewport
   by `moonlight-card.js`, which sets left/top after measuring the real box. */
.moonlight-card {
    position: fixed;
    z-index: 2600;
    min-width: 210px;
    max-width: min(92vw, 320px);
    padding: 0.7rem 0.85rem 0.75rem;
    border-radius: 14px;
    background: rgba(14, 16, 30, 0.96);
    -webkit-backdrop-filter: blur(12px);
    backdrop-filter: blur(12px);
    border: 1px solid rgba(178, 190, 235, 0.28);
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.55);
    color: #dfe4ff;
    font-size: 0.82rem;
    line-height: 1.35;
    pointer-events: auto;
}

/* The Stardust tip: same material, one word, none of the card's structure. */
.moonlight-card--tip {
    min-width: 0;
    padding: 0.35rem 0.6rem;
}

.moonlight-card__head {
    display: flex;
    align-items: baseline;
    gap: 0.5rem;
    margin-bottom: 0.45rem;
}

.moonlight-card__percent {
    font-size: 1.45rem;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.moonlight-card__name {
    font-size: 0.72rem;
    letter-spacing: 0.06em;
    text-transform: uppercase;
    color: rgba(223, 228, 255, 0.6);
}

.moonlight-card__rows { display: grid; gap: 0.15rem; }

.moonlight-card__row { margin: 0; }

.moonlight-card__note,
.moonlight-card__returns {
    margin: 0.5rem 0 0;
    font-size: 0.74rem;
    color: rgba(223, 228, 255, 0.62);
}

/* The date is the one warm thing on the card: Moonlight coming back is the
   good news, and it should not read like the rest of the small print. */
.moonlight-card__returns { color: #e0c68a; }

/* A phone gets it as a sheet at the bottom of the strip rather than a popover
   hanging off a 30px chip in a 300px-tall page box. */
@media (orientation: landscape) and (max-height: 560px) {
    .moonlight-card {
        max-width: min(94vw, 300px);
        font-size: 0.76rem;
        padding: 0.5rem 0.65rem 0.55rem;
    }
    .moonlight-card__percent { font-size: 1.15rem; }
    .moonlight-card__note,
    .moonlight-card__returns { margin-top: 0.35rem; font-size: 0.68rem; }
}

/* The Moonlight wall — it rises FROM the button that summoned it, with that
   button still lit above. Reuses the panel material so it reads as a place in
   the game rather than an error dialog, and is sized in svh/dvh so a phone
   never pushes its last line off the visible page. */
.moonlight-wall {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    z-index: 60;
    width: min(92vw, 440px);
    max-height: min(62svh, 420px);
    overflow-y: auto;
    margin-top: 0.6rem;
    padding: 1.1rem 1.2rem calc(1.1rem + var(--mf-safe-bottom, 0px));
    box-sizing: border-box;
    border-radius: 14px;
    border: 1px solid rgba(178, 190, 235, 0.24);
    border-left: 3px solid rgba(214, 224, 255, 0.75);
    background: rgba(12, 14, 26, 0.94);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    box-shadow: 0 18px 44px rgba(0, 0, 0, 0.5);
    color: #e8ebff;
    text-align: center;
}

.moonlight-wall__dial {
    width: 64px;
    height: 64px;
    margin: 0 auto 0.7rem;
    border-radius: 50%;
    background: #241d38;
    /* The ash limb ring stays: the moon is DARK, not missing. */
    box-shadow: inset 0 0 0 1px rgba(178, 190, 235, 0.28);
}

.moonlight-wall__title {
    margin: 0 0 0.45rem;
    font-size: 1.02rem;
    font-weight: 650;
    line-height: 1.3;
}

.moonlight-wall__returns {
    margin: 0 0 0.5rem;
    color: #e0c68a;
    font-size: 0.88rem;
}

.moonlight-wall__finishes {
    margin: 0 0 0.9rem;
    color: rgba(232, 235, 255, 0.62);
    font-size: 0.82rem;
}

.moonlight-wall__action {
    -webkit-appearance: none;
    appearance: none;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    min-height: var(--mf-touch, 44px);
    padding: 0 1.2rem;
    border-radius: 999px;
    border: 1px solid rgba(210, 220, 255, 0.5);
    background: linear-gradient(135deg, rgba(226, 233, 255, 0.16), rgba(160, 176, 232, 0.24));
    color: #f2f5ff;
    font: inherit;
    font-weight: 650;
    cursor: pointer;
}

.moonlight-wall__note {
    margin: 0.5rem 0 0;
    color: rgba(232, 235, 255, 0.55);
    font-size: 0.76rem;
}

.moonlight-wall__close {
    position: absolute;
    top: 0.35rem;
    right: 0.5rem;
    min-width: var(--mf-touch, 44px);
    min-height: var(--mf-touch, 44px);
    background: none;
    border: 0;
    color: rgba(232, 235, 255, 0.6);
    font-size: 1.1rem;
    cursor: pointer;
}
