/* BubbleSansRegula: bubble-style font used for Drippy's speech bubble. */
@font-face {
  font-family: 'BubbleSansRegula';
  src: url('../font/BubbleSansRegula.otf') format('opentype');
  font-display: swap;
}

/* ═══ DRIPPY PET STACK — vertical offset ═════════════════════════════════════
   Float the extra Drippy pets (Banker, Ghost, Arcane Familiar, Celestial,
   Dragon) 60px higher than their flow position. Using `top` (not transform)
   keeps the hover translateY and bob/wiggle animations intact, and since it's
   a relative offset it doesn't reflow Drippy itself. */
.banker-pet, .ghost-pet, .af-pet, .cel-pet, .dragon-pet{ top:-40px; }

/* ═══ ARCANE FAMILIAR PET ════════════════════════════════════════════════════
   A 25%-smaller, blue, star-dusted Drippy in a wizard hat. Lives above Drippy
   in #coach-avatar-col. #coach-wrap is pointer-events:none, so the pet re-
   enables pointer events on itself. Colors are fixed (skin-system independent). */
.af-pet{
  pointer-events:auto;
  cursor:pointer;
  position:relative;
  display:flex;
  flex-direction:column;
  align-items:center;
  width:40px;
  margin-bottom:16px; /* even spacing in the Drippy pet stack (+10px) */
  z-index:2;
  transition:transform 0.12s ease, filter 0.15s ease;
}
.af-pet:hover{ transform:translateY(-2px) scale(1.1); }
.af-pet.af-pet-real{ filter:drop-shadow(0 0 6px rgba(150,80,230,0.55)); }
.af-pet.af-pet-real:hover{ filter:drop-shadow(0 0 10px rgba(180,110,250,0.85)); }

.af-pet-hat{ position:absolute; left:50%; top:-14px; transform:translateX(-50%); width:32px; height:22px; z-index:3; pointer-events:none; }
.af-pet-hat svg{ width:100%; height:100%; display:block; }
/* transform-origin at the base so wiggle sways from the kiwis, like Drippy. */
.af-pet-body{ position:relative; width:34px; height:38px; transform-origin:50% 100%; }

