/* game.css, how Aiko's specific pieces look: the cards, the choice buttons,
   the feedback panel. Uses only the names defined in theme.css. */

#app {
  position: relative;
  z-index: 1;                 /* above the body star dust */
  max-width: 44rem;
  margin-inline: auto;
  padding: var(--sp-5) var(--sp-4);
  display: flex;
  flex-direction: column;
  min-height: 100vh;
  gap: var(--sp-5);
}

/* ---------- Top bar ---------- */

.topbar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4);
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--size-lg);
}

.brand-mark {
  color: var(--c-primary);
}

.topbar-right {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
}

.score {
  font-size: var(--size-sm);
  color: var(--c-ink-soft);
  font-variant-numeric: tabular-nums;
}

.lang-toggle {
  font-size: var(--size-sm);
  color: var(--c-on-dark);
  padding: var(--sp-1) var(--sp-3);
  border: 1px solid rgba(255, 255, 255, 0.16);
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.08);
}

.lang-toggle:hover {
  border-color: var(--c-accent);
}

/* ---------- Panels ---------- */

.stage {
  flex: 1;
  display: flex;
  align-items: flex-start;
}

.panel {
  width: 100%;
  background: var(--c-surface);
  color: var(--c-ink);          /* dark text on the white cards, on a dark page */
  border: 1px solid var(--c-border);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
  padding: var(--sp-6);
}

/* Keep the plain cards (loading, error, mission complete) at a phone width and
   centred, so they sit among the dark frames as one device, not a wide slab. */
.panel:not(.panel-scene) {
  max-width: 440px;
  margin-inline: auto;
}

.panel-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--size-xl);
  margin-block-end: var(--sp-3);
}

/* Start and end screens stack their content down the middle, Aiko on top. */
.panel-center {
  text-align: center;
  display: flex;
  flex-direction: column;
  align-items: center;
}

.panel-body {
  color: var(--c-ink-soft);
  margin-block-end: var(--sp-5);
}

.panel-error {
  border-color: var(--c-wrong);
}

.error-hint {
  display: inline-block;
  margin-block-start: var(--sp-3);
  padding: var(--sp-2) var(--sp-3);
  background: var(--c-bg);
  border-radius: var(--radius-sm);
  font-size: var(--size-sm);
}

.loading-text {
  color: var(--c-ink-soft);
  text-align: center;
}

/* ---------- The mission scene (ported from aiko-concept-runner-4.html) ---------- */

/* The mission screen is not a document card, it is a phone-style frame sitting
   on the page, so we strip the panel chrome and just centre the frame. */
.panel-scene {
  padding: var(--sp-3);
  background: transparent;
  border: none;
  box-shadow: none;
}

.panel-scene .back-link {
  max-width: 440px;
  margin: 0 auto var(--sp-2);
  color: var(--c-on-dark-soft);   /* it sits on the dark page, above the light frame */
}
.panel-scene .back-link:hover { color: var(--c-accent); }

/* The runner's phone frame: tall and generous, soft purple sky top to bottom,
   centred on desktop, full-width on a small screen. HUD floats on top, the
   stage fills the middle, the dock is a bottom sheet. */
.scene-frame {
  position: relative;
  width: 100%;
  max-width: 440px;
  margin-inline: auto;
  display: flex;
  flex-direction: column;
  height: min(88vh, 880px);
  border-radius: var(--radius-lg);
  overflow: hidden;
  background: linear-gradient(180deg, var(--c-sky-top) 0%, var(--c-sky-mid) 45%, var(--c-sky-bot) 72%);
  box-shadow: 0 30px 90px rgba(38, 33, 92, 0.45);
}

/* Soft sun glow in the top end-corner (runner .sun). */
.sun {
  position: absolute;
  inset-block-start: -60px;
  inset-inline-end: -40px;
  width: 240px;
  height: 240px;
  border-radius: 50%;
  background: radial-gradient(circle, rgba(255, 220, 150, 0.55), rgba(255, 220, 150, 0) 70%);
  z-index: 1;
  pointer-events: none;
}

