/* ==========================================================================
   World Explorer — styles
   Big targets, big type, high contrast. Sized so it works with a mouse on a
   laptop and with a thumb on a tablet without a separate mobile layout.
   ========================================================================== */

:root {
  --sky-1: #0b1d4d;
  --sky-2: #17357e;
  --sky-3: #2b62b8;

  --ink: #17224a;
  --ink-soft: #5b678f;
  --paper: #ffffff;

  --sun: #ffc93c;
  --coral: #ff6b6b;
  --mint: #2fd0a8;
  --grape: #7b6cf6;

  --radius: 22px;
  --shadow: 0 14px 34px rgba(8, 18, 48, .28);

  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);

  /* Where a docked panel (the info card, the lesson player) sits. */
  --dock-top: calc(86px + var(--safe-t));
  --dock-gap: 18px;
  --dock-w: min(380px, calc(100vw - 36px));
  --dock-max-h: calc(100vh - 86px - 18px - var(--safe-t) - var(--safe-b));

  /* The part of the screen no panel covers, kept up to date by js/ui.js
     (syncMapView): its middle, its width, and how much is covered from the
     bottom. The hint and the keys centre themselves under the globe with it. */
  --map-cx: 50vw;
  --map-w: 100vw;
  --map-bottom: 0px;
  --map-lift: max(var(--safe-b), var(--map-bottom));
}

* { box-sizing: border-box; }

html, body {
  height: 100%;
  margin: 0;
  overflow: hidden;
  background: radial-gradient(circle at 50% 42%, var(--sky-3) 0%, var(--sky-2) 45%, var(--sky-1) 100%);
  font-family: "Baloo 2", "Nunito", "Segoe UI Variable", "Segoe UI", system-ui, -apple-system, sans-serif;
  color: var(--ink);
  -webkit-text-size-adjust: 100%;
  -webkit-tap-highlight-color: transparent;
}

/* ==========================================================================
   Top bar
   ========================================================================== */

#topbar {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  flex-wrap: wrap;
  padding: calc(12px + var(--safe-t)) 16px 12px;
  pointer-events: none;
}

.logo {
  margin: 0;
  font-size: clamp(20px, 3.4vw, 30px);
  font-weight: 800;
  letter-spacing: .2px;
  color: #fff;
  text-shadow: 0 3px 0 rgba(0, 0, 0, .22);
  pointer-events: none;
}
.logo span { filter: drop-shadow(0 2px 4px rgba(0, 0, 0, .3)); }

#controls {
  display: flex;
  gap: 10px;
  flex-wrap: wrap;
  pointer-events: auto;
}

.ctrl {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 8px;
  min-width: 54px;
  min-height: 54px;          /* comfortable tap target */
  padding: 0 14px;
  border: none;
  border-radius: 18px;
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  font-weight: 800;
  cursor: pointer;
  box-shadow: 0 5px 0 rgba(10, 22, 60, .28), 0 10px 20px rgba(8, 18, 48, .22);
  transition: transform .12s ease, box-shadow .12s ease, background .15s ease;
  touch-action: manipulation;
  user-select: none;
}
.ctrl:hover { background: #fdfbff; }
.ctrl:active {
  transform: translateY(4px);
  box-shadow: 0 1px 0 rgba(10, 22, 60, .28), 0 4px 10px rgba(8, 18, 48, .22);
}
.ctrl:focus-visible { outline: 4px solid var(--sun); outline-offset: 3px; }
/* A lesson owns the globe, so the view buttons rest while it is open. */
.ctrl:disabled {
  opacity: .45;
  cursor: default;
  pointer-events: none;
  transform: none;
}

.ctrl-icon { font-size: 21px; line-height: 1; }
.ctrl-wide { padding: 0 18px; }

.ctrl-toggle[aria-pressed="true"],
#btn-equator[data-step="equator"],
#btn-oceans[data-step="oceans"] {
  background: var(--sun);
  color: #4a3400;
}
/* The third step of the 🌐 button: the Earth is open. Hot, like its middle. */
#btn-equator[data-step="inside"] {
  background: linear-gradient(135deg, #ffa22e 0%, #f2542d 55%, #d7261c 100%);
  color: #fff;
  text-shadow: 0 1px 2px rgba(90, 20, 0, .45);
}
/* The 🌊 button's second step: the currents are flowing. Warm into cold,
   like the two colours of arrow. */
#btn-oceans[data-step="currents"] {
  background: linear-gradient(135deg, #ff7a45 0%, #d9477a 45%, #3f8fe6 100%);
  color: #fff;
  text-shadow: 0 1px 2px rgba(20, 20, 70, .5);
}
/* The 🌊 button's third step: sea life. Deep water into coral. */
#btn-oceans[data-step="sealife"] {
  background: linear-gradient(135deg, #1fb5c9 0%, #2a7fd6 50%, #ff7f8e 100%);
  color: #fff;
  text-shadow: 0 1px 2px rgba(10, 40, 80, .5);
}
/* The fourth step: the rings of air are round the globe. Sky blue. */
#btn-equator[data-step="sky"] {
  background: linear-gradient(135deg, #7fd3ff 0%, #4f7dff 100%);
  color: #fff;
  text-shadow: 0 1px 2px rgba(10, 30, 90, .5);
}
/* The fifth step: day and night, the Sun and the Moon. Sunshine. */
#btn-equator[data-step="sun"] {
  background: linear-gradient(135deg, #ffd54f 0%, #ff9f1c 100%);
  color: #4a2a00;
}
/* The sixth step: the seasons. Winter sky, spring green, summer sun, autumn. */
#btn-equator[data-step="seasons"] {
  background: linear-gradient(135deg, #8fd3ff 0%, #7ed957 35%, #ffd54f 68%, #ff9f5a 100%);
  color: #2a2a10;
}

/* ==========================================================================
   Globe stage + labels
   ========================================================================== */

#stage {
  position: fixed;
  inset: 0;
  z-index: 1;
}
#stage canvas { display: block; }

#label-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 5;
}

.map-label {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
  font-weight: 800;
  color: #fff;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .65), 0 0 10px rgba(0, 0, 0, .45);
  pointer-events: none;
}
.map-label.is-country { font-size: 13px; letter-spacing: .1px; }
.map-label.is-continent {
  font-size: clamp(17px, 2.6vw, 26px);
  letter-spacing: .6px;
  text-transform: uppercase;
  text-shadow: 0 2px 4px rgba(0, 0, 0, .7), 0 0 16px rgba(0, 0, 0, .5);
}

