/* ─────────────────────────────────────────────────────────────────────────────
   ui_polish.css — Visual & animation improvements pass (April 2026)
   ALL changes isolated here for easy revert.
   To revert everything: remove the <link> for this file from index.html.
   See CHANGES.md for a full list of what each section changes.
   ─────────────────────────────────────────────────────────────────────────────*/

/* Ghost Job & Ghost Army: 30% more transparent icons (card + shelf). */
#upg-card-ghost .upg-icon,
#upg-card-ghost_army .upg-icon,
#shelf-items-ghost .shelf-item,
#shelf-items-ghost_army .shelf-item {
  opacity: 0.7;
}

/* ── 0. BANNER CENTER — Eggplant title + radio, absolutely centered ──────── */
/* Shifted 200px left on desktop via the transform; mobile.css overrides
   #banner-center to position:static so this transform never reaches mobile. */
#banner-center {
  position: absolute;
  left: max(50%, 780px);
  transform: translateX(calc(-50% - 200px));
  display: flex;
  align-items: center;
  gap: 8px;
  pointer-events: none;
  white-space: nowrap;
}
#banner-center .b-title,
#banner-center #radio-controls {
  pointer-events: auto;
}
#banner-center #radio-controls {
  display: none; /* JS controls visibility */
}

/* ── 1. COLUMN DEPTH — Inset glow top edge + deeper shadows ─────────────── */
#left-col {
  box-shadow:
    0 4px 32px rgba(0,0,0,0.6),
    inset 0 1px 0 rgba(200,100,160,0.18);
}
#mid-col {
  box-shadow:
    0 4px 32px rgba(0,0,0,0.6),
    inset 0 1px 0 rgba(200,100,160,0.14);
}
#right-col {
  box-shadow:
    0 4px 32px rgba(0,0,0,0.6),
    inset 0 1px 0 rgba(200,100,160,0.14);
}

/* ── 2. BANNER — Gradient + stronger shadow + accent bottom border ──────── */
#banner {
  background: linear-gradient(180deg, #301220 0%, #220e18 100%);
  box-shadow: 0 2px 22px rgba(0,0,0,0.65), 0 1px 0 rgba(180,80,140,0.18);
  border-bottom: 1px solid rgba(180,80,140,0.28);
  overflow: visible;
  z-index: 100;
}

/* ── 2b. BANNER SEPARATOR — Sits right after eggplants badge ───────────── */
.b-sep {
  display: block;
  width: 1px;
  height: 22px;
  background: rgba(180,80,140,0.28);
  margin: 0 6px;
  flex-shrink: 0;
}

/* ── 2c. TOOLTIP FADE-IN — Slide up + fade for all tooltips ────────────── */
.b-currency::after,
#cosmetics-btn[data-tooltip]::after,
#themes-btn[data-tooltip]::after {
  transition: opacity 0.15s ease, transform 0.15s ease;
  transform: translateX(-50%) translateY(4px);
}
.b-currency:hover::after,
#cosmetics-btn[data-tooltip]:hover::after,
#themes-btn[data-tooltip]:hover::after {
  opacity: 1;
  transform: translateX(-50%) translateY(0);
}
#currency-dragons::after {
  transform: translateY(4px);
}
#currency-dragons:hover::after {
  transform: translateY(0);
}
.x10-tooltip {
  transition: opacity 0.12s ease, transform 0.12s ease;
}

/* ── Shelf tip (upgrade tooltip) — expanded structured layout ─────────── */
/* All sizes scaled 1.5× from the original layout so the tooltip pairs with
 * the larger pixelated icon canvas (which renders at 2× the shop slot). */