/* HUD floating over the scene (runner .hud): setting chip start-side, stars end-side. */
.scene-hud {
  position: absolute;
  inset-block-start: 0;
  inset-inline: 0;
  z-index: 30;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 15px 18px 10px;
}

.scene-chip {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 13px;
  color: var(--c-primary-dark);
  background: rgba(255, 255, 255, 0.78);
  padding: 6px 14px;
  border-radius: 22px;
  backdrop-filter: blur(8px);
  box-shadow: 0 3px 10px rgba(60, 52, 137, 0.14);
  white-space: nowrap;
}

.scene-stars {
  display: flex;
  align-items: center;
  gap: 5px;
  font-weight: 800;
  font-size: 15px;
  color: #d98a16;
}

/* Its own thin strip just under the HUD (runner .hud-progress), filling as each
   message of the conversation is cleared. */
.scene-progress {
  position: absolute;
  inset-block-start: 48px;
  inset-inline: 18px;
  height: 7px;
  background: rgba(255, 255, 255, 0.55);
  border-radius: 7px;
  overflow: hidden;
  z-index: 30;
}
.scene-progress i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 7px;
  background: linear-gradient(90deg, var(--c-correct-bright), var(--c-correct));
  box-shadow: 0 0 10px rgba(63, 211, 155, 0.6);
  transition: width 0.6s cubic-bezier(0.4, 1.3, 0.5, 1);
}

/* The stage fills the frame and clips its contents (runner .scene). */
.scene-stage {
  position: relative;
  flex: 1;
  overflow: hidden;
  z-index: 2;
}

/* Soft layered hills (runner .hills-far / .hills-near + .blob). */
.layer {
  position: absolute;
  inset-inline: 0;
  pointer-events: none;
}
.layer span {
  position: absolute;
  inset-block-end: 0;
  border-radius: 50% 50% 0 0;
}
.hills-far  { inset-block-end: 150px; height: 200px; }
.hills-near { inset-block-end: 120px; height: 150px; }
.hills-far span  { background: rgba(255, 255, 255, 0.18); }
.hills-near span { background: rgba(127, 119, 221, 0.22); }
.hills-far  span:nth-child(1) { width: 300px; height: 160px; inset-inline-start: -60px; }
.hills-far  span:nth-child(2) { width: 260px; height: 130px; inset-inline-start: 150px; }
.hills-far  span:nth-child(3) { width: 300px; height: 170px; inset-inline-start: 320px; }
.hills-near span:nth-child(1) { width: 240px; height: 130px; inset-inline-start: -40px; }
.hills-near span:nth-child(2) { width: 280px; height: 150px; inset-inline-start: 150px; }
.hills-near span:nth-child(3) { width: 240px; height: 130px; inset-inline-start: 320px; }

/* Floating dust motes (runner .mote). */
.mote {
  position: absolute;
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: var(--c-mote);
  opacity: 0.55;
  z-index: 3;
  animation: mote-float linear infinite;
}
@keyframes mote-float {
  0%, 100% { transform: translateY(0) translateX(0); }
  50%      { transform: translateY(-24px) translateX(12px); }
}

/* The ground the characters stand on (runner .ground). */
.scene-ground {
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  height: 150px;
  z-index: 4;
  background: linear-gradient(180deg, var(--c-ground), var(--c-ground-dark));
  border-start-start-radius: 50% 30px;
  border-start-end-radius: 50% 30px;
  box-shadow: inset 0 5px 14px rgba(255, 255, 255, 0.18);
}

/* Stepping tiles, one per message, lit as the conversation advances (runner .path/.tile). */
.path {
  position: absolute;
  inset-block-end: 84px;
  inset-inline: 0;
  display: flex;
  justify-content: center;
  gap: 16px;
  z-index: 6;
}
.tile {
  width: 34px;
  height: 12px;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.45);
  transition: all 0.45s ease;
}
.tile.lit {
  background: var(--c-correct-bright);
  box-shadow: 0 0 14px var(--c-correct-bright);
  transform: translateY(-2px);
}

/* ---------- Characters on the ground ---------- */

/* You (runner .kid). */
.kid {
  position: absolute;
  inset-block-end: 104px;
  inset-inline-start: 60px;
  width: 80px;
  z-index: 10;
  filter: drop-shadow(0 6px 6px rgba(60, 40, 110, 0.25));
}