/* Equator + hemisphere labels (opacity and position set every frame). */
.geo-label {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
  pointer-events: none;
  font-weight: 800;
  will-change: transform, opacity;
}
.geo-label.is-equator {
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(40, 28, 0, .55);
  color: #ffd21f;
  font-size: 14px;
  letter-spacing: .6px;
  text-transform: uppercase;
  box-shadow: 0 0 0 2px rgba(255, 210, 31, .75);
}
.geo-label.is-north,
.geo-label.is-south {
  padding: 4px 12px;
  border-radius: 999px;
  background: rgba(12, 22, 58, .58);
  color: #fff;
  font-size: 15px;
  text-shadow: 0 1px 2px rgba(0, 0, 0, .5);
}
.geo-label.is-north { box-shadow: 0 0 0 2px rgba(255, 170, 110, .85); }
.geo-label.is-south { box-shadow: 0 0 0 2px rgba(90, 240, 205, .85); }
.geo-label.is-north::before { content: "▲ "; color: #ffb27a; }
.geo-label.is-south::before { content: "▼ "; color: #6ff0d2; }

/* The Prime Meridian: the equator's pill in the meridian's pink, and a shade
   smaller, so the pair read as the same kind of thing with the equator still
   the louder of the two. */
.geo-label.is-meridian {
  padding: 2px 10px;
  border-radius: 999px;
  background: rgba(46, 8, 26, .55);
  color: #ff9ac6;
  font-size: 13px;
  letter-spacing: .6px;
  text-transform: uppercase;
  box-shadow: 0 0 0 2px rgba(255, 95, 162, .75);
}

/* "30°N", "60°W": the quiet end of the family. Small, dark and thin-bordered,
   because there are a dozen of them and they are a scale, not a place. */
.geo-label.is-deg {
  padding: 1px 7px;
  border-radius: 999px;
  background: rgba(8, 14, 34, .55);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: .3px;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .55);
}

/* Ocean and sea names. Deliberately unlike the country labels: lighter, wider
   and letter-spaced, which is how water is lettered on a real map — so a
   child can tell at a glance whether a name belongs to land or to sea.
   Opacity is set every frame as the name turns towards the back of the globe. */
.water-label {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
  pointer-events: none;
  color: #eaf7ff;
  font-weight: 600;
  font-style: italic;
  letter-spacing: 1.6px;
  text-shadow: 0 1px 3px rgba(0, 20, 50, .8), 0 0 12px rgba(0, 20, 50, .6);
  will-change: transform, opacity;
}
.water-label.is-ocean {
  font-size: 15px;
  letter-spacing: 3px;
  text-transform: uppercase;
}
.water-label.is-sea { font-size: 12.5px; }

/* Current names. Italic like the seas, but bold, not spaced out, and tinted
   the colour of their arrow — so they never read as a sea or a country. */
.current-label {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
  pointer-events: none;
  font-size: 13.5px;
  font-weight: 800;
  font-style: italic;
  text-shadow: 0 1px 3px rgba(0, 12, 35, .9), 0 0 10px rgba(0, 12, 35, .7);
  will-change: transform, opacity;
}
.current-label.is-warm { color: #ffb59a; }
.current-label.is-cold { color: #c9f7ff; }

/* Nature mode names. Warm and solid where the water names are light and
   airy, so land and sea still read as different sorts of thing. */
.nature-label {
  position: absolute;
  top: 0;
  left: 0;
  white-space: nowrap;
  pointer-events: none;
  font-size: 12.5px;
  font-weight: 800;
  letter-spacing: .3px;
  color: #fffdf4;
  text-shadow: 0 1px 2px rgba(40, 30, 0, .85), 0 0 10px rgba(30, 20, 0, .55);
  will-change: transform, opacity;
}
.nature-label.is-ice { color: #eaf4ff; text-shadow: 0 1px 2px rgba(20, 40, 70, .8); }

/* The markers for places too small to paint — waterfalls, peaks, the reef.
   Tap target is the whole pill, comfortably over the 44px guideline on its
   short side once the emoji and the name are in it. */
.nature-marker {
  position: absolute;
  top: 0;
  left: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  /* 28px dot + 8px top and bottom = a 44px tall tap target, which is the
     usual minimum and none too big for a five-year-old's finger. */
  padding: 8px 13px 8px 6px;
  border: none;
  border-radius: 999px;
  background: rgba(24, 16, 40, .62);
  box-shadow: 0 0 0 2px rgba(255, 90, 200, .9), 0 4px 10px rgba(0, 0, 0, .35);
  backdrop-filter: blur(4px);
  color: #fff;
  font: inherit;
  font-size: 12.5px;
  font-weight: 800;
  white-space: nowrap;
  cursor: pointer;
  pointer-events: auto;       /* the label layer itself ignores pointers */
  touch-action: manipulation;
  will-change: transform, opacity;
}
.marker-dot {
  display: grid;
  place-content: center;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  background: rgba(255, 255, 255, .92);
  font-size: 15px;
  line-height: 1;
}
/* No :active transform here — ui.js sets `transform` inline every frame to
   position the marker, and an inline style would win over this rule anyway. */
.nature-marker:hover { background: rgba(40, 24, 64, .8); }
.nature-marker:focus-visible { outline: 3px solid var(--sun); outline-offset: 3px; }

/* A coral reef's pill in the Sea Life step: the nature pill, in coral. */
.reef-marker {
  background: rgba(20, 30, 56, .62);
  box-shadow: 0 0 0 2px rgba(255, 127, 142, .95), 0 4px 10px rgba(0, 0, 0, .35);
}
.reef-marker:hover { background: rgba(30, 44, 80, .8); }
.reef-marker.is-picked { box-shadow: 0 0 0 3px #ffd54f, 0 0 16px 4px rgba(255, 213, 79, .7); }
.nature-line.reef-line { stroke: #ff7f8e; }
.nature-dot.reef-dot { fill: #ff7f8e; }

/* The cities of the country a child has opened. Same pill as a nature marker
   — same 44px tap target — in the violet that says "inside a country" here,
   with a star for the national capital and a dot for the rest. */
.city-marker {
  position: absolute;
  top: 0;
  left: 0;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 8px 13px 8px 6px;
  border: none;
  border-radius: 999px;
  background: rgba(26, 14, 44, .66);
  box-shadow: 0 0 0 2px rgba(190, 120, 255, .9), 0 4px 10px rgba(0, 0, 0, .35);
  backdrop-filter: blur(4px);
  color: #fff;
  font: inherit;
  font-size: 12.5px;
  font-weight: 800;
  white-space: nowrap;
  cursor: pointer;
  pointer-events: auto;
  touch-action: manipulation;
  will-change: transform, opacity;
}
.city-marker .marker-dot { font-size: 13px; color: #6b3fa0; }
.city-marker.is-capital { box-shadow: 0 0 0 2px rgba(255, 210, 31, .95), 0 4px 10px rgba(0, 0, 0, .35); }
.city-marker.is-capital .marker-dot { background: #fff6d6; font-size: 15px; }
/* Crowded: the name goes, the dot (and so the tap target) stays. */
.city-marker.is-compact { padding: 8px; gap: 0; }
.city-marker.is-compact .marker-name { display: none; }
.city-marker:hover { background: rgba(48, 26, 78, .85); }
.city-marker:focus-visible { outline: 3px solid var(--sun); outline-offset: 3px; }

/* ---- Inside the Earth ------------------------------------------------------
   While the Earth is open (or opening, or closing) the surface's names,
   markers, hint and keys are put away; the four layer pills take over. */
body.inside-on #label-layer,
body.inside-on #hint,
body.inside-on #depth-key,
body.inside-on #nature-key,
body.inside-on #sun-key,
body.inside-on #geo-hint,
body.inside-on #hover-tip,
body.sky-on #label-layer,
body.sky-on #hint,
body.sky-on #depth-key,
body.sky-on #nature-key,
body.sky-on #sun-key,
body.sky-on #geo-hint,
body.sky-on #hover-tip { visibility: hidden; }

#inside-layer,
#sky-layer {
  position: absolute;
  inset: 0;
  pointer-events: none;
  z-index: 6;
}
body:not(.inside-on) #inside-layer,
body:not(.sky-on) #sky-layer { display: none; }
.inside-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: visible;
}
.inside-line {
  stroke-width: 3;
  stroke-linecap: round;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .45));
}
/* A nature marker's callout, in the marker's pink. */
.nature-line { stroke: rgba(255, 90, 200, .95); }
.nature-dot { fill: #ff5ac8; }
.inside-dot {
  stroke: rgba(30, 10, 0, .85);
  stroke-width: 2;
}
/* The same pill as a nature marker, bordered in its layer's colour (--c). */
.inside-pill {
  position: absolute;
  top: 0;
  left: 0;
  display: inline-flex;
  align-items: center;
  gap: 7px;
  margin: 0;
  padding: 8px 15px 8px 6px;
  border: none;
  border-radius: 999px;
  background: rgba(24, 16, 40, .66);
  box-shadow: 0 0 0 2.5px var(--c), 0 4px 10px rgba(0, 0, 0, .35);
  backdrop-filter: blur(4px);
  color: #fff;
  font: inherit;
  font-size: 14px;
  font-weight: 800;
  white-space: nowrap;
  cursor: pointer;
  pointer-events: auto;
  touch-action: manipulation;
  will-change: transform;
  transition: background .15s ease, color .15s ease;
}
.inside-pill:hover { background: rgba(44, 28, 70, .85); }
.inside-pill:focus-visible { outline: 3px solid var(--sun); outline-offset: 3px; }
/* The layer whose card is open fills with its colour. */
.inside-pill.is-picked { background: var(--c); color: #2a1600; }

/* ---- The Sky ----------------------------------------------------------------
   The same pills as Inside. A deep blue or violet pill takes white writing
   when it fills (--ink, set in js/ui.js). */
.sky-pill { background: rgba(10, 16, 44, .7); }
.sky-pill:hover { background: rgba(22, 34, 84, .88); }
.sky-pill.is-picked { color: var(--ink, #fff); }
/* The emoji's circle: a light tint of its layer's colour (--tint, from js/ui.js). */
.sky-pill .marker-dot { background: var(--tint, rgba(255, 255, 255, .92)); }
/* The Space Station and the plane, going round the rings. */
.sky-mover {
  position: absolute;
  top: 0;
  left: 0;
  font-size: 18px;
  line-height: 1;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, .5));
  will-change: transform;
}
/* "🚀 Space starts here", on the dashed 100 km line. */
.sky-space {
  position: absolute;
  top: 0;
  left: 0;
  padding: 2px 8px;
  border-radius: 999px;
  background: rgba(10, 16, 44, .62);
  color: #fff;
  font-size: 11px;
  font-weight: 800;
  white-space: nowrap;
}

#hover-tip {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 25;
  padding: 7px 13px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .96);
  color: var(--ink);
  font-size: 15px;
  font-weight: 800;
  box-shadow: var(--shadow);
  pointer-events: none;
  white-space: nowrap;
}

/* ==========================================================================
   Compass — positioned by js/ui.js (left/top/size): right of the title, or
   bottom-left on an upright window
   ========================================================================== */

.compass {
  --cmp-size: 104px;
  position: fixed;
  /* Over the top bar, which it sits in on a wide window, and still under
     the cards (40); the photos (22) stay under it, as before. */
  z-index: 31;
  left: 0;
  top: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  margin: 0;
  padding: 0;
  border: none;
  background: none;
  color: #fff;
  font: inherit;
  cursor: pointer;
  touch-action: manipulation;
  -webkit-tap-highlight-color: transparent;
}

.compass-dial {
  display: block;
  width: var(--cmp-size);
  height: var(--cmp-size);
  border-radius: 50%;
  box-shadow: 0 10px 24px rgba(4, 10, 36, .45), 0 0 0 5px rgba(255, 255, 255, .14);
  transition: transform .18s cubic-bezier(.3, 1.6, .5, 1), box-shadow .18s ease;
}
.compass-dial svg { display: block; width: 100%; height: 100%; }

.compass:hover .compass-dial {
  transform: translateY(-3px) scale(1.06);
  box-shadow: 0 14px 28px rgba(4, 10, 36, .5), 0 0 0 6px rgba(255, 201, 60, .35);
}
.compass:active .compass-dial { transform: scale(.92); transition-duration: .08s; }
.compass:focus-visible { outline: none; }
.compass:focus-visible .compass-dial { box-shadow: 0 0 0 5px var(--sun), 0 10px 24px rgba(4, 10, 36, .45); }

/* A little happy wobble when it straightens the globe. */
.compass.is-straightening .compass-dial { animation: cmp-bounce .5s cubic-bezier(.3, 1.6, .5, 1); }
@keyframes cmp-bounce {
  0%   { transform: scale(.9); }
  55%  { transform: scale(1.1); }
  100% { transform: scale(1); }
}

.compass-caption {
  padding: 4px 11px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .15);
  backdrop-filter: blur(6px);
  font-size: 13px;
  font-weight: 800;
  white-space: nowrap;
  transition: background .2s ease, color .2s ease;
}
/* When the globe is turned away from north, the caption lights up to invite a tap. */
.compass.is-tilted .compass-caption { background: var(--sun); color: #4a3400; }
.compass.no-caption .compass-caption { display: none; }

@media (prefers-reduced-motion: reduce) {
  .compass-dial { transition: none; }
  .compass.is-straightening .compass-dial { animation: none; }
}

/* ==========================================================================
   Hint line
   ========================================================================== */

#hint {
  position: fixed;
  left: var(--map-cx);
  bottom: calc(16px + var(--map-lift));
  transform: translateX(-50%);
  z-index: 20;
  margin: 0;
  padding: 10px 20px;
  /* Its own width, not the half-screen left of `left: 50%` would give it, so
     a long hint (the Sun & Moon's) stays on one line while it fits. */
  width: max-content;
  max-width: calc(var(--map-w) - 32px);
  border-radius: 999px;
  background: rgba(255, 255, 255, .14);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 16px;
  font-weight: 700;
  text-align: center;
  pointer-events: none;
}
.hint-sub {
  display: block;
  margin-top: 2px;
  font-size: 13px;
  font-weight: 600;
  opacity: .82;
}

/* ==========================================================================
   Depth key — the light-to-dark strip shown while the Oceans layer is on
   ========================================================================== */

#depth-key {
  position: fixed;
  left: var(--map-cx);
  bottom: calc(74px + var(--map-lift));
  transform: translateX(-50%);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .14);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  pointer-events: none;
}
/* The same ramp the globe is painted with, shallow on the left. */
.key-strip {
  width: 92px;
  height: 12px;
  border-radius: 999px;
  background: linear-gradient(to right, #4db8ea, #1e92d6, #176fb4, #134f90, #0f356d, #0b1c41);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .45);
}

/* The Currents step: the strip and its words make way for the two arrows. */
.key-current { display: none; align-items: center; gap: 6px; }
/* Each sample is a small copy of a current on the globe: a band of thin
   streaks, faint at the back and bright at the head, strongest in the middle
   and fading out to both edges, with a small open "›" after it. */
.key-current i {
  --c: #ff5a36;
  --c2: rgba(255, 90, 54, .6);
  --c3: rgba(255, 90, 54, .25);
  position: relative;
  width: 30px;
  height: 11px;
  margin-right: 5px;
}
/* Five thin lines, the middle one strongest, fading out to both edges.
   Plain stacked gradients rather than a mask: the key sits over the moving
   globe and is composited every frame, and a mask made that cost a frame or
   two a second. */
.key-current i::before {
  content: "";
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to right, transparent, var(--c) 70%, #fff) 0 50% / 100% 1.4px no-repeat,
    linear-gradient(to right, transparent, var(--c2)) 0 25% / 88% 1.2px no-repeat,
    linear-gradient(to right, transparent, var(--c2)) 0 75% / 92% 1.2px no-repeat,
    linear-gradient(to right, transparent, var(--c3)) 0 0 / 80% 1px no-repeat,
    linear-gradient(to right, transparent, var(--c3)) 0 100% / 84% 1px no-repeat;
}
.key-current i::after {
  content: "";
  position: absolute;
  right: -4px;
  top: 50%;
  width: 5px;
  height: 5px;
  border-top: 1.5px solid var(--c);
  border-right: 1.5px solid var(--c);
  transform: translateY(-50%) rotate(45deg);
}
.key-current.is-cold i { --c: #b4f3ff; --c2: rgba(180, 243, 255, .6); --c3: rgba(180, 243, 255, .25); }
#depth-key.is-currents .key-strip,
#depth-key.is-currents .key-text { display: none; }
#depth-key.is-currents .key-current { display: inline-flex; }

/* The Sea Life step: a coral patch like the ones on the water, and three
   dots in a row, getting brighter, for an animal on its way somewhere. */
.key-sea { display: none; align-items: center; gap: 6px; }
#depth-key.is-sealife .key-strip,
#depth-key.is-sealife .key-text { display: none; }
#depth-key.is-sealife .key-sea { display: inline-flex; }
.key-sea.is-reef i {
  width: 18px;
  height: 13px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 50%, #ff8a80 0 35%, rgba(255, 150, 100, .75) 60%, rgba(255, 160, 110, 0) 100%);
}
.key-sea.is-trip i {
  width: 24px;
  height: 6px;
  background:
    radial-gradient(circle, #fff 0 2.4px, transparent 3px) 100% 50% / 8px 6px no-repeat,
    radial-gradient(circle, rgba(255, 255, 255, .6) 0 2.2px, transparent 2.8px) 50% 50% / 8px 6px no-repeat,
    radial-gradient(circle, rgba(255, 255, 255, .3) 0 2px, transparent 2.6px) 0 50% / 8px 6px no-repeat;
}

/* Nature mode's key: five swatches, same pill as the depth key. The colours
   are the ones NATURE_COLORS paints with, in js/globe.js. */
#nature-key {
  position: fixed;
  left: var(--map-cx);
  bottom: calc(74px + var(--map-lift));
  transform: translateX(-50%);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .14);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 13px;
  font-weight: 700;
  white-space: nowrap;
  pointer-events: none;
}
.nk { display: inline-flex; align-items: center; gap: 5px; }
.nk i {
  width: 13px;
  height: 13px;
  border-radius: 4px;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .25);
}
/* Nature mode and the Oceans overlay can be on together, and both want the
   line above the hint. The nature key comes second in the markup, so it is
   the one that moves up. */
#depth-key:not([hidden]) ~ #nature-key { bottom: calc(120px + var(--map-lift)); }

/* The Sun & Moon step's key: a bright swatch and a dark one, same pill again.
   It can share the line above the hint with the other two keys, and comes
   after them in the markup, so it is the one that moves up. */
#sun-key {
  position: fixed;
  left: var(--map-cx);
  bottom: calc(74px + var(--map-lift));
  transform: translateX(-50%);
  z-index: 20;
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .14);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  pointer-events: none;
}
#sun-key .nk i { width: 16px; height: 16px; border-radius: 50%; }
#sun-key .is-day { background: #ffe27a; box-shadow: 0 0 6px #ffd54f, inset 0 0 0 1px rgba(0, 0, 0, .15); }
#sun-key .is-night { background: #1b2a55; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .5); }
#depth-key:not([hidden]) ~ #sun-key,
#nature-key:not([hidden]) ~ #sun-key { bottom: calc(120px + var(--map-lift)); }
#depth-key:not([hidden]) ~ #nature-key:not([hidden]) ~ #sun-key { bottom: calc(166px + var(--map-lift)); }
/* Just above phone width the Sun's hint, the longest, would break over two
   lines and run into the keys, so it is a little smaller there. */
