/* Game Over Popup Styling */
.game-over-popup {
    position: fixed;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    background-color: rgba(0, 0, 0, 0.8);
    display: flex;
    justify-content: center;
    /* flex-start + child margin:auto + overlay scroll so the Return/Share
       buttons stay reachable on a short landscape phone (align-items:center
       would centre a tall results card and clip its CTAs). Identical on desktop. */
    align-items: flex-start;
    overflow-y: auto;
    padding: max(env(safe-area-inset-top, 0px), 12px) 12px max(env(safe-area-inset-bottom, 0px), 12px);
    box-sizing: border-box;
    z-index: 9999;
    animation: fadeIn 0.5s ease-in-out;
}

/* The persistent battle exit remains useful during play, but the result modal
   owns the only Return action once a match is terminal. JS also applies the
   native `hidden` state; this rule covers a control replaced during teardown. */
body.game-result-active #skip-tutorial-btn {
    display: none !important;
}

.game-over-content {
    background-color: rgba(20, 10, 30, 0.95);
    border: 2px solid #eedbf1;
    border-radius: 15px;
    padding: 30px 40px;
    text-align: center;
    max-width: 500px;
    width: 90%;
    margin: auto;
    box-shadow: 0 0 30px rgba(238, 219, 241, 0.3);
    -webkit-backdrop-filter: blur(5px);
    backdrop-filter: blur(5px);
    animation: scaleIn 0.4s ease-out;
    position: relative;
}

/* Staggered content rise: header, message, buttons, itch link land in sequence */
.game-over-content > h2,
.game-over-content > p,
.game-over-content > .game-over-buttons,
.game-over-content > .game-over-itch-link {
    animation: game-end-rise 300ms cubic-bezier(0.2, 0.9, 0.3, 1) both;
}

.game-over-content > p {
    animation-delay: 120ms;
}

.game-over-content > .game-over-buttons {
    animation-delay: 240ms;
}

.game-over-content > .game-over-itch-link {
    animation-delay: 360ms;
}

@keyframes game-end-rise {
    from {
        opacity: 0;
        transform: translateY(1.2vmin);
    }
}

/* Victory-only floating moon motes, staggered by --mote-i */
.moon-mote {
    position: absolute;
    bottom: 8vh;
    left: calc(8% + var(--mote-i, 0) * 14%);
    width: 1.4vmin;
    height: 1.4vmin;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255, 215, 130, 0.9) 0%, rgba(255, 215, 130, 0) 70%);
    filter: blur(0.5px);
    opacity: 0;
    pointer-events: none;
    animation: mote-float 5s ease-in-out infinite;
    animation-delay: calc(var(--mote-i, 0) * 700ms);
}

@keyframes mote-float {
    0% {
        opacity: 0;
        transform: translateY(0);
    }

    20% {
        opacity: 0.7;
    }

    100% {
        opacity: 0;
        transform: translateY(-55vh);
    }
}

.victory-header {
    color: #6eff9e;
    font-size: 42px;
    margin-bottom: 20px;
    text-shadow: 0 0 10px rgba(110, 255, 158, 0.6);
}

.defeat-header {
    color: #ff6e6e;
    font-size: 42px;
    margin-bottom: 20px;
    text-shadow: 0 0 10px rgba(255, 110, 110, 0.6);
}

/* Warning (e.g., opponent disconnected) */
.warning-header {
    color: #ffd966;
    font-size: 42px;
    margin-bottom: 20px;
    text-shadow: 0 0 10px rgba(255, 217, 102, 0.6);
}

.game-over-content p {
    color: #eedbf1;
    font-size: 18px;
    margin-bottom: 30px;
    line-height: 1.5;
}

