/* MORE THAN ENOUGH — styles. Mobile Safari first, desktop friendly.
   The layout and the rules behind it are in docs/ui.md. */

:root {
  color-scheme: dark;
  /* Surfaces: glass over the map, and the solid panels of sheets. */
  --glass: rgba(12, 17, 14, 0.78);
  --panel: rgba(12, 17, 14, 0.96);
  --panel-line: rgba(255, 255, 255, 0.10);
  --raised: rgba(255, 255, 255, 0.06);
  /* Ink and accents. */
  --ink: #e9f1e6;
  --ink-dim: #93a291;
  --green: #7fd07a;
  --gold: #ffd166;
  --earth: #ecd3a4;
  --danger: #f08a7a;
  /* Shape. */
  --r-sm: 10px;
  --r-md: 14px;
  --r-lg: 20px;
  --shadow-1: 0 3px 12px rgba(0, 0, 0, 0.38);
  --shadow-2: 0 -8px 30px rgba(0, 0, 0, 0.5);
  --blur: blur(8px);   /* frosted glass, dropped on a device that can't keep up (quality.js) */
  /* The safe edges every HUD piece keeps to. */
  --edge-t: calc(env(safe-area-inset-top, 0px) + 8px);
  --edge-r: calc(env(safe-area-inset-right, 0px) + 12px);
  --edge-b: calc(env(safe-area-inset-bottom, 0px) + 20px);
  --edge-l: calc(env(safe-area-inset-left, 0px) + 12px);
  /* The thumb cluster: the big action and the buttons around it. */
  --act: 84px;
  --sub: 56px;
  --gap: 14px;
}

.no-glass { --blur: none; }

* { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

html, body {
  margin: 0; padding: 0;
  width: 100%; height: 100%;
  overflow: hidden;
  background: #05070a;
  overscroll-behavior: none;
  touch-action: none;
  -webkit-text-size-adjust: 100%; text-size-adjust: 100%;
  -webkit-user-select: none; user-select: none;
  -webkit-touch-callout: none;
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  color: var(--ink);
}

body { position: fixed; inset: 0; }

canvas#game {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  display: block;
  touch-action: none;
}

/* ------------------------------------------------------------------ HUD */

/* Status along the top: trophies, the resource bar, settings. It lets taps
   through to the map everywhere but on its buttons. */
#hud {
  position: absolute;
  top: 0; left: 0; right: 0;
  padding: var(--edge-t) var(--edge-r) 0 var(--edge-l);
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  pointer-events: none;
  z-index: 10;
}

#topbar {
  width: 100%; max-width: 560px;
  display: flex; align-items: center; gap: 8px;
}

/* Friends in a shared world, under the top bar on the right: a chip each in
   their colour, showing how they're doing. */
#friends {
  align-self: flex-end;
  display: flex; gap: 6px;
  pointer-events: none;
}
#friends[hidden] { display: none; }
.friend {
  display: flex; align-items: center; gap: 5px;
  height: 30px; padding: 0 10px 0 7px;
  border: 1px solid var(--panel-line); border-radius: 999px;
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--shadow-1);
  color: var(--ink); font: 800 13px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  pointer-events: auto; touch-action: manipulation; cursor: pointer;
}
.friend i {
  width: 12px; height: 12px; border-radius: 50%;
  background: var(--friend); box-shadow: 0 0 0 2px rgba(0, 0, 0, .35);
}
.friend.away i { opacity: .7; }
.friend.away::after { content: "z"; color: var(--ink-dim); font-size: 11px; }
.friend.lost i { animation: friend-lost 1s ease-in-out infinite; }
.friend.lost { border-color: rgba(255, 209, 102, .6); }
.friend.offline { opacity: .5; }
.friend.more { padding: 0 10px; color: var(--ink-dim); }
.friend.offline i { background: transparent; box-shadow: inset 0 0 0 2px var(--friend); }
@keyframes friend-lost { 50% { opacity: .2; } }

/* Round glass buttons on the top bar. */
.hudBtn {
  position: relative;
  flex: 0 0 auto;
  width: 44px; height: 44px; padding: 0;
  display: grid; place-items: center;
  border: 1px solid var(--panel-line); border-radius: 50%;
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--shadow-1);
  color: var(--ink);
  pointer-events: auto; touch-action: manipulation; cursor: pointer;
  transition: transform .08s ease;
}
.hudBtn:active { transform: scale(0.92); }
.hudBtn .gear { width: 22px; height: 22px; fill: none; stroke: currentColor; stroke-width: 1.8; stroke-linecap: round; stroke-linejoin: round; }

/* Milestones reached: a trophy with its count on a badge. It glows after a
   new one until the Awards are opened. */
#btnAwards { color: var(--gold); border-color: rgba(255, 209, 102, 0.45); }
#btnAwards .trophy { width: 22px; height: 22px; }
#awardCount {
  position: absolute; right: -4px; bottom: -4px;
  min-width: 20px; height: 20px; padding: 0 5px;
  display: grid; place-items: center;
  border-radius: 999px; border: 2px solid #0c140e;
  background: var(--gold); color: #2a1e04;
  font: 800 11px/1 -apple-system, BlinkMacSystemFont, sans-serif;
  font-variant-numeric: tabular-nums;
}
#btnAwards.new { animation: awardGlow 1.4s ease-in-out infinite; background: rgba(70, 52, 14, 0.92); }
@keyframes awardGlow {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 209, 102, 0.55); }
  50% { box-shadow: 0 0 0 8px rgba(255, 209, 102, 0); }
}
.trophy { fill: none; stroke: currentColor; stroke-width: 1.9; stroke-linejoin: round; stroke-linecap: round; }
.row .ic .trophy { width: 28px; height: 28px; color: var(--gold); }
.awardsLeft .trophy { opacity: 0.35; color: var(--ink-dim) !important; }

