/* ==========================================================================
   Ape Clicker - styles
   Placeholder art is rendered as .art blocks; swapping in real images means
   giving .art[data-art="key"] a background-image.
   ========================================================================== */

/* ---- Display face -----------------------------------------------------
   Kavoon, self-hosted so every visitor gets it rather than only machines
   with Cooper Black installed. SIL Open Font License; see fonts/OFL.txt.
   Two subsets: latin-ext carries the accented characters. */
@font-face {
	font-family: 'Kavoon';
	font-style: normal; font-weight: 400; font-display: swap;
	src: url('../fonts/kavoon-latin.woff2') format('woff2');
	unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
		U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191,
		U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
	font-family: 'Kavoon';
	font-style: normal; font-weight: 400; font-display: swap;
	src: url('../fonts/kavoon-latin-ext.woff2') format('woff2');
	unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF,
		U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020,
		U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

:root {
	/* Jungle greens, dark enough for bright art to pop, light enough not to
	   feel like a terminal. --ink is for recessed wells (bars, tooltips). */
	--bg: #173a26;
	--bg2: #1d4a31;
	--panel: #245a3c;
	--panel2: #2b6947;
	--line: #3d7f58;
	--ink: #0f2819;
	--text: #f4f8ec;
	--dim: #cfe6c6;
	--gold: #f5c518;
	--green: #9be36f;
	--red: #ef7a66;
	--purple: #b58cf0;
	--topbar: 92px;
	--leftcol: 360px;   /* left column width; the title is centred on it */
	/* Kavoon ships with the game, so the look holds on every machine. Cooper
	   Black (Windows/Office) is the local stand-in, then heavy sans faces.
	   Display is for headings and numbers only - too heavy for prose. */
	--font-display: 'Kavoon', "Cooper Black", "Segoe UI Black", "Arial Black", Impact, sans-serif;
	--font-body: "Trebuchet MS", "Segoe UI", system-ui, -apple-system, sans-serif;
}

/* Every element, not just the page. Buttons and inputs carry their own
   user-agent styles and were still flashing blue on tap. */
* {
	box-sizing: border-box;
	-webkit-tap-highlight-color: transparent;
	-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
/* Touch devices also paint a focus ring after a tap, which lingers on the
   banana. Keyboard users keep theirs through :focus-visible. */
button:focus:not(:focus-visible),
.art:focus:not(:focus-visible),
#bigBanana:focus:not(:focus-visible) { outline: none; }

html, body {
	margin: 0;
	height: 100%;
	/* The whole UI is click-driven; dragging over a building row used to
	   select its text. Inputs opt back in below. */
	user-select: none; -webkit-user-select: none;
	/* Mobile browsers paint a blue box over whatever you tap. On a game whose
	   whole loop is tapping the same banana, that flashes constantly. */
	-webkit-tap-highlight-color: transparent;
	-webkit-touch-callout: none;
	background: var(--bg);
	color: var(--text);
	font: 14px/1.45 var(--font-body);
	overflow: hidden;
}

h2 {
	font-family: var(--font-display); font-size: 15px; font-weight: normal;
	margin: 0 0 10px; letter-spacing: .04em; text-transform: uppercase; color: #d8ecd0;
}

.dim { color: var(--dim); }
.ok { color: var(--green); }
.no { color: var(--red); }

/* ---- Top bar ---------------------------------------------------------- */
#topBar {
	display: flex; align-items: center; gap: 16px;
	height: var(--topbar); padding: 0 18px 0 0;
	/* Light wood: warm against the green below, and the green logo reads on it.
	   This gradient is the fallback; with art it is the tint under the tile. */
	background: linear-gradient(180deg, #dcbc88, #c49a5e);
	border-bottom: 2px solid #8a6436;
	box-shadow: 0 2px 10px rgba(0,0,0,.3);
}
/* The wood plank: a 960px tile repeated small enough to read as grain. */
#topBar.hasWood {
	background-repeat: repeat;
	/* The tile holds ~4 planks, so at 360px one plank roughly spans the bar
	   height: it reads as a board, not as busy grain. */
	background-size: 360px 360px;
	background-position: center;
}
/* Spans the left column, so the title centres over the banana below. */
#kingdomTitle {
	width: var(--leftcol); flex: 0 0 auto;
	display: flex; flex-direction: column; align-items: center; justify-content: center;
	line-height: 1;
}
/* Set in type rather than art: a chunky display face, banana yellow, with a
   dark rim so it holds up over the planks. */