.shelf-tip.x10-tooltip {
  white-space: normal;
  padding: 15px 18px;
  font-family: Calibri, 'Trebuchet MS', sans-serif;
  min-width: 390px;
  max-width: 510px;
  font-weight: 500;
  line-height: 1.35;
  box-shadow: 0 4px 14px rgba(0,0,0,0.55);
}
.shelf-tip .st-head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 15px;
}
.shelf-tip .st-head-l {
  display: grid;
  grid-template-columns: auto 1fr;
  grid-template-rows: auto auto;
  column-gap: 9px;
  row-gap: 3px;
  min-width: 0;
}
.shelf-tip .st-head-l .st-icon {
  font-size: 29px;
  grid-row: 1 / span 2;
  align-self: center;
}
.shelf-tip .st-head-l .st-name {
  font-size: 24px;
  font-weight: 700;
  color: #ffd5e5;
}
.shelf-tip .st-head-l .st-cost {
  font-size: 20px;
  color: #d89ec0;
  font-weight: 600;
}
.shelf-tip .st-head-r {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  flex-shrink: 0;
}
.shelf-tip .st-head-r .st-owned-label {
  font-size: 17px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: #a06080;
}
.shelf-tip .st-head-r .st-owned-val {
  font-size: 21px;
  font-weight: 700;
  color: #ffe0c0;
}
.shelf-tip .st-hr {
  height: 1px;
  background: linear-gradient(90deg, transparent, rgba(160,80,120,0.55), transparent);
  margin: 9px 0;
}
.shelf-tip .st-desc {
  font-size: 20px;
  font-weight: 500;
  color: #e8c0d0;
  font-style: italic;
}
.shelf-tip .st-rate {
  font-size: 20px;
  color: #f0d0e0;
  margin-bottom: 5px;
}
.shelf-tip .st-rate-val {
  font-weight: 700;
  color: #ffffff;
}
.shelf-tip .st-rate-sep {
  color: #8a4070;
  margin: 0 3px;
}
.shelf-tip .st-rate-pct {
  font-weight: 700;
  color: #ffd080;
}
.shelf-tip .st-rate-of {
  color: #b080a0;
  font-size: 18px;
}
.shelf-tip .st-lifetime {
  font-size: 18px;
  color: #a080a0;
}
.shelf-tip .st-lifetime-val {
  color: #c0ffd0;
  font-weight: 600;
}
.shelf-tip .st-bulkhint {
  margin-top: 9px;
  padding-top: 8px;
  border-top: 1px dashed rgba(200,160,200,0.25);
  font-size: 17px;
  color: #a090b0;
  text-align: center;
  font-style: italic;
}
.buy-tip .bt-bulkhint {
  margin-top: 6px;
  padding-top: 5px;
  border-top: 1px dashed rgba(200,160,200,0.25);
  font-size: 11px;
  color: #a090b0;
  text-align: center;
  font-style: italic;
}
.shelf-tip .st-bulkhint b,
.buy-tip .bt-bulkhint b {
  color: #ffe080;
  font-style: normal;
  font-weight: 700;
}

/* ── Ability (ghost upgrade) tooltips: Calibri. Sizes are 10% bigger than
 *    the previous "30% smaller than 1.5× layout" pass (every size = old × 1.1). */
.shelf-tip.ability-tip {
  font-family: Calibri, 'Trebuchet MS', sans-serif;
  font-size: 19px; /* 17.39 × 1.1 */
}
.shelf-tip.ability-tip .st-head-l .st-icon { font-size: 26px; } /* 23.94 × 1.1 */
.shelf-tip.ability-tip .st-head-l .st-name { font-size: 22px; } /* 20.16 × 1.1 */
.shelf-tip.ability-tip .st-head-l .st-cost { font-size: 18px; } /* 16.38 × 1.1 */
.shelf-tip.ability-tip .st-head-r .st-owned-label { font-size: 15px; } /* 13.86 × 1.1 */
.shelf-tip.ability-tip .st-head-r .st-owned-val { font-size: 19px; } /* 17.64 × 1.1 */
.shelf-tip.ability-tip .st-desc { font-size: 18px; }
.shelf-tip.ability-tip .st-rate { font-size: 18px; }
.shelf-tip.ability-tip .st-rate-of { font-size: 17px; } /* 15.12 × 1.1 */
.shelf-tip.ability-tip .st-lifetime { font-size: 17px; }
.shelf-tip.ability-tip .st-bulkhint { font-size: 15px; }

/* The pixelated icon canvas overrides font-size sizing — let the canvas's
 * inline width/height drive layout so the rasterized icon stays at 2× the
 * shop slot regardless of any font-size scaling above. Mirror the shop's
 * contrast/saturate boost so tooltip icons match the shop's punchy palette. */
.shelf-tip .st-head-l .st-icon canvas.upg-icon-canvas {
  display: block;
  filter: contrast(1.3) saturate(1.5);
}

/* ── Buy-button tooltip — compact 2-row cost/owned display ─────────────── */
.buy-tip.x10-tooltip {
  white-space: normal;
  padding: 8px 11px;
  min-width: 150px;
  line-height: 1.3;
  box-shadow: 0 4px 10px rgba(0,0,0,0.5);
  font-family: Calibri, 'Trebuchet MS', sans-serif;
  font-size: 17px;
}
.buy-tip .bt-row {
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 12px;
}
.buy-tip .bt-row + .bt-row {
  margin-top: 3px;
}
.buy-tip .bt-label {
  color: #a06080;
  font-size: 13px;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  font-weight: 600;
}
.buy-tip .bt-val {
  color: #ffe0c0;
  font-weight: 700;
  font-size: 17px;
}
.buy-tip .bt-bulkhint {
  font-size: 13px;
}

/* Extra gap between Stroke Streak and Helper Hand — matches the 5px
   margin-top that sits above Harem (#upg-card-cylinder_army) so both
   pre-ghost upgrades get the same breather. */
#upg-card-helper_hand {
  margin-top: 5px;
}
#shelf-row-helper_hand,
#shelf-row-stroke_streak,
#shelf-row-coord_burst,
#shelf-row-ghost,
#shelf-row-ghost_army,
#shelf-row-cock_magic,
#shelf-row-hand_job {
  display: none !important;
}
#prestige-xp-tooltip {
  transition: opacity 0.15s ease, transform 0.15s ease !important;
}

