/* ==========================================================================
   Motion: shared keyframes and utilities for the app's small animations (tab switches, list entrances, press feedback,
   sheets, skeletons, reward count-ups and bursts). Loaded last so it can tune what the screens' own sheets set.

   Rules of thumb:
   - Fast (150–400 ms), springy on the way in, and only transform and opacity, so the compositor does the work.
   - Entrances fill "backwards" only: a lingering transform makes an element the containing block for position: fixed
     descendants, which would trap popups and the battle overlay inside it (see .sc-fade-in in site.css).
   - Entrances play when an element is inserted, never on a re-render, so busy screens (battles, timers) stay calm.
   - Everything here is off under prefers-reduced-motion (the block at the bottom), and motion.js checks it too.
   ========================================================================== */

:root {
    --sk-motion-fast: 160ms;
    --sk-motion: 280ms;
    --sk-motion-slow: 400ms;
    --sk-stagger-step: 35ms;
}

/* Rings that show progress (--p, a number from 0 to 100) glide to a new value instead of jumping */
@property --p {
    syntax: "<number>";
    inherits: true;
    initial-value: 0;
}

.app-avatar,
.avatar-wrapper,
.badge-ring,
.badge-mini-ring {
    transition: --p 700ms var(--sc-ease-out);
}

/* ---------- Press feedback ---------- */

/* Tiles and buttons sink a touch and glow while pressed, then spring back. .btn and .button already scale on :active;
   this adds the glow and the springy release, and gives tiles (.sk-press) the same feel. */
.sk-press,
.store-card,
.store-pack,
.backpack-team-pick,
.chal-card,
.trophy-tile,
.skanimal-sort-btn,
.store-tab,
.backpack-tab {
    -webkit-tap-highlight-color: transparent;
    transition: transform var(--sk-motion) var(--sc-ease-spring), box-shadow 200ms ease, border-color 200ms ease,
        background-color 200ms ease, opacity 200ms ease, filter 200ms ease;
}

.btn,
.button {
    -webkit-tap-highlight-color: transparent;
    transition: transform var(--sk-motion) var(--sc-ease-spring), box-shadow 200ms ease, filter 200ms ease, opacity 200ms ease;
}

:is(.sk-press, .store-card, .store-pack, .backpack-team-pick, .skanimal-sort-btn, .store-tab, .backpack-tab):active:not(:disabled) {
    transform: scale(0.96);
    transition-duration: 90ms;
}

:is(.btn-primary, .button, .sk-press.is-glow, .store-pack):active:not(:disabled) {
    transition-duration: 90ms;
    box-shadow: 0 0 0 3px rgba(var(--sc-primary-rgb), 0.22), 0 0 22px rgba(var(--sc-primary-rgb), 0.45);
}

.btn:active:not(:disabled),
.button:active {
    transition-duration: 90ms;
}

/* Hover lift, only where there's a real pointer (a tap shouldn't leave a card stuck in the air on a phone) */
@media (hover: hover) and (pointer: fine) {
    :is(.store-card, .store-pack, .chal-card, .trophy-tile, .backpack-item):hover {
        transform: translateY(-2px);
        box-shadow: 0 10px 24px rgba(0, 0, 0, 0.35);
    }
    .skanimals-card.is-selectable:hover {
        transform: translateY(-3px);
    }
}

/* ---------- Tab switches ---------- */

/* The panel slides in from the side of the tab that was picked: further right comes in from the right */
.tabs-panel-inner.sk-tab-fwd {
    animation: sk-tab-in-fwd var(--sk-motion) var(--sc-ease-out) backwards;
}

.tabs-panel-inner.sk-tab-back {
    animation: sk-tab-in-back var(--sk-motion) var(--sc-ease-out) backwards;
}

@keyframes sk-tab-in-fwd {
    from { opacity: 0; transform: translateX(28px); }
}

@keyframes sk-tab-in-back {
    from { opacity: 0; transform: translateX(-28px); }
}