#gameTitle {
	font-family: var(--font-display);
	font-size: 34px; font-weight: normal; letter-spacing: .04em; text-transform: uppercase;
	color: #ffd23f;   /* fallback wherever background-clip:text is unsupported */
	background: linear-gradient(180deg, #fffce8 8%, #ffea70 45%, #ffd52e);
	-webkit-background-clip: text; background-clip: text;
	-webkit-text-fill-color: transparent;
	-webkit-text-stroke: 1.2px rgba(44, 22, 2, .95);
	paint-order: stroke fill;
	text-shadow: 0 3px 0 rgba(40, 20, 2, .45), 0 5px 12px rgba(0, 0, 0, .45);
}
#kingdomName {
	margin-top: 5px; font-size: 11px; letter-spacing: .2em; text-transform: uppercase;
	color: #f2e4c6; text-shadow: 0 1px 3px rgba(0, 0, 0, .75);
}
#tabs { display: flex; gap: 6px; margin-left: auto; }
.tab {
	background: transparent; border: 1px solid transparent; color: var(--text); font-weight: 600;
	text-shadow: 0 1px 2px rgba(0,0,0,.55);
	padding: 8px 14px; border-radius: 8px; cursor: pointer;
	font: normal 15px var(--font-display); letter-spacing: .02em;
}
.tab:hover { color: #fff; background: rgba(0,0,0,.28); }
.tab.active { color: var(--text); background: var(--panel); border-color: #8a6436; }
/* Looks and behaves exactly like a tab - same colour, same hover - it just
   never takes .active, because it leaves the page instead of switching one.
   It is a sibling of #tabs rather than a child, so the -10px cancels the
   topbar's 16px gap and leaves the same 6px the tabs use between themselves.
   Without it, moving the link out of the nav would nudge the PC header. */
#howToPlay {
	display: inline-flex; align-items: center; text-decoration: none;
	margin-left: -10px; white-space: nowrap;
}
#saveState { width: 52px; text-align: right; font-size: 11px; color: #f0e2c6; opacity: 0; transition: opacity .3s; }
#saveState.show { opacity: 1; }

/* ---- Layout ----------------------------------------------------------- */
#game {
	display: grid;
	grid-template-columns: var(--leftcol) 1fr 380px;
	height: calc(100% - var(--topbar));
}
#left, #right { overflow-y: auto; padding: 16px; }
#left { background: rgba(23, 58, 38, .78); border-right: 1px solid var(--line); text-align: center; }
#right { background: rgba(30, 74, 48, .78); border-left: 1px solid var(--line); }
/* Palm tile behind the columns. It sits on body, so it also backs the page
   on narrow screens where the columns stack. */
/* No background-attachment:fixed here: it forces a full-page repaint on
   every frame the hand ring animates. */
body.hasPalm { background-size: 460px 460px; background-repeat: repeat; }

/* The middle never scrolls as a whole. The jungle tab fills it edge to edge;
   the other tabs scroll inside themselves. */
#middle { position: relative; overflow: hidden; padding: 0; }
/* Every panel but the jungle needs an opaque ground: without one the palm
   tile reads straight through the text. */
#middle > .panel { height: 100%; overflow-y: auto; padding: 16px; background: var(--panel); }
#middle > #panel_jungle { position: relative; overflow: hidden; padding: 0; background: none; }

/* ---- Left column ------------------------------------------------------ */
#countStrip {
	position: relative; z-index: 2;
	padding: 10px 14px; border-radius: 14px;
	background: rgba(12, 34, 20, .86);
	border: 1px solid rgba(255, 255, 255, .14);
	box-shadow: 0 6px 18px rgba(0, 0, 0, .25);
}
#bananaCount {
	font-family: var(--font-display); font-size: 28px; font-weight: normal;
	line-height: 1.2; text-shadow: 0 2px 4px rgba(0,0,0,.3);
	display: flex; align-items: baseline; justify-content: center; gap: 8px;
}
/* The digits sit in a fixed-width, right-aligned column so the scale word
   beside them never shuffles as the number ticks. */
#bananaCount .num { min-width: 6.4ch; text-align: right; font-variant-numeric: tabular-nums; }
#bananaCount .scale { font-size: 19px; color: var(--dim); }
#bananaCount .tail { display: none; }
/* "0" on a fresh save has no scale word: centre it instead of parking it at
   the right of a column sized for "999.99". */
#bananaCount .scale:empty, #bananaPs .scale:empty { display: none; }
#bananaCount.noScale .num { min-width: 0; text-align: center; }
#bananaPs.noScale .num { min-width: 0; text-align: right; }
#bananaPs .num { min-width: 6.4ch; text-align: right; display: inline-block; font-variant-numeric: tabular-nums; }
#bananaPs .scale:not(:empty) { margin-left: 4px; }
#bananaPs .tail { margin-left: 4px; }
#bananaPs { color: var(--dim); font-size: 13px; margin-top: 2px; }

/* The stage is the positioning context for the hand ring; the ring sits
   behind the banana so hands appear to reach in from underneath it. */
#bananaStage {
	position: relative; width: 240px; height: 240px;
	/* The ring reaches ~25px past the stage edge. The count strip above is
	   opaque and stacked over it, so only a little clearance is needed. */
	margin: 14px auto 26px; display: block;
}
#handRing { position: absolute; inset: 0; pointer-events: none; z-index: 0; }
.handSlot {
	position: absolute; left: 50%; top: 50%; width: 0; height: 0;
	/* transform (rotate, push out, turn to face the banana) is set in render.js */
}
.handSprite {
	position: absolute; left: 50%; top: 50%;
	/* centring margins are set inline, since the sprite scales with the stage */
	animation: handGrab 4s ease-in-out infinite;
	transform-origin: center;
}
/* The grab: a small lurch toward the banana, most of the cycle spent still.
   Each slot is turned 180deg so the finger faces the banana, which makes
   "toward the banana" negative Y in the sprite's own frame. */