/* The stranger waits off-side, then slides in (runner .stranger-svg). */
.stranger {
  position: absolute;
  inset-block-end: 104px;
  inset-inline-end: -100px;
  width: 74px;
  z-index: 9;
  filter: drop-shadow(0 6px 6px rgba(40, 30, 80, 0.25));
  transition: inset-inline-end 0.7s cubic-bezier(0.4, 1.1, 0.5, 1);
}
.stranger.in { inset-inline-end: 20px; }

/* Aiko, the guardian floating above the kid (runner .aiko-wrap + .aiko-glow).
   She is clearly in the scene at a good size, glowing, and her image swaps
   (idle / safe / worried) while cheer / worried tune the glow and the motion. */
.scene-aiko {
  position: absolute;
  inset-block-end: 176px;
  inset-inline-start: 40px;
  width: 116px;
  margin: 0;
  z-index: 20;
}
.scene-aiko .aiko-img {
  width: 100%;
  height: auto;
  display: block;
  filter: drop-shadow(0 0 18px rgba(239, 159, 39, 0.5));
  animation: scene-aiko-hover 3.4s ease-in-out infinite;
  transition: filter 0.4s ease, transform 0.3s ease;
}
.scene-aiko.cheer .aiko-img {
  filter: drop-shadow(0 0 26px rgba(63, 211, 155, 0.75));
  animation: scene-aiko-pop 0.5s cubic-bezier(0.3, 1.6, 0.4, 1), scene-aiko-hover 3.4s ease-in-out infinite 0.5s;
}
.scene-aiko.worried .aiko-img {
  filter: drop-shadow(0 0 16px rgba(242, 153, 74, 0.55));
  animation: scene-aiko-wobble 0.5s ease-in-out, scene-aiko-hover 3.4s ease-in-out infinite 0.5s;
}

.scene-aiko-glow {
  position: absolute;
  inset-block-end: 168px;
  inset-inline-start: 40px;
  width: 116px;
  height: 52px;
  z-index: 19;
  pointer-events: none;
  background: radial-gradient(ellipse, rgba(255, 210, 140, 0.5), transparent 70%);
  filter: blur(4px);
  animation: scene-aiko-pulse 3.4s ease-in-out infinite;
}

@keyframes scene-aiko-hover  { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-13px); } }
@keyframes scene-aiko-pop    { 0% { transform: scale(1); } 45% { transform: scale(1.14); } 100% { transform: scale(1); } }
@keyframes scene-aiko-wobble { 0%, 100% { transform: rotate(0); } 25% { transform: rotate(-6deg); } 75% { transform: rotate(6deg); } }
@keyframes scene-aiko-pulse  { 0%, 100% { opacity: 0.5; transform: scale(1); } 50% { opacity: 0.8; transform: scale(1.1); } }

/* ---------- Speech bubbles (runner .bubble) ---------- */

.bubble {
  position: absolute;
  z-index: 25;
  max-width: 215px;
  padding: 12px 16px;
  border-radius: 20px;
  font-weight: 700;
  font-size: 14.5px;
  line-height: 1.34;
  opacity: 0;
  transform: translateY(10px) scale(0.95);
  transition: opacity 0.32s ease, transform 0.32s ease;
  pointer-events: none;
}
.bubble.show {
  opacity: 1;
  transform: none;
  pointer-events: auto;
}

/* The stranger's message: white, end-side, tail pointing down toward them. */
.bubble-stranger {
  background: var(--c-surface);
  color: var(--c-ink);
  inset-inline-end: 18px;
  inset-block-start: 92px;
  box-shadow: 0 10px 28px rgba(60, 52, 137, 0.2);
  border-end-end-radius: 6px;
}
.bubble-stranger::after {
  content: "";
  position: absolute;
  inset-block-end: -9px;
  inset-inline-end: 26px;
  border: 9px solid transparent;
  border-block-start-color: var(--c-surface);
  border-block-end: 0;
}
.bubble-stranger small {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 10.5px;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  opacity: 0.7;
  margin-block-end: 3px;
}