/* One resource bar: every resource in one capsule, tap one to see what you
   collected. */
#resources {
  flex: 1 1 auto; min-width: 0;
  display: flex; align-items: stretch;
  height: 44px; padding: 0 4px;
  border: 1px solid var(--panel-line); border-radius: 999px;
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--shadow-1);
}
.chip {
  flex: 1 1 0; min-width: 0;
  display: flex; align-items: center; justify-content: center; gap: 4px;
  padding: 0 2px;
  background: none; border: 0;
  font: inherit; color: inherit;
  pointer-events: auto; touch-action: manipulation; cursor: pointer;
}
.chip + .chip { border-left: 1px solid var(--panel-line); }
.chip:active { background: var(--raised); }
.chip:first-child { border-radius: 999px 0 0 999px; }
.chip:last-child { border-radius: 0 999px 999px 0; }
.chip .ic { width: 20px; height: 20px; flex: 0 0 auto; }
.chip .col { display: flex; flex-direction: column; align-items: flex-start; line-height: 1.05; min-width: 0; }
.chip .val {
  font-size: 15px; font-weight: 800; color: var(--ink);
  font-variant-numeric: tabular-nums;
}
.chip .rate { font-size: 9.5px; color: var(--green); font-weight: 700; font-variant-numeric: tabular-nums; }
.chip .rate:empty { display: none; }
/* Narrow phones: each resource's picture over its count, rates left out. */
@media (max-width: 360px) {
  .chip { flex-direction: column; gap: 1px; }
  .chip .ic { width: 16px; height: 16px; }
  .chip .col { align-items: center; }
  .chip .val { font-size: 13px; }
  .chip .rate { display: none; }
}

/* Performance panel: F3, or ?perf in the address. */
#perf {
  align-self: flex-end;
  margin: 0;
  padding: 7px 9px;
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-left: 3px solid var(--green);
  border-radius: 8px;
  background: rgba(8, 12, 10, 0.82);
  color: #d6e4d3;
  font: 10.5px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre;
  pointer-events: none;
}
#perf[hidden] { display: none; }
#perf[data-grade="ok"] { border-left-color: var(--gold); }
#perf[data-grade="bad"] { border-left-color: #ff5a5a; }

/* A milestone reached: a banner under the top bar, a few seconds each. It
   lets taps through to the map; the trophy button lists them all. */
#milestone {
  pointer-events: none;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  margin-top: 4px; padding: 10px 22px 12px; max-width: 90%;
  background: linear-gradient(180deg, rgba(58, 44, 16, 0.96), rgba(28, 22, 10, 0.96));
  border: 1px solid rgba(255, 209, 102, 0.6); border-radius: var(--r-md);
  box-shadow: 0 6px 24px rgba(0, 0, 0, 0.45), 0 0 18px rgba(255, 209, 102, 0.18);
  text-align: center;
  animation: milestone-in .35s cubic-bezier(.2, 1.4, .4, 1);
}
#milestone[hidden] { display: none; }
#milestone .trophy { width: 30px; height: 30px; color: var(--gold); filter: drop-shadow(0 0 6px rgba(255, 209, 102, 0.6)); }
#milestone small { font-size: 11px; font-weight: 800; letter-spacing: .14em; text-transform: uppercase; color: var(--gold); }
#milestone strong { font-size: 17px; line-height: 1.25; color: #fff3d6; }
@keyframes milestone-in { from { opacity: 0; transform: translateY(-14px) scale(.85); } 60% { transform: scale(1.06); } to { opacity: 1; transform: none; } }

/* Underground: how deep you are, and the layers as a column under it: the
   forest on top, every layer you've been down to, a dashed one for deeper
   still, and you lit. Going down moves the light down. */
#depthMeter {
  position: absolute; z-index: 10;
  left: var(--edge-l);
  top: calc(var(--edge-t) + 56px);
  display: flex; flex-direction: column; align-items: center; gap: 6px;
  pointer-events: none;
}
#depth {
  min-width: 44px; padding: 5px 8px;
  border: 1px solid rgba(225, 181, 105, 0.4); border-radius: 999px;
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--shadow-1);
  text-align: center;
  font-size: 13px; font-weight: 800; color: var(--earth);
  font-variant-numeric: tabular-nums;
}
#depth[hidden], #depthGauge[hidden] { display: none; }
#depthGauge {
  display: flex; flex-direction: column; gap: 2px;
  padding: 4px; border-radius: 8px;
  background: var(--glass);
  border: 1px solid rgba(225, 181, 105, 0.25);
}
#depthGauge i { display: block; width: 16px; height: 9px; border-radius: 2px; background: #5e4a36; }
#depthGauge i.surface { background: #56803a; }
#depthGauge i.deeper { background: none; border: 1px dashed rgba(236, 211, 164, 0.35); }
#depthGauge i.here { background: #ffd28a; box-shadow: 0 0 6px rgba(255, 210, 138, 0.8); }