@media (min-width: 621px) and (max-width: 760px) {
  #hint.is-long { font-size: 14px; }
}

/* ==========================================================================
   The Seasons — the month bar, the pole labels, the trip picture
   ========================================================================== */

/* The bar takes the hint's and the Sun key's place along the bottom, with
   its own hint and a key that adds the "Sun right overhead" line. */
body.seasons-on #hint,
body.seasons-on #sun-key { display: none; }
/* The depth and nature keys stack above the bar (js/ui.js keeps --season-h). */
body.seasons-on #depth-key,
body.seasons-on #nature-key { bottom: calc(var(--season-h, 170px) + 20px + var(--map-lift)); }
body.seasons-on #depth-key:not([hidden]) ~ #nature-key { bottom: calc(var(--season-h, 170px) + 64px + var(--map-lift)); }

#season-bar {
  position: fixed;
  left: var(--map-cx);
  bottom: calc(12px + var(--map-lift));
  transform: translateX(-50%);
  z-index: 20;
  width: min(900px, calc(var(--map-w) - 24px));
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}
#season-bar[hidden] { display: none; }
#season-hint {
  margin: 0;
  color: #fff;
  font-size: 15px;
  font-weight: 700;
  text-align: center;
  text-shadow: 0 2px 6px rgba(0, 0, 0, .55);
}
.season-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 8px;
}
/* The month and the two halves' seasons, as tags round the globe: the
   Inside callout's line and dot, on a plain white pill. Summer's is warm,
   winter's cool; spring and autumn stay white. */