/* Aiko's reply: purple gradient, start-side, tail pointing down toward her. */
.bubble-aiko {
  background: linear-gradient(135deg, var(--c-primary), var(--c-primary-dark));
  color: #fff;
  inset-inline-start: 16px;
  inset-block-start: 60px;
  box-shadow: 0 12px 30px rgba(60, 52, 137, 0.34);
  border-end-start-radius: 6px;
}
.bubble-aiko::after {
  content: "";
  position: absolute;
  inset-block-end: -9px;
  inset-inline-start: 30px;
  border: 9px solid transparent;
  border-block-start-color: var(--c-primary-dark);
  border-block-end: 0;
}

/* The tappable pieces of the stranger's message. Inline buttons so keyboards
   and screen readers can reach them too. */
.msg-piece {
  display: inline;
  font: inherit;
  color: inherit;
  padding: 0 2px;
  border-radius: 6px;
  cursor: pointer;
  transition: background-color 0.2s ease, opacity 0.2s ease;
}

.msg-piece:hover:not(:disabled) {
  background: var(--aiko-glow-soft);
}

/* A found red flag lights up gold and stays lit. */
.msg-piece.found {
  background: var(--c-accent);
  color: #3c1e00;
  box-shadow: 0 0 0 3px var(--aiko-glow);
}

.msg-piece:disabled {
  cursor: default;
}

/* ---------- The dock: hint, choices, takeaway ---------- */

.dock {
  flex: none;
  position: relative;
  z-index: 8;
  padding: var(--sp-3) var(--sp-4) var(--sp-4);
  background: linear-gradient(180deg, transparent, rgba(255, 255, 255, 0.94) 24%, var(--c-surface));
  translate: 0 110%;
  transition: translate 0.45s cubic-bezier(0.4, 1.2, 0.5, 1);
}

.dock.up {
  translate: 0 0;
}

.dock-hint {
  text-align: center;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--size-sm);
  color: var(--c-ink-soft);
  margin-block-end: var(--sp-3);
}

.dock-choices {
  display: flex;
  gap: var(--sp-3);
}

.choice-card {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  background: var(--c-surface);
  border: 2.5px solid var(--c-border);
  border-radius: 22px;
  padding: 15px 10px 13px;
  text-align: center;
  box-shadow: 0 5px 16px rgba(60, 52, 137, 0.09);
  transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, opacity 0.2s ease;
}

.choice-card:hover:not(:disabled) {
  border-color: var(--c-primary);
  transform: translateY(-2px);
}

.choice-ic {
  width: 52px;
  height: 52px;
  border-radius: 16px;
  display: grid;
  place-items: center;
  font-size: 28px;
  background: var(--c-bg);
}

.choice-lb {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 14px;
  color: var(--c-ink);
  line-height: 1.25;
}

/* Set by ui.js when a card is picked. Safe glows green (runner .safe-pick),
   the tempting wrong pick glows amber (runner .risk-pick). */
.choice-card.safe-pick {
  border-color: var(--c-correct);
  box-shadow: 0 0 0 4px rgba(63, 211, 155, 0.22);
}
.choice-card.safe-pick .choice-ic { background: rgba(63, 211, 155, 0.18); }

.choice-card.risk-pick {
  border-color: var(--c-risk-ring);
  box-shadow: 0 0 0 4px rgba(242, 153, 74, 0.2);
}

.choice-card.dim {
  opacity: 0.45;
}
.choice-card:disabled {
  cursor: default;
}

/* "Keep going", offered after the last flag is found. Gold, so it reads as a
   reward rather than a plain next-step, and it rises gently into view. */