/* ----------------------------------------------------- thumb cluster */

#controls { position: absolute; inset: 0; pointer-events: none; z-index: 12; }

/* One-hand play: everything you press sits in the right thumb's arc around
   the big action. Build and Upgrade to its left; the climb button pops in
   above-left of it, only beside a way between layers. The map keeps the
   rest of the screen. */
#thumbDock {
  position: absolute;
  right: var(--edge-r); bottom: var(--edge-b);
  width: var(--act); height: var(--act);
  pointer-events: none;
}

.btn {
  position: absolute;
  border-radius: 50%;
  border: 1px solid rgba(255, 255, 255, 0.16);
  background: radial-gradient(circle at 50% 30%, rgba(44, 58, 48, 0.92), rgba(16, 22, 18, 0.92));
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  color: var(--ink);
  display: flex; align-items: center; justify-content: center;
  padding: 0;
  pointer-events: auto;
  touch-action: manipulation;
  -webkit-user-select: none; user-select: none;
  box-shadow: var(--shadow-1), inset 0 1px 0 rgba(255, 255, 255, 0.08);
  transition: transform .08s ease;
}
.btn:active { transform: scale(0.93); }
.btn .big { width: 30px; height: 30px; object-fit: contain; pointer-events: none; }
/* Every button's name on a small plate across its bottom edge. */
.btn .cap {
  position: absolute; left: 50%; bottom: -7px; transform: translateX(-50%);
  padding: 2px 6px;
  border-radius: 999px; border: 1px solid rgba(255, 255, 255, 0.14);
  background: #141c17;
  font-size: 9px; font-weight: 800; letter-spacing: 0.03em; line-height: 1.2;
  white-space: nowrap; color: #c9d6c6;
  pointer-events: none;
}
/* Something in the sheet you can buy or place right now. */
.btn.has::before {
  content: ""; position: absolute; top: 0; right: 0;
  width: 14px; height: 14px; border-radius: 50%;
  background: #7fe06e; border: 2px solid #0c140e;
  box-shadow: 0 0 8px rgba(127, 224, 110, 0.8);
}

#btnBuild, #btnUpgrade, #btnMine { width: var(--sub); height: var(--sub); }
#btnUpgrade { right: calc(var(--act) + var(--gap)); bottom: calc((var(--act) - var(--sub)) / 2); }
#btnBuild { right: calc(var(--act) + var(--sub) + var(--gap) * 2); bottom: calc((var(--act) - var(--sub)) / 2); }

/* The big action: what holding it does right now. */
#btnAction {
  right: 0; bottom: 0;
  width: var(--act); height: var(--act);
  background: radial-gradient(circle at 50% 32%, rgba(84, 146, 94, 0.95), rgba(24, 44, 31, 0.95));
  border: 2px solid rgba(150, 230, 150, 0.5);
}
#btnAction .big { width: 42px; height: 42px; }
#btnAction .cap { font-size: 11px; color: #e4f7df; background: #1d3524; border-color: rgba(150, 230, 150, 0.45); }
#btnAction.disabled { opacity: 0.55; }
#btnAction.ready { animation: readyPulse 1.6s ease-in-out infinite; }
#btnAction.ready:active { animation: none; }
@keyframes readyPulse {
  0%, 100% { box-shadow: var(--shadow-1), 0 0 0 0 rgba(127, 208, 122, 0.3); }
  50% { box-shadow: var(--shadow-1), 0 0 0 8px rgba(127, 208, 122, 0); }
}

/* Invite: the other main action, as big as Gather, in the left thumb's
   corner. Pressed while your sign is up (tap again to put it down). Its
   colour is the sign's friendly sky blue. */
#btnInvite {
  left: var(--edge-l); bottom: var(--edge-b);
  width: var(--act); height: var(--act);
  color: #eaf6ff;
  background: radial-gradient(circle at 50% 32%, rgba(98, 180, 234, 0.95), rgba(22, 62, 98, 0.95));
  border: 2px solid rgba(160, 214, 255, 0.55);
}
#btnInvite[hidden] { display: none; }
#btnInvite .big { width: 40px; height: 40px; }
#btnInvite .cap { font-size: 11px; color: #eaf6ff; background: #133150; border-color: rgba(160, 214, 255, 0.45); }
#btnInvite.up { background: radial-gradient(circle at 50% 32%, #fff, #dcecf7); color: #133150; border-color: #fff; }

/* The climb button, above-left of the action; it pops in beside a way up or
   down and is gone elsewhere. */
#btnMine {
  right: calc(var(--act) - var(--sub) / 2 + 4px);
  bottom: calc(var(--act) + 4px);
  border-color: rgba(225, 181, 105, 0.6);
  background: radial-gradient(circle at 50% 30%, rgba(96, 72, 44, 0.95), rgba(36, 26, 16, 0.95));
  animation: pop-in .22s cubic-bezier(.2, 1.5, .4, 1);
}
#btnMine[hidden] { display: none; }
#btnMine .big { width: 26px; height: 26px; }
#btnMine .cap { color: var(--earth); background: #2a1f13; border-color: rgba(225, 181, 105, 0.45); }
@keyframes pop-in { from { opacity: 0; transform: scale(.5); } to { opacity: 1; transform: none; } }