@keyframes handGrab {
	0%, 86%, 100% { transform: translateY(0); }
	91%           { transform: translateY(-7px); }
	96%           { transform: translateY(0); }
}

#bigBanana {
	cursor: pointer; user-select: none;
	-webkit-tap-highlight-color: transparent;
	position: absolute; inset: 0; z-index: 1;
	display: flex; align-items: center; justify-content: center;
}
.bigBananaArt {
	border-radius: 50%;
	transform-origin: center 60%;
	transition: filter .12s ease;
	will-change: transform;
	filter: drop-shadow(0 6px 10px rgba(0,0,0,.3));
}
#bigBanana:hover .bigBananaArt { filter: drop-shadow(0 6px 10px rgba(0,0,0,.3)) brightness(1.06); }

/* The "smashed" frame is this animation, not a second drawing: a real
   squash-and-stretch - wide+flat on impact, a slight tall overshoot on the
   way back, then settle. Reads as weight without needing extra art. */
#bigBanana.pressed .bigBananaArt { animation: squash .22s ease-out; }
@keyframes squash {
	0%   { transform: scale(1, 1); }
	28%  { transform: scale(1.11, 0.87); }
	55%  { transform: scale(0.95, 1.05); }
	78%  { transform: scale(1.02, 0.985); }
	100% { transform: scale(1, 1); }
}
/* Dense rings drop the per-sprite animation: see renderHandRing. */
#handRing.dense .handSprite { animation: none; }

@media (prefers-reduced-motion: reduce) {
	#bigBanana.pressed .bigBananaArt { animation-duration: .01s; }
	.handSprite { animation: none; }
}

/* ---- Art placeholders ------------------------------------------------- */
.art {
	display: flex; align-items: center; justify-content: center;
	border-radius: 8px; line-height: 1;
	text-shadow: 0 1px 2px rgba(0,0,0,.35);
	flex: 0 0 auto;
	/* contain, not cover: an asset that isn't exactly square letterboxes
	   inside its box instead of being cropped. Ratio slop is harmless. */
	background-size: contain;
	background-repeat: no-repeat;
	background-position: center;
	image-rendering: auto;
}
/* Real art supplies its own shape - drop the placeholder plate. */
.art.hasArt { background-color: transparent; border-radius: 0; }

/* Composites: an icon built by stacking copies of another asset (see
   COMPOSITES in js/data/art.js). Each layer fills the box and is then
   offset/rotated/scaled into place. */
.art.composite { position: relative; overflow: visible; }
.artLayer {
	position: absolute; inset: 0;
	background-size: contain; background-repeat: no-repeat; background-position: center;
}

/* ---- Sap nuggets ------------------------------------------------------ */
#lumpWrap { margin-top: 18px; padding: 10px; background: var(--panel); border-radius: 10px; }
.lumpTop { display: flex; align-items: center; gap: 8px; justify-content: center; font-size: 12px; }
.lumpNode { font-size: 22px; filter: grayscale(1) brightness(.6); }
.lumpNode.phase1 { filter: grayscale(.5); }
.lumpNode.phase2 { filter: none; animation: pulse 1.6s infinite; }
@keyframes pulse { 50% { transform: scale(1.15); } }
.lumpBar { height: 5px; background: var(--ink); border-radius: 3px; margin: 8px 0; overflow: hidden; }
.lumpBar i { display: block; height: 100%; background: var(--gold); }

