/* ============================================================================
   events/halloween.css — the Halloween event theme (EventTheme::HALLOWEEN).
   Loaded by base.html.twig (and web/solo.html.twig) only while the theme is
   on; the markup is templates/web/components/EventTheme/Halloween/*.

   A light touch, not a reskin: buttons, links and headings keep the violet
   accent. The theme adds small flat SVG pieces in Halloween colours — warm
   pumpkin orange and candlelight, a little witch purple, moss green — and
   turns the voice line's lit part into candlelight. The palette lives here,
   not in tokens.css, because nothing else may use it.

   Where:
     every page    a cobweb pinned to the window's top-left corner (stays
                   while scrolling); lit pumpkins on the footer's top line;
                   a bat crossing the screen now and then (desktop only)
     home hero     spider and a ghost with a lantern gliding along
                   the voice line over its lit part (phones and tablet
                   portrait: the ghost only)
     inner pages   the header's engraved word carved like a jack-o'-lantern,
                   lit from within, a cobweb with a spider in its frame's
                   corner; a small piece at the end of the breadcrumb row
                   where the header has no word (desktop; Subpage.html.twig
                   lists them); the game page's ghost hides behind the
                   cover, a news post's spider hangs into its picture
     error pages   the same lantern word on the status code
     back to top   an upright witch's broom in place of the arrow; on a
                   click it takes off and rises with the page
     home team     one piece per card (hat, bat, spider, pumpkin, ghost)
     donations     the podium: cobwebs, mist, slime on the winner's card,
                   a hat on the winner, a bat and a spider
     suggestions   the light in the current progress step burns warm
     download btns a corner cobweb; under a mouse a spider drops from it

   Motion: transform / opacity only, on small SVGs. The hero and footer
   layers are [data-loop] and stand still while off screen; reduced motion
   and the visitor's switch are handled for every .ev in layout.css. The
   pieces are images, not text, and their loops never end, so the Firefox
   end-of-transform re-snap (tokens.css) does not apply.
   ========================================================================== */

:root[data-event="halloween"] {
  --ev-orange:       #ff9a3d;   /* candlelight: the voice line, the switch */
  --ev-ghost:        #eee7df;
  --ev-ghost-shade:  rgba(52, 34, 72, 0.13);
  --ev-ink:          #231e2b;
  --ev-cheek:        #f2a7b4;
  --ev-pumpkin:      #cf6414;   /* the outer ribs */
  --ev-pumpkin-core: #ec7f22;
  --ev-stem:         #6d8b3a;
  --ev-leaf:         #88a94a;
  --ev-candle:       #ffd36a;   /* a carved face, a flame, lit glass */
  --ev-candle-pool:  rgba(255, 168, 64, 0.2);
  --ev-witch:        #6a4a9c;   /* headphone cups */
  --ev-hat:          #3a2858;   /* dark, with a light outline: reads on avatars and cards */
  --ev-iron:         #3c3548;   /* cauldron, lantern, stands */
  --ev-bat:          #6a5a86;   /* light enough to read on the graphite */
  --ev-bat-eye:      #ffb547;
  --ev-cat:          #2c2536;   /* barely there: the eyes give it away */
  --ev-spider:       #7a6c92;
  --ev-spider-eye:   #ff7a66;
  --ev-thread:       rgba(255, 214, 170, 0.28);
  --ev-brew:         #8bd14a;
  --ev-stone:        #4b4756;
  --ev-moss:         #5f8a3a;
  --ev-web:          rgba(255, 206, 160, 0.16);
}

/* The voice line in candlelight (components.css section 15): warm lit bars,
   a warm faint core, the dim bars just warmer — only while the decorations
   are on (the visitor's switch brings the violet back). Everything else the
   theme changes outside its own .ev pieces is gated the same way. */
:root[data-event="halloween"]:not(.ev-off) {
  --voiceline-lit:   var(--ev-orange);
  --voiceline-core:  #ffe2a8;
  --voiceline-dim:   rgba(255, 228, 200, 0.14);
}

/* The visitor's switch (layout.css) carries the theme's colour while the
   decorations are on. */
:root[data-event="halloween"]:not(.ev-off) .ev-toggle.btn { color: var(--ev-orange); }

/* ── Art ───────────────────────────────────────────────────────────────── */
.ev-ghost,
.ev-pumpkin,
.ev-bat,
.ev-web,
.ev-hat,
.ev-cat,
.ev-cauldron,
.ev-crystal,
.ev-grave,
.ev-lantern,
.ev-potion { display: block; width: 100%; height: auto; overflow: visible; }

.ev-ghost__body  { fill: var(--ev-ghost); }
.ev-ghost__shade { fill: var(--ev-ghost-shade); }
.ev-ghost__cheek { fill: var(--ev-cheek); opacity: 0.75; }
.ev-ghost__ink   { fill: var(--ev-ink); }
.ev-ghost__cape  {
  fill: var(--ev-pumpkin-core);
  transform-box: fill-box;
  transform-origin: 100% 0;
  animation: ev-cape 1.8s ease-in-out infinite;
}
.ev-ghost__eyes  {
  transform-box: fill-box;
  transform-origin: center;
  animation: ev-blink 5.5s ease-in-out infinite;
}