/* Zoom: a slim column on the right edge, above the cluster. The middle
   shows the magnification; tap it for 1×. Pinching zooms too. */
#zoomControls {
  position: absolute;
  right: calc(var(--edge-r) + (var(--act) - 40px) / 2);
  bottom: calc(var(--edge-b) + var(--act) + 78px);
  width: 40px;
  display: flex; flex-direction: column; align-items: stretch;
  border: 1px solid var(--panel-line); border-radius: 999px;
  background: var(--glass);
  -webkit-backdrop-filter: var(--blur); backdrop-filter: var(--blur);
  box-shadow: var(--shadow-1);
  overflow: hidden;
  pointer-events: auto;
}
/* Nothing on the HUD may cover your QR sign (zoom doesn't change its size). */
body.signing #zoomControls { visibility: hidden; }
#zoomControls button {
  height: 40px; padding: 0;
  border: 0; background: none; color: var(--ink);
  font: 600 22px/1 -apple-system, BlinkMacSystemFont, sans-serif;
  touch-action: manipulation;
}
#zoomControls button:active { background: rgba(80, 130, 90, 0.5); }
#zoomControls #zoomLevel {
  height: 26px;
  border-top: 1px solid var(--panel-line); border-bottom: 1px solid var(--panel-line);
  color: var(--ink-dim); font-size: 10.5px; font-weight: 800;
  font-variant-numeric: tabular-nums;
}

/* ---------------------------------------------------------------- sheet */

#sheet {
  position: absolute; left: 0; right: 0; bottom: 0;
  max-width: 640px; margin: 0 auto;
  height: min(72vh, 720px);
  background: var(--panel);
  border-top-left-radius: var(--r-lg); border-top-right-radius: var(--r-lg);
  border: 1px solid var(--panel-line); border-bottom: 0;
  transform: translateY(110%);
  transition: transform .26s cubic-bezier(.2, .9, .3, 1);
  display: flex; flex-direction: column;
  z-index: 30;
  box-shadow: var(--shadow-2);
}
#sheet.open { transform: translateY(0); }
/* Settings is short: it takes only the room it needs. */
#sheet[data-tab="settings"] { height: auto; max-height: 88vh; }

#sheetGrab {
  flex: 0 0 auto;
  height: 18px;
  display: flex; align-items: center; justify-content: center;
  cursor: grab;
  touch-action: none;
}
#sheetGrab span {
  width: 40px; height: 5px;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.22);
}
#sheetGrab:active span { background: rgba(255, 255, 255, 0.4); }

/* The tabs, or a screen's own title, with × on the right. */
#sheetHead {
  flex: 0 0 auto;
  display: flex; align-items: center; gap: 10px;
  padding: 0 12px 8px;
}
#sheetTitle { flex: 1 1 auto; padding-left: 6px; font-size: 20px; font-weight: 800; color: var(--ink); }
#sheet[data-tab]:not([data-tab="settings"]):not([data-tab="collected"]):not([data-tab="map"]):not([data-tab="invites"]) #sheetTitle,
#sheet[data-tab="settings"] #tabs, #sheet[data-tab="collected"] #tabs, #sheet[data-tab="map"] #tabs, #sheet[data-tab="invites"] #tabs { display: none; }
#sheet[data-tab="map"] { height: min(88vh, 900px); max-width: 900px; }
#btnClose { width: 40px; height: 40px; box-shadow: none; background: var(--raised); }
#btnClose svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; }

/* Tabs: one segmented control under the title. */
#tabs {
  flex: 1 1 auto; min-width: 0;
  display: flex; gap: 2px;
  padding: 3px;
  border-radius: 12px;
  background: rgba(0, 0, 0, 0.35);
  border: 1px solid var(--panel-line);
}
#tabs [hidden] { display: none; }
.tab {
  flex: 1 1 0;
  min-width: 0; height: 38px;
  border: 0; border-radius: 9px;
  background: none;
  color: var(--ink-dim);
  font: 800 13.5px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  touch-action: manipulation; cursor: pointer;
  transition: background .15s ease, color .15s ease;
}
.tab.active { color: #0c1a0e; background: var(--green); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); }

#sheetBody {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  touch-action: pan-y;
  flex: 1 1 auto;
  padding: 2px 0 calc(env(safe-area-inset-bottom, 0px) + 16px);
  min-height: 60px;
}