/* ── 3. CURRENCY BADGES — Larger emoji + hover glow ─────────────────────── */
.b-currency span:first-child {
  font-size: 16px;
}
.b-currency {
  transition: transform 0.18s, box-shadow 0.18s;
}
.b-currency:hover {
  box-shadow: 0 2px 10px rgba(160,80,140,0.35);
}

/* ── Currency tooltips (disabled — handled by universal JS tooltip) ───── */
.b-currency { position: relative; }
.b-currency::after { display: none !important; }

/* ── 4. BANNER BUTTONS — Squarer pills + hover glow + ripple ───────────── */
.b-btn {
  border-radius: 8px;
  overflow: hidden;
  position: relative;
}
.b-btn:hover {
  box-shadow: 0 0 14px rgba(200,100,160,0.3);
}
.b-btn .btn-ripple {
  position: absolute;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255,255,255,0.25) 0%, transparent 70%);
  transform: scale(0);
  animation: btnRippleExpand 0.5s ease-out forwards;
  pointer-events: none;
}
@keyframes btnRippleExpand {
  0%   { transform: scale(0); opacity: 1; }
  100% { transform: scale(2.5); opacity: 0; }
}

/* ── 5. PRESTIGE BAR — Glow on fill + deeper track ─────────────────────── */
#prestige-bar-fill {
  box-shadow: 0 0 10px rgba(192,80,200,0.7), 0 0 20px rgba(160,60,200,0.35);
}
#prestige-bar-wrap {
  background: #160a14;
  height: 16px;
}

/* ── 6. DROPLET COUNT — [reverted] ─────────────────────────────────────── */

/* ── 7. AFFORDABLE GLOW — see animations.css. The upg-card pulse is now an
   opacity animation on a ::before pseudo-element with a static inset shadow,
   because animating box-shadow forced per-frame repaints on every affordable
   card (40-60 cards × 60fps stacked up inside #right-col and made star
   movement jank badly). Perk cards still use box-shadow animation via the
   original affordableGlow keyframes in animations.css. */

/* ── 8. UPGRADE CARD HOVER — Micro-lift only ────────────────────────────── */
/* box-shadow removed from both transition + hover. Sweeping the mouse across
   a column of cards used to fire per-card animated paints; the lift alone is
   compositor-only and doesn't invalidate the stars beneath. */
.upg-card {
  transition: background 0.15s, border-color 0.15s, transform 0.15s;
}
.upg-card.affordable:hover {
  transform: translateY(-2px);
}

/* ── 9. PANEL SLIDE-IN ANIMATIONS (stats + achievements) ────────────────── */
@keyframes panelSlideIn {
  from { opacity: 0; transform: translateX(18px); }
  to   { opacity: 1; transform: translateX(0); }
}
#stats-panel.visible {
  animation: panelSlideIn 0.22s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  background: rgba(20, 8, 16, 0.92);
}
#achievements-panel.visible {
  animation: panelSlideIn 0.22s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  background: rgba(20, 8, 16, 0.92);
}

/* ── 10. ACHIEVEMENT TILE HOVER — Lift + scale ──────────────────────────── */
.ach-tile {
  transition: all 0.18s;
}
.ach-tile.ach-earned:hover {
  transform: translateY(-2px) scale(1.02);
  box-shadow: 0 6px 24px rgba(140,80,240,0.5);
}

/* ── 11. MID-TOP-BAR BUTTONS — Base style + hover ──────────────────────── */
/* Brighter border + tri-stop gradient + soft inset highlight to lift them above
   the previous flat look — but deliberately tamer than the cosmetics/themes
   buttons (no backdrop-blur, smaller glow radius, lower-saturation fill). */
