/* Native CSS backgrounds for seasonal finds. Content stays above the layer;
   background clicks are checked by js/seasonal-background.js, not intercepted. */
body.seasonal-background { isolation: isolate; }

.sg-season-background {
    position: fixed;
    inset: 0;
    z-index: -1;
    overflow: hidden;
    pointer-events: none;
}

.seasonal-particle { position: absolute; }

.seasonal-catch {
    display: grid;
    place-items: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    background: transparent;
    pointer-events: none;
}

.seasonal-catch:focus-visible {
    outline: 1px dashed var(--season-color, #bddaff);
    outline-offset: -4px;
}

/* Focus makes the target visible and stationary, including between flights. */
.sg-season-background:focus-within { z-index: 31; }
.seasonal-particle:focus-within {
    top: 18vh;
    opacity: 1;
    animation: none;
}
.seasonal-particle:focus-within .sakura-drift,
.seasonal-particle:focus-within .sakura-petal,
.seasonal-particle:focus-within .sakura-petal svg { animation: none; }

.sg-season-background.paused .seasonal-particle,
.sg-season-background.paused .sakura-drift,
.sg-season-background.paused .sakura-petal,
.sg-season-background.paused .sakura-petal svg,
.sg-season-background.paused .perseid-star { animation-play-state: paused; }

/* The petal glides downwind (--season-lean), sways in gusts (--season-sway),
   shivers a little (--season-flutter) and turns over in the air (--season-turn).
   Each motion keeps its own time, so they never line up into one pendulum. */
.sakura-fall {
    top: -50px;
    animation: sakura-fall var(--season-duration) var(--season-delay) linear infinite;
}
.sakura-drift {
    animation: sakura-drift var(--season-sway) var(--season-delay) ease-in-out infinite;
}
/* the small, faster shiver of air catching the petal */
.sakura-petal {
    animation: sakura-flutter var(--season-flutter) var(--season-flutter-delay) ease-in-out infinite;
}
.sakura-petal svg {
    width: var(--season-size);
    height: calc(var(--season-size) * 1.18);
    fill: var(--season-color);
    opacity: var(--season-opacity);
    transform: rotate(-32deg);
    animation: sakura-turn var(--season-turn) var(--season-turn-delay) ease-in-out infinite;
    transition: opacity 0.2s;
}
.sakura-petal.catching svg,
.sakura-petal:focus-visible svg { opacity: 1; }

.perseid-star {
    position: absolute;
    width: var(--season-size);
    height: var(--season-size);
    border-radius: 50%;
    background: #dbe9ff;
    box-shadow: 0 0 5px rgba(151, 192, 255, 0.45);
    animation: perseid-twinkle var(--season-duration) var(--season-delay) ease-in-out infinite alternate;
}
.perseid-flight {
    top: 0;
    animation: perseid-flight var(--season-duration) var(--season-delay) linear infinite;
}
.perseid-comet { position: relative; }
/* The trail points up the flight's own axis: the rotation in the keyframes
   turns the whole comet to its heading, so the tail always trails straight
   behind the head however the meteor leans. */
.perseid-comet::before {
    content: "";
    position: absolute;
    left: 50%;
    bottom: 50%;
    width: 2px;
    height: var(--season-tail, 130px);
    border-radius: 50%;
    background: linear-gradient(0deg, #8bbcf3, rgba(139, 188, 243, 0));
    transform: translateX(-50%);
    opacity: var(--season-bright, 0.8);
}
.perseid-comet::after {
    content: "";
    width: var(--season-head, 5px);
    height: var(--season-head, 5px);
    border-radius: 50%;
    background: #eff8ff;
    box-shadow: 0 0 8px #b8d9ff, 0 0 18px rgba(139, 188, 243, 0.65);
}
.perseid-comet.catching::after { box-shadow: 0 0 18px #eff8ff; }
.perseid-comet.catching::before { opacity: 1; }

/* Small wandering insects pulse independently; they have neither meteor
   trails nor the straight falling paths of petals. */
.firefly-wander {
    top: var(--season-rest-top);
    animation: firefly-wander var(--season-duration) var(--season-delay) ease-in-out infinite;
}
.firefly-body {
    position: relative;
    width: var(--season-size);
    height: calc(var(--season-size) * 1.65);
    color: var(--season-color);
    transform: rotate(-20deg);
}
.firefly-wings {
    position: absolute;
    top: 0;
    left: -40%;
    width: 180%;
    height: 65%;
    border-radius: 70% 70% 40% 40%;
    background: currentColor;
    opacity: 0.24;
    transform: rotate(15deg);
}
.firefly-light {
    position: absolute;
    inset: 35% 0 0;
    border-radius: 45% 45% 65% 65%;
    background: currentColor;
    box-shadow: 0 0 7px currentColor, 0 0 17px color-mix(in srgb, currentColor 55%, transparent);
    animation: firefly-pulse var(--season-pulse) var(--season-pulse-delay) ease-in-out infinite;
}
.firefly-catch.catching .firefly-light,
.firefly-catch:focus-visible .firefly-light { animation: none; opacity: 1; }
.sg-season-background.paused .firefly-light { animation-play-state: paused; }
@keyframes firefly-wander {
    0%, 100% { transform: translate(0, 0) rotate(-8deg); }
    19% { transform: translate(var(--season-wind), calc(var(--season-rise) * -0.45)) rotate(14deg); }
    43% { transform: translate(calc(var(--season-wind) * 0.3), calc(var(--season-rise) * -1)) rotate(-18deg); }
    68% { transform: translate(calc(var(--season-wind) * -0.6), calc(var(--season-rise) * -0.3)) rotate(9deg); }
    86% { transform: translate(calc(var(--season-wind) * -0.2), calc(var(--season-rise) * 0.4)) rotate(-4deg); }
}
@keyframes firefly-pulse {
    0%, 100% { opacity: 0.35; transform: scale(0.85); }
    38% { opacity: 0.65; transform: scale(1); }
    57% { opacity: 1; transform: scale(1.12); }
    74% { opacity: 0.5; transform: scale(0.95); }
}

@keyframes sakura-fall {
    0% {
        transform: translate(var(--season-lean, 0px), 0);
        animation-timing-function: cubic-bezier(0.55, 0.28, 0.75, 0.65);
    }
    45% {
        transform: translate(calc(var(--season-lean, 0px) * 0.45), 50vh);
        animation-timing-function: cubic-bezier(0.35, 0.5, 0.85, 0.9);
    }
    100% { transform: translate(var(--season-lean, 0px), calc(100vh + 100px)); }
}
@keyframes sakura-drift {
    0%, 100% { transform: translateX(calc(var(--season-sway-amp, 24px) * -0.5)); }
    18% { transform: translateX(calc(var(--season-sway-amp, 24px) * 0.45)); }
    43% { transform: translateX(calc(var(--season-sway-amp, 24px) * 0.95)); }
    62% { transform: translateX(calc(var(--season-sway-amp, 24px) * 0.3)); }
    83% { transform: translateX(calc(var(--season-sway-amp, 24px) * -1)); }
}
@keyframes sakura-flutter {
    0%, 100% { transform: translateX(calc(var(--season-flutter-amp, 5px) * -1)); }
    50% { transform: translateX(var(--season-flutter-amp, 5px)); }
}
@keyframes sakura-turn {
    0%, 100% { transform: rotate(-27deg) scaleX(1); }
    21% { transform: rotate(-2deg) scaleX(0.5); }
    46% { transform: rotate(30deg) scaleX(1); }
    71% { transform: rotate(4deg) scaleX(0.5); }
}
@keyframes perseid-twinkle {
    from { opacity: 0.15; }
    to { opacity: 0.75; }
}
/* A meteor leaves the radiant leaning down-right (--season-angle), crosses on
   its own time (--season-duration) and shows its own trail and brightness; the
   transform spans the whole cycle so the streak keeps a steady speed. */
@keyframes perseid-flight {
    0% {
        opacity: 0;
        transform: rotate(var(--season-angle, 0deg)) translateY(var(--season-from, -40vh));
    }
    24% { opacity: 0; }
    31% { opacity: var(--season-bright, 0.8); }
    97% { opacity: var(--season-bright, 0.8); }
    100% {
        opacity: 0;
        transform: rotate(var(--season-angle, 0deg)) translateY(var(--season-to, 140vh));
    }
}

/* Tomie: a thin drop lands, then opens into an uneven pool of ink. Each
   spill has its own position and cycle; only opacity and transforms move. */
.ink-spill {
    position: absolute;
    width: var(--season-size);
    height: calc(var(--season-size) * 0.6);
    transform: translateX(-50%) rotate(var(--season-angle));
}
.ink-spill::before,
.ink-spill::after { content: ""; position: absolute; }
.ink-spill::before {
    left: 48%;
    bottom: 65%;
    width: 4px;
    height: 15px;
    border-radius: 70% 35% 60% 40%;
    background: #030304;
    box-shadow: 1px 0 rgba(143, 143, 154, 0.12);
    animation: ink-drip var(--season-duration) var(--season-delay) linear infinite;
}
.ink-spill::after {
    inset: 0;
    border-radius: 41% 59% 63% 37% / 57% 39% 61% 43%;
    background: radial-gradient(ellipse at 38% 35%, #020203 20%, #050506 68%, transparent 73%);
    box-shadow: -9px 6px 0 -5px #030304, 12px -4px 0 -6px #040405;
    animation: ink-spread var(--season-duration) var(--season-delay) ease-out infinite;
}
@keyframes ink-drip {
    0%, 5% { opacity: 0; transform: translateY(-140px) scaleY(1.4); }
    12% { opacity: 0.7; }
    25% { opacity: 0.7; transform: translateY(-5px) scaleY(1); }
    28%, 100% { opacity: 0; transform: translateY(0) scaleY(0.2); }
}
@keyframes ink-spread {
    0%, 25% { opacity: 0; transform: scale(0.04, 0.1); }
    36% { opacity: 0.8; transform: scale(0.45, 0.65); }
    70% { opacity: 0.7; transform: scale(1); }
    100% { opacity: 0; transform: scale(1.2, 1.05); }
}

/* Lain: dim scan lines and paths through the Wired, with occasional narrow
   bands of interference. The page's text and controls never glitch with them. */
.sg-wired::before,
.sg-wired::after { content: ""; position: absolute; inset: 0; }
.sg-wired::before {
    background-image:
        repeating-linear-gradient(0deg, transparent 0 3px, rgba(var(--accent-rgb), 0.055) 3px 4px),
        repeating-linear-gradient(93deg, transparent 0 37px, rgba(var(--accent-rgb), 0.025) 38px 39px, transparent 40px 83px);
}
.sg-wired::after {
    bottom: auto;
    height: 34px;
    background: repeating-linear-gradient(0deg, transparent 0 2px, rgba(var(--accent-rgb), 0.2) 2px 3px, transparent 3px 7px);
    animation: wired-interference 19s steps(1) infinite;
}
.wired-line {
    position: absolute;
    width: var(--season-size);
    height: 1px;
    background: linear-gradient(90deg, transparent, rgba(var(--accent-light-rgb), 0.4), transparent);
    animation: wired-signal var(--season-duration) var(--season-delay) steps(1) infinite;
}
.wired-line::after {
    content: "";
    position: absolute;
    left: 62%;
    width: 1px;
    height: var(--season-branch);
    background: linear-gradient(rgba(var(--accent-light-rgb), 0.25), transparent);
}
@keyframes wired-signal {
    0%, 62% { opacity: 0; transform: translateX(0); }
    65% { opacity: 0.5; transform: translateX(-8px); }
    71% { opacity: 0.75; transform: translateX(12px); }
    74% { opacity: 0.3; transform: translateX(4px); }
    83%, 100% { opacity: 0; transform: translateX(0); }
}
@keyframes wired-interference {
    0%, 90% { opacity: 0; transform: translateY(18vh); }
    92% { opacity: 0.3; transform: translate(8px, 18vh); }
    94% { opacity: 0.2; transform: translate(-6px, 67vh); }
    96%, 100% { opacity: 0; transform: translateY(67vh); }
}
/* Raiden Shogun: a violet storm. Darkened clouds at the top, faint rain and
   long bolts of different strengths: a bright core in a soft glow, branches
   thinner. A strike flickers twice and lights the sky around it; rare and
   dim, never a strobe. */
.sg-lightning { overflow: hidden; }
.sg-lightning::before {
    content: "";
    position: absolute;
    inset: 0;
    background: linear-gradient(color-mix(in srgb, var(--bg-dark) 55%, transparent), transparent 42%);
}
.sg-lightning::after {
    content: "";
    position: absolute;
    top: -120px;
    left: -10%;
    width: 120%;
    height: calc(100% + 240px);
    background-image:
        radial-gradient(0.6px 11px at 30% 20%, rgba(var(--accent-light-rgb), 0.28), transparent),
        radial-gradient(0.6px 9px at 70% 60%, rgba(var(--accent-light-rgb), 0.22), transparent),
        radial-gradient(0.5px 13px at 45% 85%, rgba(var(--accent-light-rgb), 0.18), transparent);
    background-size: 53px 120px, 71px 120px, 89px 120px;
    background-position: 0 0, 17px 40px, 41px 85px;
    animation: lightning-rain 0.45s linear infinite;
}
@keyframes lightning-rain {
    from { transform: rotate(9deg) translateY(0); }
    to { transform: rotate(9deg) translateY(120px); }
}
.lightning-bolt {
    position: absolute;
    width: calc(var(--season-length) * 0.32);
    height: var(--season-length);
    opacity: 0;
    animation: lightning-strike var(--season-duration) var(--season-delay) linear infinite;
}
/* the sky lit around the strike */
.lightning-bolt::before {
    content: "";
    position: absolute;
    left: -80%;
    right: -80%;
    top: -12%;
    height: 75%;
    background: radial-gradient(ellipse at 50% 25%, rgba(var(--accent-rgb), 0.2), transparent 70%);
}
.lightning-bolt svg {
    position: relative;
    display: block;
    width: 100%;
    height: 100%;
    overflow: visible;
    fill: none;
    stroke-linecap: round;
    stroke-linejoin: round;
    filter: drop-shadow(0 0 3px rgba(var(--accent-rgb), 0.9)) drop-shadow(0 0 14px rgba(var(--accent-rgb), 0.5));
}
.lightning-bolt path { vector-effect: non-scaling-stroke; }
.lightning-glow { stroke: rgba(var(--accent-rgb), 0.35); stroke-width: calc(var(--season-width) * 3.5); }
.lightning-core { stroke: color-mix(in srgb, rgb(var(--accent-light-rgb)) 55%, #fff); stroke-width: var(--season-width); }
.lightning-branch { stroke: rgba(var(--accent-light-rgb), 0.75); stroke-width: max(0.7px, calc(var(--season-width) * 0.5)); }
.lightning-twig { stroke-width: 0.7px; opacity: 0.7; }
@keyframes lightning-strike {
    0%, 85% { opacity: 0; }
    85.5% { opacity: 0.9; }
    86.3% { opacity: 0.15; }
    87.1% { opacity: 0.7; }
    90%, 100% { opacity: 0; }
}
.sg-season-background.paused .lightning-bolt,
.sg-season-background.paused.sg-lightning::after { animation-play-state: paused; }

.sg-season-background.paused .ink-spill::before,
.sg-season-background.paused .ink-spill::after,
.sg-season-background.paused .wired-line,
.sg-season-background.paused.sg-wired::after { animation-play-state: paused; }

/* Echidna: green butterflies turn their wings while following separate
   wandering paths. The palette keeps them visible against her light skin. */
.witch-butterfly {
    position: absolute;
    width: var(--season-size);
    color: var(--accent-dark);
    animation: butterfly-flight var(--season-duration) var(--season-delay) ease-in-out infinite;
}
.witch-butterfly svg {
    display: block;
    width: 100%;
    height: auto;
    fill: var(--accent);
    filter: drop-shadow(0 0 3px rgba(var(--accent-rgb), 0.2));
}
.butterfly-wing {
    transform-box: view-box;
    transform-origin: 50% 53%;
    animation: butterfly-flutter var(--season-flutter) var(--season-delay) ease-in-out infinite;
}
.butterfly-body { fill: none; stroke: currentColor; stroke-width: 1.1; stroke-linecap: round; }
@keyframes butterfly-flight {
    0%, 100% { opacity: 0.45; transform: translate(0, 12px) rotate(-12deg); }
    23% { opacity: 0.7; transform: translate(calc(var(--season-wind) * 0.7), -24px) rotate(16deg); }
    51% { opacity: 0.6; transform: translate(var(--season-wind), -65px) rotate(-8deg); }
    77% { opacity: 0.5; transform: translate(calc(var(--season-wind) * -0.4), -16px) rotate(10deg); }
}
@keyframes butterfly-flutter {
    0%, 100% { transform: scaleX(1); }
    50% { transform: scaleX(0.18); }
}

/* Marisa: drifting gold dust and occasional little stars, each with a short
   trail pointing back along its own flight rather than across the text. */
.magic-dust,
.magic-star { position: absolute; width: var(--season-size); height: var(--season-size); }
.magic-dust {
    border-radius: 50%;
    background: var(--accent-light);
    box-shadow: 0 0 5px rgba(var(--accent-rgb), 0.45);
    animation: magic-drift var(--season-duration) var(--season-delay) ease-in-out infinite;
}
.magic-star {
    color: var(--accent);
    font: var(--season-size)/1 "Sanakan Mono", monospace;
    font-style: normal;
    text-shadow: 0 0 6px rgba(var(--accent-rgb), 0.5);
    animation: magic-flight var(--season-duration) var(--season-delay) linear infinite;
}
.magic-star::before {
    content: "";
    position: absolute;
    right: calc(100% - 2px);
    top: 50%;
    width: var(--season-tail);
    height: 1px;
    background: linear-gradient(90deg, transparent, currentColor);
    opacity: 0.4;
}
@keyframes magic-drift {
    0% { opacity: 0; transform: translate(-12px, 25px); }
    24% { opacity: 0.35; }
    63% { opacity: 0.6; }
    100% { opacity: 0; transform: translate(30px, -60px); }
}
@keyframes magic-flight {
    0%, 55% { opacity: 0; transform: rotate(var(--season-angle)) translateX(-45px); }
    66% { opacity: 0.7; }
    88% { opacity: 0.5; }
    100% { opacity: 0; transform: rotate(var(--season-angle)) translateX(85px); }
}
.sg-season-background.paused .witch-butterfly,
.sg-season-background.paused .butterfly-wing,
.sg-season-background.paused .magic-dust,
.sg-season-background.paused .magic-star { animation-play-state: paused; }

/* Reisen: softly glowing lavender motes drifting through the night. */
.lavender-mote {
    position: absolute;
    width: var(--season-size);
    height: var(--season-size);
    border-radius: 50%;
    background: var(--accent-light);
    box-shadow: 0 0 7px rgba(var(--accent-rgb), 0.5);
    animation: lavender-drift var(--season-duration) var(--season-delay) ease-in-out infinite;
}
@keyframes lavender-drift {
    0% { opacity: 0; transform: translate(-10px, 20px); }
    28% { opacity: 0.55; }
    72% { opacity: 0.35; }
    100% { opacity: 0; transform: translate(var(--season-wind), -60px); }
}

/* Hoshino Ai: an idol's stage. Cones of stage light sweep from the top, one
   colour in two, and star sparkles twinkle, a few six-pointed like her eyes. */
/* a cone of light from its top centre: soft edges from the conic stops,
   fading downwards through the mask */
.idol-beam {
    --beam: var(--accent-rgb);
    position: absolute;
    top: -8vh;
    width: 110vh;
    height: 125vh;
    margin-left: -55vh;
    background: conic-gradient(from calc(180deg - var(--season-spread)) at 50% 0,
        rgba(var(--beam), 0) 0deg,
        rgba(var(--beam), 0.24) calc(var(--season-spread) * 0.6),
        rgba(var(--beam), 0.24) calc(var(--season-spread) * 1.4),
        rgba(var(--beam), 0) calc(var(--season-spread) * 2),
        rgba(var(--beam), 0) 360deg);
    -webkit-mask-image: linear-gradient(#000, rgba(0, 0, 0, 0.35) 55%, transparent 92%);
    mask-image: linear-gradient(#000, rgba(0, 0, 0, 0.35) 55%, transparent 92%);
    transform-origin: 50% 0;
    transform: rotate(var(--season-tilt));
    mix-blend-mode: screen;
    animation: idol-sweep var(--season-duration) var(--season-delay) ease-in-out infinite;
}
.idol-beam-light { --beam: var(--accent-light-rgb); }
.idol-star {
    position: absolute;
    width: var(--season-size);
    height: var(--season-size);
    color: var(--accent-light);
    opacity: 0;
    animation: idol-twinkle var(--season-duration) var(--season-delay) ease-in-out infinite;
}
.idol-star svg {
    display: block;
    width: 100%;
    height: 100%;
    fill: currentColor;
    filter: drop-shadow(0 0 4px rgba(var(--accent-rgb), 0.9));
}
.idol-star-eye { color: #fff; }
/* light bases: screen blending would wash the beams out */
:root:where([data-skin="echidna"], [data-skin="custom"][data-skin-base="light"]) .idol-beam { mix-blend-mode: normal; }
:root:where([data-skin="echidna"], [data-skin="custom"][data-skin-base="light"]) .idol-star-eye { color: var(--accent); }
@keyframes idol-sweep {
    0%, 100% { opacity: 0.55; transform: rotate(calc(var(--season-tilt) - var(--season-swing))); }
    50% { opacity: 0.9; transform: rotate(calc(var(--season-tilt) + var(--season-swing))); }
}
@keyframes idol-twinkle {
    0%, 100% { opacity: 0; transform: scale(0.3) rotate(0deg); }
    45% { opacity: 0.85; transform: scale(1) rotate(25deg); }
    60% { opacity: 0.5; transform: scale(0.8) rotate(35deg); }
}
.sg-season-background.paused .idol-beam,
.sg-season-background.paused .idol-star { animation-play-state: paused; }

/* Pekora: little rabbits cross the lower edge in both directions. Their hop
   stretches on takeoff, arcs through the air and squashes on landing. */
.rabbit-run {
    position: absolute;
    left: -70px;
    width: var(--season-size);
    opacity: 0.55;
    animation: rabbit-cross var(--season-duration) var(--season-delay) linear infinite;
    animation-direction: var(--season-route);
}
.rabbit-facing { display: block; transform: scaleX(var(--season-direction)); }
.rabbit-run svg {
    display: block;
    width: 100%;
    height: auto;
    transform-origin: 50% 92%;
    animation: rabbit-hop var(--season-hop) var(--season-delay) linear infinite;
}
.rabbit-coat { fill: var(--accent-light); }
.rabbit-ear { fill: none; stroke: var(--accent); stroke-width: 2; stroke-linecap: round; }
.rabbit-eye { fill: var(--accent-dark); }
@keyframes rabbit-cross {
    to { transform: translateX(calc(100vw + 140px)); }
}
@keyframes rabbit-hop {
    0%, 100% { transform: translateY(0) scale(1.08, 0.9); }
    12% {
        transform: translateY(-2px) rotate(-9deg) scale(0.93, 1.08);
        animation-timing-function: ease-out;
    }
    43% {
        transform: translateY(calc(var(--season-height) * -1)) rotate(-4deg) scale(1);
        animation-timing-function: ease-in;
    }
    78% { transform: translateY(0) rotate(5deg) scale(1.1, 0.87); }
    90% { transform: translateY(0) scale(1); }
}
.sg-season-background.paused .lavender-mote,
.sg-season-background.paused .rabbit-run,
.sg-season-background.paused .rabbit-run svg { animation-play-state: paused; }

/* Cibo: a barely visible generated mesh carries little lavender signals. */
.netsphere-mesh {
    display: block;
    width: 100%;
    height: 100%;
    fill: none;
}
.netsphere-links {
    stroke: var(--accent-light);
    stroke-width: 0.6;
    opacity: 0.045;
}
.netsphere-node {
    fill: var(--accent-light);
    opacity: 0.14;
}
.netsphere-signal,
.netsphere-trail {
    stroke: var(--accent-light);
    stroke-linecap: round;
    animation: netsphere-transmit var(--season-duration) var(--season-delay) linear infinite;
}
.netsphere-signal {
    stroke-width: 1.8;
    stroke-dasharray: 0.006 0.994;
    filter: drop-shadow(0 0 3px rgba(var(--accent-rgb), 0.5));
}
.netsphere-trail {
    --season-packet-from: 1.029;
    --season-packet-to: 0.029;
    --season-bright: 0.12;
    stroke-width: 1;
    stroke-dasharray: 0.035 0.965;
}
@keyframes netsphere-transmit {
    0% { opacity: 0; stroke-dashoffset: var(--season-packet-from, 1); }
    8%, 92% { opacity: var(--season-bright, 0.55); }
    100% { opacity: 0; stroke-dashoffset: var(--season-packet-to, 0); }
}

/* Killy: steel dust and gently glowing embers drift through the darkness. */
.emitter-dust,
.emitter-ember {
    position: absolute;
    width: var(--season-size);
    height: var(--season-size);
    animation: emitter-ember var(--season-duration) var(--season-delay) ease-in-out infinite;
}
.emitter-dust { --season-bright: 0.25; background: var(--accent); border-radius: 1px; }
.emitter-ember {
    border-radius: 50%;
    background: var(--accent-light);
    box-shadow: 0 0 6px rgba(var(--accent-rgb), 0.5);
}
@keyframes emitter-ember {
    0% { opacity: 0; transform: translate(0, 16px); }
    30% { opacity: var(--season-bright, 0.45); }
    65% { opacity: 0.2; }
    100% { opacity: 0; transform: translate(var(--season-wind), -65px); }
}
.sg-season-background.paused .netsphere-signal,
.sg-season-background.paused .netsphere-trail,
.sg-season-background.paused .emitter-dust,
.sg-season-background.paused .emitter-ember { animation-play-state: paused; }

/* Ayame and Albedo share the event's firework renderer, in a golden
   background layer below the page's content. */
.sg-fireworks { opacity: 0.8; }
.sg-fireworks .sg-spark { position: absolute; z-index: auto; }

/* Teto and Miku: an equalizer along the bottom edge. Each bar grows from the
   floor (scaleY, set by js/seasonal-background.js while the song plays) with
   its peak line above it; without the song it sways in a slow wave. */
.sg-equalizer {
    top: auto;
    display: flex;
    align-items: stretch;
    gap: 4px;
    height: 22vh;
    padding: 0 12px;
    -webkit-mask-image: linear-gradient(to top, #000 55%, transparent);
    mask-image: linear-gradient(to top, #000 55%, transparent);
}
.equalizer-band {
    position: relative;
    flex: 1;
}
.equalizer-bar,
.equalizer-peak {
    position: absolute;
    inset: 0;
}
.equalizer-bar {
    background: linear-gradient(to top, rgba(var(--accent-rgb), 0.4), rgba(var(--accent-light-rgb), 0.22));
    transform: scaleY(var(--season-rest));
    transform-origin: bottom;
    animation: equalizer-idle var(--season-duration) var(--season-delay) ease-in-out infinite;
}
.equalizer-peak {
    border-top: 2px solid rgba(var(--accent-light-rgb), 0.75);
    transform: translateY(calc((1 - var(--season-rest, 0.1)) * 100%));
    opacity: 0;
    transition: opacity 0.4s;
}
.sg-equalizer.live .equalizer-bar { animation: none; }
.sg-equalizer.live .equalizer-peak { opacity: 1; }
@keyframes equalizer-idle {
    0%, 100% { transform: scaleY(var(--season-rest)); }
    50% { transform: scaleY(calc(var(--season-rest) * 1.9)); }
}
.sg-season-background.paused .equalizer-bar { animation-play-state: paused; }
@media only screen and (max-width: 760px) {
    .sg-equalizer { gap: 3px; height: 18vh; padding: 0 6px; }
}

/* the song's button and its volume, in the bottom left corner while the
   equalizer is shown */
.music-control {
    position: fixed;
    left: 20px;
    bottom: max(20px, env(safe-area-inset-bottom));
    z-index: 12;
    display: flex;
    align-items: center;
    gap: 10px;
}
.music-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    width: 44px;
    height: 44px;
    padding: 0;
    border: 0;
    --fill: var(--surface-raised);
    color: var(--link);
    cursor: pointer;
    -webkit-backdrop-filter: blur(10px);
    backdrop-filter: blur(10px);
}
.music-toggle:hover,
.music-toggle:focus-visible {
    --arm: 18px;
    color: var(--text-strong);
    outline: none;
}
.music-toggle:disabled {
    --arm: 10px;
    color: var(--text-dim);
    cursor: default;
}
.music-toggle svg {
    width: 20px;
    height: 20px;
    fill: none;
    stroke: currentColor;
    stroke-width: 2;
    stroke-linecap: round;
    stroke-linejoin: round;
}
/* the browser holds the carried-over song back until a click: the corners
   blink to say so */
.music-control.waiting .music-toggle { animation: music-waiting 1.6s ease-in-out infinite; }
@keyframes music-waiting {
    0%, 100% { --arm: 10px; color: var(--link); }
    50% { --arm: 18px; color: var(--text-strong); }
}
.music-toggle .music-pause,
.music-toggle[aria-pressed="true"] .music-play { display: none; }
.music-toggle[aria-pressed="true"] .music-pause { display: block; }

/* the volume: a thin HUD line filled up to the chosen level, a square thumb */
.music-volume {
    width: 96px;
    height: 24px;
    margin: 0;
    background: transparent;
    cursor: pointer;
    -webkit-appearance: none;
    appearance: none;
}
.music-volume:disabled { opacity: 0.4; cursor: default; }
.music-volume::-webkit-slider-runnable-track {
    height: 2px;
    background: linear-gradient(to right, var(--accent-light) var(--music-volume), var(--border-strong) var(--music-volume));
}
.music-volume::-moz-range-track { height: 2px; background: var(--border-strong); }
.music-volume::-moz-range-progress { height: 2px; background: var(--accent-light); }
.music-volume::-webkit-slider-thumb {
    width: 10px;
    height: 10px;
    margin-top: -4px;
    border: 0;
    background: var(--accent-light);
    -webkit-appearance: none;
    appearance: none;
}
.music-volume::-moz-range-thumb {
    width: 10px;
    height: 10px;
    border: 0;
    border-radius: 0;
    background: var(--accent-light);
}
.music-volume:focus-visible { outline: 1px dashed var(--accent-light); outline-offset: 2px; }
@media only screen and (max-width: 760px) {
    .music-control { left: 16px; bottom: max(16px, env(safe-area-inset-bottom)); }
    /* the footer's links stay clear of the button */
    body:has(> .music-control) .site-foot { padding-bottom: 72px; }
}

/* Turning effects off hides decorations. During an event one stationary
   target remains reachable by keyboard, appearing only when it has focus. */
:root[data-skin-animations="off"] .sg-season-background .seasonal-particle {
    top: 18vh;
    opacity: 0;
    animation: none;
}
:root[data-skin-animations="off"] .sg-season-background .seasonal-particle:focus-within { opacity: 1; }
:root[data-skin-animations="off"] .sg-season-background .seasonal-particle ~ .seasonal-particle,
:root[data-skin-animations="off"] .sg-season-background .perseid-star { display: none; }
:root[data-skin-animations="off"] .sakura-drift,
:root[data-skin-animations="off"] .sakura-petal,
:root[data-skin-animations="off"] .sakura-petal svg { animation: none; }
:root[data-skin-animations="off"] .firefly-light { animation: none; }

@media (prefers-reduced-motion: reduce) {
    .seasonal-particle {
        top: var(--season-rest-top);
        opacity: 0.65;
        animation: none;
    }
    .sakura-drift,
    .sakura-petal,
    .sakura-petal svg,
    .perseid-star { animation: none; }
    .sakura-petal svg { transition: none; }
    .sg-sakura .seasonal-particle:nth-child(n + 9) { display: none; }
    .perseid-star { opacity: 0.35; }
    .firefly-light { animation: none; opacity: 0.8; }
    .ink-spill::before { display: none; }
    .ink-spill::after { animation: none; opacity: 0.35; transform: scale(0.7); }
    .wired-line { animation: none; opacity: 0.15; }
    .lightning-bolt { animation: none; opacity: 0.14; }
    .lightning-bolt::before { display: none; }
    .sg-lightning::after { animation: none; opacity: 0; }
    .sg-wired::after { animation: none; opacity: 0; }
    .witch-butterfly { animation: none; opacity: 0.5; }
    .butterfly-wing { animation: none; }
    .magic-dust { animation: none; opacity: 0.3; }
    .magic-star { animation: none; opacity: 0.5; }
    .magic-star::before { display: none; }
    .lavender-mote { animation: none; opacity: 0.3; }
    .idol-beam { animation: none; opacity: 0.6; }
    .idol-star { animation: none; opacity: 0.5; transform: scale(0.8); }
    .rabbit-run { animation: none; left: var(--season-rest-left); transform: translateX(-50%); }
    .rabbit-run svg { animation: none; }
    .netsphere-signal,
    .netsphere-trail { animation: none; display: none; }
    .emitter-dust { animation: none; opacity: 0.15; }
    .emitter-ember { animation: none; opacity: 0.25; }
    .equalizer-bar { animation: none; }
    .music-control.waiting .music-toggle { animation: none; --arm: 18px; }
}