.keep-going {
  display: block;
  margin-inline: auto;
  margin-block-start: var(--sp-4);
  background: linear-gradient(135deg, var(--c-accent), #e08e1c);
  color: #fff;
  box-shadow: 0 8px 24px rgba(239, 159, 39, 0.45);
  animation: rise 0.3s ease;
}
.keep-going:hover { transform: translateY(-2px); }

/* Takeaway + Next, revealed once the safe choice is made. */
.dock-after {
  margin-block-start: var(--sp-4);
  text-align: center;
  animation: rise 0.25s ease;
}

@keyframes rise {
  from { opacity: 0; transform: translateY(6px); }
  to   { opacity: 1; transform: none; }
}

.takeaway {
  background: var(--c-bg);
  border-radius: var(--radius-sm);
  padding: var(--sp-4);
  margin-block-end: var(--sp-4);
  font-size: var(--size-sm);
  text-align: start;
}

.takeaway-label {
  font-weight: 700;
  margin-inline-end: var(--sp-2);
}

/* ---------- Buttons ---------- */

.btn {
  padding: var(--sp-3) var(--sp-6);
  border-radius: 999px;              /* full pill, friendly, not form-like */
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--size-md);
  transition: background-color 0.15s ease, transform 0.15s ease;
}

.btn-primary {
  background: var(--c-primary);
  color: #fff;
  box-shadow: 0 6px 16px rgba(127, 119, 221, 0.35);
}

.btn-primary:hover {
  background: var(--c-primary-dark);
  transform: translateY(-2px);
}

.btn-primary:active {
  transform: translateY(0);
}

/* ---------- Aiko the character ---------- */

/* The figure is a centred box that holds two layers: a soft golden glow
   (the ::before) and the character image on top of it. State classes
   is-safe / is-risky (toggled by ui.js) change the glow and brightness. */
.aiko {
  position: relative;
  display: grid;
  place-items: center;
  width: fit-content;
  margin-inline: auto;
  margin-block-end: var(--sp-5);
}

/* The glow. Sits behind Aiko, softly pulsing. Its strength is driven by the
   --glow variable so each state can dial it up or down with one number. */
.aiko::before {
  content: "";
  position: absolute;
  inset: 50% auto auto 50%;
  width: 128%;
  aspect-ratio: 1;
  translate: -50% -50%;
  border-radius: 50%;
  background: radial-gradient(circle at center,
              var(--aiko-glow) 0%,
              var(--aiko-glow-soft) 42%,
              transparent 70%);
  opacity: var(--glow, 0.75);
  scale: var(--glow-scale, 1);
  filter: blur(6px);
  z-index: 0;
  transition: opacity 0.4s ease, scale 0.4s ease;
  animation: glow-breathe 4s ease-in-out infinite;
}

.aiko-img {
  position: relative;
  z-index: 1;
  width: clamp(140px, 34vw, 180px);
  height: auto;
  transition: filter 0.4s ease, scale 0.4s ease, translate 0.4s ease;
  animation: aiko-float 5s ease-in-out infinite;
}

/* The larger portrait used on the start and end screens. */
.aiko-lg .aiko-img {
  width: clamp(170px, 42vw, 220px);
}

/* Correct choice: Aiko throws her arms up, brightens, and the glow swells. */
.aiko.is-safe {
  --glow: 1;
  --glow-scale: 1.12;
}
.aiko.is-safe .aiko-img {
  filter: brightness(1.06) drop-shadow(0 0 14px var(--aiko-glow));
  scale: 1.04;
  animation: aiko-pop 0.45s ease;
}

/* Risky choice: Aiko dims and shrinks back a touch, worried, never scary. */
.aiko.is-risky {
  --glow: 0.3;
}
.aiko.is-risky .aiko-img {
  filter: brightness(0.9) saturate(0.92);
  scale: 0.97;
  animation: aiko-pop 0.45s ease;
}

/* Gentle, calm motion. base.css disables all of this for anyone who has asked
   their system to reduce motion. */
@keyframes aiko-float {
  0%, 100% { translate: 0 0; }
  50%      { translate: 0 -8px; }
}

@keyframes glow-breathe {
  0%, 100% { opacity: var(--glow, 0.75); }
  50%      { opacity: calc(var(--glow, 0.75) * 0.72); }
}

@keyframes aiko-pop {
  0%   { scale: 1; }
  55%  { scale: 1.08; }
  100% { scale: var(--pop-end, 1); }
}

/* ---------- Back link ---------- */

.back-link {
  color: var(--c-ink-soft);
  font-size: var(--size-sm);
  font-weight: 600;
  padding: var(--sp-1) 0;
  margin-block-end: var(--sp-4);
}
.back-link:hover { color: var(--c-primary); }