#mid-top-bar { --mtb-text: 1; --mtb-pad: 1; }
#stats-btn, #achievements-btn, #graph-btn, #options-btn {
  background: linear-gradient(135deg, #321448 0%, #1d0a30 55%, #150624 100%);
  border: 1.5px solid #7a40b0;
  /* Base sizes bumped +10% (radius/padding/font). The responsive system in
     mid_top_bar_responsive.js scales --mtb-text + --mtb-pad continuously as
     the bar approaches its column edge, then flips to icon-only when even
     the smallest text size won't fit.
     Only HORIZONTAL padding scales with --mtb-pad; vertical padding and
     border-radius stay fixed so the buttons retain their full height all the
     way through the shrink — and so the transition into icon-only mode (which
     also keeps full height) has no visible height jump. */
  border-radius: 9px;
  padding: 6px calc(16px * var(--mtb-pad, 1)) 7px;
  font-size: calc(16px * var(--mtb-text, 1));
  font-weight: 700;
  color: #d4a8ee;
  cursor: pointer;
  letter-spacing: 0.02em;
  white-space: nowrap;
  text-shadow: 0 1px 2px rgba(0,0,0,0.45);
  box-shadow:
    inset 0 1px 0 rgba(180,130,230,0.22),
    inset 0 -1px 0 rgba(0,0,0,0.35),
    0 0 8px 1px rgba(140,80,200,0.32),
    0 0 16px 3px rgba(140,80,200,0.14);
  transition: background 0.15s, border-color 0.15s, color 0.15s, box-shadow 0.18s, transform 0.12s, filter 0.15s, font-size 0.18s, padding 0.18s, border-radius 0.18s;
}
#stats-btn:hover, #achievements-btn:hover, #graph-btn:hover, #options-btn:hover {
  background: linear-gradient(135deg, #44205c 0%, #2a1244 55%, #1f0c34 100%);
  border-color: #a060d0;
  color: #f0d0ff;
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(220,170,255,0.30),
    inset 0 -1px 0 rgba(0,0,0,0.35),
    0 4px 14px rgba(140,90,220,0.42),
    0 0 18px rgba(140,90,220,0.22);
  filter: brightness(1.10);
}
#achievements-btn {
  background: linear-gradient(135deg, #1e3a80 0%, #112260 55%, #0d1a4a 100%);
  border-color: #5080d0;
  color: #b8d4f8;
  box-shadow:
    inset 0 1px 0 rgba(140,190,255,0.22),
    inset 0 -1px 0 rgba(0,0,0,0.35),
    0 0 8px 1px rgba(70,130,240,0.22),
    0 0 16px 3px rgba(60,110,220,0.10);
}
#achievements-btn:hover {
  background: linear-gradient(135deg, #2848a0 0%, #162e78 55%, #111e5a 100%);
  border-color: #6a96e8;
  color: #d8eaff;
  box-shadow:
    inset 0 1px 0 rgba(180,210,255,0.30),
    inset 0 -1px 0 rgba(0,0,0,0.35),
    0 4px 14px rgba(80,140,255,0.32),
    0 0 18px rgba(70,120,240,0.18);
}

/* Icon-only mode — applied by JS when even the smallest scale (text 62%, pad
   45%) wraps to a second line. Mirrors the mobile.css emoji-only pattern: hide
   inline label via font-size:0, render emoji from a ::before pseudo. JS also
   sets data-tooltip in this mode so hovering shows the button's name. */
#mid-top-bar.mtb-icons-only #stats-btn,
#mid-top-bar.mtb-icons-only #graph-btn,
#mid-top-bar.mtb-icons-only #achievements-btn,
#mid-top-bar.mtb-icons-only #options-btn {
  font-size: 0;
  /* Fixed padding in icon-only mode — no --mtb-pad multiplier — so the
     buttons stay at full height once the bar collapses to icons. The
     vertical padding here matches the text-mode vertical padding above
     (5.6925 / 6.831) for a seamless visual height match. */
  padding: 6px 10px 7px;
}
#mid-top-bar.mtb-icons-only #stats-btn::before        { content:"📊"; font-size:18px; line-height:1; display:inline-block; }
#mid-top-bar.mtb-icons-only #graph-btn::before        { content:"📈"; font-size:18px; line-height:1; display:inline-block; }
#mid-top-bar.mtb-icons-only #achievements-btn::before { content:"🏆"; font-size:18px; line-height:1; display:inline-block; }
#mid-top-bar.mtb-icons-only #options-btn::before      { content:"⚙️"; font-size:18px; line-height:1; display:inline-block; }

/* Suppresses the size transition during JS probe writes (set scale=1 then 0.8
   to measure natural + minimum widths) so the user never sees a flash of the
   probed values. */
#mid-top-bar.mtb-measuring #stats-btn,
#mid-top-bar.mtb-measuring #graph-btn,
#mid-top-bar.mtb-measuring #achievements-btn,
#mid-top-bar.mtb-measuring #options-btn { transition: none !important; }

/* ── 12. BOOKSHELF ROW — Subtle hover highlight ─────────────────────────── */
.shelf-row {
  transition: background 0.15s;
}
.shelf-row:hover {
  background: linear-gradient(to bottom, #2e1220, #261018);
}

/* ── 13. MODAL ENTRANCE — Punchy scale-with-overshoot ─────────────────── */
@keyframes fadeInScale {
  0%   { transform: scale(0.55); opacity: 0; }
  60%  { transform: scale(1.06); opacity: 1; }
  100% { transform: scale(1);    opacity: 1; }
}
.modal-box {
  animation: fadeInScale 0.32s cubic-bezier(0.2, 0.9, 0.3, 1.2);
  transform-origin: center center;
}
.vip-modal, .daily-modal, .ad-box, .scratch-box {
  animation: fadeInScale 0.34s cubic-bezier(0.2, 0.9, 0.3, 1.2);
  transform-origin: center center;
}
.premium-shop-modal, .fake-pay-modal {
  animation: fadeInScale 0.32s cubic-bezier(0.2, 0.9, 0.3, 1.2);
  transform-origin: center center;
}
/* Backdrop fade-in, runs in parallel with the scale-in above */
@keyframes overlayFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}
.overlay {
  animation: overlayFadeIn 0.18s ease both;
}
/* ── 13b. MODAL EXIT — Scale-down + fade ─────────────────────────────── */
@keyframes fadeOutScale {
  0%   { transform: scale(1);    opacity: 1; }
  100% { transform: scale(0.82); opacity: 0; }
}
.modal-box.modal-closing,
.vip-modal.modal-closing,
.daily-modal.modal-closing,
.ad-box.modal-closing,
.scratch-box.modal-closing,
.premium-shop-modal.modal-closing,
.fake-pay-modal.modal-closing {
  animation: fadeOutScale 0.16s cubic-bezier(0.55, 0, 0.675, 0.19) forwards !important;
  transform-origin: center center;
}
@keyframes overlayFadeOut {
  from { opacity: 1; }
  to   { opacity: 0; }
}
.overlay.overlay-closing {
  animation: overlayFadeOut 0.16s ease forwards !important;
  pointer-events: none;
}