/* Nested tabs (Social's Friends / Trades / Mail) move a little less */
.tabs-segmented > .tabs-panel > .tabs-panel-inner.sk-tab-fwd { animation-name: sk-tab-in-fwd-sm; }
.tabs-segmented > .tabs-panel > .tabs-panel-inner.sk-tab-back { animation-name: sk-tab-in-back-sm; }

@keyframes sk-tab-in-fwd-sm { from { opacity: 0; transform: translateX(16px); } }
@keyframes sk-tab-in-back-sm { from { opacity: 0; transform: translateX(-16px); } }

/* The pill behind the active tab pops when picked */
.tabs-segmented .tab-button.active,
.store-tab.is-active,
.backpack-tab.is-active {
    animation: sk-pill-pop 320ms var(--sc-ease-spring);
}

@keyframes sk-pill-pop {
    from { transform: scale(0.92); }
}

/* ---------- Screen headers ---------- */

.screen-title {
    animation: sk-head-in 360ms var(--sc-ease-spring) backwards;
}

.screen-subtitle {
    animation: sk-head-in 360ms var(--sc-ease-out) 60ms backwards;
}

.screen-header-actions {
    animation: sk-fade 300ms ease 120ms backwards;
}

@keyframes sk-head-in {
    from { opacity: 0; transform: translateY(-8px) scale(0.98); }
}

@keyframes sk-fade {
    from { opacity: 0; }
}

/* ---------- Staggered entrances ---------- */

/* Children of a list or grid (the containers are listed in motion.js, or marked .sk-stagger) rise in one after another.
   motion.js adds .sk-enter and a delay step to each child as Blazor inserts it, and takes them off when the entrance
   ends, so a later state change (a challenge claimed, an item bought) can never replay it. Anything with its own,
   more specific animation keeps it. */
.sk-enter {
    animation: sk-rise-in 340ms var(--sc-ease-out) backwards;
}

.sk-enter.sk-d1 { animation-delay: calc(1 * var(--sk-stagger-step)); }
.sk-enter.sk-d2 { animation-delay: calc(2 * var(--sk-stagger-step)); }
.sk-enter.sk-d3 { animation-delay: calc(3 * var(--sk-stagger-step)); }
.sk-enter.sk-d4 { animation-delay: calc(4 * var(--sk-stagger-step)); }
.sk-enter.sk-d5 { animation-delay: calc(5 * var(--sk-stagger-step)); }
.sk-enter.sk-d6 { animation-delay: calc(6 * var(--sk-stagger-step)); }
.sk-enter.sk-d7 { animation-delay: calc(7 * var(--sk-stagger-step)); }
.sk-enter.sk-d8 { animation-delay: calc(8 * var(--sk-stagger-step)); }
.sk-enter.sk-d9 { animation-delay: calc(9 * var(--sk-stagger-step)); }
.sk-enter.sk-d10 { animation-delay: calc(10 * var(--sk-stagger-step)); }
.sk-enter.sk-d11 { animation-delay: calc(11 * var(--sk-stagger-step)); }

@keyframes sk-rise-in {
    from { opacity: 0; transform: translateY(12px) scale(0.97); }
}

/* Single elements that pop in (notices, banners, a "Coming soon" card) */
.sk-pop-in,
.store-banner,
.backpack-notice,
.store-detail,
.store-soon {
    animation: sk-pop-in 320ms var(--sc-ease-spring) backwards;
}

@keyframes sk-pop-in {
    from { opacity: 0; transform: translateY(6px) scale(0.96); }
}

/* ---------- Sheets and the backdrop ---------- */

/* Sheets slide up with a little settle at the top; the backdrop fades. "backwards" so nothing lingers on the sheet. */
.title-sheet-backdrop {
    animation: sk-backdrop-in 220ms ease-out backwards;
}

.title-sheet {
    animation: sk-sheet-up 460ms var(--sc-ease-out) backwards;
}

.title-sheet-backdrop.is-closing {
    animation: sk-backdrop-out 200ms ease-in forwards;
    pointer-events: none;
}

