html {
    overflow: hidden;
    /* Transparent canvas so the overlay shows through in a plain iframe / browser
       tab (the dashboard preview), not just in OBS — OBS composites with
       transparency, but a bare iframe paints the UA-default white behind the
       card's transparent areas (wings / corners) without this.
       color-scheme:dark is the piece that actually kills the white: Chromium
       gives a cross-origin iframe a UA-LIGHT (white) base regardless of the
       transparent background, and a parent-side color-scheme is ignored across
       origins — so it must be declared here on the embedded document. OBS stays
       transparent (it composites on alpha; the bg is still transparent). */
    background: transparent;
    color-scheme: dark;
}

* {
    box-sizing: border-box;
    margin: 0;
    padding: 0;
}

body {
    font-family: 'Montserrat', 'Noto Sans Thai', 'Noto Color Emoji', 'Segoe UI Emoji', sans-serif;
    background: transparent;
    margin: 0;
    padding: 0;
    overflow: hidden;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
}

/* SOLO overlay background (from the special_sticker_bg collection) — CLIPPED to
   the card (injected inside .card-wrap), behind the card content. Fills the card
   frame instead of the whole viewport so it doesn't spill past the overlay
   ("รูปเลยกรอบ"). Hidden until a background is picked → overlay stays transparent. */
/* Match .bg-canvas EXACTLY = the card BODY rect (below the name plate), so the
   image fits inside the frame instead of spilling over the whole card-wrap
   ("รูปเลยกรอบ"). `.card-wrap>` needed to beat `.card-wrap>*`'s inset reset. */
.card-wrap>.solo-bg-media {
    position: absolute;
    left: 0.379%;
    top: 17.975%;
    width: 99.242%;
    height: 74.380%;
    border-radius: 2.652%/7.231%;
    object-fit: cover;
    z-index: 0;
    pointer-events: none;
    display: none;
}

/* Preview-only (LITE) click target to open the Background collection picker —
   same card-body rect as the visible bg, BELOW the avatar-frame hitbox
   (z-index 5) so the frame still wins on the avatar. */
.card-wrap>.solo-bg-pick-hitbox {
    position: absolute;
    left: 0.379%;
    top: 17.975%;
    width: 99.242%;
    height: 74.380%;
    z-index: 4;
    cursor: pointer;
    background: transparent;
    border: 0;
    padding: 0;
}

.solo-bg-pick-hitbox:focus-visible {
    outline: 2px solid rgba(103, 232, 249, 0.75);
    outline-offset: -2px;
}

.root {
    position: relative;
    width: 100%;
    display: flex;
    align-items: flex-start;
    justify-content: flex-start;
}

.card-wrap {
    position: relative;
    width: 100%;
    /* Fallback for old Chromium/CEF (e.g. OBS bundled browser) that
       doesn't support `aspect-ratio`. 242/660 = 36.6667% */
    padding-top: 36.6667%;
    aspect-ratio: 660 / 242;
    height: 0;
    overflow: hidden;
}

/* When aspect-ratio is supported, drop the padding hack */
@supports (aspect-ratio: 1 / 1) {
    .card-wrap {
        padding-top: 0;
        height: auto;
    }
}

.card-wrap>* {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

/* Canvas bg sits inside the card border rect.
   Card rect in SVG viewBox (660×242): x=2.5 y=43.5 w=655 h=180 r=17.5
   → as % of card-wrap: left 0.379%, top 17.975%, w 99.242%, h 74.380% */
.card-wrap>.bg-canvas {
    left: 0.379%;
    top: 17.975%;
    width: 99.242%;
    height: 74.380%;
    border-radius: 2.652%/7.231%;
    display: block;
    z-index: 1;
    opacity: 0.4;
}

#shooting-star-container {
    z-index: 3;
}

.card-wrap>svg {
    z-index: 2;
}

.solo-avatar-frame-media {
    position: absolute;
    left: 16.667%;
    top: 44.215%;
    width: 36%;
    /* Card is 660x242. Height % is relative to 242, so this keeps the media box
       roughly square while preserving object-fit: contain for wide wing assets. */
    height: 98.2%;
    transform: translate(-50%, -50%);
    object-fit: contain;
    background: transparent;
    pointer-events: none;
    z-index: 4;
    filter: drop-shadow(0 0 10px rgba(0, 180, 220, 0.25));
}