/* ── 14. STAT ROW HOVER — Gentle slide right ────────────────────────────── */
.stat-row {
  transition: background 0.12s, border-color 0.12s, transform 0.12s;
}
.stat-row:hover {
  transform: translateX(3px);
}

/* ── 15. CYLINDER NAME HEADER — Hover background tint ──────────────────── */
#cylinder-name-header {
  transition: color 0.18s, background 0.18s;
  border-radius: 0;
}
#cylinder-name-header:hover {
  background: rgba(200,100,160,0.07);
}

/* ── 16. SHOP HEADER — Subtle gradient bg + bottom glow ─────────────────── */
#shop-header {
  background: linear-gradient(180deg, #1e1015 0%, #1a0c12 100%);
  box-shadow: 0 1px 0 rgba(180,80,140,0.25);
}

/* ── 17. SCROLLBAR — Gradient thumb for polish ──────────────────────────── */
::-webkit-scrollbar-thumb {
  background: linear-gradient(to bottom, #6a2848, #4a1838);
  border: 1px solid #3a1525;
}
::-webkit-scrollbar-thumb:hover {
  background: linear-gradient(to bottom, #9a3868, #6a2848);
}

/* ── 17a. CYLINDER PARALLAX SHINE — Smooth shine position transition ───── */
#cylinder-shine {
  transition: left 0.12s ease-out, top 0.12s ease-out;
}

/* ── 17b. STAGGERED CARD REVEAL — Cards animate in with stagger ────────── */
@keyframes cardStaggerIn {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}
.upg-card.stagger-in {
  animation: cardStaggerIn 0.3s cubic-bezier(0.25, 0.46, 0.45, 0.94) both;
}
/* Stagger for modal children */
@keyframes modalChildIn {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: translateY(0); }
}
.stagger-child {
  animation: modalChildIn 0.22s ease both;
}

/* ── 18. UPGRADE SPLIT — Smooth scroll ─────────────────────────────────── */
#upgrades-scroll, #upgrades-split, #bookshelf {
  scroll-behavior: smooth;
}

/* ── 19. TAB TRANSITIONS — All modal tabs ──────────────────────────────── */
.vip-modal-tab, .daily-tab, .fp-tab {
  transition: all 0.2s ease;
}

/* ── 20. COSMETICS/THEMES/STROKE BUTTONS — Enhanced hover ──────────────── */
#cosmetics-btn, #themes-btn {
  transition: background 0.15s, box-shadow 0.2s, transform 0.15s;
}
#cosmetics-btn:hover, #themes-btn:hover {
  box-shadow:
    0 0 22px 6px rgba(112,64,192,0.65),
    0 0 44px 12px rgba(112,64,192,0.32);
  transform: translateY(-2px);
}
#drug-market-btn {
  transition: background 0.15s, box-shadow 0.2s, transform 0.15s;
}
#drug-market-btn:hover {
  box-shadow:
    0 0 12px 3px rgba(80,200,80,0.6),
    0 0 22px 5px rgba(80,200,80,0.28);
  transform: translateY(-2px);
}

/* ── 21. LEFT STATS — [reverted] ────────────────────────────────────────── */

/* ── 22. VIRILITY EXCHANGE BUTTON — Lift on hover ───────────────────────── */
.virility-exchange-btn {
  transition: background 0.15s, border-color 0.15s, transform 0.15s, box-shadow 0.15s;
}
.virility-exchange-btn:hover {
  transform: translateY(-1px);
  box-shadow: 0 4px 14px rgba(160,80,255,0.4);
}

/* ── 23. CLAIM BUTTONS — Stronger pulse + bigger scale ──────────────────── */
@keyframes claimGlowFree {
  0%,100% {
    box-shadow: 0 0 8px rgba(200,80,140,0.5), 0 0 18px rgba(200,80,140,0.24);
    transform: scale(1);
  }
  50% {
    box-shadow: 0 0 22px rgba(220,80,140,1), 0 0 44px rgba(200,60,120,0.65);
    transform: scale(1.035);
  }
}
@keyframes claimGlowVip {
  0%,100% {
    box-shadow: 0 0 8px rgba(160,80,255,0.5), 0 0 18px rgba(160,80,255,0.24);
    transform: scale(1);
  }
  50% {
    box-shadow: 0 0 22px rgba(180,80,255,1), 0 0 44px rgba(140,60,220,0.65);
    transform: scale(1.035);
  }
}