.play-again-btn {
    box-sizing: border-box;
    min-height: 48px;
    flex: 1 1 220px;
    max-width: 320px;
    padding: 12px 28px;
    border: 2px solid #d8c5ff;
    border-radius: 9px;
    background: linear-gradient(135deg, #7044c2 0%, #3d237f 100%);
    color: #fff;
    font-family: inherit;
    font-size: 19px;
    font-weight: 700;
    letter-spacing: 0.035em;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.65);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.2),
        0 7px 20px rgba(92, 54, 170, 0.38);
    cursor: pointer;
    transition: transform 180ms ease, background 180ms ease, border-color 180ms ease, box-shadow 180ms ease;
}

.play-again-btn:hover:not(:disabled) {
    transform: translateY(-2px);
    border-color: #f1eaff;
    background: linear-gradient(135deg, #8052d4 0%, #4b2b97 100%);
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.25),
        0 10px 26px rgba(111, 68, 199, 0.52);
}

.play-again-btn:active:not(:disabled) {
    transform: translateY(1px);
    box-shadow:
        inset 0 2px 5px rgba(0, 0, 0, 0.28),
        0 3px 9px rgba(58, 31, 116, 0.45);
}

.play-again-btn:disabled {
    opacity: 0.56;
    cursor: not-allowed;
    transform: none;
    filter: saturate(0.62);
}

.play-again-btn[aria-busy="true"] {
    cursor: wait;
    opacity: 0.72;
    filter: saturate(0.78);
    box-shadow:
        inset 0 0 0 2px rgba(255, 255, 255, 0.13),
        0 4px 12px rgba(58, 31, 116, 0.34);
}

/* Game-over button row + Share Storybook CTA */
.game-over-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    justify-content: center;
    margin-top: 8px;
}

.game-over-content .rematch-status {
    width: min(100%, 430px);
    min-height: 3em;
    margin: -12px auto 18px;
    color: #d9cff0;
    font-size: 15px;
    line-height: 1.5;
}

/* Share sits on the shared command material (geometry, weight and motion all
   come from .game-command-btn) and keeps ONLY its gold accent — it is the
   celebratory action, not a differently-shaped control. */
.game-over-share-btn {
    border-color: #ffd782;
    color: #ffd782;
    text-shadow: 0 0 10px rgba(255, 215, 130, 0.4);
}

.game-over-share-btn:hover:not(:disabled) {
    border-color: #ffe9b0;
    box-shadow:
        inset 0 1px 0 rgba(255, 255, 255, 0.2),
        0 8px 22px rgba(255, 215, 130, 0.32);
}

.play-again-btn:focus-visible,
.game-over-share-btn:focus-visible {
    outline: 3px solid #fff0a8;
    outline-offset: 3px;
    box-shadow: 0 0 0 6px rgba(124, 90, 255, 0.5);
}

/* A lobby toast raised while the results card is up — the "starting too
   quickly" refusal Play Again can draw — must clear that card. `.lobby-toast`
   is z-index 1500, written for a lobby where nothing competes; behind the
   result popup's 9999 and its full-viewport black scrim it was invisible.
   Kept below the consent gate (10200). Lobby toasts are untouched; this
   marker exists only while a terminal result modal is mounted. */
body.game-result-active .lobby-toast {
    z-index: 10101;
}

/* Share modal — sits above the game-over modal */
/* The share sheet is a full-viewport overlay whose card paints at 0.96, so the
   results screen below is fully occluded -- it only ever contributed a ghost of
   "Victory!" and the three result buttons showing through the remaining 4%. That
   was invisible enough to ignore until the privacy line had to be read in the
   same band. `visibility` rather than `display`, so nothing reflows and the
   screen is exactly as it was when the sheet closes. */
body.share-modal-open #game-over-popup {
    visibility: hidden;
}

.share-modal {
    position: fixed;
    inset: 0;
    background: rgba(6, 3, 18, 0.78);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    z-index: 99999;
    display: flex;
    /* flex-start + card margin:auto + scroll so the share card's buttons stay
       reachable on a short landscape phone. Identical on desktop. */
    align-items: flex-start;
    justify-content: center;
    overflow-y: auto;
    animation: fadeIn 220ms ease;
    padding: max(env(safe-area-inset-top, 0px), 24px) 24px max(env(safe-area-inset-bottom, 0px), 24px);
    box-sizing: border-box;
}