.solo-avatar-frame-hitbox {
    position: absolute;
    left: 16.667%;
    top: 44.215%;
    width: 36%;
    height: 98.2%;
    transform: translate(-50%, -50%);
    z-index: 5;
    cursor: pointer;
    background: transparent;
    border: 0;
    padding: 0;
}

.solo-avatar-frame-hitbox:focus-visible {
    outline: 2px solid rgba(103, 232, 249, 0.75);
    outline-offset: 2px;
    border-radius: 50%;
}

#shooting-star-container {
    position: absolute;
    inset: 0;
    pointer-events: none;
    overflow: hidden;
    z-index: 3;
    border-radius: 18px;
}

.shooting-star {
    position: absolute;
    height: 3px;
    width: var(--star-w, 80px);
    top: var(--star-y, 0%);
    left: var(--star-x, 0%);
    background: linear-gradient(90deg, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 50%, rgba(255, 255, 255, 0) 100%);
    opacity: 0;
    animation: shootingDiagonal var(--star-dur, 5s) var(--star-d, 0s) linear infinite both;
}

@keyframes shootingDiagonal {
    0% {
        transform: translate(-150px, -150px) rotate(45deg);
        opacity: 0;
    }

    10% {
        opacity: 1;
    }

    100% {
        transform: translate(1200px, 1200px) rotate(45deg);
        opacity: 0;
    }
}

canvas {
    display: block;
    width: 100%;
    height: 100%;
    opacity: 0.9;
}

.card-wrap svg {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
    z-index: 2;
    margin: 0;
    filter: drop-shadow(0 4px 12px rgba(0, 180, 220, 0.12));
}

/* Score text pop animation on update */
@keyframes scoreRoll {
    0% {
        opacity: 0.2;
        transform: translateY(5px);
    }

    100% {
        opacity: 1;
        transform: translateY(0);
    }
}

.score-pop {
    animation: scoreRoll 0.22s ease-out forwards;
}

/* Progress bar fill smooth transition */
#prog-fill,
#fill-clip-rect {
    transition: width 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* Glitch effect when timer hits 0 */