#season-layer {
  position: absolute;
  inset: 0;
  z-index: 6;
  pointer-events: none;
}
#season-layer[hidden] { display: none; }
.season-tag {
  position: absolute;
  top: 0;
  left: 0;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .95);
  box-shadow: 0 4px 10px rgba(8, 18, 48, .3);
  color: var(--ink);
  font-size: 15px;
  font-weight: 800;
  white-space: nowrap;
  will-change: transform;
}
.season-tag[hidden] { display: none; }
.season-tag[data-season="summer"] { background: #fff1c7; box-shadow: 0 0 0 2px #ffc94a, 0 4px 10px rgba(8, 18, 48, .3); }
.season-tag[data-season="winter"] { background: #e4f2ff; box-shadow: 0 0 0 2px #8fc8ff, 0 4px 10px rgba(8, 18, 48, .3); }
.season-line { stroke: rgba(255, 255, 255, .95); stroke-width: 2.5; }
.season-dot { fill: #fff; }
.season-dot.is-summer { fill: #ffc94a; }
.season-dot.is-winter { fill: #8fc8ff; }
.season-dot.is-spring { fill: #7ed957; }
.season-dot.is-autumn { fill: #ff9f5a; }
#season-key {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 7px 14px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .14);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
}
#season-key .nk { font-size: 14px; gap: 6px; }
#season-key .nk i { width: 16px; height: 16px; border-radius: 50%; }
#season-key .is-day { background: #ffe27a; box-shadow: 0 0 6px #ffd54f, inset 0 0 0 1px rgba(0, 0, 0, .15); }
#season-key .is-night { background: #1b2a55; box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .5); }
#season-key .nk i.is-line { width: 20px; height: 5px; border-radius: 3px; background: #ffe06e; box-shadow: 0 0 6px #ffd54f; }
#season-months {
  display: flex;
  gap: 6px;
  align-items: center;
  width: 100%;
  padding: 10px 8px 8px;
  border-radius: 22px;
  background: rgba(255, 255, 255, .94);
  box-shadow: 0 6px 18px rgba(8, 18, 48, .28);
  overflow-x: auto;
  scrollbar-width: none;
  pointer-events: auto;
}
#season-months::-webkit-scrollbar { display: none; }
#season-play {
  flex: 0 0 auto;
  min-height: 56px;
  padding: 0 16px;
  border: none;
  border-radius: 16px;
  background: linear-gradient(135deg, #ffd54f 0%, #ff9f1c 100%);
  color: #4a2a00;
  font: inherit;
  font-size: 16px;
  font-weight: 800;
  white-space: nowrap;
  cursor: pointer;
}
#season-play.is-playing { background: linear-gradient(135deg, #ffe9a8 0%, #ffc56b 100%); }
.month-chip {
  flex: 1 0 54px;
  min-height: 56px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 1px;
  padding: 4px 2px;
  border: none;
  border-radius: 14px;
  background: #eef1fb;
  color: var(--ink);
  font: inherit;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.1;
  cursor: pointer;
  transition: transform .15s, background .15s, box-shadow .15s;
}
.mc-emoji { font-size: 20px; line-height: 1.1; }
.month-chip.is-on {
  background: linear-gradient(135deg, #fff3c4 0%, #ffd27a 100%);
  transform: translateY(-3px);
  box-shadow: 0 4px 10px rgba(8, 18, 48, .22), inset 0 0 0 2px #ffb938;
}

/* "North Pole" / "South Pole" at the ends of the lean stick. */
.pole-pill {
  position: absolute;
  top: 0;
  left: 0;
  z-index: 6;
  padding: 3px 10px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .92);
  box-shadow: 0 2px 6px rgba(8, 18, 48, .3);
  color: var(--ink);
  font-size: 12px;
  font-weight: 800;
  white-space: nowrap;
  pointer-events: none;
}
.pole-pill[hidden] { display: none; }

/* The little picture of the Earth going round the Sun: on the right of the
   globe's space, level with its middle on a wide window, or in the bottom
   corner above the bar on an upright one. A picture only; it goes rather
   than cover the globe or a tag. */
#season-trip {
  position: fixed;
  right: calc(100vw - var(--map-cx) - var(--map-w) / 2 + 14px);
  bottom: calc(var(--season-h, 170px) + 22px + var(--map-lift));
  z-index: 19;
  width: 190px;
  padding: 8px 10px 4px;
  border-radius: 18px;
  background: rgba(255, 255, 255, .92);
  box-shadow: 0 4px 14px rgba(8, 18, 48, .25);
  text-align: center;
  pointer-events: none;
}
#season-trip[hidden] { display: none; }
/* On a wide window: on the right edge, level with the globe's middle (js/ui.js sets top). */
#season-trip.is-mid { bottom: auto; transform: translateY(-50%); }
#season-trip.is-covering { visibility: hidden; }
#season-trip p { margin: 0; color: var(--ink); font-size: 13px; font-weight: 800; }
#season-trip svg { display: block; width: 100%; height: auto; }

/* The season box at the top of a country card. */
.season-box {
  margin: 0 0 14px;
  padding: 12px 14px;
  border-radius: 16px;
  background: linear-gradient(135deg, #eaf6ff 0%, #fff4d6 100%);
  box-shadow: inset 0 0 0 2px rgba(255, 185, 56, .35);
}
.season-box[hidden] { display: none; }
.season-box p { margin: 0; }
.sb-title { font-size: 19px; font-weight: 800; line-height: 1.25; }
.sb-text { margin-top: 6px !important; font-size: 15px; line-height: 1.4; color: var(--ink-soft); }
.sb-chips { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.sb-fact {
  margin-top: 10px !important;
  padding: 8px 10px;
  border-radius: 12px;
  background: #fff6d6;
  font-size: 14px;
  line-height: 1.4;
}

@media (max-width: 620px) {
  #season-bar { width: calc(var(--map-w) - 16px); gap: 6px; }
  #season-hint { display: none; }
  .season-tag { font-size: 13px; padding: 5px 11px; }
  #season-key { gap: 8px; padding: 5px 10px; }
  #season-key .nk { font-size: 12px; gap: 4px; }
  #season-key .nk i { width: 13px; height: 13px; }
  #season-key .nk i.is-line { width: 16px; height: 4px; }
  #season-months { padding: 8px 6px 6px; }
  #season-play { font-size: 15px; padding: 0 12px; }
  .month-chip { flex: 0 0 54px; }
  #season-trip { width: 130px; padding: 5px 6px 2px; bottom: calc(var(--season-h, 150px) + 14px + var(--map-lift)); }
  #season-trip p { font-size: 11px; }
}
@media (prefers-reduced-motion: reduce) {
  .month-chip { transition: none; }
}

/* The one-time grid hint: same frosted pill as the keys, stacked above
   whichever of them are showing (it comes last in the markup, so it is the
   one that moves up). It fades in and out on its own; see UI.showGeoHint. */
#geo-hint {
  position: fixed;
  left: var(--map-cx);
  bottom: calc(74px + var(--map-lift));
  transform: translateX(-50%);
  z-index: 20;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: 4px 10px;
  max-width: calc(var(--map-w) - 32px);
  padding: 7px 16px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .14);
  backdrop-filter: blur(6px);
  color: #fff;
  font-size: 14px;
  font-weight: 700;
  text-align: center;
  pointer-events: none;
  opacity: 0;
  transition: opacity .5s ease;
}
#geo-hint.is-shown { opacity: 1; }
.geo-hint-dot { opacity: .6; }
#depth-key:not([hidden]) ~ #geo-hint,
#nature-key:not([hidden]) ~ #geo-hint { bottom: calc(120px + var(--map-lift)); }
#depth-key:not([hidden]) ~ #nature-key:not([hidden]) ~ #geo-hint { bottom: calc(166px + var(--map-lift)); }

/* ==========================================================================
   Nature photos — three photos of the natural place whose card is open.
   Floats bottom-left where js/ui.js (layoutPhotoBox) finds room, and moves
   to the top of the card body (.is-inline) where it does not.
   ========================================================================== */

.photo-box {
  position: fixed;
  z-index: 22;                         /* over the keys, under the compass and card */
  width: var(--pb-w, 320px);
  padding: 6px;
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: var(--shadow);
  animation: pb-in .3s ease;
}
@keyframes pb-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

.pb-frame {
  position: relative;
  height: var(--pb-h, 220px);
  overflow: hidden;
  border-radius: 16px;
  background: #e4e9f5;
  touch-action: pan-y;                 /* sideways is a swipe; up and down still scrolls */
  user-select: none;
  -webkit-user-select: none;
}
.pb-photos img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity .35s ease;
}
.pb-photos img.is-on { opacity: 1; }

/* The credit every photo must carry: tiny, over a soft shadow at the bottom. */
.pb-credit {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  margin: 0;
  padding: 16px 12px 5px;
  background: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, .55));
  color: #fff;
  font-size: 11px;
  font-weight: 600;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  pointer-events: none;
}

.pb-arrow {
  position: absolute;
  top: 50%;
  width: 48px;
  height: 48px;
  margin-top: -24px;
  padding: 0 0 4px;
  border: none;
  border-radius: 50%;
  background: rgba(255, 255, 255, .9);
  color: var(--ink);
  font: inherit;
  font-size: 34px;
  font-weight: 800;
  line-height: 1;
  box-shadow: 0 4px 12px rgba(8, 18, 48, .3);
  cursor: pointer;
  transition: transform .1s ease, background .15s ease;
}
.pb-arrow:hover { background: #fff; }
.pb-arrow:active { transform: scale(.9); }
.pb-arrow:focus-visible { outline: 4px solid var(--sun); outline-offset: 2px; }
.pb-prev { left: 8px; }
.pb-next { right: 8px; }

.pb-dots {
  display: flex;
  justify-content: center;
  gap: 8px;
  padding: 7px 0 2px;
}
.pb-dots i {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: #c9cfe3;
  transition: background .2s ease, transform .2s ease;
}
.pb-dots i.is-on { background: var(--grape); transform: scale(1.3); }

/* In the card (phones, and anywhere the corner has no room): full card width. */
.photo-box.is-inline {
  position: static;
  width: auto;
  margin: 0 0 14px;
  padding: 0;
  background: none;
  box-shadow: none;
  animation: none;
}
.photo-box.is-inline .pb-frame { height: auto; aspect-ratio: 16 / 10; }

@media (prefers-reduced-motion: reduce) {
  .photo-box { animation: none; }
  .pb-photos img, .pb-dots i { transition: none; }
}

/* ==========================================================================
   Info card
   ========================================================================== */

/* Several elements below set their own display (flex, grid); make sure the
   hidden attribute still wins over them. */
[hidden] { display: none !important; }

/* Header stays put; only .card-body scrolls. The card uses the full height
   down to near the bottom of the window instead of stopping short.
   The lesson player docks in exactly the same place (.lp-stage). */
#info-card,
.lp-stage {
  position: fixed;
  z-index: 40;
  top: var(--dock-top);
  right: var(--dock-gap);
  width: var(--dock-w);
  max-height: var(--dock-max-h);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: var(--radius);
  background: var(--paper);
  box-shadow: var(--shadow);
}

.card-header {
  flex: none;
  padding: 16px 16px 14px 22px;
  border-bottom: 2px solid #f0f2f8;
}

.card-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;        /* scrolling the card never drags the page */
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  padding: 16px 22px 28px;             /* room below the last row */
  scrollbar-width: thin;
  scrollbar-color: #c9cfe3 transparent;
}
.card-body::-webkit-scrollbar { width: 10px; }
.card-body::-webkit-scrollbar-thumb {
  background: #c9cfe3;
  border-radius: 10px;
  border: 3px solid #fff;
}

/* "There's more below" fade over the bottom edge while scrolling is possible. */
.card-fade {
  position: absolute;
  left: 0;
  right: 12px;
  bottom: 0;
  height: 46px;
  border-radius: 0 0 var(--radius) var(--radius);
  background: linear-gradient(to bottom, rgba(255, 255, 255, 0), #fff 85%);
  pointer-events: none;
  opacity: 0;
  transition: opacity .2s ease;
}
#info-card.can-scroll .card-fade { opacity: 1; }

.card-back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  min-height: 38px;
  margin: 0 0 12px -6px;
  padding: 0 14px 0 10px;
  border: none;
  border-radius: 999px;
  background: #eef1f9;
  color: #35406b;
  font: inherit;
  font-size: 15px;
  font-weight: 800;
  cursor: pointer;
  transition: background .15s ease, transform .1s ease;
}
.card-back:hover { background: #e2e7f6; }
.card-back:active { transform: scale(.96); }
.card-back:focus-visible { outline: 4px solid var(--sun); outline-offset: 2px; }

#info-card.pop { animation: pop .34s cubic-bezier(.2, 1.35, .45, 1); }
@keyframes pop {
  0%   { transform: scale(.82) translateY(10px); opacity: 0; }
  100% { transform: scale(1) translateY(0); opacity: 1; }
}

.card-close {
  width: 40px;
  height: 40px;
  border: none;
  border-radius: 50%;
  background: #eef1f9;
  color: var(--ink-soft);
  font-size: 17px;
  font-weight: 800;
  cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.card-close:hover { background: var(--coral); color: #fff; }
.card-close:focus-visible { outline: 4px solid var(--sun); outline-offset: 2px; }

/* Three columns: flag | name + chip | close. The middle column can shrink
   and wrap, the other two never move, so nothing can overlap the name. */
.card-head {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 14px;
}
.card-close { align-self: start; }
.card-flag {
  font-size: 46px;
  line-height: 1;
  filter: drop-shadow(0 3px 5px rgba(0, 0, 0, .18));
}
/* Real flag image — same size, shape and spot as the old badge. The thin dark
   inner outline plus shadow keeps mostly-white flags (Japan, Cyprus...)
   readable against the white card. */
.card-flag.is-image {
  position: relative;
  width: 62px;
  height: 44px;
  border-radius: 9px;
  overflow: hidden;
  background: #eef1f9;
  box-shadow: 0 3px 8px rgba(0, 0, 0, .22);
  filter: none;
}
.card-flag.is-image::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1.5px rgba(23, 34, 74, .22);
  pointer-events: none;
}
/* A sea animal with no emoji: a round photo of it in the flag's place. */
.card-flag.is-image.is-round {
  width: 54px;
  height: 54px;
  border-radius: 50%;
}
.flag-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.tip-flag {
  width: 22px;
  height: 16px;
  margin-right: 8px;
  border-radius: 3px;
  object-fit: cover;
  vertical-align: -3px;
  box-shadow: 0 0 0 1px rgba(23, 34, 74, .25);
}

/* Last-resort fallback only: shown if a flag image fails to load on a
   platform with no flag emoji font (Windows). */
.card-flag.is-badge {
  display: grid;
  place-content: center;
  width: 62px;
  height: 44px;
  border-radius: 9px;
  background: linear-gradient(135deg, #5b8def, #7b6cf6);
  border: 3px solid #fff;
  box-shadow: 0 3px 7px rgba(0, 0, 0, .25);
  color: #fff;
  font-size: 19px;
  font-weight: 800;
  letter-spacing: 1px;
}

.tip-badge {
  display: inline-block;
  margin-right: 7px;
  padding: 2px 7px;
  border-radius: 5px;
  background: linear-gradient(135deg, #5b8def, #7b6cf6);
  color: #fff;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .5px;
  vertical-align: 1px;
}

.card-head-text {
  min-width: 0;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 7px;
}
#card-title {
  margin: 0;
  font-size: clamp(23px, 4.6vw, 29px);
  font-weight: 800;
  line-height: 1.12;
  color: var(--ink);
  overflow-wrap: anywhere;
}
/* Water names run long in a single word — "Mediterranean" alone is wider than
   the title column, and overflow-wrap would snap it mid-word. A step down in
   size fits the longest of them whole, and countries keep their own sizing. */
#info-card[data-view="water"] #card-title,
/* Subdivision names run long too — "Autonomous Community of Andalusia". */
#info-card[data-view="province"] #card-title { font-size: clamp(21px, 4.2vw, 26px); }

.chip {
  display: inline-block;
  padding: 5px 13px;
  border: none;
  border-radius: 999px;
  background: #ece9ff;
  color: #4b3fc4;
  font: inherit;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.35;
  text-align: left;
}
.chip:disabled { cursor: default; opacity: 1; }

.chip-row {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  align-items: center;
}
/* Which hemisphere a country is in — colours match the globe's tints. */
.hemi-chip { cursor: default; }
.hemi-chip.is-north { background: #ffe6d4; color: #a3470f; }
.hemi-chip.is-south { background: #d6f8ef; color: #0f6e58; }
.hemi-chip.is-both  { background: linear-gradient(90deg, #ffe6d4, #d6f8ef); color: #5a4a2a; }

/* In the continent view the chip slot holds a subtitle ("52 countries,
   biggest to smallest"). Plain text, so it doesn't look like a button. */
#info-card[data-view="continent-list"] .chip {
  padding: 0;
  background: none;
  color: var(--ink-soft);
  font-size: 15px;
  font-weight: 700;
}

/* The continent chip on a country card opens that continent's country list. */
.chip.is-link {
  cursor: pointer;
  box-shadow: 0 2px 0 #d6d0ff;
  transition: background .15s ease, transform .1s ease, box-shadow .15s ease;
}
.chip.is-link::after { content: " ›"; font-size: 16px; line-height: 0; }
.chip.is-link:hover { background: #ddd7ff; }
/* The "what is inside this country" chip, in the violet its borders are
   drawn in, so the chip and the lines on the globe read as one idea. */
.prov-chip { background: #f0e2ff; color: #6b2fa8; }
.prov-chip.is-link { box-shadow: 0 2px 0 #dcc4f5; }
.prov-chip.is-link:hover { background: #e7d3ff; }
.chip.is-link:active { transform: translateY(2px); box-shadow: none; }
.chip:focus-visible { outline: 4px solid var(--sun); outline-offset: 2px; }

/* ---- continent view: country list, biggest first ---- */
.country-list {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 8px;
}
.country-row {
  display: grid;
  grid-template-columns: 26px auto minmax(0, 1fr) auto;
  align-items: center;
  column-gap: 12px;
  width: 100%;
  min-height: 60px;
  padding: 9px 12px 9px 8px;
  border: 2px solid transparent;
  border-radius: 16px;
  background: #f2f6ff;
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background .15s ease, border-color .15s ease, transform .1s ease;
  touch-action: pan-y;
}
.country-row:hover { background: #fff4cc; border-color: #ffd21f; }
.country-row:active { transform: scale(.98); }
.country-row:focus-visible { outline: 4px solid var(--sun); outline-offset: 2px; }

.row-rank {
  justify-self: end;
  font-size: 14px;
  font-weight: 800;
  color: #9aa3c2;
}
.row-flag {
  position: relative;
  display: grid;
  place-content: center;
  width: 46px;
  height: 33px;
  border-radius: 7px;
  overflow: hidden;
  background: #e3e8f5;
  box-shadow: 0 2px 5px rgba(0, 0, 0, .18);
}
.row-flag::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: inherit;
  box-shadow: inset 0 0 0 1px rgba(23, 34, 74, .22);
}
.row-flag img { width: 100%; height: 100%; object-fit: cover; display: block; }
.row-flag.is-badge { font-size: 13px; font-weight: 800; color: #4b3fc4; }
/* A sea has no flag, so its emoji sits in the same square. */
.row-flag.is-emoji { font-size: 21px; background: #d8ecfb; }
.row-text { min-width: 0; display: flex; flex-direction: column; }
.row-name {
  font-size: 17px;
  font-weight: 800;
  line-height: 1.2;
  overflow-wrap: anywhere;
}
.row-area {
  margin-top: 2px;
  font-size: 13px;
  font-weight: 600;
  color: #7c86a8;
}
.row-go {
  font-size: 24px;
  font-weight: 800;
  color: #b5bdd6;
}
.country-row:hover .row-go { color: #e0a800; }

/* Capital / Language / Animals / Climate / Currency / Invented */
.card-info {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 8px;
}
/* Plain text flow (not flex), so a long value wraps right after its label
   instead of dropping onto its own line. */
.info-row {
  display: block;
  padding: 10px 15px;
  border-radius: 14px;
  background: #f2f6ff;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.35;
  color: #35406b;
}
.info-icon { margin-right: 4px; }
.info-value { font-weight: 800; }

/* A gap in the data: still shown, but visibly a placeholder. */
.info-row.is-missing {
  background: #f6f6f8;
  border: 2px dashed #d5d9e6;
  padding: 8px 13px;
}
.info-row.is-missing .info-value {
  font-weight: 600;
  font-style: italic;
  color: #8a93b3;
}

.facts-heading {
  margin: 20px 0 10px;
  font-size: 18px;
  font-weight: 800;
  color: var(--ink);
}

.facts {
  margin: 0;
  padding: 0;
  list-style: none;
  display: grid;
  gap: 11px;
}
.facts li {
  position: relative;
  padding: 13px 15px 13px 44px;
  border-radius: 16px;
  background: #fff7e2;
  font-size: 17px;
  font-weight: 600;
  line-height: 1.42;
  color: #4a3f21;
}
.facts li::before {
  content: "⭐";
  position: absolute;
  left: 14px;
  top: 12px;
  font-size: 18px;
}
.facts li:nth-child(even) { background: #e6fbf3; color: #1f4b41; }
.facts li:nth-child(even)::before { content: "🌟"; }

/* A layer of the Earth: one short paragraph in place of the fact list, and
   the big emoji on a disc of the layer's colour (--layer-c). */
.card-blurb {
  margin: 2px 0 0;
  padding: 14px 16px;
  border-radius: 16px;
  background: #fff3e4;
  color: #4a2c16;
  font-size: 18px;
  font-weight: 600;
  line-height: 1.45;
}
#info-card[data-view="layer"] .facts-heading,
#info-card[data-view="layer"] .facts { display: none; }
#info-card[data-view="layer"] .card-flag {
  display: grid;
  place-content: center;
  width: 62px;
  height: 62px;
  border-radius: 50%;
  background: var(--layer-c);
  box-shadow: inset 0 0 0 3px rgba(255, 255, 255, .55), 0 3px 8px rgba(0, 0, 0, .2);
  font-size: 36px;
  filter: none;
}
#info-card[data-view="layer"] .chip { background: #ffeedd; color: #9a3a0e; }

/* A layer of the sky: the same card in blues, with its place in the order
   under the title and a footnote under the paragraph. */
/* Over a layer of the atmosphere's title: "Earth's atmosphere (its blanket of air)". */
.card-kicker {
  margin: 0 0 -3px;
  color: #1d4f8a;
  font-size: 14px;
  font-weight: 800;
  line-height: 1.25;
}
.card-sub {
  margin: -3px 0 0;
  color: #7a8394;
  font-size: 14px;
  font-weight: 700;
}
.card-footnote {
  margin: 10px 2px 0;
  color: #7a8394;
  font-size: 13px;
  font-weight: 600;
  line-height: 1.4;
}
#info-card.is-sky .card-blurb { background: #e8f5ff; color: #173a5e; }
#info-card.is-sky .chip { background: #e0f0ff; color: #1d4f8a; }

/* The Sun and the Moon: the same card in sunny yellows, with its "Did you
   know?" line, and the size note moved under it. */
#info-card.is-space #country-view { display: flex; flex-direction: column; }
#info-card.is-space .facts-heading,
#info-card.is-space .facts { display: block; }
#info-card.is-space #card-footnote { order: 1; }
#info-card.is-space .card-blurb { background: #fff8dc; color: #4a3400; }
#info-card.is-space .chip { background: #fff1c2; color: #7a4a00; }

.card-hint {
  margin: 16px 0 0;
  font-size: 14px;
  font-weight: 600;
  color: var(--ink-soft);
  text-align: center;
}

/* ==========================================================================
   Loading
   ========================================================================== */

#loading {
  position: fixed;
  inset: 0;
  z-index: 60;
  display: grid;
  place-content: center;
  justify-items: center;
  gap: 14px;
  background: var(--sky-1);
  color: #fff;
  font-size: 19px;
  font-weight: 700;
  transition: opacity .45s ease, visibility .45s ease;
}
/* Stop swallowing taps the moment it starts fading — otherwise an eager tap
   during the half-second fade-out lands on the overlay instead of the globe. */
#loading.gone { opacity: 0; visibility: hidden; pointer-events: none; }
.spinner {
  font-size: 62px;
  animation: spin 1.7s linear infinite;
}
@keyframes spin {
  from { transform: rotate(0deg); }
  to   { transform: rotate(360deg); }
}

/* ==========================================================================
   Narrow screens / phones — card becomes a bottom sheet
   ========================================================================== */

/* Tablet-ish widths still show the button labels, and six labelled buttons is
   a tight fit — on an 820px tablet the row has only a few pixels to spare.
   Trimming the padding buys back about 70px, so the row stays on one line
   even where the fallback font runs wider than the one we ask for. */
@media (min-width: 621px) and (max-width: 950px) {
  #controls { gap: 8px; }
  .ctrl { padding: 0 11px; }
  .ctrl-wide { padding: 0 12px; }
}
/* Below about 720px the labelled row no longer fits, and "🌤️ Atmosphere" is
   the longest label of all. Only this label shrinks, a little with the width
   and never below 13px, and every button gives up some side padding first, so
   the row still stays on one line down to 621px (where the labels go). */
@media (min-width: 621px) and (max-width: 719px) {
  #topbar { padding-left: 12px; padding-right: 12px; }
  #controls { gap: 6px; }
  .ctrl { gap: 5px; }
  .ctrl, .ctrl-wide { padding: 0 7px; }
  #btn-equator[data-step="sky"] { padding: 0 5px; }
  /* 17px at 719px, down in a straight line to 13px at 621px. */
  #btn-equator[data-step="sky"] .ctrl-text { font-size: clamp(13px, calc(13px + (100vw - 621px) * .0408), 17px); }
}

@media (max-width: 620px) {
  #topbar { padding-left: 12px; padding-right: 12px; }
  .logo { font-size: 20px; width: 100%; }
  /* Six buttons is one more than this row used to hold. The labels are
     already gone at this width, so the space comes out of the padding and the
     gaps instead — which keeps all six on one line down to a 360px phone
     rather than letting the row wrap. Targets stay 48×50. */
  #controls { gap: 8px; }
  .ctrl { min-width: 48px; min-height: 50px; font-size: 15px; padding: 0 9px; }
  .ctrl-text { display: none; }
  .ctrl-wide { padding: 0 9px; }

  #info-card {
    top: auto;
    right: 10px;
    left: 10px;
    bottom: calc(10px + var(--safe-b));
    width: auto;
    max-height: 60vh;
  }
  .card-header { padding: 12px 12px 10px 16px; }
  .card-body { padding: 12px 16px 24px; }
  #card-title { font-size: 22px; }
  .country-row { min-height: 54px; }
  .row-name { font-size: 16px; }
  #hint { display: none; }
  .info-row { font-size: 15px; padding: 8px 12px; }
  .info-row.is-missing { padding: 6px 10px; }
  .map-label.is-country { font-size: 12px; }
  .water-label.is-ocean { font-size: 13px; letter-spacing: 2px; }
  .water-label.is-sea { font-size: 11.5px; letter-spacing: 1.2px; }
  .current-label { font-size: 12px; }
  /* The hint is gone at this width, so the key takes the bottom line for
     itself. The info card sits above it when one is open. */
  #depth-key,
  #nature-key {
    bottom: calc(10px + var(--map-lift));
    font-size: 13px;
    padding: 6px 12px;
  }
  .key-strip { width: 74px; height: 10px; }
  /* Five swatches will not fit on a phone with words beside them, so the
     words go and the swatches stay — the colours are the message. */
  #nature-key { gap: 7px; }
  .nk { font-size: 0; gap: 0; }
  .nk i { width: 17px; height: 17px; }
  #depth-key:not([hidden]) ~ #nature-key { bottom: calc(52px + var(--map-lift)); }
  #sun-key { bottom: calc(10px + var(--map-lift)); font-size: 13px; padding: 6px 12px; }
  #sun-key .nk { font-size: 13px; gap: 5px; }
  #depth-key:not([hidden]) ~ #sun-key,
  #nature-key:not([hidden]) ~ #sun-key { bottom: calc(52px + var(--map-lift)); }
  #depth-key:not([hidden]) ~ #nature-key:not([hidden]) ~ #sun-key { bottom: calc(94px + var(--map-lift)); }
  /* On a phone the pill wraps to two lines, and stacks over the keys. */
  #geo-hint { bottom: calc(10px + var(--map-lift)); font-size: 13px; padding: 6px 12px; border-radius: 18px; }
  .geo-hint-dot { display: none; }
  #depth-key:not([hidden]) ~ #geo-hint,
  #nature-key:not([hidden]) ~ #geo-hint { bottom: calc(52px + var(--map-lift)); }
  #depth-key:not([hidden]) ~ #nature-key:not([hidden]) ~ #geo-hint { bottom: calc(94px + var(--map-lift)); }
  .nature-marker { font-size: 12px; padding: 8px 11px 8px 6px; }
  .city-marker { font-size: 12px; padding: 8px 11px 8px 6px; }
  .inside-pill { font-size: 12px; gap: 5px; padding: 7px 11px 7px 5px; }
  .inside-pill .marker-dot { width: 26px; height: 26px; font-size: 14px; }
  /* A long name can break over two lines at its soft hyphen ("Thermo-sphere"). */
  .sky-pill { padding-right: 9px; white-space: normal; text-align: left; line-height: 1.15; }
  .sky-pill .marker-name { max-width: 64px; hyphens: manual; }
  .card-blurb { font-size: 16px; padding: 11px 13px; }
  #info-card[data-view="layer"] .card-flag { width: 50px; height: 50px; font-size: 29px; }
}

@media (prefers-reduced-motion: reduce) {
  #info-card.pop { animation: none; }
  .spinner { animation: none; }
}

/* ==========================================================================
   Lessons (js/lessons.js)
   The player docks where the info card does (the shared rule above): down
   the right-hand side, or a sheet along the bottom on a phone or an upright
   tablet. The globe stays live beside it and frames itself in the space
   that is left, so the panel never covers what a step is about.
   ========================================================================== */

/* The chip on a country card, in the sun colour of the focus rings. */
.lesson-chip { background: #fff1c2; color: #7a5200; }
.lesson-chip.is-link { box-shadow: 0 2px 0 #f3d98a; }
.lesson-chip.is-link:hover { background: #ffe7a0; }

#lesson-player[hidden] { display: none; }
/* Only the panel takes taps; everything else goes through to the globe. */
#lesson-player { position: fixed; inset: 0; z-index: 50; pointer-events: none; }
.lp-stage { z-index: 50; pointer-events: auto; animation: pop .34s cubic-bezier(.2, 1.35, .45, 1); }
/* Header, guide and footer keep their height; only .lp-body scrolls, so Back
   and Next stay pinned to the bottom of the panel. */
.lp-panel {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-height: 0;
}

.lp-top {
  position: relative;
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 12px;
  padding: 14px 14px 12px 16px;
  border-bottom: 2px solid #eef0f8;
}
.lp-top-text { min-width: 0; }
.lp-top h2 {
  margin: 0;
  font-size: clamp(20px, 3.6vw, 25px);
  line-height: 1.15;
  text-wrap: balance;
  outline: none;
}
.lp-sub { color: var(--ink-soft); font-size: 14px; font-weight: 700; }
.lp-flag { width: 46px; height: 34px; border-radius: 6px; object-fit: cover; font-size: 30px; line-height: 34px; box-shadow: 0 0 0 1px rgba(23, 34, 74, .12); }
.lp-icon {
  width: 42px; height: 42px;
  border: none; border-radius: 50%;
  background: #f1f2f8; color: var(--ink-soft);
  font: inherit; font-size: 18px; font-weight: 800;
  cursor: pointer;
}
.lp-icon:hover { background: #e4e7f3; color: var(--ink); }
.lp-steps-bar { position: absolute; left: 0; right: 0; bottom: -2px; height: 4px; background: transparent; }
.lp-steps-bar span { display: block; height: 100%; background: var(--grape); border-radius: 0 4px 4px 0; transition: width .3s ease; }

.lp-body {
  flex: 1 1 auto;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  padding: 16px 20px 20px;
  font-size: 18px;
  line-height: 1.5;
}
.lp-body > * + * { margin-top: 12px; }
.lp-body p { margin: 0; }
.lp-h3 { margin: 0; font-size: 21px; line-height: 1.25; text-wrap: balance; }
.lp-text { max-width: 60ch; }
.lp-pic { font-size: 52px; line-height: 1; }
.lp-lede { color: var(--ink-soft); font-weight: 600; }
.lp-note { color: var(--ink-soft); font-size: 15px; font-weight: 700; }

.lp-foot {
  display: flex;
  justify-content: space-between;
  gap: 10px;
  padding: 12px 16px calc(12px);
  border-top: 2px solid #eef0f8;
}
.lp-btn {
  min-height: 48px;
  padding: 8px 20px;
  border: none;
  border-radius: 999px;
  background: #f1f2f8;
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  font-weight: 800;
  cursor: pointer;
}
.lp-btn:hover { background: #e4e7f3; }
.lp-primary { background: var(--sun); color: #4a3400; box-shadow: 0 3px 0 #d9a514; }
.lp-primary:hover { background: #ffd35e; }
.lp-primary:disabled { background: #eceef5; color: #a3a9c2; box-shadow: none; cursor: default; }
.lp-small { min-height: 40px; padding: 6px 16px; font-size: 15px; }
.lp-btn:focus-visible, .lp-icon:focus-visible, .lp-option:focus-visible,
.lp-card:focus-visible, .lp-module:focus-visible { outline: 4px solid var(--sun); outline-offset: 2px; }

/* Home: the module list */
.lp-meter { height: 12px; border-radius: 999px; background: #eef0f8; overflow: hidden; }
.lp-meter span { display: block; height: 100%; background: var(--mint); border-radius: 999px; }
.lp-meter-label { color: var(--ink-soft); font-size: 14px; font-weight: 800; margin-top: 6px !important; }
.lp-modules { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.lp-module {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 14px;
  width: 100%;
  padding: 12px 16px;
  border: 2px solid #eef0f8;
  border-radius: 16px;
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: border-color .15s ease, transform .1s ease;
}
.lp-module:hover { border-color: #d6d0ff; }
.lp-module:active { transform: translateY(1px); }
.lp-module.is-done { background: #f2fcf8; border-color: #c8f0e2; }
.lp-module-emoji { font-size: 30px; line-height: 1; }
.lp-module-text { display: grid; line-height: 1.25; }
.lp-module-text strong { font-size: 18px; }
.lp-module-text span { color: var(--ink-soft); font-size: 14px; font-weight: 700; }
.lp-go { color: #4b3fc4; font-weight: 800; font-size: 15px; white-space: nowrap; }
.lp-stars { color: #f0a500; font-size: 20px; letter-spacing: 1px; white-space: nowrap; }

/* Intro */
.lp-goals { margin: 0; padding-left: 1.2em; }
.lp-goals li + li { margin-top: 4px; }
.lp-teacher { border-radius: 14px; background: #f5f3ff; padding: 10px 14px; font-size: 16px; }
.lp-teacher summary { cursor: pointer; font-weight: 800; color: #4b3fc4; }
.lp-teacher p { margin-top: 8px; }

/* Questions */
.lp-options { display: grid; gap: 8px; }
.lp-option, .lp-card {
  min-height: 52px;
  padding: 10px 16px;
  border: 2px solid #e2e5f1;
  border-radius: 14px;
  background: var(--paper);
  color: var(--ink);
  font: inherit;
  font-size: 17px;
  font-weight: 700;
  line-height: 1.3;
  text-align: left;
  cursor: pointer;
}
.lp-option:hover:not(:disabled), .lp-card:hover:not(:disabled) { border-color: #b9b0ff; }
.lp-option:disabled { cursor: default; }
.lp-option.is-right, .lp-card.is-matched { border-color: var(--mint); background: #e6faf4; color: #0f6e58; }
.lp-option.is-wrong { border-color: var(--coral); background: #fff0f0; color: #a32626; }
.lp-card.is-picked { border-color: var(--grape); background: #efedff; }
.lp-card:disabled { cursor: default; }

.lp-match { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; }
.lp-col { display: grid; gap: 8px; align-content: start; }
.lp-line { display: grid; gap: 6px; margin: 0; padding-left: 1.6em; min-height: 8px; font-weight: 800; }
.lp-line .lp-card { cursor: default; }
.lp-pool { display: flex; flex-wrap: wrap; gap: 8px; }

.lp-live { min-height: 1.5em; font-size: 16px; font-weight: 700; color: var(--ink-soft); }
.lp-feedback { padding: 10px 14px; border-radius: 14px; font-size: 16px; font-weight: 600; color: var(--ink); }
.lp-feedback.is-right { background: #e6faf4; }
.lp-feedback.is-right strong { color: #0f6e58; }
.lp-feedback.is-wrong { background: #fff0f0; }
.lp-feedback.is-wrong strong { color: #a32626; }

.shake { animation: lp-shake .35s ease; }
@keyframes lp-shake {
  20%, 60% { transform: translateX(-6px); }
  40%, 80% { transform: translateX(6px); }
}

/* Finished */
.lp-trophy { display: flex; justify-content: center; gap: 8px; font-size: 56px; line-height: 1; }
.lp-trophy span { color: #e4e7f3; animation: lp-star .4s ease-out backwards; }
.lp-trophy span.on { color: #f0b400; }
@keyframes lp-star { from { transform: scale(.3); opacity: 0; } }
.lp-score { text-align: center; font-weight: 800; color: var(--ink-soft); }
.lp-words { display: grid; grid-template-columns: max-content 1fr; gap: 6px 14px; margin: 0; font-size: 16px; }
.lp-words dt { font-weight: 800; }
.lp-words dd { margin: 0; color: var(--ink-soft); }

/* Phones and upright tablets: a sheet along the bottom, a fixed 44% of the
   height so the globe above it does not jump about from step to step. */
@media (max-width: 620px), (orientation: portrait) and (max-width: 1024px) {
  .lp-stage {
    top: auto;
    left: 10px;
    right: 10px;
    bottom: calc(10px + var(--safe-b));
    width: auto;
    height: 44vh;
    height: 44dvh;
    max-height: none;
  }
}

@media (max-width: 620px) {
  .lp-body { padding: 14px 16px 16px; font-size: 17px; }
  .lp-top { padding: 12px 10px 10px 12px; gap: 10px; }
  .lp-flag { width: 38px; height: 28px; line-height: 28px; font-size: 24px; }
  .lp-match { gap: 6px; }
  .lp-option, .lp-card { font-size: 16px; padding: 8px 12px; }
  .lp-words { grid-template-columns: 1fr; }
  .lp-words dd { margin-bottom: 6px; }
}

@media (prefers-reduced-motion: reduce) {
  .lp-stage, .lp-trophy span, .shake { animation: none; }
  .lp-steps-bar span { transition: none; }
}

/* "Find it" questions: no names on the globe, no hover chip. */
body.lesson-find #label-layer,
body.lesson-find #hover-tip { visibility: hidden; }

/* Matched pairs carry the same number. */
.lp-card[data-pair]::before {
  content: attr(data-pair);
  display: inline-grid;
  place-items: center;
  width: 24px; height: 24px;
  margin-right: 8px;
  border-radius: 50%;
  background: var(--mint);
  color: #fff;
  font-size: 14px;
  font-weight: 800;
  vertical-align: 1px;
}

/* ==========================================================================
   Guide characters (js/guide.js + js/guides/*.js)
   ========================================================================== */

.guide[hidden] { display: none; }
.guide { position: absolute; z-index: 0; }
.gd-char {
  display: block;
  width: 100%;
  padding: 0;
  border: none;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.gd-char:focus-visible { outline: 4px solid var(--sun); outline-offset: 2px; border-radius: 16px; }
.gd-svg { display: block; width: 100%; height: auto; overflow: visible; }
.gd-svg g, .gd-svg path, .gd-svg ellipse { transform-box: view-box; }

/* Pop in: rise up with a springy overshoot. */
.guide.is-in .gd-char { animation: gd-pop .7s cubic-bezier(.2, 1.6, .4, 1) both; }
@keyframes gd-pop {
  0%   { transform: translateY(70%) scale(.6); opacity: 0; }
  60%  { opacity: 1; }
  100% { transform: none; }
}
/* Beside the card it slides out from behind it instead. */
.guide--card-side.is-in .gd-char { animation-name: gd-peek; }
@keyframes gd-peek {
  0%   { transform: translateX(60%) rotate(12deg); opacity: 0; }
  60%  { opacity: 1; }
  100% { transform: none; }
}

/* ---- always on: bob, sway, blink ---- */
.gd-all { animation: gd-bob 2.6s ease-in-out infinite; }
@keyframes gd-bob { 50% { transform: translateY(-3px); } }
.gd-shadow { transform-origin: 70px 162px; animation: gd-shadow 2.6s ease-in-out infinite; }
@keyframes gd-shadow { 50% { transform: scaleX(.92); } }
.gd-tail { animation: gd-sway 1.8s ease-in-out infinite alternate; }
@keyframes gd-sway { from { transform: rotate(-7deg); } to { transform: rotate(9deg); } }
.gd-eye { animation: gd-blink 4.6s infinite; }
.gd-eye + .gd-eye { animation-delay: .04s; }
@keyframes gd-blink { 0%, 93%, 100% { transform: scaleY(1); } 95.5% { transform: scaleY(.08); } }
.gd-pupil { transition: transform .12s ease-out; }

/* Arms and head spring between poses. */
.gd-arm-l, .gd-arm-r, .gd-head { transition: transform .35s cubic-bezier(.3, 1.7, .5, 1); }

/* ---- talking: the mouth flaps while the words type out ---- */
.gd-mouth-open { opacity: 0; }
.is-talking .gd-mouth-open { animation: gd-talk .28s steps(1) infinite; }
.is-talking .gd-mouth-closed { animation: gd-talk .28s steps(1) infinite reverse; }
@keyframes gd-talk { 0% { opacity: 1; } 50% { opacity: 0; } }
.is-talking .gd-head { animation: gd-nod .56s ease-in-out infinite; }
@keyframes gd-nod { 50% { transform: rotate(2.5deg); } }

/* ---- poses ---- */
[data-pose="wave"] .gd-arm-r { animation: gd-wave .36s ease-in-out 4 alternate; transform: rotate(-125deg); }
@keyframes gd-wave { from { transform: rotate(-105deg); } to { transform: rotate(-145deg); } }

[data-pose="cheer"] .gd-arm-r { transform: rotate(-135deg); }
[data-pose="cheer"] .gd-arm-l { transform: rotate(135deg); }
[data-pose="cheer"] .gd-all { animation: gd-jump .7s cubic-bezier(.3, .7, .4, 1) 2; }
@keyframes gd-jump {
  0%, 100% { transform: none; }
  15% { transform: translateY(2px) scale(1.06, .92); }
  45% { transform: translateY(-20px) scale(.96, 1.05); }
  75% { transform: translateY(0) scale(1.04, .95); }
}
[data-pose="cheer"] .gd-mouth-closed { opacity: 0; }
[data-pose="cheer"] .gd-mouth-open { opacity: 1; animation: none; }

.gd-fx-cheer, .gd-fx-oops { opacity: 0; }
[data-pose="cheer"] .gd-fx-cheer { animation: gd-sparkle 1.4s ease-out both; }
@keyframes gd-sparkle {
  0% { opacity: 0; transform: scale(.4); transform-origin: 70px 50px; }
  25% { opacity: 1; transform: scale(1.1); transform-origin: 70px 50px; }
  100% { opacity: 0; transform: scale(1.25) rotate(8deg); transform-origin: 70px 50px; }
}

[data-pose="oops"] .gd-head { transform: rotate(-10deg); }
[data-pose="oops"] .gd-arm-l { transform: rotate(38deg); }
[data-pose="oops"] .gd-arm-r { transform: rotate(-38deg); }
[data-pose="oops"] .gd-fx-oops { animation: gd-drop 1.3s ease-in both; }
@keyframes gd-drop { 0% { opacity: 0; } 20% { opacity: 1; } 100% { opacity: 0; transform: translateY(12px); } }

/* Pointing at the globe (lesson guides stand on the left, so: up and right). */
[data-pose="point"] .gd-arm-r { transform: rotate(-100deg); animation: gd-jab 1.2s ease-in-out infinite; }
@keyframes gd-jab { 50% { transform: rotate(-92deg); } }
[data-pose="point"] .gd-head { transform: rotate(6deg); }

[data-pose="look"] .gd-head { animation: gd-look 1.5s ease-in-out; }
@keyframes gd-look { 30%, 45% { transform: rotate(-8deg); } 70%, 85% { transform: rotate(8deg); } }

[data-pose="wiggle"] .gd-all { animation: gd-wiggle .6s ease-in-out; }
@keyframes gd-wiggle {
  20% { transform: rotate(-7deg) scale(1.04); }
  45% { transform: rotate(6deg); }
  70% { transform: rotate(-3deg); }
}
[data-pose="wiggle"] .gd-eye { animation: none; transform: scaleY(.15); }

/* ---- speech bubble ---- */
.gd-bubble {
  position: absolute;
  z-index: 2;
  width: max-content;
  padding: 10px 14px 11px;
  border-radius: 18px;
  background: var(--paper);
  color: var(--ink);
  box-shadow: 0 8px 22px rgba(8, 18, 48, .28);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.35;
  cursor: pointer;
}
.gd-bubble[hidden] { display: none; }
.gd-bubble.is-new { animation: gd-bubble .35s cubic-bezier(.2, 1.5, .4, 1); }
@keyframes gd-bubble { from { transform: scale(.85); opacity: .3; } }
.gd-bubble::after {                 /* the tail, pointing at the character */
  content: "";
  position: absolute;
  width: 16px; height: 16px;
  background: var(--paper);
  transform: rotate(45deg);
  border-radius: 3px;
}
.gd-name {
  display: block;
  color: #a3470f;
  font-size: 12px;
  font-weight: 800;
  letter-spacing: .06em;
  text-transform: uppercase;
}
.gd-text { margin: 0; min-height: 1.35em; }
.gd-sr { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }

/* In a lesson: in a row at the top-left of the panel, under its header, with
   the bubble beside it, so neither ever floats over the globe. */
.lp-narrator {
  flex: none;
  padding: 10px 14px 4px 10px;
}
.guide--lesson {
  position: relative;
  display: grid;
  grid-template-columns: 70px 1fr;
  align-items: end;
  gap: 12px;
}
.guide--lesson .gd-char { grid-column: 1; grid-row: 1; }
.guide--lesson .gd-bubble {
  position: relative;
  grid-column: 2;
  grid-row: 1;
  align-self: center;
  width: auto;
  background: #f5f3ff;
  box-shadow: none;
  font-size: 15px;
}
.guide--lesson .gd-bubble::after { left: -6px; bottom: 14px; background: #f5f3ff; }

/* On a country card: fixed, positioned by lessons.js next to the card. */
.guide--card-side, .guide--card-top { position: fixed; z-index: 39; }
.guide--card-side { width: 104px; }
.guide--card-side .gd-bubble { right: calc(100% + 4px); top: 18px; max-width: 230px; }
.guide--card-side .gd-bubble::after { right: -6px; top: 26px; }
.guide--card-top { width: 84px; }
.guide--card-top .gd-bubble { right: calc(100% + 4px); top: 2px; max-width: calc(100vw - 130px); font-size: 15px; }
.guide--card-top .gd-bubble::after { right: -6px; top: 20px; }

@media (max-width: 620px), (orientation: portrait) and (max-width: 1024px) {
  .lp-narrator { padding: 6px 12px 2px 8px; }
  .guide--lesson { grid-template-columns: 50px 1fr; gap: 10px; }
  .guide--lesson .gd-bubble { font-size: 14px; padding: 7px 12px 8px; }
}

@media (prefers-reduced-motion: reduce) {
  .gd-svg *, .guide .gd-char, .gd-bubble { animation: none !important; transition: none !important; }
}

/* Live lesson: shell hides WE topbar while this role does not have the wheel. */
body.tl-live-follower #topbar {
  display: none !important;
}