.ev-pumpkin__pool { fill: var(--ev-candle-pool); }
.ev-pumpkin__stem { fill: var(--ev-stem); }
.ev-pumpkin__leaf { fill: var(--ev-leaf); }
.ev-pumpkin__rib  { fill: var(--ev-pumpkin); }
.ev-pumpkin__core { fill: var(--ev-pumpkin-core); }
.ev-pumpkin__face { fill: var(--ev-candle); }
.ev-pumpkin__face,
.ev-pumpkin__pool { animation: ev-flicker 3.4s linear infinite; }
.ev-pumpkin__shades { fill: #15121b; }
.ev-pumpkin__glint  { fill: #fff; opacity: 0; animation: ev-glint 6s ease-in-out infinite 1s; }
.ev-pumpkin__band   { fill: none; stroke: var(--ev-iron); stroke-width: 3.4; stroke-linecap: round; }
.ev-pumpkin__cup    { fill: var(--ev-witch); }
.ev-pumpkin__note   { fill: var(--ev-bat-eye); opacity: 0; animation: ev-note 3.2s ease-out infinite; }

.ev-bat__body,
.ev-bat__wing   { fill: var(--ev-bat); }
.ev-bat__eye    { fill: var(--ev-bat-eye); }
.ev-bat__feet   { fill: none; stroke: var(--ev-bat); stroke-width: 1.6; stroke-linecap: round; }
.ev-bat__wing-fold { fill: none; stroke: rgba(0, 0, 0, 0.3); stroke-width: 1; stroke-linecap: round; }

.ev-spider {
  position: absolute;
  width: 1.5rem;
  transform-origin: 50% 0;
}
.ev-spider::before {   /* the thread, from the top of the box to the spider */
  content: '';
  position: absolute;
  top: 0;
  bottom: 1rem;
  left: calc(50% - 0.5px);
  width: 1px;
  background: linear-gradient(transparent, var(--ev-thread) 35%);
}
.ev-spider__body {
  position: absolute;
  bottom: 0;
  left: 0;
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}
.ev-spider__legs    { fill: none; stroke: var(--ev-spider); stroke-width: 1.6; stroke-linecap: round; }
.ev-spider__abdomen { fill: var(--ev-spider); }
.ev-spider__eye     { fill: var(--ev-spider-eye); }

.ev-web path {
  fill: none;
  stroke: var(--ev-web);
  stroke-width: 1;
  vector-effect: non-scaling-stroke;
}

.ev-hat__cone   { fill: var(--ev-hat); stroke: #c9b0ff; stroke-width: 1.1; stroke-linejoin: round; }
.ev-hat__band   { fill: var(--ev-pumpkin-core); }
.ev-hat__buckle { fill: var(--ev-candle); }

.ev-cat__fur   { fill: var(--ev-cat); }
.ev-cat__eye   { fill: var(--ev-bat-eye); }
.ev-cat__pupil { fill: none; stroke: #1a1410; stroke-width: 0.9; stroke-linecap: round; }
.ev-cat__eyes  {
  transform-box: fill-box;
  transform-origin: center;
  animation: ev-blink 4.6s ease-in-out infinite 0.8s;
}
.ev-cat__tail  {
  transform-box: fill-box;
  transform-origin: 0 90%;
  animation: ev-tail 3s ease-in-out infinite;
}

.ev-cauldron__iron   { fill: var(--ev-iron); }
.ev-cauldron__shade  { fill: rgba(0, 0, 0, 0.25); }
.ev-cauldron__rim    { fill: #4c4559; }
.ev-cauldron__brew   { fill: var(--ev-brew); }
.ev-cauldron__flame  { fill: var(--ev-pumpkin-core); }
.ev-cauldron__flame-core { fill: var(--ev-candle); }
.ev-cauldron__fire   { animation: ev-flicker 1.6s linear infinite; }
.ev-cauldron__bubble {
  fill: var(--ev-brew);
  transform-box: fill-box;
  animation: ev-bubble 2.4s ease-in infinite;
}
.ev-cauldron__bubble--2 { animation-delay: -0.8s; }
.ev-cauldron__bubble--3 { animation-delay: -1.6s; }

.ev-crystal__aura  { fill: rgba(164, 114, 245, 0.16); animation: ev-breathe 3.6s ease-in-out infinite; }
.ev-crystal__glass { fill: rgba(164, 114, 245, 0.3); stroke: rgba(255, 255, 255, 0.24); stroke-width: 0.8; }
.ev-crystal__mist  {
  fill: none;
  stroke: var(--ev-orange);
  stroke-width: 1.4;
  stroke-linecap: round;
  opacity: 0.85;
  transform-box: fill-box;
  transform-origin: center;
  animation: ev-spin 9s linear infinite;
}
.ev-crystal__shine { fill: rgba(255, 255, 255, 0.55); }
.ev-crystal__stand { fill: var(--ev-iron); }
.ev-crystal__band  { fill: #e0a24a; }

.ev-grave__stone { fill: var(--ev-stone); }
.ev-grave__shade { fill: rgba(0, 0, 0, 0.18); }
.ev-grave__text  { fill: #2c2934; font-family: var(--font-mono); font-size: 7.5px; font-weight: 700; letter-spacing: 0.5px; }
.ev-grave__crack { fill: none; stroke: rgba(0, 0, 0, 0.35); stroke-width: 0.9; stroke-linecap: round; }
.ev-grave__grass { fill: var(--ev-moss); }
.ev-grave__wisp  { fill: var(--ev-ghost); opacity: 0; animation: ev-wisp 7s ease-in-out infinite 1.5s; }

.ev-lantern__aura  { fill: rgba(255, 190, 90, 0.16); }
.ev-lantern__metal { fill: var(--ev-iron); }
.ev-lantern__metal-line { fill: none; stroke: var(--ev-iron); stroke-width: 1.2; stroke-linecap: round; }
.ev-lantern__glass { fill: rgba(255, 200, 110, 0.35); }
.ev-lantern__flame { fill: var(--ev-candle); }
.ev-lantern__aura,
.ev-lantern__glass,
.ev-lantern__flame { animation: ev-flicker 2.6s linear infinite; }

.ev-potion__glow-stop { stop-color: var(--ev-brew); }
.ev-potion__aura   { animation: ev-breathe 3.2s ease-in-out infinite; }
.ev-potion__brew   { fill: var(--ev-brew); opacity: 0.9; }
.ev-potion__bubble {
  fill: #c9f59a;
  opacity: 0;
  transform-box: fill-box;
  animation: ev-potion-bubble 2.6s ease-in infinite;
}
.ev-potion__bubble--2 { animation-delay: -0.9s; }
.ev-potion__bubble--3 { animation-delay: -1.7s; }
.ev-potion__glass  { fill: rgba(255, 255, 255, 0.05); stroke: rgba(255, 255, 255, 0.4); stroke-width: 1.1; stroke-linejoin: round; }
.ev-potion__shine  { fill: none; stroke: rgba(255, 255, 255, 0.5); stroke-width: 1.2; stroke-linecap: round; }
.ev-potion__cork   { fill: #a87445; }
.ev-potion__lip    { fill: none; stroke: rgba(255, 255, 255, 0.4); stroke-width: 1.6; stroke-linecap: round; }

/* ── Every page: the bat crossing the screen (desktop only) ─────────────
   Off screen most of the time: one 7s pass, then 27s away. Under the topbar
   (z-index under --z-sticky), over the page. */
.ev-hw-flyer { display: none; }
@media (min-width: 1024px) and (pointer: fine) {
  .ev-hw-flyer {
    position: fixed;
    z-index: 5;
    top: 18vh;
    left: 0;
    display: block;
    width: 2.75rem;
    opacity: 0;
    animation: ev-fly 34s linear infinite 8s;
  }
  .ev-hw-flyer .ev-bat__wing {
    transform-box: fill-box;
    animation: ev-flap-l 0.26s ease-in-out infinite alternate;
  }
  .ev-hw-flyer .ev-bat__wing--l { transform-origin: 100% 40%; }
  .ev-hw-flyer .ev-bat__wing--r { transform-origin: 0 40%; animation-name: ev-flap-r; }
}

/* ── The corner cobweb: every page, pinned to the window's top-left ──────
   Fixed, so it stays while the page scrolls, and over the topbar (whose
   scrolled surface would cover it), under the maintenance strip when that
   is open. As wide as the side margin, so it stays off the logo; a phone
   or tablet portrait has no margin to speak of, so there it is small and
   just touches the logo mark. */
.ev-hw-cornerweb {
  position: fixed;
  z-index: calc(var(--z-sticky) + 1);
  top: var(--maint-offset, 0px);
  left: 0;
  width: clamp(4rem, (100vw - var(--container)) / 2 - 0.25rem, 8rem);
}
@media (max-width: 1023px) {
  .ev-hw-cornerweb { width: 2.25rem; }
}

/* ── Home hero ─────────────────────────────────────────────────────────────
   Over the veil and the wall, under the copy and the voice line (z-index 2).
   Places follow the hero's own measures (home.css): --hero-edge (where the
   copy starts), --copy-w, --wall-left (where the cover wall starts) and the
   voice line's box, so they hold at every desktop width. */
.ev-hw-hero {
  position: absolute;
  z-index: 1;
  inset: 0;
}
.ev-hw-hero:not(.is-visible) *,
.ev-hw-foot:not(.is-visible) * { animation-play-state: paused; }

/* Let down from the very top of the page, through the clear topbar in the
   gap between the logo and the nav links (the logo ends ~8.5rem past the
   copy's edge, the links start ~5rem further at every desktop width); it
   bobs 0.75rem, so the box starts that much above the page. */
.ev-hw-hero__spider {
  top: -0.75rem;
  left: calc(var(--hero-edge) + 11rem);
  height: calc(0.75rem + var(--nav-h) + clamp(2.75rem, 8vh, 5.5rem));
  animation: ev-bob 4.8s ease-in-out infinite;
}

/* The ghost on the voice line. The rider box is the voice line's own box
   (home.css .hero__voice: centred, at most 75rem, the line's height and
   bottom margin grow with --hero-wide), zero tall, on the line's top edge.
   The track is as wide as the line and glides with the line's lit window
   (components.css .voiceline--drift: a window 36% wide whose centre runs
   from -10.8% to 110.8% of the line, linear, --drift-dur 8s here), so the
   ghost at its left edge rides right over the lit bars. Its glide starts
   in the same style change as the line's drift (both hang on the line's
   .is-visible), so they never part. At rest it waits in the middle. */
.ev-hw-rider {
  --rider-w: min(100% - 2 * var(--gutter), 75rem);
  position: absolute;
  left: calc((100% - var(--rider-w)) / 2);
  bottom: calc(var(--space-8) + var(--hero-wide) * 0.16 + 2.75rem);
  width: var(--rider-w);
  height: 0;
}
.ev-hw-rider__track {
  position: absolute;
  left: 0;
  bottom: 0;
  width: 100%;
  transform: translateX(50%);
}
@media (prefers-reduced-motion: no-preference) {
  .hero:has(.hero__voice.is-visible) .ev-hw-rider__track { animation: ev-ride 8s linear infinite; }
}
.ev-hw-rider__ghost {
  position: absolute;
  left: -1.125rem;
  bottom: 0.125rem;
  width: 2.25rem;
  animation: ev-float 2.4s ease-in-out infinite;
}
/* A faint warm light around the ghost and its lantern only. */
.ev-hw-rider__ghost::before {
  content: '';
  position: absolute;
  z-index: -1;
  top: -60%;
  right: -90%;
  bottom: -50%;
  left: -60%;
  background: radial-gradient(closest-side, rgba(255, 170, 90, 0.16), transparent);
}
.ev-hw-rider__lantern {
  position: absolute;
  right: -0.75rem;
  bottom: 0.25rem;
  width: 0.875rem;
  transform-origin: 50% 0;
  animation: ev-sway 2.4s ease-in-out infinite;
}

/* Phones and tablet portrait: no wall — only the ghost on the voice line. */
@media (max-width: 1023px) {
  .ev-hw-hero__spider { display: none; }
  /* The note line stands right over the voice line here, so the ghost
     floats lower, in the upper half of the lit bars. */
  .ev-hw-rider { bottom: calc(var(--space-6) + 2.75rem * 0.45); }
}
@media (max-width: 767px) {
  .ev-hw-rider__ghost { left: -0.75rem; width: 1.5rem; }
  .ev-hw-rider__lantern { right: -0.5rem; width: 0.625rem; }
}

/* ── Inner pages ─────────────────────────────────────────────────────────
   .ev-hw-sub: the small piece at the end of the breadcrumb row (below);
   the engraved word's own touch follows it. */
.ev-hw-sub {
  position: absolute;
  z-index: 1;
  display: block;
}

/* The engraved word, carved like a jack-o'-lantern (Shared/PageMark,
   components.css section 8): its glyphs are lit from within — the fill is a
   warm candle glow clipped to the text, brightest low in the middle — the
   outlines turn warm (the first letter keeps its violet), a soft glow
   spills around it and the candle flickers. */
:root[data-event="halloween"]:not(.ev-off) .page-mark__word {
  background: radial-gradient(60% 80% at 50% 62%, rgba(255, 196, 110, 0.5), rgba(255, 128, 40, 0.24) 55%, rgba(120, 40, 10, 0.06) 100%);
  -webkit-background-clip: text;
          background-clip: text;
  color: transparent;
  -webkit-text-stroke-color: rgba(255, 150, 70, 0.5);
  filter: drop-shadow(0 0 14px rgba(255, 130, 40, 0.2));
}
@media (prefers-reduced-motion: no-preference) {
  :root[data-event="halloween"]:not(.ev-off) .page-mark__word { animation: ev-flicker 3.6s linear infinite; }
}

/* A cobweb spun across the frame's top-left corner (over its corner
   bracket), a small spider resting on it, facing the corner, now and then
   creeping a step along the web and back. */
.ev-hw-markweb {
  position: absolute;
  z-index: 1;
  top: 0;
  left: 0;
  width: 3.25rem;
  height: 3.25rem;
}
.ev-hw-markweb__web { position: absolute; top: 0; left: 0; width: 100%; }
.ev-hw-markweb__web path { stroke: rgba(255, 206, 160, 0.3); }
.ev-hw-markweb__spider {
  top: 1.125rem;
  left: 1.125rem;
  width: 1.125rem;
  height: 1rem;
  transform: rotate(-45deg);
  transform-origin: 50% 50%;
  animation: ev-creep 7s ease-in-out infinite;
}
.ev-hw-markweb__spider::before { display: none; }

.ev-hw-sub__lantern {
  position: absolute;
  right: -0.875rem;
  bottom: 0.375rem;
  width: 36%;
  transform-origin: 50% 0;
  animation: ev-sway 3s ease-in-out infinite;
}

/* Small, at the right end of the breadcrumb row: where the header shows no
   engraved word — phones and tablet portrait, or a header without one. */
.page-header__inner:has(> .ev-hw-sub--crumbs) { position: relative; }
.ev-hw-sub--crumbs {
  top: -0.375rem;
  right: var(--gutter);
  display: none;
  width: 2.25rem;
}
.ev-hw-sub--crumbs.ev-hw-sub--potion { top: -0.5rem; width: 1.75rem; }
.ev-hw-sub--crumbs.ev-hw-sub--hero { width: 2.75rem; }
.ev-hw-sub--crumbs.ev-hw-sub--lantern,
.ev-hw-sub--crumbs.ev-hw-sub--hero { animation: ev-float 4s ease-in-out infinite; }
/* Desktop only, where the header has no word; on phones and tablet
   portrait the breadcrumb row stays plain. */
@media (min-width: 1024px) {
  .page-header:not(.page-header--mark) .ev-hw-sub--crumbs { display: block; }
}

/* The game page: a ghost behind the cover (the frame is lifted over it),
   leaning out of its right edge now and then — on a phone, where the title
   column stands right by the small cover, up over its top edge instead. */
.game-hero__frame:has(+ .ev-hw-peek) { position: relative; z-index: 1; }
.ev-hw-peek {
  position: absolute;
  z-index: 0;
  top: 14%;
  right: 3%;
  width: 3.25rem;
  animation: ev-peek-out 9s ease-in-out infinite 2s;
}

/* A news post: a spider let down into its cover picture from the top —
   dark, as a cover is mostly bright. */
.ev-hw-postspider {
  --ev-spider: #2b2338;
  --ev-thread: rgba(255, 255, 255, 0.55);
  z-index: 2;
  top: -0.75rem;
  right: 12%;
  height: calc(0.75rem + clamp(3rem, 22%, 6.5rem));
  animation: ev-bob 4.8s ease-in-out infinite;
}

/* ── Home team cards: one piece each (TeamCard.html.twig) ───────────────
   In the portrait stage (home.css .player__stage: 9.5rem tall, 1.5rem side
   padding; the 7rem portrait stands on its bottom, 1.75rem below it, so
   its top is 4.25rem down and its right edge 8.5rem in). The card clips
   (overflow hidden) and tilts as a whole, the pieces with it. */
.ev-hw-team { position: absolute; z-index: 3; }
.ev-hw-team--hat {
  top: 2.875rem;
  left: 0.625rem;
  width: 2.75rem;
  transform: rotate(-22deg);
  filter: drop-shadow(0 0 3px rgba(255, 154, 61, 0.45));
}
.ev-hw-team--bat {   /* between the portrait and the @nick */
  top: 0;
  left: 44%;
  width: 1.25rem;
  transform-origin: 50% 0;
  animation: ev-sway 5s ease-in-out infinite;
}
.ev-hw-team--spider {
  top: -0.75rem;
  left: 7.25rem;
  height: calc(0.75rem + 3.25rem);
  animation: ev-bob 4.8s ease-in-out infinite;
}
.ev-hw-team--pumpkin {
  z-index: 1;
  right: 1.25rem;
  bottom: -0.3rem;
  width: 2.25rem;
}
.ev-hw-team--peek {   /* behind the portrait (z-index 2) */
  z-index: 1;
  top: 5rem;
  left: 6rem;
  width: 2.5rem;
  animation: ev-peek-out 10s ease-in-out infinite 3s;
}

/* ── Donations podium: a horror mood (Podium / PodiumBadge slots) ───────
   Behind each card's content (the card is made a stacking context, the
   layer sits at z-index -1 over its background; .card clips): a cobweb in
   the top-left corner and mist creeping along the bottom. The winner's
   top edge oozes slime, a drop falling now and then, and the winner wears
   a witch hat; a bat hangs over second place, a spider over third. Loops
   run only while the podium is on screen ([data-loop] .is-visible). */
.don-place:has(> .ev-hw-podium) { isolation: isolate; }
.ev-hw-podium {
  position: absolute;
  z-index: -1;
  inset: 0;
}
.don-podium:not(.is-visible) .ev-hw-podium * { animation-play-state: paused; }
.ev-hw-podium__web {
  position: absolute;
  top: 0;
  left: 0;
  width: 4.5rem;
}
.ev-hw-podium__mist {
  position: absolute;
  right: -25%;
  bottom: -1rem;
  left: -25%;
  height: 4.5rem;
  background:
    radial-gradient(45% 60% at 28% 70%, rgba(214, 204, 255, 0.1), transparent 70%),
    radial-gradient(38% 50% at 72% 62%, rgba(214, 204, 255, 0.08), transparent 70%);
  animation: ev-mist 14s ease-in-out infinite alternate;
}
.ev-hw-podium__mist--2 {
  bottom: -0.5rem;
  opacity: 0.8;
  animation-duration: 19s;
  animation-direction: alternate-reverse;
}
.ev-hw-podium__slime {
  position: absolute;
  top: -1px;
  left: 0;
  display: block;
  width: 100%;
  height: 1.75rem;
  overflow: visible;
}
.ev-slime__ooze  { fill: #74b43a; }
.ev-slime__shine { fill: none; stroke: rgba(255, 255, 255, 0.28); stroke-width: 1; vector-effect: non-scaling-stroke; }
.ev-slime__drop  { fill: #74b43a; opacity: 0; animation: ev-drip 4.5s ease-in infinite 1s; }
.ev-hw-podium__bat {
  position: absolute;
  top: 0;
  left: 24%;
  width: 1.125rem;
  transform-origin: 50% 0;
  animation: ev-sway 5s ease-in-out infinite;
}
.ev-hw-podium__spider {
  top: -0.75rem;
  left: 22%;
  height: calc(0.75rem + 3rem);
  animation: ev-bob 4.8s ease-in-out infinite;
}
.ev-hw-podium-hat {   /* on the winner's avatar (.don-place__badge is positioned) */
  position: absolute;
  z-index: 2;
  top: -0.875rem;
  left: -0.625rem;
  width: 2.75rem;
  transform: rotate(-20deg);
  filter: drop-shadow(0 0 3px rgba(255, 154, 61, 0.45));
}

/* ── Download buttons: a corner cobweb, a spider on hover ───────────────
   Every two-line "Pobierz dla …" button (kit .btn--split: the download
   page's big buttons, the home hero's): a small cobweb in its top-right
   corner and, under a mouse, a spider that drops from it on its thread
   while the pointer is on the button. Both are the button's own pseudo
   elements (the kit uses none on buttons), painted in its text colour
   through a mask, so they read on the violet and on the dark one alike;
   the button clips them. */
:root[data-event="halloween"]:not(.ev-off) .btn--split { overflow: hidden; }
:root[data-event="halloween"]:not(.ev-off) .btn--split::before,
:root[data-event="halloween"]:not(.ev-off) .btn--split::after {
  content: '';
  position: absolute;
  top: 0;
  pointer-events: none;
  background-color: currentColor;
  -webkit-mask: var(--ev-mask) no-repeat center / contain;
          mask: var(--ev-mask) no-repeat center / contain;
}
:root[data-event="halloween"]:not(.ev-off) .btn--split::after {
  --ev-mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 120 120'><path fill='none' stroke='%23000' stroke-width='4' d='M0 0L118 0M0 0L109 45.2M0 0L83.4 83.4M0 0L45.2 109M0 0L0 118M24 0Q19.8 3.9 22.2 9.2Q16.8 11.2 17 17Q11.2 16.8 9.2 22.2Q3.9 19.8 0 24M46 0Q37.9 7.5 42.5 17.6Q32.1 21.5 32.5 32.5Q21.5 32.1 17.6 42.5Q7.5 37.9 0 46M70 0Q57.7 11.5 64.7 26.8Q48.9 32.7 49.5 49.5Q32.7 48.9 26.8 64.7Q11.5 57.7 0 70M96 0Q79.1 15.7 88.7 36.7Q67 44.8 67.9 67.9Q44.8 67 36.7 88.7Q15.7 79.1 0 96'/></svg>");
  right: 0;
  width: 2.25rem;
  height: 2.25rem;
  opacity: 0.32;
  transform: scaleX(-1);
}
:root[data-event="halloween"]:not(.ev-off) .btn--split::before {
  --ev-mask: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 40'><path d='M8 0V27' stroke='%23000' stroke-width='.8'/><path fill='none' stroke='%23000' stroke-width='1.1' stroke-linecap='round' d='M5.5 30C3 28 1.5 28 .5 29.5M5 32c-2.5 0-4 1-5 2.5M5.5 34c-2 1-3 2.5-3.5 4.5M10.5 30c2.5-2 4-2 5-.5M11 32c2.5 0 4 1 5 2.5M10.5 34c2 1 3 2.5 3.5 4.5'/><ellipse cx='8' cy='32.4' rx='3.3' ry='3.8'/><circle cx='8' cy='27.6' r='2'/></svg>");
  right: 1.125rem;
  width: 0.875rem;
  height: 2.25rem;
  opacity: 0.8;
  transform: translateY(-100%);
  transition: transform 0.6s cubic-bezier(0.34, 1.3, 0.64, 1);
}
@media (hover: hover) and (pointer: fine) {
  :root[data-event="halloween"]:not(.ev-off) .btn--split:hover::before { transform: translateY(-36%); }
}
/* Firefox: a small image that moves — kept on its own layer, so it does
   not re-snap when the drop ends (tokens.css). */
@supports (-moz-appearance: none) {
  :root[data-event="halloween"]:not(.ev-off) .btn--split::before { will-change: transform; }
}

/* ── Game suggestions: the step in progress, by candlelight ─────────────
   Only the light running through the current step turns warm; the bar
   itself keeps its colours (game-suggestions.css .gs-step). */
:root[data-event="halloween"]:not(.ev-off) .gs-step.is-current::after {
  background: linear-gradient(90deg, transparent, #ffc27a 55%, var(--ev-orange) 80%, transparent);
}

/* ── Back to top: a witch's broom instead of the arrow ──────────────────
   While the decorations are on, the kit button (layout.css .to-top, bottom
   right) loses its tile — no fill, line or shadow; the keyboard focus ring
   stays — and an upright broom, twice its icon's size, hovers over it on a
   faint warm glow. A click (main.js initEventTheme) is the broom's: it
   shakes off the ground with sparks from its bristles (html.ev-launch),
   then carries the page up at a steady pace, rising with it — main.js sets
   --ev-launch-p (0 → 1) every frame — and flies off past the top of the
   screen. Interrupted by the visitor, it lands back (html.ev-landing). */
:root[data-event="halloween"]:not(.ev-off) .to-top.btn {
  --btn-bg:         transparent;
  --btn-bg-hover:   transparent;
  --btn-line:       transparent;
  --btn-line-hover: transparent;
  --btn-shadow:     none;
  width: 3rem;
  min-height: 4.25rem;
}
:root[data-event="halloween"]:not(.ev-off) .to-top.btn > svg { opacity: 0; }
.ev-hw-broom {
  position: fixed;
  z-index: calc(var(--z-dock) + 1);
  right: var(--space-6);
  bottom: var(--space-6);
  display: grid;
  place-items: center;
  width: 3rem;
  height: 4.25rem;
  opacity: 0;
  visibility: hidden;
  transition: opacity var(--dur-base) var(--ease-standard), visibility 0s linear var(--dur-base);
}
.to-top.is-visible ~ .ev-hw-broom {
  opacity: 1;
  visibility: visible;
  transition-delay: 0s;
}
.ev-hw-broom::before {   /* the warm glow it hovers over */
  content: '';
  position: absolute;
  bottom: -0.125rem;
  left: 50%;
  width: 2.75rem;
  height: 0.75rem;
  margin-left: -1.375rem;
  border-radius: 50%;
  background: radial-gradient(closest-side, rgba(255, 154, 61, 0.35), transparent);
}
.ev-hw-broom__art {
  width: 1.875rem;
  animation: ev-hover 2.8s ease-in-out infinite;
}
@media (hover: hover) and (pointer: fine) {
  .to-top:hover ~ .ev-hw-broom .ev-hw-broom__art { animation: ev-eager 0.5s ease-in-out infinite; }
}
.ev-hw-broom::after {   /* the trail, from under the bristles down */
  content: '';
  position: absolute;
  top: calc(50% + 1.75rem);
  left: calc(50% - 2px);
  width: 4px;
  height: 9rem;
  border-radius: 2px;
  background: linear-gradient(var(--ev-orange), rgba(255, 154, 61, 0));
  opacity: 0;
  transform: scaleY(0);
  transform-origin: 50% 0;
}
.ev-broom__stick      { fill: none; stroke: #9a6a3e; stroke-width: 2.4; stroke-linecap: round; }
.ev-broom__knob       { fill: #7a5030; }
.ev-broom__straw      { fill: #e9b44c; }
.ev-broom__straw-line { fill: none; stroke: #c4842a; stroke-width: 0.9; stroke-linecap: round; }
.ev-broom__band       { fill: none; stroke: var(--ev-pumpkin-core); stroke-width: 2.4; stroke-linecap: round; }
.ev-broom__band--thin { stroke-width: 1.2; }
.ev-broom__spark      { fill: var(--ev-candle); opacity: 0; }

/* The flight: no transition — main.js moves it every frame with its own
   eased scroll. It stays on screen though the button hides near the top. */
.ev-launch .ev-hw-broom {
  opacity: 1;
  visibility: visible;
  transform: translateY(calc(var(--ev-launch-p, 0) * (-100vh - 6rem)));
}
.ev-launch .ev-hw-broom::before { opacity: 0; transition: opacity 0.3s ease-out; }
.ev-launch .ev-hw-broom__art { animation: ev-takeoff 0.45s ease-out both; }
.ev-launch .ev-hw-broom::after {
  opacity: calc(0.45 + var(--ev-launch-p, 0) * 0.55);
  transform: scaleY(calc(0.25 + var(--ev-launch-p, 0) * 1.1));
  transition: opacity 0.3s ease-out;
}
.ev-launch .ev-broom__spark { animation: ev-twinkle 0.25s ease-in-out infinite alternate; }
.ev-launch .ev-broom__spark--2 { animation-delay: -0.08s; }
.ev-launch .ev-broom__spark--3 { animation-delay: -0.16s; }
.ev-landing .ev-hw-broom { animation: ev-land 0.45s var(--ease-out) both; }
/* Back in the hidden button after the flight: no fade-out there. */
.ev-instant .ev-hw-broom { transition: none; }

/* ── Footer: pumpkins on the top line, at the right of the page measure ── */
.ev-hw-foot {
  position: absolute;
  z-index: 1;
  right: calc(max(var(--gutter), (100% - var(--container)) / 2) + 1rem);
  bottom: 100%;
  display: flex;
  align-items: flex-end;
  gap: 0.25rem;
  margin-bottom: -0.3rem;   /* the candle pool under them reaches onto the line */
}
.ev-hw-foot__pumpkin--a { width: 1.875rem; }
.ev-hw-foot__pumpkin--b { width: 2.625rem; }
.ev-hw-foot__pumpkin--c { width: 1.5rem; }
.ev-hw-foot__pumpkin--a .ev-pumpkin__face,
.ev-hw-foot__pumpkin--a .ev-pumpkin__pool { animation-delay: -0.9s; }
.ev-hw-foot__pumpkin--c .ev-pumpkin__face,
.ev-hw-foot__pumpkin--c .ev-pumpkin__pool { animation-delay: -2.1s; }

/* ── Phones: lighter everywhere ─────────────────────────────────────────── */
@media (max-width: 767px) {
  .ev-hw-foot__pumpkin--a,
  .ev-hw-foot__pumpkin--c { display: none; }
  .ev-hw-foot__pumpkin--b { width: 2.25rem; }
  .ev-hw-sub--crumbs { width: 2rem; }
  .ev-hw-peek { top: 2%; right: 12%; width: 2.25rem; animation-name: ev-peek-up; }
  .ev-hw-broom { right: var(--space-4); bottom: var(--space-4); }
}

/* ── Motion ────────────────────────────────────────────────────────────── */
@keyframes ev-float {
  0%, 100% { transform: translateY(0) rotate(-2deg); }
  50%      { transform: translateY(-0.5rem) rotate(2deg); }
}
@keyframes ev-bob {
  0%, 100% { transform: translateY(0) rotate(-1.5deg); }
  50%      { transform: translateY(0.75rem) rotate(1.5deg); }
}
@keyframes ev-sway {
  0%, 100% { transform: rotate(-7deg); }
  50%      { transform: rotate(7deg); }
}
@keyframes ev-nod {   /* nodding along to the music */
  0%, 100% { transform: rotate(-3deg); }
  50%      { transform: rotate(3deg) translateY(1px); }
}
@keyframes ev-blink {
  0%, 92%, 100% { transform: scaleY(1); }
  95%           { transform: scaleY(0.1); }
}
@keyframes ev-creep {   /* rests, creeps a step towards the corner, rests, back */
  0%, 30%  { transform: rotate(-45deg) translateY(0); }
  38%, 70% { transform: rotate(-45deg) translateY(-0.375rem); }
  78%, 100% { transform: rotate(-45deg) translateY(0); }
}
@keyframes ev-flicker {
  0%, 100% { opacity: 1; }
  7%       { opacity: 0.8; }
  11%      { opacity: 1; }
  33%      { opacity: 0.9; }
  37%      { opacity: 1; }
  61%      { opacity: 0.84; }
  66%      { opacity: 0.97; }
  71%      { opacity: 1; }
}
@keyframes ev-breathe {
  0%, 100% { opacity: 0.55; }
  50%      { opacity: 1; }
}
@keyframes ev-spin {
  to { transform: rotate(360deg); }
}
@keyframes ev-tail {
  0%, 100% { transform: rotate(0); }
  50%      { transform: rotate(-9deg); }
}
@keyframes ev-cape {
  0%, 100% { transform: skewY(0) scaleX(1); }
  50%      { transform: skewY(-5deg) scaleX(0.94); }
}
@keyframes ev-glint {
  0%, 80%, 100% { opacity: 0; }
  86%           { opacity: 0.9; }
}
@keyframes ev-note {
  0%   { opacity: 0; transform: translate(0, 0); }
  20%  { opacity: 1; }
  80%  { opacity: 0; transform: translate(3px, -9px); }
  100% { opacity: 0; transform: translate(3px, -9px); }
}
@keyframes ev-bubble {
  0%   { opacity: 0; transform: translateY(2px) scale(0.6); }
  25%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-9px) scale(1.1); }
}
/* The little ghost rising from behind the tombstone, then gone. */
@keyframes ev-wisp {
  0%, 30%   { opacity: 0; transform: translateY(6px); }
  45%       { opacity: 0.85; }
  70%       { opacity: 0.85; transform: translateY(-4px); }
  85%, 100% { opacity: 0; transform: translateY(-8px); }
}
/* The game page ghost: hidden behind the cover, then out and back. */
@keyframes ev-peek-out {
  0%, 52%, 100% { transform: translateX(0) rotate(0); }
  62%, 80%      { transform: translateX(88%) rotate(9deg); }
}
@keyframes ev-peek-up {
  0%, 52%, 100% { transform: translateY(0) rotate(0); }
  62%, 80%      { transform: translateY(-62%) rotate(-6deg); }
}
/* With the voice line's lit window (components.css ls-beam), fading at
   the ends where the window's tail leaves the line. */
@keyframes ev-ride {
  0%   { opacity: 0; transform: translateX(-10.8%); }
  12%  { opacity: 1; }
  88%  { opacity: 1; }
  100% { opacity: 0; transform: translateX(110.8%); }
}
@keyframes ev-potion-bubble {
  0%   { opacity: 0; transform: translateY(0); }
  20%  { opacity: 0.9; }
  100% { opacity: 0; transform: translateY(-12px); }
}
@keyframes ev-mist {
  from { transform: translateX(-8%); }
  to   { transform: translateX(8%); }
}
@keyframes ev-drip {   /* the drop gathers under the longest drip, falls, fades */
  0%, 50% { opacity: 0; transform: translateY(-6px) scale(0.6); }
  62%     { opacity: 1; transform: translateY(0) scale(1); }
  92%     { opacity: 0.9; transform: translateY(16px); }
  100%    { opacity: 0; transform: translateY(20px); }
}
/* The broom: hovering in the button, eager under the pointer, shaking off
   the ground as it takes off, dropping back in. */
@keyframes ev-hover {
  0%, 100% { transform: translateY(1px) rotate(-2deg); }
  50%      { transform: translateY(-2px) rotate(2deg); }
}
@keyframes ev-eager {
  0%, 100% { transform: translateY(-2px) rotate(-4deg); }
  50%      { transform: translateY(-3px) rotate(4deg); }
}
@keyframes ev-takeoff {
  0%   { transform: none; }
  20%  { transform: translateY(2px) scaleY(0.9) rotate(-5deg); }
  40%  { transform: translateY(1px) scaleY(0.92) rotate(5deg); }
  60%  { transform: translateY(-1px) rotate(-3deg); }
  100% { transform: translateY(-2px) scaleY(1.06) rotate(0); }
}
@keyframes ev-twinkle {
  from { opacity: 0.2; }
  to   { opacity: 1; }
}
@keyframes ev-land {
  from { opacity: 0; transform: translateY(0.75rem) scale(0.6); }
  to   { opacity: 1; transform: none; }
}
/* One pass left → right along a gentle wave, then off screen. */
@keyframes ev-fly {
  0%     { opacity: 1; transform: translate(-3rem, 0); }
  5%     { transform: translate(25vw, -3vh); }
  10%    { transform: translate(50vw, 1vh); }
  15%    { transform: translate(75vw, -4vh); }
  20%    { opacity: 1; transform: translate(calc(100vw + 3rem), -1vh); }
  20.1%, 100% { opacity: 0; transform: translate(calc(100vw + 3rem), -1vh); }
}
@keyframes ev-flap-l {
  from { transform: rotate(0); }
  to   { transform: rotate(-24deg) scaleY(0.8); }
}
@keyframes ev-flap-r {
  from { transform: rotate(0); }
  to   { transform: rotate(24deg) scaleY(0.8); }
}