/* A chevron that points "back" in either reading direction. */
.back-link::before { content: "\2039"; margin-inline-end: 0.35em; }
:root[dir="rtl"] .back-link::before { content: "\203A"; }

/* ---------- Card grids (world map, region, topic) ---------- */

.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 15rem), 1fr));
  gap: var(--sp-4);
}

/* One card serves regions, topics, and missions. */
.card {
  position: relative;
  text-align: start;
  padding: var(--sp-5);
  border: 1px solid var(--c-border);
  border-inline-start: 6px solid var(--card-accent, var(--c-primary));
  border-radius: var(--radius);
  background: var(--c-surface);
  box-shadow: var(--shadow);
  transition: transform 0.15s ease, box-shadow 0.15s ease;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}

.card:hover:not(.is-locked) {
  transform: translateY(-3px);
  box-shadow: 0 6px 12px rgba(38, 33, 92, 0.06), 0 20px 40px rgba(127, 119, 221, 0.18);
}

/* A locked / coming-soon card is visible but clearly not ready. */
.card.is-locked {
  cursor: default;
  opacity: 0.6;
  border-inline-start-color: var(--c-border);
  box-shadow: none;
}

.card-title {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--size-lg);
}

.card-desc {
  color: var(--c-ink-soft);
  font-size: var(--size-sm);
}

/* Small pill in the corner: "Coming soon" or "2 / 3 done". */
.badge {
  align-self: flex-start;
  margin-block-start: var(--sp-1);
  padding: var(--sp-1) var(--sp-3);
  border-radius: 999px;
  font-size: var(--size-sm);
  font-weight: 600;
}
.badge-soon { background: var(--c-bg); color: var(--c-ink-soft); }
.badge-progress { background: var(--c-correct-soft); color: var(--c-correct); }

/* ---------- Mission list (inside a topic) ---------- */

.mission-list {
  display: flex;
  flex-direction: column;
  gap: var(--sp-3);
}

.mission-row {
  width: 100%;
  text-align: start;
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4);
  border: 2px solid var(--c-border);
  border-radius: var(--radius);
  background: var(--c-surface);
  transition: border-color 0.15s ease, transform 0.15s ease;
}
.mission-row:hover { border-color: var(--c-primary); transform: translateY(-1px); }

.mission-row-num {
  flex: none;
  width: 2rem;
  height: 2rem;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--c-bg);
  font-family: var(--font-display);
  font-weight: 700;
  color: var(--c-ink-soft);
}
.mission-row.is-done .mission-row-num {
  background: var(--c-correct);
  color: #fff;
}

.mission-row-body { flex: 1; display: flex; flex-direction: column; gap: 2px; }
.mission-row-title { font-weight: 700; }
.mission-row-sub { font-size: var(--size-sm); font-weight: 600; color: var(--c-ink-soft); }
.mission-row-tick { flex: none; color: var(--c-correct); font-weight: 700; }

/* Placeholder that keeps the topic open: more missions are coming. */
.mission-soon {
  padding: var(--sp-4);
  border: 2px dashed rgba(255, 255, 255, 0.15);
  border-radius: 16px;
  text-align: center;
  font-size: var(--size-sm);
  font-weight: 700;
  color: var(--c-on-dark-soft);
}

/* ---------- Topic complete: stars, parent note, confetti ---------- */

.star-row {
  display: flex;
  gap: var(--sp-2);
  justify-content: center;
  font-size: 2rem;
  margin-block: var(--sp-2) var(--sp-3);
}

.star-row .s {
  filter: grayscale(1) opacity(0.3);
}

.star-row .s.on {
  filter: none;
  animation: popstar 0.45s cubic-bezier(0.3, 1.7, 0.5, 1) both;
}

@keyframes popstar {
  from { transform: scale(0) rotate(-30deg); }
  to   { transform: scale(1) rotate(0); }
}

.parent-note {
  margin-block: var(--sp-3) var(--sp-5);
  background: var(--c-bg);
  border-radius: var(--radius-sm);
  padding: var(--sp-4);
  max-width: 28rem;
  font-size: var(--size-sm);
  color: var(--c-ink-soft);
  text-align: start;
}