.title-sheet-backdrop.is-closing .title-sheet {
    animation: sk-sheet-down 220ms cubic-bezier(0.4, 0, 1, 1) forwards;
}

@keyframes sk-backdrop-in { from { opacity: 0; } }
@keyframes sk-backdrop-out { to { opacity: 0; } }

@keyframes sk-sheet-up {
    0% { transform: translateY(100%); }
    70% { transform: translateY(-1.2%); }
    100% { transform: none; }
}

@keyframes sk-sheet-down {
    to { transform: translateY(100%); }
}

/* ---------- Skeletons (a section loading, in place of a spinner) ---------- */

.sk-skel-grid {
    display: grid;
    grid-template-columns: repeat(2, minmax(0, 1fr));
    gap: 12px;
    padding: 4px 0;
}

.sk-skel-grid.is-tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 10px; }

.sk-skel-rows {
    display: grid;
    gap: 8px;
    padding: 4px 0;
}

.sk-skel {
    position: relative;
    overflow: hidden;
    border-radius: var(--sc-radius);
    background: rgba(160, 200, 255, 0.07);
    isolation: isolate;
}

.sk-skel::after {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(100deg, transparent 20%, rgba(255, 255, 255, 0.09) 50%, transparent 80%);
    transform: translateX(-100%);
    animation: sk-skel-sweep 1.3s ease-in-out infinite;
}

.sk-skel-card { aspect-ratio: 3 / 4; border-radius: 20px; }
.sk-skel-row { height: 62px; }
.sk-skel-tile { aspect-ratio: 1; }
.sk-skel-line { height: 12px; border-radius: 6px; }

/* Each skeleton block starts its sweep a moment after the last, so the shimmer travels down the list */
.sk-skel-grid > .sk-skel:nth-child(2)::after,
.sk-skel-rows > .sk-skel:nth-child(2)::after { animation-delay: 0.1s; }
.sk-skel-grid > .sk-skel:nth-child(3)::after,
.sk-skel-rows > .sk-skel:nth-child(3)::after { animation-delay: 0.2s; }
.sk-skel-grid > .sk-skel:nth-child(4)::after,
.sk-skel-rows > .sk-skel:nth-child(4)::after { animation-delay: 0.3s; }

@keyframes sk-skel-sweep {
    to { transform: translateX(100%); }
}

/* ---------- Reward chips: count-ups, bumps and flying coins (driven by motion.js) ---------- */

.sk-count {
    display: inline-block;
    font-variant-numeric: tabular-nums;
}

/* The chip a reward lands on gives a springy bump and a glow */
.sk-chip-bump {
    animation: sk-chip-bump 420ms var(--sc-ease-spring);
}

.sc-coins.sk-chip-bump { box-shadow: inset 0 0 0 1px rgba(255, 200, 61, 0.6), 0 0 16px rgba(255, 200, 61, 0.55); }
.sc-bytes.sk-chip-bump { box-shadow: inset 0 0 0 1px rgba(143, 120, 255, 0.7), 0 0 16px rgba(143, 120, 255, 0.6); }

@keyframes sk-chip-bump {
    0% { transform: scale(1); }
    35% { transform: scale(1.16); }
    100% { transform: scale(1); }
}

/* A spend dips the chip instead */
.sk-chip-dip {
    animation: sk-chip-dip 300ms var(--sc-ease-out);
}

@keyframes sk-chip-dip {
    40% { transform: scale(0.94); opacity: 0.8; }
}

/* The particles themselves: fixed to the viewport, moved by the Web Animations API (transform and opacity only) */
.sk-fly {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 3000;
    width: 18px;
    height: 18px;
    margin: -9px 0 0 -9px;
    pointer-events: none;
    will-change: transform, opacity;
}