/* ── 24. BANNER BUTTON GLOWS — Static, color-matched, non-pulsing ───────── */
/* All glows here are static (no animation) and tuned to be subtle but
   visible against the dark banner. Each color is matched to its button's
   accent so the button feels "lit from within" rather than spotlit. */
/* Per-banner-button glows + colour overrides moved to addons.css alongside
   #ai-or-human-btn / #dice-btn so every banner pill is themed via a single
   dedicated ID rule. The shared .b-btn ripple/border-radius styles above
   still cascade for properties the ID rules don't set. */

/* ── 25. UPGRADES COL HEADERS — Hover color brightening ─────────────────── */
.upgrades-col-header, .bookshelf-col-header {
  transition: color 0.2s;
}
.upgrades-col-header:hover {
  color: #c090a8;
}
.bookshelf-col-header:hover {
  color: #9a5078;
}

/* ── 26. PERK SECTION — Glowing top border ──────────────────────────────── */
#perk-section {
  border-top: 1px solid rgba(180,80,140,0.3);
}

/* ── 27. PRESTIGE LABEL — Glow on hover ─────────────────────────────────── */
#prestige-label:hover {
  filter: brightness(1.35) drop-shadow(0 0 6px rgba(220,150,255,0.5));
}

/* ── 28. SHELF ITEM — Slightly bouncier pop on hover ────────────────────── */
.shelf-item {
  transition: transform 0.12s cubic-bezier(0.175, 0.885, 0.32, 1.5);
}
.shelf-item:hover {
  transform: scale(1.38) translateY(-2px);
}

/* ── 29. SKILL NODE — Brighter hover glow ───────────────────────────────── */
.skill-node:hover:not(.locked-node) {
  box-shadow: 0 0 22px 6px rgba(144,80,240,0.55);
  filter: brightness(1.18);
}

/* ── 30. DAILY TAB — Active underline glow ──────────────────────────────── */
.daily-tab.active {
  text-shadow: 0 0 8px rgba(200,80,140,0.6);
}
.daily-tab.vip-tab.active {
  text-shadow: 0 0 8px rgba(160,80,255,0.6);
}

/* ── 31. NOTIF DOT — [reverted] ─────────────────────────────────────────── */

/* ── 32. VIRILITY BAR FILL — Smoother width transition ──────────────────── */
.virility-bar-fill {
  transition: width 0.5s cubic-bezier(0.25, 0.46, 0.45, 0.94);
}

/* ══════════════════════════════════════════════════════════════════════════
   FEEL IMPROVEMENTS — April 2026 pass
   ══════════════════════════════════════════════════════════════════════════ */

/* ── OPT 2: Cylinder and kiwi idle breathing ─────────────────────────────── */
@keyframes cylinderBreath {
  0%,100% { transform: translateX(-50%) scale(1.0); }
  50%     { transform: translateX(-50%) scale(1.05); }
}
@keyframes kiwiBreath {
  0%,100% { transform: translateX(-50%) scale(1.0); }
  50%     { transform: translateX(-50%) scale(1.04); }
}
/* Breath is driven by JS (squeeze.js _getBreathCyl/_getBreathKiwi + idle rAF
   loop) so it can compose with drag shake, tutorial scale, hover bounce, and
   squeeze progress. CSS animations override inline transforms, which would
   otherwise wipe out those effects. */

/* ── OPT 5b: Streak fire effect — visual heat-up at high combos ──────────── */
@keyframes streakHeatT1 {
  0%,100% { filter: brightness(1); }
  50%     { filter: brightness(1.15); }
}
@keyframes streakHeatT2 {
  0%,100% { filter: brightness(1) hue-rotate(0deg); }
  50%     { filter: brightness(1.3) hue-rotate(-10deg); }
}
@keyframes streakHeatT3 {
  0%      { filter: brightness(1) hue-rotate(0deg); }
  25%     { filter: brightness(1.4) hue-rotate(-15deg); }
  50%     { filter: brightness(1.6) hue-rotate(-25deg); }
  75%     { filter: brightness(1.4) hue-rotate(-15deg); }
  100%    { filter: brightness(1) hue-rotate(0deg); }
}
#streak-msg.streak-fire-t1 { animation: streakHeatT1 1.2s ease-in-out infinite; }
#streak-msg.streak-fire-t2 { animation: streakHeatT2 0.9s ease-in-out infinite; }
#streak-msg.streak-fire-t3 { animation: streakHeatT3 0.6s ease-in-out infinite; }
#streak-bar-fill.streak-bar-t2 {
  background: linear-gradient(to right, #e060c0, #ff60e8, #ff40d0);
}
#streak-bar-fill.streak-bar-t3 {
  background: linear-gradient(to right, #ff8800, #ffcc44, #ff6600);
}