.parent-note strong {
  color: var(--c-ink);
}

/* The end-of-topic celebration: Aiko's glow turns all the way up… */
.aiko-celebrate {
  --glow: 1;
  --glow-scale: 1.2;
}

/* …and confetti falls over the whole page. Pieces are spawned by ui.js and
   remove themselves; reduced-motion users simply never see them fall. */
.confetti {
  position: fixed;
  top: -14px;
  width: 9px;
  height: 14px;
  border-radius: 2px;
  z-index: 99;
  pointer-events: none;
  animation: confetti-fall linear forwards;
}

@keyframes confetti-fall {
  to { transform: translateY(105vh) rotate(640deg); }
}

/* ---------- Button row (topic complete) ---------- */

.button-row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-3);
}

.btn-ghost {
  background: transparent;
  color: var(--c-primary);
  border: 2px solid var(--c-border);
}
.btn-ghost:hover { border-color: var(--c-primary); }

/* ---------- Footer ---------- */

.footer {
  text-align: center;
  font-size: var(--size-sm);
  color: var(--c-on-dark-soft);
}

/* ================================================================== *
 *  The dark travel world: home, world map, region, topic
 *  (styling ported from reference/aiko_game_demo-2.html)
 * ================================================================== */

/* Each of these screens is a phone-ish dark frame centred on the page, the
   same footprint as the mission scene, so the app reads as one device. */
.dark-screen {
  width: 100%;
  max-width: 400px;
  margin-inline: auto;
  min-height: min(84vh, 780px);
  display: flex;
  flex-direction: column;
  color: var(--c-on-dark);
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: 0 30px 90px rgba(0, 0, 0, 0.5);
}

/* ---------- Home / companion ---------- */

#open-screen {
  background:
    radial-gradient(circle at 50% 38%, rgba(239, 159, 39, 0.18), transparent 55%),
    linear-gradient(180deg, var(--c-night-2), var(--c-night));
}
.home {
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 28px 24px;
  gap: 16px;
}
.home-aiko {
  width: 180px;
  filter: drop-shadow(0 0 34px var(--c-glow));
  animation: home-bob 3.2s ease-in-out infinite;
}
@keyframes home-bob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(-10px); } }
.home-speech {
  background: rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(8px);
  border: 1px solid rgba(255, 255, 255, 0.14);
  border-radius: 18px 18px 18px 4px;
  padding: 14px 18px;
  max-width: 270px;
}
.home-greeting {
  display: block;
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 19px;
}
.home-tagline {
  display: block;
  margin-block-start: 4px;
  font-weight: 700;
  font-size: 14px;
  line-height: 1.4;
  color: var(--c-on-dark);
}

/* The gold call-to-action button (demo-2 .btn). */
.cta {
  font-family: var(--font-display);
  font-weight: 700;
  font-size: 16px;
  border: none;
  border-radius: 16px;
  padding: 14px 32px;
  cursor: pointer;
  background: linear-gradient(135deg, var(--c-accent), #f5b23c);
  color: var(--c-ink);
  box-shadow: 0 8px 22px rgba(239, 159, 39, 0.4);
  transition: transform 0.15s ease;
}
.cta:hover { transform: translateY(-2px); }

/* ---------- World map (islands + winding path) ---------- */

#world-screen {
  background:
    radial-gradient(circle at 30% 20%, rgba(127, 119, 221, 0.25), transparent 45%),
    radial-gradient(circle at 75% 80%, rgba(29, 158, 117, 0.18), transparent 45%),
    linear-gradient(180deg, var(--c-night-2), var(--c-night));
}
.map-head { padding: 18px 22px 4px; }
.map-head h2 { font-family: var(--font-display); font-weight: 800; font-size: 20px; }
.map-head p { font-size: 12px; color: var(--c-on-dark-soft); margin-block-start: 2px; }

.map-canvas { position: relative; flex: 1; min-height: 500px; }
.map-path { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; }
.islands { position: absolute; inset: 0; }