@keyframes zeroGlitch {
    0% {
        transform: translate(0, 0);
        filter: none;
        opacity: 1;
    }

    3% {
        transform: translate(-4px, 1px);
        filter: drop-shadow(3px 0 #ff003c) drop-shadow(-3px 0 #00fff9);
        opacity: 1;
    }

    6% {
        transform: translate(4px, -1px);
        filter: drop-shadow(-3px 0 #ff003c) drop-shadow(3px 0 #00fff9);
        opacity: 0.85;
    }

    9% {
        transform: translate(0, 0);
        filter: none;
        opacity: 1;
    }

    25% {
        transform: translate(0, 0);
        filter: none;
        opacity: 1;
    }

    26% {
        transform: translate(3px, 0);
        filter: drop-shadow(-4px 0 #ff00ea);
        opacity: 1;
    }

    27% {
        transform: translate(-3px, 1px);
        filter: drop-shadow(4px 0 #00fff9);
        opacity: 0.7;
    }

    28% {
        transform: translate(0, 0);
        filter: none;
        opacity: 1;
    }

    55% {
        transform: translate(0, 0);
        filter: none;
        opacity: 1;
    }

    56% {
        transform: translate(-6px, -2px);
        filter: drop-shadow(6px 0 #ff003c) drop-shadow(-6px 0 #00fff9);
        opacity: 1;
    }

    57% {
        transform: translate(6px, 2px);
        filter: drop-shadow(-5px 0 #ff00ea);
        opacity: 0.5;
    }

    58% {
        transform: translate(-2px, 0);
        filter: none;
        opacity: 1;
    }

    59% {
        transform: translate(0, 0);
        filter: none;
        opacity: 1;
    }

    80% {
        transform: translate(0, 0);
        filter: none;
        opacity: 1;
    }

    81% {
        transform: translate(2px, 1px);
        filter: drop-shadow(-3px 0 #ff003c);
        opacity: 0.9;
    }

    82% {
        transform: translate(-2px, 0);
        filter: drop-shadow(3px 0 #00fff9);
        opacity: 1;
    }

    83% {
        transform: translate(0, 0);
        filter: none;
        opacity: 1;
    }

    100% {
        transform: translate(0, 0);
        filter: none;
        opacity: 1;
    }
}

.zero-glitch {
    transform-box: fill-box;
    transform-origin: center;
    animation: zeroGlitch 1.5s steps(1, end) infinite;
}

/* Timer urgency pulse */
.timer-urgent {
    animation: timerPulse 0.5s ease-in-out infinite alternate;
}

@keyframes timerPulse {
    0% {
        fill: #ff4444;
        opacity: 1;
    }

    100% {
        fill: #ff8888;
        opacity: 0.85;
    }
}

/* Card glow pulse when active */
.card-wrap svg.active {
    animation: cardGlow 2.5s ease-in-out infinite;
}

@keyframes cardGlow {

    0%,
    100% {
        filter: drop-shadow(0 2px 8px rgba(0, 180, 220, 0.35)) drop-shadow(0 0 1px rgba(80, 215, 255, 0.2));
    }

    50% {
        filter: drop-shadow(0 2px 16px rgba(0, 215, 255, 0.55)) drop-shadow(0 0 2px rgba(120, 245, 255, 0.35));
    }
}

/* Sparkle 4-pointed stars */
@keyframes sparkleAnim {

    0%,
    100% {
        opacity: 0;
        transform: scale(0.2) rotate(0deg);
    }

    35% {
        opacity: 1;
        transform: scale(1.3) rotate(18deg);
    }

    55% {
        opacity: 0.7;
        transform: scale(1.0) rotate(0deg);
    }

    80% {
        opacity: 0.2;
        transform: scale(0.6) rotate(-8deg);
    }
}

.sv-star {
    animation: sparkleAnim ease-in-out infinite;
    transform-box: fill-box;
    transform-origin: center;
}

/* Shimmer sweep across card face */
@keyframes shimmerSweep {
    0% {
        transform: translateX(-260px);
    }

    100% {
        transform: translateX(650px);
    }
}

#shimmer-overlay {
    animation: shimmerSweep 3.5s linear infinite;
    animation-delay: -0.8s;
}

/* Clock wobble during setup (PENDING) */
@keyframes clockWobble {

    0%,
    100% {
        transform: rotate(0deg) scale(1);
    }

    18% {
        transform: rotate(-18deg) scale(1.06);
    }

    36% {
        transform: rotate(18deg) scale(1.06);
    }

    54% {
        transform: rotate(-12deg) scale(1);
    }

    72% {
        transform: rotate(10deg) scale(1);
    }

    88% {
        transform: rotate(-4deg) scale(1);
    }
}

.clock-wobble {
    animation: clockWobble 0.65s ease-in-out infinite;
    transform-box: fill-box;
    transform-origin: center;
}

/* Marching border light */
@keyframes borderDash {
    to {
        stroke-dashoffset: -1680;
    }
}

@keyframes borderDashReverse {
    to {
        stroke-dashoffset: 1680;
    }
}

#border-shimmer {
    animation: borderDash 8s linear infinite;
}

#border-shimmer-2 {
    animation: borderDashReverse 6s linear infinite;
}

/* Power bar charge sweep (Lv2+) */
@keyframes barCharge {
    0% {
        transform: translateX(-110px);
    }

    100% {
        transform: translateX(660px);
    }
}

#bar-charge-a,
#bar-charge-b {
    animation: barCharge linear infinite;
}

/* ══════════════════════════════════════════
   Premium Fill Bar Effects
   ══════════════════════════════════════════ */

/* Bar outer glow pulse */
@keyframes barGlowPulse {

    0%,
    100% {
        opacity: 0.35;
    }

    50% {
        opacity: 0.65;
    }
}

#bar-outer-glow {
    animation: barGlowPulse 2.5s ease-in-out infinite;
    transition: width 0.55s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* Bar shimmer sweep */
@keyframes barShimmerSweep {
    0% {
        transform: translateX(-160px);
        opacity: 0;
    }

    5% {
        opacity: 1;
    }

    85% {
        opacity: 1;
    }

    100% {
        transform: translateX(700px);
        opacity: 0;
    }
}

#bar-shimmer {
    animation: barShimmerSweep 3s ease-in-out infinite;
    animation-delay: -1s;
}

/* Leading edge glow pulse */
@keyframes barEdgePulse {

    0%,
    100% {
        opacity: 0.5;
        transform: scaleX(0.8) scaleY(0.9);
    }

    50% {
        opacity: 1;
        transform: scaleX(1.4) scaleY(1.15);
    }
}

#bar-edge-glow {
    animation: barEdgePulse 1.2s ease-in-out infinite;
    transform-box: fill-box;
    transform-origin: center;
}

/* Edge sparkle stars — staggered */
@keyframes barSparkle1 {

    0%,
    100% {
        opacity: 0;
        transform: translate(0, 0) scale(0.3) rotate(0deg);
    }

    15% {
        opacity: 1;
        transform: translate(-12px, -18px) scale(1.2) rotate(25deg);
    }

    50% {
        opacity: 0.5;
        transform: translate(-20px, -28px) scale(0.7) rotate(45deg);
    }

    80% {
        opacity: 0;
        transform: translate(-26px, -34px) scale(0.2) rotate(60deg);
    }
}

@keyframes barSparkle2 {

    0%,
    100% {
        opacity: 0;
        transform: translate(0, 0) scale(0.3) rotate(0deg);
    }

    20% {
        opacity: 0.9;
        transform: translate(6px, -20px) scale(1.0) rotate(-20deg);
    }

    55% {
        opacity: 0.4;
        transform: translate(10px, -32px) scale(0.5) rotate(-40deg);
    }

    85% {
        opacity: 0;
        transform: translate(14px, -38px) scale(0.2) rotate(-55deg);
    }
}

@keyframes barSparkle3 {

    0%,
    100% {
        opacity: 0;
        transform: translate(0, 0) scale(0.3) rotate(0deg);
    }

    10% {
        opacity: 0.8;
        transform: translate(-4px, 14px) scale(1.1) rotate(15deg);
    }

    45% {
        opacity: 0.3;
        transform: translate(-8px, 22px) scale(0.6) rotate(30deg);
    }

    75% {
        opacity: 0;
        transform: translate(-12px, 28px) scale(0.2) rotate(45deg);
    }
}

.bar-sparkle {
    transform-box: fill-box;
    transform-origin: center;
}

.bar-sparkle-1 {
    animation: barSparkle1 1.8s ease-out infinite;
    animation-delay: 0s;
}

.bar-sparkle-2 {
    animation: barSparkle2 2.1s ease-out infinite;
    animation-delay: 0.4s;
}

.bar-sparkle-3 {
    animation: barSparkle3 1.6s ease-out infinite;
    animation-delay: 0.8s;
}

/* Edge group transition */
#bar-edge-group {
    transition: opacity 0.4s ease;
}

/* ══════════════════════════════════════════
   Premium Countdown — last 10 seconds
   ══════════════════════════════════════════ */

/* Elegant digit reveal: drops in from above with elastic settle */
@keyframes digitReveal {
    0% {
        transform: scale(2.8) translateY(-10px);
        opacity: 0;
    }

    38% {
        transform: scale(0.90) translateY(3px);
        opacity: 1;
    }

    62% {
        transform: scale(1.08);
    }

    80% {
        transform: scale(0.97);
    }

    100% {
        transform: scale(1) translateY(0);
        opacity: 1;
    }
}

.countdown-pop {
    animation: digitReveal 0.52s cubic-bezier(0.34, 1.56, 0.64, 1) both;
    transform-box: fill-box;
    transform-origin: center;
}

/* Triple concentric rings — staggered timing */
@keyframes ring1Expand {
    0% {
        r: 24;
        opacity: 1;
        stroke-width: 5;
    }

    100% {
        r: 72;
        opacity: 0;
        stroke-width: 0.5;
    }
}

@keyframes ring2Expand {
    0% {
        r: 18;
        opacity: 0.7;
        stroke-width: 3;
    }

    100% {
        r: 94;
        opacity: 0;
        stroke-width: 0.5;
    }
}

@keyframes ring3Expand {
    0% {
        r: 12;
        opacity: 0.4;
        stroke-width: 1.5;
    }

    100% {
        r: 115;
        opacity: 0;
        stroke-width: 0.5;
    }
}

.ring-1 {
    animation: ring1Expand 0.50s ease-out forwards;
}

.ring-2 {
    animation: ring2Expand 0.70s ease-out forwards;
}

.ring-3 {
    animation: ring3Expand 0.90s ease-out forwards;
}

/* Flash overlay — luxury subtle */
@keyframes luxFlash {
    0% {
        opacity: 0.20;
    }

    25% {
        opacity: 0.12;
    }

    100% {
        opacity: 0;
    }
}

.countdown-flash {
    animation: luxFlash 0.55s ease-out forwards;
}

/* ── Phase glows ── */
@keyframes glowCold {

    0%,
    100% {
        filter: drop-shadow(0 0 1px rgba(100, 210, 255, .08));
    }
}

@keyframes glowWarm {

    0%,
    100% {
        filter: drop-shadow(0 0 1px rgba(255, 205, 0, .08));
    }
}

@keyframes glowHot {

    0%,
    100% {
        filter: drop-shadow(0 0 1px rgba(255, 70, 0, .08));
    }
}

@keyframes glowFinal {

    0%,
    100% {
        filter: drop-shadow(0 0 1px rgba(255, 255, 255, .08));
    }
}

.cd-cold {
    animation: glowCold 0.75s ease-in-out infinite !important;
}

.cd-warm {
    animation: glowWarm 0.62s ease-in-out infinite !important;
}

.cd-hot {
    animation: glowHot 0.50s ease-in-out infinite !important;
}

.cd-final {
    animation: glowFinal 0.35s ease-in-out infinite !important;
}

/* Elite shake — refined, not crude */
@keyframes eliteShake {

    0%,
    100% {
        transform: translate(0, 0) rotate(0deg);
    }

    18% {
        transform: translate(-4px, 1px) rotate(-0.3deg);
    }

    36% {
        transform: translate(4px, -1px) rotate(0.3deg);
    }

    54% {
        transform: translate(-3px, 1px) rotate(-0.2deg);
    }

    72% {
        transform: translate(2px, -1px) rotate(0.1deg);
    }

    88% {
        transform: translate(-1px, 0) rotate(0deg);
    }
}

.countdown-shake {
    animation: eliteShake 0.40s cubic-bezier(0.36, .07, .19, .97) both;
}

/* ══════════════════════════════════════════
   Lite mode (?lite=1, in-app operator preview)
   Drop ambient/decorative animations to cut continuous GPU compositing inside
   the desktop webview. Functional timer/score/bar-fill display is untouched.
   ══════════════════════════════════════════ */
body.lite #shimmer-overlay,
body.lite .sv-star,
body.lite #border-shimmer,
body.lite #border-shimmer-2,
body.lite #bar-charge-a,
body.lite #bar-charge-b,
body.lite #bar-shimmer,
body.lite #bar-outer-glow,
body.lite #bar-edge-glow,
body.lite .bar-sparkle {
    display: none !important;
}

body.lite .card-wrap svg.active {
    animation: none !important;
    filter: none !important;
}

body.lite .clock-wobble {
    animation: none !important;
}

/* ═══════════════════════════════════════════════════════════════════════════
   OVERLAY STYLES (manual, app-selectable) — applied as body.theme-* classes.
   theme-classic = no overrides → identical to the original look. neon/minimal
   are placeholder hooks for UX/UI to design later. This layer is independent of
   the level-based ?theme=1|2|3 colour system in script.js.
   ═══════════════════════════════════════════════════════════════════════════ */
body.theme-neon {
    /* UX TODO: neon style overrides */
}
body.theme-minimal {
    /* UX TODO: minimal style overrides */
}