.share-modal-card {
    position: relative;
    box-sizing: border-box;
    background: linear-gradient(180deg, rgba(28, 14, 52, 0.96), rgba(12, 6, 26, 0.96));
    border: 1px solid rgba(255, 215, 130, 0.32);
    border-radius: 18px;
    padding: 32px 28px 24px;
    max-width: 480px;
    width: 100%;
    margin: auto;
    color: #eedbf1;
    box-shadow: 0 18px 60px rgba(0, 0, 0, 0.65), 0 0 28px rgba(124, 90, 255, 0.22);
    animation: scaleIn 280ms cubic-bezier(0.2, 0.9, 0.3, 1.05);
}

.share-modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    border: 1px solid rgba(238, 219, 241, 0.18);
    background: rgba(20, 12, 36, 0.7);
    color: #eedbf1;
    font-size: 24px;
    line-height: 1;
    padding: 0;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: background 160ms ease, transform 160ms ease, border-color 160ms ease;
}
.share-modal-close:hover {
    background: rgba(40, 22, 70, 0.9);
    border-color: rgba(255, 215, 130, 0.55);
    transform: scale(1.06);
}

.share-modal-title {
    margin: 0 0 6px;
    font-family: 'Cinzel', serif;
    color: #ffd782;
    font-size: 26px;
    letter-spacing: 0.06em;
    text-align: center;
    text-shadow: 0 0 14px rgba(255, 215, 130, 0.34);
}

.share-modal-subtitle {
    margin: 0 0 18px;
    color: #b6a8c0;
    font-size: 14px;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    text-align: center;
}

/* THE CARD THE LINK WILL SHOW.
   The frame reserves the card's own 1200:630 box from the first paint, so the
   sheet is exactly the same size before the picture arrives, while it is the
   placeholder, and once it is the finished card. Capped against the viewport
   height so a short desktop window keeps the buttons on screen. */
.share-modal-preview {
    margin: 0 0 14px;
    display: flex;
    justify-content: center;
}
.share-modal-preview-frame {
    position: relative;
    width: min(100%, calc(34svh * 1200 / 630));
    aspect-ratio: 1200 / 630;
    border-radius: 12px;
    overflow: hidden;
    isolation: isolate;
    background:
        radial-gradient(ellipse at 50% 40%, rgba(124, 90, 255, 0.22), transparent 62%),
        linear-gradient(180deg, #17102b, #0a0616);
    box-shadow: 0 12px 34px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 215, 130, 0.22);
}
/* A slow sheen while the picture is on its way; it stops the moment it lands. */
.share-modal-preview-frame::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(
        100deg,
        transparent 30%,
        rgba(255, 215, 130, 0.09) 50%,
        transparent 70%
    );
    background-size: 220% 100%;
    animation: sharePreviewSheen 1.8s ease-in-out infinite;
    z-index: 0;
}
.share-modal-preview[data-loaded="true"] .share-modal-preview-frame::before,
.share-modal-preview[data-state="failed"] .share-modal-preview-frame::before {
    animation: none;
    content: none;
}
.share-modal-preview-image {
    position: absolute;
    inset: 0;
    display: block;
    width: 100%;
    height: 100%;
    object-fit: cover;
    opacity: 0;
    transition: opacity 260ms ease;
    z-index: 1;
}
.share-modal-preview[data-loaded="true"] .share-modal-preview-image {
    opacity: 1;
}
/* The ribbon over the card's foot: what this picture IS, while it is still
   the placeholder, and a beat of confirmation when the finished card lands. */
.share-modal-preview-status {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
    margin: 0;
    padding: 8px 12px 9px;
    background: linear-gradient(180deg, rgba(8, 4, 20, 0.55), rgba(8, 4, 20, 0.9));
    color: #ffe6a8;
    font-size: 12.5px;
    line-height: 1.4;
    text-align: center;
    letter-spacing: 0.01em;
    text-wrap: balance;
}
.share-modal-preview[data-state="ready"] .share-modal-preview-status {
    color: #c0ffd0;
}