/* ---- Ascension box ---------------------------------------------------- */
#ascendBox { margin-top: 18px; padding: 10px; background: var(--panel); border-radius: 10px; font-size: 12px; }
.ascendRow { display: flex; justify-content: space-between; padding: 2px 0; }
.ascendRow span { color: var(--dim); }
#ascendBtn, .smallBtn {
	margin-top: 8px; width: 100%; padding: 7px 10px; border-radius: 8px; cursor: pointer;
	background: var(--panel2); border: 1px solid var(--line); color: var(--text); font: inherit;
}
#ascendBtn:hover, .smallBtn:hover { background: var(--line); }
#ascendBtn.ready { background: var(--purple); border-color: var(--purple); color: #fff; font-weight: 600; }
.smallBtn.danger:hover { background: var(--red); border-color: var(--red); color: #fff; }

/* ---- Buffs ------------------------------------------------------------ */
#buffs { margin-top: 16px; display: flex; flex-direction: column; gap: 6px; }
.buff { background: var(--panel); border-radius: 8px; padding: 6px 8px; font-size: 11px; text-align: left; }
.buffIcon { display: inline-block; width: 14px; height: 14px; vertical-align: -2px; margin-right: 5px; }
.buff .buffTime { float: right; color: var(--dim); }
.buffBar { height: 3px; background: var(--ink); border-radius: 2px; margin-top: 5px; overflow: hidden; }
.buffBar i { display: block; height: 100%; background: var(--gold); }

/* ---- Jungle Juice ------------------------------------------------------ */
/* The hand ring spills past its stage, and the stage's absolutely positioned
   ring would otherwise paint over the panels below it. */
#juiceWrap, #lumpWrap, #ascendBox, #buffs { position: relative; z-index: 2; }
#juiceWrap { margin-top: 16px; padding: 9px 10px; background: var(--panel); border-radius: 10px; }
.juiceLabel {
	display: flex; align-items: center; gap: 6px;
	font-size: 12px; color: var(--dim); margin-bottom: 6px;
}
.juiceLabel b { color: var(--text); font-size: 13px; margin-left: auto; }
.juiceIcon { border-radius: 5px; }
.juiceBar { height: 8px; background: var(--ink); border-radius: 4px; overflow: hidden; }
.juiceBar i {
	display: block; height: 100%; border-radius: 4px;
	background: linear-gradient(90deg, #f0e6c8, #fff8e2);
	transition: width .3s ease;
}
/* Each full lap deepens the colour, so progress stays visible past 100%. */
#juiceWrap[data-laps="1"] .juiceBar i { background: linear-gradient(90deg, #ffe9a8, #fff3cf); }
#juiceWrap[data-laps="2"] .juiceBar i { background: linear-gradient(90deg, #ffd76b, #ffe9a8); }
#juiceWrap[data-laps="3"] .juiceBar i { background: linear-gradient(90deg, #f5c518, #ffd76b); }
#juiceWrap[data-laps="4"] .juiceBar i { background: linear-gradient(90deg, #e8973a, #f5c518); }
#juiceWrap[data-laps="5"] .juiceBar i { background: linear-gradient(90deg, #d8624f, #e8973a); }
#juiceWrap[data-laps="6"] .juiceBar i { background: linear-gradient(90deg, #a06fd8, #d8624f); }

.volLabel { display: flex; align-items: center; gap: 8px; font-size: 12px; }
.volLabel input[type=range] { width: 120px; accent-color: var(--gold); }

/* ---- Middle: the jungle ------------------------------------------------ */
/* The jungle fills the whole middle column; golden bananas and leeches sit
   directly on the background art. */
#jungleField {
	position: absolute; inset: 0;
	background:
		radial-gradient(circle at 30% 20%, rgba(155,227,111,.18), transparent 55%),
		radial-gradient(circle at 70% 75%, rgba(245,197,24,.10), transparent 55%),
		var(--bg);
}
/* The background is the one asset that should crop rather than letterbox. */
#jungleField.hasArt {
	background-size: cover; background-position: center; background-repeat: no-repeat;
}
/* Both layers span the whole field; the leech layer sits on top of the golden
   one. Let clicks fall through the empty layer to the sprites themselves,
   or the leech layer swallows every click on a golden banana. */
/* Above the pool panel (z-index 6): the panel now sits in the middle of the
   field, and a golden banana behind it would be invisible and unclickable. */
#goldenLayer { position: absolute; inset: 0; pointer-events: none; z-index: 8; }
#leechLayer { position: absolute; inset: 0; pointer-events: none; z-index: 7; }
#goldenLayer > *, #leechLayer > * { pointer-events: auto; }
/* The prize banana lives here, above both, and is never swept by the
   per-frame golden banana render. */
#claimLayer { position: absolute; inset: 0; pointer-events: none; z-index: 12; }
#claimLayer > * { pointer-events: auto; }
.goldenBanana, .leech { position: absolute; cursor: pointer; transform: translate(-50%, -50%); }
.goldenBanana { filter: drop-shadow(0 0 14px rgba(255,220,60,.9)); animation: bob 2.4s ease-in-out infinite; }
/* Rotten bananas share the golden banana's class for layout, but must not
   share its gold glow - they read as a different, hostile thing. */
.goldenBanana.wrath { filter: drop-shadow(0 0 13px rgba(216,79,122,.85)); }

/* Leech art is dark by design, so it needs a rim to separate from the
   background. Shiny gets a brighter version of the same glow. */
.leech { filter: drop-shadow(0 0 7px rgba(200,160,255,.7)); }
.leech.shiny { filter: drop-shadow(0 0 11px rgba(210,170,255,1)); }
/* Phase 1 = crawling in, phase 2 = latched on and feeding. The difference is
   opacity plus a slow drift, not separate art. */
.leech.approaching { animation: leechCrawl 2.2s ease-in-out infinite; }
@keyframes leechCrawl {
	50% { transform: translate(-50%, -54%) scale(.94); }
}
@keyframes bob { 50% { transform: translate(-50%, -58%) rotate(6deg); } }

/* ---- Prize pool panel: floats over the jungle, bottom left -------------
   No backdrop-filter and no drop-shadows on children: this panel updates
   every second, and filtered elements are re-rendered on every repaint. */