.row {
  display: flex; align-items: center; gap: 12px;
  margin: 0 10px 6px; padding: 10px 12px;
  border: 1px solid var(--panel-line); border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.035);
}
.row .ic { width: 34px; height: 34px; flex: 0 0 auto; display: flex; align-items: center; justify-content: center; }
.row .ic .ico { width: 34px; height: 34px; object-fit: contain; }
/* Pictures inline with text: prices, rates, tags. */
.ico { width: 1.25em; height: 1.25em; object-fit: contain; vertical-align: -0.28em; }
.row .main { flex: 1 1 auto; min-width: 0; }
.row .nm { font-size: 15px; font-weight: 800; color: var(--ink); }
.row .nm .tag {
  font-size: 10px; font-weight: 700; color: var(--ink-dim);
  background: rgba(255,255,255,0.06);
  border: 1px solid var(--panel-line);
  border-radius: 999px;
  padding: 1px 6px; margin-left: 4px;
  vertical-align: 1px;
}
.row .sub { font-size: 11.5px; color: var(--ink-dim); margin-top: 2px; }
.row .sub .cost { color: #e8d59a; }
.row .sub .ok { color: var(--green); }
.row .sub .bad { color: #e08a7a; }

/* Prices: one pill per resource, picture first. Short of it: how much more
   to gather (red). Enough of it: a tick. All there: what it costs (green). */
.price { display: inline-flex; flex-wrap: wrap; gap: 4px; margin-top: 3px; }
.amt {
  display: inline-flex; align-items: center; gap: 3px;
  padding: 1px 8px 1px 3px;
  border: 1px solid color-mix(in srgb, var(--res, #fff) 45%, transparent); border-radius: 999px;
  background: color-mix(in srgb, var(--res, #fff) 10%, transparent);
  font-size: 12px; font-weight: 700; white-space: nowrap; font-variant-numeric: tabular-nums;
}
.amt .ico { width: 16px; height: 16px; vertical-align: 0; }
.amt.need .n { color: #f0a08f; }
.amt.met { opacity: 0.6; }
.amt.met .n { color: var(--green); }
.amt.cost .n { color: var(--green); }
.row .buy {
  flex: 0 0 auto;
  min-width: 84px; min-height: 46px;
  border-radius: 12px;
  padding: 0 12px;
  font: 800 14px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  letter-spacing: 0.02em;
  touch-action: manipulation;
  cursor: pointer;
}
/* One you can press looks like a real button: solid, raised, glowing. */
.row .buy:not(:disabled) {
  border: 1px solid #a4ec92;
  background: linear-gradient(180deg, #6fcf62, #3f9a45);
  color: #08200b;
  box-shadow: 0 4px 0 #24652c, 0 6px 14px rgba(80, 200, 90, 0.28);
  text-shadow: 0 1px 0 rgba(255, 255, 255, 0.3);
  transform: translateY(-2px);
  transition: transform .06s ease, box-shadow .06s ease;
}
.row .buy:not(:disabled):active { transform: translateY(2px); box-shadow: 0 0 0 #24652c, 0 2px 6px rgba(80, 200, 90, 0.2); }
/* One you can't press yet is flat and outlined, like a label. */
.row .buy:disabled {
  border: 1px dashed rgba(255,255,255,0.18);
  background: transparent;
  color: rgba(147, 162, 145, 0.75);
  cursor: default;
}
.row .buy.max { border: 1px solid transparent; background: rgba(255,255,255,0.04); color: var(--ink-dim); }
.row.locked { opacity: 0.6; }
.section { padding: 12px 20px 6px; font-size: 11px; font-weight: 800; letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink-dim); }

/* ------------------------------------------------------ Collected */

/* A resource's heading, lit for a moment when its counter was tapped. */
.colHead { display: flex; align-items: center; gap: 6px; font-size: 12px; font-weight: 800; color: var(--ink); transition: background 1.2s; border-radius: 10px; }
.colHead .ico { width: 20px; height: 20px; }
.colHead.lit { background: rgba(127, 208, 122, 0.22); }
/* Where it came from: a share bar in the resource's own colour. */
.row.share .bar { height: 6px; margin-top: 5px; border-radius: 3px; background: rgba(255, 255, 255, 0.08); overflow: hidden; }
.row.share .bar i { display: block; height: 100%; width: var(--share); background: var(--res); border-radius: 3px; }
/* Every kind of mushroom, as a card; ones not found yet are shadows. */
.cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(104px, 1fr)); gap: 8px; padding: 4px 12px 12px; }
.card {
  background: rgba(255, 255, 255, 0.04); border: 1px solid var(--panel-line); border-radius: 12px;
  padding: 8px 6px 7px; text-align: center; min-width: 0;
}
.card .ico { width: 64px; height: 52px; object-fit: contain; display: block; margin: 0 auto 4px; }
.card .nm { font-size: 13px; font-weight: 800; color: var(--ink); }
.card .sub { font-size: 11px; color: var(--ink-dim); margin-top: 2px; }
.card.unseen .ico { filter: brightness(0); opacity: 0.35; }
.card.unseen .nm { color: var(--ink-dim); }
.card.magic { border-color: rgba(201, 166, 255, 0.5); }
.card.magic:not(.unseen) { background: rgba(201, 166, 255, 0.1); }
.card .spark { color: #c9a6ff; }

/* ------------------------------------ progression map (Upgrades tab) */

/* A family header: full-width tap target with icon, name, a progress rail of
   nodes, a count, and a chevron. */
.railHead {
  display: flex; align-items: center; gap: 10px;
  width: calc(100% - 20px); text-align: left;
  min-height: 56px;
  margin: 0 10px 6px; padding: 10px 12px;
  background: rgba(255, 255, 255, 0.05);
  border: 1px solid var(--panel-line); border-radius: var(--r-md);
  color: var(--ink); font: inherit; font-weight: 700;
  cursor: pointer; touch-action: manipulation;
}
.railHead.ready { background: rgba(60, 120, 80, 0.18); border-color: rgba(127, 208, 122, 0.35); }
.railHead:active { background: rgba(255,255,255,0.06); }
.railHead .fh-ic { width: 28px; height: 28px; flex: 0 0 auto; }
.railHead .fh-ic .ico { width: 28px; height: 28px; }
.railHead .fh-main { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.railHead .fh-nm { font-size: 14px; font-weight: 800; color: var(--ink); }
.railHead .fh-count { flex: 0 0 auto; font-size: 11.5px; font-weight: 700; color: var(--ink-dim); }
.railHead .chev {
  flex: 0 0 auto; width: 28px; height: 28px; display: grid; place-items: center;
  border-radius: 50%; border: 1px solid var(--panel-line); background: rgba(255,255,255,0.05);
  color: var(--ink); font-size: 13px;
}
.railHead.ready .chev { border-color: rgba(127,208,122,0.6); color: var(--green); }

/* One dot per system in the family: filled = maxed, half = in progress,
   ringed = a next level is affordable, hollow = not started. */
.rail { display: flex; gap: 5px; align-items: center; flex-wrap: wrap; }
.rail .node {
  width: 12px; height: 12px; border-radius: 999px;
  border: 1.5px solid var(--panel-line);
  background: rgba(255,255,255,0.04);
}
.rail .node.owned { background: var(--green); border-color: var(--green); }
.rail .node.partial {
  border-color: var(--green);
  background: linear-gradient(90deg, var(--green) 50%, rgba(255,255,255,0.05) 50%);
}
.rail .node.ready { border-color: var(--green); background: rgba(127,208,122,0.22); }
.rail .node.saving { border-color: rgba(255,255,255,0.18); background: rgba(255,255,255,0.03); }

/* Expanded family: the existing buy rows, indented under their header. */
.familyBody { margin-bottom: 8px; }
.familyBody .row { margin-left: 24px; }

/* Settings: grouped rows, a name on the left and its value on the right,
   the destructive one alone at the bottom. No tabs: it isn't a game list. */
#settingsPanel {
  overflow-y: auto; -webkit-overflow-scrolling: touch; touch-action: pan-y;
  flex: 1 1 auto; min-height: 0;
  display: flex; flex-direction: column; gap: 14px;
  padding: 6px 12px calc(env(safe-area-inset-bottom, 0px) + 16px);
}
#settingsPanel[hidden], #sheetBody[hidden], #mapPanel[hidden] { display: none; }

/* The world map fills the sheet; its own zoom sits in the corner like the
   game's, and a button brings you back to where you are. */
#mapPanel { position: relative; flex: 1 1 auto; min-height: 0; margin: 0 10px calc(env(safe-area-inset-bottom, 0px) + 10px); border-radius: var(--r-md); overflow: hidden; border: 1px solid var(--panel-line); }
#worldMap { display: block; width: 100%; height: 100%; touch-action: none; cursor: grab; }
#mapTools {
  position: absolute; right: 10px; bottom: 10px; width: 40px;
  display: flex; flex-direction: column;
  border: 1px solid var(--panel-line); border-radius: 999px; overflow: hidden;
  background: var(--glass); box-shadow: var(--shadow-1);
}
#mapTools button { height: 40px; padding: 0; border: 0; background: none; color: var(--ink); font: 600 22px/1 -apple-system, BlinkMacSystemFont, sans-serif; touch-action: manipulation; }
#mapTools button + button { border-top: 1px solid var(--panel-line); }
#mapTools svg, #btnMap svg { width: 20px; height: 20px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linejoin: round; vertical-align: middle; }
#zoomControls #btnMap { border-top: 1px solid var(--panel-line); }
/* Invite links: one card per link, newest first. */
#invitesPanel { overflow-y: auto; padding: 4px 16px 20px; display: flex; flex-direction: column; gap: 8px; }
#invitesPanel[hidden] { display: none; }
#invitesPanel .empty { color: var(--ink-dim); text-align: center; padding: 24px 8px; line-height: 1.45; }
.invite {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px; border-radius: var(--r-md);
  border: 1px solid var(--panel-line); background: rgba(255, 255, 255, 0.03);
}
.invite.dead { opacity: .55; }
/* Picks for new invite links: how many people, for how long. */
.inviteAsk { display: flex; flex-direction: column; gap: 6px; }
.inviteAsk > span { font-size: 12.5px; font-weight: 700; color: var(--ink-dim); padding-left: 2px; }
.inviteAsk .pick {
  display: flex; gap: 2px; padding: 3px; border-radius: 12px;
  background: rgba(0, 0, 0, 0.35); border: 1px solid var(--panel-line);
}
.inviteAsk .pick button {
  flex: 1 1 0; min-width: 0; height: 38px; border: 0; border-radius: 9px;
  background: none; color: var(--ink-dim);
  font: 800 13.5px/1 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  white-space: nowrap; touch-action: manipulation; cursor: pointer;
}
.inviteAsk .pick button.on { color: #0c1a0e; background: var(--green); box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4); }
.inviteAsk + .inviteAsk { margin-bottom: 6px; }
.invite i { flex: none; width: 12px; height: 12px; border-radius: 50%; background: var(--friend); }
.invite div { flex: 1 1 auto; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.invite strong { font-size: 15px; }
.invite small { font-size: 12.5px; color: var(--ink-dim); }
.invite button {
  flex: none; min-height: 40px; padding: 0 14px; border-radius: var(--r-sm);
  border: 1px solid var(--panel-line); background: var(--raised); color: var(--ink);
  font: 800 13px/1 -apple-system, BlinkMacSystemFont, system-ui, sans-serif;
  touch-action: manipulation; cursor: pointer;
}
.invite button.stop { color: var(--danger); border-color: rgba(240, 138, 122, 0.35); }

.setGroup {
  display: flex; flex-direction: column;
  border: 1px solid var(--panel-line); border-radius: var(--r-md);
  background: rgba(255, 255, 255, 0.03);
  overflow: hidden;
}
.setRow {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 52px; padding: 0 16px;
  border: 0; background: none;
  color: var(--ink); font: 700 15px/1.2 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  text-align: left; text-decoration: none;
  touch-action: manipulation; cursor: pointer;
}
.setRow[hidden], .setGroup[hidden] { display: none; }
.setRow + .setRow { border-top: 1px solid var(--panel-line); }
.setRow:active { background: var(--raised); }
.setRow b {
  min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-weight: 600; color: var(--green);
}
.setRow b::first-letter { text-transform: uppercase; }
#version {
  align-self: center;
  font-size: 11px; font-weight: 700; letter-spacing: 0.05em;
  color: var(--ink-dim);
}
#version #brand { color: #e8d9a8; letter-spacing: 0.12em; }
#version span + span::before { content: '\00B7'; margin: 0 6px; opacity: 0.6; }

/* --------------------------------------------------------------- toast */

/* Status messages drop in under the top bar, out of the thumb's way. */
#toast {
  position: absolute; left: 50%; top: calc(var(--edge-t) + 56px);
  transform: translate(-50%, -8px);
  background: rgba(20, 26, 22, 0.95);
  border: 1px solid var(--panel-line);
  border-radius: 12px;
  padding: 9px 15px;
  font-size: 13.5px; font-weight: 700; color: var(--ink);
  opacity: 0; pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
  z-index: 40;
  max-width: 88%;
  text-align: center;
}
#toast.show { opacity: 1; transform: translate(-50%, 0); }

/* A region's name as you walk into it: big and quiet across the upper
   middle of the map, fading in and away on its own. Taps go through. */
#place {
  position: absolute; left: 50%; top: 24%; z-index: 20;
  transform: translateX(-50%);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  pointer-events: none; text-align: center; white-space: nowrap;
  color: #fff6dc; text-shadow: 0 2px 6px rgba(0, 0, 0, 0.75), 0 0 18px rgba(0, 0, 0, 0.45);
  animation: place-show 5s ease forwards;
}
#place[hidden] { display: none; }
#place small { font-size: 12px; font-weight: 800; letter-spacing: .22em; text-transform: uppercase; color: var(--gold); }
#place strong { font-family: Georgia, 'Times New Roman', serif; font-size: clamp(26px, 8vw, 40px); font-weight: 700; letter-spacing: .02em; }
@keyframes place-show { 0% { opacity: 0; transform: translate(-50%, 8px); } 14%, 70% { opacity: 1; transform: translate(-50%, 0); } 100% { opacity: 0; transform: translate(-50%, 0); } }

/* ------------------------------------------------------------ dialogs */

/* Every question and report the game puts in front of you is a card in the
   middle of the screen over a dimmed map: a title, what it means, and its
   buttons at the bottom, the safe one first. */
.scrim {
  position: fixed; inset: 0; z-index: 95;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  background: rgba(0, 0, 0, 0.55);
}
.scrim[hidden] { display: none; }
.dialog {
  width: 100%; max-width: 400px;
  display: flex; flex-direction: column; gap: 10px;
  padding: 20px 18px 18px;
  border: 1px solid var(--panel-line); border-radius: var(--r-lg);
  background: #121a15; color: var(--ink);
  box-shadow: 0 16px 50px rgba(0, 0, 0, 0.6);
  animation: fade-in .16s ease-out;
}
@keyframes fade-in { from { opacity: 0; } to { opacity: 1; } }
/* The nuke: centre stage over a red-dark map, above everything else, with
   one huge round red button and nothing to close it. */
#nuke { z-index: 120; background: radial-gradient(circle at 50% 45%, rgba(120, 24, 12, 0.55), rgba(0, 0, 0, 0.82)); }
#nuke .dialog { align-items: center; text-align: center; gap: 14px; border-color: rgba(240, 138, 122, 0.45); }
#nuke .dialog strong { font-size: 22px; }
#nuke button {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  width: min(200px, 56vw); aspect-ratio: 1; margin: 6px 0;
  border: 3px solid #ffab9c; border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, #ff7a63, #c2402b 60%, #8e2a1b);
  color: #fff4f1; font: 900 22px/1.1 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  letter-spacing: 0.08em; text-transform: uppercase;
  box-shadow: 0 8px 0 #6b1e12, 0 0 0 10px rgba(232, 111, 92, 0.18), 0 18px 40px rgba(0, 0, 0, 0.6);
  touch-action: manipulation; cursor: pointer;
  animation: nuke-pulse 1.4s ease-in-out infinite;
}
#nuke button:focus { outline: none; }
#nuke button:focus-visible { outline: 3px solid #ffab9c; outline-offset: 6px; }
#nuke button::before { content: '\2622'; font-size: 64px; line-height: 1; }
#nuke button:active { transform: translateY(5px); box-shadow: 0 3px 0 #6b1e12, 0 0 0 10px rgba(232, 111, 92, 0.18); }
#nuke button[aria-pressed="true"] { animation: none; transform: translateY(6px); filter: saturate(0.5) brightness(0.75); box-shadow: 0 2px 0 #6b1e12; cursor: default; }
#nuke p:last-child { white-space: pre-line; margin: 0; }
#nuke p[hidden] { display: none; }
@keyframes nuke-pulse { 50% { box-shadow: 0 8px 0 #6b1e12, 0 0 0 22px rgba(232, 111, 92, 0.08), 0 18px 40px rgba(0, 0, 0, 0.6); } }
@media (prefers-reduced-motion: reduce) { #nuke button { animation: none; } }
.dialog strong { font-size: 19px; line-height: 1.25; }
.dialog p { margin: 0 0 6px; font-size: 14.5px; line-height: 1.45; color: var(--ink-dim); }
.dialog .choices { display: flex; gap: 10px; }
.dialog .choices button {
  flex: 1 1 0; min-height: 48px; padding: 0 12px;
  border-radius: 12px;
  font: 800 15px/1.1 -apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif;
  touch-action: manipulation; cursor: pointer;
}
.dialog .secondary { border: 1px solid var(--panel-line); background: var(--raised); color: var(--ink); }
.dialog .primary { border: 1px solid #a4ec92; background: linear-gradient(180deg, #6fcf62, #3f9a45); color: #08200b; }
.dialog .primary.danger { border-color: #ffab9c; background: linear-gradient(180deg, #e86f5c, #b6432f); color: #fff4f1; }
.dialog .choices button:active { transform: scale(0.97); }

/* What's new after the game updated itself: each release's notes, scrolling. */
#news .news {
  max-height: min(46vh, 360px); overflow-y: auto;
  padding: 10px 12px; border: 1px solid var(--panel-line); border-radius: var(--r-md);
  background: var(--raised);
}
#news h3 { margin: 0 0 4px; font-size: 12px; letter-spacing: 0.06em; color: var(--gold); }
#news section + section { margin-top: 10px; }
#news ul { margin: 0; padding-left: 18px; font-size: 14px; line-height: 1.45; }
#news li + li { margin-top: 4px; }

/* Two tabs saved the same world: pick which to keep, one card each. */
#fork .picks { display: flex; flex-direction: column; gap: 8px; }
#fork .picks button {
  display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
  padding: 12px 14px; text-align: left;
  border: 1px solid var(--panel-line); border-radius: var(--r-md);
  background: var(--raised); color: inherit; font: inherit;
  touch-action: manipulation; cursor: pointer;
}
#fork .picks button.ahead { border-color: var(--green); background: rgba(127, 208, 122, 0.12); }
#fork .title { font-weight: 800; font-size: 15px; }
#fork .title em { margin-left: 6px; font-style: normal; font-size: 12px; color: var(--green); }
#fork .text { font-size: 13px; color: var(--ink-dim); }

/* A texture pack that didn't load: every problem, by thing and slot. */
.dialog.warn { border-color: rgba(255, 179, 71, 0.6); background: #1e160a; color: #ffe9cc; }
.dialog.warn strong { color: #ffc46b; }
#packReport ul {
  margin: 0; padding-left: 18px; max-height: 50vh; overflow: auto;
  font: 12px/1.5 ui-monospace, SFMono-Regular, Menlo, monospace;
  word-break: break-word;
}

/* Fail loud: the crash report covers the game so nothing broken looks fine. */
/* Shown instead of the game when another page frames it (src/game/main.js). */
#framed {
  position: fixed; inset: 0; display: grid; place-items: center; padding: 24px;
  text-align: center; font: 700 18px/1.4 system-ui, sans-serif; color: var(--ink); background: var(--bg, #0a0e0b);
}
#crash {
  position: fixed; inset: 12px; z-index: 100;
  display: flex; flex-direction: column; gap: 10px;
  padding: 16px;
  border: 2px solid #ff5a5a; border-radius: 14px;
  background: rgba(30, 6, 6, 0.96); color: #ffd9d9;
}
#crash[hidden] { display: none; }
#crash strong { color: #ff7b7b; font-size: 18px; }
#crash pre {
  flex: 1; margin: 0; overflow: auto;
  font: 12px/1.45 ui-monospace, SFMono-Regular, Menlo, monospace;
  white-space: pre-wrap; word-break: break-word;
}
#crash button {
  align-self: flex-start; padding: 8px 16px;
  border: 1px solid #ff7b7b; border-radius: 10px;
  background: transparent; color: inherit; font: inherit; font-weight: 700;
}

@media (min-width: 700px) {
  :root { --edge-t: calc(env(safe-area-inset-top, 0px) + 12px); }
  #depth { font-size: 14px; }
}

/* Keyboard users get a clear focus ring; touch users never see it. */
:focus-visible { outline: 2px solid rgba(127, 208, 122, 0.85); outline-offset: 2px; }

/* Short screens (landscape phones): keep the map visible and controls reachable. */
@media (max-height: 500px) {
  :root { --act: 72px; --sub: 50px; --gap: 10px; --edge-b: calc(env(safe-area-inset-bottom, 0px) + 14px); }
  #zoomControls { bottom: calc(var(--edge-b) + var(--act) + 64px); }
  #sheet { height: 88vh; }
  .tab { height: 34px; }
  .setRow { min-height: 44px; }
}

@supports (height: 100dvh) {
  #sheet { height: min(72dvh, 720px); }
  @media (max-height: 500px) { #sheet { height: 88dvh; } }
}

/* Respect the OS "reduce motion" setting. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; }
}