.share-modal-url-block {
    display: flex;
    flex-direction: column;
    gap: 6px;
    margin-bottom: 12px;
}
.share-modal-url-label {
    font-size: 12px;
    letter-spacing: 0.08em;
    text-transform: uppercase;
    color: #b6a8c0;
}
.share-modal-url,
.share-modal-pending {
    width: 100%;
    padding: 10px 12px;
    background: rgba(8, 4, 20, 0.85);
    border: 1px solid rgba(124, 90, 255, 0.32);
    border-radius: 8px;
    color: #eedbf1;
    font-family: 'JetBrains Mono', 'Menlo', 'Consolas', monospace;
    font-size: 14px;
    letter-spacing: 0.02em;
    outline: none;
}
.share-modal-url:focus {
    border-color: rgba(255, 215, 130, 0.6);
    box-shadow: 0 0 0 3px rgba(255, 215, 130, 0.18);
}

/* THE PREPARING STATE STANDS IN THE LINK'S OWN BOX: an input of the link
   field's make (the shared rule above), read-only, dashed, quiet, inside the
   same labelled block. It used to be a shorter dashed strip, so when the link
   arrived the card grew by seventy pixels and re-centred itself: every element
   -- the preview above it included -- jumped. Same element, same class rules,
   same height in every engine; `share-modal-preview.spec.js` holds the sheet
   still across that transition in three engines and on the phone page boxes. */
.share-modal-pending {
    border-style: dashed;
    border-color: rgba(124, 90, 255, 0.4);
    background: rgba(8, 4, 20, 0.65);
    color: #b6a8c0;
    text-align: center;
    cursor: default;
}

.share-modal-error {
    margin: 4px 0 14px;
    padding: 12px 14px;
    background: rgba(78, 28, 45, 0.42);
    border: 1px solid rgba(255, 146, 164, 0.46);
    border-radius: 8px;
    color: #ffd5dc;
    text-align: center;
    font-size: 13px;
    line-height: 1.5;
}

/* Sits between the body and the share controls. Quieter than the subtitle --
   it is a caution, not a heading -- but NOT scrimmed and not faint: it is the
   only place the reader is told the link is public, so it has to survive a
   glance. Sentence case, because it is a sentence. */
.share-modal-privacy {
    margin: 0 0 14px;
    color: #c3b5cc;
    font-size: 13px;
    line-height: 1.45;
    text-align: center;
    max-width: 42ch;
    margin-inline: auto;
}

.share-modal-buttons {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: center;
    /* Reserved while empty, so the row's arrival does not grow the sheet. */
    min-height: 52px;
}

/* Reuse Storybook share styles: fallback destinations stay compact while the
   single native action reads as one clear, localized CTA. */