/* ── OPT 6: Streak glow tiers ────────────────────────────────────────────── */
#streak-wrap.streak-t1 {
  border-color: rgba(255,100,180,0.42);
  box-shadow: 0 0 14px rgba(255,100,180,0.45);
}
#streak-wrap.streak-t2 {
  border-color: rgba(255,60,220,0.55);
  box-shadow: 0 0 22px rgba(240,60,220,0.65), 0 0 44px rgba(200,40,200,0.3);
}
#streak-wrap.streak-t3 {
  border-color: rgba(255,185,60,0.72);
  box-shadow: 0 0 28px rgba(255,165,55,0.85), 0 0 56px rgba(255,120,30,0.42);
  animation: streakMaxGlow 0.75s ease-in-out infinite !important;
}
@keyframes streakMaxGlow {
  0%,100% { box-shadow: 0 0 28px rgba(255,165,55,0.85), 0 0 56px rgba(255,120,30,0.42); }
  50%     { box-shadow: 0 0 42px rgba(255,210,80,1),    0 0 84px rgba(255,155,45,0.6); }
}

/* ── OPT 9: Milestone moment full-screen flash ───────────────────────────── */
.milestone-moment {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 99999;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(255,210,50,0.07);
  animation: milestoneMomentBg 1.6s ease-out forwards;
}
.milestone-moment-text {
  font-family: Calibri, sans-serif;
  font-size: 60px;
  font-weight: 900;
  color: #ffd700;
  text-align: center;
  text-shadow:
    0 0 20px rgba(255,200,0,1),
    0 0 50px rgba(255,150,0,0.7),
    0 0 90px rgba(255,100,0,0.4);
  animation: milestoneMomentText 1.6s ease-out forwards;
}
@keyframes milestoneMomentBg {
  0%   { opacity: 0; }
  12%  { opacity: 1; }
  68%  { opacity: 1; }
  100% { opacity: 0; }
}
@keyframes milestoneMomentText {
  0%   { transform: translateY(calc(-200px - var(--mm-slot, 0) * 90px)) scale(0.4);  opacity: 0; }
  18%  { transform: translateY(calc(-200px - var(--mm-slot, 0) * 90px)) scale(1.09); opacity: 1; }
  30%  { transform: translateY(calc(-200px - var(--mm-slot, 0) * 90px)) scale(1.0);  opacity: 1; }
  75%  { transform: translateY(calc(-200px - var(--mm-slot, 0) * 90px)) scale(1.0);  opacity: 1; }
  100% { transform: translateY(calc(-200px - var(--mm-slot, 0) * 90px)) scale(1.04); opacity: 0; }
}
.milestone-moment-text .mm-char {
  display: inline-block;
  animation: milestoneMomentWave 1.1s ease-in-out infinite;
}
@keyframes milestoneMomentWave {
  0%,100% { transform: translateY(0); }
  50%     { transform: translateY(-18px); }
}

/* ── OPT 10: Prestige bar XP gain flash ──────────────────────────────────── */
@keyframes prestigeXpGain {
  0%   { filter: brightness(1); }
  25%  { filter: brightness(2.1) saturate(1.4); }
  100% { filter: brightness(1); }
}
#prestige-bar-fill.xp-gain-flash {
  animation: prestigeXpGain 0.38s ease-out;
}

/* ── OPT 11: Upgrade purchase confetti burst ─────────────────────────────── */
.upg-confetti {
  position: fixed;
  pointer-events: none;
  z-index: 99998;
  font-size: 12px;
  transform: translate(-50%, -50%);
  animation: confettiBurst 0.65s ease-out forwards;
}
@keyframes confettiBurst {
  0%   { transform: translate(-50%,-50%) scale(0) rotate(0deg);   opacity: 1; }
  55%  { opacity: 0.9; }
  100% { transform: translate(calc(-50% + var(--dx)), calc(-50% + var(--dy))) scale(1.1) rotate(var(--rot, 0deg)); opacity: 0; }
}

/* ── OPT 12: Currency value scale pop ────────────────────────────────────── */
@keyframes currencyScalePop {
  0%   { transform: scale(1); }
  35%  { transform: scale(1.22); }
  100% { transform: scale(1); }
}
.currency-scale-pop {
  display: inline-block;
  animation: currencyScalePop 0.28s ease-out;
}