.af-pet-cyl{
  position:absolute; left:50%; top:2px; transform:translateX(-50%);
  width:20px; height:32px; border-radius:10px;
  background:linear-gradient(to right,#b07ae8,#7a3fc8,#b07ae8);
  border:2px solid #8a4ad0;
  box-shadow:0 0 8px rgba(150,80,230,0.45), inset 0 0 9px rgba(0,0,0,0.3);
  z-index:2;
  /* 4.6s (vs Drippy's 4s) so the idle breathing drifts out of sync. */
  animation:afPetBreathe 4.6s ease-in-out infinite;
}
@keyframes afPetBreathe{ 0%,100%{ transform:translateX(-50%) scaleY(1) scaleX(1);} 50%{ transform:translateX(-50%) scaleY(1.02) scaleX(0.99);} }

/* Drippy-style one-shot liveliness (bob / wiggle), triggered by JS on the
   familiar's own timer. Applied to .af-pet-body so the cylinder + kiwis move
   together while the cylinder keeps its own breathe transform. --af-amp scales
   the amplitude, mirroring Drippy's --drippy-amp. */
.af-pet-bob{ animation:afPetBob 0.55s ease-in-out; }
.af-pet-wiggle{ animation:afPetWiggle 0.55s ease-in-out; }
/* Ghost's wiggle is slower/lazier than the other pets' quick jiggle. */
.ghost-body.af-pet-wiggle{ animation-duration:1.1s; }
@keyframes afPetBob{ 0%,100%{ transform:translateY(0);} 50%{ transform:translateY(calc(-5px * var(--af-amp,1)));} }
@keyframes afPetWiggle{ 0%,100%{ transform:rotate(0deg);} 25%{ transform:rotate(calc(7deg * var(--af-amp,1)));} 75%{ transform:rotate(calc(-7deg * var(--af-amp,1)));} }
.af-pet-shine{ position:absolute; left:4px; top:5px; width:3px; height:58%; border-radius:2px; background:linear-gradient(to bottom,rgba(255,255,255,0.5),transparent); }
.af-pet-eyes{ position:absolute; left:50%; top:9px; transform:translateX(-50%); display:flex; gap:5px; }
.af-pet-eye{ width:4px; height:5px; background:#fff; border-radius:50%; position:relative; }
.af-pet-eye::after{ content:''; position:absolute; left:50%; top:55%; transform:translate(-50%,-50%); width:2px; height:2px; background:#0a1830; border-radius:50%; }
.af-pet-mouth{ position:absolute; left:50%; top:19px; transform:translateX(-50%); width:10px; height:5px; }
.af-pet-kiwis{ position:absolute; left:50%; bottom:0; transform:translateX(-50%); width:34px; height:14px; }
.af-pet-kiwis svg{ position:absolute; width:13px; height:13px; bottom:0; }
.af-pet-kiwis svg:first-child{ left:1px; transform:rotate(90deg); }
.af-pet-kiwis svg:last-child{ right:1px; transform:rotate(-90deg); }

.af-pet-star{ position:absolute; color:#4f93ff; font-size:8px; text-shadow:0 0 4px rgba(80,150,255,0.95); pointer-events:none; animation:afPetStar 2.4s ease-in-out infinite; }
.af-pet-star1{ left:-1px; top:16px; animation-duration:2.3s; animation-delay:0s; }
.af-pet-star2{ right:-1px; top:9px; font-size:6px; animation-duration:3.4s; animation-delay:0.9s; }
.af-pet-star3{ right:3px; top:27px; font-size:7px; animation-duration:2.8s; animation-delay:1.7s; }
/* Fade fully in, then completely out over the tail (~1s) so each star winks
   out instead of just dimming; per-star durations above stagger the rhythm. */
@keyframes afPetStar{ 0%{ opacity:0; transform:scale(0.6);} 30%{ opacity:1; transform:scale(1.15);} 60%{ opacity:0.8; transform:scale(1);} 100%{ opacity:0; transform:scale(0.7);} }

/* Cock Magic spell-cast messages (e.g. "Slick Surge! +100 droplets") — blue and
   "shiny": the text + ✨ icon are filled with a blue gradient (clipped to the
   glyph shapes, which also tints the emoji) carrying a near-white diagonal band
   that sweeps across on a loop. drop-shadow gives the blue glow since the text
   fill is transparent. Keeps the base milestoneFloat rise/fade. */
.cm-spell-toast{
  color:transparent !important;
  background:linear-gradient(115deg,#9b4dff 0%,#9b4dff 42%,#f5ecff 50%,#9b4dff 58%,#9b4dff 100%) !important;
  background-size:250% 100% !important;
  -webkit-background-clip:text !important;
  background-clip:text !important;
  -webkit-text-fill-color:transparent !important;
  text-shadow:none !important; /* kill the inherited gold milestone glow */
  animation:milestoneFloat 2s ease-out forwards, cmShine 1.6s linear infinite, cmGlow 1.2s ease-in-out infinite, cmWave 0.9s ease-in-out infinite !important;
}
@keyframes cmShine{ 0%{ background-position:210% 0; } 100%{ background-position:-60% 0; } }
/* Pulsing purple glow (filter so it works with the clipped gradient text). */
@keyframes cmGlow{ 0%,100%{ filter:drop-shadow(0 0 4px rgba(150,80,240,0.55)); } 50%{ filter:drop-shadow(0 0 15px rgba(180,110,255,0.95)); } }
/* Gentle wavy wobble — rotate property so it composes with milestoneFloat's transform. */
@keyframes cmWave{ 0%,100%{ rotate:-2.5deg; } 50%{ rotate:2.5deg; } }

/* Unlocked-but-unpurchased placeholder: dashed, transparent, pulsing + button. */
.af-pet.af-pet-placeholder{ filter:none; }
.af-pet-ph-outline{
  width:24px; height:46px; border-radius:11px;
  border:2px dashed #6a8ad0; background:rgba(90,140,240,0.10);
  display:flex; align-items:center; justify-content:center;
  box-shadow:0 0 8px rgba(80,130,230,0.22);
}
.af-pet-ph-plus{
  width:18px; height:18px; border-radius:50%; padding:0;
  border:1.5px solid #7aa8e8; background:rgba(60,110,200,0.35);
  color:#cfe2ff; font-size:14px; font-weight:700; line-height:1; cursor:pointer;
  display:flex; align-items:center; justify-content:center;
  animation:afPetPlusPulse 1.4s ease-in-out infinite;
}
.af-pet-ph-plus-afford{ border-color:#a8d4ff; color:#fff; background:rgba(80,140,240,0.6); }
@keyframes afPetPlusPulse{ 0%,100%{ transform:scale(1); box-shadow:0 0 4px rgba(120,170,240,0.5);} 50%{ transform:scale(1.18); box-shadow:0 0 12px 2px rgba(120,170,240,0.85);} }

/* Purchase confirmation popup — blue/magic themed. */
.af-buy-modal{ max-width:420px; border:1.5px solid #4a7ad0 !important; }
.af-buy-hat{ width:54px; height:42px; margin:2px auto 4px; }
.af-buy-hat svg{ width:100%; height:100%; display:block; }
.af-buy-title{ color:#cfe2ff !important; }
.af-buy-desc{ color:#bcd6ff; font-size:13px; margin:6px 0 16px; }
.af-buy-btns{ display:flex; gap:12px; justify-content:center; }
.af-buy-no, .af-buy-yes{ padding:8px 22px; border-radius:9px; font-size:14px; font-weight:700; cursor:pointer; border:1.5px solid; transition:filter 0.12s, background 0.12s; }
.af-buy-no{ background:#2a1830; border-color:#7a5a90; color:#e0c8f0; }
.af-buy-no:hover{ background:#3a2444; }
.af-buy-yes{ background:linear-gradient(135deg,#2a55a0,#1a3a78); border-color:#5a90e0; color:#eaf2ff; display:inline-flex; align-items:center; gap:8px; }
.af-buy-yes:hover{ filter:brightness(1.12); }
.af-buy-cost{ font-size:12px; color:#bcd6ff; }
.af-buy-yes-disabled{ opacity:0.5; cursor:not-allowed; filter:grayscale(0.4); }
.af-buy-yes-disabled:hover{ filter:grayscale(0.4); }

/* ═══ THE BANKER PET ══════════════════════════════════════════════════════════
   Default-Drippy-colored, with slicked-back hair + a business suit and tie.
   Sits above the Arcane Familiar. Reuses .af-pet-body (transform-origin + bob/
   wiggle animations) for its idle liveliness. */
.banker-pet{
  pointer-events:auto;
  cursor:pointer;
  position:relative;
  display:flex;
  flex-direction:column;
  align-items:center;
  width:40px;
  margin-bottom:16px;
  z-index:2;
  filter:drop-shadow(0 0 5px rgba(150,90,170,0.45));
  transition:transform 0.12s ease, filter 0.15s ease;
}
.banker-pet:hover{ transform:translateY(-2px) scale(1.1); filter:drop-shadow(0 0 9px rgba(200,140,220,0.7)); }

.banker-hair{ position:absolute; left:50%; top:-1px; transform:translateX(-50%); width:21px; height:11px; z-index:3; pointer-events:none; }
.banker-hair svg{ width:100%; height:100%; display:block; }

.banker-cyl{
  position:absolute; left:50%; top:2px; transform:translateX(-50%);
  width:20px; height:32px; border-radius:10px;
  background:linear-gradient(to right,#c89cbe,#a87098,#c89cbe);
  border:2px solid #c080a8;
  box-shadow:0 0 8px rgba(192,128,168,0.35), inset 0 0 9px rgba(0,0,0,0.28);
  z-index:2; overflow:hidden;
  /* 5.2s breathe — distinct from Drippy (4s) and Arcane Familiar (4.6s). */
  animation:afPetBreathe 5.2s ease-in-out infinite;
}
.banker-shine{ position:absolute; left:4px; top:4px; width:3px; height:42%; border-radius:2px; background:linear-gradient(to bottom,rgba(255,255,255,0.5),transparent); z-index:1; }
.banker-eyes{ position:absolute; left:50%; top:7px; transform:translateX(-50%); display:flex; gap:5px; z-index:2; }
.banker-eye{ width:4px; height:5px; background:#fff; border-radius:50%; position:relative; }
.banker-eye::after{ content:''; position:absolute; left:50%; top:55%; transform:translate(-50%,-50%); width:2px; height:2px; background:#1a0810; border-radius:50%; }
.banker-mouth{ position:absolute; left:50%; top:13px; transform:translateX(-50%); width:10px; height:5px; z-index:2; }
.banker-suit{ position:absolute; left:50%; transform:translateX(-50%); bottom:-2px; width:24px; height:32px; z-index:5; pointer-events:none; border-radius:0 0 5px 5px; overflow:hidden; }
.banker-suit svg{ width:100%; height:100%; display:block; }
.banker-kiwis{ position:absolute; left:50%; bottom:0; transform:translateX(-50%); width:34px; height:14px; z-index:4; }
.banker-kiwis svg{ position:absolute; width:13px; height:13px; bottom:0; }
.banker-kiwis svg:first-child{ left:1px; transform:rotate(90deg); }
.banker-kiwis svg:last-child{ right:1px; transform:rotate(-90deg); }

/* ═══ BANK WINDOW (green; modeled on the Arcane Familiar perk popup) ══════════ */
.bank-modal{
  position:relative; background:rgba(9,45,23,0.7) !important; border:1.5px solid #2f8f4f !important;
  border-radius:14px; padding:20px 22px 18px; width:380px; max-width:92vw;
  color:#d6f0de; box-shadow:0 0 32px rgba(40,180,90,0.35),0 8px 28px #0008; text-align:center;
}
/* The five special-Drippy click popups: 20% bigger (window + text via zoom)
   and every bit of text bold. */
.bank-modal, .ghost-modal, .dragon-modal, .cel-modal, .apt-modal-arcane{ zoom:1.2; }
.bank-modal *, .ghost-modal *, .dragon-modal *, .cel-modal *, .apt-modal-arcane *{ font-weight:700 !important; }
.bank-have-label{ opacity:0.85; }
.bank-have-vals{ text-align:right; }
.bank-title{ color:#7fe6a0 !important; text-shadow:0 0 10px rgba(90,230,140,0.4); }
.bank-section{ background:rgba(13,35,22,0.8); border:1px solid #1f5a34; border-radius:10px; padding:12px 12px 14px; margin-top:12px; }
.bank-section-head{ font-size:15px; font-weight:700; color:#9fe8b8; margin-bottom:4px; }
.bank-sub{ font-size:13px; color:#9cc8ad; margin-bottom:8px; }
.bank-sub-cost{ display:block; font-size:11px; opacity:0.85; font-weight:400; }
.bank-balance, .bank-rate{ font-size:14px; color:#cfeedd; margin-bottom:8px; }
.bank-balance b, .bank-rate b{ color:#eafff2; }
.bank-row{ display:flex; gap:8px; justify-content:center; align-items:stretch; margin-bottom:8px; }
.bank-input{ flex:1 1 0; min-width:0; background:#06140c; border:1px solid #2f8f4f; border-radius:7px; padding:7px 9px; color:#eafff2; font-size:13px; font-family:inherit; }
.bank-btn{ background:#123a22; border:1px solid #2f8f4f; border-radius:8px; padding:8px 12px; font-size:13px; font-weight:700; color:#bfeccd; cursor:pointer; font-family:inherit; transition:filter 0.12s, background 0.12s; }
.bank-btn:hover{ background:#1a5232; }
.bank-btn-go{ background:linear-gradient(135deg,#1a6e38,#125a2c); border-color:#46c46a; color:#eafff2; }
.bank-btn-go:hover{ filter:brightness(1.12); }
.bank-btn-claim{ width:100%; margin-top:2px; }
.bank-btn-claim.bank-on{ background:linear-gradient(135deg,#1a6e38,#125a2c); border-color:#5ad07a; color:#eafff2; box-shadow:0 0 10px rgba(90,210,120,0.3); }
.bank-disabled{ opacity:0.45; cursor:not-allowed; filter:grayscale(0.4); }
.bank-disabled:hover{ filter:grayscale(0.4); background:linear-gradient(135deg,#1a6e38,#125a2c); }
.bank-balances{ display:flex; justify-content:space-between; font-size:13px; background:#06140c; border:1px solid #1f5a34; border-radius:7px; padding:6px 10px; margin-top:8px; }

/* ═══ DRIPPY GHOST PET ════════════════════════════════════════════════════════
   Translucent, whiter Drippy. Reuses .af-pet-body (transform-origin + bob/wiggle). */
.ghost-pet{ pointer-events:auto; cursor:pointer; position:relative; display:flex; flex-direction:column; align-items:center; width:40px; margin-bottom:16px; z-index:2; opacity:0.9; filter:drop-shadow(0 0 7px rgba(200,225,255,0.7)); transition:transform 0.12s ease, filter 0.15s ease; transform-origin:50% 100%; }
.ghost-pet:hover{ transform:translateY(-2px) scale(1.1); filter:drop-shadow(0 0 11px rgba(225,240,255,0.95)); }
/* Ghostly idle: slowly sways between -8° and +8°, passing upright in the middle,
   while gently drifting up and down ~5px. Both use the `rotate`/`translate`
   properties (not transform) so the body's wiggle + hover lift still compose on
   top. Sway/drift live on each .ghost-unit so the main + twin move independently. */
@keyframes ghostSway{ 0%,100%{ rotate:-8deg; } 50%{ rotate:8deg; } }
@keyframes ghostDrift{ 0%,100%{ translate:0 2.5px; } 50%{ translate:0 -2.5px; } }
.ghost-unit{ position:relative; transform-origin:50% 100%; animation:ghostSway 5.5s ease-in-out infinite, ghostDrift 3.6s ease-in-out infinite; }
/* Twin form (Drippy dead): a second ghost beside him, swaying/drifting on its
   own out-of-phase timing. The pair shifts 20px right; the twin sits 4px closer. */
.ghost-unit-twin{ position:absolute; top:0; left:-9px; opacity:0.85; pointer-events:none; z-index:1; animation-duration:4.7s,4.2s; animation-delay:-1.6s,-0.9s; }
.ghost-pet.ghost-twinned .ghost-unit-main{ left:10px; }
.ghost-cyl{ position:absolute; left:50%; top:2px; transform:translateX(-50%); width:20px; height:32px; border-radius:10px; background:linear-gradient(to right,rgba(232,242,255,0.55),rgba(205,225,250,0.4),rgba(232,242,255,0.55)); border:2px solid rgba(220,235,255,0.7); box-shadow:0 0 10px rgba(205,228,255,0.6), inset 0 0 9px rgba(255,255,255,0.3); z-index:2; animation:afPetBreathe 4.9s ease-in-out infinite; }
.ghost-eyes{ position:absolute; left:50%; top:9px; transform:translateX(-50%); display:flex; gap:5px; }
.ghost-eye{ width:4px; height:5px; background:rgba(90,120,160,0.9); border-radius:50%; }
/* Mouth = a copy of an eye (inherits .ghost-eye color + shape), 30% bigger. */
.ghost-mouth-eye{ position:absolute; left:50%; top:18px; transform:translateX(-50%); width:5px; height:7px; }
.ghost-kiwis{ position:absolute; left:50%; bottom:0; transform:translateX(-50%); width:34px; height:14px; }
.ghost-kiwis svg{ position:absolute; width:13px; height:13px; bottom:0; }
.ghost-kiwis svg:first-child{ left:1px; transform:rotate(90deg); }
.ghost-kiwis svg:last-child{ right:1px; transform:rotate(-90deg); }

/* Ghost perk menu (frosty white-on-dark) */
.ghost-modal{ position:relative; background:#1a2230; border:1.5px solid #b8cce0 !important; border-radius:14px; padding:20px 22px 18px; width:344px; max-width:92vw; color:#e8f0fa; box-shadow:0 0 32px rgba(200,225,255,0.3),0 8px 28px #0008; text-align:center; }
.ghost-title{ color:#eaf4ff !important; text-shadow:0 0 12px rgba(210,232,255,0.7); }
.ghost-sub{ font-size:13px; color:#a8bccf; margin:4px 0 12px; }
.ghost-tree{ display:flex; flex-direction:column; gap:7px; }
.ghost-node{ display:flex; align-items:center; gap:8px; padding:8px 11px; border-radius:9px; background:rgba(255,255,255,0.05); border:1px solid #3a4a5c; color:#cfdcea; font-size:13px; }
.ghost-node-icon{ font-size:15px; }
.ghost-node-name{ font-weight:700; white-space:nowrap; }
.ghost-node-eff{ margin-left:auto; color:#a8c4dd; font-size:11px; white-space:nowrap; }
.ghost-node-cost{ font-size:11px; color:#8aa0b6; min-width:78px; text-align:right; }
.ghost-owned{ background:rgba(180,210,255,0.14); border-color:#9fc4ec; color:#eaf4ff; }
.ghost-owned .ghost-node-cost{ color:#bfe0ff; }
.ghost-next{ border-color:#cfe2ff; }
.ghost-afford{ cursor:pointer; background:linear-gradient(135deg,#33506e,#24405c); border-color:#dff0ff; box-shadow:0 0 10px rgba(200,228,255,0.4); }
.ghost-afford:hover{ filter:brightness(1.1); }
.ghost-locked{ opacity:0.5; }

/* ═══ DRAGON DRIPPY PET ═══════════════════════════════════════════════════════
   Green, scaley, horned Drippy. Reuses .af-pet-body. */
.dragon-pet{ pointer-events:auto; cursor:pointer; position:relative; display:flex; flex-direction:column; align-items:center; width:40px; margin-bottom:16px; z-index:2; filter:drop-shadow(0 0 6px rgba(70,200,110,0.5)); transition:transform 0.12s ease, filter 0.15s ease; }
.dragon-pet:hover{ transform:translateY(-2px) scale(1.1); filter:drop-shadow(0 0 10px rgba(110,230,150,0.8)); }
.dragon-horns{ position:absolute; left:50%; top:-5px; transform:translateX(-50%); width:22px; height:11px; z-index:3; pointer-events:none; }
.dragon-horns svg{ width:100%; height:100%; display:block; }
.dragon-cyl{ position:absolute; left:50%; top:2px; transform:translateX(-50%); width:20px; height:32px; border-radius:10px; background:linear-gradient(to right,#5fc47e,#2f8f4f,#5fc47e); border:2px solid #2a7a44; box-shadow:0 0 8px rgba(70,200,110,0.4), inset 0 0 9px rgba(0,0,0,0.28); z-index:2; overflow:hidden; animation:afPetBreathe 5.5s ease-in-out infinite; }
.dragon-scales{ position:absolute; inset:0; z-index:1; opacity:0.85; pointer-events:none; }
.dragon-scales svg{ width:100%; height:100%; display:block; }
.dragon-shine{ position:absolute; left:4px; top:5px; width:3px; height:52%; border-radius:2px; background:linear-gradient(to bottom,rgba(255,255,255,0.45),transparent); z-index:2; }
.dragon-eyes{ position:absolute; left:50%; top:9px; transform:translateX(-50%); display:flex; gap:5px; z-index:3; }
.dragon-eye{ width:4px; height:5px; background:#fdf6c0; border-radius:50%; position:relative; }
.dragon-eye::after{ content:''; position:absolute; left:50%; top:50%; transform:translate(-50%,-50%); width:1.4px; height:4px; background:#0a2a14; border-radius:1px; }
/* Tilt the slit-pupil eyes: left 70° counter-clockwise, right 70° clockwise. */
.dragon-eyes .dragon-eye:first-child{ transform:rotate(-70deg); }
.dragon-eyes .dragon-eye:last-child{ transform:rotate(70deg); }
.dragon-mouth{ position:absolute; left:50%; top:18px; transform:translateX(-50%); width:11px; height:5px; z-index:3; }
.dragon-kiwis{ position:absolute; left:50%; bottom:0; transform:translateX(-50%); width:34px; height:14px; }
.dragon-kiwis svg{ position:absolute; width:13px; height:13px; bottom:0; }
.dragon-kiwis svg:first-child{ left:1px; transform:rotate(90deg); }
.dragon-kiwis svg:last-child{ right:1px; transform:rotate(-90deg); }

/* Dragon boon window (green; pick exactly one, permanent) */
.dragon-modal{ position:relative; background:#08160c; border:1.5px solid #2f8f4f !important; border-radius:14px; padding:20px 22px 18px; width:440px; max-width:94vw; color:#d6f0de; box-shadow:0 0 32px rgba(40,180,90,0.4),0 8px 28px #0008; text-align:center; }
.dragon-title{ color:#7fe6a0 !important; text-shadow:0 0 12px rgba(90,230,140,0.5); }
.dragon-note{ font-size:13px; color:#a8d8bb; margin:6px 0 12px; line-height:1.45; }
.dragon-note-locked{ color:#cfeedd; }
.dragon-note b{ color:#eafff2; }
.dragon-grid{ display:grid; grid-template-columns:repeat(4,1fr); gap:8px; }
.dragon-card{ background:#0d2316; border:1px solid #1f5a34; border-radius:9px; padding:9px 6px; cursor:pointer; transition:filter 0.12s, transform 0.1s, box-shadow 0.15s; }
.dragon-card:hover{ filter:brightness(1.12); transform:translateY(-2px); box-shadow:0 0 12px rgba(70,200,110,0.4); }
.dragon-card-icon{ font-size:20px; line-height:1; }
.dragon-card-name{ font-size:12px; font-weight:700; color:#eafff2; margin:3px 0 2px; }
.dragon-card-eff{ font-size:11px; color:#9fd8b4; line-height:1.3; }
.dragon-card-tag{ font-size:10px; font-weight:700; color:#ffe27a; margin-top:3px; }
.dragon-card-chosen{ border-color:#ffd24a; background:linear-gradient(135deg,#1a6e38,#125a2c); box-shadow:0 0 14px rgba(255,210,74,0.4); cursor:default; }
.dragon-card-chosen:hover{ transform:none; }
.dragon-card-locked{ opacity:0.4; cursor:not-allowed; filter:grayscale(0.5); }
.dragon-card-locked:hover{ transform:none; filter:grayscale(0.5); box-shadow:none; }
.dragon-confirm{ width:340px; }
.dragon-confirm-icon{ font-size:42px; margin-bottom:6px; }
.dragon-confirm-btns{ display:flex; gap:12px; justify-content:center; margin-top:14px; }
.dragon-btn{ padding:8px 20px; border-radius:9px; font-size:13px; font-weight:700; cursor:pointer; border:1.5px solid; font-family:inherit; transition:filter 0.12s; }
.dragon-btn-no{ background:#1a2a1e; border-color:#3a6a48; color:#bfe0cc; }
.dragon-btn-yes{ background:linear-gradient(135deg,#1a6e38,#125a2c); border-color:#5ad07a; color:#eafff2; }
.dragon-btn-yes:hover{ filter:brightness(1.13); }

/* ═══ CELESTIAL DRIPPY PET ════════════════════════════════════════════════════
   Deep-blue, star-dusted Drippy with orbiting sparkles. Reuses .af-pet-body. */
.cel-pet{ pointer-events:auto; cursor:pointer; position:relative; display:flex; flex-direction:column; align-items:center; width:40px; margin-bottom:16px; z-index:2; filter:drop-shadow(0 0 7px rgba(120,150,255,0.6)); transition:transform 0.12s ease, filter 0.15s ease; }
.cel-pet:hover{ transform:translateY(-2px) scale(1.1); filter:drop-shadow(0 0 11px rgba(170,195,255,0.9)); }
.cel-cyl{ position:absolute; left:50%; top:2px; transform:translateX(-50%); width:20px; height:32px; border-radius:10px; background:linear-gradient(160deg,#2a3478,#161b46 60%,#222c66); border:2px solid #3a4a9e; box-shadow:0 0 9px rgba(90,110,220,0.5), inset 0 0 9px rgba(0,0,0,0.4); z-index:2; overflow:hidden; animation:afPetBreathe 5.0s ease-in-out infinite; }
.cel-speck{ position:absolute; width:1.6px; height:1.6px; border-radius:50%; background:#fff; box-shadow:0 0 3px #cfe2ff; animation:celTwinkle 2.4s ease-in-out infinite; }
.cel-speck1{ left:5px; top:7px; animation-delay:0s; }
.cel-speck2{ left:13px; top:14px; animation-delay:0.8s; }
.cel-speck3{ left:7px; top:22px; animation-delay:1.5s; }
@keyframes celTwinkle{ 0%,100%{ opacity:0.25; } 50%{ opacity:1; } }
.cel-eyes{ position:absolute; left:50%; top:9px; transform:translateX(-50%); display:flex; gap:5px; z-index:3; }
.cel-eye{ width:4px; height:5px; background:rgba(234,242,255,0.7); border-radius:50%; position:relative; }
.cel-eye::after{ content:''; position:absolute; left:50%; top:55%; transform:translate(-50%,-50%); width:2px; height:2px; background:#10163a; border-radius:50%; }
.cel-mouth{ position:absolute; left:50%; top:18px; transform:translateX(-50%); width:10px; height:5px; z-index:3; }
.cel-kiwis{ position:absolute; left:50%; bottom:0; transform:translateX(-50%); width:34px; height:14px; }
.cel-kiwis svg{ position:absolute; width:13px; height:13px; bottom:0; }
.cel-kiwis svg:first-child{ left:1px; transform:rotate(90deg); }
.cel-kiwis svg:last-child{ right:1px; transform:rotate(-90deg); }
.cel-orbit{ position:absolute; color:#cfe2ff; font-size:3.5px; text-shadow:0 0 3px rgba(180,205,255,0.9); pointer-events:none; z-index:2; animation:afPetStar 2.8s ease-in-out infinite; }
.cel-orbit1{ left:-1px; top:11px; animation-delay:0.2s; }
.cel-orbit2{ right:-1px; top:23px; font-size:3px; animation-delay:1.2s; }
.cel-orbit3{ left:6px; top:30px; font-size:3.5px; animation-delay:0.7s; }
.cel-orbit4{ right:4px; top:7px; font-size:3px; animation-delay:1.7s; }
/* Faint dashed constellation line linking the four orbit sparkles. */
.cel-orbit-lines{ position:absolute; left:0; top:0; width:40px; height:44px; pointer-events:none; z-index:1; overflow:visible; }
.cel-orbit-lines path{ fill:none; stroke:rgba(170,200,255,0.32); stroke-width:0.5; stroke-dasharray:1.6 1.9; stroke-linejoin:round; }

/* ═══ ANGRY FACES (evil Drippy pet forms) ═════════════════════════════════════
   Vengeful Banker / Angry Arcane / Jealous Celestial get an angry face: a frown
   (the smile mouth flipped vertically) and angled "\  /" eyebrows above the eyes.
   The .pet-angry class is toggled on the pet element by each pet's JS. */
.pet-angry .banker-mouth, .pet-angry .af-pet-mouth, .pet-angry .cel-mouth{ transform:translateX(-50%) scaleY(-1); }
.pet-angry .banker-eyes::before, .pet-angry .banker-eyes::after,
.pet-angry .af-pet-eyes::before, .pet-angry .af-pet-eyes::after,
.pet-angry .cel-eyes::before, .pet-angry .cel-eyes::after{
  content:''; position:absolute; top:-3px; width:6px; height:1.6px; border-radius:1px; pointer-events:none;
}
.pet-angry .banker-eyes::before, .pet-angry .af-pet-eyes::before, .pet-angry .cel-eyes::before{ left:-2px; transform:rotate(22deg); }
.pet-angry .banker-eyes::after,  .pet-angry .af-pet-eyes::after,  .pet-angry .cel-eyes::after{ right:-2px; transform:rotate(-22deg); }
.pet-angry .banker-eyes::before, .pet-angry .banker-eyes::after{ background:#3a1828; }
.pet-angry .af-pet-eyes::before,  .pet-angry .af-pet-eyes::after{ background:#0a1830; }
.pet-angry .cel-eyes::before,     .pet-angry .cel-eyes::after{ background:rgba(207,224,255,0.7); }

/* Celestial star-map window */
.cel-modal{ position:relative; background:radial-gradient(ellipse at 50% 0%, #1a2150, #0a0e28 70%); border:1.5px solid #4a5ab0 !important; border-radius:14px; padding:20px 22px 18px; width:520px; max-width:95vw; color:#d6e0fa; box-shadow:0 0 32px rgba(80,110,220,0.4),0 8px 28px #0008; text-align:center; }
.cel-title{ color:#bcd0ff !important; text-shadow:0 0 12px rgba(150,180,255,0.7); }
.cel-sub{ font-size:13px; color:#9fb0d8; margin:4px 0 12px; }
.cel-map{ position:relative; width:100%; height:360px; background:radial-gradient(ellipse at 50% 40%, rgba(40,55,130,0.4), rgba(10,14,40,0.2)); border:1px solid #2a3470; border-radius:10px; margin-bottom:10px; overflow:hidden; }
.cel-lines{ position:absolute; inset:0; width:100%; height:100%; }
.cel-star{ position:absolute; transform:translate(-50%,-50%); font-size:15px; opacity:0.35; filter:grayscale(0.6) brightness(0.7); transition:opacity 0.2s, filter 0.2s; cursor:default; }
.cel-star-lit{ opacity:1; filter:none; text-shadow:0 0 8px rgba(200,220,255,0.9),0 0 14px rgba(150,180,255,0.6); animation:celTwinkle 3s ease-in-out infinite; }
.cel-stat{ font-size:13px; font-weight:700; color:#cfe0ff; }
.cel-progress{ font-size:12px; color:#9fb0d8; margin-top:4px; }
.cel-progress b{ color:#eaf2ff; }
#coach-line { font-family: 'BubbleSansRegula', 'Comic Sans MS', cursive, sans-serif; }

/* ─── White droplet emoji + cost text ────────────────────────────────────── */
/* droplet_white.js wraps every 💧 in <span class="dw">; the filter renders the
   colored emoji as solid white. Cost-text overrides recolor the numbers/labels
   that sit beside those emojis (upgrade cards, shelf tooltips, cylinder
   droplet count + label). */
/* Pale yellow-tinted white + 1px glow applied to droplet emoji and the
   cost text we previously made pure white. The .dw filter chain converts
   the colored emoji to white (brightness 0 → invert) then warms it via
   sepia, plus a drop-shadow glow. Text uses a matching color + text-shadow. */
.dw { filter: brightness(0) invert(1) sepia(0.07) saturate(1.0) drop-shadow(0 0 1px #fffef5); }
#droplet-label { color: #ffffff !important; text-shadow: 0 0 2px rgba(255,255,255,0.9); }
.cash-word { color: #51b85f; }
/* Golden text with a horizontal shine sweeping left→right. Used for "Cosmetics"
   in the Skins & Themes unlock popup. */
.gold-shine{
  font-weight:800;
  background-image:linear-gradient(90deg,#ffd56b 0%,#ffe999 40%,#ffffff 50%,#ffe999 60%,#ffd56b 100%);
  background-size:200% 100%;
  background-repeat:repeat-x;
  background-position:0 0;
  -webkit-background-clip:text;
  background-clip:text;
  -webkit-text-fill-color:transparent;
  color:transparent;
  text-shadow:0 0 6px rgba(255,200,80,0.4);
  animation:goldShineSweep 2.4s linear infinite;
}
@keyframes goldShineSweep{
  0%   {background-position:200% 0;}
  100% {background-position:-200% 0;}
}
#droplet-count { color: #f0d0ff !important; }
#droplet-count-wrap { opacity: 0.9; }
.upg-cost,
.upg-buy-wrap.can-buy .upg-cost,
.upg-buy-wrap.ghost-can .upg-cost,
.shelf-tip .st-head-l .st-cost { color: #fffef5 !important; text-shadow: 0 0 1px #fffef5; }
.perk-cost { text-shadow: 0 0 1px #fffef5; }
/* Hired Cylinders ("harem") bottom DPS bar: "💧 X / sec total" */
.cylarmy-dps-bottom .cylarmy-total-stat,
.cylarmy-dps-bottom .cylarmy-total-stat span { color: #fffef5 !important; text-shadow: 0 0 1px #fffef5; }
/* Upgrade-card "+N 💧 per squeeze" tinted span (inline style overridden) */
.upg-desc-bigstat > span[style] { color: #fffef5 !important; text-shadow: 0 0 1px #fffef5; }

/* ─── Drippy Drop Storm / Shower rain layering ───────────────────────────── */
/* Storm + shower rain renders into the main droplets canvas (z-index 50).
   Coach speech bubble (z 9500) and virility-trait-unlocked popup (.virility-
   trait-popup) both sit above that, so they would visually mask the rain.
   When either event is active, raise the droplets canvas above those UI
   pieces. body.modal-open pushes the canvas back below modal overlays so
   modal popups remain unaffected. */
.virility-trait-popup { z-index: 9600; }
body.storm-active #droplets-canvas-wrap,
body.shower-active #droplets-canvas-wrap { z-index: 9750; }
body.modal-open.storm-active #droplets-canvas-wrap,
body.modal-open.shower-active #droplets-canvas-wrap { z-index: 50; }

/* ─── From coach.js ──────────────────────────────────────────────────────── */
#coach-wrap {
  position: fixed; bottom: 46px; left: 36px; z-index: 9500;
  display: flex; align-items: flex-end; gap: 8px;
  pointer-events: none;
  opacity: 1;
  transform: scale(1.3);
  transform-origin: bottom left;
}
#coach-wrap:not(.coach-mounted) { display: none; }
/* Drippy must never sit over a modal/overlay — the body.modal-open class is
   toggled in utils.js whenever isModalOpen() flips. */
body.modal-open #coach-wrap { display: none !important; }
/* Tamagotchi exception: Drippy stays visible above the tama overlay (10500)
   so stat-change floaters can pop above his head, but his speech bubble is
   suppressed (coach-visible removed on open + show() bails while open). */
body.modal-open.tama-open #coach-wrap { display: flex !important; z-index: 10600; }
body.tama-open #coach-bubble { opacity: 0 !important; }
#coach-avatar-col { pointer-events: auto; }
#coach-bubble {
  opacity: 0;
  transition: opacity 0.35s ease;
}
#coach-wrap.coach-visible #coach-bubble { opacity: 1; }
#coach-avatar {
  font-size: 36px; line-height: 1; flex-shrink: 0;
  /* brightness var drives the "turning black" effect as combined stats fall
     from 20% → 10% (see coach.js _coachStatsTick) */
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.7)) brightness(var(--coach-brightness, 1));
  /* subtle bounce when appearing */
  animation: coachBounceIn 0.4s cubic-bezier(0.34,1.56,0.64,1) both;
  cursor: pointer;
  transition: filter 0.5s ease, scale 0.14s ease, translate 0.14s ease;
}
#coach-wrap.coach-visible #coach-bubble { cursor: pointer; }

/* "Caught 1 Drippy Drop!" floater spawned above the cursor when the player
   collides with a Drippy droplet. Fades in, drifts up, fades out. */
.drippy-catch-float {
  position: fixed;
  z-index: 10002;
  font-size: 14px;
  font-weight: 700;
  color: #b8e4ff;
  text-shadow: 0 0 6px rgba(80,160,255,0.85), 0 1px 2px rgba(0,0,0,0.9);
  pointer-events: none;
  white-space: nowrap;
  transform: translate(-50%, 4px);
  will-change: transform, opacity;
  animation:
    drippyCatchFloatMove 1.2s cubic-bezier(0.22, 0.61, 0.36, 1) forwards,
    drippyCatchFloatFade 1.2s linear forwards;
}
@keyframes drippyCatchFloatMove {
  from { transform: translate(-50%, 4px); }
  to   { transform: translate(-50%, -56px); }
}
@keyframes drippyCatchFloatFade {
  0%   { opacity: 0; }
  15%  { opacity: 1; }
  70%  { opacity: 1; }
  100% { opacity: 0; }
}

/* Drippy Skill Tree access button — bottom-right of the left column. */
#drippy-tree-btn {
  position: absolute;
  right: 8px;
  bottom: 8px;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: linear-gradient(160deg, #6a3aa8 0%, #3a1a6a 100%);
  border: 2px solid #b497e0;
  color: #fff;
  font-weight: 800;
  font-size: 16px;
  cursor: pointer;
  z-index: 50;
  box-shadow: 0 0 10px rgba(160,112,204,0.6), inset 0 1px 2px rgba(255,255,255,0.25);
  display: flex; align-items: center; justify-content: center;
  transition: transform 0.15s ease, box-shadow 0.2s ease;
}
#drippy-tree-btn:hover {
  transform: scale(1.08);
  box-shadow: 0 0 16px rgba(180,148,224,0.9), inset 0 1px 2px rgba(255,255,255,0.35);
}
#drippy-tree-btn:active { transform: scale(0.95); }

/* Drippy Skill Tree modal — re-uses the prestige-tree visual idiom. */
.drippy-tree-modal { padding: 8px 4px; width: 930px; }
.drippy-tree-header {
  display: flex; align-items: center; justify-content: space-between;
  /* Extra right padding keeps the reset button + drops pill clear of the
     absolutely-positioned close X in the modal's top-right corner. */
  padding: 0 52px 10px 12px;
  border-bottom: 1px solid rgba(180,148,224,0.3);
  margin-bottom: 10px;
}
/* Close X on the skill tree, sized to match the standard close buttons. */
.drippy-tree-modal .ui-unlock-x { font-size: 20px; padding: 4px 12px; opacity: 1; }
.drippy-tree-header h2 {
  margin: 0;
  color: #d4c0ff;
  text-shadow: 0 0 8px rgba(160,112,204,0.7);
}
.drippy-tree-currency {
  font-size: 16px;
  font-weight: 700;
  color: #b8e4ff;
  background: rgba(40,20,80,0.3);
  border: 1px solid rgba(180,148,224,0.4);
  border-radius: 8px;
  padding: 5px 12px;
}
.drippy-tree-currency .drippy-drop-icon { margin-right: 4px; font-size: 13.6px; }
.drippy-tree-modal .prestige-scroll { overflow-x: hidden; }
.drippy-tree-canvas {
  position: relative;
  margin: 0 auto;
  background: radial-gradient(ellipse at center, rgba(60,30,120,0.15) 0%, rgba(20,10,40,0.15) 70%);
  border-radius: 10px;
  border: 1px solid rgba(180,148,224,0.18);
}
.drippy-node {
  position: absolute;
  background: linear-gradient(160deg, #2c1850 0%, #1a0d30 100%);
  border: 2px solid #6a3aa8;
  border-radius: 10px;
  padding: 6px 4px;
  text-align: center;
  cursor: not-allowed;
  user-select: none;
  transition: transform 0.15s ease, box-shadow 0.2s ease, border-color 0.2s ease;
  box-shadow: 0 2px 6px rgba(0,0,0,0.5);
}
.drippy-node.affordable {
  cursor: pointer;
  border-color: #b497e0;
  box-shadow: 0 0 10px rgba(180,148,224,0.5), 0 2px 6px rgba(0,0,0,0.5);
}
.drippy-node.affordable:hover {
  transform: scale(1.05);
  box-shadow: 0 0 16px rgba(180,148,224,0.8), 0 2px 6px rgba(0,0,0,0.5);
}
.drippy-node.owned {
  background: linear-gradient(160deg, #3a8a3a 0%, #1a4a1a 100%);
  border-color: #7ed27e;
  cursor: default;
  box-shadow: 0 0 10px rgba(126,210,126,0.55), 0 2px 6px rgba(0,0,0,0.5);
}
.drippy-node.locked {
  opacity: 0.45;
  filter: grayscale(0.6);
}
/* Mutually-exclusive nodes (e.g. Talkative side once Introvert is bought) —
   stronger gray-out so the player can tell at a glance the path is closed. */
.drippy-node.excluded {
  opacity: 0.25;
  filter: grayscale(1) brightness(0.55);
  cursor: not-allowed;
}
/* Drippy skill-tree reset button — sits to the LEFT of the Drippy Drops pill
   in the modal header. Costs 5 💵 cash and refunds every drop spent. */
.drippy-tree-reset {
  font-size: 13px;
  font-weight: 700;
  color: #ffd6a8;
  background: linear-gradient(160deg, #5a2e10 0%, #3a1e08 100%);
  border: 1px solid #b07040;
  border-radius: 8px;
  padding: 6px 12px;
  cursor: pointer;
  /* Very subtle golden glow while clickable (removed in the disabled state). */
  box-shadow: 0 0 7px rgba(224,176,96,0.30);
  transition: background 0.15s, border-color 0.15s, transform 0.1s, box-shadow 0.15s;
}
.drippy-tree-reset:hover { background: linear-gradient(160deg, #7a3e18 0%, #4a2810 100%); border-color: #e0a060; }
.drippy-tree-reset:active { transform: scale(0.97); }
.drippy-tree-reset.disabled,
.drippy-tree-reset[disabled] {
  opacity: 0.45;
  cursor: not-allowed;
  filter: grayscale(0.5);
  box-shadow: none;
}
.drippy-tree-reset.disabled:hover,
.drippy-tree-reset[disabled]:hover { background: linear-gradient(160deg, #5a2e10 0%, #3a1e08 100%); border-color: #b07040; }
.drippy-node-icon  { font-size: 24.2px; line-height: 1; }
.drippy-node-name  { font-size: 13.31px; font-weight: 700; color: #e8e0ff; margin-top: 2px; }
.drippy-node-cost  { font-size: 12.1px; color: #b8e4ff; margin-top: 2px; }
.drippy-node.owned .drippy-node-cost { color: #b8ffb8; }
.drippy-node-desc-tip {
  font-size: 11px;
  white-space: pre-line;
}

/* Floating "-1 relationship" popup spawned when the bubble is clicked */
.coach-rel-popup {
  position: fixed;
  z-index: 10002;
  font-size: 14px;
  font-weight: 700;
  color: #ff6b6b;
  text-shadow: 0 0 6px rgba(255,0,0,0.6), 0 1px 2px rgba(0,0,0,0.8);
  pointer-events: none;
  white-space: nowrap;
  animation: coachRelPopup 1.4s ease-out forwards;
}
.coach-rel-popup.negative { color: #ff6b6b; }
@keyframes coachRelPopup {
  0%   { opacity: 0; transform: translateY(0); }
  12%  { opacity: 1; }
  75%  { opacity: 1; }
  100% { opacity: 0; transform: translateY(-42px); }
}
/* ── Mini-cylinder coach avatar (mirrors the player's cylinder + kiwis) ── */
#coach-avatar.coach-mini {
  position: relative;
  width: 46px;
  height: 62px;
  font-size: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
}
.coach-mini-cyl {
  position: relative;
  width: 26px;
  height: 42px;
  border-radius: 13px;
  border: 2px solid #c080a8;
  background: linear-gradient(to right, #c89cbe, #a87098, #c89cbe);
  box-shadow: 0 0 8px rgba(192,128,168,0.35), inset 0 0 10px rgba(0,0,0,0.28);
  transform-origin: 50% 100%;
}
.coach-mini-shine {
  position: absolute;
  left: 4px; top: 7px;
  width: 4px; height: 62%;
  border-radius: 3px;
  background: linear-gradient(to bottom,
    rgba(255,255,255,0.45) 0%,
    rgba(255,255,255,0.12) 60%,
    rgba(255,255,255,0.02) 100%);
  pointer-events: none;
}
.coach-mini-eyes {
  position: absolute;
  left: 0; right: 0; top: 10px;
  display: flex;
  justify-content: center;
  gap: 4px;
  pointer-events: none;
  z-index: 2;
}
.coach-eye {
  position: relative;
  width: 5px;
  height: 7px;
  border-radius: 50%;
  background: #fff;
  box-shadow: 0 0 2px rgba(0,0,0,0.6);
}
.coach-eye::after {
  content: '';
  position: absolute;
  top: 2.5px;
  left: 1px;
  width: 3px;
  height: 3px;
  border-radius: 50%;
  background: #120610;
}
/* Mouth — shape reflects combined hunger/happiness/health (see coach.js) */
.coach-mouth {
  position: absolute;
  left: 50%;
  top: 24px;
  transform: translateX(-50%);
  width: 12px;
  height: 6px;
  pointer-events: none;
  z-index: 2;
}
.coach-mouth svg {
  width: 100%;
  height: 100%;
  overflow: visible;
  display: block;
}
.coach-mouth-path {
  fill: none;
  stroke: #1a0810;
  stroke-width: 1.4;
  stroke-linecap: round;
  transition: d 0.4s ease;
}
/* Death: cylinder + kiwis are replaced by a gravestone emoji by coach.js */
.coach-grave {
  font-size: 44px;
  line-height: 1;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.8));
}
#coach-avatar.coach-dead {
  animation: none;
  cursor: default;
}
/* Floating ghost that rises from the coach's position on death */
.coach-ghost {
  position: fixed;
  font-size: 40px;
  line-height: 1;
  pointer-events: none;
  transform: translate(-50%, -50%);
  z-index: 10010;
  animation: coachGhostFloat 2.2s ease-out forwards;
  filter: drop-shadow(0 0 6px rgba(255,255,255,0.85));
}
@keyframes coachGhostFloat {
  0%   { opacity: 0; transform: translate(-50%, -50%)  scale(0.6); }
  15%  { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, -200%) scale(1.3); }
}
.coach-mini-kiwis {
  display: flex;
  gap: 1px;
  margin-top: -3px;
  z-index: 1;
}
.coach-kiwi {
  width: 18px;
  height: 18px;
  display: block;
  transform-origin: 50% 30%;
}
.coach-mini-kiwis .coach-kiwi:first-child { transform: rotate(90deg); }
.coach-mini-kiwis .coach-kiwi:last-child  { transform: rotate(-90deg); }
.coach-tier-badge {
  position: absolute;
  top: -4px;
  right: -8px;
  font-size: 13px;
  line-height: 1;
  pointer-events: none;
  display: none;
  filter: drop-shadow(0 1px 2px rgba(0,0,0,0.7));
}
/* Passive idle breathe — mirrors the player cylinder's subtle breathing */
@keyframes coachCylIdleBreathe {
  0%, 100% { transform: scaleY(1)     scaleX(1);     }
  50%      { transform: scaleY(1.008) scaleX(0.997); }
}
#coach-avatar.coach-mini .coach-mini-cyl {
  animation: coachCylIdleBreathe 4s ease-in-out infinite;
  transform-origin: 50% 100%;
}
/* Breathe + bounce when the player hovers the coach */
@keyframes coachCylBreathe {
  0%, 100% { transform: scaleY(1)    scaleX(1);    }
  50%      { transform: scaleY(1.10) scaleX(0.93); }
}
@keyframes coachKiwiBounce {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-3px); }
}
@keyframes coachKiwiBounceLeft {
  0%, 100% { transform: rotate(90deg)  translateX(0); }
  50%      { transform: rotate(90deg)  translateX(3px); }
}
@keyframes coachKiwiBounceRight {
  0%, 100% { transform: rotate(-90deg) translateX(0); }
  50%      { transform: rotate(-90deg) translateX(-3px); }
}
#coach-wrap.coach-visible #coach-avatar.coach-mini:hover .coach-mini-cyl {
  animation: coachCylBreathe 1s ease-in-out infinite;
}
#coach-wrap.coach-visible #coach-avatar.coach-mini:hover .coach-mini-kiwis .coach-kiwi:first-child {
  animation: coachKiwiBounceLeft 1s ease-in-out infinite;
}
#coach-wrap.coach-visible #coach-avatar.coach-mini:hover .coach-mini-kiwis .coach-kiwi:last-child {
  animation: coachKiwiBounceRight 1s ease-in-out infinite;
}
/* Original Drippy hover: 10% bigger + small lift + soft glow (matching the
   extra pets). Uses independent scale/translate so they compose with the
   coachBounceIn transform-fill instead of being overridden by it. */
#coach-wrap.coach-visible #coach-avatar.coach-mini:hover {
  scale: 1.1;
  translate: 0 -2px;
  filter: drop-shadow(0 0 7px rgba(255,250,235,0.6)) drop-shadow(0 2px 6px rgba(0,0,0,0.7)) brightness(var(--coach-brightness, 1));
}
#coach-wrap.coach-visible { pointer-events: auto; }

/* Drippy liveliness — one-shot bob/wiggle actions triggered from coach.js.
   Amplitude scales via --drippy-amp (set inline per-trigger, default 1).
   Each animation plays once, then the class is removed on animationend so
   the default breathe / resting transform resumes. */
@keyframes drippyCylBob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(calc(var(--drippy-amp, 1) * -5px)); }
}
@keyframes drippyCylWiggle {
  0%, 100% { transform: rotate(0deg); }
  25%      { transform: rotate(calc(var(--drippy-amp, 1) * -8deg)); }
  75%      { transform: rotate(calc(var(--drippy-amp, 1) *  8deg)); }
}
/* Kiwi keyframes preserve each kiwi's base rotation (90° / -90°) — the
   animation replaces the static transform while it runs. */
@keyframes drippyKiwiLeftBob {
  0%, 100% { transform: rotate(90deg) translateX(0); }
  50%      { transform: rotate(90deg) translateX(calc(var(--drippy-amp, 1) * -4px)); }
}
@keyframes drippyKiwiRightBob {
  0%, 100% { transform: rotate(-90deg) translateX(0); }
  50%      { transform: rotate(-90deg) translateX(calc(var(--drippy-amp, 1) * -4px)); }
}
@keyframes drippyKiwiLeftWiggle {
  0%, 100% { transform: rotate(90deg) translateY(0); }
  50%      { transform: rotate(90deg) translateY(calc(var(--drippy-amp, 1) * 4px)); }
}
@keyframes drippyKiwiRightWiggle {
  0%, 100% { transform: rotate(-90deg) translateY(0); }
  50%      { transform: rotate(-90deg) translateY(calc(var(--drippy-amp, 1) * 4px)); }
}
/* ID on #coach-avatar bumps specificity above the base breathe rule
   (#coach-avatar.coach-mini .coach-mini-cyl) so the one-shot animation
   actually replaces the breathe while running. */
#coach-avatar .coach-mini-cyl.drippy-cyl-bob    { animation: drippyCylBob    0.55s ease-in-out 1; }
#coach-avatar .coach-mini-cyl.drippy-cyl-wiggle { animation: drippyCylWiggle 0.55s ease-in-out 1; }
#coach-avatar .coach-kiwi.drippy-kiwi-left-bob     { animation: drippyKiwiLeftBob     0.55s ease-in-out 1; }
#coach-avatar .coach-kiwi.drippy-kiwi-right-bob    { animation: drippyKiwiRightBob    0.55s ease-in-out 1; }
#coach-avatar .coach-kiwi.drippy-kiwi-left-wiggle  { animation: drippyKiwiLeftWiggle  0.55s ease-in-out 1; }
#coach-avatar .coach-kiwi.drippy-kiwi-right-wiggle { animation: drippyKiwiRightWiggle 0.55s ease-in-out 1; }
#coach-wrap.coach-hurt #coach-avatar {
  filter: drop-shadow(0 0 8px rgba(255,40,40,0.95))
          drop-shadow(0 0 14px rgba(255,0,0,0.8))
          hue-rotate(-50deg) saturate(3) brightness(1.1);
  animation: coachHurtShake 0.4s ease-in-out 2;
}
@keyframes coachHurtShake {
  0%,100% { transform: translateX(0) rotate(0); }
  25%     { transform: translateX(-4px) rotate(-8deg); }
  75%     { transform: translateX(4px)  rotate(8deg); }
}
#coach-wrap:not(.coach-visible) #coach-avatar { animation: none; }
@keyframes coachBounceIn {
  0%   { transform: translateY(12px) scale(0.8); }
  100% { transform: translateY(0)    scale(1);   }
}
#coach-bubble {
  position: relative;
  background: rgba(14, 4, 22, 0.5);
  border: 1px solid rgba(190, 110, 255, 0.68);
  border-radius: 12px 12px 12px 2px;
  padding: 8px 12px 8px 18px;
  max-width: 210px;
  font-size: 12px;
  color: rgba(223, 200, 245, 0.85);
  line-height: 1.55;
  box-shadow: 0 0 12px rgba(170, 90, 255, 0.476), 0 0 22px rgba(140, 60, 230, 0.476), 0 4px 18px rgba(130, 0, 255, 0.476);
}
#coach-timer {
  position: absolute;
  top: 8px;
  bottom: 4px;
  left: 5px;
  width: 3px;
  background: linear-gradient(180deg, #ff2040, #c00020);
  border-radius: 2px;
  transform-origin: bottom center;
  opacity: 0.7;
  pointer-events: none;
}
@keyframes coachTimerShrink { from { transform: scaleY(1); } to { transform: scaleY(0); } }
#coach-name {
  font-size: 11px; color: #a070cc; font-weight: 700;
  margin-bottom: 3px;
  text-transform: uppercase; letter-spacing: 1px;
}

/* ─── Drippy-drop tutorial (drippy_drop_tutorial.js) ─────────────────────── */
/* Full-screen click swallower. Sits below Drippy (z 9500) but above all UI
   so clicks/squeezes are blocked while the tutorial runs. */
#drippy-tutorial-blocker {
  position: fixed; inset: 0;
  z-index: 9400;
  background: rgba(8, 2, 16, 0.18);
  cursor: default;
  pointer-events: auto;
  animation: drippyTutFadeIn 0.4s ease both;
}
@keyframes drippyTutFadeIn { from { background: rgba(8, 2, 16, 0); } to { background: rgba(8, 2, 16, 0.18); } }

/* Blur the whole game backdrop. Drippy's wrap, the droplet canvases, and the
   floating "Caught Drippy Drop!" label live outside #root, so they stay sharp. */
#root { transition: filter 0.4s ease; }
body.drippy-tutorial-active #root,
body.drippy-tutorial-active #stars-canvas,
body.drippy-tutorial-active #passive-canvas {
  filter: blur(5px) saturate(0.85);
}

/* 2× Drippy + bubble. Existing scale is 1.3 → 2.6 doubles the player's
   on-screen size while the tutorial runs. */
body.drippy-tutorial-active #coach-wrap {
  transform: scale(2.6) !important;
  z-index: 9600 !important;
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
body.drippy-tutorial-active #coach-bubble {
  max-width: 280px;
}
body.drippy-tutorial-active #coach-wrap.coach-visible #coach-bubble {
  box-shadow: 0 0 18px rgba(190, 110, 255, 0.85),
              0 0 36px rgba(140, 60, 230, 0.7),
              0 6px 22px rgba(130, 0, 255, 0.6);
}
#coach-wrap { transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1); }

/* Drippy Drop Tutorial — D+ button glow inside the Tamagotchi shell. */
#drippy-tree-btn.drippy-tutorial-glow {
  animation: drippyDPlusGlow 0.9s ease-in-out infinite alternate;
}
@keyframes drippyDPlusGlow {
  from {
    box-shadow: 0 0 10px rgba(160,112,204,0.6),
                inset 0 1px 2px rgba(255,255,255,0.25);
  }
  to {
    box-shadow: 0 0 24px 6px rgba(220,170,255,1),
                0 0 44px 12px rgba(180,120,240,0.85),
                inset 0 1px 2px rgba(255,255,255,0.45);
  }
}
/* Pointing hand sitting just to the right of the D+ button (which is
   centered at left:50%, top:44px, 55×55 in the shell). The hand points
   left at the button and bobs toward/away from it quickly. */
#drippy-tutorial-hand {
  position: absolute;
  top: 53px;
  left: calc(50% + 32px);
  font-size: 34px;
  line-height: 1;
  z-index: 6;
  pointer-events: none;
  user-select: none;
  filter: drop-shadow(0 0 4px rgba(255, 220, 140, 0.9));
  animation: drippyTutHandBob 0.42s ease-in-out infinite alternate;
}
@keyframes drippyTutHandBob {
  from { transform: translateX(14px); }
  to   { transform: translateX(0); }
}
/* Pointing-down hand prepended above Drippy's avatar column during the
   drippy drop tutorial. Bobs up and down to draw the player's eye. */
#drippy-above-hand {
  font-size: 22px;
  line-height: 1;
  pointer-events: none;
  user-select: none;
  filter: drop-shadow(0 0 4px rgba(255, 220, 140, 0.8));
  animation: drippyAboveHandBob 0.55s ease-in-out infinite alternate;
}
@keyframes drippyAboveHandBob {
  from { transform: translateY(0); }
  to   { transform: translateY(-8px); }
}

/* Close button on Drippy's tutorial bubble. The whole #coach-wrap is scaled
   2.6× during the tutorial, so the stock .ui-unlock-x sizing reads ~2× too
   large; halve font/padding so it fits the bubble at the scaled size. */
#drippy-tut-close.ui-unlock-x {
  font-size: 8px;
  padding: 1.5px 5px;
  top: 4px;
  right: 5px;
}

/* ─── Drippy Evolution (first-prestige cinematic) ──────────────────────── */
/* Same blur as drippy-tutorial-active. */
body.drippy-evolving #root,
body.drippy-evolving #stars-canvas,
body.drippy-evolving #passive-canvas {
  filter: blur(5px) saturate(0.85);
}
/* After the player accepts the revive, drop the background blur immediately
   even though the rest of the cinematic (2× Drippy jump) keeps playing. */
body.drippy-evolving.drippy-revive-noblur #root,
body.drippy-evolving.drippy-revive-noblur #stars-canvas,
body.drippy-evolving.drippy-revive-noblur #passive-canvas {
  filter: none;
}
/* 2× drippy + bubble during the cinematic. Overrides drippy-evolved's
   permanent 1.5× tall transform while evolving so the 2× wins. */
body.drippy-evolving #coach-wrap {
  transform: scale(2.6) !important;
  z-index: 9700 !important;
  transition: transform 0.45s cubic-bezier(0.34, 1.56, 0.64, 1);
}
/* Silver baseline filter so Drippy never snaps back to "normal color" between
   the pulse and spin animations — those each animate `filter` and override
   this while running, but the moment a pulse class drops the static silver
   shows through instead of a bare default look. */
body.drippy-evolving #coach-avatar {
  filter: drop-shadow(0 0 14px rgba(220,240,255,0.85))
          drop-shadow(0 0 28px rgba(180,210,255,0.7))
          brightness(1.4);
}
/* Hide the buff-icon stack and any floating event emojis above Drippy for
   the duration of his prestige cinematic — clean stage, no distractions. */
body.drippy-evolving #ge-effect-stack,
body.drippy-evolving #ge-icon,
body.drippy-evolving #golden-eggplant-portal,
body.drippy-evolving .golden-eggplant-emoji,
body.drippy-evolving .bad-eggplant-emoji,
body.drippy-evolving #droplet-storm-rain,
body.drippy-evolving #droplet-shower-rain,
body.drippy-evolving #cursed-squeeze-overlay,
body.drippy-evolving #small-curse-overlay,
body.drippy-evolving #big-curse-overlay,
body.drippy-evolving #golden-balls-overlay {
  display: none !important;
}
body.drippy-evolving #coach-bubble {
  max-width: 320px;
}
body.drippy-evolving #coach-wrap.coach-visible #coach-bubble {
  box-shadow: 0 0 18px rgba(220, 180, 255, 0.9),
              0 0 36px rgba(160, 100, 230, 0.75),
              0 6px 22px rgba(140, 40, 220, 0.65);
}
/* Click blocker — same fade-in idiom as the drippy-tutorial blocker. */
#drippy-evolve-blocker {
  position: fixed; inset: 0; z-index: 9650;
  background: rgba(8, 2, 16, 0.18);
  cursor: default; pointer-events: auto;
  animation: drippyTutFadeIn 0.4s ease both;
}

/* Phase 1 — pulse white + stretch tall/short, three sub-phases of
   increasing rate (0.55s → 0.30s → 0.13s). */
@keyframes coachEvolvePulse {
  0%   { transform: scaleY(0.85);
         filter: drop-shadow(0 0 12px rgba(220,240,255,0.85))
                 drop-shadow(0 0 24px rgba(180,210,255,0.65))
                 brightness(1.2); }
  50%  { transform: scaleY(1.35);
         filter: drop-shadow(0 0 22px rgba(255,255,255,1))
                 drop-shadow(0 0 36px rgba(220,170,255,0.85))
                 brightness(2.4); }
  100% { transform: scaleY(0.9);
         filter: drop-shadow(0 0 14px rgba(220,240,255,0.9))
                 drop-shadow(0 0 28px rgba(190,215,255,0.7))
                 brightness(1.35); }
}
#coach-avatar.coach-evolve-pulse-1,
#coach-avatar.coach-evolve-pulse-2,
#coach-avatar.coach-evolve-pulse-3 {
  transform-origin: bottom center;
  will-change: transform, filter;
}
#coach-avatar.coach-evolve-pulse-1 { animation: coachEvolvePulse 0.55s ease-in-out infinite alternate; }
#coach-avatar.coach-evolve-pulse-2 { animation: coachEvolvePulse 0.30s ease-in-out infinite alternate; }
#coach-avatar.coach-evolve-pulse-3 { animation: coachEvolvePulse 0.13s ease-in-out infinite alternate; }

/* Phase 2 — fast spin in place while still glowing. */
@keyframes coachEvolveSpin {
  from { transform: rotate(0deg)   scale(1.05);
         filter: drop-shadow(0 0 24px rgba(255,255,255,1))
                 drop-shadow(0 0 48px rgba(220,170,255,0.9))
                 brightness(2.5); }
  to   { transform: rotate(720deg) scale(1.1);
         filter: drop-shadow(0 0 32px rgba(255,255,255,1))
                 drop-shadow(0 0 64px rgba(220,170,255,1))
                 brightness(2.8); }
}
#coach-avatar.coach-evolve-spin {
  animation: coachEvolveSpin 0.55s linear infinite;
  transform-origin: 50% 60%;
  will-change: transform, filter;
}

/* Phase 3 — radial glow burst spawned over Drippy that expands and fades. */
#drippy-evolve-burst {
  position: fixed;
  width: 40px; height: 40px;
  border-radius: 50%;
  background: radial-gradient(circle,
    rgba(255,255,255,1) 0%,
    rgba(230,200,255,0.95) 25%,
    rgba(180,120,235,0.7) 55%,
    rgba(120,50,200,0.0) 100%);
  transform: translate(-50%, -50%);
  pointer-events: none;
  z-index: 9999;
  mix-blend-mode: screen;
  animation: drippyEvolveBurst 1.2s ease-out forwards;
}
@keyframes drippyEvolveBurst {
  0%   { width:   40px; height:   40px; opacity: 1; }
  60%  { width: 1400px; height: 1400px; opacity: 1; }
  100% { width: 1900px; height: 1900px; opacity: 0; }
}

/* Persistent post-evolution: silver color tint + pulsing silver glow. Applied
   while body.drippy-evolved is set AND the evolving cinematic isn't running.
   filter is set directly on the rule (not just in keyframes) so the silver
   holds even during the brief animation: none reset in show() — that inline
   override stops the animation but the CSS rule's filter still applies,
   preventing the transition: filter 0.5s on #coach-avatar from fading him out. */
body.drippy-evolved:not(.drippy-evolving) #coach-avatar {
  /* Drippy II+ keeps his default / player-chosen color — no silver recolor or
     glow. Matches the base #coach-avatar filter so he looks like normal Drippy. */
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.7)) brightness(var(--coach-brightness, 1));
}
@keyframes drippyEvolvedSilver {
  from {
    filter: grayscale(1) brightness(1.55)
            drop-shadow(0 2px 6px rgba(0,0,0,0.7))
            drop-shadow(0 0  8px rgba(210, 230, 250, 0.55))
            drop-shadow(0 0 16px rgba(180, 200, 230, 0.4));
  }
  to {
    filter: grayscale(1) brightness(1.55)
            drop-shadow(0 2px 6px rgba(0,0,0,0.7))
            drop-shadow(0 0 18px rgba(230, 245, 255, 1))
            drop-shadow(0 0 36px rgba(200, 230, 255, 0.7));
  }
}
/* When a Drippy skin is equipped the player chose a custom look — keep the
   silver glow but drop the grayscale so their skin colors show through. */
body.drippy-evolved.drippy-coach-skin-active:not(.drippy-evolving) #coach-avatar {
  /* Skin equipped: also no evolved recolor/glow — show the player's chosen look. */
  filter: drop-shadow(0 2px 6px rgba(0,0,0,0.7)) brightness(var(--coach-brightness, 1));
}
@keyframes drippyEvolvedGlowOnly {
  from {
    filter: drop-shadow(0 2px 6px rgba(0,0,0,0.7))
            drop-shadow(0 0  8px rgba(210, 230, 250, 0.55))
            drop-shadow(0 0 16px rgba(180, 200, 230, 0.4));
  }
  to {
    filter: drop-shadow(0 2px 6px rgba(0,0,0,0.7))
            drop-shadow(0 0 18px rgba(230, 245, 255, 1))
            drop-shadow(0 0 36px rgba(200, 230, 255, 0.7));
  }
}
/* Silver name styling for evolved Drippy. */
body.drippy-evolved #coach-name {
  color: #c8d8ec;
  text-shadow: 0 0 6px rgba(200,220,255,0.7);
}

/* "Drippy has evolved into Drippy II!" banner — fades + scales in. */
#drippy-evolve-bigtext {
  position: fixed;
  inset: 0;
  display: flex; align-items: center; justify-content: center;
  text-align: center;
  font-family: inherit;
  font-size: 56px;
  font-weight: 900;
  color: #fff;
  text-shadow:
    0 0 16px rgba(220,170,255,1),
    0 0 36px rgba(160, 90,220,0.95),
    0 0 60px rgba(100, 40,180,0.85),
    0 4px 18px rgba(0,0,0,0.9);
  z-index: 10000;
  pointer-events: none;
  letter-spacing: 1px;
  padding: 0 6vw;
  opacity: 0;
  transform: scale(0.7);
  transition: opacity 0.5s ease, transform 0.55s cubic-bezier(0.34, 1.56, 0.64, 1);
}
#drippy-evolve-bigtext.show {
  opacity: 1;
  transform: scale(1);
}

/* ─── Drippy Revival (first-prestige, dead-Drippy branch) ──────────────── */
/* Rose fading in at the bottom of the gravestone. The avatar already gets
   2× via body.drippy-evolving so the rose tags along. */
.drippy-revive-rose {
  position: absolute;
  left: 50%;
  bottom: -8px;
  font-size: 22px;
  line-height: 1;
  transform: translateX(-50%) translateY(8px);
  opacity: 0;
  filter: drop-shadow(0 1px 4px rgba(0,0,0,0.65));
  animation: drippyRoseIn 1.4s ease-out forwards;
  pointer-events: none;
}
@keyframes drippyRoseIn {
  to { opacity: 1; transform: translateX(-50%) translateY(0); }
}
.drippy-revive-rose.fade-out {
  animation: drippyRoseOut 0.6s ease-in forwards;
}
@keyframes drippyRoseOut {
  from { opacity: 1; transform: translateX(-50%) translateY(0); }
  to   { opacity: 0; transform: translateX(-50%) translateY(-12px); }
}

/* Click blocker behind the prompts. */
#drippy-revive-blocker {
  position: fixed; inset: 0; z-index: 9650;
  background: rgba(8, 2, 16, 0.18);
  cursor: default; pointer-events: auto;
  animation: drippyTutFadeIn 0.4s ease both;
}

/* 50% black screen dim that appears with the prompt. */
#drippy-revive-black {
  position: fixed; inset: 0; z-index: 9680;
  background: rgba(0, 0, 0, 0);
  pointer-events: none;
  transition: background 0.7s ease;
}
#drippy-revive-black.show { background: rgba(0, 0, 0, 0.5); }

/* Prompt card with question + yes/no buttons. */
#drippy-revive-prompt {
  position: fixed;
  left: 50%; top: 38%;
  transform: translate(-50%, -50%) scale(0.92);
  z-index: 9690;
  padding: 26px 36px 28px;
  background: rgba(18, 6, 28, 0.92);
  border: 2px solid rgba(180, 140, 230, 0.45);
  border-radius: 14px;
  box-shadow: 0 0 32px rgba(120, 60, 180, 0.55),
              0 12px 40px rgba(0, 0, 0, 0.7);
  text-align: center;
  opacity: 0;
  transition: opacity 0.32s ease, transform 0.32s cubic-bezier(0.34, 1.56, 0.64, 1);
  pointer-events: auto;
  max-width: 460px;
}
#drippy-revive-prompt.show {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}
.drippy-revive-prompt-text {
  font-size: 28px;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 0 12px rgba(220,170,255,0.8), 0 2px 8px rgba(0,0,0,0.9);
  letter-spacing: 0.3px;
  margin-bottom: 22px;
  line-height: 1.25;
}
.drippy-revive-btnrow {
  display: flex; gap: 18px; justify-content: center;
}
.drippy-revive-btn {
  font: inherit;
  font-size: 17px;
  font-weight: 800;
  padding: 10px 30px;
  border-radius: 9px;
  cursor: pointer;
  transition: transform 0.12s ease, box-shadow 0.18s ease, filter 0.18s ease;
  letter-spacing: 0.5px;
}
.drippy-revive-btn:hover  { transform: translateY(-1px); filter: brightness(1.1); }
.drippy-revive-btn:active { transform: translateY(0);    filter: brightness(0.95); }
.drippy-revive-yes {
  background: linear-gradient(160deg, #5a3aa8 0%, #2a1a6a 100%);
  border: 2px solid #b497e0;
  color: #fff;
  box-shadow: 0 0 14px rgba(160,112,204,0.55);
}
.drippy-revive-yes:hover { box-shadow: 0 0 22px rgba(180,148,224,0.9); }
.drippy-revive-no {
  background: linear-gradient(160deg, #3a2030 0%, #1a0a18 100%);
  border: 2px solid #6a4a60;
  color: #d8c8d4;
}

/* Standalone fade-in/out flash text used for "Very well" + "He is yours
   again." Sits a bit above the prompt zone. */
#drippy-revive-flashline {
  position: fixed;
  left: 50%; top: 38%;
  transform: translate(-50%, -50%) scale(0.85);
  z-index: 9695;
  font-size: 32px;
  font-weight: 900;
  color: #fff;
  text-shadow: 0 0 14px rgba(220,170,255,0.95),
               0 0 30px rgba(160,90,220,0.85),
               0 4px 14px rgba(0,0,0,0.9);
  letter-spacing: 0.5px;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.5s ease, transform 0.5s cubic-bezier(0.34, 1.56, 0.64, 1);
  padding: 0 6vw;
}
#drippy-revive-flashline.show {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

/* Drippy jumping out of the grave. Brief upward arc + scale, then return
   to rest position. The class is added/removed on #coach-avatar. */
@keyframes drippyReviveJump {
  0%   { transform: translateY(0)    scale(1);   }
  35%  { transform: translateY(-90px) scale(1.15); }
  70%  { transform: translateY(-30px) scale(1.05); }
  100% { transform: translateY(0)    scale(1);   }
}
#coach-avatar.drippy-revive-jump {
  animation: drippyReviveJump 1.3s cubic-bezier(0.34, 1.56, 0.64, 1) both;
  filter: drop-shadow(0 6px 18px rgba(220, 180, 255, 0.6))
          drop-shadow(0 0 22px rgba(180, 120, 240, 0.5));
}

/* Sub-line in the buff tooltip describing the multiplier. */
.drippy-revive-buff .ge-effect-tooltip {
  min-width: 200px;
  max-width: 230px;
  white-space: normal;   /* override the base nowrap so the description wraps */
  line-height: 1.35;
}
.drippy-revive-buff .ge-effect-tooltip-sub {
  font-size: 11px;
  color: #ff9a9a;
  margin-top: 4px;
  letter-spacing: 0.02em;
}
.drippy-revive-buff .ge-effect-tooltip-sub b { color: #ffd0d0; }

/* Golden tier nodes in the Drippy skill tree (unlocked post-evolution). */
.drippy-node.golden {
  background: linear-gradient(160deg, #ffd54a 0%, #b88e1a 100%);
  border: 2px solid #ffe896;
  box-shadow: 0 0 14px rgba(255, 215, 90, 0.55), inset 0 1px 2px rgba(255,255,255,0.4);
  color: #2a1900;
}
.drippy-node.golden .drippy-node-name,
.drippy-node.golden .drippy-node-cost { color: #2a1900; }
.drippy-node.golden.locked {
  background: linear-gradient(160deg, #4a3a10 0%, #2a200a 100%);
  border-color: #6a521a;
  box-shadow: none;
  color: #6a521a;
  filter: grayscale(0.6);
}
.drippy-node.golden.locked .drippy-node-name,
.drippy-node.golden.locked .drippy-node-cost { color: #8a6f30; }
.drippy-node.golden.affordable {
  animation: drippyGoldPulse 1.6s ease-in-out infinite alternate;
}
@keyframes drippyGoldPulse {
  from { box-shadow: 0 0 14px rgba(255, 215,  90, 0.55),
                     inset 0 1px 2px rgba(255,255,255,0.4); }
  to   { box-shadow: 0 0 26px rgba(255, 235, 130, 0.95),
                     0 0 50px rgba(255, 200,  80, 0.6),
                     inset 0 1px 2px rgba(255,255,255,0.55); }
}

/* ─── From cock_magic.js ─────────────────────────────────────────────────── */
#upg-card-cock_magic { margin-top: 5px; }
#cm-panel { padding: 8px 10px 10px; border-top: 1px solid #3a1828; }
#cm-juice-row { display:flex; align-items:center; gap:7px; margin-bottom:8px; }
#cm-juice-label { font-size:13px; font-weight:700; color:#e0a0d0; white-space:nowrap; }
#cm-juice-track { flex:1; height:13px; background:#180b12; border-radius:6px; overflow:hidden; border:1px solid #3a1828; position:relative; cursor:default; }
#cm-juice-fill { height:100%; background:linear-gradient(90deg,#8030b0,#d050f0); border-radius:4px; transition:width 0.25s ease; }
#cm-juice-pct { font-size:10px; color:#6a4568; min-width:28px; text-align:right; white-space:nowrap; }
#cm-spells { display:grid; grid-template-columns:1fr 1fr; gap:4px; }
.cm-spell-btn {
  background:#1c0e18; border:1px solid #3a1828; border-radius:7px;
  padding:6px 7px; cursor:pointer; display:flex; flex-direction:column;
  gap:2px; text-align:left; transition:background 0.12s, border-color 0.12s;
}
.cm-spell-btn:hover:not(:disabled) { background:#27122a; border-color:#7040a0; }
.cm-spell-btn:disabled { opacity:0.4; cursor:not-allowed; }
.cm-spell-btn.cm-can { border-color:#7040b0; }
.cm-spell-btn.cm-active { border-color:#c060ff; background:#220e2a; animation:cmGlow 1.2s ease-in-out infinite; }
.cm-spell-row { display:flex; align-items:center; gap:5px; }
.cm-spell-icon { font-size:15px; line-height:1; }
.cm-spell-name { font-size:12px; font-weight:700; color:#e0a0c0; flex:1; }
.cm-spell-cost { font-size:11px; color:#a060d0; font-weight:700; white-space:nowrap; }
.cm-spell-desc { font-size:10px; color:#7a5070; line-height:1.3; }
@keyframes cmGlow {
  0%,100% { box-shadow:0 0 4px rgba(192,80,255,0.25); }
  50%      { box-shadow:0 0 10px rgba(192,80,255,0.65); }
}

/* ─── From cursed_squeeze.js ─────────────────────────────────────────────── */
@keyframes cursedPulse {
  0%,100% { box-shadow: 0 0 18px rgba(140,0,220,0.85),
                        0 0 4px  rgba(180,0,255,0.55),
                        inset 0 0 36px rgba(0,0,0,0.45); }
  50%     { box-shadow: 0 0 36px rgba(180,0,255,1),
                        0 0 10px rgba(220,80,255,0.7),
                        inset 0 0 42px rgba(20,0,40,0.55); }
}
#cylinder.cursed-active {
  background: linear-gradient(to right,
              #4a1c66 0%, #6a2c8c 35%, #5a2278 65%, #3e1456 100%) !important;
  border-color: #9040d0 !important;
  animation: cursedPulse 0.55s ease-in-out infinite !important;
}
#tip.cursed-active {
  filter: brightness(0.55) saturate(0.6) hue-rotate(220deg)
          drop-shadow(0 0 14px rgba(180,0,255,0.95)) !important;
}
#cursed-arrow-svg {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  /* Anchored on top of the cylinder body (cylinder-wrap top:330) so the arrow
     overlays the cylinder rather than floating above it. Grows downward to
     show the squeeze direction. */
  top: 335px;
  z-index: 9;
  pointer-events: none;
  overflow: visible;
}
.cursed-toast {
  position: absolute; left: 50%; top: 120px; z-index: 102;
  font-size: 24px; font-weight: 700; color: #cc44ff;
  text-shadow: 0 0 12px rgba(180,0,255,0.9), 0 0 28px rgba(120,0,200,0.6);
  pointer-events: none; white-space: nowrap;
  transform: translateX(-50%);
  animation: milestoneFloat 2.5s ease-out forwards;
}
.cursed-pip-wrap {
  position: absolute; left: 50%; top: 170px; z-index: 102;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 6px; pointer-events: none;
}
.cursed-pip-row {
  display: flex; gap: 9px;
}
.cursed-pip {
  width: 20px; height: 20px; border-radius: 50%;
  border: 2px solid rgba(180,0,255,0.65);
  background: #150020;
  transition: background 0.2s, box-shadow 0.2s;
}
.cursed-pip.filled {
  background: #cc44ff;
  box-shadow: 0 0 9px rgba(200,0,255,0.9), 0 0 20px rgba(150,0,200,0.55);
}
.cursed-relieved-toast {
  position: absolute; left: 50%; top: 400px; z-index: 102;
  font-size: 26px; font-weight: 700; color: #ffcc00;
  text-shadow: 0 0 14px rgba(255,200,0,0.9), 0 0 30px rgba(200,150,0,0.6);
  pointer-events: none; white-space: nowrap;
  transform: translateX(-50%);
  animation: milestoneFloat 2.5s ease-out forwards;
}

/* ─── From double_fist.js ────────────────────────────────────────────────── */
#upg-card-double_fist { margin-top: 5px; }
.df-fist {
  position: absolute;
  font-size: 93px;
  line-height: 1;
  opacity: 0.35;
  pointer-events: none;
  filter: brightness(0.82) saturate(1.5);
  display: none;
  user-select: none;
}

/* ─── From golden_eggplant.js ────────────────────────────────────────────── */
/* ── Idle glow animations ── */
@keyframes geGlow {
  0%,100% { transform:translate(-50%,-50%) scale(1);
            filter:sepia(1) saturate(5) hue-rotate(-10deg) brightness(1.4)
                   drop-shadow(0 0 14px #ffd700) drop-shadow(0 0 30px #ff9900); }
  50%      { transform:translate(-50%,-50%) scale(1.18);
            filter:sepia(1) saturate(6) hue-rotate(-10deg) brightness(1.7)
                   drop-shadow(0 0 28px #ffd700) drop-shadow(0 0 55px #ff9900)
                   drop-shadow(0 0 80px rgba(255,180,0,0.45)); }
}
@keyframes geGlowBronze {
  0%,100% { transform:translate(-50%,-50%) scale(0.9);
            filter:sepia(1) saturate(3) hue-rotate(20deg) brightness(1.0)
                   drop-shadow(0 0 12px #cd7f32) drop-shadow(0 0 26px #8b4513); }
  50%     { transform:translate(-50%,-50%) scale(1.25);
            filter:sepia(1) saturate(3.5) hue-rotate(20deg) brightness(1.3)
                   drop-shadow(0 0 26px #cd7f32) drop-shadow(0 0 52px #a0522d)
                   drop-shadow(0 0 80px rgba(180,100,30,0.5)); }
}
@keyframes geGlowSilver {
  0%,100% { transform:translate(-50%,-50%) scale(0.88);
            filter:grayscale(1) brightness(1.9) contrast(1.1)
                   drop-shadow(0 0 16px #e8e8e8) drop-shadow(0 0 34px #b0b8d0); }
  50%     { transform:translate(-50%,-50%) scale(1.32);
            filter:grayscale(1) brightness(2.4) contrast(1.15)
                   drop-shadow(0 0 38px #ffffff) drop-shadow(0 0 74px #d0d8f0)
                   drop-shadow(0 0 108px rgba(200,210,255,0.55)); }
}
@keyframes geGlowGold {
  0%,100% { transform:translate(-50%,-50%) scale(0.85);
            filter:sepia(1) saturate(8) hue-rotate(0deg) brightness(2.2)
                   drop-shadow(0 0 22px #ffd700) drop-shadow(0 0 52px #ff9900)
                   drop-shadow(0 0 100px rgba(255,200,0,0.5)); }
  50%     { transform:translate(-50%,-50%) scale(1.4);
            filter:sepia(1) saturate(9) hue-rotate(0deg) brightness(2.9)
                   drop-shadow(0 0 44px #ffe866) drop-shadow(0 0 88px #ffb033)
                   drop-shadow(0 0 130px rgba(255,200,0,0.65)); }
}

/* ── Click flash animations ── */
@keyframes geFadeOut {
  0%   { opacity:1; transform:translate(-50%,-50%) scale(1); }
  100% { opacity:0; transform:translate(-50%,-50%) scale(0.5); }
}
@keyframes geFlashGood {
  0%   { transform:translate(-50%,-50%) scale(1);   filter:sepia(1) saturate(6) hue-rotate(60deg)  brightness(1.8) drop-shadow(0 0 30px #00ff88) drop-shadow(0 0 60px #00cc44); }
  50%  { transform:translate(-50%,-50%) scale(1.5); filter:sepia(1) saturate(9) hue-rotate(80deg)  brightness(2.8) drop-shadow(0 0 55px #00ff88) drop-shadow(0 0 110px #00ff00); }
  100% { transform:translate(-50%,-50%) scale(1.3); filter:sepia(1) saturate(7) hue-rotate(70deg)  brightness(2.2) drop-shadow(0 0 40px #00ff88); }
}
@keyframes geFlashBad {
  0%   { transform:translate(-50%,-50%) scale(1);   filter:sepia(1) saturate(6) hue-rotate(-30deg) brightness(1.8) drop-shadow(0 0 30px #ff4444) drop-shadow(0 0 60px #cc0000); }
  50%  { transform:translate(-50%,-50%) scale(1.5); filter:sepia(1) saturate(9) hue-rotate(-50deg) brightness(2.8) drop-shadow(0 0 55px #ff4444) drop-shadow(0 0 110px #ff0000); }
  100% { transform:translate(-50%,-50%) scale(1.3); filter:sepia(1) saturate(7) hue-rotate(-40deg) brightness(2.2) drop-shadow(0 0 40px #ff4444); }
}
@keyframes geFlashGoodSilver {
  0%   { transform:translate(-50%,-50%) scale(1);   filter:grayscale(1) brightness(2.0) contrast(1.1) drop-shadow(0 0 30px #e0e0e0) drop-shadow(0 0 60px #b0b8d0); }
  50%  { transform:translate(-50%,-50%) scale(1.5); filter:grayscale(1) brightness(3.0) contrast(1.2) drop-shadow(0 0 55px #ffffff) drop-shadow(0 0 110px #d0d8f0); }
  100% { transform:translate(-50%,-50%) scale(1.3); filter:grayscale(1) brightness(2.4) contrast(1.1) drop-shadow(0 0 40px #e8e8e8); }
}
@keyframes geFlashGoodGold {
  0%   { transform:translate(-50%,-50%) scale(1);   filter:sepia(1) saturate(8) hue-rotate(0deg)   brightness(2.0) drop-shadow(0 0 30px #ffd700); }
  30%  { transform:translate(-50%,-50%) scale(1.6); filter:sepia(1) saturate(8) hue-rotate(120deg) brightness(3.2) drop-shadow(0 0 65px #40ff88) drop-shadow(0 0 130px #00ff44); }
  65%  { transform:translate(-50%,-50%) scale(1.8); filter:sepia(1) saturate(8) hue-rotate(240deg) brightness(3.6) drop-shadow(0 0 85px #aa44ff) drop-shadow(0 0 160px #8800ff); }
  100% { transform:translate(-50%,-50%) scale(1.5); filter:sepia(1) saturate(8) hue-rotate(360deg) brightness(2.5) drop-shadow(0 0 50px #ffd700) drop-shadow(0 0 100px #ffaa00); }
}

/* ── Droplet portal (wide, narrow oval with pulsing rainbow glow) ── */
#golden-eggplant {
  position: fixed;
  z-index: 9000;
  transform: translate(-50%, -50%);
  user-select: none;
  pointer-events: none; /* triggered by droplet collision, not clicks */
}
#golden-eggplant.ge-portal {
  border-radius: 50%;
  background: radial-gradient(ellipse at center,
      rgba(255,255,255,0.95) 0%,
      rgba(255,220,255,0.65) 22%,
      rgba(180,160,255,0.45) 45%,
      rgba(120,80,220,0.25) 72%,
      rgba(60,20,120,0) 100%);
  border: 2px solid rgba(255,255,255,0.7);
  animation: gePortalPulse 1.8s linear infinite,
             gePortalBreathe 1.3s ease-in-out infinite;
}
/* Tier size comes from inline style; tiers add tier-colored backgrounds + glows */
#golden-eggplant.ge-portal.tier-bronze {
  background: radial-gradient(ellipse at center,
      rgba(255,222,160,0.95) 0%,
      rgba(220,158,68,0.65)  22%,
      rgba(178,98,22,0.45)   45%,
      rgba(120,58,8,0.25)    72%,
      rgba(80,40,0,0)        100%);
  border-color: rgba(220,158,68,0.8);
  animation: gePortalPulseBronze 1.8s ease-in-out infinite,
             gePortalBreatheBronze 1.35s ease-in-out infinite;
}
#golden-eggplant.ge-portal.tier-silver {
  background: radial-gradient(ellipse at center,
      rgba(240,245,255,0.95) 0%,
      rgba(200,212,242,0.65) 22%,
      rgba(155,165,210,0.45) 45%,
      rgba(100,110,170,0.25) 72%,
      rgba(50,58,120,0)      100%);
  border-color: rgba(200,212,245,0.8);
  animation: gePortalPulseSilver 1.5s ease-in-out infinite,
             gePortalBreatheSilver 1.15s ease-in-out infinite;
}
#golden-eggplant.ge-portal.tier-gold {
  background: radial-gradient(ellipse at center,
      rgba(255,252,200,0.95) 0%,
      rgba(255,220,55,0.65)  22%,
      rgba(218,152,0,0.45)   45%,
      rgba(158,92,0,0.25)    72%,
      rgba(80,44,0,0)        100%);
  border-color: rgba(255,220,55,0.85);
  animation: gePortalPulseGold 1.2s ease-in-out infinite,
             gePortalBreatheGold 0.95s ease-in-out infinite;
}
#golden-eggplant.ge-fading   { animation: gePortalFadeOut 0.35s ease-in forwards; }
#golden-eggplant.ge-flash-bad  { animation: gePortalFlashBad  0.35s ease-out forwards; }
#golden-eggplant.ge-flash-good { animation: gePortalFlashGood 0.35s ease-out forwards; }
#golden-eggplant.tier-bronze.ge-flash-good { animation: gePortalFlashBronze 0.35s ease-out forwards; }
#golden-eggplant.tier-silver.ge-flash-good { animation: gePortalFlashSilver 0.4s ease-out forwards; }
#golden-eggplant.tier-gold.ge-flash-good   { animation: gePortalFlashGold   0.55s ease-out forwards; }

/* Upward glow plume emitted from the top of a portal when triggered. */
#golden-eggplant.ge-portal::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: 50%;
  width: 80%;
  height: 260px;
  transform: translateX(-50%) scaleY(0) scaleX(0.5);
  transform-origin: bottom center;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(ellipse 55% 100% at 50% 100%,
      rgba(255,255,255,0.95) 0%,
      rgba(255,240,190,0.70) 18%,
      rgba(255,200,120,0.35) 42%,
      rgba(255,160,80,0)     75%);
  border-radius: 50%;
  filter: blur(8px);
}
#golden-eggplant.ge-portal.tier-silver::after {
  background: radial-gradient(ellipse 55% 100% at 50% 100%,
      rgba(255,255,255,0.95) 0%,
      rgba(220,232,255,0.70) 18%,
      rgba(170,190,255,0.35) 42%,
      rgba(120,150,220,0)    75%);
}
#golden-eggplant.ge-portal.tier-gold::after {
  background: radial-gradient(ellipse 55% 100% at 50% 100%,
      rgba(255,255,230,0.98) 0%,
      rgba(255,230,100,0.80) 18%,
      rgba(255,190,30,0.42)  42%,
      rgba(255,160,0,0)      75%);
  filter: blur(10px);
}
#golden-eggplant.ge-flash-good::after,
#golden-eggplant.ge-flash-bad::after {
  animation: gePortalTopBeam 0.9s ease-out forwards;
}
#golden-eggplant.tier-gold.ge-flash-good::after {
  animation: gePortalTopBeam 1.1s ease-out forwards;
}
@keyframes gePortalTopBeam {
  0%   { opacity: 0;   transform: translateX(-50%) scaleY(0)   scaleX(0.5); }
  20%  { opacity: 1;   transform: translateX(-50%) scaleY(1)   scaleX(1);   }
  60%  { opacity: 0.9; transform: translateX(-50%) scaleY(1.2) scaleX(0.85);}
  100% { opacity: 0;   transform: translateX(-50%) scaleY(1.5) scaleX(0.4); }
}

/* Rainbow pulse sweep — mirrors cylTranscendentGlow hue cycle. */
@keyframes gePortalPulse {
  0%,100% { box-shadow: 0 0 22px #ff4080, 0 0 48px rgba(255,0,96,0.55),  inset 0 0 18px rgba(255,128,200,0.55); border-color: rgba(255,120,180,0.85); }
  14%     { box-shadow: 0 0 22px #ff8040, 0 0 48px rgba(255,102,0,0.55), inset 0 0 18px rgba(255,180,128,0.55); border-color: rgba(255,170,130,0.85); }
  28%     { box-shadow: 0 0 22px #ffe060, 0 0 48px rgba(255,224,0,0.55), inset 0 0 18px rgba(255,240,160,0.55); border-color: rgba(255,230,140,0.85); }
  42%     { box-shadow: 0 0 22px #60e070, 0 0 48px rgba(0,221,0,0.55),   inset 0 0 18px rgba(160,240,170,0.55); border-color: rgba(130,230,150,0.85); }
  57%     { box-shadow: 0 0 22px #40a0ff, 0 0 48px rgba(0,170,255,0.55), inset 0 0 18px rgba(140,200,255,0.55); border-color: rgba(120,180,255,0.85); }
  71%     { box-shadow: 0 0 22px #b060ff, 0 0 48px rgba(136,0,255,0.55), inset 0 0 18px rgba(200,160,255,0.55); border-color: rgba(190,130,255,0.85); }
  85%     { box-shadow: 0 0 22px #ff60d0, 0 0 48px rgba(255,0,204,0.55), inset 0 0 18px rgba(255,170,230,0.55); border-color: rgba(255,140,220,0.85); }
}
@keyframes gePortalBreathe {
  0%,100% { transform: translate(-50%,-50%) scale(1);    filter: brightness(1);   }
  50%     { transform: translate(-50%,-50%) scale(1.10); filter: brightness(1.25);}
}
@keyframes gePortalBreatheBronze {
  0%,100% { transform: translate(-50%,-50%) scale(0.95); filter: brightness(0.95);}
  50%     { transform: translate(-50%,-50%) scale(1.10); filter: brightness(1.2); }
}
@keyframes gePortalBreatheSilver {
  0%,100% { transform: translate(-50%,-50%) scale(1);    filter: brightness(1.1); }
  50%     { transform: translate(-50%,-50%) scale(1.14); filter: brightness(1.35);}
}
@keyframes gePortalBreatheGold {
  0%,100% { transform: translate(-50%,-50%) scale(1.02); filter: brightness(1.2); }
  50%     { transform: translate(-50%,-50%) scale(1.2);  filter: brightness(1.6); }
}
@keyframes gePortalPulseBronze {
  0%,100% { box-shadow: 0 0 22px #cd7f32, 0 0 50px rgba(178,98,22,0.65),  inset 0 0 18px rgba(255,190,90,0.5);  border-color: rgba(218,155,58,0.85); }
  50%     { box-shadow: 0 0 38px #e8a040, 0 0 75px rgba(218,132,38,0.85), inset 0 0 28px rgba(255,215,130,0.7); border-color: rgba(255,188,88,0.95); }
}
@keyframes gePortalPulseSilver {
  0%,100% { box-shadow: 0 0 22px #b0bcd8, 0 0 50px rgba(155,165,215,0.65), inset 0 0 18px rgba(215,222,255,0.5);  border-color: rgba(195,208,242,0.85); }
  50%     { box-shadow: 0 0 38px #ccd6ff, 0 0 75px rgba(178,190,255,0.85),  inset 0 0 28px rgba(232,238,255,0.7); border-color: rgba(218,228,255,0.95); }
}
@keyframes gePortalPulseGold {
  0%,100% { box-shadow: 0 0 28px #ffd700, 0 0 60px rgba(255,198,0,0.70),  inset 0 0 20px rgba(255,240,128,0.55); border-color: rgba(255,215,48,0.85); }
  50%     { box-shadow: 0 0 50px #ffe84d, 0 0 100px rgba(255,220,0,0.90), inset 0 0 35px rgba(255,252,178,0.75); border-color: rgba(255,240,108,0.95); }
}
@keyframes gePortalFlashBronze {
  0%   { transform: translate(-50%,-50%) scale(1);    filter: brightness(1.6) saturate(1.8); box-shadow: 0 0 40px #fff8ec, 0 0 90px rgba(220,138,38,0.85); }
  50%  { transform: translate(-50%,-50%) scale(1.55); filter: brightness(3.2) saturate(2.2); box-shadow: 0 0 70px #fffbe0, 0 0 150px rgba(218,128,18,0.95); }
  100% { transform: translate(-50%,-50%) scale(1.35); filter: brightness(2) saturate(1.4);   box-shadow: 0 0 50px rgba(220,138,38,0.6); opacity: 0.6; }
}
@keyframes gePortalFlashSilver {
  0%   { transform: translate(-50%,-50%) scale(1);    filter: brightness(1.6) saturate(1.4); box-shadow: 0 0 40px #ffffff, 0 0 90px rgba(178,192,255,0.85); }
  50%  { transform: translate(-50%,-50%) scale(1.55); filter: brightness(3.5) saturate(1.6); box-shadow: 0 0 70px #f0f4ff, 0 0 150px rgba(198,212,255,0.95); }
  100% { transform: translate(-50%,-50%) scale(1.35); filter: brightness(2) saturate(1.2);   box-shadow: 0 0 50px rgba(178,192,255,0.6); opacity: 0.6; }
}
@keyframes gePortalFlashGold {
  0%   { transform: translate(-50%,-50%) scale(1);    filter: brightness(1.6) saturate(2.0); box-shadow: 0 0 40px #ffffff, 0 0 90px rgba(255,218,0,0.9); }
  50%  { transform: translate(-50%,-50%) scale(1.6);  filter: brightness(3.8) saturate(2.5); box-shadow: 0 0 80px #fffce0, 0 0 180px rgba(255,215,0,1.0); }
  100% { transform: translate(-50%,-50%) scale(1.4);  filter: brightness(2.2) saturate(1.6); box-shadow: 0 0 60px rgba(255,215,0,0.7); opacity: 0.6; }
}
@keyframes gePortalFadeOut {
  0%   { opacity: 1; transform: translate(-50%,-50%) scale(1); }
  100% { opacity: 0; transform: translate(-50%,-50%) scale(0.55); }
}
@keyframes gePortalFlashGood {
  0%   { transform: translate(-50%,-50%) scale(1);    filter: brightness(1.6) saturate(1.8); box-shadow: 0 0 40px #ffffff, 0 0 90px rgba(120,255,180,0.85); }
  50%  { transform: translate(-50%,-50%) scale(1.55); filter: brightness(3.2) saturate(2.2); box-shadow: 0 0 70px #ffffff, 0 0 150px rgba(60,255,160,0.95); }
  100% { transform: translate(-50%,-50%) scale(1.35); filter: brightness(2) saturate(1.4);   box-shadow: 0 0 50px rgba(120,255,180,0.6); opacity: 0.6; }
}
@keyframes gePortalFlashBad {
  0%   { transform: translate(-50%,-50%) scale(1);    filter: brightness(1.6) saturate(1.8); box-shadow: 0 0 40px #ffffff, 0 0 90px rgba(255,80,80,0.85); }
  50%  { transform: translate(-50%,-50%) scale(1.55); filter: brightness(3.2) saturate(2.2); box-shadow: 0 0 70px #ffffff, 0 0 150px rgba(255,40,40,0.95); }
  100% { transform: translate(-50%,-50%) scale(1.35); filter: brightness(2) saturate(1.4);   box-shadow: 0 0 50px rgba(255,80,80,0.6); opacity: 0.6; }
}

/* ── Effect toasts ── */
@keyframes geToastFloat {
  0%   { opacity:0;  transform:translateX(-50%) translateY(0); }
  12%  { opacity:1; }
  70%  { opacity:1; }
  100% { opacity:0;  transform:translateX(-50%) translateY(-110px); }
}
.ge-toast {
  position: fixed;
  z-index: 10000;
  font-size: 27px;
  font-weight: 700;
  color: #ffd700;
  text-shadow: 0 0 12px rgba(255,215,0,0.9), 0 0 26px rgba(255,160,0,0.6);
  pointer-events: none;
  white-space: nowrap;
  transform: translateX(-50%);
  animation: geToastFloat 2.4s ease-out forwards;
}
.ge-toast.negative {
  color: #ff6060;
  text-shadow: 0 0 12px rgba(255,80,80,0.9), 0 0 26px rgba(200,0,0,0.5);
}
.ge-toast.silver {
  color: #b8ddff;
  text-shadow: 0 0 12px rgba(120,180,255,0.9), 0 0 26px rgba(80,140,255,0.6);
}
.ge-toast.gold {
  font-size: 34px;
  color: #ffd700;
  text-shadow: 0 0 14px rgba(255,215,0,1), 0 0 32px rgba(255,160,0,0.85), 0 0 56px rgba(255,100,0,0.5);
}

/* ── Spawn announcement (silver/gold only) ── */
@keyframes geAnnounceFloat {
  0%   { opacity:0;  transform:translateX(-50%) translateY(0) scale(0.8); }
  15%  { opacity:1;  transform:translateX(-50%) translateY(0) scale(1.05); }
  30%  { transform:translateX(-50%) translateY(0) scale(1); }
  75%  { opacity:1; }
  100% { opacity:0;  transform:translateX(-50%) translateY(-70px); }
}
.ge-announce {
  position: fixed;
  z-index: 10001;
  font-weight: 700;
  pointer-events: none;
  white-space: nowrap;
  transform: translateX(-50%);
  animation: geAnnounceFloat 2s ease-out forwards;
}
.ge-announce.silver {
  font-size: 19px;
  color: #b8ddff;
  text-shadow: 0 0 10px rgba(120,180,255,0.9), 0 0 22px rgba(80,140,255,0.55);
}
.ge-announce.gold {
  font-size: 26px;
  color: #ffd700;
  text-shadow: 0 0 14px rgba(255,215,0,1), 0 0 30px rgba(255,160,0,0.8);
}

/* ── Sunburst effects ── */
@keyframes sunburstRotateFast{from{transform:translate(-50%,-50%) rotate(0deg);}to{transform:translate(-50%,-50%) rotate(360deg);}}
@keyframes sunburstRotateSlow{from{transform:translate(-50%,-50%) rotate(0deg);}to{transform:translate(-50%,-50%) rotate(360deg);}}
@keyframes sunburstRainbowPulse{
  0%  {opacity:0.5; filter:hue-rotate(0deg)   saturate(2.5) brightness(1.3) blur(0px);}
  20% {opacity:1;   filter:hue-rotate(72deg)  saturate(4)   brightness(1.9) blur(1.5px);}
  40% {opacity:0.6; filter:hue-rotate(144deg) saturate(3)   brightness(1.5) blur(0.5px);}
  60% {opacity:1;   filter:hue-rotate(216deg) saturate(4)   brightness(1.9) blur(1.5px);}
  80% {opacity:0.6; filter:hue-rotate(288deg) saturate(3)   brightness(1.5) blur(0.5px);}
  100%{opacity:0.5; filter:hue-rotate(360deg) saturate(2.5) brightness(1.3) blur(0px);}
}
@keyframes sunburstRainbowPulseMid{
  0%  {opacity:0.25;filter:hue-rotate(120deg) saturate(2.5) brightness(1.3) blur(0px);}
  20% {opacity:0.6; filter:hue-rotate(192deg) saturate(4)   brightness(1.9) blur(1.5px);}
  40% {opacity:0.3; filter:hue-rotate(264deg) saturate(3)   brightness(1.5) blur(0.5px);}
  60% {opacity:0.6; filter:hue-rotate(336deg) saturate(4)   brightness(1.9) blur(1.5px);}
  80% {opacity:0.3; filter:hue-rotate(408deg) saturate(3)   brightness(1.5) blur(0.5px);}
  100%{opacity:0.25;filter:hue-rotate(480deg) saturate(2.5) brightness(1.3) blur(0px);}
}
@keyframes sunburstRainbowPulseRight{
  0%  {opacity:0.12;filter:hue-rotate(240deg) saturate(2.5) brightness(1.3) blur(0px);}
  20% {opacity:0.3; filter:hue-rotate(312deg) saturate(4)   brightness(1.9) blur(1.5px);}
  40% {opacity:0.15;filter:hue-rotate(384deg) saturate(3)   brightness(1.5) blur(0.5px);}
  60% {opacity:0.3; filter:hue-rotate(456deg) saturate(4)   brightness(1.9) blur(1.5px);}
  80% {opacity:0.15;filter:hue-rotate(528deg) saturate(3)   brightness(1.5) blur(0.5px);}
  100%{opacity:0.12;filter:hue-rotate(600deg) saturate(2.5) brightness(1.3) blur(0px);}
}
@keyframes sunburstDarkRedPulse{
  0%,100%{opacity:0.65;filter:sepia(1) saturate(6) hue-rotate(320deg) brightness(0.2) blur(0px);}
  50%    {opacity:0.85;filter:sepia(1) saturate(7) hue-rotate(310deg) brightness(0.28) blur(2px);}
}
@keyframes sunburstDarkRedPulseMid{
  0%,100%{opacity:0.35;filter:sepia(1) saturate(6) hue-rotate(320deg) brightness(0.2) blur(0px);}
  50%    {opacity:0.5; filter:sepia(1) saturate(7) hue-rotate(310deg) brightness(0.28) blur(2px);}
}
@keyframes sunburstDarkRedPulseRight{
  0%,100%{opacity:0.18;filter:sepia(1) saturate(6) hue-rotate(320deg) brightness(0.2) blur(0px);}
  50%    {opacity:0.26;filter:sepia(1) saturate(7) hue-rotate(310deg) brightness(0.28) blur(2px);}
}
.ge-sunburst-good.col-sunburst--left{animation:sunburstRotateFast 8s linear infinite,sunburstRainbowPulse 1.4s ease-in-out infinite!important;}
.ge-sunburst-good.col-sunburst--mid{animation:sunburstRotateFast 8s linear infinite,sunburstRainbowPulseMid 1.4s ease-in-out infinite!important;}
.ge-sunburst-good.col-sunburst--right{animation:sunburstRotateFast 8s linear infinite,sunburstRainbowPulseRight 1.4s ease-in-out infinite!important;}
.ge-sunburst-bad.col-sunburst--left{animation:sunburstRotateSlow 50s linear infinite,sunburstDarkRedPulse 3.5s ease-in-out infinite!important;}
.ge-sunburst-bad.col-sunburst--mid{animation:sunburstRotateSlow 50s linear infinite,sunburstDarkRedPulseMid 3.5s ease-in-out infinite!important;}
.ge-sunburst-bad.col-sunburst--right{animation:sunburstRotateSlow 50s linear infinite,sunburstDarkRedPulseRight 3.5s ease-in-out infinite!important;}

/* ── Effect icon stack ── */
#ge-effect-stack {
  position: absolute;
  bottom: 12px;
  right: 12px;
  display: flex;
  flex-direction: column-reverse;
  align-items: flex-end;
  gap: 5px;
  z-index: 8000;
  pointer-events: none;
}
@keyframes geIconIn  { from{opacity:0;transform:scale(0.5) translateY(6px);}to{opacity:1;transform:scale(1) translateY(0);} }
@keyframes geIconOut { from{opacity:1;transform:scale(1);}to{opacity:0;transform:scale(0.4) translateY(4px);} }
@keyframes geTimerDrain { from{width:100%;}to{width:0%;} }
@keyframes geIconPulseGood {
  0%,100%{ box-shadow:0 0 5px rgba(40,210,90,0.55),0 0 12px rgba(40,210,90,0.25); }
  50%    { box-shadow:0 0 10px rgba(40,210,90,0.9),0 0 22px rgba(40,210,90,0.5); }
}
@keyframes geIconPulseNeutral {
  0%,100%{ box-shadow:0 0 5px rgba(220,220,220,0.45),0 0 12px rgba(220,220,220,0.18); }
  50%    { box-shadow:0 0 10px rgba(220,220,220,0.8),0 0 22px rgba(220,220,220,0.4); }
}
@keyframes geIconPulseBad {
  0%,100%{ box-shadow:0 0 5px rgba(200,35,35,0.55),0 0 12px rgba(200,35,35,0.25); }
  50%    { box-shadow:0 0 10px rgba(200,35,35,0.9),0 0 22px rgba(200,35,35,0.5); }
}
.ge-effect-icon {
  position: relative;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 19px;
  pointer-events: auto;
  cursor: default;
  flex-shrink: 0;
  overflow: hidden;
}
.ge-effect-icon.removing { animation: geIconOut 0.18s ease-in forwards !important; }
.ge-effect-good {
  background: rgba(0,200,80,0.16);
  border: 2px solid #22bb55;
  animation: geIconIn 0.2s ease-out forwards, geIconPulseGood 2s ease-in-out 0.2s infinite;
}
.ge-effect-neutral {
  background: rgba(220,220,220,0.12);
  border: 2px solid #cccccc;
  animation: geIconIn 0.2s ease-out forwards, geIconPulseNeutral 2s ease-in-out 0.2s infinite;
}
.ge-effect-bad {
  background: rgba(180,20,20,0.2);
  border: 2px solid #aa1818;
  animation: geIconIn 0.2s ease-out forwards, geIconPulseBad 2.5s ease-in-out 0.2s infinite;
}
.ge-effect-icon:hover { z-index: 50; overflow: visible; }
.ge-effect-timerbar {
  position: absolute;
  bottom: 0;
  left: 0;
  height: 3px;
  animation: geTimerDrain linear forwards;
}
.ge-effect-good    .ge-effect-timerbar { background: linear-gradient(to right, #0d6630, #33ff77); }
.ge-effect-neutral .ge-effect-timerbar { background: linear-gradient(to right, #666666, #dddddd); }
.ge-effect-bad     .ge-effect-timerbar { background: linear-gradient(to right, #5a0000, #ff2222); }
/* Always Lucky (gambler_root) buff icon — rainbow background, pinned to the
   bottom of the buff stack via order:-1 (column-reverse renders DOM-first
   children at the visual bottom). */
.ge-effect-rainbow {
  order: -1;
  background: linear-gradient(135deg,#ff6bd6,#ffd56b,#6bffc8,#6ba0ff,#c76bff) !important;
  background-size: 300% 300% !important;
  border: 2px solid rgba(255,255,255,0.65) !important;
  animation: geIconIn 0.2s ease-out forwards, grRainbowIconShift 6s linear infinite !important;
}
@keyframes grRainbowIconShift {
  0%   { background-position: 0% 0%; }
  100% { background-position: 300% 0%; }
}
.ge-effect-rainbow .ge-effect-timerbar {
  background: linear-gradient(to right,#ff6bd6,#ffd56b,#6bffc8,#6ba0ff,#c76bff) !important;
  background-size: 300% 100%;
  animation: geTimerDrain linear forwards, grRainbowBarShift 6s linear infinite;
}
@keyframes grRainbowBarShift {
  0%   { background-position: 0% 0%; }
  100% { background-position: 300% 0%; }
}
.ge-effect-rainbow .ge-effect-tooltip,
.ge-effect-tooltip.ge-effect-rainbow { border-left-color: #ff6bd6; }
.ge-effect-rainbow .ge-effect-tooltip-name,
.ge-effect-tooltip.ge-effect-rainbow .ge-effect-tooltip-name {
  background: linear-gradient(90deg,#ff6bd6,#ffd56b,#6bffc8,#6ba0ff,#c76bff);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-fill-color: transparent;
}
.ge-effect-tooltip {
  position: absolute;
  left: calc(100% + 8px);
  top: 50%;
  transform: translateY(-50%);
  background: rgba(12,4,9,0.96);
  border-radius: 8px;
  padding: 7px 11px 8px;
  min-width: 148px;
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.14s ease;
  white-space: nowrap;
  z-index: 200;
  border-left: 3px solid #22bb55;
  /* Buff/debuff tooltips: Calibri, bold, ~20% larger than the previous look. */
  font-family: Calibri, 'Trebuchet MS', sans-serif;
  font-weight: 700;
}
.ge-effect-tooltip * { font-family: inherit; font-weight: inherit; }
.ge-effect-silver .ge-effect-tooltip,
.ge-effect-tooltip.ge-effect-silver { border-left-color: #5599ee; }
.ge-effect-gold   .ge-effect-tooltip,
.ge-effect-tooltip.ge-effect-gold   { border-left-color: #ddaa00; }
.ge-effect-bad    .ge-effect-tooltip,
.ge-effect-tooltip.ge-effect-bad    { border-left-color: #cc2222; }
.ge-effect-icon:hover .ge-effect-tooltip { opacity: 1; }
.ge-effect-tooltip-name {
  font-size: 14px; /* 12 × 1.2 */
  font-weight: 700;
  letter-spacing: 0.02em;
  color: #44ee88;
}
.ge-effect-silver .ge-effect-tooltip-name,
.ge-effect-tooltip.ge-effect-silver .ge-effect-tooltip-name { color: #88bbff; }
.ge-effect-gold   .ge-effect-tooltip-name,
.ge-effect-tooltip.ge-effect-gold   .ge-effect-tooltip-name { color: #ffdd44; }
.ge-effect-bad    .ge-effect-tooltip-name,
.ge-effect-tooltip.ge-effect-bad    .ge-effect-tooltip-name { color: #ff5555; }
.ge-effect-tooltip-timer {
  font-size: 13px; /* 11 × 1.2 */
  color: #806070;
  margin-top: 3px;
}
/* Sub-line in buff/debuff tooltips (e.g. Drippy's Debt's "−33% passive
   droplets") — keep it in step with the +20% bigger size bump. */
.ge-effect-tooltip-sub { font-size: 13px; }

/* ─── From perks.js ──────────────────────────────────────────────────────── */
#perk-header {
  padding: 8px 14px 5px;
  font-size: 19px;
  font-weight: 700;
  color: #c090a8;
  letter-spacing: 0.04em;
  display: flex;
  align-items: center;
  gap: 6px;
}
#perk-header span { font-size: 14px; color: #6a4060; font-weight: 700; position: relative; top: 2px; }
#perk-collapse-btn {
  position: absolute;
  top: 8px;
  right: 10px;
  margin-left: 0;
  background: #2a1040;
  border: 1.2px solid #a050d0;
  border-radius: 7px;
  padding: 2.4px 11px;
  font-size: 16px;
  font-weight: 700;
  color: #d0a0ff;
  cursor: pointer;
  line-height: 1;
  transition: background 0.15s, border-color 0.15s;
  flex-shrink: 0;
  z-index: 110;
}
#perk-collapse-btn:hover { background: #4020a0; border-color: #c080ff; }
/* Mid-column perks panel is permanently hidden — perks are now bought from
   the per-card "+" buttons / perk pill bars on each ability card itself.
   The DOM nodes stay in place so renderPerks() can keep writing into them
   harmlessly, and so any sub-panel that pokes at #perk-section won't break.
   !important defeats the JS in options.js that clears the inline style on
   close (which would otherwise un-hide it). */
#perk-section { position: relative; padding-bottom: 0; display: none !important; }

/* Radio relocated from the banner to the bottom of the bookshelf, just above
   the perk and virility panels. Centered horizontally; #radio-controls keeps
   the same flex layout it used in the banner. */
#mid-radio-wrap {
  flex-shrink: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  padding: 0;
  background: transparent;
}
#mid-radio-wrap #radio-controls {
  display: flex;
  align-items: center;
  gap: 4px;
  margin-right: 0;
}
#perk-header { padding-right: 14px; }
#perk-section.collapsed { padding-bottom: 6px; }
#perk-section.collapsed #perk-header { padding-bottom: 5px; }
#perk-section.collapsed #perk-grid-wrap { display: none; }
#perk-grid-wrap { display: block; padding: 8px; border-top: 1px solid #3a1525; }
#perk-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 5px;
}
body.stats-panel-open #perk-grid-wrap,
body.stats-panel-open #perk-section { display: none !important; }
.perk-card {
  background: #3a0f25;
  border: 0.5px solid #6a3050;
  border-radius: 8px;
  padding: 7px 4px 6px;
  text-align: center;
  cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
  min-width: 0;
  display: flex;
  flex-direction: column;
}
.perk-card:hover { background: #2a1022; border-color: #7040a0; }
.perk-card.perk-affordable {
  border-color: #9060c0;
  background: #1e0c24;
  position: relative;
}
.perk-card.perk-affordable::before {
  content:''; position:absolute; inset:0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: inset 0 0 14px 2px rgba(224,96,255,0.55);
  animation: upgAffordPulse 2s ease-in-out infinite;
  will-change: opacity;
}
.perk-card.perk-affordable:hover {
  background: #2c1038;
  border-color: #c080f0;
}
.perk-icon { font-size: 26px; line-height: 1.1; }
.perk-tier-label {
  font-size: 13px;
  font-weight: 700;
  color: #d0a0ff;
  margin: 2px 0 1px;
}
.perk-upg-name {
  font-size: 14px;
  font-weight: 700;
  color: #7a5080;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  margin-top: auto;
}
.perk-cost {
  font-size: 12px;
  color: #fffef5;
  padding-top: 4px;
}
.perk-progress {
  display: none;
}

/* ─── From virility.js ───────────────────────────────────────────────────── */
#vir-tooltip {
  display: none;
  position: fixed;
  z-index: 999999;
  background: #1a0825;
  border: 1px solid #7040a0;
  border-radius: 8px;
  padding: 8px 12px;
  max-width: 230px;
  min-width: 140px;
  pointer-events: none;
  box-shadow: 0 4px 18px rgba(0,0,0,0.7);
  font-family: sans-serif;
}
#vir-tooltip .vt-name {
  font-size: 14px; /* 12 × 1.15 */
  font-weight: 700;
  color: #f0c0ff;
  margin-bottom: 4px;
  line-height: 1.3;
}
#vir-tooltip .vt-desc {
  font-size: 13px; /* 11 × 1.15 */
  color: #a07088;
  line-height: 1.45;
  margin-bottom: 5px;
}
#vir-tooltip .vt-effect-bad     { font-size: 13px; font-weight: 700; color: #ff6060; }
#vir-tooltip .vt-effect-good    { font-size: 13px; font-weight: 700; color: #60e880; }
#vir-tooltip .vt-effect-neutral { font-size: 13px; font-weight: 700; color: #aaaaaa; }

/* ─── From golden_eggplant.js: first-portal trickshot tutorial ────────────── */
/* Shown the first time a droplet portal spawns. An S-curved flashing arrow
   appears above the cylinder and a text label appears to the right.
   Removed when the portal disappears (triggered or expired). */
#trickshot-tutorial {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 120;
}
#trickshot-tutorial .trickshot-arrow-svg {
  position: fixed;
  overflow: visible;
  filter: drop-shadow(0 0 8px rgba(255,255,255,0.85));
  animation: trickshotFlash 0.9s ease-in-out infinite;
  z-index: 2;
}
#trickshot-tutorial .trickshot-arrow-path {
  stroke-dasharray: var(--ts-len, 400);
  stroke-dashoffset: var(--ts-len, 400);
  animation: trickshotDraw 3s ease-in-out infinite;
}
#trickshot-tutorial .trickshot-down-path {
  stroke-dasharray: var(--ts-down-len, 120);
  stroke-dashoffset: var(--ts-down-len, 120);
  animation: trickshotDownDraw 3s ease-in-out infinite;
}
/* Down arrow draws fully across the first third of the cycle (0 → 33%), then
   holds visible while the curve arrow draws, then both fade together. */
@keyframes trickshotDownDraw {
  0%    { stroke-dashoffset: var(--ts-down-len, 120); opacity: 1; }
  33%   { stroke-dashoffset: 0; opacity: 1; }
  33.01%{ stroke-dashoffset: 0; opacity: 0; }
  100%  { stroke-dashoffset: 0; opacity: 0; }
}
/* Curve arrow stays fully hidden (visibility: hidden also hides the arrowhead
   marker) until the down arrow has reached the bottom (33% of the cycle).
   Then it snaps visible and draws from bottom-right up to top-right across
   33% → 75%. */
@keyframes trickshotDraw {
  0%    { stroke-dashoffset: var(--ts-len, 400); opacity: 0; visibility: hidden; }
  33%   { stroke-dashoffset: var(--ts-len, 400); opacity: 0; visibility: hidden; }
  33.01%{ stroke-dashoffset: var(--ts-len, 400); opacity: 1; visibility: visible; }
  75%   { stroke-dashoffset: 0; opacity: 1; visibility: visible; }
  92%   { stroke-dashoffset: 0; opacity: 1; visibility: visible; }
  100%  { stroke-dashoffset: 0; opacity: 0.15; visibility: visible; }
}
@keyframes trickshotFlash {
  0%, 100% { opacity: 1; }
  50%      { opacity: 0.45; }
}
#trickshot-tutorial .trickshot-tutorial-text {
  position: fixed;
  font-family: Calibri, sans-serif;
  font-size: 23px;
  font-weight: 800;
  color: #fff1c8;
  text-align: left;
  line-height: 1.25;
  letter-spacing: 0.3px;
  text-shadow:
    0 0 10px rgba(255,213,74,0.85),
    0 0 4px rgba(255,170,40,0.9),
    0 2px 3px rgba(0,0,0,0.85);
  white-space: nowrap;
  pointer-events: none;
  animation: trickshotTextPulse 1.1s ease-in-out infinite;
}
@keyframes trickshotTextPulse {
  0%, 100% { transform: scale(1); }
  50%      { transform: scale(1.06); }
}

/* ─── From golden_balls.js ───────────────────────────────────────────────── */
#kiwi-wrap.golden-balls-active #kiwi-left-wrap,
#kiwi-wrap.golden-balls-active #kiwi-right-wrap {
  animation: goldenBallsPulse 1.1s ease-in-out infinite;
  filter: drop-shadow(0 0 12px #ffd560) drop-shadow(0 0 24px #ffb020);
}
#kiwi-wrap.golden-balls-active #kiwi-left,
#kiwi-wrap.golden-balls-active #kiwi-right {
  filter: sepia(1) saturate(5) hue-rotate(-12deg) brightness(1.2);
}
@keyframes goldenBallsPulse {
  0%, 100% {
    transform: scale(1);
    filter: drop-shadow(0 0 10px #ffd560) drop-shadow(0 0 18px #ffb020);
  }
  50% {
    transform: scale(1.08);
    filter: drop-shadow(0 0 20px #fff2a0) drop-shadow(0 0 36px #ffb020);
  }
}

/* ─── From ai_or_human.js (launcher button) ─────────────────────────────── */
#ai-or-human-btn {
  background: linear-gradient(135deg, #143a50, #081a28);
  border: 1.5px solid #4080c0;
  border-radius: 6px;
  color: #c0e8ff;
  font-size: 14px;
  font-weight: 700;
  padding: 2.8px 10px 5px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.2s;
  letter-spacing: 0.02em;
  box-shadow: 0 0 10px 2px rgba(80, 160, 220, 0.35), 0 0 20px 4px rgba(80, 160, 220, 0.18);
}
#ai-or-human-btn:hover {
  background: linear-gradient(135deg, #1e5070, #12283a);
  border-color: #60a0ff;
  color: #f0f8ff;
  box-shadow: 0 0 14px 3px rgba(120, 200, 255, 0.55), 0 0 28px 6px rgba(80, 160, 220, 0.3);
}

/* ─── From dice.js (launcher button) ────────────────────────────────────── */
#dice-btn {
  background: linear-gradient(135deg, #1a4028, #081a10);
  border: 1.5px solid #40a060;
  border-radius: 6px;
  color: #c8f0d8;
  font-size: 14px;
  font-weight: 700;
  padding: 2.8px 10px 5px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.2s;
  letter-spacing: 0.02em;
  box-shadow: 0 0 10px 2px rgba(80, 200, 120, 0.35), 0 0 20px 4px rgba(80, 200, 120, 0.18);
}
#dice-btn:hover {
  background: linear-gradient(135deg, #265838, #10281a);
  border-color: #60d080;
  color: #f0fff4;
  box-shadow: 0 0 14px 3px rgba(120, 240, 160, 0.55), 0 0 28px 6px rgba(80, 200, 120, 0.3);
}

/* ─── Other banner buttons ──────────────────────────────────────────────────
   Mirror the #ai-or-human-btn / #dice-btn ID-override pattern so every banner
   pill is themed via its own dedicated rule rather than inheriting the shared
   .b-btn defaults. Each button keeps its prior colour identity (VIP=purple,
   Shop=gold, Convert=blue, Roulette=magenta, Plinko=violet, Slots=hot-pink,
   default=red-pink). The .notif-dot pulse on #daily-btn / #plinko-btn is
   unaffected because it lives on a child element styled in core.css and only
   needs the button to keep position:relative — which still cascades from the
   .b-btn class. .b-btn.convert-btn{margin-right:50px} in core.css also still
   applies for the same reason. */

/* Default red-pink — Currencies / Radio toggle / $ Buy / Cash-Convert / Daily
   / Scratch / Lootbox. */
#wallet-toggle-btn,
#radio-toggle-btn,
#sell-btn,
#cash-convert-btn,
#daily-btn,
#scratch-btn,
#lootbox-btn {
  background: linear-gradient(135deg, #4a1a30, #250c18);
  border: 1.5px solid #8a3060;
  border-radius: 6px;
  color: #f0c0d0;
  font-size: 14px;
  font-weight: 700;
  padding: 2.8px 10px 5px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.2s;
  letter-spacing: 0.02em;
  box-shadow: 0 0 10px 2px rgba(200, 80, 120, 0.35), 0 0 20px 4px rgba(200, 80, 120, 0.18);
}
#wallet-toggle-btn:hover,
#radio-toggle-btn:hover,
#sell-btn:hover,
#cash-convert-btn:hover,
#daily-btn:hover,
#scratch-btn:hover,
#lootbox-btn:hover {
  background: linear-gradient(135deg, #6a2545, #380f22);
  border-color: #c04880;
  color: #ffe0e8;
  box-shadow: 0 0 14px 3px rgba(220, 100, 140, 0.55), 0 0 28px 6px rgba(200, 80, 120, 0.3);
}

/* VIP — purple. */
#vip-btn {
  background: linear-gradient(135deg, #3a1560, #1a0830);
  border: 1.5px solid #7a50c0;
  border-radius: 6px;
  color: #d0b0f0;
  font-size: 14px;
  font-weight: 700;
  padding: 2.8px 10px 5px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.2s;
  letter-spacing: 0.02em;
  box-shadow: 0 0 10px 2px rgba(120, 80, 200, 0.35), 0 0 20px 4px rgba(120, 80, 200, 0.18);
}
#vip-btn:hover {
  background: linear-gradient(135deg, #5a25a0, #2e0f55);
  border-color: #a080e0;
  color: #f0e0ff;
  box-shadow: 0 0 14px 3px rgba(140, 100, 220, 0.55), 0 0 28px 6px rgba(120, 80, 200, 0.3);
}

/* Shop — gold. */
#shop-btn {
  background: linear-gradient(135deg, #7a5800, #c08c10);
  border: 1.5px solid #f0c030;
  border-radius: 6px;
  color: #fff0a0;
  font-size: 14px;
  font-weight: 700;
  padding: 2.8px 10px 5px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.2s;
  letter-spacing: 0.02em;
  box-shadow: 0 0 10px 2px rgba(240, 192, 48, 0.35), 0 0 20px 4px rgba(240, 192, 48, 0.18);
}
#shop-btn:hover {
  background: linear-gradient(135deg, #9a7000, #e0aa18);
  border-color: #ffd860;
  color: #fffcd0;
  box-shadow: 0 0 14px 3px rgba(255, 210, 70, 0.55), 0 0 28px 6px rgba(240, 192, 48, 0.3);
}

/* Convert (banner-right) — blue. */
#convert-btn {
  background: linear-gradient(135deg, #102a5a, #081428);
  border: 1.5px solid #3060c0;
  border-radius: 6px;
  color: #90c0ff;
  font-size: 14px;
  font-weight: 700;
  padding: 2.8px 10px 5px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.2s;
  letter-spacing: 0.02em;
  box-shadow: 0 0 10px 2px rgba(80, 130, 220, 0.35), 0 0 20px 4px rgba(80, 130, 220, 0.18);
}
#convert-btn:hover {
  background: linear-gradient(135deg, #1a3a7a, #0c1e3c);
  border-color: #5080e0;
  color: #c0d8ff;
  box-shadow: 0 0 14px 3px rgba(120, 170, 255, 0.55), 0 0 28px 6px rgba(80, 130, 220, 0.3);
}

/* Roulette — magenta-purple glow on red-pink base. */
#roulette-btn {
  background: linear-gradient(135deg, #4a1a30, #250c18);
  border: 1.5px solid #8a3060;
  border-radius: 6px;
  color: #f0c0d0;
  font-size: 14px;
  font-weight: 700;
  padding: 2.8px 10px 5px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.2s;
  letter-spacing: 0.02em;
  box-shadow: 0 0 10px 2px rgba(160, 80, 160, 0.35), 0 0 20px 4px rgba(160, 80, 160, 0.18);
}
#roulette-btn:hover {
  background: linear-gradient(135deg, #6a2545, #380f22);
  border-color: #c04880;
  color: #ffe0e8;
  box-shadow: 0 0 14px 3px rgba(190, 100, 190, 0.55), 0 0 28px 6px rgba(160, 80, 160, 0.3);
}

/* Plinko — violet-blue glow on red-pink base. .notif-dot pulse preserved. */
#plinko-btn {
  background: linear-gradient(135deg, #4a1a30, #250c18);
  border: 1.5px solid #8a3060;
  border-radius: 6px;
  color: #f0c0d0;
  font-size: 14px;
  font-weight: 700;
  padding: 2.8px 10px 5px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.2s;
  letter-spacing: 0.02em;
  box-shadow: 0 0 10px 2px rgba(128, 96, 208, 0.35), 0 0 20px 4px rgba(128, 96, 208, 0.18);
}
#plinko-btn:hover {
  background: linear-gradient(135deg, #6a2545, #380f22);
  border-color: #c04880;
  color: #ffe0e8;
  box-shadow: 0 0 14px 3px rgba(150, 120, 224, 0.55), 0 0 28px 6px rgba(128, 96, 208, 0.3);
}

/* Slots — hot pink/red glow on red-pink base. */
#slots-btn {
  background: linear-gradient(135deg, #4a1a30, #250c18);
  border: 1.5px solid #8a3060;
  border-radius: 6px;
  color: #f0c0d0;
  font-size: 14px;
  font-weight: 700;
  padding: 2.8px 10px 5px 10px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.2s;
  letter-spacing: 0.02em;
  box-shadow: 0 0 10px 2px rgba(240, 96, 128, 0.35), 0 0 20px 4px rgba(240, 96, 128, 0.18);
}
#slots-btn:hover {
  background: linear-gradient(135deg, #6a2545, #380f22);
  border-color: #c04880;
  color: #ffe0e8;
  box-shadow: 0 0 14px 3px rgba(255, 120, 150, 0.55), 0 0 28px 6px rgba(240, 96, 128, 0.3);
}

/* ─── Cylinder army: favorite star (NPC card button + picker indicator) ─── */
.cylarmy-fav-btn {
  position: absolute;
  top: 6px;
  left: 6px;
  width: 26px;
  height: 26px;
  padding: 0;
  background: #2a2410;
  border: 1px solid #c0a04055;
  border-radius: 5px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.55;
  font-size: 16px;
  color: #c0a040;
  line-height: 1;
  transition: opacity 0.15s, border-color 0.15s, background 0.15s, color 0.15s, text-shadow 0.15s;
  flex-shrink: 0;
  z-index: 3;
}
.cylarmy-fav-btn:hover {
  opacity: 1;
  background: #3a3010;
  border-color: #ffd060;
  color: #ffe080;
}
.cylarmy-fav-btn.cylarmy-fav-on {
  opacity: 1;
  background: #3a2a08;
  border-color: #ffd060;
  color: #ffe070;
  text-shadow: 0 0 6px rgba(255, 220, 100, 0.7);
}
.cylarmy-fav-btn.cylarmy-fav-on:hover {
  background: #4a3608;
  color: #fff0a0;
}

/* Magnifying-glass detail button — sits next to the favorite star and
   opens the NPC info popup anchored to the button. */
.cylarmy-detail-btn {
  position: absolute;
  top: 6px;
  left: 36px;
  width: 26px;
  height: 26px;
  padding: 0;
  background: #1a2030;
  border: 1px solid #4a80b055;
  border-radius: 5px;
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: 0.55;
  font-size: 16px;
  color: #b0d0ff;
  line-height: 1;
  transition: opacity 0.15s, border-color 0.15s, background 0.15s, box-shadow 0.15s;
  flex-shrink: 0;
  z-index: 3;
}
.cylarmy-npc-card:hover .cylarmy-detail-btn { opacity: 0.85; }
.cylarmy-detail-btn:hover {
  opacity: 1;
  background: #243a55;
  border-color: #6ab0ff;
  box-shadow: 0 0 10px rgba(120, 180, 255, 0.45);
}

/* Small star indicator shown on NPC selection cards across the various
   pickers (fuse, cock fight, raid, expedition, cum champion). */
.cylarmy-fuse-pick,
.cf-pick-card,
.rd-pick-card,
.exped-npc-card,
.cc-pick-card { position: relative; }
.npc-fav-indicator {
  position: absolute;
  top: 4px;
  left: 4px;
  font-size: 13px;
  line-height: 1;
  color: #ffe070;
  text-shadow: 0 0 5px rgba(255, 220, 100, 0.85), 0 1px 2px rgba(0, 0, 0, 0.7);
  pointer-events: none;
  z-index: 4;
}

/* ─── From cock_rings.js ─────────────────────────────────────────────────── */
.cockring-band {
  /* Common base — colors & box-shadow set inline per-ring. Rectangular band
     with pseudo overlays giving 3D depth: bright top sheen + side darkening
     to suggest the band wrapping around the cylinder. */
  position: relative;
  pointer-events: auto;
  overflow: hidden;
}
.cockring-band::before {
  /* Top highlight: thin bright sheen along the top edge. */
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    180deg,
    rgba(255, 255, 255, 0.55) 0%,
    rgba(255, 255, 255, 0.12) 18%,
    rgba(0, 0, 0, 0) 35%,
    rgba(0, 0, 0, 0) 70%,
    rgba(0, 0, 0, 0.18) 100%
  );
  pointer-events: none;
}
.cockring-band::after {
  /* Side darkening: simulates the band curving around the cylinder so the
     left/right edges fall away into shadow. */
  content: '';
  position: absolute;
  inset: 0;
  border-radius: inherit;
  background: linear-gradient(
    90deg,
    rgba(0, 0, 0, 0.55) 0%,
    rgba(0, 0, 0, 0.18) 8%,
    rgba(0, 0, 0, 0) 22%,
    rgba(0, 0, 0, 0) 78%,
    rgba(0, 0, 0, 0.18) 92%,
    rgba(0, 0, 0, 0.55) 100%
  );
  pointer-events: none;
}
.cockring-band.cr-shimmer {
  animation: cr-shimmer-anim 2.4s linear infinite;
  background-size: 100% 200% !important;
}
@keyframes cr-shimmer-anim {
  0%   { filter: brightness(1) saturate(1); }
  50%  { filter: brightness(1.35) saturate(1.3); }
  100% { filter: brightness(1) saturate(1); }
}
.cockring-band.cr-ethereal {
  animation: cr-ethereal-anim 3s ease-in-out infinite;
}
@keyframes cr-ethereal-anim {
  0%, 100% {
    filter: hue-rotate(0deg) brightness(1.05);
    box-shadow: 0 0 14px rgba(192,128,255,0.9), 0 0 24px rgba(128,240,255,0.7);
  }
  50% {
    filter: hue-rotate(60deg) brightness(1.25);
    box-shadow: 0 0 22px rgba(192,128,255,1), 0 0 36px rgba(128,240,255,0.85);
  }
}

/* Slot-machine reward animation reuses .cf-slot-* classes. The preview band
   inside each slot row needs to look ring-like. */
.cf-slot-row .cr-slot-band {
  align-self: center;
  flex-shrink: 0;
  margin: 0 8px 0 4px;
}

/* Reward modal */
.cr-reward-modal { width: 360px; }
.cr-reward-body {
  padding: 22px 24px 18px;
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.cr-reward-line {
  font-size: 18px; font-weight: 700; color: #f5d0e8; text-align: center;
  text-shadow: 0 1px 4px rgba(0,0,0,0.6);
}
.cr-reward-preview {
  width: 200px; height: 60px;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(ellipse at center, rgba(180,120,180,0.18) 0%, rgba(0,0,0,0) 70%);
}
.cr-reward-band {
  width: 180px !important; height: 26px !important;
  border-radius: 5px !important;
}
.cr-reward-stat {
  font-size: 13px; font-weight: 700; letter-spacing: 0.04em;
}
.cr-reward-actions {
  display: flex; gap: 10px; margin-top: 6px;
}

/* Cock-rings tab cards in cosmetics → Size & Style */
.cr-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(110px, 1fr)); gap: 10px; }
.cr-card {
  position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 10px 8px 8px;
}
.cr-card.cosm-locked { opacity: 0.5; filter: grayscale(0.55); }
.cr-card-preview {
  width: 100%; height: 32px;
  display: flex; align-items: center; justify-content: center;
  background: radial-gradient(ellipse at center, rgba(120,80,140,0.18) 0%, rgba(0,0,0,0) 70%);
  border-radius: 6px;
}
.cr-card .cockring-band {
  width: 86px !important; height: 16px !important;
  border-radius: 4px !important;
}
.cr-card .cr-stat { font-size: 11px; font-weight: 700; }
.cr-count {
  position: absolute; top: 4px; right: 6px;
  font-size: 10px; font-weight: 700;
  color: #f0d0e8;
  background: rgba(40,20,40,0.7);
  padding: 1px 5px; border-radius: 4px;
}
.cr-slots-line {
  font-size: 11px; color: #b090d0; font-weight: 600;
  background: rgba(40,20,40,0.4);
  padding: 2px 8px; border-radius: 6px;
}
.cr-controls {
  display: flex; align-items: center; justify-content: center; gap: 6px;
  margin-top: 4px;
}
.cr-btn {
  width: 24px; height: 22px;
  border: 1px solid #5a3868;
  background: #2a1a36;
  color: #e8c8f0;
  font-weight: 700; font-size: 14px; line-height: 1;
  border-radius: 5px; cursor: pointer;
  transition: background 0.12s, border-color 0.12s;
}
.cr-btn:hover:not(:disabled) { background: #3e2650; border-color: #8050a0; }
.cr-btn:disabled { opacity: 0.35; cursor: not-allowed; }
.cr-equipped-count {
  font-size: 11px; font-weight: 700; color: #e8c8f0;
  min-width: 36px; text-align: center;
}

/* ─── Column resizer (js/column_resize.js) ─────────────────────────────────
   Two draggable dividers between left/mid/right columns. Each column gets
   a CSS zoom of 0.8–1.2 applied by the JS, which scales every button, icon
   and child along with the column width. */
.col-divider {
  flex: 0 0 12px;
  align-self: stretch;
  position: relative;
  z-index: 6;
  background: transparent;
  touch-action: none;
  user-select: none;
}
.col-divider-grip {
  position: absolute;
  left: 50%;
  top: 50%;
  width: 2px;
  height: 38px;
  margin-left: -1px;
  margin-top: -19px;
  background: rgba(192, 128, 168, 0.32);
  border-radius: 2px;
  transition: background 0.15s, height 0.15s, box-shadow 0.15s, width 0.15s;
  pointer-events: none;
}
.col-divider:hover .col-divider-grip,
body.col-resizing .col-divider .col-divider-grip {
  background: rgba(255, 200, 235, 0.9);
  height: 64px;
  margin-top: -32px;
  width: 3px;
  margin-left: -1.5px;
  box-shadow: 0 0 8px rgba(255, 160, 220, 0.55), 0 0 18px rgba(220, 100, 180, 0.35);
}
body.col-resizing { user-select: none; }
body.col-resizing .col-divider { background: rgba(192, 80, 168, 0.06); }

/* On mobile the layout collapses (mobile.css turns #main into a column and
   makes mid/right slide-in overlays). Hide dividers entirely there — the JS
   also clears the inline width it applied. */
@media (max-width: 1400px) {
  .col-divider { display: none !important; }
}

/* ─── Pixelated icons: right column ability shop ────────────────────────────
   shop_pixelate.js replaces each .upg-icon's contents with a small <canvas>
   (rasterized via SVG <foreignObject> at the slot's natural size, then
   downsampled). The canvas itself sets image-rendering:pixelated for the
   nearest-neighbor upscale — canvas bitmaps honor that hint, so emoji and
   inline SVG actually pixelate (text/SVG would be re-rasterized crisp if we
   relied on transform: scale). Centering rule below positions the canvas
   inside the original slot. */
#right-col .upg-card:not(.upg-teaser) .upg-icon {
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: visible;
  /* Clear --cyl-emoji-filter (grayscale+sepia+hue-rotate cylinder-skin tint)
     so the rasterized canvas keeps its real palette. The canvas runs its own
     contrast/saturate boost below to match the tooltip preview. */
  filter: none;
}

#right-col .upg-card:not(.upg-teaser) .upg-icon-canvas {
  /* Punchy pixel-art palette to match prior visual treatment */
  filter: contrast(1.3) saturate(1.5);
}

/* ─── Layout: +4 px additive padding around the columns ───────────────────
   Adds 4 px to the existing 8 px on the left side, right side, and bottom.
   Top stays at the original 8 px. The 12 px column-resizer tracks in core
   .css's grid-template-columns provide the between-column separation, so
   `gap` stays at 0 — adding gap on top would double-spaced both gaps and
   only the right one (covered by the bar in row 1) would visibly differ.
   Background made transparent so the full-screen sunburst at #root level
   reads through the gaps + outer padding. */
#main {
  padding: 8px 12px 12px 12px;       /* top  right  bottom  left  (right/bottom/left = 8 + 4) */
  background: transparent;
  /* Lifted above the full-screen sunburst (z-index: 0). Combined with the
     transparent background, this lets the sunburst show through #main's
     gaps + outer padding while keeping the column children (which have
     their own opaque backgrounds) painted over it. */
  position: relative;
  z-index: 1;
}

/* ─── Full-screen sunburst overlay ──────────────────────────────────────────
   #sunburst-fullscreen is the same conic-gradient ray pattern as the per-
   column sunbursts (.col-sunburst), but lives at #root level instead of
   inside a column — so it spans the full viewport. It uses the same rotate
   keyframe and a fresh opacity pulse, and sits behind every in-flow element
   via z-index: -1. Pair it with semi-transparent banner + transparent #main
   below so the rays are visible across the banner, the minigame bar, the
   gaps between columns, and the outer padding. */
#sunburst-fullscreen {
  /* The per-column sunbursts inside #left-col / #mid-col / #right-col
     already cover everything the player sees, so the full-screen overlay
     was just doubling them up behind the columns. Element stays in the
     DOM because cylinders.js / metaballs.js use it as an
     insertion anchor; just hide it visually. */
  display: none;
}
@keyframes sunburstPulseFull {
  0%,100% { opacity: 0.75; }
  50%     { opacity: 1.0; }
}

/* Banner: semi-transparent so the sunburst behind reads through the banner
   strip. The original gradient is preserved at 70% alpha — the dark pink
   theme still anchors the top, but rays pulse through. */
#banner {
  background: linear-gradient(to right,
    rgba(30, 10, 19, 0.7) 0%,
    rgba(58, 21, 37, 0.7) 50%,
    rgba(30, 10, 19, 0.7) 100%);
}

/* The minigame bar — 100 px tall. Sits inside #main on the desktop grid in
   row 1, spanning cols 3 → 5 (mid-col + M↔R divider + right-col) so the
   left column reaches up under the banner. Transparent so the full-screen
   sunburst shows through. On mobile #main reverts to flex-column and the
   bar is hidden. */
#minigame-bar {
  grid-column: 3 / span 3;
  grid-row: 2;
  flex-shrink: 0;
  /* min-height (not a fixed height) so the bar can grow taller when the
     VIP/Daily/Casino/Minigames/Lootbox buttons wrap onto a second row — its
     grid row is auto-sized, so the columns below shift down to make room. */
  min-height: 60px;
  display: flex;
  align-items: center;
  padding: 4px 4px 0 4px;
  position: relative;
  z-index: 2;
  overflow: hidden;
}

/* At game start the bar holds nothing the player can see — radio is hidden,
   the 14 minigame wraps are display:none, and only the chevron sits at the
   right edge. Hide the whole row (and its grid track) until any of the five
   starter buttons unlocks. As soon as one drops .ui-locked, the :has chain
   stops matching and the bar reappears. */
#minigame-bar:has(#vip-btn.ui-locked):has(#daily-btn.ui-locked):has(#casino-btn.ui-locked):has(#minigames-btn.ui-locked):has(#lootbox-btn.ui-locked) {
  display: none !important;
}

/* Until the prestige XP bar is unlocked, nudge the radio + minigame buttons
   up 6px to close the gap left by the still-hidden bar above. */
body:has(#prestige-bar-wrap.ui-locked) #minigame-bar {
  top: -6px;
}

/* Left side of the minigame bar — holds the cash currency pill + Buy button.
   Always visible regardless of the chevron's collapsed state (the chevron
   only hides #minigame-buttons-wrap on the right). */
#minigame-bar-left {
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 6px;
  margin-right: 8px;
  padding-left: 4px;
  z-index: 3;
}

/* Wrap that holds the 14 minigame buttons. flex-wrap lets them spill onto
   multiple rows; justify-content: flex-end right-aligns each row. */
#minigame-buttons-wrap {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  justify-content: flex-end;
  align-content: center;
  align-items: center;
  /* Sizes to its own content (one or two rows of buttons) rather than being
     pinned to the bar's height, so a wrapped second row grows the bar instead
     of being clipped. min-height keeps a single row centered at 60px. */
  min-height: 100%;
  transition: transform 0.45s cubic-bezier(0.65, 0, 0.35, 1),
              opacity   0.35s ease;
}

/* The per-minigame button wrappers (Cylinder City, Adventure, Survivor, etc.)
   are kept in the DOM so minigames_menu.js can read their inline
   style.display to detect which minigames have unlocked, but they're hidden
   from the bar since the 🕹️ Minigames button is the entry point. !important
   beats the per-minigame unlock scripts that flip inline display to ''. */
#minigame-buttons-wrap > div {
  display: none !important;
}
#minigame-buttons-wrap > button {
  white-space: nowrap;
}

/* Collapsed state: slide the wrap off the right edge into the chevron. */
#minigame-bar.collapsed #minigame-buttons-wrap {
  transform: translateX(110%);
  opacity: 0;
  pointer-events: none;
}

/* Chevron toggle — sits at the right edge, persists when buttons are hidden. */
#minigame-toggle {
  flex-shrink: 0;
  margin-left: 4px;
  width: 30px;
  height: 40px;
  background: linear-gradient(135deg, #4a1a30, #250c18);
  border: 1.5px solid #8a3060;
  border-radius: 7px;
  color: #f0c0d0;
  font-size: 18px;
  font-weight: 700;
  line-height: 1;
  cursor: pointer;
  padding: 0;
  box-shadow: 0 0 8px 2px rgba(160, 60, 100, 0.28),
              0 0 16px 4px rgba(160, 60, 100, 0.13);
  transition: background 0.15s, border-color 0.15s,
              box-shadow 0.2s, transform 0.15s;
  z-index: 2;
}
#minigame-toggle:hover {
  background: linear-gradient(135deg, #6a2545, #380f22);
  transform: translateY(-1px);
  box-shadow: 0 0 12px 3px rgba(200, 80, 130, 0.45),
              0 0 24px 6px rgba(160, 60, 100, 0.25);
}
#minigame-toggle:active { transform: translateY(0); filter: brightness(0.96); }

/* Mobile-only minigame-bar collapse chevrons — hidden on desktop (desktop uses
   #minigame-toggle). Shown + positioned in mobile.css. */
#mm-mobile-collapse,
#mm-bar-expand {
  display: none;
}

/* On mobile the bar is NOT hidden — it's restacked into a top banner (radio
   centered above the VIP/Daily/Casino/Minigames/Lootbox buttons). See the
   #minigame-bar block in mobile.css. */

/* VIP / Daily / Casino / Minigames / Lootbox — 20% larger than .b-btn baseline
   (padding, font, border-radius all ×1.2). */
#vip-btn,
#daily-btn,
#casino-btn,
#minigames-btn,
#lootbox-btn {
  font-size: 17px;
  padding: 3.36px 11px 6px 11px;
  border-radius: 8px;
}

/* In the desktop band just above the mobile breakpoint (≈1400–1700px) the
   minigame-bar's column gets too narrow for the five full-size starter
   buttons, so they wrap onto a second row. Keep them on ONE line: forbid the
   wrap and ramp font + horizontal padding down across that band. The clamps
   max out at the normal size (~1700px+), so wider screens are unchanged; the
   mobile breakpoint (≤1400px) has its own sizing in mobile.css. */
@media (min-width: 1401px) {
  #minigame-buttons-wrap { flex-wrap: nowrap; }
  #vip-btn,
  #daily-btn,
  #casino-btn,
  #minigames-btn,
  #lootbox-btn {
    font-size: clamp(12px, calc(1.77vw - 13px), 17px);
    padding-left: clamp(5px, calc(1.18vw - 9px), 11px);
    padding-right: clamp(5px, calc(1.18vw - 9px), 11px);
    white-space: nowrap;
  }
}

/* Mid-top-bar buttons (Stats / Graph / Achievements / Options) — sizing +
   visuals now live in ui_polish.css with CSS-var scaling for the responsive
   shrink-then-icons mode. (Old hardcoded override removed.) */

/* === Casino — red marquee with chasing orange-yellow bulb lights ====== */
/* Background dark/saturation matched to VIP (#3a1560 → #1a0830) so all five
   buttons share the same opacity profile; identity comes from the bulb pseudo
   elements + colored border/glow. */
#casino-btn {
  background: linear-gradient(135deg, #5a1020, #2a0810);
  border: 1.5px solid #ffb030;
  text-shadow: 0 0 6px rgba(255, 80, 80, 0.7), 0 1px 0 rgba(0, 0, 0, 0.5);
  box-shadow: 0 0 10px 2px rgba(220, 40, 60, 0.45),
              0 0 22px 5px rgba(220, 40, 60, 0.22),
              inset 0 0 8px rgba(255, 180, 60, 0.35);
  position: relative;
  overflow: hidden;
}
#casino-btn:hover {
  background: linear-gradient(135deg, #7a1830, #3a0c18);
  border-color: #ffd060;
  box-shadow: 0 0 14px 3px rgba(240, 60, 80, 0.6),
              0 0 30px 7px rgba(220, 40, 60, 0.3),
              inset 0 0 12px rgba(255, 200, 80, 0.5);
}
#casino-btn::before,
#casino-btn::after {
  content: "";
  position: absolute;
  left: 4px;
  right: 4px;
  height: 4px;
  pointer-events: none;
  background-image: radial-gradient(circle, #ffe060 35%, rgba(255, 160, 30, 0.65) 50%, transparent 62%);
  background-size: 8px 4px;
  background-repeat: repeat-x;
  /* Dull by default — only brightens + animates when a casino game has a
     free play banked. has-freeplay class is toggled by updateBannerDots. */
  opacity: 0.3;
  filter: grayscale(0.7) brightness(0.55) drop-shadow(0 0 1px #6a4818);
  animation: none;
}
#casino-btn::before { top: 1px; }
#casino-btn::after  { bottom: 1px; }
#casino-btn.has-freeplay::before,
#casino-btn.has-freeplay::after {
  opacity: 1;
  filter: drop-shadow(0 0 3px #ffae20);
  animation: casinoBulbs 0.7s steps(2) infinite;
}
#casino-btn.has-freeplay::after { animation-delay: 0.35s; }
@keyframes casinoBulbs {
  0%   { background-position: 0 50%; opacity: 1; }
  50%  { background-position: 4px 50%; opacity: 0.35; }
  100% { background-position: 0 50%; opacity: 1; }
}

/* === Minigames — transcendent pulsing inner glow ====================== */
/* Background already at VIP-equivalent darkness; identity is the animated
   ::before inner glow. */
#minigames-btn {
  position: relative;
  background: linear-gradient(135deg, #2a1545, #100820);
  border: 1.5px solid #b070e8;
  text-shadow: 0 0 6px rgba(200, 140, 255, 0.6), 0 1px 0 rgba(0, 0, 0, 0.4);
  overflow: hidden;
}
#minigames-btn:hover {
  background: linear-gradient(135deg, #3a1f60, #1a1030);
  border-color: #d090ff;
}
#minigames-btn::before {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  pointer-events: none;
  box-shadow: inset 0 0 14px 4px rgba(180, 120, 255, 0.55);
  animation: upgAffordPulse 2.8s ease-in-out infinite;
  will-change: opacity;
}

/* === Lootbox — golden, shiny, with sweeping shimmer =================== */
/* Base gradient darkened to match VIP's opacity profile; gold identity comes
   from the bright border + warm glow + sweeping ::after shimmer. */
#lootbox-btn {
  background: linear-gradient(135deg, #5a4010, #2a1d04);
  border: 1.5px solid #ffe680;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.5), 0 0 6px rgba(255, 200, 80, 0.5);
  box-shadow: 0 0 10px 2px rgba(255, 200, 80, 0.5),
              0 0 24px 6px rgba(255, 160, 40, 0.28),
              inset 0 1px 0 rgba(255, 230, 140, 0.35),
              inset 0 -1px 0 rgba(120, 70, 0, 0.45);
  position: relative;
  overflow: hidden;
}
#lootbox-btn:hover {
  background: linear-gradient(135deg, #7a5618, #3a2808);
  border-color: #fff0a0;
  box-shadow: 0 0 14px 3px rgba(255, 220, 100, 0.7),
              0 0 32px 8px rgba(255, 180, 60, 0.4),
              inset 0 1px 0 rgba(255, 240, 160, 0.5),
              inset 0 -1px 0 rgba(120, 70, 0, 0.5);
}
#lootbox-btn::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(110deg,
              transparent 30%,
              rgba(255, 255, 255, 0.55) 45%,
              rgba(255, 255, 255, 0) 60%);
  transform: translateX(-130%);
  animation: lootboxShine 3.2s ease-in-out infinite;
}
@keyframes lootboxShine {
  0%, 50% { transform: translateX(-130%); }
  100%    { transform: translateX(130%); }
}

/* === Shared text colour for the five banner-2.0 minigame buttons ======= */
/* #eee at 80% opacity (20% transparent), per spec. Overrides each button's
   own colour rule by virtue of cascade order. Applied to base + :hover so
   the label brightness stays constant across states. */
#vip-btn,
#vip-btn:hover,
#daily-btn,
#daily-btn:hover,
#casino-btn,
#casino-btn:hover,
#minigames-btn,
#minigames-btn:hover,
#lootbox-btn,
#lootbox-btn:hover {
  color: rgba(238, 238, 238, 0.8);
}

/* === Pocket Change (skill: pocket_change) =============================== */
/* Floats up the left column when the random 5–15min payout fires. */
@keyframes pocketChangeRise {
  0%   { opacity: 0; transform: translate(-50%, 12px); }
  15%  { opacity: 1; transform: translate(-50%, 0); }
  80%  { opacity: 0.85; transform: translate(-50%, -28px); }
  100% { opacity: 0; transform: translate(-50%, -64px); }
}
.pocket-change-toast {
  position: absolute;
  left: 50%;
  bottom: 18%;
  transform: translateX(-50%);
  font-size: 18px;
  font-weight: 800;
  color: #d8ffd0;
  text-shadow: 0 0 12px rgba(120, 220, 120, 0.7),
               0 0 24px rgba(80, 180, 80, 0.4);
  pointer-events: none;
  white-space: nowrap;
  z-index: 105;
  letter-spacing: 0.02em;
  animation: pocketChangeRise 3s ease-out forwards;
  font-family: Euphemia, sans-serif;
}

/* === Sticky Ghost (skill: sticky_ghost) ================================= */
/* When ghost is suppressed by Torsion / curses (and the player hasn't
   bought Sticky Ghost), tint the ghost upgrade card red and dim it so
   the player can see the ability is temporarily disabled. */
.upg-card.ghost-card.ghost-disabled {
  filter: hue-rotate(-65deg) saturate(1.4) brightness(0.85);
  opacity: 0.55;
  border-color: #c04040 !important;
  box-shadow: 0 0 12px rgba(192, 64, 64, 0.45),
              inset 0 0 18px rgba(192, 64, 64, 0.18) !important;
}
.upg-card.ghost-card.ghost-disabled #ghost-card-timer {
  color: #ff8080 !important;
}

/* === Recursive Ghost (skill: recursive_ghost) =========================== */
/* Extra ghost-job toast renders 20% more transparent than the base
   .ghost-job-toast (0.78 alpha → 0.624). */
.ghost-job-toast.extra-ghost-job {
  color: rgba(210, 235, 255, 0.624);
  text-shadow: 0 0 18px rgba(140, 200, 255, 0.6),
               0 0 36px rgba(100, 170, 255, 0.28);
}

/* === Per-ability Perk Tree popup ========================================= */
/* Vertical chain of 8 perk tiers: cheapest at the bottom, priciest at the
   top, connected by a thin spine. Owned tiers glow purple; the next-buyable
   one is highlighted (and pulses softly when affordable); later tiers are
   dimmed. Opened by clicking the .upg-perk-bar inline next to each ability
   name in the right column. */
.apt-modal .modal-body { font-size: 13px; }
.apt-ascended {
  font-size: 13px; font-weight: 700; color: #ffd860;
  text-shadow: 0 0 10px rgba(255,200,80,0.55);
  margin: -4px 0 10px;
}
.apt-tree {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  padding: 6px 0 4px;
}
.apt-spine { display: none; }
.apt-row { position: relative; z-index: 1; width: 100%; display: flex; justify-content: center; }
.apt-node {
  position: relative;
  width: 200px;
  padding: 8px 12px;
  border-radius: 10px;
  border: 2px solid #3a1828;
  background: linear-gradient(160deg, #1c0d18, #14070f);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  color: #6a4060;
  cursor: default;
  transition: border-color 0.15s, background 0.15s, box-shadow 0.15s, transform 0.1s;
}
.apt-tier-label { font-weight: 700; font-size: 14px; flex: 0 0 auto; }
.apt-cost { font-size: 12px; font-weight: 700; opacity: 0.9; color: #fff; }
.apt-rank { font-size: 11px; opacity: 0.7; }
.apt-node.apt-owned {
  border-color: #ba6dd3;
  background: linear-gradient(160deg, #2a1240, #1a0828);
  color: #e0b0f0;
  box-shadow: 0 0 10px rgba(192,80,220,0.45), inset 0 0 10px rgba(192,80,220,0.18);
}
.apt-node.apt-owned .apt-cost { color: #b080d0; }
.apt-node.apt-next {
  border-color: #7040a0;
  color: #d0a0e0;
  cursor: pointer;
}
.apt-node.apt-next.apt-affordable {
  border-color: #e060ff;
  background: linear-gradient(160deg, #2e1340, #1f0d24);
  color: #f0d0ff;
  animation: aptPulse 1.4s ease-in-out infinite;
}
.apt-node.apt-next:hover { transform: translateY(-1px); }
.apt-node.apt-locked { opacity: 0.45; }
@keyframes aptPulse {
  0%, 100% { box-shadow: 0 0 6px rgba(220,90,255,0.45); }
  50%      { box-shadow: 0 0 16px rgba(220,90,255,0.8), 0 0 28px rgba(180,60,220,0.45); }
}

/* Per-ability perk tree (non-harem): the modal grew from 340px to 510px
   (+50%) inline; here we widen each node from 200 → 300 (+50%), drop the
   solid fill backgrounds to 80% alpha (= 20% transparent), and bump every
   text element +20% in size + bold. Scoped with :not(.apt-modal-harem) so
   the harem perk tree's own typography and layout stay intact. */
.apt-modal:not(.apt-modal-harem) .apt-node {
  width: 390px;
  background: linear-gradient(160deg, rgba(28,13,24,0.8), rgba(20,7,15,0.8));
}
.apt-modal:not(.apt-modal-harem) .apt-node.apt-owned {
  background: linear-gradient(160deg, rgba(42,18,64,0.8), rgba(26,8,40,0.8));
}
.apt-modal:not(.apt-modal-harem) .apt-node.apt-next.apt-affordable {
  background: linear-gradient(to right, rgba(224,96,255,0.12) 0%, rgba(224,96,255,0.5) 100%), linear-gradient(160deg, rgba(46,19,64,0.8), rgba(31,13,36,0.8));
}
.apt-modal:not(.apt-modal-harem) .modal-body { font-size: 17px; font-weight: 700; }
.apt-modal:not(.apt-modal-harem) .apt-ascended { font-size: 17px; font-weight: 700; }
.apt-modal:not(.apt-modal-harem) .apt-tier-label { font-size: 18px; font-weight: 700; }
.apt-modal:not(.apt-modal-harem) .apt-cost { font-size: 16px; font-weight: 700; }
.apt-modal:not(.apt-modal-harem) .apt-rank { font-size: 15px; font-weight: 700; }

/* Harem-specific perk tree: 20 alternating Training (💪) and Endurance (🏃)
   nodes. Two types are visually distinguished by a slight horizontal offset
   and by border-color tints — warm reddish for Training, cool blue for
   Endurance — so the alternation reads at a glance. */
/* Zig-zag layout: Training (str) and Endurance (end) rows are pushed far enough
   apart horizontally that the two node types no longer stack — they fan out to
   either side of the central spine. With the horizontal separation, vertical
   spacing is collapsed (negative margin) to shrink overall tree height. */
.apt-tree-harem { gap: 0; }
.apt-tree-harem .apt-row { margin-top: -10px; }
.apt-tree-harem .apt-row:first-child { margin-top: 0; }
.apt-tree-harem .apt-row-str { transform: translateX(-110px); }
.apt-tree-harem .apt-row-end { transform: translateX(110px); }
.apt-tree-harem .apt-node { padding: 5px 12px; }

/* New three-column harem perk tree: Training (left), Perks (middle, 8 nodes),
   Endurance (right). Columns are bottom-aligned so level 1 of every chain
   sits on the same baseline; nodes inside each column stack with a small gap. */
.apt-tree-harem-cols {
  display: flex;
  /* Override the base .apt-tree's flex-direction:column so the three chains
     actually sit side-by-side instead of stacking vertically. */
  flex-direction: row;
  align-items: flex-end;
  justify-content: center;
  gap: 28px;
  padding: 6px 4px 4px;
}
.apt-tree-harem-cols .apt-col {
  display: flex;
  flex-direction: column;
  align-items: stretch;
  gap: 4px;
  min-width: 150px;
}
/* Training (💪 str) and Endurance (🏃 end) columns are wider than the middle
   ⚡ Perks column: their longer "Training N" / "Endurance N" labels need the
   room. Widening them grows the modal out to its max-width (the middle column
   stays 150px). */
.apt-tree-harem-cols .apt-col-str,
.apt-tree-harem-cols .apt-col-end { min-width: 180px; }
.apt-tree-harem-cols .apt-col-head {
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: #c8b0e8;
  text-align: center;
  padding-bottom: 6px;
  border-bottom: 1px solid rgba(180,148,224,0.25);
  margin-bottom: 6px;
}
.apt-tree-harem-cols .apt-node {
  padding: 5px 12px;
  width: 100%;
  box-sizing: border-box;
  /* Title (emoji + name) top-left, cost (number + 💧) bottom-right. They share
     one line when they fit; when they don't, the cost wraps below the title and
     stays right-aligned, giving the title TL / cost BR look. */
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: flex-start;
}
.apt-tree-harem-cols .apt-tier-label { text-align: left; }
.apt-tree-harem-cols .apt-cost { margin-left: auto; text-align: right; }
/* Modal width: three 150px columns + 2 × 28px gaps + the .modal-box's
   28px-each-side padding = ~562px minimum. 660 gives ~10% extra breathing
   room around the columns and lets wider cost numbers (5T / 100T at L9-10)
   sit comfortably. */
.apt-modal-harem { max-width: 660px !important; }
/* Harem Perk Tree typography: Calibri, bold everywhere, ~10% larger text,
   and the per-node rank ("x / 10", "1 / 8") suppressed. */
.apt-modal-harem,
.apt-modal-harem * { font-family: Calibri, "Calibri", "Trebuchet MS", sans-serif; font-weight: 700; }
.apt-modal-harem .modal-title { font-size: 21px; }
.apt-modal-harem .modal-close { font-size: 15px; }
.apt-modal-harem .modal-body { font-size: 16px; }
.apt-modal-harem .apt-ascended { font-size: 15px; }
.apt-modal-harem .apt-tier-label { font-size: 16px; }
.apt-modal-harem .apt-cost { font-size: 15px; }
.apt-modal-harem .apt-col-head { font-size: 16px; }
.apt-modal-harem .apt-rank { display: none; }
.apt-node-str {
  border-color: #5a3220;
  background: linear-gradient(160deg, #2a1810, #160a06);
}
.apt-node-end {
  border-color: #284058;
  background: linear-gradient(160deg, #0e1c2a, #0a141d);
}
.apt-node-str.apt-owned {
  border-color: #ee9063;
  background: linear-gradient(160deg, #401c10, #2a0e08);
  color: #ffc8a8;
  box-shadow: 0 0 10px rgba(255,138,82,0.5), inset 0 0 10px rgba(255,138,82,0.2);
}
.apt-node-end.apt-owned {
  border-color: #79acf0;
  background: linear-gradient(160deg, #0e2440, #0a1428);
  color: #c4dcff;
  box-shadow: 0 0 10px rgba(106,170,255,0.5), inset 0 0 10px rgba(106,170,255,0.2);
}
.apt-node-str.apt-next            { border-color: #a0603a; color: #f0b090; }
.apt-node-end.apt-next            { border-color: #4a7aaa; color: #b0c8e8; }
.apt-node-str.apt-next.apt-affordable {
  border-color: #ffaa70;
  background: linear-gradient(to right, rgba(255,138,82,0.12) 0%, rgba(255,138,82,0.5) 100%), linear-gradient(160deg, #401c10, #2a0e08);
  color: #ffe0c8;
  animation: aptPulseStr 1.4s ease-in-out infinite;
}
.apt-node-end.apt-next.apt-affordable {
  border-color: #80c0ff;
  background: linear-gradient(to right, rgba(106,170,255,0.12) 0%, rgba(106,170,255,0.5) 100%), linear-gradient(160deg, #0e2440, #0a1428);
  color: #d4e4ff;
  animation: aptPulseEnd 1.4s ease-in-out infinite;
}
@keyframes aptPulseStr {
  0%, 100% { box-shadow: 0 0 6px rgba(255,138,82,0.45); }
  50%      { box-shadow: 0 0 16px rgba(255,138,82,0.85), 0 0 28px rgba(220,100,40,0.45); }
}
@keyframes aptPulseEnd {
  0%, 100% { box-shadow: 0 0 6px rgba(106,170,255,0.45); }
  50%      { box-shadow: 0 0 16px rgba(106,170,255,0.85), 0 0 28px rgba(60,120,220,0.45); }
}

/* Perk-tree redesign pass: panel fill at 85% alpha (15% transparent), the
   close X and the standard-tree title bumped +10% to match the +10% body
   text. Applies to every ability perk tree (standard + harem). */
.modal-box.apt-modal {
  background: radial-gradient(ellipse at 50% 0%, rgba(60,21,48,0.85) 0%, rgba(34,16,24,0.85) 65%);
}
.apt-modal:not(.apt-modal-harem) .modal-title { font-size: 19px; }
.apt-modal .ui-unlock-x { font-size: 18px; }

/* Stroke Streak perk tree: two same-colored columns of window-extension perks
   laid out side by side (like the harem tree, but both columns share the
   default purple node styling). Bottom-aligned so level 1 of each column sits
   on the same baseline. */
.apt-modal-ss { max-width: 470px !important; }
.apt-ss-summary {
  font-size: 14px;
  font-weight: 700;
  color: #e0a8f4;
  margin-bottom: 10px;
}
.apt-ss-summary b { color: #ffd0ff; }
.apt-tree-ss-cols {
  flex-direction: row;
  align-items: flex-end;
  justify-content: center;
  gap: 26px;
  padding: 6px 4px 4px;
}
.apt-tree-ss-cols .apt-col {
  display: flex;
  flex-direction: column;
  gap: 6px;
  min-width: 175px;
}
.apt-tree-ss-cols .apt-col-head {
  font-size: 13px;
  font-weight: 700;
  text-align: center;
  color: #d8a0f0;
  margin-bottom: 6px;
}
/* Beat the .apt-modal:not(.apt-modal-harem) .apt-node {width:390px} rule
   (equal specificity, later in source) so nodes fill their column instead. */
.apt-modal-ss .apt-tree-ss-cols .apt-node {
  width: 100%;
  padding: 6px 12px;
  justify-content: space-between;
}
.apt-tree-ss-cols .apt-tier-label { text-align: left; }
.apt-tree-ss-cols .apt-cost { margin-left: auto; text-align: right; }

/* === Arcane Drippy perk-tree window — blue retheme (cock-magic blue) ===== */
/* Scoped to .apt-modal-arcane so the shared .apt-modal-ss (Stroke Streak) stays
   purple. Overrides the default magenta chrome, headers, nodes and spell chips. */
.modal-box.apt-modal.apt-modal-arcane {
  background: radial-gradient(ellipse at 50% 0%, rgba(20,40,92,0.9) 0%, rgba(9,16,40,0.9) 65%);
  border: 1.5px solid #4f7fd0;
  box-shadow: 0 0 32px rgba(70,120,255,0.32), 0 8px 28px #0008;
}
.apt-modal-arcane .modal-title { color: #bcd9ff; text-shadow: 0 0 10px rgba(110,160,255,0.5); }
.apt-modal-arcane .apt-ss-summary { color: #9fc0ff; }
.apt-modal-arcane .apt-ss-summary b { color: #e6f0ff; }
.apt-modal-arcane .apt-col-head { color: #a8c8ff; }
.apt-modal-arcane .af-sel-head { color: #a8c8ff; border-top-color: #2a4a9e; }
.apt-modal-arcane:not(.apt-modal-harem) .apt-node { background: linear-gradient(160deg, rgba(14,26,52,0.82), rgba(8,14,34,0.82)); }
.apt-modal-arcane:not(.apt-modal-harem) .apt-node.apt-owned { background: linear-gradient(160deg, rgba(26,52,104,0.82), rgba(12,24,58,0.82)); }
.apt-modal-arcane:not(.apt-modal-harem) .apt-node.apt-next.apt-affordable { background: linear-gradient(to right, rgba(96,160,255,0.14) 0%, rgba(80,150,255,0.5) 100%), linear-gradient(160deg, rgba(20,38,72,0.82), rgba(12,22,48,0.82)); }
.apt-modal-arcane .af-spell-chip { background: #0e1a30; border-color: #2a4a8e; color: #bcd0ff; }
.apt-modal-arcane .af-spell-chip:hover { background: #16294a; border-color: #4f7fd0; }
.apt-modal-arcane .af-spell-chip-sel { background: linear-gradient(135deg, #1a3a7a, #2a5ab0); border-color: #7fb0ff; color: #eaf2ff; box-shadow: 0 0 8px rgba(120,170,255,0.5); }
.apt-modal-arcane .af-spell-chip-cd { color: #6f90c8; }
.apt-modal-arcane .af-spell-chip-sel .af-spell-chip-cd { color: #cfe2ff; }

/* === Arcane Familiar auto-cast spell selector =========================== */
/* Lives in the Arcane Familiar perk-tree popup, beneath the cooldown column. */
.af-sel-head {
  font-size: 13px;
  font-weight: 700;
  color: #d8a0f0;
  text-align: center;
  margin: 16px 0 8px;
  padding-top: 12px;
  border-top: 1px solid #4a2070;
}
.af-spell-grid {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 7px;
  max-width: 420px;
  margin: 0 auto;
}
.af-spell-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 6px 10px;
  background: #1a0e24;
  border: 1.5px solid #4a2070;
  border-radius: 8px;
  color: #c8a0e0;
  font-size: 12px;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, transform 0.1s;
}
.af-spell-chip:hover {
  background: #2a1440;
  border-color: #7040a0;
  transform: translateY(-1px);
}
.af-spell-chip-sel {
  background: linear-gradient(135deg, #3a1060, #6a2a9b);
  border-color: #ce93d8;
  color: #f3e5f5;
  box-shadow: 0 0 8px rgba(206, 147, 216, 0.5);
}
.af-spell-chip-icon { font-size: 14px; line-height: 1; }
.af-spell-chip-name { font-weight: 600; }
.af-spell-chip-cd { font-size: 11px; color: #9068b0; }
.af-spell-chip-sel .af-spell-chip-cd { color: #e0c0ff; }
.af-sel-empty {
  font-size: 12px;
  color: #8a6aa0;
  text-align: center;
  padding: 6px 0 2px;
}

/* === Droplet portal: dim while a modal/window is open ==================== */
/* Pairs with the JS pause of _autoTimer in golden_eggplant.js so the portal
   visibly recedes (and stops aging) whenever the player opens a modal. */
body.modal-open #golden-eggplant {
  opacity: 0.5;
  transition: opacity 0.18s ease;
}

/* === IGE Milestone Reward popup ========================================== */
/* Achievements milestone popup: 80% opaque (20% transparent) backdrop,
   bolded text 20% larger than base modal sizes, "Great!" button 30% larger
   on top of that, and per-card pulsing inset fill + outer glow keyed on the
   card's rarity color (CSS var --upg-color set inline by the JS). */
.ige-milestone-popup {
  background: radial-gradient(ellipse at 50% 0%, rgba(60,21,48,0.8) 0%, rgba(34,16,24,0.8) 65%) !important;
}
.ige-milestone-popup,
.ige-milestone-popup * { font-weight: 700 !important; }
.ige-milestone-popup .modal-title { font-size: 20px; }
.ige-milestone-popup .modal-body { font-size: 16px; }
.ige-milestone-popup .modal-body > div:first-child { font-size: 18px !important; }
.ige-milestone-popup .ige-milestone-card div[style*="color:#a080c0"] { font-size: 14px !important; }
.ige-milestone-popup .modal-close {
  font-size: 19px;
  padding: 11px 30px;
}
.ige-milestone-popup .ige-milestone-cards {
  padding: 10px 0;
}
.ige-milestone-popup .ige-milestone-card {
  animation: igeMilestoneCardPulse 1.6s ease-in-out infinite;
}
@keyframes igeMilestoneCardPulse {
  0%, 100% {
    box-shadow:
      inset 0 0 10px 2px var(--upg-color, #ffffff),
      0 0 12px var(--upg-color, #ffffff);
  }
  50% {
    box-shadow:
      inset 0 0 26px 6px var(--upg-color, #ffffff),
      0 0 28px var(--upg-color, #ffffff);
  }
}