.share-modal-buttons .storybook-share-button {
    -webkit-appearance: none;
    appearance: none;
    border: 1px solid rgba(238, 219, 241, 0.18);
    background: rgba(20, 12, 36, 0.72);
    color: #eedbf1;
    font-family: inherit;
    width: 44px;
    height: 44px;
    padding: 0;
    border-radius: 50%;
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: transform 160ms ease, background 160ms ease, border-color 160ms ease, box-shadow 160ms ease, color 160ms ease;
}
.share-modal-buttons .storybook-share-button:hover {
    background: rgba(40, 22, 70, 0.9);
    border-color: rgba(255, 215, 130, 0.55);
    transform: translateY(-1px);
    box-shadow: 0 8px 22px rgba(255, 215, 130, 0.18);
}
.share-modal-buttons .storybook-share-button:focus-visible {
    outline: 3px solid #fff2a8;
    outline-offset: 3px;
}
.share-modal-buttons .storybook-share-native[aria-busy="true"] {
    cursor: progress;
    opacity: 0.62;
}
.share-modal-buttons .storybook-share-button--ok {
    background: rgba(105, 215, 130, 0.18) !important;
    border-color: rgba(120, 255, 160, 0.55) !important;
    color: #c0ffd0 !important;
}
.share-modal-buttons .storybook-share-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 22px;
    height: 22px;
}
.share-modal-buttons .storybook-share-icon svg { display: block; }
.share-modal-buttons .storybook-share-srlabel {
    position: absolute;
    width: 1px;
    height: 1px;
    padding: 0;
    margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
}
.share-modal-buttons .storybook-share-native {
    width: auto;
    min-width: 124px;
    padding: 0 18px;
    border-radius: 999px;
    gap: 9px;
}
.share-modal-buttons .storybook-share-native .storybook-share-srlabel {
    position: static;
    width: auto;
    height: auto;
    padding: 0;
    margin: 0;
    overflow: visible;
    clip: auto;
    white-space: nowrap;
    font-size: 14px;
    font-weight: 700;
    letter-spacing: 0.04em;
}
.share-modal-buttons .storybook-share-twitter:hover  { border-color: #fff;    color: #fff; }
.share-modal-buttons .storybook-share-facebook:hover { border-color: #4f7fe6; color: #6e9bff; }
.share-modal-buttons .storybook-share-reddit:hover   { border-color: #ff7438; color: #ff9959; }
.share-modal-buttons .storybook-share-copy:hover,
.share-modal-buttons .storybook-share-native:hover { color: #ffd782; }

.share-modal-toast {
    margin-top: 14px;
    text-align: center;
    color: #ffd782;
    font-size: 13px;
    letter-spacing: 0.08em;
    height: 18px;
    opacity: 0;
    transition: opacity 180ms ease;
}
.share-modal-toast--show {
    opacity: 1;
}

@media (max-width: 480px) {
    .share-modal-card { padding: 26px 20px 18px; }
    .share-modal-title { font-size: 22px; }
}

/* Safari's visible landscape page box can be only 275–288px tall after browser
   chrome. Keep every share action and the close target inside that box; taller
   error copy can still use the overlay's existing vertical scroll path. */
@media (orientation: landscape) and (max-height: 560px) {
    /* ---- the result card on a landscape phone -----------------------------
       This block styled the SHARE modal and left the result card itself on its
       desktop metrics: 30px/40px padding and a 500px cap inside a 288pt page
       box. The copy then filled the card edge to edge with no breathing room
       and the actions crowded the bottom — "unnaturally ugly crowded /
       proportioned". Rebalance it for a wide, short box: wider and shorter,
       with the padding and type scaled to the space that actually exists, and
       an internal scroll only if a translation genuinely overflows. */
    .game-over-content {
        width: min(94vw, 620px);
        max-width: min(94vw, 620px);
        /* The cap has to describe the box the OVERLAY actually offers. That
           overlay floors each of its vertical paddings at 12px, so subtracting
           the RAW inset let the card stand up to 8px taller than the space it
           was given on a zero-inset phone (iPhone SE landscape, and every
           Firefox/WebKit run, which cannot be handed insets at all). The only
           scroll that could recover those pixels belongs to the overlay, and
           `overscroll-behavior: contain` below stops a swipe that starts on the
           card from chaining out to it — a dead band by construction. Same
           floors here means one scroll owner and no dead band, and it hands the
           card back 4px on a notched phone. */
        max-height: calc(
            100dvh
            - max(var(--mf-safe-top, 0px), 12px)
            - max(var(--mf-safe-bottom, 0px), 12px)
        );
        padding: 12px clamp(16px, 3.4vw, 28px) 14px;
        border-radius: 12px;
        /* THE CARD IS A COLUMN, NOT ONE SCROLL LANE. It used to be a capped
           `overflow-y: auto` box with the action row at the bottom of the
           scrolled content, so the only way out of a finished match stayed
           reachable purely because the copy above it happened to be short.
           Measured at 844x280 with copy one paragraph longer: content 300px in
           a 240px lane, the row 60px below the fold, and on a phone there is no
           scrollbar to say so. Copy yields and scrolls; the actions never move.
           Contract: tests/unit/styles/gameEndLandscapeReach.test.js and
           tests/e2e-playwright/real/game-over-page-box.real.spec.js. */
        display: flex;
        flex-direction: column;
        overflow: hidden;
        overscroll-behavior: contain;
    }

    /* The header keeps its natural size on purpose: it is one short line, and
       giving it a scroll lane would clip the victory/defeat glow (`overflow`
       cuts ink to the padding box whether or not it is scrolling). */
    .game-over-content > h2 {
        flex: 0 0 auto;
        margin: 0 0 4px;
        font-size: clamp(19px, 4.4vh, 26px);
        line-height: 1.12;
    }

    /* The message and the rematch status are the only parts that can grow with
       a translation, so they are the parts that yield. `min-height: 0` is what
       actually permits a flex item to shrink below its content — without it the
       copy refuses to yield and pushes the row out of the card again. */
    .game-over-content > p {
        flex: 0 1 auto;
        min-height: 0;
        overflow-y: auto;
        overscroll-behavior: contain;
        margin: 0 0 8px;
        font-size: clamp(12px, 2.9vh, 15px);
        line-height: 1.3;
    }

    /* One row of equal actions; they are the reason the card is on screen.
       (.game-over-buttons is what game-end.js actually emits — this block
       previously targeted a `.game-over-button-row` class no script ever
       created, so the whole landscape-phone button layout was inert.) */
    .game-over-buttons {
        flex: 0 0 auto;
        gap: 8px;
        margin-top: 10px;
        flex-wrap: nowrap;
    }

    /* EVERY action in the row, not only the ones carrying `game-command-btn`.
       game-end.js gives the rematch button `play-again-btn` ALONE, so the old
       class-keyed rule skipped it: Play Again kept its desktop
       `flex: 1 1 220px` and took ~300px of a 564px row while the other three
       collapsed to ~74px with `nowrap` labels 85-155px wide. Every label — the
       Return CTA's included — spilled out of its own button and over its
       neighbours, in all eight locales, at all six landscape page boxes, in all
       three engines. Equal share, and a label that wraps inside its button
       rather than escaping it. */
    .game-over-buttons > button {
        flex: 1 1 0;
        min-width: 0;
        min-height: 44px;
        padding-inline: 10px;
        font-size: clamp(12px, 2.8vh, 15px);
        white-space: normal;
        line-height: 1.15;
        /* de/pt compounds are one unbreakable word wider than a quarter row. */
        overflow-wrap: anywhere;
    }

    .game-over-itch-link {
        margin-top: 8px;
        font-size: 11px;
    }

    .share-modal {
        padding:
            max(env(safe-area-inset-top, 0px), 6px)
            max(env(safe-area-inset-right, 0px), 8px)
            max(env(safe-area-inset-bottom, 0px), 6px)
            max(env(safe-area-inset-left, 0px), 8px);
    }

    .share-modal-card {
        max-width: 680px;
        padding: 10px 16px 8px;
        border-radius: 14px;
        /* A scale-in temporarily shrinks the 44px Close target to 35.2px and
           also makes the fitted bottom edge appear clipped during first tap. */
        animation: none;
        /* TWO COLUMNS ON A SHORT LANDSCAPE BOX. Stacked, the card preview alone
           is 200px of a 275px page box; beside the link and the buttons it
           costs nothing the row was not already paying. Title and eyebrow
           span both columns; everything actionable stays in the right one. */
        display: grid;
        grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
        grid-template-areas:
            "title title"
            "subtitle subtitle"
            "preview body"
            "preview privacy"
            "preview buttons"
            "preview toast";
        column-gap: 14px;
        align-items: start;
    }
    .share-modal-title { grid-area: title; }
    .share-modal-subtitle { grid-area: subtitle; }
    .share-modal-preview { grid-area: preview; margin: 0; }
    .share-modal-preview-frame { width: 100%; }
    .share-modal-preview-status {
        padding: 5px 8px 6px;
        font-size: 10.5px;
        line-height: 1.3;
    }
    .share-modal-body { grid-area: body; }
    .share-modal-privacy { grid-area: privacy; margin-bottom: 6px; font-size: 11.5px; line-height: 1.3; }
    .share-modal-buttons { grid-area: buttons; }
    .share-modal-toast { grid-area: toast; }

    .share-modal-close {
        top: 6px;
        right: 8px;
        width: 44px;
        height: 44px;
    }

    .share-modal-title {
        margin-bottom: 2px;
        padding-inline: 44px;
        font-size: 20px;
        line-height: 1.2;
    }

    .share-modal-subtitle {
        margin-bottom: 6px;
        font-size: 12px;
        line-height: 1.2;
    }

    .share-modal-url-block {
        gap: 2px;
        margin-bottom: 6px;
    }

    .share-modal-url-label {
        font-size: 10px;
        line-height: 1.2;
    }

    .share-modal-url,
    .share-modal-pending {
        min-height: 44px;
        padding: 7px 10px;
        font-size: 16px;
    }

    .share-modal-error {
        margin: 2px 0 6px;
        padding: 8px 10px;
        line-height: 1.25;
    }

    .share-modal-toast {
        height: 14px;
        margin-top: 4px;
        font-size: 11px;
        line-height: 14px;
    }
}

@keyframes fadeIn {
    from { opacity: 0; }
    to { opacity: 1; }
}

@keyframes sharePreviewSheen {
    from { background-position: 120% 0; }
    to { background-position: -120% 0; }
}

@keyframes scaleIn {
    from { transform: scale(0.8); opacity: 0; }
    to { transform: scale(1); opacity: 1; }
}

/* Animation for victory/defeat/warning text */
.victory-header {
    animation: pulseGreen 2s infinite;
}

.defeat-header {
    animation: pulseRed 2s infinite;
}

.warning-header {
    animation: pulseYellow 2s infinite;
}

@keyframes pulseGreen {
    0% { text-shadow: 0 0 10px rgba(110, 255, 158, 0.6); }
    50% { text-shadow: 0 0 20px rgba(110, 255, 158, 0.9); }
    100% { text-shadow: 0 0 10px rgba(110, 255, 158, 0.6); }
}

@keyframes pulseYellow {
    0% { text-shadow: 0 0 10px rgba(255, 217, 102, 0.6); }
    50% { text-shadow: 0 0 20px rgba(255, 217, 102, 0.9); }
    100% { text-shadow: 0 0 10px rgba(255, 217, 102, 0.6); }
}

@keyframes pulseRed {
    0% { text-shadow: 0 0 10px rgba(255, 110, 110, 0.6); }
    50% { text-shadow: 0 0 20px rgba(255, 110, 110, 0.9); }
    100% { text-shadow: 0 0 10px rgba(255, 110, 110, 0.6); }
}

@media (prefers-reduced-motion: reduce) {
    .game-over-popup,
    .game-over-content,
    .share-modal,
    .share-modal-card,
    .moon-mote,
    .victory-header,
    .defeat-header,
    .warning-header {
        animation: none;
    }

    .moon-mote {
        display: none;
    }

    .game-over-content > h2,
    .game-over-content > p,
    .game-over-content > .game-over-buttons,
    .game-over-content > .game-over-itch-link {
        animation: none;
    }

    .play-again-btn,
    .game-over-share-btn,
    .share-modal-close,
    .share-modal-buttons .storybook-share-button,
    .share-modal-preview-image,
    .share-modal-toast {
        transition: none;
    }

    .share-modal-preview-frame::before {
        animation: none;
    }

    .play-again-btn:hover:not(:disabled),
    .play-again-btn:active:not(:disabled),
    .game-over-share-btn:hover,
    .game-over-share-btn:active,
    .share-modal-close:hover,
    .share-modal-buttons .storybook-share-button:hover {
        transform: none;
    }
}