#poolPanel {
	position: absolute; z-index: 6;
	/* Lower half of the field: spawns get the space above it, notifications
	   the strip below it. */
	left: 50%; bottom: 96px; transform: translateX(-50%);
	width: min(340px, calc(100% - 32px));
	max-height: calc(100% - 220px); overflow-y: auto;
	padding: 12px 14px; border-radius: 14px;
	background: rgba(12, 34, 20, .92);
	border: 1px solid rgba(255, 255, 255, .16);
	box-shadow: 0 8px 22px rgba(0, 0, 0, .45);
	font-size: 13px;
}
.poolHead { display: flex; align-items: baseline; gap: 8px; margin-bottom: 6px; }
.poolTitle {
	font-family: var(--font-display); font-size: 15px;
	text-transform: uppercase; letter-spacing: .04em; color: var(--gold);
}
.poolNet { margin-left: auto; font-size: 10px; color: var(--dim); text-transform: uppercase; letter-spacing: .1em; }
.poolSize { font-family: var(--font-display); font-size: 24px; line-height: 1.1; }
.poolSize span { font-size: 13px; color: var(--dim); }
.poolBarWrap { height: 7px; background: var(--ink); border-radius: 4px; overflow: hidden; margin: 8px 0 5px; }
.poolBarWrap i { display: block; height: 100%; width: 0; background: linear-gradient(90deg, #e8973a, var(--gold)); }
.poolRow { display: flex; justify-content: space-between; gap: 8px; font-size: 12px; padding: 1px 0; }
.poolWhen {
	margin: 8px 0; padding: 6px 8px; border-radius: 8px;
	background: rgba(255, 255, 255, .06); text-align: center; font-size: 12px;
}
.poolWhen.hot { color: var(--gold); background: rgba(245, 197, 24, .12); }
.poolWhen.win { color: #2a2000; background: var(--gold); font-weight: 700; }
.poolMine { border-top: 1px solid var(--line); padding-top: 7px; margin-bottom: 9px; }
.poolMine b { font-variant-numeric: tabular-nums; }
.poolBuy { display: flex; gap: 6px; }
.poolBuy input {
	flex: 1; min-width: 0; padding: 7px 9px; border-radius: 8px; font: inherit;
	background: var(--ink); border: 1px solid var(--line); color: var(--text);
}
.poolBuy input:focus { outline: none; border-color: var(--gold); }
.poolBuy .smallBtn { width: auto; margin-top: 0; padding: 7px 14px; }
#poolConnect { margin-top: 0; }
/* Wallet chooser: only shown when more than one is installed. */
.walletPick { display: flex; flex-direction: column; gap: 5px; margin-bottom: 7px; }
.pickLabel { font-size: 11px; color: var(--dim); text-transform: uppercase; letter-spacing: .1em; }
.smallBtn.walletBtn {
	margin-top: 0; display: flex; align-items: center; gap: 8px;
	justify-content: flex-start; text-align: left;
}
.smallBtn.walletBtn img { width: 18px; height: 18px; border-radius: 4px; }
/* The deep-link versions are anchors, not buttons. */
a.smallBtn.walletBtn { text-decoration: none; color: var(--text); }
a.smallBtn.walletBtn:hover { background: var(--line); }
.pickNote { font-size: 11px; color: var(--dim); line-height: 1.4; margin-top: 2px; }
.linkBtn {
	background: none; border: 0; padding: 0; cursor: pointer;
	color: var(--dim); font: inherit; font-size: 11px; text-decoration: underline;
}
.linkBtn:hover { color: var(--gold); }
.poolStatus { margin-top: 7px; font-size: 11px; line-height: 1.4; color: var(--dim); min-height: 1em; }
.poolStatus.ok { color: var(--green); }
.poolStatus.no { color: var(--red); }
.poolWinner { margin-top: 6px; font-size: 11px; color: var(--dim); }

/* ---- The golden banana you win the pool with ---------------------------
   Centred in the jungle, above everything, impossible to miss. */
.claimBanana {
	/* High enough that the countdown underneath clears the prize panel, which
	   sits in the lower half of the field. */
	position: absolute; left: 50%; top: 22%;
	transform: translate(-50%, -50%);
	pointer-events: auto; cursor: pointer; z-index: 20;
	display: flex; flex-direction: column; align-items: center; gap: 4px;
	animation: claimBob 1.4s ease-in-out infinite;
}
/* The glow is a halo painted behind the banana, not a filter on it. A
   drop-shadow here failed to rasterise at all in headless rendering, taking
   the banana with it, and filters are what made the game lag earlier. */
.claimBanana::before {
	content: ''; position: absolute; left: 50%; top: 60px;
	width: 250px; height: 250px; margin: -125px 0 0 -125px;
	border-radius: 50%; pointer-events: none; z-index: -1;
	background: radial-gradient(circle,
		rgba(255, 226, 110, .70) 0%,
		rgba(255, 200, 40, .38) 38%,
		rgba(255, 190, 30, 0) 70%);
}
.claimBanana:hover::before { background: radial-gradient(circle,
	rgba(255, 240, 160, .85) 0%, rgba(255, 210, 60, .45) 40%, rgba(255,190,30,0) 72%); }
.claimBananaTime {
	font-family: var(--font-display); font-size: 21px; color: var(--gold);
	letter-spacing: .06em; white-space: nowrap;
	padding: 3px 12px; border-radius: 10px;
	background: rgba(12, 34, 20, .82);
	text-shadow: 0 2px 0 rgba(40, 20, 2, .6);
	font-variant-numeric: tabular-nums;
}
.claimBanana.urgent { animation: claimBob .6s ease-in-out infinite; }
.claimBanana.urgent .claimBananaTime { color: var(--red); }
@keyframes claimBob {
	50% { transform: translate(-50%, -58%) scale(1.06) rotate(-3deg); }
}
@media (prefers-reduced-motion: reduce) { .claimBanana { animation: none; } }

/* ---- News ticker: one line, centred, floating over the jungle ---------- */
#ticker {
	position: absolute; z-index: 5;
	top: 16px; left: 50%; transform: translateX(-50%);
	width: min(780px, calc(100% - 32px));
	padding: 14px 22px; border-radius: 14px; cursor: pointer;
	background: rgba(12, 34, 20, .86);
	border: 1px solid rgba(255, 255, 255, .14);
	box-shadow: 0 6px 18px rgba(0, 0, 0, .25);
	text-align: center; font-size: 18px; line-height: 1.45;
}
#ticker:hover { border-color: rgba(245, 197, 24, .55); }
#tickerText.fresh { animation: tickerIn .6s ease-out; }
@keyframes tickerIn {
	from { opacity: 0; transform: translateY(6px); }
	to   { opacity: 1; transform: none; }
}
#tickerText q { font-style: italic; color: var(--text); quotes: '"' '"'; }
#tickerText sig {
	display: block; margin-top: 4px; font-size: 13px;
	color: var(--dim); font-style: normal;
}

/* ---- Other tabs ------------------------------------------------------- */
.statRow { display: flex; justify-content: space-between; padding: 4px 0; border-bottom: 1px solid var(--line); font-size: 13px; }
.statRow span { color: var(--dim); }
#statsBody, #statsBuildings { margin-bottom: 20px; }

#ownedUpgrades { display: flex; flex-wrap: wrap; gap: 4px; margin-bottom: 20px; }
.ownedUpgrade { cursor: help; opacity: .9; transition: opacity .12s, transform .12s; }
.ownedUpgrade:hover { opacity: 1; transform: translateY(-2px); }
#ownedCount { font-weight: 400; text-transform: none; letter-spacing: 0; }

#achievementsBody { display: flex; flex-wrap: wrap; gap: 5px; margin-top: 10px; }
.achievement {
	width: 34px; height: 34px; border-radius: 6px; display: flex;
	align-items: center; justify-content: center; font-size: 16px;
	background: var(--ink); color: #5f8a6c; cursor: help;
}
.achievement.owned { background: var(--gold); color: #3a2c00; }
/* Real badge art: scale the whole image into the 34px tile. Without this the
   browser draws it at its natural size and the tile shows only a corner. */
.achievement.hasArt {
	background-color: transparent;
	background-size: contain; background-repeat: no-repeat; background-position: center;
}

#ascensionTree { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 12px; }
.heavenly {
	width: 110px; padding: 8px; border-radius: 10px; text-align: center; cursor: pointer;
	background: var(--panel); border: 1px solid var(--line);
}
.heavenly .art { margin: 0 auto 6px; }
.heavenlyName { font-size: 11px; line-height: 1.25; min-height: 28px; }
.heavenlyPrice { font-size: 11px; color: var(--gold); margin-top: 4px; }
.heavenly.owned { border-color: var(--purple); background: rgba(181, 140, 240, .2); }
.heavenly.owned .heavenlyPrice { color: var(--purple); }
.heavenly.cantAfford { opacity: .55; }
.heavenly.locked { opacity: .3; cursor: help; }

.optRow { margin-bottom: 12px; display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }
.optRow label { color: var(--dim); }
.optRow input[type=text] {
	background: var(--panel); border: 1px solid var(--line); color: var(--text);
	padding: 6px 8px; border-radius: 6px; font: inherit;
}
.optRow .smallBtn { width: auto; margin-top: 0; }
/* Anything the player needs to read out or paste into stays selectable. */
input, textarea, #saveBox { user-select: text; -webkit-user-select: text; }
#saveBox {
	width: 100%; height: 110px; background: var(--ink); color: var(--dim);
	border: 1px solid var(--line); border-radius: 6px; padding: 8px;
	font-family: ui-monospace, Consolas, monospace; font-size: 11px; resize: vertical;
}

/* ---- Store ------------------------------------------------------------ */
.storeHead { margin-bottom: 8px; }
#upgrades { display: flex; flex-wrap: wrap; gap: 4px; min-height: 20px; }
.upgrade { cursor: pointer; border-radius: 8px; transition: transform .08s; }
.upgrade:hover { transform: translateY(-2px); }
/* Opacity, not filter: a filtered element is re-rendered on every repaint,
   and these sit in lists that update each frame. */
.upgrade.cantAfford { opacity: .42; }
.upgrade.tech .art { box-shadow: inset 0 0 0 3px var(--green); }

#buyControls { display: flex; gap: 6px; margin: 14px 0 10px; }
.modeGroup { display: flex; gap: 2px; }
.modeBtn {
	background: var(--panel2); border: 1px solid var(--line); color: var(--dim);
	padding: 4px 9px; border-radius: 6px; cursor: pointer; font: inherit; font-size: 12px;
}
.modeBtn.active { background: var(--gold); border-color: var(--gold); color: #3a2c00; font-weight: 600; }

.building {
	display: flex; align-items: center; gap: 10px; padding: 8px;
	border-radius: 10px; cursor: pointer; margin-bottom: 4px;
	background: var(--panel2); border: 1px solid transparent;
}
.building:hover { border-color: var(--green); }
.building.locked { display: none; }
.building.cantAfford { opacity: .5; }
.building.flash { animation: flash .3s; }
@keyframes flash { 0% { background: var(--gold); } }
.buildingInfo { flex: 1; min-width: 0; }
.buildingName { font-family: var(--font-display); font-weight: normal; font-size: 15px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.buildingPrice { font-size: 12px; }
.buildingPrice.ok { color: var(--green); }
.buildingPrice.no { color: var(--red); }
.buildingPop {
	display: flex; align-items: flex-end; gap: 1px;
	height: 14px; margin-top: 2px; overflow: hidden;
}
.popDot { opacity: .8; }
/* When the count is past what we draw, fade the tail so it reads as "more". */
.buildingPop.capped {
	-webkit-mask-image: linear-gradient(90deg, #000 78%, transparent);
	mask-image: linear-gradient(90deg, #000 78%, transparent);
}
.buildingRight { text-align: right; }
.buildingAmount { font-family: var(--font-display); font-size: 20px; font-weight: normal; color: var(--dim); line-height: 1; }
.buildingLevel { font-size: 10px; color: var(--gold); }

/* ---- Modal ------------------------------------------------------------ */
.modalBack {
	position: fixed; inset: 0; z-index: 800;
	background: rgba(6, 20, 12, .72);
	display: flex; align-items: center; justify-content: center;
	padding: 24px; animation: modalFade .15s ease-out;
}
@keyframes modalFade { from { opacity: 0; } }
.modal {
	width: 420px; max-width: 100%;
	background: var(--bg2); border: 1px solid var(--line);
	border-radius: 12px; padding: 20px;
	box-shadow: 0 20px 60px rgba(0,0,0,.6);
	animation: modalRise .18s ease-out;
}
@keyframes modalRise { from { transform: translateY(10px); opacity: 0; } }
.modalTitle { font-family: var(--font-display); font-size: 18px; font-weight: normal; color: var(--gold); margin-bottom: 10px; }
.modalBody { font-size: 13px; line-height: 1.55; }
.modalBody p { margin: 0 0 9px; }
.modalButtons { display: flex; gap: 8px; margin-top: 16px; }
.modalButtons .smallBtn { margin-top: 0; }
.smallBtn.primary { background: var(--purple); border-color: var(--purple); color: #fff; font-weight: 600; }
.smallBtn.primary:hover { filter: brightness(1.12); background: var(--purple); }
.smallBtn.danger { border-color: var(--red); color: var(--red); }
.smallBtn.danger:hover { background: var(--red); border-color: var(--red); color: #fff; }

/* ---- Tooltip ---------------------------------------------------------- */
.tooltip {
	position: fixed; z-index: 500; display: none; width: 300px;
	background: var(--ink); border: 1px solid var(--line); border-radius: 10px;
	padding: 12px; font-size: 12px; box-shadow: 0 8px 26px rgba(0,0,0,.5);
	pointer-events: none;
}
.tipHead { font-family: var(--font-display); font-size: 15px; font-weight: normal; color: var(--gold); }
.tipTier { font-size: 11px; text-transform: uppercase; letter-spacing: .06em; }
.tipPrice { margin: 4px 0 8px; }
.tipDesc { line-height: 1.5; }
.tipStat { margin-top: 5px; color: var(--dim); }
.tipQuote { margin-top: 8px; font-style: italic; color: #8fb392; border-top: 1px solid var(--line); padding-top: 6px; }
.line { height: 1px; background: var(--line); margin: 8px 0; }

/* ---- Effects ---------------------------------------------------------- */
.particle {
	position: fixed; pointer-events: none; z-index: 600;
	font-weight: 700; color: var(--text); text-shadow: 0 2px 4px #000;
	animation: rise 1.1s ease-out forwards;
}
.particle.golden { color: var(--gold); font-size: 20px; }
@keyframes rise {
	0% { opacity: 1; transform: translate(-50%, 0); }
	100% { opacity: 0; transform: translate(-50%, -70px); }
}

/* Bottom centre of the jungle column. On the right they covered the store,
   which is exactly where the player is clicking. */
#toasts {
	position: absolute; z-index: 700;
	left: 50%; transform: translateX(-50%); bottom: 18px;
	display: flex; flex-direction: column; align-items: center; gap: 8px;
	width: min(420px, calc(100% - 32px));
	pointer-events: none;
}
.toast {
	width: 100%; text-align: center;
	background: rgba(12, 34, 20, .88); border: 1px solid rgba(255,255,255,.16);
	border-top: 3px solid var(--gold);
	border-radius: 10px; padding: 10px 14px; font-size: 13px; line-height: 1.45;
	box-shadow: 0 8px 22px rgba(0,0,0,.45); transition: opacity .5s, transform .5s;
}
.toast.out { opacity: 0; transform: translateY(12px); }

/* ---- Narrow screens ---------------------------------------------------
   The hand ring needs roughly 320px of clear width around the banana, so the
   stage shrinks with the column rather than overflowing it. */
@media (max-width: 1240px) {
	:root { --leftcol: 320px; }
	#game { grid-template-columns: var(--leftcol) 1fr 340px; }
	#bananaStage { width: 210px; height: 210px; }
	.bigBananaArt { width: 210px !important; height: 210px !important; }
	#ticker { font-size: 16px; }
}
@media (max-width: 1040px) {
	:root { --leftcol: 280px; }
	#game { grid-template-columns: var(--leftcol) 1fr 300px; }
	#bananaStage { width: 180px; height: 180px; }
	.bigBananaArt { width: 180px !important; height: 180px !important; }
	#right { padding: 12px; }
}
@media (max-width: 880px) {
	:root { --topbar: auto; }
	html, body { overflow: auto; }
	#game { grid-template-columns: 1fr; height: auto; }
	#left, #right { border: none; }
	#left { border-bottom: 1px solid var(--line); }
	#middle > #panel_jungle { height: 520px; }
	#poolPanel { width: calc(100% - 24px); bottom: 76px; max-height: 260px; }
	#bananaStage { width: 240px; height: 240px; }
	.bigBananaArt { width: 240px !important; height: 240px !important; }
	#topBar { flex-wrap: wrap; height: auto; padding: 8px 12px; gap: 8px; }
	#kingdomTitle { width: auto; align-items: flex-start; }
	#gameTitle { font-size: 26px; }
	#tabs { margin-left: 0; width: 100%; overflow-x: auto; }
	/* The header wraps here and #tabs takes a whole row. Flex order lifts the
	   how-to link up beside the title so it is always on screen, instead of
	   sitting below the tab strip or scrolling off the end of it. */
	#kingdomTitle { order: -2; }
	#howToPlay { order: -1; margin-left: auto; }
	#toasts { left: 12px; right: 12px; width: auto; }

	/* ---- phone layout ------------------------------------------------
	   On a phone the three columns become one long page, and in source
	   order the store ends up last - so the core loop, buying things, is
	   below everything else. Flex order puts it directly under the banana,
	   with the jungle and the prize pool after it. */
	#game { display: flex; flex-direction: column; }
	#left   { order: 1; }
	#right  { order: 2; }
	#middle { order: 3; }

	/* All five tabs have to fit; they were running off the right edge. */
	#tabs { gap: 2px; }
	.tab { padding: 7px 9px; font-size: 13px; }

	/* The banana was taking half the screen before anything else showed. */
	#bananaStage { width: 150px; height: 150px; margin: 8px auto 14px; }
	.bigBananaArt { width: 150px !important; height: 150px !important; }
	#bananaCount { font-size: 24px; }
	#countStrip { padding: 7px 12px; }

	/* The hand ring is laid out from the stage size, so it follows along. */

	/* Squeeze the side panels: they are secondary on a phone. */
	#left, #right { padding: 10px; }
	#juiceWrap, #lumpWrap, #ascendBox { margin-top: 10px; padding: 8px; }
	#ascendBox { font-size: 11px; }

	/* The jungle no longer needs to be tall, since the pool panel is the
	   thing worth seeing and it sits inside it. */
	#middle > #panel_jungle { height: 420px; }
	#poolPanel { bottom: 12px; max-height: calc(100% - 90px); }
	#ticker { font-size: 14px; padding: 9px 14px; top: 10px; }
	.claimBanana { top: 26%; }

	/* 392 badges in a left-aligned grid left a ragged edge and filled the
	   screen. Centred, smaller, and capped so the list scrolls inside itself
	   instead of pushing everything else off the page. */
	#achievementsBody {
		justify-content: center; gap: 4px;
		max-height: 46vh; overflow-y: auto;
	}
	.achievement { width: 27px; height: 27px; font-size: 13px; border-radius: 5px; }
	#ownedUpgrades { justify-content: center; }
	#ascensionTree { justify-content: center; }
}

/* Very narrow phones: the store rows and tabs need a little more room. */
@media (max-width: 400px) {
	.tab { padding: 6px 7px; font-size: 12px; }
	#gameTitle { font-size: 22px; }
	.buildingName { font-size: 14px; }
	.buildingAmount { font-size: 17px; }
	#bananaStage { width: 132px; height: 132px; }
	.bigBananaArt { width: 132px !important; height: 132px !important; }
	.achievement { width: 24px; height: 24px; font-size: 11px; }
}