/* ── OPT 14: Kiwi idle micro-jiggle ──────────────────────────────────────── */
@keyframes kiwiLeftJiggle {
  0%   { transform: translateY(0px) rotate(0deg); }
  20%  { transform: translateY(calc(-4px * var(--jiggle-scale,1)))  rotate(calc( 2deg   * var(--jiggle-scale,1))); }
  45%  { transform: translateY(calc( 2px * var(--jiggle-scale,1)))  rotate(calc(-1.5deg * var(--jiggle-scale,1))); }
  70%  { transform: translateY(calc(-1.5px * var(--jiggle-scale,1))) rotate(calc( 1deg  * var(--jiggle-scale,1))); }
  88%  { transform: translateY(calc( 0.5px * var(--jiggle-scale,1))) rotate(calc(-0.4deg * var(--jiggle-scale,1))); }
  100% { transform: translateY(0px) rotate(0deg); }
}
@keyframes kiwiRightJiggle {
  0%   { transform: translateY(0px) rotate(0deg); }
  20%  { transform: translateY(calc(-4px * var(--jiggle-scale,1)))  rotate(calc(-2deg   * var(--jiggle-scale,1))); }
  45%  { transform: translateY(calc( 2px * var(--jiggle-scale,1)))  rotate(calc( 1.5deg * var(--jiggle-scale,1))); }
  70%  { transform: translateY(calc(-1.5px * var(--jiggle-scale,1))) rotate(calc(-1deg  * var(--jiggle-scale,1))); }
  88%  { transform: translateY(calc( 0.5px * var(--jiggle-scale,1))) rotate(calc( 0.4deg * var(--jiggle-scale,1))); }
  100% { transform: translateY(0px) rotate(0deg); }
}
#kiwi-left-wrap.kiwi-left-jiggle   { animation: kiwiLeftJiggle  0.5s ease-in-out !important; }
#kiwi-right-wrap.kiwi-right-jiggle { animation: kiwiRightJiggle 0.5s ease-in-out !important; }

/* ── Name easter egg scroll ──────────────────────────────────────────────── */
@keyframes nameEasterEggScroll {
  0%   { transform: translateX(-50%) translateY(110vh); opacity: 0; }
  8%   { opacity: 1; }
  88%  { opacity: 1; }
  100% { transform: translateX(-50%) translateY(-20vh); opacity: 0; }
}
.name-easter-egg {
  position: fixed;
  left: 50%;
  top: 0;
  pointer-events: none;
  z-index: 1000001;
  font-size: 110px;
  line-height: 1;
  white-space: nowrap;
  color: #ffffff;
  text-shadow: 0 0 30px rgba(255,255,255,0.6), 0 0 60px rgba(255,255,255,0.3);
  animation: nameEasterEggScroll 5s ease-in-out forwards;
  user-select: none;
}

/* ═══════════════════════════════════════════════════════════════════════════
   PERF MODE — each visual effect has its own toggle in Options
   ═══════════════════════════════════════════════════════════════════════════
   Body classes (fx-no-*) are added by applyFxFlags() in squeeze.js when the
   matching optSettings flag is set to false. Selector presence means the
   effect is OFF, so each rule disables the effect entirely.
   ─────────────────────────────────────────────────────────────────────────── */

/* Card glow ::before pseudo on cosmetic/theme/size cards. */
body.fx-no-card-hover .cosm-card::before,
body.fx-no-card-hover .theme-card::before,
body.fx-no-card-hover .size-card::before{
  display:none;
}

/* Skill-node hover glows — both the regular hover and the rarity-specific
   golden/silver/bronze/darkgray variants share one toggle. */
body.fx-no-skill-node-hover .skill-node:hover:not(.locked-node),
body.fx-no-skill-node-hover .skill-node.golden:hover:not(.locked-node),
body.fx-no-skill-node-hover .skill-node.silver:hover:not(.locked-node),
body.fx-no-skill-node-hover .skill-node.bronze:hover:not(.locked-node),
body.fx-no-skill-node-hover .skill-node.darkgray:hover:not(.locked-node){
  box-shadow:none;
}

/* Banner button hover glow swap. */
body.fx-no-banner-btn-hover .b-btn:hover,
body.fx-no-banner-btn-hover #cock-fight-btn:hover,
body.fx-no-banner-btn-hover #drug-market-btn:hover,
body.fx-no-banner-btn-hover #stroke-style-btn:hover{
  box-shadow:none;
}

/* Legendary card permanent box-shadow glow. */
body.fx-no-legendary-glow .cosm-card.cosm-rarity-legendary,
body.fx-no-legendary-glow .size-card.cosm-rarity-legendary,
body.fx-no-legendary-glow .style-card.cosm-rarity-legendary{
  box-shadow:none;
}

/* Class / cock-fight pick / move-btn hover lift shadow. */
body.fx-no-class-card-hover .class-card:hover:not(.taken),
body.fx-no-class-card-hover .cf-pick-card:hover,
body.fx-no-class-card-hover .cf-move-btn:hover:not([disabled]){
  box-shadow:none;
}

/* Backdrop-filter blurs (modals, panels, mobile overlays + tab bars). Each
   backdrop-filter forces an offscreen copy + GPU blur + composite every
   frame; turning this flag off drops the blur and leans on the existing
   translucent colors. */
body.fx-no-backdrop-blur .overlay,
body.fx-no-backdrop-blur .ui-unlock-panel,
body.fx-no-backdrop-blur #mid-col,
body.fx-no-backdrop-blur #right-col,
body.fx-no-backdrop-blur #mobile-col-tabs{
  backdrop-filter:none;
  -webkit-backdrop-filter:none;
}