.sk-fly.is-coins {
    border-radius: 50%;
    background: radial-gradient(circle at 35% 30%, #fff3b0 0%, #ffd23f 35%, #e08a00 100%);
    box-shadow: inset 0 -2px 0 rgba(0, 0, 0, 0.2), 0 0 10px rgba(255, 200, 61, 0.7);
}

.sk-fly.is-bytes {
    width: 16px;
    height: 16px;
    margin: -8px 0 0 -8px;
    border-radius: 4px;
    background: linear-gradient(135deg, #c9b8ff 0%, #8f78ff 50%, #5a3dff 100%);
    box-shadow: 0 0 10px rgba(143, 120, 255, 0.85);
    rotate: 45deg;
}

.sk-fly.is-spark {
    width: 6px;
    height: 6px;
    margin: -3px 0 0 -3px;
    border-radius: 50%;
    background: #fff;
    box-shadow: 0 0 8px #fff;
}

/* ---------- Idle motion on hero elements ---------- */

/* Now and then a soft shine runs across the Bytes chip in the top bar */
.app-topbar .sc-bytes-button {
    position: relative;
    overflow: hidden;
    isolation: isolate;
}

.app-topbar .sc-bytes-button::after {
    content: "";
    position: absolute;
    inset: 0;
    z-index: -1;
    background: linear-gradient(105deg, transparent 30%, rgba(214, 200, 255, 0.35) 50%, transparent 70%);
    transform: translateX(-120%);
    animation: sk-chip-shine 9s ease-in-out 4s infinite;
    pointer-events: none;
}

@keyframes sk-chip-shine {
    0%, 86% { transform: translateX(-120%); }
    96%, 100% { transform: translateX(120%); }
}

/* ---------- Capture celebration (the scan result card) ---------- */

/* The card sinks, springs back and settles, as if it's just been tucked into the team */
.skanimals-card.is-captured {
    animation: sk-capture-settle 700ms var(--sc-ease-out);
}

@keyframes sk-capture-settle {
    0% { transform: scale(1); }
    18% { transform: scale(0.94); }
    48% { transform: scale(1.03) translateY(-4px); }
    72% { transform: scale(0.99); }
    100% { transform: none; }
}

.mc-capture-burst {
    position: absolute;
    inset: 0;
    z-index: 4;
    pointer-events: none;
}

/* A bright ring and rays from the creature */
.mc-capture-burst::before,
.mc-capture-burst::after {
    content: "";
    position: absolute;
    top: 55%;
    left: 50%;
    width: 64px;
    height: 64px;
    margin: -32px 0 0 -32px;
    border-radius: 50%;
}

.mc-capture-burst::before {
    border: 3px solid color-mix(in srgb, var(--el, var(--sc-primary)) 70%, white);
    box-shadow: 0 0 24px var(--el, var(--sc-primary));
    animation: sk-capture-ring 700ms var(--sc-ease-out) forwards;
}

.mc-capture-burst::after {
    background: radial-gradient(circle, rgba(255, 255, 255, 0.9), color-mix(in srgb, var(--el, var(--sc-primary)) 60%, transparent) 45%, transparent 70%);
    animation: sk-capture-flash 520ms ease-out forwards;
}

.mc-capture-burst i {
    position: absolute;
    top: 55%;
    left: 50%;
    width: 8px;
    height: 8px;
    margin: -4px 0 0 -4px;
    border-radius: 50%;
    background: color-mix(in srgb, var(--el, var(--sc-primary)) 50%, white);
    box-shadow: 0 0 10px var(--el, var(--sc-primary));
    opacity: 0;
    animation: sk-capture-spark 720ms var(--sc-ease-out) forwards;
}

.mc-capture-burst i:nth-child(1) { --a: 0deg; }
.mc-capture-burst i:nth-child(2) { --a: 45deg; animation-delay: 30ms; }
.mc-capture-burst i:nth-child(3) { --a: 90deg; }
.mc-capture-burst i:nth-child(4) { --a: 135deg; animation-delay: 30ms; }
.mc-capture-burst i:nth-child(5) { --a: 180deg; }
.mc-capture-burst i:nth-child(6) { --a: 225deg; animation-delay: 30ms; }
.mc-capture-burst i:nth-child(7) { --a: 270deg; }
.mc-capture-burst i:nth-child(8) { --a: 315deg; animation-delay: 30ms; }

.mc-captured-stamp {
    position: absolute;
    top: 12px;
    left: 50%;
    z-index: 5;
    display: inline-flex;
    align-items: center;
    gap: 6px;
    padding: 5px 14px;
    border-radius: var(--sc-radius-pill);
    background: var(--sc-gradient-success);
    color: #062014;
    font-family: var(--sc-font-display);
    font-size: 15px;
    font-weight: 700;
    box-shadow: 0 6px 18px rgba(61, 220, 132, 0.45);
    transform: translateX(-50%);
    animation: sk-stamp-in 1.6s var(--sc-ease-spring) forwards;
    pointer-events: none;
}

@keyframes sk-capture-ring {
    0% { opacity: 1; transform: scale(0.4); }
    100% { opacity: 0; transform: scale(4.2); }
}

@keyframes sk-capture-flash {
    0% { opacity: 0; transform: scale(0.5); }
    25% { opacity: 1; }
    100% { opacity: 0; transform: scale(3.4); }
}

@keyframes sk-capture-spark {
    0% { opacity: 1; transform: rotate(var(--a)) translateX(0) scale(1); }
    100% { opacity: 0; transform: rotate(var(--a)) translateX(110px) scale(0.3); }
}

@keyframes sk-stamp-in {
    0% { opacity: 0; transform: translateX(-50%) scale(0.4) rotate(-8deg); }
    18% { opacity: 1; transform: translateX(-50%) scale(1.08) rotate(2deg); }
    28%, 82% { opacity: 1; transform: translateX(-50%) scale(1) rotate(0); }
    100% { opacity: 0; transform: translateX(-50%) translateY(-10px) scale(0.96); }
}

/* ---------- Store and Backpack micro-animations ---------- */

/* Something just bought, equipped or used: a springy pulse and a soft glow in its rarity's colour */
.backpack-item.is-just-done,
.store-card.is-just-bought {
    animation: sk-just-done 700ms var(--sc-ease-spring);
}

@keyframes sk-just-done {
    0% { transform: scale(1); box-shadow: 0 0 0 0 rgba(var(--sc-primary-rgb), 0.7); }
    30% { transform: scale(1.03); box-shadow: 0 0 0 6px rgba(var(--sc-primary-rgb), 0.25); }
    100% { transform: scale(1); box-shadow: 0 0 0 14px rgba(var(--sc-primary-rgb), 0); }
}

.backpack-notice:not(.is-error)::before {
    content: "";
    display: inline-block;
    width: 8px;
    height: 8px;
    margin-right: 8px;
    border-radius: 50%;
    background: var(--sc-success);
    box-shadow: 0 0 8px var(--sc-success);
    vertical-align: 1px;
    animation: sk-dot-pop 420ms var(--sc-ease-spring) 80ms backwards;
}

@keyframes sk-dot-pop {
    from { transform: scale(0); }
}

/* ---------- Install prompt ---------- */

.sk-install {
    position: fixed;
    left: 12px;
    right: 12px;
    /* Clear of the tab bar and the Scan button that rises out of it */
    bottom: calc(var(--sc-tabbar-height) + var(--sc-safe-bottom) + 26px);
    z-index: 1100;
    display: flex;
    align-items: center;
    gap: 12px;
    max-width: 460px;
    margin: 0 auto;
    padding: 10px 10px 10px 12px;
    border: 1px solid rgba(var(--sc-primary-rgb), 0.3);
    border-radius: var(--sc-radius-lg);
    background:
        radial-gradient(120% 140% at 0% 0%, rgba(var(--sc-primary-rgb), 0.16), transparent 60%),
        var(--sc-bg-elevated);
    box-shadow: var(--sc-shadow-lg), 0 0 0 1px rgba(255, 255, 255, 0.03) inset;
    color: var(--sc-text);
    animation: sk-install-in 460ms var(--sc-ease-spring) backwards;
}

.sk-install.is-closing {
    animation: sk-install-out 220ms ease-in forwards;
}

.sk-install-icon {
    flex: none;
    width: 44px;
    height: 44px;
    border-radius: 12px;
    box-shadow: 0 4px 12px rgba(0, 0, 0, 0.35);
}

.sk-install-text {
    display: flex;
    flex: 1;
    flex-direction: column;
    min-width: 0;
    gap: 1px;
    font-size: 13px;
    line-height: 1.35;
    color: var(--sc-text-muted);
}

.sk-install-text strong {
    color: var(--sc-text);
    font-family: var(--sc-font-display);
    font-size: 16px;
    font-weight: 600;
}

.sk-install-text b { color: var(--sc-text); font-weight: 700; }

.sk-install-glyph {
    display: inline-grid;
    place-items: center;
    width: 22px;
    height: 22px;
    margin: 0 1px;
    border-radius: 6px;
    background: rgba(58, 168, 255, 0.16);
    color: var(--sc-azure);
    vertical-align: -6px;
}

.sk-install-actions {
    display: flex;
    flex: none;
    align-items: center;
    gap: 4px;
}

.sk-install-actions .btn-sm {
    min-height: 36px;
    padding: 6px 16px;
    font-size: 15px;
}

.sk-install-close {
    display: grid;
    place-items: center;
    width: 32px;
    height: 32px;
    padding: 0;
    border: 0;
    border-radius: 50%;
    background: transparent;
    color: var(--sc-text-faint);
    font-size: 18px;
    cursor: pointer;
}

.sk-install-close:active { background: rgba(255, 255, 255, 0.06); }

/* Hidden while a sheet covers the bars, like the top bar and tab bar */
body.has-sheet .sk-install { display: none; }

@keyframes sk-install-in {
    from { opacity: 0; transform: translateY(24px) scale(0.96); }
}

@keyframes sk-install-out {
    to { opacity: 0; transform: translateY(16px) scale(0.98); }
}

/* ---------- Reduced motion: nothing moves ---------- */

@media (prefers-reduced-motion: reduce) {
    .tabs-panel-inner.sk-tab-fwd,
    .tabs-panel-inner.sk-tab-back,
    .tabs-segmented .tab-button.active,
    .store-tab.is-active,
    .backpack-tab.is-active,
    .screen-title,
    .screen-subtitle,
    .screen-header-actions,
    .sk-enter,

    .sk-pop-in,
    .store-banner,
    .backpack-notice,
    .backpack-notice::before,
    .store-detail,
    .store-soon,
    .title-sheet-backdrop,
    .title-sheet,
    .title-sheet-backdrop.is-closing,
    .title-sheet-backdrop.is-closing .title-sheet,
    .sk-skel::after,
    .sk-chip-bump,
    .sk-chip-dip,
    .app-topbar .sc-bytes-button::after,
    .skanimals-card.is-captured,
    .backpack-item.is-just-done,
    .store-card.is-just-bought,
    .sk-install,
    .sk-install.is-closing {
        animation: none !important;
    }

    .mc-capture-burst,
    .sk-fly {
        display: none !important;
    }

    /* The stamp still says "Captured!", just without moving */
    .mc-captured-stamp {
        animation: none !important;
    }

    :is(.sk-press, .store-card, .store-pack, .backpack-team-pick, .chal-card, .trophy-tile, .skanimal-sort-btn, .store-tab,
        .backpack-tab, .btn, .button, .app-avatar, .avatar-wrapper, .badge-ring, .badge-mini-ring) {
        transition: none !important;
    }

    :is(.sk-press, .store-card, .store-pack, .backpack-team-pick, .skanimal-sort-btn, .store-tab, .backpack-tab, .btn, .button):active:not(:disabled),
    :is(.store-card, .store-pack, .chal-card, .trophy-tile, .backpack-item, .skanimals-card):hover {
        transform: none !important;
    }
}