.island {
  position: absolute;
  width: 118px;
  text-align: center;
  cursor: pointer;
  color: var(--c-on-dark);
  transition: transform 0.2s ease;
}
.island:hover:not(.is-locked) { transform: translateY(-4px) scale(1.03); }
.island.is-locked { opacity: 0.5; cursor: default; }
/* Physical left/top on purpose: the map is a spatial layout, so it stays the
   same in both reading directions and lines up with the fixed SVG path. */
.island:nth-child(1) { left: 32px;  top: 40px; }
.island:nth-child(2) { left: 200px; top: 150px; }
.island:nth-child(3) { left: 44px;  top: 270px; }
.island:nth-child(4) { left: 150px; top: 390px; }

.island-blob {
  position: relative;
  width: 92px;
  height: 92px;
  margin: 0 auto;
  border-radius: 46% 54% 52% 48% / 54% 48% 52% 46%;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 34px;
  background: var(--card-accent, var(--c-primary));
  box-shadow: 0 12px 28px rgba(0, 0, 0, 0.4), inset 0 2px 8px rgba(255, 255, 255, 0.25);
}
.island.is-active .island-blob { animation: island-pulse 2s ease-in-out infinite; }
@keyframes island-pulse {
  0%, 100% { box-shadow: 0 12px 28px rgba(0, 0, 0, 0.4), inset 0 2px 8px rgba(255, 255, 255, 0.25), 0 0 0 0 rgba(239, 159, 39, 0.5); }
  50%      { box-shadow: 0 12px 28px rgba(0, 0, 0, 0.4), inset 0 2px 8px rgba(255, 255, 255, 0.25), 0 0 24px 6px rgba(239, 159, 39, 0.45); }
}
.island-label { font-size: 11px; font-weight: 800; margin-block-start: 8px; line-height: 1.2; }
.island-lock {
  position: absolute;
  inset-block-start: -4px;
  inset-inline-end: -4px;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.6);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 13px;
}

/* ---------- Region and topic list screens ---------- */

#region-screen, #topic-screen {
  background:
    radial-gradient(circle at 30% 10%, rgba(127, 119, 221, 0.28), transparent 50%),
    linear-gradient(180deg, var(--c-night-2), var(--c-night-3));
}
.region-banner { padding: 18px 20px 8px; }
.region-banner .back {
  font-size: 12px;
  font-weight: 800;
  color: var(--c-on-dark-soft);
  cursor: pointer;
  margin-block-end: 8px;
  display: inline-block;
}
.region-banner .back:hover { color: var(--c-accent); }
.region-banner .back::before { content: "\2039"; margin-inline-end: 0.35em; }
:root[dir="rtl"] .region-banner .back::before { content: "\203A"; }
.region-banner h2 { font-family: var(--font-display); font-weight: 800; font-size: 22px; }
.region-banner p { font-size: 12px; color: var(--c-on-dark-soft); margin-block-start: 2px; }

.topics {
  padding: 6px 16px 22px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  overflow-y: auto;
}

/* One row serves topics (in a region) and missions (in a topic). */
.list-row {
  width: 100%;
  text-align: start;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 14px;
  border-radius: 16px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid rgba(255, 255, 255, 0.08);
  color: var(--c-on-dark);
  cursor: pointer;
  transition: background-color 0.18s ease, border-color 0.18s ease, transform 0.18s ease;
}
.list-row:hover:not(.is-locked) {
  background: rgba(127, 119, 221, 0.15);
  border-color: var(--c-primary);
  transform: translateY(-1px);
}
.list-row.is-locked { opacity: 0.45; cursor: default; }

.list-icon {
  flex: none;
  width: 44px;
  height: 44px;
  border-radius: 13px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  background: var(--card-accent, rgba(255, 255, 255, 0.08));
}
.list-row.is-done .list-icon { background: rgba(63, 211, 155, 0.2); }

.list-info { flex: 1; min-width: 0; }
.list-info h4 { font-size: 14px; font-weight: 800; }
.list-info p { font-size: 11px; color: var(--c-on-dark-soft); margin-block-start: 1px; }

.list-badge { flex: none; font-size: 11px; font-weight: 800; color: var(--c-accent); }
.list-badge.list-done { color: var(--c-correct-bright); }
.list-go { flex: none; font-size: 18px; color: var(--c-on-dark-faint); }
