/* ───────── Bobo's City – styles ───────── */
/* Sky + sea colours for each time of day. Used by the island drawing AND the page
   background, so inside and outside the game always match. */
@property --sky-top-c { syntax: '<color>'; inherits: true; initial-value: #5ec8f5; }
@property --sky-bot-c { syntax: '<color>'; inherits: true; initial-value: #c4f0ff; }
@property --sea-top-c { syntax: '<color>'; inherits: true; initial-value: #2bb3e0; }
@property --sea-bot-c { syntax: '<color>'; inherits: true; initial-value: #1279b8; }
@property --cloud-c { syntax: '<color>'; inherits: true; initial-value: #ffffff; }
@property --sea-deep-c { syntax: '<color>'; inherits: true; initial-value: #0b3a66; }
:root {
  --sky-top-c: #5ec8f5; --sky-bot-c: #c4f0ff; --sea-top-c: #2bb3e0; --sea-bot-c: #1279b8; --cloud-c: #ffffff; --sea-deep-c: #0b3a66;
}
/* ── Full-screen layers as plain HTML: the phone's GPU fades/moves these almost for free ── */
html, body { -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: transparent; }
.backdrop { position: fixed; inset: 0; z-index: -1; pointer-events: none; }
.bd, .bd-haze, .bd-gloom, .bd-cover { position: absolute; inset: 0; opacity: 0; transition: opacity 2s ease-in-out; }
/* sky + sea for each time of day; the horizon lines up with the island drawing (app.js: syncHorizon) */
.bd-morning { background: linear-gradient(#7cc8ef calc(var(--sky-top, 0%) + var(--bd-shift, 0px)), #ffe3c4 calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #45b4dc calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #1a7fb6 calc(var(--deep, 80%) + var(--bd-shift, 0px)), #0e406e calc(var(--abyss, 100%) + var(--bd-shift, 0px))); }
.bd-day     { background: linear-gradient(#5ec8f5 calc(var(--sky-top, 0%) + var(--bd-shift, 0px)), #c4f0ff calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #2bb3e0 calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #1279b8 calc(var(--deep, 80%) + var(--bd-shift, 0px)), #0b3a66 calc(var(--abyss, 100%) + var(--bd-shift, 0px))); }
.bd-evening { background: linear-gradient(#5b5fb0 calc(var(--sky-top, 0%) + var(--bd-shift, 0px)), #ffae80 calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #3f86b8 calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #1b4f86 calc(var(--deep, 80%) + var(--bd-shift, 0px)), #0c2a52 calc(var(--abyss, 100%) + var(--bd-shift, 0px))); }
.bd-night   { background: linear-gradient(#142a5e calc(var(--sky-top, 0%) + var(--bd-shift, 0px)), #3e5aa6 calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #2a5f95 calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #133a6c calc(var(--deep, 80%) + var(--bd-shift, 0px)), #071a36 calc(var(--abyss, 100%) + var(--bd-shift, 0px))); }
.bd-eclipse { background: linear-gradient(#1c2850 calc(var(--sky-top, 0%) + var(--bd-shift, 0px)), #4a5590 calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #2a5480 calc(var(--horizon, 58%) + var(--bd-shift, 0px)), #133a6c calc(var(--deep, 80%) + var(--bd-shift, 0px)), #071a36 calc(var(--abyss, 100%) + var(--bd-shift, 0px))); }
:root[data-time="morning"] .bd-morning, :root[data-time="day"] .bd-day, :root:not([data-time]) .bd-day,
:root[data-time="evening"] .bd-evening, :root[data-time="night"] .bd-night, :root[data-time="eclipse"] .bd-eclipse { opacity: 1; }
.bd-stars { position: absolute; left: 0; right: 0; top: var(--bd-shift, 0px); height: var(--horizon, 58%); }
.bd-stars svg { display: block; }
.bd-haze { background: linear-gradient(#9c8f86 calc(var(--sky-top, 0%) + var(--bd-shift, 0px)), #e9b98a calc(var(--horizon, 58%) + var(--bd-shift, 0px)), transparent calc(var(--horizon, 58%) + var(--bd-shift, 0px))); }
.bd-gloom { background: #4b5563; }
.raining .bd-gloom { opacity: 0.3; }
/* rain / storm: the whole sky is one cloud cover with a soft bumpy edge */
.bd-cover { bottom: auto; height: calc(var(--cloud-base, 30%) + var(--bd-shift, 0px)); }
/* the bumpy bottom edge is sized in city units, so it never reaches past the horizon on small phones */
.bd-cover::after {
  content: ""; position: absolute; left: 0; right: 0; top: 100%; height: calc(44 * var(--u, 1px));
  background-size: calc(80 * var(--u, 1px)) calc(44 * var(--u, 1px)); background-repeat: repeat-x;
}
.bd-rain { background: linear-gradient(#7c8591, #9aa3ae); }
.bd-rain::after { background-image: radial-gradient(circle at 50% 0, #9aa3ae calc(36 * var(--u, 1px)), transparent calc(37 * var(--u, 1px))); }
.bd-storm { background: linear-gradient(#2f3540, #4a525f); height: calc(var(--cloud-base, 30%) + var(--bd-shift, 0px) + 10 * var(--u, 1px)); }
.bd-storm::after { background-image: radial-gradient(circle at 50% 0, #4a525f calc(36 * var(--u, 1px)), transparent calc(37 * var(--u, 1px))); }
.raining .bd-rain, .storming .bd-storm { opacity: 1; }
/* The sun and moon are HTML too, so moving them never redraws the island.
   Positions are in island units (see app.js: --u, --ox, --oy). */
.sun-html, .moon-html { position: absolute; width: 0; height: 0; }
.sun-html > *, .moon-html > * { position: absolute; border-radius: 50%; }
.sun-html {
  left: calc(var(--ox, 0px) + 680 * var(--u, 1px)); top: calc(var(--oy, 0px) + 80 * var(--u, 1px));
  transform: translate(calc(-160 * var(--u, 1px)), calc(-10 * var(--u, 1px)));
  transition: transform 3s ease-in-out, opacity 1.5s;
}
:root[data-time="morning"] .sun-html { transform: translate(calc(-585 * var(--u, 1px)), calc(85 * var(--u, 1px))); }
:root[data-time="evening"] .sun-html { transform: translate(calc(30 * var(--u, 1px)), calc(165 * var(--u, 1px))); }
:root[data-time="night"] .sun-html { transform: translate(calc(80 * var(--u, 1px)), calc(260 * var(--u, 1px))); opacity: 0; }
.raining .sun-html, .storming .sun-html { opacity: 0; }
/* the close-up camera (games and the title): the sky and sea slide up and down with the city, and the sun and
   moon stay near the top of the view (left in the morning, high in the day, right in the evening) */
/* (the camera slides the two .bd-pan layers, scene.js: camTo; they reach a bit above and below the screen) */
.bd-pan { position: absolute; inset: 0; }
/* a new sky fades in on top of the old one, and the old one goes only once it's covered (scene.js: setTime),
   so there's never a see-through moment in between */
.bd { transition: opacity 0s linear 2s; }
.bd.bd-in { z-index: 1; transition: opacity 2s ease-in-out; }
.zoomed { --bd-shift: 60vh; }
.zoomed .bd-pan { top: calc(-1 * var(--bd-shift)); bottom: calc(-1 * var(--bd-shift)); will-change: transform; }
.zoomed .sun-html, .zoomed .moon-html { top: calc(var(--view-top, 0px) + 30 * var(--u, 1px)); }
.zoomed .sun-html { left: 50vw; transform: translate(22vw, 0); }
:root[data-time="morning"] .zoomed .sun-html { transform: translate(-30vw, calc(26 * var(--u, 1px))); }
:root[data-time="evening"] .zoomed .sun-html { transform: translate(30vw, calc(50 * var(--u, 1px))); }
:root[data-time="night"] .zoomed .sun-html { transform: translate(36vw, calc(90 * var(--u, 1px))); }
.zoomed .moon-html { left: 26vw; }
/* a very hot city: the sun looks bigger and the air glows orange */
.clim-hot .sun-html > .sun-disc, .clim-hot .sun-html > .sun-halo { transform: scale(1.3); }
.clim-hot.heat-day .fxh-heat { opacity: 0.16; }
.sun-halo { --r: 62; background: #ffe680; opacity: 0.35; }
.sun-disc { --r: 42; background: radial-gradient(#fff6b0, #ffd23f); }
.sun-tint { --r: 42; background: #ff7a3d; opacity: 0; transition: opacity 3s; }
:root[data-time="morning"] .sun-tint { opacity: 0.35; }
:root[data-time="evening"] .sun-tint { opacity: 0.7; }
.sun-heat { --r: 95; background: #ffb03a; opacity: 0.45; }
.sun-html > *, .moon-html > * {
  width: calc(var(--r) * 2 * var(--u, 1px)); height: calc(var(--r) * 2 * var(--u, 1px));
  left: calc(var(--r) * -1 * var(--u, 1px)); top: calc(var(--r) * -1 * var(--u, 1px));
}
.moon-html { left: calc(var(--ox, 0px) + 110 * var(--u, 1px)); top: calc(var(--oy, 0px) + 80 * var(--u, 1px)); opacity: 0; transition: opacity 2s; }
:root[data-time="night"] .moon-html { opacity: 1; }
.raining .moon-html, .storming .moon-html { opacity: 0; }
.moon-halo { --r: 30; background: #fff7d6; opacity: 0.25; }
.moon-disc { --r: 22; background: #fff4c2; }
.moon-cut { --r: 19; background: #142a5e; margin-left: calc(9 * var(--u, 1px)); margin-top: calc(-6 * var(--u, 1px)); }
/* solar eclipse: the moon slides in front of the sun */
.corona { --r: 50; border: calc(7 * var(--u, 1px)) solid #fff6c8; box-sizing: border-box; opacity: 0; }
.eclipse-moon { --r: 44; background: #151a2b; opacity: 0; }
.eclipse-on .eclipse-moon { animation: moonPassHtml 7s ease-in-out forwards; }
.eclipse-on .corona { animation: corona 7s ease-in-out forwards; }
@keyframes moonPassHtml { 0% { transform: translateX(calc(-120 * var(--u, 1px))); opacity: 1; } 40%, 62% { transform: translateX(0); opacity: 1; } 100% { transform: translateX(calc(120 * var(--u, 1px))); opacity: 1; } }
@keyframes corona { 0%, 33% { opacity: 0; } 42%, 60% { opacity: 1; } 70%, 100% { opacity: 0; } }
:root[data-time="eclipse"] .bd-stars { opacity: 0.8; }

/* night tint + storm flashes, on top of the island (but under the lights and speech bubble) */
.fx-html { position: fixed; inset: 0; z-index: 1; pointer-events: none; }
.fxh { position: absolute; inset: 0; opacity: 0; }
.fxh-tint { background: #071230; transition: opacity 2s ease-in-out, background-color 2s ease-in-out; }
:root[data-time="morning"] .fxh-tint { background: #ffb070; opacity: 0.08; }
:root[data-time="evening"] .fxh-tint { background: #5a2a5a; opacity: 0.2; }
:root[data-time="night"] .fxh-tint { background: #071230; opacity: 0.58; }
:root[data-time="eclipse"] .fxh-tint { background: #0b1430; opacity: 0.45; }
.fxh-heat { background: #ff7a2e; transition: opacity 2s; }
.fxh-dark { background: #1d2533; }
.fx-storm .fxh-dark { animation: dark 3.4s ease forwards; }
.fxh-flash { background: #eaf2ff; }   /* (lightning flashes: gentle, driven by strike() in scene.js) */
/* the lights + speech bubble SVG sits exactly over the island SVG */
.scene-top { position: absolute; inset: 0; z-index: 2; pointer-events: none; }
/* the camera slides the city sideways on phones (see Scene camTo) */
:is(.scene-wrap, .title-scene).zoomed > svg { will-change: transform; overflow: hidden; }   /* (the drawing's box covers all the camera can see) */
.scene-main { position: relative; z-index: 0; }

/* Rain: one big image of raindrops that slides down. Moving it with transform lets the
   phone's graphics chip do the work, so it stays smooth. */
.rain-fx {
  /* (it reaches past the top and bottom of the screen, so no edge of it ever shows, e.g. when a phone's toolbar moves) */
  position: fixed; inset: -120px 0; z-index: 1; overflow: hidden;
  pointer-events: none; opacity: 0; transition: opacity 0.8s;
}
.rain-fx::before {
  content: ""; position: absolute; left: 0; right: 0; top: -180px; bottom: 0;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='130' height='180'><g stroke='%23dbe9f5' stroke-width='1.7' stroke-linecap='round' opacity='.8'><line x1='12' y1='8' x2='8' y2='26'/><line x1='58' y1='40' x2='54' y2='58'/><line x1='100' y1='16' x2='96' y2='34'/><line x1='30' y1='92' x2='26' y2='110'/><line x1='84' y1='104' x2='80' y2='122'/><line x1='120' y1='72' x2='116' y2='90'/><line x1='46' y1='150' x2='42' y2='168'/><line x1='108' y1='150' x2='104' y2='168'/><line x1='70' y1='4' x2='66' y2='22'/></g></svg>");
  background-size: 130px 180px;
}
.raining .rain-fx { opacity: 1; }
.raining .rain-fx::before { animation: rainMove 0.5s linear infinite; will-change: transform; }
@keyframes rainMove { from { transform: translate3d(0, 0, 0); } to { transform: translate3d(0, 180px, 0); } }
:root[data-time="morning"] { --sky-top-c: #7cc8ef; --sky-bot-c: #ffe3c4; --sea-top-c: #45b4dc; --sea-bot-c: #1a7fb6; --cloud-c: #fff6ec; --sea-deep-c: #0e406e; }
:root[data-time="evening"] { --sky-top-c: #5b5fb0; --sky-bot-c: #ffae80; --sea-top-c: #3f86b8; --sea-bot-c: #1b4f86; --cloud-c: #ffd9c7; --sea-deep-c: #0c2a52; }
:root[data-time="eclipse"] { --sky-top-c: #1c2850; --sky-bot-c: #4a5590; --sea-top-c: #2a5480; --sea-bot-c: #133a6c; --cloud-c: #7480a0; --sea-deep-c: #071a36; }
:root[data-time="night"]   { --sky-top-c: #142a5e; --sky-bot-c: #3e5aa6; --sea-top-c: #2a5f95; --sea-bot-c: #133a6c; --cloud-c: #8a96b6; --sea-deep-c: #071a36; }

:root {
  --sky: #7fd3f7;
  --sea: #1e9bd7;
  --sand: #ffe3a3;
  --leaf: #3cb853;
  --leaf-d: #23863e;
  --sun: #ffc93c;
  --sun-d: #e8a90f;
  --coral: #ff7b54;
  --pink: #ff6fa8;
  --ink: #23313f;
  --ink2: #546271;
  --paper: #fffaf0;
  --good: #2fb35a;
  --mid: #ffb627;
  --bad: #ff5b4a;
  --radius: 22px;
  --shadow: 0 5px 0 rgba(35, 49, 63, 0.14), 0 12px 28px rgba(35, 49, 63, 0.12);
  --font: ui-rounded, "SF Pro Rounded", "Arial Rounded MT Bold", "Nunito", "Trebuchet MS", system-ui, sans-serif;
}

* { box-sizing: border-box; }
[hidden] { display: none !important; }
html, body { height: 100%; margin: 0; overflow: hidden; overscroll-behavior: none; }
body {
  font-family: var(--font);
  color: var(--ink);
  /* --sky-top / --horizon / --deep are measured from the island drawing (app.js: syncHorizon)
     so the sea outside the game lines up exactly with the sea inside it. */
  background: linear-gradient(var(--sky-top-c) calc(var(--sky-top, 0%) + var(--bd-shift, 0px)), var(--sky-bot-c) calc(var(--horizon, 58%) + var(--bd-shift, 0px)), var(--sea-top-c) calc(var(--horizon, 58%) + var(--bd-shift, 0px)), var(--sea-bot-c) var(--deep, 85%), var(--sea-deep-c) 100%);
  overflow: hidden;
  -webkit-tap-highlight-color: transparent;
  -webkit-font-smoothing: antialiased;
}
button, input, select { font-family: inherit; }
button { cursor: pointer; }
button:focus-visible, input:focus-visible, select:focus-visible { outline: 3px solid var(--ink); outline-offset: 2px; }

#app {
  height: 100vh;
  height: 100dvh;
  max-width: 1180px;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left);
}

/* ── top bar ── */
.topbar { flex: 0 0 auto; display: flex; align-items: center; gap: 8px; padding: 8px 12px; }
.brand { font-weight: 900; font-size: 18px; letter-spacing: 0.3px; color: #fff; text-shadow: 0 2px 0 rgba(35, 49, 63, 0.35); }
.controls { margin-left: auto; display: flex; gap: 6px; align-items: center; }
.icon-btn {
  width: 38px; height: 38px; border-radius: 50%; border: none;
  background: rgba(255, 255, 255, 0.9); box-shadow: 0 3px 0 rgba(35, 49, 63, 0.15);
  font-size: 18px; display: grid; place-items: center; padding: 0; position: relative;
}
.icon-btn[aria-pressed="false"] { opacity: 0.5; }
.icon-btn[aria-pressed="false"]::after {
  content: ""; position: absolute; width: 26px; height: 3px; background: var(--bad); border-radius: 2px; transform: rotate(-45deg);
}
.lang-sel {
  appearance: none; -webkit-appearance: none; border: none; border-radius: 999px;
  background: rgba(255, 255, 255, 0.9) ; box-shadow: 0 3px 0 rgba(35, 49, 63, 0.15);
  padding: 0 12px; height: 38px; font-weight: 800; font-size: 13px; color: var(--ink);
}

#screen { flex: 1 1 auto; min-height: 0; display: flex; position: relative; }
.screen { flex: 1; min-width: 0; min-height: 0; display: flex; flex-direction: column; padding: 0 12px 10px; }

/* ── bottom tabs ── */
.tabs { flex: 0 0 auto; display: flex; gap: 6px; padding: 4px 12px 10px; justify-content: center; }
.tabs button {
  flex: 1; max-width: 170px; border: none; border-radius: 16px; padding: 6px 4px;
  background: rgba(255, 255, 255, 0.78); color: var(--ink); font-weight: 800; font-size: 12px;
  display: flex; flex-direction: column; align-items: center; gap: 1px; line-height: 1.15;
}
.tabs button .ti { font-size: 20px; }
.tabs button[aria-current="page"] { background: #fff; box-shadow: var(--shadow); color: var(--leaf-d); }

/* ── buttons ── */
.btn {
  border: none; border-radius: 999px; padding: 11px 22px; font-weight: 900;
  font-size: clamp(15px, 2.2vh, 19px); color: var(--ink);
  box-shadow: 0 5px 0 rgba(0, 0, 0, 0.18); transition: transform 0.08s, box-shadow 0.08s;
}
.btn:active { transform: translateY(3px); box-shadow: 0 2px 0 rgba(0, 0, 0, 0.18); }
.btn:disabled { opacity: 0.4; cursor: default; }
.btn.primary { background: var(--sun); }
.btn.green { background: var(--good); color: #fff; }
.btn.ghost { background: #fff; }
.btn.danger { background: var(--bad); color: #fff; }
.btn.big { font-size: clamp(22px, 3.6vh, 30px); padding: 14px 46px; }
.btn.small { font-size: 14px; padding: 8px 16px; }
.row { display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; align-items: center; }

.panel {
  background: var(--paper); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: clamp(14px, 2.6vh, 28px); width: 100%; max-width: 580px; margin: auto;
  max-height: 100%; overflow: auto; text-align: center;
}
.panel.wide { max-width: 760px; }
.panel h2 { margin: 0 0 6px; font-size: clamp(22px, 3.4vh, 30px); }
.muted { color: var(--ink2); }
.small { font-size: 13px; }

/* ── title screen ── */
.title-screen { text-align: center; gap: 6px; }
.logo {
  margin: 0; font-size: clamp(34px, min(9vh, 15vw), 84px); line-height: 1; font-weight: 900; letter-spacing: 1px;
  -webkit-text-stroke: 3px var(--ink); paint-order: stroke fill; text-shadow: 0 6px 0 var(--ink);
}
.logo .w1 { color: var(--sun); }
.logo .w2 { color: #7fe06a; }
.subtitle {
  margin: 4px auto 0; max-width: 560px; font-weight: 800; font-size: clamp(14px, 2.2vh, 19px);
  color: var(--ink); background: rgba(255, 255, 255, 0.75); border-radius: 999px; padding: 6px 16px;
}
.title-scene { flex: 1 1 auto; min-height: 90px; position: relative; z-index: 0; width: 100%; margin: 4px auto; pointer-events: none; }
.title-scene svg { position: absolute; inset: 0; }
.title-actions { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.lang-chips { display: flex; gap: 6px; justify-content: center; flex-wrap: wrap; }
.lang-chips button {
  border: 2px solid transparent; background: rgba(255, 255, 255, 0.85); border-radius: 999px;
  padding: 5px 12px; font-weight: 800; font-size: 13px; color: var(--ink);
}
.lang-chips button[aria-pressed="true"] { border-color: var(--ink); background: #fff; }
/* the credits sit in the top left corner of the title screen */
.credits {
  position: fixed; top: 10px; left: 14px; z-index: 5; margin: 0; max-width: min(46vw, 430px); text-align: left;
  font-size: clamp(10.5px, 1.5vh, 12.5px); line-height: 1.3;
  color: #fff; font-weight: 700; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45);
}
@media (max-width: 600px) { .credits { top: 8px; left: 10px; max-width: 48vw; font-size: 8px; line-height: 1.25; } }

/* ── intro ── */
.big-emoji { font-size: clamp(44px, 8vh, 72px); line-height: 1; }
.intro-text { font-size: clamp(16px, 2.4vh, 20px); font-weight: 700; line-height: 1.4; margin: 8px 0 12px; }
.meter-legend { display: grid; gap: 8px; margin: 0 auto 14px; max-width: 380px; text-align: left; }
.meter-legend div { display: flex; align-items: center; gap: 10px; background: #fff; border-radius: 14px; padding: 8px 12px; font-weight: 800; }
.meter-legend span { font-size: 28px; }

/* ── game screen ── */
.game { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; gap: 8px; }
.hud {
  display: flex; align-items: center; gap: 12px; background: rgba(255, 255, 255, 0.92);
  border-radius: 18px; padding: 6px 12px; box-shadow: var(--shadow);
}
.meter { flex: 1; min-width: 0; display: flex; align-items: center; gap: 6px; position: relative; }
.meter .emo { font-size: clamp(22px, 3.4vh, 32px); line-height: 1; }
.meter .mcol { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.meter small { font-size: 11px; font-weight: 800; color: var(--ink2); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.meter .bar { height: 14px; background: #e4ebf0; border-radius: 999px; overflow: hidden; }
.meter .bar i {
  display: block; height: 100%; width: 50%; border-radius: 999px; background: var(--good);
  transition: width 0.9s cubic-bezier(0.3, 1.3, 0.5, 1), background-color 0.5s;
}
.meter[data-level="mid"] .bar i { background: var(--mid); }
.meter[data-level="lo"] .bar i { background: var(--bad); }
.meter b { min-width: 2em; text-align: right; font-size: 15px; }
.delta {
  position: absolute; right: 0; top: -4px; font-weight: 900; font-size: 18px; pointer-events: none;
  animation: floatUp 1.4s ease-out forwards; text-shadow: 0 1px 0 #fff;
}
.delta.up { color: var(--good); }
.delta.down { color: #e2392a; }
@keyframes floatUp { from { transform: translateY(6px); opacity: 0; } 20% { opacity: 1; } to { transform: translateY(-26px); opacity: 0; } }
.dots { display: flex; gap: 4px; }
.dots span { width: 10px; height: 10px; border-radius: 50%; background: #d5dde3; }
.dots .g { background: var(--good); }
.dots .b { background: var(--bad); }
.dots .now { box-shadow: 0 0 0 2px var(--ink); }
.turn-txt { display: none; font-weight: 900; font-size: 14px; white-space: nowrap; }

/* The island has no frame: the drawing's sky and sea spill out over the whole screen,
   behind the top bar, the meters and the cards. */
.scene-wrap { min-height: 0; position: relative; z-index: 0; pointer-events: none; }
.scene-wrap svg, .title-scene svg { width: 100%; height: 100%; display: block; overflow: visible; }
.topbar, .hud, .card, .tabs, .title-actions, .logo, .subtitle { position: relative; z-index: 2; }

.card {
  background: var(--paper); border-radius: var(--radius); box-shadow: var(--shadow);
  padding: clamp(12px, 2vh, 20px); max-height: 60vh; overflow: auto;
  animation: cardIn 0.35s ease-out;
}
@keyframes cardIn { from { transform: translateY(10px); opacity: 0; } }
/* while the monkey's animation plays, the card steps aside (text comes after the animation) */
.card.card-wait { opacity: 0; transform: translateY(14px); pointer-events: none; transition: opacity .25s, transform .25s; }
.card-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; }
.pill { background: var(--ink); color: #fff; border-radius: 999px; padding: 3px 10px; font-size: 12px; font-weight: 800; white-space: nowrap; }
.topic { font-weight: 900; color: var(--leaf-d); }
.card-head .spacer { flex: 1; }
.link-btn { border: none; background: none; font-weight: 800; color: var(--ink2); font-size: 14px; padding: 4px 6px; }
.situation { font-size: clamp(17px, 2.6vh, 23px); font-weight: 800; line-height: 1.3; margin: 2px 0 10px; }
.choices { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.choice-btn {
  display: flex; align-items: center; gap: 10px; text-align: left; border: 3px solid transparent;
  border-radius: 18px; padding: 10px 14px; font-weight: 800; font-size: clamp(14px, 2.2vh, 18px);
  color: var(--ink); box-shadow: 0 5px 0 rgba(35, 49, 63, 0.16); line-height: 1.25;
  transition: transform 0.1s, border-color 0.15s;
}
.choice-btn:nth-child(1) { background: #e3f6ff; }
.choice-btn:nth-child(2) { background: #fff1d6; }
.choice-btn:hover { border-color: var(--sun); transform: translateY(-2px); }
.choice-btn:active { transform: translateY(3px); box-shadow: 0 2px 0 rgba(35, 49, 63, 0.16); }
.choice-btn .emo { font-size: clamp(28px, 4.4vh, 40px); line-height: 1; }
.result { display: flex; align-items: center; gap: 12px; }
.result .emo { font-size: clamp(36px, 6vh, 54px); line-height: 1; }
.result p { margin: 0; font-size: clamp(16px, 2.5vh, 21px); font-weight: 800; line-height: 1.3; }
.because { font-size: 13px; color: var(--ink2); font-weight: 700; margin-top: 4px !important; }
.chips { display: flex; gap: 8px; flex-wrap: wrap; margin: 10px 0; }
.chip { background: #fff; border-radius: 999px; padding: 4px 12px; font-weight: 900; font-size: 15px; box-shadow: 0 2px 0 rgba(35, 49, 63, 0.12); }
.chip.up { color: #1d8f43; }
.chip.down { color: #d6322a; }
.card .row.end { justify-content: flex-end; }

/* ending / recap / takeaways */
.game.ending .scene-wrap { min-height: 90px; }
.game.ending .card { max-height: none; padding: clamp(16px, 2.6vh, 26px); }
/* the end (ending, recap, lessons): bigger and easier to read */
.game.ending .card-head .pill { font-size: 14px; padding: 4px 12px; }
.game.ending .topic { font-size: clamp(17px, 2.6vh, 21px); }
.game.ending .verdict { font-size: clamp(20px, 3.1vh, 27px); }
.game.ending .recap p { font-size: clamp(17px, 2.7vh, 22px); line-height: 1.4; margin: 6px 0; }
.game.ending .fact { font-size: clamp(16px, 2.5vh, 20px); padding: 12px 16px; }
.game.ending .end-text { font-size: clamp(17px, 2.7vh, 22px); }
.game.ending .takeaways { gap: 10px; margin: 12px 0 16px; }
.game.ending .takeaways li { font-size: clamp(16px, 2.6vh, 21px); padding: 12px 14px; line-height: 1.3; }
.game.ending .takeaways li span { font-size: 34px; }
.game.ending .card h2 { font-size: clamp(22px, 3.4vh, 30px); }
.game.ending .btn.small { font-size: 17px; padding: 10px 20px; }
.game.ending .read-check { font-size: 17px; padding: 9px 18px; }
.game.ending .read-hint { font-size: 15px; }
.end-top { display: flex; gap: 12px; align-items: center; }
.end-emoji { font-size: clamp(44px, 8vh, 72px); line-height: 1; }
.end-top h2 { margin: 0; font-size: clamp(22px, 3.6vh, 32px); }
.end-text { font-weight: 700; line-height: 1.4; margin: 8px 0; font-size: clamp(14px, 2.2vh, 18px); }
.note { background: #fff4e0; border-radius: 14px; padding: 6px 10px; font-weight: 800; font-size: 14px; margin: 6px 0; }
.ach-chip { background: #fff4c2; border: 2px solid var(--sun); }
.new-ach {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px; margin: 0 0 10px;
  background: #fff4c2; border: 2px solid var(--sun); border-radius: 16px; padding: 6px 10px; font-size: 14px;
}
.new-ach .ach-chip { border: none; padding: 2px 8px; }
.ach-mini { font-size: 22px; line-height: 1; }
.verdict { font-weight: 900; font-size: clamp(17px, 2.6vh, 22px); margin: 2px 0 6px; }
.verdict.good { color: #1d8f43; }
.verdict.bad { color: #c9562a; }
.recap p { margin: 4px 0; font-weight: 700; line-height: 1.35; font-size: clamp(14px, 2.1vh, 17px); }
.fact { background: #eaf7ff; border-radius: 14px; padding: 8px 12px; margin: 8px 0; font-weight: 700; font-size: clamp(13px, 2vh, 16px); line-height: 1.35; }
.fact b { display: block; margin-bottom: 2px; }
.recap-nav { display: flex; gap: 8px; justify-content: space-between; align-items: center; margin-top: 8px; }
/* the recap must be read once: tick "I read this" on every card to go on */
.read-check {
  border: 2.5px solid #2fb35a; background: #fff; color: #1f7a3c; border-radius: 999px; padding: 6px 12px;
  font: inherit; font-weight: 900; font-size: 14px; cursor: pointer; display: inline-flex; align-items: center; gap: 6px;
}
.read-check.on { background: #2fb35a; color: #fff; }
.read-check .ic { width: 1.1em; height: 1.1em; }
.read-hint { margin: 6px 0 0; font-size: 13px; font-weight: 800; color: var(--ink2); text-align: center; }
.note.streak { background: #e3f8e8; color: #1f7a3c; }
.takeaways { list-style: none; padding: 0; margin: 8px 0 12px; display: grid; grid-template-columns: 1fr 1fr; gap: 8px; }
.takeaways li { background: #fff; border-radius: 14px; padding: 8px 10px; font-weight: 800; display: flex; gap: 8px; align-items: center; font-size: clamp(13px, 2vh, 16px); line-height: 1.25; }
.takeaways li span { font-size: 24px; }

/* ── my games ── */
.game-list { display: grid; gap: 8px; margin: 10px 0; text-align: left; }
.game-row { display: flex; gap: 10px; align-items: center; background: #fff; border-radius: 16px; padding: 8px 12px; }
.game-row .emo { font-size: 30px; }
.game-row .info { flex: 1; min-width: 0; }
.game-row .info b { display: block; }
.game-row .info small { color: var(--ink2); font-weight: 700; }
.game-row .mini { font-weight: 800; font-size: 13px; text-align: right; white-space: nowrap; }
.pager { display: flex; gap: 10px; align-items: center; justify-content: center; font-weight: 800; }

/* ── achievements ── */
.ach-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 8px; margin-top: 10px; }
.badge { background: #fff; border-radius: 16px; padding: 8px 6px; display: flex; flex-direction: column; align-items: center; gap: 2px; }
.badge .emo { font-size: clamp(26px, 4.4vh, 38px); line-height: 1.1; }
.badge b { font-size: 13px; line-height: 1.15; max-width: 100%; overflow-wrap: anywhere; hyphens: auto; }
.badge small { font-size: 11px; color: var(--ink2); font-weight: 700; line-height: 1.2; }
.badge.locked .emo { filter: grayscale(1); opacity: 0.35; }
.badge.locked b { color: var(--ink2); }
.badge.got { box-shadow: 0 0 0 3px var(--sun); }

/* ── privacy ── */
.privacy { text-align: left; }
.privacy h2, .privacy h3 { text-align: center; }
.privacy h3 { margin: 12px 0 6px; font-size: 18px; }
.privacy p { margin: 6px 0; font-weight: 700; line-height: 1.4; font-size: clamp(13px, 2vh, 16px); }
.privacy ul { margin: 0; padding: 0; list-style: none; display: grid; gap: 6px; }
.privacy li { background: #fff; border-radius: 12px; padding: 7px 10px; font-weight: 700; font-size: clamp(13px, 1.9vh, 15px); }
.privacy .row { margin-top: 12px; }

/* ── modal + toast ── */
.modal-back { position: fixed; inset: 0; background: rgba(20, 30, 40, 0.5); display: grid; place-items: center; padding: 16px; z-index: 50; animation: fadeIn 0.2s; }
.modal-back .panel { max-width: 420px; margin: 0; }
.qr { background: #fff; border-radius: 16px; padding: 10px; width: min(240px, 60vw); margin: 10px auto; }
.qr svg { width: 100%; height: auto; display: block; }
.url { word-break: break-all; font-size: 12px; color: var(--ink2); font-weight: 700; }
#toasts { position: fixed; top: 60px; left: 50%; transform: translateX(-50%); display: grid; gap: 8px; z-index: 60; pointer-events: none; }
.toast {
  background: #fff; border: 3px solid var(--sun); border-radius: 18px; padding: 8px 16px; box-shadow: var(--shadow);
  font-weight: 800; display: flex; gap: 10px; align-items: center; animation: toastIn 3.2s ease forwards;
}
.toast .emo { font-size: 28px; }
.toast small { display: block; color: var(--ink2); font-size: 12px; }
.toast.long { animation-duration: 7.2s; width: min(92vw, 420px); }
.toast.long small { font-size: 13px; line-height: 1.3; }
@keyframes toastIn { 0% { transform: translateY(-20px); opacity: 0; } 10%, 85% { transform: none; opacity: 1; } 100% { transform: translateY(-10px); opacity: 0; } }
@keyframes fadeIn { from { opacity: 0; } }

/* ── responsive ── */
@media (max-width: 600px) {
  .choices { grid-template-columns: 1fr; gap: 8px; }
  .meter small { display: none; }
  .ach-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 5px; }
  .badge { padding: 6px 3px; }
  .badge b { font-size: 10.5px; }
  .badge .emo { font-size: 24px; }
  .badge small { display: none; }
  .takeaways { grid-template-columns: 1fr; gap: 5px; }
  .brand { font-size: 15px; }
  .game-row .mini { font-size: 12px; }
  .chips { gap: 6px; margin: 8px 0; }
  .chip { font-size: 13px; padding: 3px 9px; }
}
@media (max-width: 460px) {
  .dots { display: none; }
  .turn-txt { display: block; }
  .hud { gap: 8px; padding: 6px 10px; }
  .tabs button { font-size: 10.5px; }
  .brand { display: none; }
}
@media (max-height: 720px) {
  .meter small { display: none; }
  .badge small { display: none; }
  .privacy { padding: 12px 14px; }
  .privacy h2 { font-size: 21px; margin-bottom: 2px; }
  .privacy h3 { margin: 6px 0 4px; font-size: 16px; }
  .privacy p { margin: 3px 0; font-size: 12.5px; line-height: 1.3; }
  .privacy ul { gap: 4px; }
  .privacy li { padding: 5px 8px; font-size: 12.5px; line-height: 1.25; }
  .privacy .row { margin-top: 8px; }
}
/* phones held sideways: island on the left, card on the right */
@media (max-height: 560px) and (orientation: landscape) {
  .game { grid-template-columns: 1.15fr 1fr; grid-template-rows: auto minmax(0, 1fr); }
  .game .hud { grid-column: 1 / -1; }
  .game .card { max-height: none; min-height: 0; }
  .game.ending .scene-wrap { min-height: 0; }
  .choices { grid-template-columns: 1fr; gap: 6px; }
  .topbar { padding: 4px 12px; }
  .icon-btn, .lang-sel { height: 32px; }
  .icon-btn { width: 32px; }
  .tabs { padding: 2px 12px 6px; }
  .tabs button .ti { font-size: 16px; }
  .ach-grid { grid-template-columns: repeat(8, minmax(0, 1fr)); }
  .title-screen { gap: 2px; }
  .logo { font-size: 38px; -webkit-text-stroke: 2px var(--ink); text-shadow: 0 3px 0 var(--ink); }
}


/* ───────── the city (SVG) ───────── */
.hide { opacity: 0 !important; visibility: hidden; }
.hide, .hide * { animation-play-state: paused !important; }
.offcam { animation-play-state: paused !important; }
/* the flood ending (scene.js: flood): the water rises over the city with a big rolling wave, then calms down */
.flood-rise { transform: translateY(340px); transition: transform 3.6s cubic-bezier(.35, 0, .3, 1); }
.flood.rising .flood-rise { transform: translateY(0); }
.surge { transform-box: view-box; transform-origin: 0 302px; transition: transform 2.4s ease-out; }
.flood.calm .surge { transform: scaleY(0.28); }
.surge-roll { animation: surgeRoll 1.1s linear infinite; }
.flood.calm .surge-roll { animation-duration: 3s; }
@keyframes surgeRoll { from { transform: translateX(0); } to { transform: translateX(80px); } }
.ripples-flood { animation: floodRipple 4s ease-in-out infinite alternate; }
@keyframes floodRipple { to { transform: translateX(-40px); } }
.debris { opacity: 0; transition: opacity 1.5s 0.5s; }
.flood.calm .debris { opacity: 1; }
.bob-float { animation: bobFloat 3.2s ease-in-out infinite alternate; transform-box: fill-box; transform-origin: center; }
@keyframes bobFloat { from { transform: translate(-6px, 1.5px) rotate(-7deg); } to { transform: translate(6px, -1.5px) rotate(7deg); } }
/* everything that sticks out of the water is washed away (one after another, from right to left like the wave) */
.flooded :is(.plant, .station, .powerline, .school, .thrift, .mall, .tree, .nest, [data-k="turbines"], [data-k="trains"], [data-k="trainFx"], [data-k="solarSchool"]) {
  transform-box: fill-box; transform-origin: 50% 100%; animation: swept 1.1s ease-in forwards; }
.flooded :is(.plant, .powerline, .mall) { animation-delay: 0s; }
.flooded :is(.thrift, .nest, [data-k="trains"], [data-k="trainFx"]) { animation-delay: .25s; }
.flooded :is(.station, .tree) { animation-delay: .5s; }
.flooded :is(.school, [data-k="turbines"], [data-k="solarSchool"]) { animation-delay: .75s; }
@keyframes swept { 0% { transform: none; opacity: 1; } 35% { transform: translate(-8px, 2px) rotate(-6deg); opacity: 1; } 100% { transform: translate(-60px, 26px) rotate(-28deg); opacity: 0; } }
/* the circle between screens (app.js: iris) */
.iris { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 9999; pointer-events: auto; }
.iris[hidden] { display: none; }   /* (off camera, scene.js: cullAnims) */
.pop {
  transform-box: fill-box; transform-origin: 50% 100%;
  transition: opacity 0.5s, transform 0.6s cubic-bezier(0.34, 1.56, 0.64, 1), visibility 0.5s;
}
.pop.hide { transform: scale(0.3); }
.fade { transition: opacity 0.9s, visibility 0.9s; }

.st-sea-top { stop-color: var(--sea-top-c); }
.st-sea-bot { stop-color: var(--sea-bot-c); }
.st-sea-deep { stop-color: var(--sea-deep-c); }
.cloud { fill: var(--cloud-c); opacity: 0.92; transition: fill 2s; }
.rainy [data-k="skyClouds"] { opacity: 0; }   /* the full cloud cover replaces them */
.waves path { stroke: #fff; stroke-width: 3; fill: none; opacity: 0.55; stroke-linecap: round; }
.lagoon { fill: #7fe3e6; opacity: 0.22; }

/* ground, trees and bushes: green when the climate is OK, dry and brown when it's too hot */
.grass { fill: #6cc551; transition: fill 1.5s; }
.grass.light { fill: #7fd65b; }
.leaf { fill: #3cb853; transition: fill 1.5s; }
.leaf.dark { fill: #2e9e46; }
.bush-d { fill: #3f9e3a; transition: fill 1.5s; } .bush-l { fill: #5cc148; transition: fill 1.5s; } .berry { fill: #ff5a7a; transition: opacity 1s; }
.clim-1 .grass { fill: #8cc657; } .clim-1 .grass.light { fill: #9cd166; }
.clim-2 .grass { fill: #b8bd5e; } .clim-2 .grass.light { fill: #c6c56c; }
.clim-2 .leaf { fill: #8fb243; } .clim-2 .leaf.dark { fill: #7b9b38; } .clim-2 .berry { opacity: 0; }
.clim-2 .bush-d { fill: #8a9a45; } .clim-2 .bush-l { fill: #a5b25a; }
.clim-3 .grass { fill: #d1b46a; } .clim-3 .grass.light { fill: #dcc27c; }
.clim-3 .leaf { fill: #c99a45; } .clim-3 .leaf.dark { fill: #b0832f; }
.clim-3 .bush-d { fill: #a27c3a; } .clim-3 .bush-l { fill: #c0954a; }
/* the sea rises over the beach as the city gets hotter */
.sea-rise { stroke-width: 0; transition: stroke-width 2s ease-in-out; }

.pave { fill: #ddd6c6; }
.road { fill: #5d6470; }
.win { fill: #cfefff; transition: fill 2s; }
:root[data-time="evening"] .win { fill: #ffe9a3; }
:root[data-time="night"] .win { fill: #ffd85a; }
/* at night: some office windows are dark; the school, the shops and the station are closed */
:root[data-time="night"] .win.unlit, :root[data-time="night"] .closed .win { fill: #33465c; }
:root[data-time="night"] .lights-off .hw, :root[data-time="evening"] .lights-off .hw { fill: #2c3a55; }
.win-open .hw { fill: #fff; }
.lampbulb { fill: #fff3a8; }
.tv-flicker { animation: tv 0.5s steps(2) infinite; }
@keyframes tv { 50% { fill: #b388ff; } }
.flag { transform-box: fill-box; transform-origin: 0 50%; animation: flag 1.4s ease-in-out infinite alternate; }
@keyframes flag { from { transform: skewY(-6deg) scaleX(0.9); } to { transform: skewY(6deg); } }

/* smoke from the power plant, chimneys and cars */
.smoke { transform-box: fill-box; transform-origin: center; animation: smokeRise 4s linear infinite; opacity: 0; }
@keyframes smokeRise { 0% { transform: translate(0, 0) scale(0.4); opacity: 0; } 15% { opacity: 0.85; } 100% { transform: translate(-30px, -80px) scale(1.6); opacity: 0; } }
.exhaust circle { fill: #9aa3ad; opacity: 0; }
:is(.puffing, .moving) .exhaust circle { animation: exhaust 0.8s linear infinite; }
:root:not([data-perf="high"]) .tcar .exhaust { display: none; }
/* headlights: cars and bikes that are driving shine their lights in the evening and at night */
.beam { fill: #fff6c4; opacity: 0; transition: opacity 1.5s; pointer-events: none; }
:root[data-time="evening"] :is(.tcar, .moving, .cv, .to-school, .walker) .beam { opacity: 0.35; }
:root:is([data-time="night"], [data-time="eclipse"]) :is(.tcar, .moving, .cv, .to-school, .walker) .beam { opacity: 0.65; }
@keyframes exhaust { 0% { transform: translate(0, 0); opacity: 0.6; } 100% { transform: translate(-10px, -7px); opacity: 0; } }
/* (the cars on the main road are driven by the traffic model in scene.js: see "Smart traffic") */
.cow-gas .smoke { animation-name: gasRise; }
@keyframes gasRise { 0% { transform: translate(0, 0) scale(0.4); opacity: 0; } 20% { opacity: 0.8; } 100% { transform: translate(-6px, -40px) scale(1.4); opacity: 0; } }
/* electricity flowing along the wire from the power plant */
.energy circle { fill: #ffd23f; stroke: #ff9f1c; stroke-width: 1; animation: energy 3s linear infinite; }
.energy.fast circle { animation-duration: 0.8s; }
.energy.slow circle { animation-duration: 7s; opacity: 0.5; }
@keyframes energy { from { transform: translateX(0); } to { transform: translateX(-172px); } }

/* moving things */
@keyframes driveR { from { transform: translateX(-500px); } to { transform: translateX(1300px); } }
/* bike riders seen from the side: legs pedal, wheels turn */
.leg-a { animation: pedal 0.5s ease-in-out infinite alternate; }
.leg-b { animation: pedal 0.5s ease-in-out infinite alternate-reverse; }
@keyframes pedal { from { transform: rotate(-20deg); } to { transform: rotate(16deg); } }
.wheelspin { transform-box: fill-box; transform-origin: center; animation: spin 0.6s linear infinite; }
.walker:not(.pedaling) .leg-a, .walker:not(.pedaling) .leg-b, .walker:not(.pedaling) .wheelspin { animation-play-state: paused; }
.walker.riding [data-k="monkey"] { opacity: 0; }
/* monkeys in the cars: Bobo only sits in the car while riding along */
.passenger { opacity: 0; }
.with-bobo .passenger { opacity: 1; }
[data-k^="traffic"] { transition: opacity 0.6s; }
/* boats and the whale */
.sail { animation: driveR 100s linear infinite; }
.boat-rock { transform-box: fill-box; transform-origin: 50% 100%; animation: boatRock 3.2s ease-in-out infinite alternate; }
@keyframes boatRock { from { transform: rotate(-3deg); } to { transform: rotate(3deg); } }
.whale-bob { animation: whale 4s ease-in-out infinite; }
@keyframes whale { 50% { transform: translateY(4px); } }
.spout { transform-box: fill-box; transform-origin: 50% 100%; animation: spout 4s ease-out infinite; }
@keyframes spout { 0%, 55% { transform: scale(0.2); opacity: 0; } 65% { transform: scale(1.1); opacity: 1; } 90% { transform: scale(1); opacity: 0.8; } 100% { opacity: 0; } }
/* eclipse glasses */
.shades { opacity: 0; transition: opacity 0.4s; }
.eclipse-on .shades { opacity: 1; transition-delay: 1.8s; }   /* (after Bobo's "Whoa!") */
/* the school clock's hands (scene.js: setClock) */
.clock-hand { transform-box: view-box; transform-origin: 108px 292px; }
/* trains: headlight at dusk and at night */
:root[data-time="evening"] .train .beam { opacity: 0.35; }
:root:is([data-time="night"], [data-time="eclipse"]) .train .beam { opacity: 0.65; }
.trainrun { animation: train 26s linear infinite; }
.trainrun.back { animation-name: trainBack; }
@keyframes train { 0% { transform: translateX(-750px); } 60%, 100% { transform: translateX(1700px); } }
@keyframes trainBack { 0% { transform: translateX(1550px); } 60%, 100% { transform: translateX(-900px); } }
.vehicle, .buddy { transform-box: view-box; }
.spin { transform-box: fill-box; transform-origin: center; animation: spin 3.2s linear infinite; }
.fast-spin { animation-duration: 0.4s; }
@keyframes spin { to { transform: rotate(360deg); } }
.balloon { animation: balloon 3s ease-in-out infinite alternate; }
@keyframes balloon { from { transform: translateY(0) rotate(-2deg); } to { transform: translateY(-5px) rotate(2deg); } }
.ac-air path { stroke: #bfe9ff; stroke-width: 2.5; fill: none; stroke-linecap: round; animation: acAir 0.9s linear infinite; }
@keyframes acAir { from { transform: translateX(0); opacity: 1; } to { transform: translateX(12px); opacity: 0; } }
.bubbles-up circle { animation: bubbleUp 1.8s ease-out infinite; }
@keyframes bubbleUp { from { transform: translate(0, 0); opacity: 1; } 50% { transform: translate(6px, -36px); } to { transform: translate(-4px, -72px); opacity: 0; } }

/* Bobo goes inside a house, a shop, a car or the train */
.walker.inside { opacity: 0; }

.glows circle { opacity: 0; transition: opacity 1.2s; pointer-events: none; }
.glows circle.on { opacity: 1; animation: glowFlicker 2.4s ease-in-out infinite alternate; }
@keyframes glowFlicker { 50% { opacity: 0.8; } }

/* Bobo's reactions */
.r { opacity: 0; transition: opacity 0.2s; }
[data-react] .mood { opacity: 0 !important; }
[data-react="yay"] .eyes, [data-react="scared"] .eyes { opacity: 0; }
[data-react="yay"] .r-yay, [data-react="scared"] .r-scared, [data-react="cold"] .r-cold,
[data-react="hot"] .r-hot, [data-react="sad"] .r-sad, [data-react="think"] .r-think { opacity: 1; }
[data-react="cold"] .bob { animation: shiver 0.12s linear infinite; }
[data-react="scared"] .bob { animation: shiver 0.2s linear infinite; }
.heart { transform-box: fill-box; transform-origin: center; }
[data-react="yay"] .heart { animation: heartUp 1.4s ease-in-out infinite; }
[data-react="hot"] .drip, [data-react="sad"] .drip { animation: drip 1.2s ease-in infinite; }
@keyframes shiver { 25% { transform: translateX(-1.5px); } 75% { transform: translateX(1.5px); } }
@keyframes heartUp { 0% { transform: translateY(4px) scale(0.8); opacity: 0.4; } 50% { opacity: 1; } 100% { transform: translateY(-8px) scale(1.1); opacity: 0.2; } }
@keyframes drip { from { transform: translateY(0); } to { transform: translateY(6px); opacity: 0.3; } }

/* speech bubble */
.bubble { transition: opacity 0.25s; pointer-events: none; }
.bubble text { font-family: var(--font); }
.bubble-in { transform-box: fill-box; transform-origin: 50% 100%; }
.bubble-in.jump { animation: bubblePop 0.35s cubic-bezier(0.34, 1.56, 0.64, 1); }
@keyframes bubblePop { from { transform: scale(0.4); opacity: 0; } }
.fly-bug { animation: buzzA 1.3s linear infinite; }
.fly-bug.f1 { animation-name: buzzB; animation-duration: 1.1s; }
.fwing { transform-box: fill-box; transform-origin: 50% 100%; animation: flapFly 0.09s linear infinite alternate; }
@keyframes buzzA { 0%, 100% { transform: translate(0, 0); } 20% { transform: translate(7px, -4px); } 40% { transform: translate(2px, -9px); } 60% { transform: translate(-6px, -5px); } 80% { transform: translate(-3px, 2px); } }
@keyframes buzzB { 0%, 100% { transform: translate(0, 0); } 25% { transform: translate(-6px, -6px); } 50% { transform: translate(-1px, -11px); } 75% { transform: translate(6px, -4px); } }
@keyframes flapFly { from { transform: scaleY(1); } to { transform: scaleY(0.3); } }

/* seagulls, butterflies, bees, birds, crabs */
.fly { animation: fly 20s linear infinite; }
.soar { animation: soar 3s ease-in-out infinite; }
@keyframes fly { from { transform: translateX(-350px); } to { transform: translateX(1150px); } }
@keyframes soar { 50% { transform: translateY(-10px); } }
.flutter { animation: flutter 16s ease-in-out infinite; }
.bfly .bwing { transform-box: fill-box; transform-origin: center; }
.bfly { animation: wingbeat 0.25s ease-in-out infinite alternate; transform-box: fill-box; transform-origin: center; }
@keyframes wingbeat { to { transform: scaleX(0.35); } }
/* butterflies wander around the open park and garden (never into buildings) */
@keyframes flutter { 0%, 100% { transform: translate(0, 0); } 15% { transform: translate(22px, -16px); } 30% { transform: translate(44px, -6px); } 45% { transform: translate(30px, 12px); }
  60% { transform: translate(-6px, 8px); } 75% { transform: translate(-30px, -10px); } 90% { transform: translate(-14px, -20px); } }
.beefly { animation: beefly 7s ease-in-out infinite; }
.beefly .bwing { animation: flicker 0.08s linear infinite alternate; transform-box: fill-box; transform-origin: 50% 100%; }
@keyframes beefly { 0%, 100% { transform: translate(0, 0); } 20% { transform: translate(16px, -10px); } 40% { transform: translate(26px, 2px); } 60% { transform: translate(6px, -16px); } 80% { transform: translate(-14px, -4px); } }
.scuttle { animation: scuttle 14s ease-in-out infinite; }
/* crabs walk sideways up and down the beach, stopping now and then */
@keyframes scuttle { 0%, 100% { transform: translateX(0); } 20%, 30% { transform: translateX(70px); } 55%, 62% { transform: translateX(110px); } 85% { transform: translateX(30px); } }
.hop { animation: hop 5s ease-in-out infinite; }
/* songbirds hop along a little and back */
@keyframes hop { 0%, 100% { transform: translate(0, 0); } 10% { transform: translate(3px, -5px); } 16% { transform: translate(6px, 0); } 46% { transform: translate(6px, 0); }
  56% { transform: translate(2px, -5px); } 62% { transform: translate(-2px, 0); } 90% { transform: translate(-2px, 0); } }

/* coral reef: colourful when healthy, pale, then white when bleached */
.reef { opacity: 0.88; }
.coral { transition: color 2s; }
.c-a { color: #ef7d72; } .c-b { color: #f2a65a; } .c-c { color: #9a7fd1; } .c-d { color: #e9c46a; } .c-e { color: #3fb8a9; }
.coral-pale .c-a { color: #f4bdb6; } .coral-pale .c-b { color: #f5cfa6; } .coral-pale .c-c { color: #cfc1ea; } .coral-pale .c-d { color: #f1dfac; } .coral-pale .c-e { color: #a5dcd5; }
.kelp { transform-box: fill-box; transform-origin: 50% 100%; animation: kelp 4s ease-in-out infinite alternate; }
.sway-soft { transform-box: fill-box; transform-origin: 50% 100%; animation: kelp 2.6s ease-in-out infinite alternate; }
@keyframes kelp { from { transform: rotate(-6deg); } to { transform: rotate(6deg); } }
.coral-bleached .kelp path { stroke: #9b8f5c; }
.coral-bleached .coral { color: #f1efe8; }

/* bottles drifting around the sea */
.wander { animation: wander 36s ease-in-out infinite; }
@keyframes wander {
  0%, 100% { transform: translate(0, 0); }
  25% { transform: translate(calc(var(--wx, 1) * 110px), 6px); }
  50% { transform: translate(calc(var(--wx, 1) * 200px), -4px); }
  75% { transform: translate(calc(var(--wx, 1) * 90px), 9px); }
}

/* storms in a hot climate: trees bend in the wind */
.storming .crown { transform-box: fill-box; transform-origin: 50% 100%; animation: sway 0.9s ease-in-out infinite alternate; }
.fx-storm .fxh-dark { animation: dark 3.4s ease forwards; }
@keyframes dark { to { opacity: 0.35; } }
.heat-lines path { stroke: #ff8a3d; stroke-width: 1.5; fill: none; stroke-linecap: round; }
.heat-lines .shimmer { opacity: 0; animation: shimmer 1.8s ease-out infinite; }
@keyframes shimmer { 0% { transform: translateY(0); opacity: 0; } 30% { opacity: 0.75; } 100% { transform: translateY(-14px); opacity: 0; } }

.swim { animation: swim 34s linear infinite; }
.bob { animation: bob 2.4s ease-in-out infinite; }
.float { animation: floaty 3s ease-in-out infinite; transform-box: fill-box; transform-origin: center; }
.flicker { transform-box: fill-box; transform-origin: 50% 100%; animation: flicker 0.32s ease-in-out infinite alternate; }
.drift { animation: drift 110s linear infinite; }
.sparkle { transform-box: fill-box; transform-origin: center; animation: spark 1.2s ease-out forwards; }
.walker { transition: transform 1s ease-in-out, opacity 0.4s; }
.walking .bob, .walking .bd-bob { animation: walkbob 0.26s ease-in-out infinite alternate; transform-box: fill-box; transform-origin: 50% 100%; }
.running :is(.bob, .bd-bob) { animation-duration: 0.15s; }
.running .foot { animation-duration: 0.15s !important; }
@keyframes walkbob { from { transform: translateY(0) rotate(-4deg); } to { transform: translateY(-6px) rotate(4deg); } }
/* the feet take steps while walking (one forward and up, then the other) */
.walking .foot.fl { animation: stepL 0.26s ease-in-out infinite alternate; }
.walking .foot.fr { animation: stepR 0.26s ease-in-out infinite alternate; }
@keyframes stepL { from { transform: translate(-4px, 0); } to { transform: translate(4px, -6px); } }
@keyframes stepR { from { transform: translate(4px, -6px); } to { transform: translate(-4px, 0); } }
.mjump.chop { animation: chop 0.25s ease-in-out 4; transform-box: fill-box; transform-origin: 50% 100%; }
@keyframes chop { 50% { transform: rotate(-12deg) translateY(2px); } }
.mjump.jump { animation: jump 0.7s ease; }
.mjump.droop { animation: droop 0.9s ease; transform-box: fill-box; transform-origin: 50% 100%; }

@keyframes swim { from { transform: translateX(-350px); } to { transform: translateX(1150px); } }
@keyframes bob { 50% { transform: translateY(-4px); } }
@keyframes floaty { 50% { transform: translateY(3px) rotate(5deg); } }
@keyframes flicker { to { transform: scale(1.08, 1.2); } }
@keyframes drift { from { transform: translateX(-400px); } to { transform: translateX(1200px); } }
@keyframes spark { from { transform: scale(0.2) rotate(0); opacity: 1; } to { transform: scale(1.6) rotate(60deg); opacity: 0; } }
@keyframes jump { 30% { transform: translateY(-24px); } 60% { transform: translateY(0); } 78% { transform: translateY(-7px); } }
@keyframes droop { 40% { transform: scale(1.04, 0.9); } }
@keyframes sway { from { transform: rotate(-7deg); } to { transform: rotate(7deg); } }

/* the thermometer in the HUD */
.thermo .bar i { background: #4fc3f7; }   /* (one colour that warms up with the temperature: set in app.js) */
.meter.thermo b { min-width: 3.2em; }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001s !important; animation-iteration-count: 1 !important; transition-duration: 0.2s !important; }
}

/* ── animation scaler (js/perf.js) ──
   mid: the little extras stand still; low: only the animations the story needs */
:root[data-perf="mid"] :is(.kelp, .sway-soft, .flag, .balloon, .boat-rock, .v-steam .smoke, .flicker, .tv-flicker, .glows circle.on) { animation: none !important; }
:root[data-perf="mid"] .fwing { animation: none !important; }
:root[data-perf="low"] .flies, :root[data-perf="low"] .heat-lines { display: none; }   /* (hidden rather than frozen) */
:root[data-perf="mid"] .plant-smoke .smoke:nth-child(even), :root[data-perf="mid"] .exhaust circle:nth-child(3) { display: none; }
/* (the animals always stay and keep moving around on every level: they show how healthy the island is.
   The lowest level only stops little extras, like flapping and fluttering wings and swaying plants) */
:root[data-perf="low"] :is(.kelp, .sway-soft, .flutter, .bfly, .beefly .bwing, .vwing, .flag, .balloon, .boat-rock, .wing, .flicker, .tv-flicker, .glows circle.on, .bob, .heat-lines path, .cow-gas .smoke, .v-steam .smoke, .energy circle, .wheelspin) { animation: none !important; }
:root[data-perf="low"] :is([data-k="skyClouds"], [data-k^="traffic2"], [data-k^="traffic3"]) { display: none; }
:root[data-perf="low"] .plant-smoke .smoke:not(:first-child), :root[data-perf="low"] .exhaust circle:not(:first-child) { display: none; }
:root[data-perf="low"] .raining .rain-fx::before { animation-duration: 0.9s; }
:root[data-perf="low"] .bd.bd-in, :root[data-perf="low"] .fxh-tint { transition-duration: 1s; }
:root[data-perf="low"] .bd { transition-delay: 1s; }

/* walking is part of the story: it moves on every level (nobody slides around) */
:root[data-perf="low"] .walking :is(.bob, .bd-bob) { animation: walkbob 0.26s ease-in-out infinite alternate !important; }

/* our own icons (js/icons.js): they size like text */
.ic { display: inline-block; width: 1.1em; height: 1.1em; vertical-align: -0.2em; flex: none; overflow: visible; }
.btn .ic, .link-btn .ic { width: 1em; height: 1em; vertical-align: -0.14em; }
.icon-btn .ic { width: 22px; height: 22px; vertical-align: middle; }
.brand .ic { width: 22px; height: 22px; vertical-align: -5px; filter: drop-shadow(0 2px 0 rgba(35, 49, 63, 0.3)); }
.big-emoji .ic { width: 1em; height: 1em; margin: 0 2px; }
.meter-legend span .ic, .choice-btn .emo .ic, .result .emo .ic, .end-emoji .ic, .badge .emo .ic, .game-row .emo .ic, .toast .emo .ic { width: 1em; height: 1em; vertical-align: middle; }

/* the volcano island far away: green when the climate is OK, dry and brown when it's too hot */
.v-land { fill: #8fd17a; transition: fill 1.5s; }
.v-rock { fill: #9c8a7c; }
.vleaf { fill: #4f9f4a; transition: fill 1.5s; }
.clim-1 .v-land { fill: #a6cf78; }
.clim-2 .v-land { fill: #c8c07a; } .clim-2 .vleaf { fill: #8fae4a; }
.clim-3 .v-land { fill: #cfae76; } .clim-3 .vleaf { fill: #b0863a; }
:root[data-perf="low"] .sun-html, :root[data-perf="low"] .moon-html { transition-duration: 1.2s; }

/* birds: things that circle (the hawk, the birds around the volcano), pecking pigeons, hungry chicks */
.orbit { animation: orbit 24s linear infinite; }
.orbit.back { animation-direction: reverse; }
@keyframes orbit { to { transform: rotate(360deg); } }
.peck { transform-box: fill-box; transform-origin: 70% 100%; animation: peck 2.6s ease-in-out infinite; }
@keyframes peck { 0%, 30%, 60%, 100% { transform: rotate(0); } 40%, 50% { transform: rotate(-32deg); } 70%, 76% { transform: rotate(-30deg); } }
.pigeon-walk { animation: pigeonWalk 9s ease-in-out infinite; }
@keyframes pigeonWalk { 0%, 100% { transform: translateX(0); } 45%, 55% { transform: translateX(-12px); } }
.chick { transform-box: fill-box; transform-origin: 50% 100%; animation: chick 0.7s ease-in-out infinite alternate; }
@keyframes chick { to { transform: translateY(-1.6px) scale(1.05); } }
:root[data-perf="mid"] :is(.pigeon-walk, .chick) { animation: none !important; }
:root[data-perf="low"] :is(.orbit, .peck, .pigeon-walk, .chick) { animation: none !important; }

/* Bobo on the bike from behind: the legs go up and down */
.pedal-l { animation: pedalUp 0.45s ease-in-out infinite alternate; }
.pedal-r { animation: pedalUp 0.45s ease-in-out infinite alternate-reverse; }
@keyframes pedalUp { from { transform: translateY(0); } to { transform: translateY(-5px); } }
.walker:not(.pedaling) .pedal-l, .walker:not(.pedaling) .pedal-r { animation-play-state: paused; }
.walker [data-k="mRide"] { transition: opacity 0.15s; }
.walker.riding [data-k="monkey"] { transition: opacity 0.15s; }

/* seagulls flying right-to-left; the hawk glides slowly across, flapping now and then */
.fly.left { animation-name: flyLeft; }
/* birds drift up and down as they fly, each at its own height and pace */
.alt { animation: alt 9s ease-in-out infinite alternate; }
/* ripples on the water: little rings that spread out and fade */
.ripple { transform-box: fill-box; transform-origin: center; opacity: 0; animation: ripple 4.2s ease-out infinite; }
@keyframes ripple { 0% { transform: scale(0.3); opacity: 0.75; } 100% { transform: scale(1.9); opacity: 0; } }
:root[data-perf="low"] .ripples { display: none; }
@keyframes alt { from { transform: translateY(calc(var(--alt, 20px) * -1)); } to { transform: translateY(var(--alt, 20px)); } }
/* an airplane crosses the sky only now and then (most of the time it's far off-screen) */
.plane { animation: plane 150s linear infinite; }
.plane.left { animation-name: planeLeft; }
@keyframes plane { 0% { transform: translateX(-300px); } 22%, 100% { transform: translateX(1150px); } }
@keyframes planeLeft { 0% { transform: translateX(1150px); } 22%, 100% { transform: translateX(-300px); } }
@keyframes flyLeft { from { transform: translateX(1150px); } to { transform: translateX(-350px); } }
.hawk-fly { animation: flyLeft 48s linear infinite; animation-delay: -12s; }
/* the title screen: calm, just a few birds */
.calm :is([data-k="butterflies"], [data-k="bees"], [data-k="songbirds"], [data-k="crabs"], [data-k="fish"], [data-k="seaTurtle"], [data-k="farFish"], [data-k="hawk"], [data-k="vBirds"], [data-k="vAnimals"], [data-k="cyclists"], .nest) { display: none; }

/* birds round the volcano: fly round an oval, staying upright, flapping */
.oval { animation: oval 12s linear infinite; }
@keyframes oval { 0%, 100% { transform: translate(28px, 0); } 12.5% { transform: translate(20px, -9px); } 25% { transform: translate(0, -12px); } 37.5% { transform: translate(-20px, -9px); }
  50% { transform: translate(-28px, 0); } 62.5% { transform: translate(-20px, 7px); } 75% { transform: translate(0, 9px); } 87.5% { transform: translate(20px, 7px); } }
.vwing { transform-box: fill-box; transform-origin: center; animation: vflap 0.5s ease-in-out infinite alternate; }
@keyframes vflap { to { transform: scaleY(0.4); } }

/* umbrellas come out when it rains */
.umbrella { opacity: 0; transition: opacity 0.4s; }
.raining .umbrella { opacity: 1; }
/* a new reward pops in with a glowing ring, so it's easy to notice */
.reveal { animation: reveal 1.1s cubic-bezier(0.3, 1.6, 0.5, 1); transform-box: fill-box; transform-origin: 50% 100%; }
@keyframes reveal { 0% { transform: scale(0.2); opacity: 0; } 60% { transform: scale(1.18); opacity: 1; } 100% { transform: scale(1); } }
.ring { fill: none; stroke: #fff36b; stroke-width: 4; opacity: 0; transform-box: fill-box; transform-origin: center; animation: ring 1.5s ease-out forwards; }
@keyframes ring { 0% { transform: scale(0.2); opacity: 1; } 100% { transform: scale(2.6); opacity: 0; } }

/* the bike group: two friends ride along the street by the school, arrive, and set off again */
.to-school { animation: toSchool 18s linear infinite; }
@keyframes toSchool { 0% { transform: translateX(600px); opacity: 0; } 4% { opacity: 1; } 80% { transform: translateX(200px); opacity: 1; } 86%, 100% { transform: translateX(180px); opacity: 0; } }
:root[data-perf="low"] .to-school { animation-duration: 30s; }
