/* ============================================
   TOWER SCENE v2 -- Level 7's living Witch's Tower
   Used by game/js/tower-scene.js on top of css/scene-kit.css (stage,
   props, particles). This file holds the tower look: the seven rooms and
   the transitions between them (the iris, the door push-in, the stair
   pan), the lightning, the candle glows, the drifting wisps, the lock on
   the door (the eight carved runes, the countdown, the answer slots, the
   grid rising from the flagstones), the rune steps, the puzzle panel on
   its painted frame, the letter reveal and the fragment bar, the Witch,
   Princess Pumpkin caged, the spell-break crack and the restored world.
   All sizes inside the stage are design px (960x540); the fragment bar is
   HUD (viewport units) like the seals.
   ============================================ */

.fs-root.fs-tower { background: #07050f; }
.fs-tower img { image-rendering: pixelated; }
.fs-tower .tw-backdrop img { image-rendering: auto; }

/* ---- Rooms: one active at a time; every layer is inert to taps unless it opts back in ---- */
.tw-rooms { position: absolute; inset: 0; }
.tw-room { position: absolute; inset: 0; display: none; transform-origin: 50% 62%; }
.tw-room.active { display: block; }
.tw-room > div { position: absolute; left: 0; top: 0; width: 960px; height: 540px; pointer-events: none; }
.tw-room.tall > div { height: 1080px; top: -540px; }
.tw-backdrop img { position: absolute; left: 0; top: 0; width: 960px; height: 540px; }
.tw-room.tall .tw-backdrop img { height: 1080px; }
.tw-room.tall .tw-mid, .tw-room.tall .tw-fore, .tw-room.tall .tw-backdrop { will-change: transform; }
.tw-fore .fs-prop img { filter: brightness(0.55) saturate(0.85); }
.tw-room.bright .tw-fore .fs-prop img { filter: brightness(0.9); }
.tw-atmo { overflow: hidden; }
.tw-vignette {
  position: absolute; inset: 0;
  background:
    linear-gradient(to bottom, rgba(4, 2, 12, 0.45) 0%, rgba(4, 2, 12, 0) 20%),
    radial-gradient(ellipse at 50% 55%, rgba(0, 0, 0, 0) 52%, rgba(3, 2, 10, 0.6) 100%);
}
.tw-vignette.bright { background: radial-gradient(ellipse at 50% 50%, rgba(0, 0, 0, 0) 60%, rgba(40, 30, 10, 0.25) 100%); }
.tw-dust { background: rgba(230, 210, 255, 0.7); box-shadow: 0 0 3px rgba(200, 170, 255, 0.6); width: 2px; height: 2px; }
.tw-gold-mote { background: rgba(255, 236, 170, 0.95); box-shadow: 0 0 5px rgba(255, 220, 120, 0.9); width: 3px; height: 3px; }
.tw-sunrays {
  position: absolute; inset: -40px 0 0 0;
  background: repeating-linear-gradient(104deg, rgba(255, 240, 190, 0) 0 60px, rgba(255, 244, 200, 0.16) 60px 90px, rgba(255, 240, 190, 0) 90px 180px);
  mix-blend-mode: screen; opacity: 0.8;
  -webkit-mask-image: linear-gradient(to bottom, #000 0%, transparent 70%);
  mask-image: linear-gradient(to bottom, #000 0%, transparent 70%);
  animation: tw-rays 18s ease-in-out infinite alternate;
}
@keyframes tw-rays { from { transform: translateX(-20px); } to { transform: translateX(20px); } }

/* The lightning: a screen-blended flash overlay (never a filter), brighter at the top */
.tw-flash {
  position: absolute; inset: 0; opacity: 0; mix-blend-mode: screen;
  background: linear-gradient(to bottom, rgba(210, 225, 255, 0.95) 0%, rgba(180, 200, 255, 0.55) 45%, rgba(150, 170, 255, 0.15) 100%);
}
.tw-flash.on { animation: tw-lightning 0.7s ease-out; }
@keyframes tw-lightning {
  0% { opacity: 0; } 8% { opacity: 0.9; } 18% { opacity: 0.15; } 30% { opacity: 0.7; } 45% { opacity: 0.1; } 60% { opacity: 0.35; } 100% { opacity: 0; }
}

/* ---- Ambient life: candle / torch / cauldron glows breathe and flicker (pixel-stepped) ---- */
.tw-glow .fs-body::after {
  content: ''; position: absolute; left: 50%; top: 0; width: 120px; height: 120px;
  transform: translate(-50%, -50%); border-radius: 50%; mix-blend-mode: screen; pointer-events: none;
  background: radial-gradient(circle, rgba(255, 200, 110, 0.7) 0%, rgba(255, 160, 60, 0.28) 35%, rgba(255, 140, 40, 0) 70%);
  animation: tw-flicker 1.6s steps(6) infinite;
}
.tw-glow-green .fs-body::after { background: radial-gradient(circle, rgba(140, 255, 160, 0.7) 0%, rgba(80, 220, 110, 0.28) 35%, rgba(60, 200, 90, 0) 70%); animation-duration: 3.2s; top: 30%; }
.tw-glow-blue .fs-body::after { background: radial-gradient(circle, rgba(140, 200, 255, 0.7) 0%, rgba(80, 150, 255, 0.28) 35%, rgba(60, 120, 255, 0) 70%); animation-duration: 3s; }
.tw-glow-gold .fs-body::after { background: radial-gradient(circle, rgba(255, 235, 160, 0.8) 0%, rgba(255, 210, 100, 0.3) 35%, rgba(255, 200, 80, 0) 70%); }
[data-id="cauldron"].tw-glow .fs-body::after { top: 18%; width: 150px; height: 110px; }
[data-id="ball"].tw-glow .fs-body::after { top: 22%; width: 130px; height: 130px; }
[data-id="candelabra"].tw-glow .fs-body::after { top: 8%; width: 150px; height: 120px; }
[data-id="candles"].tw-glow .fs-body::after { width: 90px; height: 90px; }
[data-id="lantern"].tw-glow .fs-body::after { top: 60%; width: 110px; height: 110px; }
@keyframes tw-flicker {
  0% { opacity: 0.55; transform: translate(-50%, -50%) scale(1); }
  20% { opacity: 0.9; transform: translate(-50%, -50%) scale(1.06); }
  40% { opacity: 0.6; transform: translate(-51%, -49%) scale(0.97); }
  60% { opacity: 0.95; transform: translate(-49%, -50%) scale(1.08); }
  80% { opacity: 0.7; transform: translate(-50%, -51%) scale(1.02); }
  100% { opacity: 0.55; transform: translate(-50%, -50%) scale(1); }
}
/* A wisp of green magic drifting slowly */
.tw-wisp .fs-body { opacity: 0.75; animation: tw-wisp var(--dur, 18s) ease-in-out infinite; mix-blend-mode: screen; }
@keyframes tw-wisp {
  0%, 100% { transform: translate(-30px, 0) rotate(-4deg); opacity: 0.45; }
  50% { transform: translate(30px, -18px) rotate(4deg); opacity: 0.8; }
}
.tw-wisp .fs-body > img { filter: drop-shadow(0 0 8px rgba(120, 255, 150, 0.6)); }

/* ---- Transitions ---- */
/* The iris: a black plate with a circular hole that closes over the old room and opens on the new */
.tw-iris {
  position: absolute; inset: -20px; background: #000; pointer-events: none; opacity: 0;
  clip-path: circle(0% at 50% 50%);
}
.tw-iris.closed { opacity: 1; animation: tw-iris-close 0.6s ease-in forwards; }
.tw-iris.opening { opacity: 1; animation: tw-iris-open 0.8s ease-out forwards; }
.tw-iris.fading { opacity: 1; clip-path: none; animation: tw-fade-through 1.3s ease-in-out forwards; }
@keyframes tw-iris-close { from { clip-path: circle(0% at 50% 50%); } to { clip-path: circle(75% at 50% 50%); } }
@keyframes tw-iris-open { from { clip-path: circle(75% at 50% 50%); } to { clip-path: circle(0% at 50% 50%); } }
@keyframes tw-fade-through { 0% { opacity: 0; } 45% { opacity: 1; } 55% { opacity: 1; } 100% { opacity: 0; } }
/* The white-out for the restore, and the black hold after the door push-in */
.tw-white { position: absolute; inset: -20px; background: #fffdf2; opacity: 0; pointer-events: none; transition: opacity 0.6s ease; }
.tw-white.black { background: #000; opacity: 1; transition: opacity 1.2s ease-in; }
.tw-white.flash { opacity: 0; animation: tw-white-flash 2.8s ease-in-out forwards; }
@keyframes tw-white-flash { 0% { opacity: 0; } 40% { opacity: 1; } 60% { opacity: 1; } 100% { opacity: 0; } }
/* The door push-in: the gate room scales up toward the door as the black hold rises */
.tw-room-gate { transform-origin: 50% 58%; }
.tw-room-gate.push-in { animation: tw-push-in 1.6s cubic-bezier(0.4, 0, 0.8, 0.6) forwards; }
@keyframes tw-push-in { from { transform: scale(1); } to { transform: scale(1.9); } }
.tw-door .fs-body.tw-door-open { animation: tw-door-swing 0.9s ease-out; }
@keyframes tw-door-swing { 0% { transform: scaleX(1); } 40% { transform: scaleX(0.96); } 100% { transform: scaleX(1); } }
/* The last door (floor 3) lights when FREE is assembled */
.tw-room-floor3 .tw-atmo::before {
  content: ''; position: absolute; left: 380px; top: 130px; width: 200px; height: 300px; border-radius: 50%;
  background: radial-gradient(ellipse, rgba(255, 235, 160, 0.9) 0%, rgba(255, 220, 120, 0.45) 40%, rgba(255, 200, 80, 0) 70%);
  mix-blend-mode: screen; opacity: 0; transition: opacity 1.4s ease;
}
.tw-room-floor3.door-lit .tw-atmo::before { opacity: 1; animation: tw-door-glow 2.6s ease-in-out infinite; }
@keyframes tw-door-glow { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.1); } }

/* ---- The dim behind a panel, the cue banner ---- */
.tw-dim { position: absolute; inset: 0; background: rgba(4, 2, 12, 0); pointer-events: none; transition: background 0.45s ease; z-index: 700; }
.tw-dim.on { background: rgba(4, 2, 12, 0.62); }
.tw-dim.soft { background: rgba(4, 2, 12, 0.45); }
.tw-cue {
  position: absolute; left: 50%; top: 74px; transform: translateX(-50%) translateY(-12px); z-index: 850;
  font-family: var(--font-pixel, 'Press Start 2P', monospace); font-size: 15px; line-height: 1.6; color: #ffe888;
  background: rgba(8, 4, 20, 0.86); border: 3px solid #c5952e; border-radius: 4px; padding: 9px 18px;
  box-shadow: inset 0 0 0 2px #8a6518, 0 0 18px rgba(255, 220, 120, 0.35); text-shadow: 0 0 8px rgba(255, 220, 120, 0.6), 0 2px 0 #000;
  opacity: 0; pointer-events: none; transition: opacity 0.35s ease, transform 0.35s ease; white-space: nowrap;
}
.tw-cue.show { opacity: 1; transform: translateX(-50%) translateY(0); }

/* ---- The lock on the door (call 3): the plate, the ring of eight carved runes, the countdown, the slots ---- */
.tw-lock { position: absolute; width: 0; height: 0; pointer-events: none; transition: transform 0.7s cubic-bezier(0.3, 0.7, 0.3, 1), opacity 0.6s ease; }
.tw-lock-plate {
  position: absolute; left: 0; top: 0; width: var(--plate); height: var(--plate); transform: translate(-50%, -50%);
  filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.7)); transition: filter 0.6s ease;
}
.tw-lock.awake .tw-lock-plate { filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.7)) drop-shadow(0 0 16px rgba(180, 130, 240, 0.55)); }
.tw-lock.open .tw-lock-plate { filter: drop-shadow(0 6px 10px rgba(0, 0, 0, 0.7)) drop-shadow(0 0 22px rgba(255, 220, 120, 0.8)); }
.tw-lock.fading { opacity: 0; }
.tw-lock.grid-up { transform: translateY(-78px) scale(0.86); }
.tw-lock-ring { position: absolute; left: 0; top: 0; }
/* Each carved socket: a stone square with its rune centred inside (the glow stays clear of the edges) */
.tw-rune-cell {
  position: absolute; width: var(--tile); height: var(--tile); transform: translate(-50%, -50%) scale(1);
  border-radius: 6px; opacity: 0.6; box-sizing: border-box; border: 2px solid rgba(90, 64, 128, 0.9);
  background: radial-gradient(ellipse at 50% 40%, rgba(106, 58, 138, 0.35) 0%, transparent 70%), linear-gradient(160deg, #2c2046 0%, #181028 100%);
  box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(0, 0, 0, 0.7);
  filter: brightness(0.6) saturate(0.6);
  transition: transform 0.22s cubic-bezier(0.3, 1.4, 0.5, 1), opacity 0.3s ease, filter 0.3s ease, box-shadow 0.3s ease, border-color 0.3s ease;
}
.tw-rune-cell img { position: absolute; inset: 6%; width: 88%; height: 88%; object-fit: contain; display: block; }
.tw-rune-cell.carved-lit { opacity: 0.8; filter: brightness(0.68) saturate(0.8); box-shadow: inset 0 0 0 2px rgba(120, 80, 180, 0.9), 0 0 10px rgba(150, 100, 220, 0.5); }
.tw-rune-cell.lit {
  opacity: 1; transform: translate(-50%, -50%) scale(1.7); z-index: 5; border-color: #fff;
  filter: brightness(1.3) saturate(1.2);
  box-shadow: inset 0 0 14px var(--glow, #ffe888), 0 0 26px 8px var(--glow, #ffe888), 0 0 60px 18px rgba(255, 255, 255, 0.25);
}
.tw-lock-centre { position: absolute; left: 0; top: 0; transform: translate(-50%, -50%); width: 240px; height: 120px; display: flex; align-items: center; justify-content: center; }
.tw-lock-count {
  font-family: var(--font-pixel, 'Press Start 2P', monospace); font-size: 64px; color: #ffe888; line-height: 1;
  text-shadow: 0 0 16px rgba(255, 220, 120, 0.95), 0 0 40px rgba(255, 200, 90, 0.6), 0 3px 0 #000;
}
.tw-lock-count.tw-count-pulse { animation: tw-count 0.7s ease-out; }
@keyframes tw-count { 0% { transform: scale(0.5); opacity: 0; } 25% { transform: scale(1.25); opacity: 1; } 100% { transform: scale(1); opacity: 1; } }
.tw-lock.tw-lock-pulse .tw-lock-plate { animation: tw-plate-pulse 0.7s ease-out; }
@keyframes tw-plate-pulse { 0% { filter: brightness(1); } 25% { filter: brightness(1.8) drop-shadow(0 0 30px rgba(255, 220, 120, 0.9)); } 100% { filter: brightness(1); } }
.tw-lock.tw-lock-shake { animation: tw-shake 0.5s ease; }
@keyframes tw-shake { 0%, 100% { margin-left: 0; } 20% { margin-left: -8px; } 40% { margin-left: 8px; } 60% { margin-left: -5px; } 80% { margin-left: 5px; } }
/* "your answer so far": five small sockets in the plate's centre (the v1 ids and classes) */
.tw-lock-slots { display: none; gap: 6px; }
.tw-lock.slots-on:not(.counting) .tw-lock-slots { display: flex; }
.fs-tower .tower-gate-slot {
  width: 40px; height: 40px; border: 2px solid #8a6518; border-radius: 4px; box-sizing: border-box;
  background: radial-gradient(ellipse at 50% 40%, rgba(106, 58, 138, 0.4) 0%, transparent 70%), linear-gradient(160deg, #2c2046 0%, #1a1230 100%);
  box-shadow: inset 0 3px 6px rgba(0, 0, 0, 0.7), 0 0 0 1px rgba(0, 0, 0, 0.7);
  display: flex; align-items: center; justify-content: center; overflow: hidden;
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.fs-tower .tower-gate-slot img { width: 100%; height: 100%; display: block; }
.fs-tower .tower-gate-slot.filled { border-color: #b48ae0; box-shadow: inset 0 0 8px rgba(154, 90, 191, 0.6), 0 0 8px rgba(154, 90, 191, 0.45); }
.fs-tower .tower-gate-slot.success { border-color: #58a248; box-shadow: 0 0 10px rgba(88, 162, 72, 0.8); }
.fs-tower .tower-gate-slot.wrong { border-color: #ca5a48; box-shadow: 0 0 10px rgba(202, 90, 72, 0.8); }
.fs-tower .tower-gate-slot.tw-pop { animation: tw-pop 0.4s cubic-bezier(0.3, 1.5, 0.5, 1); }
@keyframes tw-pop { 0% { transform: scale(0.6); } 100% { transform: scale(1); } }
/* The 3x3 answer grid rises from the flagstones in front of the door */
.tw-gate-grid {
  position: absolute; left: 480px; top: 535px; width: 258px; transform: translate(-50%, -100%) translateY(240px); opacity: 0;
  display: grid; grid-template-columns: repeat(3, 70px); gap: 10px; padding: 12px; box-sizing: content-box;
  background: linear-gradient(160deg, rgba(58, 42, 90, 0.75) 0%, rgba(30, 22, 48, 0.9) 100%);
  border: 3px solid #c5952e; border-radius: 6px; pointer-events: auto;
  box-shadow: inset 0 0 0 1px rgba(8, 10, 16, 0.8), inset 0 0 0 2px #8a6518, inset 0 0 28px rgba(106, 58, 138, 0.45), 0 0 0 1px rgba(0, 0, 0, 0.7), 0 8px 24px rgba(0, 0, 0, 0.6);
  transition: transform 0.9s cubic-bezier(0.2, 0.8, 0.3, 1), opacity 0.5s ease;
}
.tw-gate-grid.up { transform: translate(-50%, -100%) translateY(0); opacity: 1; }
.tw-gate-grid.disabled { pointer-events: none; }
.tw-gate-grid.disabled .tower-rune-btn { filter: brightness(0.6); }
.fs-tower .tower-rune-btn {
  width: 70px; height: 70px; padding: 4px; box-sizing: border-box; border-radius: 5px; cursor: pointer;
  background: linear-gradient(155deg, #3a2a5a 0%, #241a3a 100%); border: 2px solid #6a4a9a;
  box-shadow: inset 0 1px 0 rgba(180, 140, 230, 0.3), inset 0 0 12px rgba(106, 58, 138, 0.45), 0 3px 0 #14102a, 0 0 8px rgba(106, 58, 138, 0.35);
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, filter 0.3s ease;
  display: flex; align-items: center; justify-content: center; font-size: 0;
}
.fs-tower .tower-rune-btn img { width: 100%; height: 100%; border-radius: 3px; }
.fs-tower .tower-rune-btn:active { transform: scale(1.06); border-color: #ffe888; box-shadow: inset 0 0 14px rgba(140, 85, 180, 0.55), 0 3px 0 #14102a, 0 0 14px rgba(255, 220, 120, 0.6); }
.fs-tower .tower-rune-btn.wrong { border-color: #ca5a48; animation: tw-shake 0.4s ease; }

/* ---- The stairs: four rune steps on the stairway (the v1 ids and classes), lit as the climb passes ---- */
.tw-stairs-box { position: absolute; left: 0; top: 0; width: 960px; height: 1080px; pointer-events: none; }
.tw-stairs-box.disabled .tower-stair-rune { pointer-events: none; }
.fs-tower .tower-stair-rune {
  position: absolute; width: 96px; height: 96px; transform: translate(-50%, -100%) rotate(-6deg); padding: 6px; box-sizing: border-box; cursor: pointer; pointer-events: auto;
  background: linear-gradient(160deg, #3a2a5a 0%, #241a3a 100%); border: 3px solid #5a4080; border-radius: 8px;
  box-shadow: inset 0 1px 0 rgba(180, 140, 230, 0.25), inset 0 0 14px rgba(106, 58, 138, 0.4), 0 6px 0 #14102a, 0 10px 14px rgba(0, 0, 0, 0.6);
  transition: background 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, transform 0.15s ease; font-size: 0;
}
.fs-tower .tower-stair-rune img { width: 100%; height: 100%; border-radius: 4px; opacity: 0.5; transition: opacity 0.2s ease, filter 0.2s ease; }
.fs-tower .tower-stair-rune img { position: relative; inset: auto; }
.fs-tower .tower-stair-rune.glow, .fs-tower .tower-stair-rune.pressed {
  border-color: #fff; background: linear-gradient(160deg, #3a2a5a 0%, #241a3a 100%); transform: translate(-50%, -100%) rotate(-6deg) scale(1.12);
  box-shadow: 0 0 30px 6px var(--glow, #ffe888), inset 0 0 16px var(--glow, #ffe888), 0 6px 0 #14102a;
}
.fs-tower .tower-stair-rune.glow img, .fs-tower .tower-stair-rune.pressed img { opacity: 1; filter: brightness(1.35) saturate(1.2); }
.fs-tower .tower-stair-rune.wrong { border-color: #ca5a48; background: rgba(202, 90, 72, 0.3); animation: tw-shake 0.4s ease; }
.fs-tower .tower-stair-rune.all-lit, .tw-stairs-box.climb-lit .tower-stair-rune { border-color: #58a248; background: rgba(88, 162, 72, 0.2); box-shadow: 0 0 20px rgba(88, 162, 72, 0.7), 0 6px 0 #14102a; }
.fs-tower .tower-stair-rune.all-lit img, .tw-stairs-box.climb-lit .tower-stair-rune img { opacity: 1; filter: brightness(1.4); }

/* ---- The puzzle panel: on its painted frame inside the room, sizes in design px ---- */
.tw-panel { position: absolute; inset: 0; display: none; align-items: center; justify-content: center; z-index: 800; pointer-events: none; }
.tw-panel.on { display: flex; }
.tw-panel-box {
  position: relative; width: 720px; height: 480px; pointer-events: auto;
  background: url('../assets/images/puzzles/level7/cipher-frame.webp') center / 100% 100% no-repeat;
  filter: drop-shadow(0 12px 24px rgba(0, 0, 0, 0.7));
}
.tw-panel-box.frame-assembly { background-image: url('../assets/images/puzzles/level7/code-assembly-frame.webp'); }
/* aside: the panel parked small on the left of the room (the throne room's assembly, so Princess Pumpkin watches from her cage on the right) */
.tw-panel.aside { inset: auto; left: 28px; top: 50%; width: 720px; height: 480px; transform: translateY(-50%) scale(0.74); transform-origin: left center; }
.tw-dim.on.aside { background: rgba(4, 2, 12, 0.28); }
.tw-panel-box.tw-panel-in { animation: tw-panel-in 0.45s cubic-bezier(0.2, 0.8, 0.3, 1); }
.tw-panel-box.tw-panel-out { animation: tw-panel-out 0.38s ease-in forwards; }
@keyframes tw-panel-in { from { transform: scale(0.7) translateY(30px); opacity: 0; } to { transform: scale(1) translateY(0); opacity: 1; } }
@keyframes tw-panel-out { to { transform: scale(0.8) translateY(40px); opacity: 0; } }
.tw-panel-content {
  position: absolute; inset: 66px 88px 58px 88px; display: flex; flex-direction: column; align-items: center; justify-content: center;
  color: #eae4d4; text-shadow: 0 0 6px rgba(0, 0, 0, 0.9); font-family: var(--font-pixel, 'Press Start 2P', monospace);
}
.tw-panel-content > div { width: 100%; }
/* The v1 puzzle stages, restyled in design px: same ids, classes and rules */
.tw-panel .tower-stage-title { font-size: 12px; color: #ffe888; text-shadow: 0 0 8px rgba(218, 186, 106, 0.6), 0 0 2px #000; margin: 0 0 12px; text-align: center; line-height: 1.6; }
.tw-panel .tower-stage-hint, .tw-panel .tower-cipher-instructions, .tw-panel .tower-assembly-instructions, .tw-panel .tower-gem-feedback { font-size: 9px; color: rgba(234, 228, 212, 0.85); text-align: center; margin: 8px 0 0; line-height: 1.7; }
.tw-panel .tower-gem-feedback { min-height: 14px; margin: 4px 0 0; }
.tw-panel .tower-gem-feedback.success { color: #8ee49a; }
.tw-panel .tower-gem-feedback.error { color: #ff9a8a; }
/* cipher */
.tw-panel .tower-cipher { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.tw-panel .tower-cipher .tower-stage-title { margin-bottom: 4px; }
.tw-panel .tower-cipher-words { display: flex; gap: 28px; justify-content: center; margin: 0; }
.tw-panel .tower-cipher-word { display: flex; gap: 6px; }
.tw-panel .tower-cipher-cell {
  width: 46px; height: 56px; box-sizing: border-box; border: 2px solid #daba6a; border-radius: 4px; font-size: 16px; color: #eae4d4;
  background: linear-gradient(165deg, #3a2a5a 0%, #241a3a 100%); display: flex; align-items: center; justify-content: center;
  box-shadow: inset 0 1px 0 rgba(180, 140, 230, 0.2), inset 0 0 10px rgba(106, 58, 138, 0.35), 0 2px 0 #14102a;
}
.tw-panel .tower-cipher-cell.cipher-blank { background: linear-gradient(165deg, #4c3066 0%, #2e1c42 100%); border-color: #6a3a8a; cursor: pointer; transition: border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease; }
.tw-panel .tower-cipher-cell.cipher-blank.selected { border-color: #ffe888; box-shadow: inset 0 0 12px rgba(140, 85, 180, 0.5), 0 2px 0 #14102a, 0 0 12px rgba(255, 220, 120, 0.6); }
.tw-panel .tower-cipher-cell.solved { border-color: #58a248; background: linear-gradient(165deg, rgba(74, 170, 90, 0.35) 0%, rgba(30, 60, 36, 0.6) 100%); color: #8ee49a; box-shadow: inset 0 0 10px rgba(74, 170, 90, 0.4), 0 2px 0 #14102a, 0 0 12px rgba(74, 170, 90, 0.45); }
.tw-panel .tower-cipher-cell.wrong { border-color: #ca5a48; animation: tw-shake 0.4s ease; }
.tw-panel .cipher-symbol { font-size: 22px; color: #ffe888; }
.tw-panel .cipher-resolved { font-size: 16px; color: #ffe888; }
.tw-panel .tower-cipher-keyboard {
  display: flex; flex-wrap: wrap; gap: 4px; justify-content: center; width: 480px; padding: 6px; box-sizing: border-box;
  background: linear-gradient(160deg, rgba(58, 42, 90, 0.45) 0%, rgba(36, 26, 58, 0.7) 100%), rgba(12, 16, 22, 0.88);
  border: 2px solid #c5952e; border-radius: 6px; box-shadow: inset 0 0 0 1px rgba(8, 10, 16, 0.8), inset 0 0 0 2px #8a6518, inset 0 0 22px rgba(106, 58, 138, 0.3);
}
.tw-panel .tower-cipher-keyboard.disabled { pointer-events: none; opacity: 0.5; }
.tw-panel .tower-cipher-key {
  width: 34px; height: 33px; box-sizing: border-box; font-family: inherit; font-size: 11px; color: #ffe888; cursor: pointer; border-radius: 3px;
  background: linear-gradient(165deg, #3a2a5a 0%, #241a3a 100%); border: 2px solid #5a4080; box-shadow: inset 0 1px 0 rgba(180, 140, 230, 0.25), 0 3px 0 #14102a; padding: 0;
}
.tw-panel .tower-cipher-key:active { border-color: #ffe888; transform: translateY(1px); box-shadow: inset 0 1px 0 rgba(200, 165, 245, 0.35), 0 2px 0 #14102a, 0 0 8px rgba(180, 130, 230, 0.45); }
.tw-panel .tower-cipher-legend {
  display: flex; gap: 22px; justify-content: center; font-size: 11px; padding: 4px 14px;
  background: linear-gradient(160deg, rgba(58, 42, 90, 0.35) 0%, rgba(36, 26, 58, 0.55) 100%), rgba(12, 16, 22, 0.88);
  border: 2px solid #c5952e; border-radius: 4px; box-shadow: inset 0 0 0 1px rgba(8, 10, 16, 0.8), inset 0 0 0 2px #8a6518;
}
.tw-panel .legend-item { padding: 3px 8px; border-radius: 3px; border: 1px solid transparent; }
.tw-panel .legend-item.active { background: rgba(218, 186, 106, 0.25); border-color: #daba6a; }
/* gems */
.tw-panel .tower-gems { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.tw-panel .tower-gem-values {
  font-size: 11px; color: rgba(234, 228, 212, 0.95); padding: 6px 14px; line-height: 1.6; white-space: nowrap;
  background: linear-gradient(160deg, rgba(58, 42, 90, 0.4) 0%, rgba(36, 26, 58, 0.6) 100%), rgba(12, 16, 22, 0.88);
  border: 2px solid #c5952e; border-radius: 4px; box-shadow: inset 0 0 0 1px rgba(8, 10, 16, 0.8), inset 0 0 0 2px #8a6518;
}
.tw-panel .tower-gem-values .tower-gem { width: 22px; height: 22px; margin: 0 2px 0 6px; }
.tw-panel .tower-gem-progress { display: flex; gap: 10px; margin: 0; }
.tw-panel .tower-gem-slot {
  width: 28px; height: 28px; box-sizing: border-box; border: 2px solid #5a4080; border-radius: 50%; font-size: 12px; color: #8ee49a;
  background: radial-gradient(circle at 50% 40%, rgba(106, 58, 138, 0.4) 0%, transparent 70%), linear-gradient(160deg, #2c2046 0%, #181028 100%);
  display: flex; align-items: center; justify-content: center; box-shadow: inset 0 2px 6px rgba(0, 0, 0, 0.7);
  transition: border-color 0.3s ease, box-shadow 0.3s ease;
}
.tw-panel .tower-gem-slot.filled { border-color: #58a248; box-shadow: inset 0 0 8px rgba(74, 170, 90, 0.5), 0 0 10px rgba(88, 162, 72, 0.6); }
.tw-panel .tower-gem-problem {
  padding: 10px 18px; min-height: 40px;
  background: linear-gradient(160deg, rgba(58, 42, 90, 0.45) 0%, rgba(36, 26, 58, 0.7) 100%), rgba(12, 16, 22, 0.88);
  border: 2px solid #c5952e; border-radius: 8px; box-shadow: inset 0 0 0 1px rgba(8, 10, 16, 0.8), inset 0 0 0 2px #8a6518, inset 0 0 20px rgba(106, 58, 138, 0.3);
}
.tw-panel .gem-equation { font-size: 18px; display: flex; align-items: center; gap: 6px; }
.tw-panel .gem-equation .tower-gem { width: 44px !important; height: 44px !important; object-fit: contain; }
.tw-panel .gem-equation .mystery { color: #d8b0ff; background: rgba(106, 58, 138, 0.3); border: 2px dashed #8a5aaa; border-radius: 6px; font-size: 30px; line-height: 1; padding: 2px 10px; min-width: 40px; display: inline-flex; justify-content: center; align-items: center; }
.tw-panel .tower-gem-input { display: flex; flex-wrap: wrap; gap: 8px; justify-content: center; align-items: center; margin-top: 4px; }
.tw-panel .tower-gem-pick {
  width: 64px; height: 64px; box-sizing: border-box; border-radius: 8px; cursor: pointer; padding: 6px;
  background: linear-gradient(160deg, #3a2a5a 0%, #241a3a 100%); border: 3px solid #5a4080;
  box-shadow: inset 0 1px 0 rgba(180, 140, 230, 0.25), inset 0 0 12px rgba(106, 58, 138, 0.4), 0 4px 0 #14102a; display: flex; align-items: center; justify-content: center;
  transition: transform 0.15s ease, border-color 0.15s ease;
}
.tw-panel .tower-gem-pick .tower-gem { width: 44px !important; height: 44px !important; }
.tw-panel .tower-gem-pick:active { transform: scale(1.06); border-color: #ffe888; }
.tw-panel .tower-gem-pick.correct { border-color: #58a248; background: rgba(88, 162, 72, 0.3); }
.tw-panel .tower-gem-pick.wrong { border-color: #ca5a48; animation: tw-shake 0.4s ease; }
.tw-panel .gem-number-display {
  min-width: 56px; font-size: 26px; color: #ffe888; padding: 6px 12px; border: 2px solid #daba6a; border-radius: 4px; text-align: center; margin-right: 12px;
  background: radial-gradient(ellipse at 50% 30%, rgba(106, 58, 138, 0.35) 0%, transparent 70%), rgba(8, 6, 16, 0.85);
  box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.7);
}
.tw-panel .gem-number-display.correct { border-color: #58a248; color: #8ee49a; }
.tw-panel .gem-number-display.wrong { border-color: #ca5a48; color: #ff9a8a; animation: tw-shake 0.4s ease; }
.tw-panel .gem-number-pad { display: grid; grid-template-columns: repeat(6, 52px); gap: 6px; }
.tw-panel .gem-num-key {
  height: 40px; box-sizing: border-box; font-family: inherit; font-size: 14px; color: #ffe888; cursor: pointer; border-radius: 4px; padding: 0;
  background: linear-gradient(165deg, #3a2a5a 0%, #241a3a 100%); border: 2px solid #5a4080; box-shadow: inset 0 1px 0 rgba(180, 140, 230, 0.25), 0 3px 0 #14102a;
}
.tw-panel .gem-num-key:active { border-color: #ffe888; }
.tw-panel .gem-num-key.num-go { background: linear-gradient(165deg, #2e5a32 0%, #1c3a22 100%); border-color: #58a248; }
.tw-panel .gem-num-key.num-del { background: linear-gradient(165deg, #5a2a3a 0%, #381a26 100%); border-color: #7a4a5a; }
/* riddle + anagram */
.tw-panel .tower-riddle { display: flex; flex-direction: column; align-items: center; gap: 10px; }
.tw-panel .tower-riddle-text {
  font-size: 11px; line-height: 1.9; text-align: center; padding: 10px 18px; width: 500px; box-sizing: border-box;
  background: linear-gradient(160deg, rgba(58, 42, 90, 0.45) 0%, rgba(36, 26, 58, 0.7) 100%), rgba(12, 16, 22, 0.88);
  border: 2px solid #c5952e; border-radius: 6px; box-shadow: inset 0 0 0 1px rgba(8, 10, 16, 0.8), inset 0 0 0 2px #8a6518, inset 0 0 22px rgba(106, 58, 138, 0.3);
}
.tw-panel .tower-riddle-text strong { color: #ffe888; }
.tw-panel .tower-anagram-slots { display: flex; gap: 10px; }
.tw-panel .tower-anagram-slot {
  width: 58px; height: 68px; box-sizing: border-box; border: 3px dashed #daba6a; border-radius: 6px; font-size: 22px; color: #ffe888; cursor: pointer;
  background: radial-gradient(ellipse at 50% 40%, rgba(106, 58, 138, 0.35) 0%, transparent 70%), linear-gradient(160deg, #2c2046 0%, #1a1230 100%);
  display: flex; align-items: center; justify-content: center; box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.6);
  transition: border-color 0.3s ease, background 0.3s ease, box-shadow 0.3s ease;
}
.tw-panel .tower-anagram-slot.filled { border-style: solid; background: linear-gradient(160deg, #4c3066 0%, #2e1c42 100%); box-shadow: inset 0 0 12px rgba(140, 85, 180, 0.45), 0 0 8px rgba(154, 90, 191, 0.35); }
.tw-panel .tower-anagram-slot.correct { border-color: #58a248; background: linear-gradient(160deg, rgba(74, 170, 90, 0.35) 0%, rgba(30, 60, 36, 0.6) 100%); box-shadow: 0 0 15px rgba(88, 162, 72, 0.55); }
.tw-panel .tower-anagram-slot.wrong { border-color: #ca5a48; animation: tw-shake 0.4s ease; }
.tw-panel .tower-anagram-tiles { display: flex; gap: 10px; justify-content: center; }
.tw-panel .tower-anagram-tile {
  width: 58px; height: 58px; box-sizing: border-box; font-family: inherit; font-size: 20px; color: #ffe888; cursor: pointer; border-radius: 6px; padding: 0;
  background: linear-gradient(165deg, #3a2a5a 0%, #241a3a 100%); border: 3px solid #daba6a;
  box-shadow: inset 0 1px 0 rgba(180, 140, 230, 0.25), inset 0 0 10px rgba(106, 58, 138, 0.35), 0 3px 0 #14102a;
  transition: transform 0.15s ease, box-shadow 0.15s ease;
}
.tw-panel .tower-anagram-tile:active { transform: scale(1.08) translateY(-2px); }
/* assembly */
.tw-panel .tower-assembly { display: flex; flex-direction: column; align-items: center; gap: 12px; }
.tw-panel .tower-assembly-frame { padding: 14px 22px; background: rgba(12, 16, 22, 0.55); border: 3px solid #c5952e; border-radius: 10px; box-shadow: inset 0 0 0 2px #8a6518, inset 0 0 26px rgba(106, 58, 138, 0.45), 0 0 30px rgba(255, 220, 120, 0.25); }
.tw-panel .tower-assembly-slots { display: flex; gap: 12px; align-items: center; justify-content: center; }
.tw-panel .tower-assembly-slot {
  min-width: 74px; height: 84px; box-sizing: border-box; border: 3px dashed #daba6a; border-radius: 8px; font-size: 26px; color: #ffe888; padding: 0 12px;
  background: radial-gradient(ellipse at 50% 40%, rgba(106, 58, 138, 0.4) 0%, transparent 70%), linear-gradient(160deg, #2c2046 0%, #181028 100%);
  display: flex; align-items: center; justify-content: center; gap: 4px; box-shadow: inset 0 3px 8px rgba(0, 0, 0, 0.6), inset 0 0 16px rgba(106, 58, 138, 0.45);
  transition: border-color 0.4s ease, box-shadow 0.4s ease;
}
.tw-panel .tower-assembly-slot[data-double="1"] { min-width: 130px; }
.tw-panel .tower-assembly-slot img { height: 56px; width: auto; }
.tw-panel .tower-assembly-slot.filled { border-style: solid; border-color: #ffe888; box-shadow: inset 0 0 14px rgba(255, 220, 120, 0.35), 0 0 14px rgba(255, 220, 120, 0.55); }
.tw-panel .tower-assembly-slot.snap { animation: tw-snap 0.4s ease; }
.tw-panel .tower-assembly-slot.complete { border-color: #58a248; box-shadow: inset 0 0 14px rgba(74, 170, 90, 0.4), 0 0 22px rgba(255, 220, 120, 0.8); }
@keyframes tw-snap { 0% { transform: scale(1.25); } 60% { transform: scale(0.94); } 100% { transform: scale(1); } }
.tw-panel .tower-assembly-fragments { display: flex; gap: 14px; justify-content: center; }
.tw-panel .tower-fragment-btn {
  min-width: 74px; height: 74px; box-sizing: border-box; padding: 0 10px; font-family: inherit; font-size: 22px; color: #ffe888; cursor: pointer; border-radius: 8px;
  background: linear-gradient(160deg, #4c3066 0%, #2e1c42 100%); border: 3px solid #daba6a; display: flex; align-items: center; justify-content: center; gap: 4px;
  box-shadow: inset 0 1px 0 rgba(200, 165, 245, 0.3), inset 0 0 12px rgba(140, 85, 180, 0.4), 0 3px 0 #14102a, 0 0 12px rgba(255, 220, 120, 0.3);
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.tw-panel .tower-fragment-btn img { height: 50px; width: auto; }
.tw-panel .tower-fragment-btn:active { transform: scale(1.06) translateY(-2px); }
.tw-panel .tower-fragment-btn.placed { opacity: 0.3; pointer-events: none; transform: scale(0.85); }
.tw-panel .tower-fragment-btn.tw-arrived { animation: tw-pop 0.5s cubic-bezier(0.3, 1.5, 0.5, 1); }
.tw-panel .tower-fragment-btn.tw-pending { visibility: hidden; }
/* the fx-layer particles inside the stage sit above the panel */
.tw-fx { position: absolute; inset: 0; pointer-events: none; z-index: 900; }
.tw-fx > * { position: absolute; }

/* ---- The letter reveal (call 5) and the fragment bar ---- */
.tw-plaque .fs-body > img { transition: filter 0.6s ease; }
.tw-plaque.cracked .fs-body > img { filter: brightness(1.15) drop-shadow(0 0 10px rgba(255, 220, 120, 0.75)); }
.tw-plaque .fs-body.tw-plaque-crack { animation: tw-plaque-crack 1.2s ease-out; }
@keyframes tw-plaque-crack {
  0% { filter: brightness(1); transform: scale(1); }
  15% { filter: brightness(2.2) drop-shadow(0 0 24px rgba(255, 235, 160, 1)); transform: scale(1.06) translateX(-3px); }
  30% { filter: brightness(1.6); transform: scale(1.04) translateX(3px); }
  45% { filter: brightness(2) drop-shadow(0 0 20px rgba(255, 235, 160, 0.9)); transform: scale(1.05); }
  100% { filter: brightness(1.15); transform: scale(1); }
}
.tw-letter-fly { position: absolute; height: 110px; width: auto; transform: translate(-50%, -50%); filter: drop-shadow(0 0 14px rgba(255, 220, 120, 0.95)) drop-shadow(0 0 30px rgba(255, 200, 90, 0.5)); z-index: 950; }
.tw-fragbar {
  position: absolute; top: 0.9rem; right: 0.9rem; z-index: 40; display: flex; gap: 0; padding: 0.35rem 0.55rem; box-sizing: border-box;
  width: clamp(150px, 20vw, 210px); height: clamp(42px, 5.6vw, 58px); align-items: center; justify-content: space-between;
  background: url('../assets/images/tower-v2/frag-bar.webp') center / 100% 100% no-repeat;
  filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8)); transition: opacity 0.6s ease, transform 0.6s ease;
}
.tw-fragbar.hidden { opacity: 0; transform: translateY(-16px); pointer-events: none; }
.tw-fragbar.tw-bar-glow { animation: tw-bar-glow 0.9s ease-out; }
@keyframes tw-bar-glow { 0% { filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8)); } 30% { filter: drop-shadow(0 0 16px rgba(255, 225, 130, 1)); } 100% { filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.8)); } }
.tw-socket { width: 19%; aspect-ratio: 1 / 1; display: flex; align-items: center; justify-content: center; }
.tw-socket img { width: 100%; height: 100%; object-fit: contain; filter: drop-shadow(0 0 5px rgba(255, 220, 120, 0.8)); }
.tw-socket.tw-land { animation: tw-land 0.7s cubic-bezier(0.3, 1.5, 0.5, 1); }
@keyframes tw-land { 0% { transform: scale(1.6); } 100% { transform: scale(1); } }

/* ---- The Witch ---- */
.tw-witch { transition: opacity 0.6s ease; }
.tw-witch .fs-body { position: relative; }
.tw-witch-figure { position: relative; transform-origin: 50% 88%; }
.tw-witch img.tw-witch-img { display: block; height: var(--h); width: auto; filter: drop-shadow(0 0 10px rgba(120, 255, 150, 0.3)); -webkit-user-drag: none; user-select: none; }
/* Her motion is pose cuts (the six swap poses) on a slow, straight bob -- the sprite is never bent, skewed or scaled */
.tw-witch .tw-witch-figure { animation: tw-witch-idle 4.8s ease-in-out infinite; }
.tw-witch.talking .tw-witch-figure { animation: tw-witch-talk 0.7s ease-in-out infinite; }
@keyframes tw-witch-idle { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-2px); } }
@keyframes tw-witch-talk { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-1.5px); } }
.tw-witch-aura {
  position: absolute; left: 50%; top: 62%; width: 220px; height: 220px; transform: translate(-50%, -50%); border-radius: 50%;
  background: radial-gradient(circle, rgba(120, 255, 150, 0.35) 0%, rgba(90, 200, 120, 0.12) 40%, rgba(60, 160, 90, 0) 70%);
  mix-blend-mode: screen; animation: tw-aura 3.6s ease-in-out infinite; pointer-events: none;
}
@keyframes tw-aura { 0%, 100% { opacity: 0.5; transform: translate(-50%, -50%) scale(1); } 50% { opacity: 0.8; transform: translate(-50%, -50%) scale(1.04); } }
.tw-witch.pose-panicked .tw-witch-aura { animation-duration: 0.9s; background: radial-gradient(circle, rgba(200, 120, 255, 0.5) 0%, rgba(150, 80, 220, 0.15) 40%, transparent 70%); }
.tw-witch.pose-cackling img.tw-witch-img, .tw-witch.pose-casting img.tw-witch-img { filter: drop-shadow(0 0 14px rgba(120, 255, 150, 0.45)); }
.fs-prop.tw-in { animation: tw-in 1.4s ease-out; }
@keyframes tw-in { 0% { opacity: 0; filter: brightness(3) blur(3px); transform: translateY(8px) scale(0.92); } 50% { opacity: 1; filter: brightness(1.6) blur(0); } 100% { opacity: 1; filter: none; transform: none; } }
.fs-prop.tw-out { animation: tw-out 0.9s ease-in forwards; }
@keyframes tw-out { to { opacity: 0; filter: brightness(2.5) blur(6px); transform: scale(1.06); } }
.tw-witch.tw-glitching .tw-witch-figure { animation: tw-glitch 0.18s steps(2) infinite; }
@keyframes tw-glitch {
  0% { transform: translateX(-6px) skewX(4deg); filter: hue-rotate(60deg) contrast(1.5); }
  50% { transform: translateX(6px) skewX(-4deg); filter: hue-rotate(-60deg) contrast(1.6) brightness(1.3); }
  100% { transform: translateX(-3px); filter: hue-rotate(20deg); }
}
.tw-witch.tw-shattering .tw-witch-figure { animation: tw-shatter 1.5s ease-in forwards; }
@keyframes tw-shatter { 0% { opacity: 1; filter: brightness(1.8); } 40% { opacity: 0.6; filter: brightness(2.4) blur(2px); transform: scale(1.08); } 100% { opacity: 0; filter: brightness(3) blur(12px); transform: scale(1.3); } }
.tw-pixel { position: absolute; image-rendering: pixelated; box-shadow: 0 0 6px rgba(216, 176, 255, 0.7); z-index: 960; }

/* ---- Princess Pumpkin caged (call 6): a slow float, the interference shimmer, the reach, the glitch ---- */
.tw-pp .fs-body { position: relative; }
.tw-pp-figure { position: relative; transform-origin: 50% 100%; animation: tw-pp-float 4.6s ease-in-out infinite; }
.tw-pp.talking .tw-pp-figure { animation-duration: 2.8s; }
.tw-pp.freed .tw-pp-figure { animation: tw-pp-float-free 3.8s ease-in-out infinite; }
@keyframes tw-pp-float { 0%, 100% { transform: translateY(0) rotate(-1deg); } 50% { transform: translateY(-9px) rotate(1deg); } }
@keyframes tw-pp-float-free { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-5px); } }
.tw-pp img.tw-pp-img, .tw-pp-rest img, .tw-helper img { display: block; height: var(--h); width: auto; -webkit-user-drag: none; user-select: none; }
.tw-pp img.tw-pp-img { filter: drop-shadow(0 0 8px rgba(255, 220, 120, 0.45)); }
.tw-pp.freed img.tw-pp-img { filter: drop-shadow(0 0 14px rgba(255, 230, 150, 0.85)); }
/* the "digital interference": screen-blended scan stripes that thin as the letters are found */
.tw-shimmer {
  position: absolute; inset: 0; pointer-events: none; mix-blend-mode: screen; opacity: calc(var(--shimmer, 1) * 0.7);
  background: repeating-linear-gradient(to bottom, rgba(255, 200, 120, 0) 0 3px, rgba(255, 220, 160, 0.55) 3px 4px, rgba(120, 200, 255, 0.35) 4px 5px, rgba(255, 200, 120, 0) 5px 8px);
  -webkit-mask-image: url('../assets/images/characters/princess-pumpkin/sprite-caged.webp'); mask-image: url('../assets/images/characters/princess-pumpkin/sprite-caged.webp');
  -webkit-mask-size: 100% 100%; mask-size: 100% 100%; animation: tw-scan 2.4s linear infinite; transition: opacity 1.2s ease;
}
.tw-pp.pose-reach .tw-shimmer { -webkit-mask-image: url('../assets/images/characters/princess-pumpkin/sprite-reach.webp'); mask-image: url('../assets/images/characters/princess-pumpkin/sprite-reach.webp'); }
.tw-pp.pose-front .tw-shimmer { -webkit-mask-image: url('../assets/images/characters/princess-pumpkin/sprite-transparent.webp'); mask-image: url('../assets/images/characters/princess-pumpkin/sprite-transparent.webp'); }
.tw-pp.freed .tw-shimmer { opacity: 0; }
@keyframes tw-scan { from { background-position: 0 0; } to { background-position: 0 16px; } }
.tw-pp-figure.tw-pp-glitch { animation: tw-pp-glitch 0.9s steps(3) !important; }
@keyframes tw-pp-glitch {
  0% { transform: translateX(-5px) skewX(3deg); filter: brightness(1.6) hue-rotate(30deg); opacity: 0.7; }
  33% { transform: translateX(5px) skewX(-3deg); filter: brightness(1.2); opacity: 1; }
  66% { transform: translateX(-3px); filter: brightness(1.8) hue-rotate(-30deg); opacity: 0.6; }
  100% { transform: none; filter: none; opacity: 1; }
}
.tw-pp-figure.tw-pp-flash img { animation: tw-pp-flash 0.7s ease-out; }
@keyframes tw-pp-flash { 0% { filter: brightness(1); } 30% { filter: brightness(4) drop-shadow(0 0 30px #fff); } 100% { filter: brightness(1); } }
.tw-pp-glow {
  position: absolute; left: 50%; top: 55%; width: 200px; height: 200px; transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(255, 215, 130, 0.5) 0%, rgba(255, 190, 90, 0.18) 40%, rgba(255, 170, 60, 0) 70%);
  mix-blend-mode: screen; animation: tw-aura 4.2s ease-in-out infinite;
}
.tw-pp-glow.gold { width: 260px; height: 260px; background: radial-gradient(circle, rgba(255, 236, 170, 0.6) 0%, rgba(255, 210, 100, 0.22) 40%, rgba(255, 200, 80, 0) 70%); }
/* the cage: a warm hum glow behind it; it dissolves upward when the spell breaks */
.tw-cage .fs-body > img { filter: drop-shadow(0 0 10px rgba(255, 215, 120, 0.7)); }
.tw-cage .fs-body::before {
  content: ''; position: absolute; left: 50%; top: 50%; width: 300px; height: 320px; transform: translate(-50%, -50%); border-radius: 50%; pointer-events: none;
  background: radial-gradient(ellipse, rgba(255, 210, 120, 0.32) 0%, rgba(255, 180, 80, 0.1) 45%, rgba(255, 160, 60, 0) 70%);
  mix-blend-mode: screen; animation: tw-aura 3.2s ease-in-out infinite;
}
.tw-cage.tw-cage-gone .fs-body { animation: tw-cage-gone 1.8s ease-in forwards; }
@keyframes tw-cage-gone { 0% { opacity: 1; filter: brightness(1); } 30% { filter: brightness(2.5) drop-shadow(0 0 30px #ffe888); } 100% { opacity: 0; transform: translateY(-90px) scale(1.1); filter: brightness(3) blur(6px); } }

/* ---- The spell breaks: the crack overlay in three stages ---- */
.tw-crack { position: absolute; inset: 0; pointer-events: none; z-index: 930; opacity: 0; transform: scale(0.3); transition: opacity 0.8s ease, transform 0.8s ease; mix-blend-mode: screen; }
.tw-crack img { width: 100%; height: 100%; object-fit: cover; filter: brightness(1.4); image-rendering: auto; }
.tw-crack.stage-1 { opacity: 0.45; transform: scale(0.55) rotate(-2deg); }
.tw-crack.stage-2 { opacity: 0.75; transform: scale(0.82) rotate(1deg); }
.tw-crack.stage-3 { opacity: 0.85; transform: scale(1); animation: tw-crack-pulse 2.5s ease infinite; }
@keyframes tw-crack-pulse { 0%, 100% { opacity: 0.7; } 50% { opacity: 0.9; } }
.tw-block { position: absolute; background: #2a1a3a; box-shadow: inset 0 0 0 2px #4a3a6a; image-rendering: pixelated; z-index: 940; }

/* ---- The restored world: PP radiant, the six helpers arriving ---- */
.tw-pp-rest .fs-body { position: relative; }
.tw-pp-rest .tw-pp-figure { animation: tw-pp-float-free 3.8s ease-in-out infinite; }
.tw-pp-rest.talking .tw-pp-figure { animation-duration: 2.4s; }
.tw-pp-rest img { filter: drop-shadow(0 0 14px rgba(255, 230, 150, 0.85)); }
.tw-helper-figure { transform-origin: 50% 100%; animation: tw-breathe 3.6s ease-in-out infinite; }
.tw-helper.float .tw-helper-figure { animation: tw-pp-float 4.4s ease-in-out infinite; }
.tw-helper.talking .tw-helper-figure { animation: tw-cheer 0.7s ease-in-out infinite; }
@keyframes tw-breathe { 0%, 100% { transform: scaleY(1); } 50% { transform: scaleY(1.02) translateY(-1px); } }
@keyframes tw-cheer { 0%, 100% { transform: translateY(0) scale(1, 1); } 50% { transform: translateY(-14px) scale(0.96, 1.05); } }
.tw-helper img { filter: drop-shadow(0 4px 6px rgba(60, 40, 10, 0.4)); }
.fs-tower.tw-bright .tw-dust { display: none; }

/* ---- Reduced motion ---- */
@media (prefers-reduced-motion: reduce) {
  .tw-flash.on, .tw-glow .fs-body::after, .tw-wisp .fs-body, .tw-sunrays, .tw-witch-figure, .tw-witch-aura, .tw-pp-figure, .tw-shimmer, .tw-pp-glow,
  .tw-cage .fs-body::before, .tw-helper-figure, .tw-room-floor3.door-lit .tw-atmo::before, .tw-crack.stage-3, .fs-prop.tw-in, .fs-prop.tw-out { animation: none !important; }
  .tw-iris, .tw-white, .tw-dim, .tw-lock, .tw-gate-grid, .tw-fragbar, .tw-rune-cell, .tw-room-gate.push-in { transition: none; animation: none !important; }
  .tw-room-gate.push-in { transform: scale(1.4); }
  .tw-shimmer { opacity: 0.25; }
}
