/* ============================================================
   CryptoSprouts — Cozy Garden UI
   ============================================================ */

:root {
  color-scheme: light;

  /* Surfaces */
  --cream: #fbf3e0;
  --cream-2: #fff8ea;
  --panel: #fffaf0;
  --panel-2: #fff3da;

  /* Brand */
  --green: #5ba845;
  --green-d: #3f8a32;
  --green-l: #7bc466;
  --brown: #8b5a2b;
  --brown-d: #69401e;
  --gold: #f2b544;
  --gold-d: #d9962a;
  --coral: #e8794b;
  --water: #41b0d8;
  --water-d: #2f93ba;
  --purple: #9a6dd7;

  /* Text */
  --ink: #3a4530;
  --ink-soft: #5d5a44;
  --muted: #978d72;

  /* Lines & depth */
  --line: rgba(110, 84, 46, 0.16);
  --line-2: rgba(110, 84, 46, 0.28);
  --shadow-sm: 0 2px 6px rgba(96, 70, 38, 0.12);
  --shadow: 0 8px 22px rgba(96, 70, 38, 0.16);
  --shadow-lg: 0 16px 40px rgba(96, 70, 38, 0.22);

  --radius: 18px;
  --radius-sm: 13px;
  --radius-xs: 9px;

  --font-ui: "Nunito", system-ui, -apple-system, "Segoe UI", sans-serif;
  --font-display: "Fredoka", var(--font-ui);

  --hud-h: 58px;
}

* { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  color: var(--ink);
  font-family: var(--font-ui);
  font-weight: 600;
  -webkit-font-smoothing: antialiased;
  background:
    radial-gradient(1200px 480px at 50% -120px, #cdeeff 0%, rgba(205, 238, 255, 0) 70%),
    linear-gradient(180deg, #dff3c6 0%, #f4ecd6 220px, #f4ecd6 100%);
  background-attachment: fixed;
}

body::before {
  content: "";
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: -1;
  background-image: radial-gradient(rgba(120, 95, 55, 0.05) 1.5px, transparent 1.5px);
  background-size: 22px 22px;
}

h1, h2, h3, p { margin: 0; }

.muted { color: var(--muted); font-weight: 700; font-size: 12.5px; }

/* Pixel-art inline icons */
.ico-img {
  width: 1.25em; height: 1.25em;
  display: inline-block;
  vertical-align: -0.28em;
  background: center / contain no-repeat;
  image-rendering: pixelated;
}
.ico-sprout { background-image: url("assets/token-sprout.png?v=3"); }
.ico-coin { background-image: url("assets/coin.png?v=3"); }
.ico-fert { background-image: url("assets/fertilizer.png?v=2"); }
.ico-water { background-image: url("assets/watering-can.png?v=2"); }
/* Painted (not pixel-art) booster medallion — smooth scaling, no pixelation. */
.ico-booster-breeding {
  background-image: url("assets/booster-breeding.png?v=2");
  image-rendering: auto;
}
.ico-flower {
  background-image: url("assets/flower-scent.png?v=2");
  image-rendering: auto;
}
.ico-scarecrow { background-image: url("assets/scarecrow.png?v=4"); }

#app {
  width: min(1160px, 100%);
  margin: 0 auto;
  padding: 0 16px calc(96px + env(safe-area-inset-bottom)) ;
}

/* ---------------- HUD ---------------- */
.hud {
  position: sticky;
  top: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  gap: 12px;
  height: var(--hud-h);
  margin: 0 -16px 0;
  padding: 0 16px;
  background: rgba(255, 250, 240, 0.86);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  box-shadow: var(--shadow-sm);
}

.brand { display: flex; align-items: center; gap: 8px; }
.brand-logo {
  height: 42px;
  width: auto;
  display: block;
  filter: drop-shadow(0 2px 2px rgba(0, 0, 0, 0.18));
}

.hud-actions { display: flex; align-items: center; gap: 8px; }

.resources {
  display: flex;
  gap: 8px;
  margin-left: auto;
  overflow-x: auto;
  scrollbar-width: none;
}
.resources::-webkit-scrollbar { display: none; }

.chip {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  padding: 6px 12px 6px 9px;
  background: linear-gradient(180deg, var(--cream-2), #ffeec8);
  border: 1px solid var(--line-2);
  border-radius: 999px;
  box-shadow: var(--shadow-sm);
  white-space: nowrap;
}
.chip-ico { font-size: 15px; }
.chip .ico-img.chip-ico { width: 18px; height: 18px; vertical-align: -4px; }
.chip strong { font-family: var(--font-display); font-weight: 600; font-size: 15px; color: var(--ink); }
.chip-tag { font-size: 10px; font-weight: 800; color: var(--muted); letter-spacing: 0.5px; }
.chip-muted { background: linear-gradient(180deg, #fdeede, #f8dcc4); }

/* ---------------- Buttons ---------------- */
.btn {
  appearance: none;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 13.5px;
  color: #fff;
  border: none;
  border-radius: 999px;
  padding: 9px 16px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  line-height: 1;
  transition: transform 0.08s ease, box-shadow 0.15s ease, filter 0.15s ease;
  box-shadow: 0 3px 0 var(--btn-shade, rgba(0,0,0,0.18)), 0 6px 14px rgba(96,70,38,0.18);
}
.btn:hover { transform: translateY(-1px); filter: brightness(1.04); }
.btn:active { transform: translateY(3px); box-shadow: 0 0 0 var(--btn-shade, rgba(0,0,0,0.18)), 0 3px 8px rgba(96,70,38,0.18); }
.btn:disabled { cursor: not-allowed; filter: grayscale(0.5) brightness(0.98); opacity: 0.55; transform: none; box-shadow: var(--shadow-sm); }

.btn-primary { background: linear-gradient(180deg, var(--green-l), var(--green-d)); --btn-shade: #2f6e26; }
.btn-gold { background: linear-gradient(180deg, #ffce63, var(--gold-d)); color: #5a3d0a; --btn-shade: #b67c1f; }
.btn-water { background: linear-gradient(180deg, #62c7e6, var(--water-d)); --btn-shade: #237a9d; }
.btn-coral { background: linear-gradient(180deg, #f59169, #d4612f); --btn-shade: #ad4d24; }
.btn-warn { background: linear-gradient(180deg, #f5a34a, #d97d1c); color: #fff; --btn-shade: #a85e0f; }
.btn-danger { background: linear-gradient(180deg, #ef5a5a, #c62f2f); color: #fff; --btn-shade: #8f1f1f; }
.btn-ghost {
  background: var(--cream-2);
  color: var(--ink);
  --btn-shade: rgba(110,84,46,0.22);
  box-shadow: 0 2px 0 var(--btn-shade), 0 4px 10px rgba(96,70,38,0.12);
}
.btn-sm { padding: 7px 12px; font-size: 12px; }
.btn-block { width: 100%; margin-top: 10px; }

/* ---------------- Hero ---------------- */
.hero {
  position: relative;
  margin: 10px 0;
  height: 115px;
  border-radius: var(--radius);
  overflow: hidden;
  background: url("assets/scene.png?v=4") center 38% / cover no-repeat;
  box-shadow: var(--shadow), inset 0 -30px 40px -20px rgba(20,40,15,0.55);
  border: 3px solid #fff;
  outline: 1px solid var(--line-2);
  display: grid;
  place-items: center;
}
.hero-logo {
  position: relative;
  z-index: 2;
  height: 84px;
  width: auto;
  max-width: 88%;
  object-fit: contain;
  margin-top: -4px;
  filter: drop-shadow(0 6px 12px rgba(0, 0, 0, 0.4));
  animation: pop-in 0.45s ease both;
}
.hero-cap {
  position: absolute;
  left: 20px;
  bottom: 12px;
  right: 20px;
  text-align: center;
  color: #fff;
  text-shadow: 0 2px 8px rgba(0,0,0,0.65);
}
/* The half-height hero has no room for the caption without crowding the logo. */
.hero-cap p { display: none; }

.hero-bugs { position: absolute; inset: 0; pointer-events: none; }
.bug {
  position: absolute;
  background-repeat: no-repeat;
  image-rendering: pixelated;
  filter: drop-shadow(0 2px 3px rgba(0,0,0,0.3));
}
/* Animated insects. Each background is a horizontal sprite strip; background-size
   is N×(element width) so stepping background-position-x by one element-width
   advances exactly one frame. Two animations run together: the *-flap one cycles
   the wing frames (steps), and flit-* drifts the insect across the hero. */
.bug.bee      { width: 40px; height: 40px; background-image: url("assets/bee-fly.png?v=2");              background-size: 160px 128px; background-position-y: center; }
.bug.bfly-mon { width: 32px; height: 28px; background-image: url("assets/butterfly-monarch.png?v=4"); background-size: 352px 28px; }
@keyframes bee-flap      { from { background-position-x: 0; } to { background-position-x: -160px; } }
@keyframes bfly-mon-flap { from { background-position-x: 0; } to { background-position-x: -352px; } }
.bug.b1  { top: 20px; left: 7%;  animation: bee-flap      0.32s steps(4)  infinite, flit-a 7s ease-in-out infinite; }
.bug.bm1 { top: 28px; left: 83%; animation: bfly-mon-flap 0.85s steps(11) infinite, flit-c 6s ease-in-out infinite 1s; }

/* ---------------- Cards & layout ---------------- */
.card {
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}

.layout {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(330px, 0.82fr);
  gap: 16px;
  align-items: start;
}

.section-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin: 4px 2px 12px;
}
.section-head.sm { margin: 16px 2px 10px; }
.section-head h2 { font-family: var(--font-display); font-weight: 700; font-size: 20px; color: var(--ink); }
.section-head h3 { font-family: var(--font-display); font-weight: 600; font-size: 16px; color: var(--ink); }

.pill {
  font-size: 11px; font-weight: 800; padding: 4px 10px; border-radius: 999px;
  letter-spacing: 0.3px;
}
.pill-soft { background: #eef6e2; color: var(--green-d); }
.pill-warn { background: #fef3e2; color: #a85e0f; }
.pill-legacy { background: #edeae2; color: var(--muted); }

/* ---------------- Daily banner ---------------- */
.daily {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 14px;
  align-items: center;
  padding: 14px 16px;
  margin-bottom: 16px;
  background: linear-gradient(180deg, var(--panel), var(--panel-2));
}

/* ---------------- Live event banner ---------------- */
.event-banner {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px 16px;
  margin-bottom: 16px;
  background: linear-gradient(110deg, #6d3fb0, #b0427a, #e08a3d);
  color: #fff;
  border: none;
  box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.15);
}
.event-banner .event-emoji { font-size: 1.6rem; line-height: 1; }
.event-banner .event-body { flex: 1; display: flex; flex-direction: column; line-height: 1.25; }
.event-banner .event-body strong { font-size: 0.98rem; }
.event-banner .event-body span { font-size: 0.8rem; opacity: 0.9; }
.event-banner .event-timer {
  font-weight: 800; font-size: 0.85rem; white-space: nowrap;
  background: rgba(0, 0, 0, 0.25); padding: 4px 10px; border-radius: 999px;
}

/* ---------------- Tip of the Day ---------------- */
.tip {
  display: grid;
  grid-template-columns: auto 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 12px 14px;
  margin-bottom: 16px;
  background: linear-gradient(180deg, #fffdf4, #fff6da);
  border-color: var(--line-2);
}
.tip-icon {
  display: grid;
  place-items: center;
  width: 38px; height: 38px;
  border-radius: 12px;
  font-size: 18px;
  background: linear-gradient(180deg, #fff0cf, #ffd98f);
  border: 1px solid var(--line-2);
  box-shadow: var(--shadow-sm);
}
.tip-body { min-width: 0; }
.tip-head { font-size: 9px; font-weight: 800; letter-spacing: 0.06em; text-transform: uppercase; color: var(--gold-d); }
.tip-text { margin: 2px 0 0; font-size: 12.5px; font-weight: 600; line-height: 1.4; color: var(--ink); }
.tip-next {
  flex-shrink: 0;
  width: 30px; height: 30px;
  border-radius: 10px;
  border: 1px solid var(--line-2);
  background: var(--panel);
  color: var(--muted);
  font-size: 15px;
  cursor: pointer;
  transition: transform 0.2s ease, color 0.2s ease;
}
.tip-next:hover { color: var(--green-d); }
.tip-next:active { transform: rotate(180deg); }

/* Lunar Vault transparency banner (NFTs tab). */
.vault-banner {
  border-radius: 14px;
  padding: 12px 14px;
  margin-bottom: 14px;
  background: linear-gradient(180deg, #2a2350, #1c1838);
  border: 1px solid #4b3f87;
  color: #efeaff;
}
.vault-head { font-weight: 700; display: flex; align-items: center; gap: 8px; margin-bottom: 10px; }
.vault-reset { margin-left: auto; font-size: 10px; font-weight: 600; opacity: 0.6; }
.vault-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(72px, 1fr)); gap: 8px; text-align: center; }
.vault-grid div { background: rgba(255, 255, 255, 0.06); border-radius: 10px; padding: 8px 4px; }
.vault-grid strong { display: block; font-size: 15px; }
.vault-grid span { font-size: 11px; opacity: 0.7; }
.vault-unit { font-size: 9px; font-weight: 600; opacity: 0.6; letter-spacing: 0.02em; }
.vault-total { margin-top: 8px; font-size: 12px; opacity: 0.8; text-align: center; }
.vault-total strong { font-weight: 700; }
.vault-note { margin-top: 10px; font-size: 11px; opacity: 0.65; line-height: 1.35; }
.vault-perks { margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(255, 255, 255, 0.12); display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.vault-perks strong { font-size: 12px; color: #ffd86b; width: 100%; }
.perk-chip { font-size: 11px; font-weight: 700; padding: 3px 8px; border-radius: 999px; background: rgba(255, 216, 107, 0.16); color: #ffe9a8; }
.vault-supply { margin-top: 10px; }
.vault-supply-track { height: 6px; border-radius: 999px; background: rgba(255, 255, 255, 0.12); overflow: hidden; margin-bottom: 5px; }
.vault-supply-fill { height: 100%; border-radius: 999px; background: linear-gradient(90deg, #c49fff, #e8b8ff); transition: width 0.4s; }
.vault-supply-label { font-size: 11px; opacity: 0.75; text-align: center; }
.vault-supply-label strong { color: #e8b8ff; }
.vault-pace { margin-top: 8px; font-size: 11px; opacity: 0.75; text-align: center; }
.vault-pace strong { color: #ffd86b; }
.vault-feed { margin-top: 10px; padding-top: 10px; border-top: 1px solid rgba(255, 255, 255, 0.12); }
.vault-feed-head { font-size: 11px; font-weight: 700; opacity: 0.55; letter-spacing: 0.5px; text-transform: uppercase; margin-bottom: 6px; }
.vault-feed-item { display: flex; align-items: baseline; gap: 6px; font-size: 11px; padding: 3px 0; opacity: 0.85; }
.vault-feed-item:not(:last-child) { border-bottom: 1px solid rgba(255, 255, 255, 0.06); }
.vault-feed-name { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.vault-feed-slice { font-weight: 700; color: #c9f0a8; white-space: nowrap; }
.vault-feed-time { font-size: 10px; opacity: 0.5; white-space: nowrap; }

/* In-game Growth Stake / Greenhouse panel. The hero art already carries the
   "GREENHOUSE" sign + tagline, so no HTML title overlay is drawn on it. */
/* Dark-green backdrop for the whole Greenhouse tab, tying it to the art. */
#tab-stake { background: linear-gradient(180deg, #133021 0%, #0c1d13 55%, #09150d 100%); }
.greenhouse-hero { border-radius: 14px; overflow: hidden; margin-bottom: 10px; line-height: 0; box-shadow: 0 4px 16px rgba(0, 0, 0, 0.35); }
.greenhouse-hero img { width: 100%; height: auto; display: block; }
.stake-agg { background: linear-gradient(180deg, rgba(120, 200, 120, 0.16), rgba(120, 200, 120, 0.06)); border: 1px solid rgba(140, 220, 140, 0.3); border-radius: 10px; padding: 8px 10px; margin-bottom: 8px; font-size: 12px; font-weight: 600; color: #d3f0c9; }
.stake-note { padding: 10px 12px; font-size: 12px; background: rgba(255, 255, 255, 0.05); border-radius: 10px; }
.stake-durs { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-bottom: 8px; }
.stake-dur { appearance: none; cursor: pointer; border: 1px solid rgba(140, 220, 140, 0.28); background: rgba(120, 200, 120, 0.06); border-radius: 10px; padding: 8px 4px; display: grid; gap: 2px; justify-items: center; color: var(--ink-soft); font-family: var(--font-ui); transition: background 0.15s, border-color 0.15s; }
.stake-dur.sel { background: rgba(64, 132, 58, 0.85); border-color: rgba(150, 230, 150, 0.9); box-shadow: 0 0 0 1px rgba(150, 230, 150, 0.5) inset; }
.stake-dur-days { font-weight: 800; font-size: 13px; }
.stake-dur-sub { font-size: 10px; opacity: 0.75; }
.stake-dur.sel .stake-dur-days { color: #fff; }
.stake-dur.sel .stake-dur-sub { color: #eafbe6; opacity: 0.95; }
.stake-amount-row { display: flex; gap: 6px; align-items: center; margin-bottom: 6px; }
.stake-amount-row input { flex: 1; }
.stake-preview { font-size: 12px; line-height: 1.45; margin: 0 0 8px; min-height: 1em; }
.stake-preview b { color: #c9f0a8; }

/* Rows inside the dark clan/referral banner keep their cream background, so
   their text must stay dark — otherwise names inherit the banner's light
   lavender (#efeaff) and become unreadable on cream (clan members, board). */
.vault-banner .row { color: var(--ink); }
.vault-banner .row-title span.name { color: var(--ink); }
/* Section headings sit directly on the dark banner, so flip them to light. */
.vault-banner .section-head h3 { color: #efeaff; }
.vault-banner .section-head .muted { color: #c9c2e6; }

/* Referral invite card (Rank tab). Reuses the vault-banner shell. */
.referral-banner { background: linear-gradient(180deg, #2a3d2a, #1c2e1c); border-color: #4b8a4f; }
.referral-link-row { display: flex; gap: 8px; margin-top: 10px; }
.referral-link-row input {
  flex: 1; min-width: 0; padding: 9px 10px; font-size: 12px; font-weight: 700;
  border: 1px solid rgba(255, 255, 255, 0.25); border-radius: 10px;
  background: rgba(255, 255, 255, 0.08); color: #efeaff;
}
.referral-link-row .btn { flex: none; }
.streak-badge {
  display: grid;
  place-items: center;
  width: 58px; height: 58px;
  border-radius: 16px;
  background: linear-gradient(180deg, #fff0cf, #ffd98f);
  border: 1px solid var(--line-2);
  box-shadow: var(--shadow-sm);
  text-align: center;
  line-height: 1;
}
.streak-badge .flame { font-size: 18px; }
.streak-badge b { font-family: var(--font-display); font-weight: 700; font-size: 20px; color: var(--gold-d); }
.streak-badge small { font-size: 9px; font-weight: 800; color: var(--muted); text-transform: uppercase; }

.quests { display: grid; gap: 8px; }
.quest { display: grid; gap: 4px; }
.quest .q-top { display: flex; justify-content: space-between; font-size: 12px; font-weight: 800; }
.quest.done .q-top { color: var(--green-d); }
.q-bar { height: 9px; border-radius: 999px; background: #ece1c4; overflow: hidden; }
.q-bar i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--green-l), var(--green)); transition: width 0.4s ease; }

/* ---------------- Plots ---------------- */
.plots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(196px, 1fr));
  gap: 14px;
}

.plot {
  position: relative;
  border-radius: var(--radius);
  overflow: hidden;
  background: linear-gradient(180deg, #bfe6ff 0%, #d8f0ff 44%, #cdeebf 44%, #cdeebf 100%);
  border: 1px solid var(--line);
  box-shadow: var(--shadow);
  transition: transform 0.18s ease, box-shadow 0.18s ease;
  animation: pop-in 0.35s ease both;
}
.plot:hover { transform: translateY(-3px); box-shadow: var(--shadow-lg); }
.plot.ready { box-shadow: var(--shadow-lg), 0 0 0 3px rgba(242,181,68,0.55); }

.plot-body {
  position: relative;
  display: grid;
  place-items: end center;
  min-height: 186px;
  padding-bottom: 4px;
  /* The crop sprites carry their own soil mound, so the plot just provides a
     soft grassy bed for them to sit on — no second, clashing soil texture. */
  background: radial-gradient(125% 58% at 50% 100%,
    #a7d56b 0%, #a7d56b 40%, rgba(167, 213, 107, 0) 72%) bottom / 100% 64px no-repeat;
}

.farm-actions { display: flex; gap: 8px; margin-bottom: 10px; }
.farm-actions .btn { flex: 1; }

/* Farm switcher (Phase 2): step between owned farms and buy a new one. */
.farm-switcher { margin-bottom: 10px; }
.farm-switcher[hidden] { display: none; }
.farm-switch-row {
  display: flex; align-items: center; gap: 8px;
  padding: 6px 10px; border-radius: var(--radius-sm);
  background: var(--panel-2, rgba(255, 255, 255, 0.5)); border: 1px solid var(--line-2);
}
.farm-switch-row .farm-label {
  font-family: var(--font-display); font-weight: 700; font-size: 14px; color: var(--ink);
}
.farm-switch-row .farm-prev, .farm-switch-row .farm-next {
  min-width: 32px; padding: 4px 8px; font-size: 16px; line-height: 1;
}
.farm-switch-row .farm-buy { margin-left: auto; white-space: nowrap; }

/* ---------------- Farm scene (single illustrated field, 4x3 plot grid) ---- */
.farm-scene {
  position: relative;
  width: 100%;
  aspect-ratio: 1 / 1;
  /* Field-green fallback shown only if a scene layer is ever missing; in normal
     use the .farm-layer card(s) cover the whole square so this never shows. */
  background: #8fc96b;
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow);
  border: 3px solid #fff;
  outline: 1px solid var(--line-2);
  container-type: inline-size;
  animation: pop-in 0.35s ease both;
  /* Let the page scroll vertically, but reserve horizontal drags for the
     farm-switch swipe gesture (see initFarmSwipe) so the webview doesn't
     hijack them as navigation. */
  touch-action: pan-y;
}

/* The full farm "card": background + plots + every sprite in one absolutely
   positioned layer that slides on a farm switch. Two exist briefly during a
   slide — the outgoing snapshot (a clone) and the incoming live layer — so the
   whole square (background included) leaves one edge as the next enters the
   other. Per-farm scenery can later be driven by adding a scene class here. */
.farm-layer {
  position: absolute; inset: 0;
  background: url("assets/farm-scene.png?v=9") center / cover no-repeat;
  will-change: transform;
}
/* Time-of-day + weather skins. JS (applyFarmAmbience) toggles these classes on
   #plots by the clock; the background lives on the layer(s) inside, so the live
   layer and any in-flight clone show the same sky. */
#plots.farm-dusk  .farm-layer { background-image: url("assets/farm-scene-sunset.png?v=2"); }
#plots.farm-night .farm-layer { background-image: url("assets/farm-scene-night.png?v=2"); }

/* Rainy day: its own overcast scene, with rain-drop sprites animated on top.
   The overlay sits under crop/critter layers (z 1) but above the field art.
   The dusk hours (sunrise/sunset) reuse this same scene on a rainy day, and
   rainy night reuses the same rain-drop overlay over a dedicated night-rain
   scene, so the storm keeps falling from dawn to dark on a rainy day. */
#plots.farm-rain .farm-layer { background-image: url("assets/farm-scene-rain.png?v=2"); }
#plots.farm-rain-night .farm-layer { background-image: url("assets/farm-scene-rain-night.png?v=5"); }
#plots.farm-rain .farm-layer::after,
#plots.farm-rain-night .farm-layer::after {
  content: "";
  position: absolute;
  inset: -20%;
  z-index: 0;
  pointer-events: none;
  background-image:
    url("assets/rain-drops-1.png?v=2"),
    url("assets/rain-drops-2.png?v=2");
  background-size: 50% 50%, 50% 50%;
  background-repeat: repeat;
  background-position: 0 0, 25% 50%;
  transform: rotate(10deg);
  opacity: 0.85;
  animation: farm-rain-drop-fall 1.2s linear infinite;
  will-change: background-position;
}
@keyframes farm-rain-drop-fall {
  from { background-position: 0 0,    25% 50%; }
  to   { background-position: 0 100%, 25% 150%; }
}
@media (prefers-reduced-motion: reduce) {
  #plots.farm-rain .farm-layer::after,
  #plots.farm-rain-night .farm-layer::after { animation: none; }
}
/* Plot cells live in their own layer so the wandering frog overlay (a sibling)
   survives each renderPlots() innerHTML swap without losing its JS-held node. */
#plot-cells { position: absolute; inset: 0; }

/* Wandering frog. Position/hops are driven from JS (see the Frog controller);
   the background is an 11-frame sprite strip stepped via background-position-x.
   Sized in cqw against the farm-scene container so it scales with the board. */
.frog2 {
  position: absolute;
  width: 11cqw; height: 11cqw;
  background: url("assets/frog-jump.png?v=2") 0 0 no-repeat;
  background-size: 121cqw 11cqw; /* 11 frames × 11cqw */
  image-rendering: pixelated;
  pointer-events: none;
  z-index: 4;
  opacity: 0;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -90%);
  filter: drop-shadow(1px 2px 2px rgba(0, 0, 0, 0.35));
  will-change: transform, left;
}

/* Wandering butterfly. It flies in from a random side, perches on one of the
   planted plots for a beat, then flutters off again — all driven from JS (see
   the Butterfly controller). The background is an 11-frame wing-flap strip
   stepped via background-position-x; sized in cqw so it scales with the board.
   Anchored at its bottom-centre (translateY -100%) so a perch point sits on the
   plant it lands on. */
.bfly2 {
  position: absolute;
  width: 6.5cqw; height: 5.69cqw;          /* one frame = 64 x 56 px */
  background: url("assets/butterfly-monarch.png?v=4") 0 0 no-repeat;
  background-size: 71.5cqw 5.69cqw;          /* 11 frames x 6.5cqw */
  image-rendering: pixelated;
  pointer-events: none;
  z-index: 5;
  opacity: 0;
  transition: opacity 0.4s ease;
  transform: translate(-50%, -100%);
  filter: drop-shadow(1px 2px 2px rgba(0, 0, 0, 0.3));
  will-change: transform, left, top;
}
@keyframes bfly2-flap { from { background-position-x: 0; } to { background-position-x: -71.5cqw; } }

/* Per-farm scarecrow guard. Shown only while the farm in view is protected
   (toggled from JS). Fixed on the right-hand grass strip between the plots and
   the fence, level with the central plot row. Anchored at its bottom centre;
   pointer-events:none so taps pass through to the plots beneath it. Sized in cqw
   so it scales with the board. A single still pose — it just stands guard; the
   only motion is the pop-in when it first appears. */
.scarecrow2 {
  position: absolute;
  left: 81%; top: 48%;
  width: 11.5cqw;
  aspect-ratio: 238 / 294;
  background: url("assets/scarecrow.png?v=4") center / contain no-repeat;
  image-rendering: pixelated;
  pointer-events: none;
  z-index: 3;
  transform: translate(-50%, -100%);
  filter: drop-shadow(2px 4px 3px rgba(0, 0, 0, 0.32));
  animation: pop-in 0.4s ease both;
}
.scarecrow2[hidden] { display: none; }

/* Raiding crow. Flown onto a plot a crow has just eaten by the CrowRaid
   controller; the background is an 8-frame flapping strip stepped via
   background-position-x, anchored at its bottom-centre so it lands on the plant. */
.crow2 {
  position: absolute;
  width: 9cqw; height: 9cqw;
  background: url("assets/crow-fly.png?v=3") 0 0 no-repeat;
  background-size: 72cqw 9cqw;             /* 8 frames × 9cqw */
  image-rendering: pixelated;
  pointer-events: none;
  z-index: 7;
  opacity: 0;
  display: none;
  transition: opacity 0.3s ease;
  transform: translate(-50%, -90%);
  filter: drop-shadow(1px 2px 2px rgba(0, 0, 0, 0.4));
  will-change: transform, left, top, background-position;
}
@keyframes crow2-flap { from { background-position-x: 0; } to { background-position-x: -72cqw; } }
/* While settled on a raided plot the crow shows a single grounded/pecking pose
   instead of the flight strip. */
.crow2.pecking {
  background-image: url("assets/crow-peck.png?v=3");
  background-size: contain;
  animation: none;
}

/* The plant a crow is devouring: the server already cleared the plot, so the
   raid controller re-draws the eaten crop here (positioned like its plot cell)
   for the crow to land on, then fades it out — shrinking toward the stem base —
   the moment it's pecked away. Sits just under the crow overlay. */
.crow-victim {
  z-index: 4;
  pointer-events: none;
  transform-origin: 50% 90%;
  transition: opacity 0.45s ease, transform 0.45s ease;
}
.crow-victim.eaten { opacity: 0; transform: scale(0.45); }

/* Panda Farmer: walks around the assigned farm plot-by-plot, planting, watering
   and harvesting autonomously. Sprite sheet: 1408×768px,
   8 cols × 4 rows, uniform cell 176×192px → element 12cqw × 15cqw.
   Background-size: 96cqw × 60cqw (8×12 by 4×15).
   Row 3 cols 6-7 (unused jump frames) keep a transparent gutter at the
   top of their cells: their hats touched the row-2/row-3 boundary, and
   fractional cqw scaling made the dig frames' bottom edge sample them,
   drawing a light line under the panda while digging.
   Row layout (0-based, y = -row×15cqw, x = -col×12cqw):
     0 WALK-side 8f (flip scaleX for left; reused as trot)
     1 WALK-down/front 6f (cols 0-5) · WATER 2f (cols 6-7)
     2 WALK-up/back 4f (cols 0-3) · PLANT/dig 4f (cols 4-7)
     3 celebration 4f (cols 0-3, unused) · IDLE 2f (cols 4-5) · jump 2f (cols 6-7, unused)
   Sideways walk flips via scaleX; vertical movement uses rows 1/2. */
.panda2 {
  position: absolute;
  width: 12cqw; height: 15cqw;
  background: url("assets/panda-farmer.png?v=12") 0 0 no-repeat;
  background-size: 96cqw 60cqw;
  image-rendering: pixelated;
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  opacity: 0;
  display: none;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -85%);
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.35));
  will-change: transform, left, top;
}
.panda2[hidden] { display: none; }
/* Row 3, cols 4-5 – idle, 2 frames */
@keyframes panda2-idle {
  from { background-position: -48cqw -45cqw; }
  to   { background-position: -72cqw -45cqw; }
}
/* Row 0 – walk sideways, 8 frames (flip scaleX for left) */
@keyframes panda2-walk {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Row 0 – trot/run, 8 frames (reuse walk-side row) */
@keyframes panda2-trot {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Row 1, cols 0-5 – walk down, 6 frames */
@keyframes panda2-walk-down {
  from { background-position: 0 -15cqw; }
  to   { background-position: -72cqw -15cqw; }
}
/* Row 2, cols 0-3 – walk up (back-view), 4 frames */
@keyframes panda2-walk-up {
  from { background-position: 0 -30cqw; }
  to   { background-position: -48cqw -30cqw; }
}
/* Row 2, cols 4-7 – plant/harvest, 4 frames (shovel + bend-down) */
@keyframes panda2-plant {
  from { background-position: -48cqw -30cqw; }
  to   { background-position: -96cqw -30cqw; }
}
/* Row 1, cols 6-7 – water, 2 frames */
@keyframes panda2-water {
  from { background-position: -72cqw -15cqw; }
  to   { background-position: -96cqw -15cqw; }
}

/* Shark Farmer sprite (1408×768 source → 8 cols × 4 rows, frame 176×192px).
   Displayed at 12cqw × 15cqw, background-size: 96cqw × 60cqw (8×12 by 4×15).
   Real row layout (0-based, y = -row×15cqw, x = -col×12cqw):
     0 WALK-side, 8f (flip scaleX for left; reused as trot)
     1 WALK-down/front 6f (cols 0-5) · WATER 2f (cols 6-7)
     2 WALK-up/back 4f (cols 0-3) · PLANT/dig 4f (cols 4-7)
     3 IDLE 4f (cols 0-3) · map/wave emotes (cols 4-7, unused)
   Dev-mode-only — never rendered in production. */
.shark2 {
  position: absolute;
  width: 12cqw; height: 15cqw;
  background: url("assets/shark-farmer.png?v=2") 0 0 no-repeat;
  background-size: 96cqw 60cqw;
  image-rendering: pixelated;
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  opacity: 0;
  display: none;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -85%);
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.35));
  will-change: transform, left, top;
}
.shark2[hidden] { display: none; }
/* Row 3 – idle: gentle 2-frame breathing (cols 0-1). */
@keyframes shark2-idle {
  from { background-position: 0 -45cqw; }
  to   { background-position: -24cqw -45cqw; }
}
/* Row 0 – walk sideways, 8 frames (flip scaleX for left). */
@keyframes shark2-walk {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Trot reuses the row-0 side walk (no dedicated run row), 8 frames. */
@keyframes shark2-trot {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Row 1 – walk down/front, 6 frames (cols 0-5; cols 6-7 are watering). */
@keyframes shark2-walk-down {
  from { background-position: 0 -15cqw; }
  to   { background-position: -72cqw -15cqw; }
}
/* Row 2 – walk up/back, 4 frames (cols 0-3; cols 4-7 are digging). */
@keyframes shark2-walk-up {
  from { background-position: 0 -30cqw; }
  to   { background-position: -48cqw -30cqw; }
}
/* Row 2 – plant/dig, 4 frames (cols 4-7). */
@keyframes shark2-plant {
  from { background-position: -48cqw -30cqw; }
  to   { background-position: -96cqw -30cqw; }
}
/* Row 1 – water, 2 frames (cols 6-7). */
@keyframes shark2-water {
  from { background-position: -72cqw -15cqw; }
  to   { background-position: -96cqw -15cqw; }
}

/* Fox Farmer sprite (1408×768 source → 8 cols × 4 rows, frame 176×192px).
   Displayed at 12cqw × 15cqw, background-size: 96cqw × 60cqw (8×12 by 4×15).
   Row layout (0-based, y = -row×15cqw, x = -col×12cqw):
     0 WALK-side, 8f (flip scaleX for left; reused as trot)
     1 WALK-down/front 6f (cols 0-5) · WATER 2f (cols 6-7)
     2 WALK-up/back 4f (cols 0-3) · PLANT/dig 4f (cols 4-7)
     3 IDLE 2f (cols 0-1) */
.fox2 {
  position: absolute;
  width: 12cqw; height: 15cqw;
  background: url("assets/fox-farmer.png?v=4") 0 0 no-repeat;
  background-size: 96cqw 60cqw;
  image-rendering: pixelated;
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  opacity: 0;
  display: none;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -85%);
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.35));
  will-change: transform, left, top;
}
.fox2[hidden] { display: none; }
/* Idle when standing still: Row 1 cols 0-1 — a neutral, closed-mouth pose
   (Row 3 cols 0-1 had an open mouth). 2 frames for a subtle breathing loop. */
@keyframes fox2-idle {
  from { background-position: 0 -15cqw; }
  to   { background-position: -24cqw -15cqw; }
}
/* Row 0 – walk sideways, 8 frames (flip scaleX for left) */
@keyframes fox2-walk {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Trot reuses the row-0 side walk, 8 frames. */
@keyframes fox2-trot {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Row 1 – walk down/front, 6 frames (cols 0-5) */
@keyframes fox2-walk-down {
  from { background-position: 0 -15cqw; }
  to   { background-position: -72cqw -15cqw; }
}
/* Row 2 – walk up/back, 4 frames (cols 0-3) */
@keyframes fox2-walk-up {
  from { background-position: 0 -30cqw; }
  to   { background-position: -48cqw -30cqw; }
}
/* Row 2 – plant/dig, 4 frames (cols 4-7) */
@keyframes fox2-plant {
  from { background-position: -48cqw -30cqw; }
  to   { background-position: -96cqw -30cqw; }
}
/* Row 1 – water, 2 frames (cols 6-7) */
@keyframes fox2-water {
  from { background-position: -72cqw -15cqw; }
  to   { background-position: -96cqw -15cqw; }
}

/* Panda Farmer LE sprite (limited edition) — same 8×4 / 176×192 layout as the
   fox sheet, so it reuses the identical geometry with the LE art. */
.pandale2 {
  position: absolute;
  width: 12cqw; height: 15cqw;
  background: url("assets/panda-farmer-le.png?v=3") 0 0 no-repeat;
  background-size: 96cqw 60cqw;
  image-rendering: pixelated;
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  opacity: 0;
  display: none;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -85%);
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.35));
  will-change: transform, left, top;
}
.pandale2[hidden] { display: none; }
/* Freestyle (embaixadinha) sheet: panda-juggle.png, 8 cols × 5 rows
   (176×192px each, same cell geometry as the main sheet):
     Row 0 – lateral keepie-uppies · Row 1 – chest kill ("matando no peito")
     Row 2 – run-up + jump header  · Row 3 – celebration
     Row 4 – front-facing keepie-uppies (the original juggle strip: the ball
             travels a vertical line through the body centre and balances on
             the head)
   The animations hand-pick cells instead of walking each row: a few source
   frames read as handling the ball (paw touching it) or carry white impact
   puffs between panda and ball, so those cells are skipped entirely and the
   keyframes jump between the clean football poses. Everything runs with
   `step-end` and non-uniform stops so the ball obeys real timing: fast while
   travelling, hanging at the apex, quick at each contact. The .juggle class
   is toggled by PandaleFarmer whenever a freestyle animation plays. */
.pandale2.juggle {
  background-image: url("assets/panda-juggle.png?v=9");
  background-size: 96cqw 75cqw; /* 8 cols × 12cqw, 5 rows × 15cqw */
}
/* Keepie-uppie loop (row 0, cells 0/3/4/5/3/7 — knee-and-foot touches only):
   knee flicks it up, ball rises past the head, hangs at the apex, falls back
   and the other knee catches it. Runs with step-end (set from JS), so each
   stop below holds until the next one. */
@keyframes pandale2-idle {
  0%   { background-position: 0      0; }  /* knee kick */
  15%  { background-position: -36cqw 0; }  /* rising past the head */
  31%  { background-position: -48cqw 0; }  /* apex above the head */
  52%  { background-position: -60cqw 0; }  /* hangs, tips over */
  66%  { background-position: -36cqw 0; }  /* falling back down */
  82%, 100% { background-position: -84cqw 0; } /* other knee takes it */
}
/* Chest kill (row 1, cells 0/1/4/5/6/7): ball flies in fast, meets the chest
   (contact implied between the arrival and the pop-up), hangs above the head,
   then drops and dies at the feet. Cells 2-3 (white impact puffs, ball at paw
   height) are skipped. */
@keyframes pandale2-chest {
  0%   { background-position: 0      -15cqw; }
  13%  { background-position: -12cqw -15cqw; }
  30%  { background-position: -48cqw -15cqw; }
  54%  { background-position: -60cqw -15cqw; }
  66%  { background-position: -72cqw -15cqw; }
  80%, 100% { background-position: -84cqw -15cqw; }
}
/* Juggle sheet row 2 – run-up + jump header. Even run strides (f0–f1),
   explosive takeoff (f2), slower rise to the ball (f3), snap head contact
   (f4), ball sails off while he falls (f5), landing crouch absorbs (f6),
   stand back up (f7). */
@keyframes pandale2-header {
  0%   { background-position: 0      -30cqw; }
  12%  { background-position: -12cqw -30cqw; }
  24%  { background-position: -24cqw -30cqw; }
  33%  { background-position: -36cqw -30cqw; }
  47%  { background-position: -48cqw -30cqw; }
  56%  { background-position: -60cqw -30cqw; }
  70%  { background-position: -72cqw -30cqw; }
  84%, 100% { background-position: -84cqw -30cqw; }
}
/* Celebration (row 3, cells 3-7): winks at the ball by his feet, arms go up,
   a little hop, lands and finishes with his foot on the ball. Cells 0-1 are
   skipped — they hold the ball in a paw, which reads as a handball. The ball
   stays on the ground through the hop (composited into cells 4-6 at build
   time). */
@keyframes pandale2-celebrate {
  0%   { background-position: -36cqw -45cqw; }
  22%  { background-position: -48cqw -45cqw; }
  44%  { background-position: -60cqw -45cqw; }
  66%  { background-position: -72cqw -45cqw; }
  84%, 100% { background-position: -84cqw -45cqw; }
}
/* Front keepie-uppies (row 4, all 8 frames): ground → knee flick → face →
   balances on the head for two beats → drops past the face → belly → ground.
   Uniform frames (steps(8) from JS), torso-aligned so nothing drifts. */
@keyframes pandale2-idle-front {
  from { background-position: 0      -60cqw; }
  to   { background-position: -96cqw -60cqw; }
}
/* Main sheet – standing idle, Row 1 cols 0-1 (neutral front pose).
   Alternates with the keepie-uppie idle so it doesn't get repetitive. */
@keyframes pandale2-stand {
  from { background-position: 0 -15cqw; }
  to   { background-position: -24cqw -15cqw; }
}
/* Row 0 – walk sideways, 8 frames (flip scaleX for left) */
@keyframes pandale2-walk {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Trot reuses the row-0 side walk, 8 frames. */
@keyframes pandale2-trot {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Row 1 – walk down/front, 6 frames (cols 0-5) */
@keyframes pandale2-walk-down {
  from { background-position: 0 -15cqw; }
  to   { background-position: -72cqw -15cqw; }
}
/* Row 2 – walk up/back, 4 frames (cols 0-3) */
@keyframes pandale2-walk-up {
  from { background-position: 0 -30cqw; }
  to   { background-position: -48cqw -30cqw; }
}
/* Row 2 – plant/dig, 4 frames (cols 4-7) */
@keyframes pandale2-plant {
  from { background-position: -48cqw -30cqw; }
  to   { background-position: -96cqw -30cqw; }
}
/* Row 1 – water, 2 frames (cols 6-7) */
@keyframes pandale2-water {
  from { background-position: -72cqw -15cqw; }
  to   { background-position: -96cqw -15cqw; }
}

/* Porcupine Farmer sprite (1408×768 source → 8 cols × 4 rows, frame 176×192px).
   Same layout as the fox/shark; dev-mode-only. */
.porcupine2 {
  position: absolute;
  width: 12cqw; height: 15cqw;
  background: url("assets/porcupine-farmer.png?v=2") 0 0 no-repeat;
  background-size: 96cqw 60cqw;
  image-rendering: pixelated;
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  opacity: 0;
  display: none;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -85%);
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.35));
  will-change: transform, left, top;
}
.porcupine2[hidden] { display: none; }
/* Row 3 – idle, 2 frames (cols 0-1) */
@keyframes porcupine2-idle {
  from { background-position: 0 -45cqw; }
  to   { background-position: -24cqw -45cqw; }
}
/* Row 0 – walk sideways, 8 frames (flip scaleX for left) */
@keyframes porcupine2-walk {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Trot reuses the row-0 side walk, 8 frames. */
@keyframes porcupine2-trot {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Row 1 – walk down/front, 6 frames (cols 0-5) */
@keyframes porcupine2-walk-down {
  from { background-position: 0 -15cqw; }
  to   { background-position: -72cqw -15cqw; }
}
/* Row 2 – walk up/back, 4 frames (cols 0-3) */
@keyframes porcupine2-walk-up {
  from { background-position: 0 -30cqw; }
  to   { background-position: -48cqw -30cqw; }
}
/* Row 2 – plant/dig, 4 frames (cols 4-7) */
@keyframes porcupine2-plant {
  from { background-position: -48cqw -30cqw; }
  to   { background-position: -96cqw -30cqw; }
}
/* Row 1 – water, 2 frames (cols 6-7) */
@keyframes porcupine2-water {
  from { background-position: -72cqw -15cqw; }
  to   { background-position: -96cqw -15cqw; }
}

/* Alligator Farmer sprite (1408×768 source → 8 cols × 4 rows, frame 176×192px).
   Same layout as the fox/porcupine; dev-mode-only. */
.alligator2 {
  position: absolute;
  width: 12cqw; height: 15cqw;
  background: url("assets/alligator-farmer.png?v=2") 0 0 no-repeat;
  background-size: 96cqw 60cqw;
  image-rendering: pixelated;
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  opacity: 0;
  display: none;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -85%);
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.35));
  will-change: transform, left, top;
}
.alligator2[hidden] { display: none; }
/* Row 3 – idle, 2 frames (cols 0-1) */
@keyframes alligator2-idle {
  from { background-position: 0 -45cqw; }
  to   { background-position: -24cqw -45cqw; }
}
/* Row 0 – walk sideways, 8 frames (flip scaleX for left) */
@keyframes alligator2-walk {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Trot reuses the row-0 side walk, 8 frames. */
@keyframes alligator2-trot {
  from { background-position: 0 0; }
  to   { background-position: -96cqw 0; }
}
/* Row 1 – walk down/front, 6 frames (cols 0-5) */
@keyframes alligator2-walk-down {
  from { background-position: 0 -15cqw; }
  to   { background-position: -72cqw -15cqw; }
}
/* Row 2 – walk up/back, 4 frames (cols 0-3) */
@keyframes alligator2-walk-up {
  from { background-position: 0 -30cqw; }
  to   { background-position: -48cqw -30cqw; }
}
/* Row 2 – plant/dig, 4 frames (cols 4-7) */
@keyframes alligator2-plant {
  from { background-position: -48cqw -30cqw; }
  to   { background-position: -96cqw -30cqw; }
}
/* Row 1 – water, 2 frames (cols 6-7) */
@keyframes alligator2-water {
  from { background-position: -72cqw -15cqw; }
  to   { background-position: -96cqw -15cqw; }
}

/* Bat Farmer sprite (1408×768 source → 8 cols × 4 rows, frame 176×192px).
   Same layout as the fox/alligator; dev-mode-only. The bat art is drawn ~17%
   larger inside its cells than the other farmers, so the whole sprite (and its
   keyframe offsets) is rendered at 0.85× to match their on-screen size. */
.bat2 {
  position: absolute;
  width: 10.2cqw; height: 12.75cqw;
  background: url("assets/bat-farmer.png?v=2") 0 0 no-repeat;
  background-size: 81.6cqw 51cqw;
  image-rendering: pixelated;
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  opacity: 0;
  display: none;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -85%);
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.35));
  will-change: transform, left, top;
}
.bat2[hidden] { display: none; }
/* Row 0 – idle, 2 frames (cols 0-1) — calm closed-mouth front pose. Row 3 is the
   mouth-open laugh, so idle borrows the neutral row-0 frames instead. */
@keyframes bat2-idle {
  from { background-position: 0 0; }
  to   { background-position: -20.4cqw 0; }
}
/* Row 0 – walk sideways, 8 frames (flip scaleX for left) */
@keyframes bat2-walk {
  from { background-position: 0 0; }
  to   { background-position: -81.6cqw 0; }
}
/* Trot reuses the row-0 side walk, 8 frames. */
@keyframes bat2-trot {
  from { background-position: 0 0; }
  to   { background-position: -81.6cqw 0; }
}
/* Row 1 – walk down/front, 6 frames (cols 0-5) */
@keyframes bat2-walk-down {
  from { background-position: 0 -12.75cqw; }
  to   { background-position: -61.2cqw -12.75cqw; }
}
/* Row 2 – walk up/back, 4 frames (cols 0-3) */
@keyframes bat2-walk-up {
  from { background-position: 0 -25.5cqw; }
  to   { background-position: -40.8cqw -25.5cqw; }
}
/* Row 2 – plant/dig, 4 frames (cols 4-7) */
@keyframes bat2-plant {
  from { background-position: -40.8cqw -25.5cqw; }
  to   { background-position: -81.6cqw -25.5cqw; }
}
/* Row 1 – water, 2 frames (cols 6-7) */
@keyframes bat2-water {
  from { background-position: -61.2cqw -12.75cqw; }
  to   { background-position: -81.6cqw -12.75cqw; }
}

/* Sheep Farmer sprite (1408×768 source → 8 cols × 4 rows, frame 176×192px).
   Same layout as the bat; dev-mode-only. The sheep art is drawn larger inside
   its cells than the standard farmers, so the whole sprite (and its keyframe
   offsets) is rendered at 0.86× to keep its on-screen size in proportion. */
.sheep2 {
  position: absolute;
  width: 10.32cqw; height: 12.9cqw;
  background: url("assets/sheep-farmer.png?v=2") 0 0 no-repeat;
  background-size: 82.56cqw 51.6cqw;
  image-rendering: pixelated;
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  opacity: 0;
  display: none;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -85%);
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.35));
  will-change: transform, left, top;
}
.sheep2[hidden] { display: none; }
/* Row 0 – idle, 2 frames (cols 0-1) — calm closed-mouth front pose. Row 3 is the
   mouth-open laugh, so idle borrows the neutral row-0 frames instead. */
@keyframes sheep2-idle {
  from { background-position: 0 0; }
  to   { background-position: -20.64cqw 0; }
}
/* Row 0 – walk sideways, 8 frames (flip scaleX for left) */
@keyframes sheep2-walk {
  from { background-position: 0 0; }
  to   { background-position: -82.56cqw 0; }
}
/* Trot reuses the row-0 side walk, 8 frames. */
@keyframes sheep2-trot {
  from { background-position: 0 0; }
  to   { background-position: -82.56cqw 0; }
}
/* Row 1 – walk down/front, 6 frames (cols 0-5) */
@keyframes sheep2-walk-down {
  from { background-position: 0 -12.9cqw; }
  to   { background-position: -61.92cqw -12.9cqw; }
}
/* Row 2 – walk up/back, 4 frames (cols 0-3) */
@keyframes sheep2-walk-up {
  from { background-position: 0 -25.8cqw; }
  to   { background-position: -41.28cqw -25.8cqw; }
}
/* Row 2 – plant/dig, 4 frames (cols 4-7) */
@keyframes sheep2-plant {
  from { background-position: -41.28cqw -25.8cqw; }
  to   { background-position: -82.56cqw -25.8cqw; }
}
/* Row 1 – water, 2 frames (cols 6-7) */
@keyframes sheep2-water {
  from { background-position: -61.92cqw -12.9cqw; }
  to   { background-position: -82.56cqw -12.9cqw; }
}

/* Mantis Farmer sprite (1408×768 source → 8 cols × 4 rows, frame 176×192px).
   Row layout matches the bat/sheep: row 0 is the neutral front pose (idle borrows
   its first frames), row 3 is the mouth-open laugh. The mantis art is drawn larger
   inside its cells than the standard farmers, so the whole sprite (and its keyframe
   offsets) is rendered at 0.85× to keep its on-screen size in proportion.
   Dev-mode-only. */
.mantis2 {
  position: absolute;
  width: 10.2cqw; height: 12.75cqw;
  background: url("assets/mantis-farmer.png?v=2") 0 0 no-repeat;
  background-size: 81.6cqw 51cqw;
  image-rendering: pixelated;
  pointer-events: auto;
  cursor: pointer;
  z-index: 4;
  opacity: 0;
  display: none;
  transition: opacity 0.45s ease;
  transform: translate(-50%, -85%);
  filter: drop-shadow(1px 2px 2px rgba(0,0,0,0.35));
  will-change: transform, left, top;
}
.mantis2[hidden] { display: none; }
/* Row 0 – idle, 2 frames (cols 0-1) — calm front pose. */
@keyframes mantis2-idle {
  from { background-position: 0 0; }
  to   { background-position: -20.4cqw 0; }
}
/* Row 0 – walk sideways, 8 frames (flip scaleX for left) */
@keyframes mantis2-walk {
  from { background-position: 0 0; }
  to   { background-position: -81.6cqw 0; }
}
/* Trot reuses the row-0 side walk, 8 frames. */
@keyframes mantis2-trot {
  from { background-position: 0 0; }
  to   { background-position: -81.6cqw 0; }
}
/* Row 1 – walk down/front, 6 frames (cols 0-5) */
@keyframes mantis2-walk-down {
  from { background-position: 0 -12.75cqw; }
  to   { background-position: -61.2cqw -12.75cqw; }
}
/* Row 2 – walk up/back, 4 frames (cols 0-3) */
@keyframes mantis2-walk-up {
  from { background-position: 0 -25.5cqw; }
  to   { background-position: -40.8cqw -25.5cqw; }
}
/* Row 2 – plant/dig, 4 frames (cols 4-7) */
@keyframes mantis2-plant {
  from { background-position: -40.8cqw -25.5cqw; }
  to   { background-position: -81.6cqw -25.5cqw; }
}
/* Row 1 – water, 2 frames (cols 6-7) */
@keyframes mantis2-water {
  from { background-position: -61.2cqw -12.75cqw; }
  to   { background-position: -81.6cqw -12.75cqw; }
}

/* Active-buff indicator floating over the farm scene (top-left). */
.farm-buffs {
  position: absolute; top: 8px; left: 8px; z-index: 6;
  display: flex; gap: 6px; pointer-events: none;
}
.buff-chip {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 9px 4px 5px; border-radius: 999px;
  background: rgba(38, 26, 12, 0.72); color: #fff7e0;
  font-family: var(--font-display); font-weight: 700; font-size: 12px;
  line-height: 1; white-space: nowrap;
  box-shadow: 0 1px 6px rgba(0, 0, 0, 0.4);
  backdrop-filter: blur(2px);
  border: 1px solid rgba(255, 214, 121, 0.5);
}
.buff-chip .ico-flower { width: 18px; height: 18px; }
.buff-chip .buff-sep { opacity: 0.5; }
.buff-chip .buff-landings { color: #ffd679; }
/* Panda LE holder-perk chip opens with an emoji, not an icon image, so it
   takes symmetric padding. */
.buff-chip.pandale { padding: 4px 9px; }
/* Greenhouse stake chip: emoji-led like the LE chip, with a green accent. */
.buff-chip.greenhouse { padding: 4px 9px; border-color: rgba(140, 220, 140, 0.6); }
.buff-chip.greenhouse .buff-landings { color: #b8f0a0; }
/* Shrine total-boost chip: moonlit lavender accent. */
.buff-chip.shrine { padding: 4px 9px; border-color: rgba(200, 160, 255, 0.6); }
.buff-chip.shrine .buff-landings { color: #e0c8ff; }
/* Multi-farm daily-cap chip: earthy amber accent (cap scaling, not a boost). */
.buff-chip.farms { padding: 4px 9px; border-color: rgba(230, 180, 110, 0.6); }
.buff-chip.farms .buff-landings { color: #ffcf8a; }

.cell {
  position: absolute;
  margin: 0; padding: 0; border: 0; background: transparent;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
}
.cell.empty:active, .cell.planted:active { filter: brightness(1.08); }

/* dashed hint ring on an empty, plantable plot */
.cell.empty::after {
  content: "";
  position: absolute; left: 50%; bottom: 16%; transform: translateX(-50%);
  width: 52%; aspect-ratio: 1; border-radius: 50%;
  border: 2px dashed rgba(255, 255, 255, 0.85);
  opacity: 0; transition: opacity 0.15s ease;
}
.cell.empty:hover::after, .cell.empty:focus-visible::after { opacity: 0.85; }

.cell.locked { cursor: default; }
.cell.locked::after {
  content: "🔒";
  position: absolute; left: 50%; bottom: 28%; transform: translateX(-50%);
  font-size: max(11px, 3.6cqw); opacity: 0.8;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.5));
}

/* The next buyable plot: tappable, with a coin-priced badge instead of a lock. */
.cell.locked.unlockable { cursor: pointer; }
.cell.locked.unlockable::after { content: none; }
.cell-unlock {
  position: absolute; left: 50%; bottom: 20%; transform: translateX(-50%);
  display: inline-flex; align-items: center; gap: 3px;
  padding: 2px 8px; border-radius: 999px; white-space: nowrap;
  background: rgba(38, 26, 12, 0.78); color: #fff7e0;
  font-family: var(--font-display); font-weight: 700; font-size: max(10px, 3.2cqw);
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.4);
  transition: transform 0.15s ease;
}
.cell.unlockable:hover .cell-unlock, .cell.unlockable:focus-visible .cell-unlock { transform: translateX(-50%) scale(1.06); }
.cell-unlock-plus { color: #aee37d; font-weight: 800; }
.cell-unlock-cost { display: inline-flex; align-items: center; gap: 3px; }

/* A butterfly-blessed plant (Flower Scent): a soft pulsing glow behind the crop
   marking the 5× NFT drop chance, centred on the tilled square. */
.cell-glow {
  position: absolute; left: 50%; top: 54%; transform: translate(-50%, -50%);
  width: 60%; aspect-ratio: 1; border-radius: 50%;
  pointer-events: none; z-index: 0;
  background: radial-gradient(circle, rgba(255, 214, 121, 0.85) 0%, rgba(247, 160, 224, 0.5) 42%, rgba(247, 160, 224, 0) 70%);
  animation: cell-glow-pulse 1.8s ease-in-out infinite;
}
@keyframes cell-glow-pulse {
  0%, 100% { opacity: 0.55; transform: translate(-50%, -50%) scale(0.92); }
  50%      { opacity: 1;    transform: translate(-50%, -50%) scale(1.12); }
}
@media (prefers-reduced-motion: reduce) {
  .cell-glow { animation: none; opacity: 0.7; }
}

.cell-crop-wrap {
  /* Anchor on the plot centre: top:50% + translateY(-82%) puts the point 82%
     down the sprite (the stem base, where the plant meets its soil mound) on
     the centre of the tilled square, so the plant grows from the plot centre. */
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -82%);
  pointer-events: none;
  z-index: 1;
}
.cell-crop-wrap .crop-sprite {
  /* Sprites carry their own soil mound, so size them so the mound covers the
     tilled plot square (mound base ~= plot width) and the plant rises above. */
  --cell: 14cqw;
  display: block;
  transform-origin: 50% 100%;
  filter: drop-shadow(1px 3px 3px rgba(0, 0, 0, 0.28));
}
/* No sway: the sprite includes its soil tile, which shouldn't rock. */
.cell.planted.ready .cell-crop-wrap .crop-sprite { animation: glow 1.4s ease-in-out infinite; }
/* Crops keep full brightness in the night scenes on purpose: dimming them
   (brightness/saturate on the wrap) made the plants read as muddy blobs on
   desktop, and legibility beats scene-matching here. */

.cell-ready {
  position: absolute; top: -4%; left: 50%; transform: translateX(-50%);
  font-size: max(11px, 3.2cqw); pointer-events: none;
  animation: bob 1s ease-in-out infinite;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.45));
}
.cell-tags {
  position: absolute; top: 4%; right: 6%;
  display: flex; gap: 2px; pointer-events: none;
  /* Above .cell-crop-wrap (z-index 1) so the watered/fertilized/blessed
     markers stay visible instead of being hidden behind a tall plant sprite. */
  z-index: 2;
}
.cell-tags i {
  font-style: normal; font-size: max(9px, 2.6cqw);
  filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.45));
}

/* PIX payment QR + copy field (also used by the USDC address field) */
.pix-qr { display: block; width: 200px; height: 200px; margin: 10px auto; image-rendering: pixelated; border-radius: 8px; }
#pix-copy, #crypto-addr { width: 100%; margin-top: 8px; font-size: 12px; padding: 8px; border-radius: 8px; border: 1px solid var(--line, #d9d2c4); background: #fff; }

/* Cell action sheet (reuses the modal root) */
.modal.sheet .sheet-list { display: flex; flex-direction: column; gap: 8px; margin: 6px 0 4px; }
/* A seed row in the plant sheet: "Plant" fills the row, "Plant all" sits beside it. */
.seed-plant-row { display: flex; gap: 6px; align-items: stretch; }
.seed-plant-row .sheet-plant { flex: 1; }
.seed-plant-row .sheet-plant-all { white-space: nowrap; flex: 0 0 auto; }
.seed-plant-row .sheet-plant .muted { color: rgba(255,255,255,0.8); font-size: 13px; }
.modal.sheet .crop-sprite.sheet-ico {
  --cell: 26px; width: 26px; height: 26px; vertical-align: -8px; margin-right: 4px;
}
/* Panda Farmer seed-choice rows */
.seed-choice-row {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px; cursor: pointer;
  border-radius: var(--radius-sm); border: 1px solid var(--line-2);
  background: var(--panel-2, rgba(255,255,255,0.45));
  transition: background 0.15s;
}
.seed-choice-row:hover, .seed-choice-row.selected { background: rgba(91,168,69,0.12); border-color: var(--green); }
.seed-choice-row input[type=checkbox] { flex: 0 0 auto; width: 18px; height: 18px; accent-color: var(--green); cursor: pointer; }
.seed-choice-row .seed-label { font-size: 14px; font-weight: 600; color: var(--ink); }
/* Auto-action toggles in the Panda Farmer modal */
.panda-toggles { display: flex; flex-direction: column; gap: 8px; margin: 12px 0 0; }
.panda-toggle {
  display: flex; align-items: center; justify-content: space-between; gap: 10px;
  width: 100%; padding: 10px 12px; cursor: pointer; font: inherit; text-align: left;
  border-radius: var(--radius-sm); border: 1px solid var(--line-2);
  background: var(--cream-2); color: var(--ink); transition: all 0.15s;
}
.panda-toggle .pt-label { font-size: 13px; font-weight: 700; }
.panda-toggle .pt-state {
  flex: 0 0 auto; font-size: 12px; font-weight: 800; letter-spacing: 0.5px;
  padding: 3px 10px; border-radius: 999px; background: #e3ddcd; color: var(--ink-soft);
}
.panda-toggle.on { border-color: var(--green); background: rgba(91,168,69,0.12); }
.panda-toggle.on .pt-state { background: var(--green-d); color: #fff; }

.crop-sprite {
  display: inline-block;
  image-rendering: pixelated;
  background-image: url("assets/crops.png?v=11");
  background-repeat: no-repeat;
  width: var(--cell);
  height: var(--cell);
  background-size: calc(var(--cell) * 4) calc(var(--cell) * 4);
  background-position: calc(var(--col, 0) * var(--cell) * -1) calc(var(--row, 0) * var(--cell) * -1);
}
.crop-sprite.sprout { --col: 0; }
.crop-sprite.grow { --col: 1; }
.crop-sprite.almost { --col: 2; }
.crop-sprite.ready { --col: 3; }
.crop-sprite.tomato { --row: 0; }
.crop-sprite.lettuce { --row: 1; }
.crop-sprite.corn { --row: 2; }
.crop-sprite.pumpkin { --row: 3; }
/* Lunar Bloom grows from its own 4-frame strip (not part of crops.png).
   Override to a 4-wide / 1-tall sheet; the stage classes still drive --col. */
.crop-sprite.lunar {
  background-image: url("assets/lunar.png?v=4");
  background-size: calc(var(--cell) * 4) var(--cell);
  --row: 0;
}

.plot .crop-sprite {
  --cell: 152px;
  position: relative;
  z-index: 2;
  transform-origin: 50% 100%;
  animation: sway 2.4s ease-in-out infinite;
  filter: drop-shadow(3px 6px 4px rgba(0,0,0,0.22));
}
.plot.ready .crop-sprite { animation: sway 2.4s ease-in-out infinite, glow 1.1s ease-in-out infinite; }

.empty-plot {
  position: relative;
  z-index: 2;
  display: grid;
  place-items: center;
  gap: 6px;
  margin-bottom: 18px;
  text-align: center;
}
.empty-plot .dig {
  width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-items: center; font-size: 22px;
  background: rgba(255,255,255,0.7);
  border: 1px dashed var(--line-2);
}
.empty-plot span { font-size: 11px; font-weight: 800; color: var(--brown-d); text-transform: uppercase; letter-spacing: 0.5px; }

.plot-tags {
  position: absolute; z-index: 3; top: 8px; left: 8px;
  display: flex; gap: 5px;
}
.tag {
  display: grid; place-items: center;
  width: 27px; height: 27px; font-size: 14px;
  border-radius: 9px;
  background: rgba(255,255,255,0.92);
  border: 1px solid var(--line-2);
  box-shadow: var(--shadow-sm);
}

.ready-flag {
  position: absolute; z-index: 3; top: 9px; right: 9px;
  font-family: var(--font-display); font-weight: 600; font-size: 11px;
  padding: 4px 9px; border-radius: 999px; color: #5a3d0a;
  background: linear-gradient(180deg, #ffd86b, var(--gold-d));
  box-shadow: var(--shadow-sm);
  animation: bob 1s ease-in-out infinite;
}

.plot-footer {
  position: relative;
  z-index: 3;
  display: grid;
  gap: 9px;
  padding: 11px 12px 12px;
  background: var(--panel);
  border-top: 1px solid var(--line);
}
.plot-name { display: flex; align-items: baseline; justify-content: space-between; gap: 8px; }
.plot-name strong { font-family: var(--font-display); font-weight: 600; font-size: 15px; }
.plot-name .timer { font-size: 11.5px; font-weight: 800; color: var(--muted); }

.bar {
  height: 10px; border-radius: 999px;
  background: #e8dcbf; overflow: hidden;
  box-shadow: inset 0 1px 2px rgba(0,0,0,0.12);
}
.bar i { display: block; height: 100%; border-radius: 999px; background: linear-gradient(90deg, var(--green-l), var(--green)); transition: width 0.5s ease; }

.plot-actions { display: flex; flex-wrap: wrap; gap: 7px; }
.plot-actions .btn { flex: 1 1 auto; }
.plot-actions.single .btn { flex: 1 1 100%; }

/* ---------------- Side panel ---------------- */
.col-panel { padding: 0; overflow: hidden; align-self: start; }

.tabs {
  display: grid;
  /* Auto-fit one column per (visible) tab so adding/removing tabs — including the
     DEV-only Greenhouse — never wraps to a second row. */
  grid-auto-flow: column;
  grid-auto-columns: 1fr;
  gap: 4px;
  padding: 8px;
  background: var(--panel-2);
  border-bottom: 1px solid var(--line);
}
.tab {
  appearance: none;
  border: none;
  background: transparent;
  border-radius: var(--radius-xs);
  padding: 8px 2px 6px;
  font-family: var(--font-ui);
  font-weight: 800;
  font-size: 10.5px;
  color: var(--ink-soft);
  cursor: pointer;
  display: grid;
  justify-items: center;
  gap: 3px;
  min-width: 0; /* let the label truncate instead of forcing the track wider */
  transition: background 0.15s ease, color 0.15s ease, transform 0.1s ease;
}
.tab span { font-size: 11px; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tab:hover { background: rgba(255,255,255,0.6); }
.tab.active { background: #fff; color: var(--green-d); box-shadow: var(--shadow-sm); }

.tab-panel { display: none; padding: 14px; animation: fade 0.25s ease; }
.tab-panel.active { display: block; }
/* .tab / .nav-item set an explicit display, which beats the UA [hidden] rule —
   so a hidden tab/nav entry (e.g. the DEV-only Greenhouse) needs this override. */
.tab[hidden], .nav-item[hidden] { display: none !important; }

.list { display: grid; gap: 9px; }

.row {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 10px;
  align-items: center;
  padding: 10px 11px;
  background: var(--cream-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  transition: border-color 0.15s ease, background 0.15s ease, transform 0.1s ease;
}
.row:hover { transform: translateY(-1px); border-color: var(--line-2); }
.row.selected { border-color: var(--green); background: #eefbe2; box-shadow: 0 0 0 2px rgba(91,168,69,0.25); }

.row-main { min-width: 0; }
.row-title { display: flex; align-items: center; gap: 9px; font-family: var(--font-display); font-weight: 600; font-size: 14.5px; margin-bottom: 2px; }
.row-title span.name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.row-meta { font-size: 11.5px; font-weight: 700; color: var(--muted); line-height: 1.35; }

/* Lunar Bloom hold-gate: per-mutant checklist on the locked seed card. */
.mutant-reqs { display: flex; flex-wrap: wrap; gap: 4px; margin-top: 5px; }
.mutant-req {
  font-size: 10.5px; font-weight: 800; line-height: 1;
  padding: 3px 6px; border-radius: 999px; white-space: nowrap;
}
.mutant-req.have { background: rgba(91, 168, 69, 0.16); color: var(--green-d); }
.mutant-req.missing { background: rgba(0, 0, 0, 0.06); color: var(--muted); }
.row-side { display: grid; gap: 6px; justify-items: end; }
.price { font-family: var(--font-display); font-weight: 600; font-size: 13px; color: var(--brown-d); }

/* Bulk-buy quantity stepper (shop rows + cash-booster modal). */
.qty-stepper {
  display: inline-flex;
  align-items: center;
  border: 1px solid var(--line-2);
  border-radius: var(--radius-xs);
  background: #fff;
  overflow: hidden;
}
.qty-stepper button {
  width: 30px;
  height: 30px;
  border: 0;
  background: var(--panel-2);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 600;
  line-height: 1;
  cursor: pointer;
}
.qty-stepper button:active { background: var(--gold); }
.qty-stepper .qty-val {
  width: 38px;
  min-width: 30px;
  height: 30px;
  padding: 0;
  border: 0;
  background: #fff;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 14px;
  color: var(--ink);
  -moz-appearance: textfield;
  appearance: textfield;
}
.qty-stepper .qty-val:focus {
  outline: none;
  background: var(--panel-2);
}
.qty-stepper .qty-val::-webkit-outer-spin-button,
.qty-stepper .qty-val::-webkit-inner-spin-button {
  -webkit-appearance: none;
  margin: 0;
}
.qty-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  margin: 6px 0 2px;
  font-weight: 700;
  color: var(--ink-soft);
}

.thumb {
  flex: 0 0 auto;
  border-radius: var(--radius-xs);
  border: 1px solid var(--line-2);
  /* background-color (not the `background` shorthand) so it tints behind the
     thumbnail without wiping the crop sprite's background-image. */
  background-color: #f3ead0;
  box-shadow: var(--shadow-sm);
}
.mini-seed { --cell: 34px; width: 34px; height: 34px; }
/* Lunar Bloom seed-pouch icon (hides the Moonbloom NFT until harvest). */
.seed-lunar {
  display: inline-block;
  width: 34px; height: 34px;
  background: center / contain no-repeat url("assets/seed-lunar.png?v=2");
  image-rendering: pixelated;
}
.seed-lunar.sheet-ico { width: 26px; height: 26px; vertical-align: -8px; margin-right: 4px; }
.seed-lunar.locked {
  display: grid; place-items: center; font-size: 16px;
  filter: grayscale(0.7) brightness(0.65);
}
.icon-chip {
  width: 34px; height: 34px; display: grid; place-items: center; font-size: 18px;
  background: linear-gradient(180deg, #eaf7d8, #d6efb6);
}
/* Front-facing farmer portraits used as the shop thumbnails: the idle frame
   cropped from the 8×4 sprite sheet (176×192 cells, ~0.917 aspect kept so the
   crop isn't squished). Idle sits on row 3 — col 0 for shark/fox/porcupine/
   alligator/bat, col 4 for the panda sheet. */
.farmer-ico {
  width: 31px; height: 34px;
  background-repeat: no-repeat;
  background-size: 800% 400%;
  image-rendering: pixelated;
}
.panda-ico     { background-image: url("assets/panda-farmer.png?v=12");     background-position: 57.143% 100%; }
.shark-ico     { background-image: url("assets/shark-farmer.png?v=2");     background-position: 0% 100%; }
.fox-ico       { background-image: url("assets/fox-farmer.png?v=4");       background-position: 0% 100%; }
.porcupine-ico { background-image: url("assets/porcupine-farmer.png?v=2"); background-position: 0% 100%; }
.alligator-ico { background-image: url("assets/alligator-farmer.png?v=2"); background-position: 0% 100%; }
/* Row-0 col-0 (closed-mouth front pose) and rendered smaller — the bat art is
   drawn larger than the other farmers, so it would otherwise loom in the chip. */
.bat-ico       { background-image: url("assets/bat-farmer.png?v=2");       background-position: 0% 0%; width: 26px; height: 29px; }
/* Row-0 col-0 (closed-mouth front pose) and rendered smaller — like the bat, the
   sheep art is drawn larger than the standard farmers, so it shrinks in the chip. */
.sheep-ico     { background-image: url("assets/sheep-farmer.png?v=2");     background-position: 0% 0%; width: 27px; height: 29px; }
/* Row-0 col-0 (front pose) and rendered smaller — like the bat/sheep, the mantis
   art is drawn larger than the standard farmers, so it shrinks in the chip. */
.mantis-ico    { background-image: url("assets/mantis-farmer.png?v=2");    background-position: 0% 0%; width: 27px; height: 29px; }
/* Panda Farmer LE chip — Row 3 col 0 (front idle pose) of the LE sheet. */
.pandale-ico   { background-image: url("assets/panda-farmer-le.png?v=3");   background-position: 0% 100%; }

/* Grouped farmer shop card: top line = selectable icon strip (left) + buy/activate
   button (right); the selected farmer's name + blurb sit on the line below. */
.farmer-shop-row { display: block; }
.farmer-nft-note { color: #d4af37; margin-top: 3px; }
.farmer-shop-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 10px; margin-bottom: 8px;
}
.farmer-shop-head .row-side { flex: 0 0 auto; }
.farmer-picks { display: flex; flex-wrap: wrap; gap: 6px; align-content: center; }
.farmer-pick {
  display: grid; place-items: center;
  width: 38px; height: 38px; padding: 0;
  border: 1px solid var(--line-2); border-radius: var(--radius-xs);
  background: linear-gradient(180deg, #eaf7d8, #d6efb6);
  cursor: pointer;
  transition: border-color 0.15s ease, box-shadow 0.15s ease, transform 0.1s ease;
}
.farmer-pick:hover { transform: translateY(-1px); border-color: var(--green); }
.farmer-pick.selected { border-color: var(--green); box-shadow: 0 0 0 2px rgba(91, 168, 69, 0.3); }
/* The painted booster medallion fills the chip rather than sitting small in it. */
.icon-chip .ico-booster-breeding { width: 32px; height: 32px; vertical-align: middle; }
.icon-chip .ico-flower { width: 32px; height: 32px; vertical-align: middle; }
.icon-chip .ico-scarecrow { width: 30px; height: 30px; vertical-align: middle; }
.nft-art {
  width: 50px; height: 50px;
  /* painted illustrations (not pixel art) — smooth scaling, no pixelation */
  background: #241a3a center / contain no-repeat;
}
.nft-art.tomato.rare { background-image: url("assets/nft-tomato-rare.png?v=2"); }
.nft-art.tomato.epic { background-image: url("assets/nft-tomato-epic.png?v=2"); }
.nft-art.tomato.mythic { background-image: url("assets/nft-tomato-mythic.png?v=2"); }
.nft-art.lettuce.rare { background-image: url("assets/nft-lettuce-rare.png?v=2"); }
.nft-art.lettuce.epic { background-image: url("assets/nft-lettuce-epic.png?v=2"); }
.nft-art.lettuce.mythic { background-image: url("assets/nft-lettuce-mythic.png?v=2"); }
.nft-art.corn.rare { background-image: url("assets/nft-corn-rare.png?v=2"); }
.nft-art.corn.epic { background-image: url("assets/nft-corn-epic.png?v=2"); }
.nft-art.corn.mythic { background-image: url("assets/nft-corn-mythic.png?v=2"); }
.nft-art.pumpkin.rare { background-image: url("assets/nft-pumpkin-rare.png?v=2"); }
.nft-art.pumpkin.epic { background-image: url("assets/nft-pumpkin-epic.png?v=2"); }
.nft-art.pumpkin.mythic { background-image: url("assets/nft-pumpkin-mythic.png?v=2"); }
.mutant-art {
  width: 50px; height: 50px;
  /* painted illustrations (not pixel art) — smooth scaling, no pixelation */
  background: #1d1536 center / contain no-repeat;
  animation: glow 1.6s ease-in-out infinite;
}
.mutant-art.golden_corn { background-image: url("assets/mutant-1.png?v=4"); }
.mutant-art.lunar_pumpkin { background-image: url("assets/mutant-2.png?v=4"); }
.mutant-art.tomettuce { background-image: url("assets/mutant-3.png?v=4"); }
.mutant-art.cornpkin { background-image: url("assets/mutant-4.png?v=4"); }
/* Moonbloom (legendary) */
.mutant-art.moonbloom { background-image: url("assets/moonbloom.png?v=2"); }
.mutant-art.moonbloom.sm { width: 34px; height: 34px; border-radius: var(--radius-xs); }
.mutant-art.moonbloom.locked {
  background: #2a2540; background-image: none;
  display: grid; place-items: center; font-size: 18px;
}

.rarity {
  display: inline-block; font-size: 10px; font-weight: 800; text-transform: uppercase;
  padding: 2px 7px; border-radius: 999px; letter-spacing: 0.4px;
}
.rarity.common { background: #ece3cf; color: #7a6f53; }
.rarity.uncommon { background: #d9eecb; color: #4f7d38; }
.rarity.rare { background: #cfe6fb; color: #2f6ca3; }
.rarity.epic { background: #e7d6fb; color: #6d3fb0; }
.rarity.mythic { background: linear-gradient(90deg, #ffe0a3, #f5b0e0); color: #8a3d7a; }
.rarity.mutant { background: linear-gradient(90deg, #c6f6d5, #9ae6e0); color: #1f6b5c; box-shadow: 0 0 0 1px rgba(34, 160, 130, 0.3); }
.rarity.legendary { background: linear-gradient(90deg, #c8b6ff, #ffd98e, #a0e9ff); color: #4b2e83; box-shadow: 0 0 0 1px rgba(120, 80, 200, 0.3); }

.empty-state { text-align: center; color: var(--muted); font-weight: 700; font-size: 13px; padding: 22px 10px; }
.empty-state .ico { font-size: 30px; display: block; margin-bottom: 6px; opacity: 0.8; }

/* ---------------- Bottom nav (mobile) ---------------- */
.bottom-nav { display: none; }

/* ---------------- Modal ---------------- */
#modal-root {
  position: fixed; inset: 0; z-index: 80;
  display: grid; place-items: center;
  padding: 20px;
  background: rgba(40, 30, 15, 0.5);
  backdrop-filter: blur(3px);
  animation: fade 0.2s ease;
}
#modal-root[hidden] { display: none; }
.modal {
  width: min(380px, 100%);
  max-height: calc(100vh - 40px);
  overflow-y: auto;
  background: var(--panel);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 20px;
  animation: pop-in 0.25s ease;
}
.modal h3 { font-family: var(--font-display); font-weight: 700; font-size: 19px; margin-bottom: 6px; }
.modal p { font-size: 13px; color: var(--ink-soft); font-weight: 700; margin-bottom: 14px; }
.modal input {
  width: 100%; padding: 12px 14px; font-family: var(--font-ui); font-weight: 800; font-size: 15px;
  border: 1px solid var(--line-2); border-radius: var(--radius-sm); background: #fff; color: var(--ink);
  margin-bottom: 14px;
}
.modal input:focus { outline: none; border-color: var(--green); box-shadow: 0 0 0 3px rgba(91,168,69,0.2); }
.modal-actions { display: flex; gap: 10px; }
.modal-actions .btn { flex: 1; }

/* Share picker: one brag + a 2×2 grid of networks (Telegram / WhatsApp / X /
   Copy). Every shareable moment routes through this so the channel list and
   look stay in one place. */
.modal-share .share-brag {
  margin: 2px 0 12px; font-size: .9rem; color: var(--muted);
}
.share-grid {
  display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin-bottom: 10px;
}
.btn-share {
  color: #fff; border: 0; font-weight: 700;
}
.btn-share.tg   { background: #229ED9; }
.btn-share.wa   { background: #25D366; }
.btn-share.x    { background: #111; }
.btn-share.copy { background: #6b7280; }

/* NFT artwork lightbox: tap the list thumbnail to view it full size. */
.nft-art-trigger {
  /* inline-flex so the sprite span stays a flex item and keeps its 50px box —
     plain inline spans ignore width/height and would collapse to nothing. */
  display: inline-flex; flex: 0 0 auto;
  padding: 0; border: 0; background: none; cursor: zoom-in; line-height: 0;
  border-radius: var(--radius-xs);
}
.nft-art-trigger:focus-visible { outline: none; box-shadow: 0 0 0 3px rgba(91,168,69,0.35); }
/* List icon as a mini collectible card. */
.nft-thumb-card {
  width: 50px; height: 50px; object-fit: cover; display: block;
  border-radius: var(--radius-xs);
}
.modal-art {
  width: auto; max-width: min(380px, 92vw); padding: 16px;
  display: grid; justify-items: center; gap: 8px; position: relative;
  text-align: center;
}
.modal-art h3 { margin: 4px 0 0; }
.art-meta { font-size: 13px; color: var(--ink-soft); font-weight: 700; }
.art-close {
  position: absolute; top: 10px; right: 10px; z-index: 1;
  width: 32px; height: 32px; border-radius: 999px; border: 0; cursor: pointer;
  background: var(--panel); box-shadow: var(--shadow-sm); color: var(--ink);
  font-size: 15px; line-height: 1;
}
.nft-art.art-lg, .mutant-art.art-lg {
  width: min(256px, 64vw); height: min(256px, 64vw);
  border-radius: var(--radius); box-shadow: var(--shadow-sm);
}
/* Full collectible card (square artwork with name + rarity baked in). */
.nft-card-img {
  width: min(340px, 84vw); height: auto; display: block;
  border-radius: var(--radius); box-shadow: var(--shadow-sm);
}

/* ---------------- Toast ---------------- */
#toast {
  position: fixed; left: 50%; bottom: calc(20px + env(safe-area-inset-bottom));
  transform: translateX(-50%) translateY(8px);
  z-index: 90;
  /* Purely informational: it sits above the bottom nav, so it must never
     swallow taps meant for the buttons beneath it (it lingers ~3s after every
     action, which otherwise dead-zones the center nav buttons mid-session). */
  pointer-events: none;
  display: flex; align-items: center; gap: 9px;
  width: min(440px, calc(100vw - 28px));
  padding: 12px 16px;
  background: #36431f;
  color: #fff7e6;
  font-weight: 800; font-size: 13.5px;
  border-radius: 14px;
  box-shadow: var(--shadow-lg);
  opacity: 0;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
#toast.show { opacity: 1; transform: translateX(-50%) translateY(0); }
#toast.error { background: #7d3326; }
#toast .t-ico { font-size: 17px; }

/* ---------------- Animations ---------------- */
@keyframes sway { 0%,100% { transform: rotate(-1.2deg); } 50% { transform: rotate(1.2deg) translateY(-2px); } }
@keyframes glow { 0%,100% { filter: drop-shadow(3px 6px 4px rgba(0,0,0,0.22)) brightness(1); } 50% { filter: drop-shadow(3px 6px 4px rgba(0,0,0,0.22)) brightness(1.28) saturate(1.15); } }
@keyframes bob { 0%,100% { transform: translateY(0); } 50% { transform: translateY(-3px); } }
@keyframes pop-in { 0% { opacity: 0; transform: scale(0.94) translateY(6px); } 100% { opacity: 1; transform: scale(1) translateY(0); } }
@keyframes fade { from { opacity: 0; } to { opacity: 1; } }
@keyframes flit-a { 0%,100% { transform: translate(0,0); } 50% { transform: translate(40px,-16px); } }
@keyframes flit-b { 0%,100% { transform: translate(0,0); } 50% { transform: translate(-52px,12px); } }
@keyframes flit-c { 0%,100% { transform: translate(0,0); } 50% { transform: translate(-44px,14px); } }

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

/* ---------------- Responsive ---------------- */
@media (max-width: 880px) {
  #app { padding: 0 12px calc(86px + env(safe-area-inset-bottom)); }
  /* Two-row HUD: brand + actions on top, resource chips on their own full
     line below, so nothing truncates or needs sideways scrolling. */
  .hud {
    margin: 0 -12px;
    flex-wrap: wrap;
    height: auto;
    row-gap: 8px;
    padding-top: 8px;
    padding-bottom: 8px;
  }
  .brand { order: 1; }
  .hud-actions { order: 2; margin-left: auto; }
  .resources {
    order: 3;
    flex-basis: 100%;
    margin-left: 0;
    justify-content: space-between;
    gap: 6px;
  }
  .brand-logo { height: 34px; }
  .layout { grid-template-columns: 1fr; }
  .hero { height: 95px; }
  .hero-logo { height: 70px; }

  /* Screen switching driven by bottom nav */
  .col-panel { display: none; }
  body.screen-shop .col-farm,
  body.screen-inventory .col-farm,
  body.screen-nfts .col-farm,
  body.screen-shrine .col-farm,
  body.screen-stake .col-farm,
  body.screen-market .col-farm,
  body.screen-rank .col-farm { display: none; }
  body.screen-shop .col-panel,
  body.screen-inventory .col-panel,
  body.screen-nfts .col-panel,
  body.screen-shrine .col-panel,
  body.screen-stake .col-panel,
  body.screen-market .col-panel,
  body.screen-rank .col-panel { display: block; }

  /* On phones the bottom nav is the section switcher, so the in-panel tab bar is
     redundant — hide it to cut clutter. */
  .tabs { display: none; }

  .bottom-nav {
    /* A single horizontally-scrollable row of every section: items keep a
       comfortable width and the bar scrolls sideways when they don't all fit,
       instead of shrinking or wrapping. */
    display: flex;
    overflow-x: auto;
    overflow-y: hidden;
    -webkit-overflow-scrolling: touch;
    /* Reserve horizontal finger drags for sliding the bar, and keep an edge
       overscroll from triggering the browser's back/forward navigation. */
    touch-action: pan-x;
    overscroll-behavior-x: contain;
    scrollbar-width: none; /* Firefox */
    scroll-behavior: smooth;
    gap: 2px;
    position: fixed;
    left: 0; right: 0; bottom: 0;
    z-index: 50;
    padding: 6px 6px calc(6px + env(safe-area-inset-bottom));
    background: rgba(255, 250, 240, 0.94);
    backdrop-filter: blur(10px);
    border-top: 1px solid var(--line);
    box-shadow: 0 -6px 18px rgba(96,70,38,0.12);
  }
  .bottom-nav::-webkit-scrollbar { display: none; } /* Chrome/Safari */
  .nav-item {
    /* Grow to fill the bar when the items fit; hold this width and let the bar
       scroll when they don't. */
    flex: 1 0 auto;
    min-width: 62px;
    appearance: none; border: none; background: transparent; cursor: pointer;
    display: grid; justify-items: center; gap: 2px;
    font-family: var(--font-ui); font-weight: 800; font-size: 20px; /* the emoji icon */
    color: var(--muted);
    padding: 5px 0;
    border-radius: 10px;
  }
  /* The label under the icon: small, and truncates rather than colliding. */
  .nav-item span { font-size: 9.5px; line-height: 1.1; max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  .nav-item.active { color: var(--green-d); background: rgba(91,168,69,0.12); }

  .plots { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 12px; }
  .plot .crop-sprite { --cell: 128px; }
  .daily { grid-template-columns: auto 1fr; }
  .daily .btn { grid-column: 1 / -1; }
}

@media (max-width: 380px) {
  .chip-tag { display: none; }
  .plots { grid-template-columns: 1fr 1fr; }
}

/* ---------------- Tokenomics page ---------------- */
.btn-info { padding: 9px 12px; font-size: 16px; }

#app.info-wrap { padding: 0 16px calc(40px + env(safe-area-inset-bottom)); }
.info-page { max-width: 640px; margin: 20px auto 0; display: grid; gap: 14px; }
.info-card { padding: 18px 20px; }
.info-card-muted { background: var(--panel-2); }
.info-title { font-family: var(--font-display); font-size: 24px; font-weight: 700; color: var(--ink); margin-bottom: 8px; }
.info-lead { font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); }
.info-note { font-size: 12.5px; line-height: 1.55; margin-top: 10px; }

.info-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.info-tile { background: var(--cream-2); border: 1px solid var(--line); border-radius: var(--radius-sm); padding: 12px 14px; }
.info-tile-h { font-family: var(--font-display); font-weight: 600; font-size: 14px; color: var(--ink); margin-bottom: 6px; }
.info-tile-p { font-size: 12px; line-height: 1.5; }

.info-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 8px; }
.info-list li {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 9px 12px;
  background: var(--cream-2);
  border: 1px solid var(--line);
  border-radius: var(--radius-sm);
  font-size: 13px;
}
.info-list li strong { font-family: var(--font-display); color: var(--green-d); }

@media (max-width: 880px) {
  .info-page { margin: 12px auto 0; }
  .info-grid { grid-template-columns: 1fr; }
}

/* ---------------- Raffle card (Shop tab) ---------------- */
.raffle-card {
  border-radius: 14px;
  padding: 13px 14px 14px;
  margin-bottom: 14px;
  background: linear-gradient(160deg, #3a1a5e, #1e1035);
  border: 1px solid #7b4fd8;
  color: #f0eaff;
}
.raffle-card:empty { display: none; }
.raffle-head {
  display: flex; align-items: center; gap: 8px;
  font-weight: 800; font-size: 14px; margin-bottom: 10px;
}
.raffle-head .raffle-badge {
  margin-left: auto; font-size: 10px; font-weight: 700;
  background: rgba(255,255,255,0.12); border-radius: 999px;
  padding: 2px 8px; letter-spacing: 0.03em;
}
.raffle-pot-row {
  display: flex; align-items: baseline; gap: 6px; margin-bottom: 8px;
}
.raffle-pot-label { font-size: 11px; opacity: 0.6; }
.raffle-pot-value { font-size: 22px; font-weight: 800; color: #ffd86b; line-height: 1; }
.raffle-pot-unit { font-size: 11px; font-weight: 700; opacity: 0.6; margin-left: 1px; }
.raffle-stats {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px;
  margin-bottom: 10px;
}
.raffle-stat {
  background: rgba(255,255,255,0.07); border-radius: 9px;
  padding: 7px 6px; text-align: center;
}
.raffle-stat strong { display: block; font-size: 14px; font-weight: 800; }
.raffle-stat span { font-size: 10px; opacity: 0.6; }
.raffle-split {
  display: flex; gap: 4px; margin-bottom: 10px;
}
.raffle-split-item {
  flex: 1; border-radius: 8px; padding: 5px 4px; text-align: center;
  font-size: 10px; font-weight: 700;
}
.raffle-split-winner { background: rgba(255,216,107,0.15); color: #ffd86b; }
.raffle-split-burn { background: rgba(255,100,80,0.15); color: #ff9080; }
.raffle-split-vault { background: rgba(140,100,255,0.15); color: #c9a8ff; }
.raffle-actions {
  display: flex; gap: 8px; margin-top: 4px;
}
.raffle-actions .btn { flex: 1; }
.raffle-qty {
  display: flex; align-items: center; gap: 6px; background: rgba(255,255,255,0.08);
  border-radius: 9px; padding: 0 10px;
}
.raffle-qty button {
  background: none; border: none; color: #f0eaff; font-size: 18px;
  font-weight: 700; padding: 6px 2px; cursor: pointer; line-height: 1;
}
.raffle-qty span { min-width: 28px; text-align: center; font-weight: 800; font-size: 14px; }
.raffle-my-tickets {
  margin-top: 8px; font-size: 11px; opacity: 0.75; text-align: center;
}
.raffle-my-tickets strong { color: #a8d4ff; font-weight: 800; }
.raffle-history {
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid rgba(255,255,255,0.1);
}
.raffle-history-head {
  font-size: 10px; font-weight: 700; opacity: 0.5;
  letter-spacing: 0.05em; text-transform: uppercase; margin-bottom: 6px;
}
.raffle-history-row {
  display: flex; align-items: baseline; gap: 6px;
  font-size: 11px; padding: 3px 0; opacity: 0.85;
}
.raffle-history-row:not(:last-child) { border-bottom: 1px solid rgba(255,255,255,0.06); }
.raffle-history-winner { flex: 1; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.raffle-history-prize { font-weight: 700; color: #ffd86b; white-space: nowrap; }
.raffle-history-time { font-size: 10px; opacity: 0.5; white-space: nowrap; }

/* ---------------- Moonbloom Shrine ---------------- */
#shrine-panel { display: flex; flex-direction: column; gap: 10px; container-type: inline-size; }
.shrine-head { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.shrine-sub { font-size: 11px; }
.shrine-note { font-size: 11px; margin: 0; }
.shrine-warn {
  font-size: 11.5px; font-weight: 700; margin: 0;
  color: #8a5a00; background: #fff2cc; border: 1px solid var(--gold);
  padding: 6px 10px; border-radius: 10px;
}
.pill-gold { background: linear-gradient(180deg, var(--gold), var(--gold-d)); color: #4a3208; font-weight: 800; border: none; }
.shrine-stage {
  position: relative; width: 100%; aspect-ratio: 1 / 1;
  background: url('assets/moonbloom-shrine.jpg?v=3') center/cover no-repeat;
  border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm);
}
.shrine-slot {
  position: absolute; transform: translate(-50%, -50%);
  display: flex; align-items: center; justify-content: center;
  margin: 0; padding: 0; border: none; background: transparent;
  border-radius: 8px; cursor: pointer;
}
.shrine-slot[disabled] { cursor: default; }
.shrine-slot.empty { transition: background 0.12s ease; }
.shrine-slot.empty:hover { background: rgba(154, 109, 215, 0.30); }
.shrine-slot.filled:hover { background: rgba(0, 0, 0, 0.20); }
.shrine-slot .nft-thumb-card,
.shrine-slot .nft-art,
.shrine-slot .mutant-art { width: 100%; height: 100%; object-fit: contain; }
.shrine-plus { font-size: 5cqw; color: rgba(255, 255, 255, 0.6); font-weight: 700; line-height: 1; }
.shrine-lock { font-size: 4cqw; opacity: 0.7; }
/* Offering altar — sits over the circular dais at the base of the shrine art. */
.shrine-slot.altar {
  background: radial-gradient(closest-side, rgba(255, 190, 80, 0.22), transparent 75%);
  transition: background 0.12s ease;
}
.shrine-slot.altar:hover { background: radial-gradient(closest-side, rgba(255, 190, 80, 0.45), transparent 75%); }
.shrine-cost {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 2.7cqw; font-weight: 800; color: #4a3208; line-height: 1;
  background: linear-gradient(180deg, var(--gold), var(--gold-d));
  padding: 3px 6px; border-radius: 999px; white-space: nowrap;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.3);
}

/* ============================================================
   V2 GAME-FEEL SKIN — DEV-ONLY PREVIEW
   Activated by app.js (`body.v2`) only while state.devMode is on.
   Turns the page layout into a game: full-screen portrait stage,
   floating HUD, wooden dock in the sky (per player decision the nav
   must never cover the farm), panels as drop-down sheets, juice.
   Design source: docs/GAME_UX_PROPOSALS.md + public/v2-preview.html.
   Every weather/time skin has its own portrait artwork (player-provided),
   each with its own plot-centre table in app.js (PLOT_CENTERS_V2).
   ============================================================ */

body.v2 {
  overflow: hidden;
  height: 100vh;   /* fallback for webviews without dvh */
  height: 100dvh;
  /* Extends the scene's own sky/grass on ultra-wide screens. */
  background: linear-gradient(180deg, #0172e7 0%, #4d9bee 40%, #7fbf5a 78%, #5e9c41 100%);
}
body.v2 #app { width: 100%; max-width: none; padding: 0; }
body.v2 .hero { display: none; }
body.v2 .layout { display: block; }

/* ---------------- The stage ---------------- */
body.v2 .farm-scene {
  position: fixed; bottom: 0;
  /* Centre with margins, NOT transform: the base .farm-scene pop-in animation
     (fill mode `both`) would permanently override a transform set here. */
  left: 0; right: 0; margin: 0 auto;
  transform: none; animation: none;
  /* Width/aspect derive from the active skin's own canvas proportions. */
  --scene-ar: 0.4626; /* day scene, 853×1844 */
  width: clamp(320px, max(100vw, calc(100vh * var(--scene-ar))), 900px);  /* fallback */
  width: clamp(320px, max(100vw, calc(100dvh * var(--scene-ar))), 900px);
  aspect-ratio: var(--scene-ar);
  border: 0; outline: none; border-radius: 0;
  box-shadow: none; background: transparent;
  z-index: 0;
}
/* Every time-of-day/weather skin has its own portrait artwork, each with its
   own canvas proportions — the stage reads them from --scene-ar so the cover
   maths and the per-skin plot tables (PLOT_CENTERS_V2 in app.js) line up.
   Keep the selectors compound (body.v2 + skin) so they outrank the
   square-scene skin rules above. */
body.v2 .farm-layer,
body.v2 #plots.farm-dusk .farm-layer,
body.v2 #plots.farm-night .farm-layer,
body.v2 #plots.farm-rain .farm-layer,
body.v2 #plots.farm-rain-night .farm-layer {
  background-image: url("assets/farm-scene-portrait.png?v=1");
  image-rendering: pixelated;
}
body.v2 #plots.farm-dusk .farm-layer { background-image: url("assets/farm-scene-portrait-sunset.png?v=1"); }
body.v2 #plots.farm-night .farm-layer { background-image: url("assets/farm-scene-portrait-night.png?v=1"); }
body.v2 #plots.farm-rain .farm-layer { background-image: url("assets/farm-scene-portrait-rain.png?v=1"); }
body.v2 #plots.farm-rain-night .farm-layer { background-image: url("assets/farm-scene-portrait-rain-night.png?v=1"); }
body.v2 #plots.farm-dusk { --scene-ar: 0.5335; }   /* 916×1717 */
body.v2 #plots.farm-night { --scene-ar: 0.4745; }  /* 864×1821 */
/* The empty-plot hint ring: cells are much shorter in the portrait field. */
body.v2 .cell.empty::after { width: 44%; bottom: 6%; }
body.v2 .cell.locked::after { bottom: 18%; }
/* Field furniture drawn for the square scene, reseated for the portrait one. */
body.v2 .scarecrow2 { left: 82%; top: 74.5%; }
/* Active-boost chips: a stat row right under the SPROUT/coins/score chips,
   instead of floating over the field. */
body.v2 .farm-buffs {
  position: fixed; z-index: 22;
  top: calc(104px + env(safe-area-inset-top));
  left: 0; right: 0; margin: 0 auto;
  width: min(430px, calc(100vw - 20px));
  display: flex; flex-wrap: nowrap; gap: 6px;
  overflow-x: auto; overflow-y: hidden;
  scrollbar-width: none;
  pointer-events: auto;
  padding: 0 2px 2px;
}
body.v2 .farm-buffs::-webkit-scrollbar { display: none; }

/* Large farm-number title over the field — a persistent scene title so it's
   always clear which farm is on screen. Sits just under the boost-chip row,
   centred over the sky. Same layer band as the chips (below the z-40 panels, so
   an open menu covers it); click-through so it never blocks the field. */
body.v2 .farm-title {
  position: fixed; z-index: 21;
  top: calc(148px + env(safe-area-inset-top));
  left: 0; right: 0; margin: 0 auto;
  display: flex; justify-content: center;
  pointer-events: none;
}
body.v2 .farm-title[hidden] { display: none; }
body.v2 .farm-title .farm-title-badge {
  display: inline-flex; align-items: baseline; gap: 8px;
  padding: 6px 20px; border-radius: 14px;
  background: rgba(20, 14, 6, 0.55);
  border: 1.5px solid rgba(255, 220, 160, 0.45);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.35);
}
body.v2 .farm-title .ft-label {
  font-family: var(--font-display); font-weight: 700; font-size: 24px;
  color: #fff6df; letter-spacing: 0.5px;
  text-shadow: 0 2px 4px rgba(0, 0, 0, 0.6), 0 0 2px rgba(0, 0, 0, 0.8);
}
body.v2 .farm-title .ft-num {
  font-family: var(--font-display); font-weight: 700; font-size: 24px;
  color: #ffd679; text-shadow: 0 2px 4px rgba(0, 0, 0, 0.6);
}
body.v2 .farm-title .ft-of {
  font-family: var(--font-display); font-weight: 600; font-size: 13px; color: #e7d3ad;
}

/* ---------------- Floating HUD ---------------- */
body.v2 .hud {
  position: fixed; top: 0; left: 0; right: 0; margin: 0; z-index: 45;
  height: auto;
  padding: calc(8px + env(safe-area-inset-top)) 12px 6px;
  background: transparent;
  border-bottom: 0; box-shadow: none; backdrop-filter: none;
  pointer-events: none;
  flex-wrap: wrap; row-gap: 8px;
}
body.v2 .hud > * { pointer-events: auto; }
body.v2 .brand { display: none; }
body.v2 .chip {
  background: rgba(15, 25, 10, 0.66);
  border-color: rgba(255, 255, 255, 0.16);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, 0.35), 0 1px 0 rgba(255, 255, 255, 0.1);
  backdrop-filter: blur(3px);
}
body.v2 .chip strong { color: #ffe9b0; }
body.v2 .chip-tag { color: #cbb591; }
body.v2 .hud .btn-ghost {
  background: rgba(15, 25, 10, 0.6);
  color: #fff;
  border: 1px solid rgba(255, 255, 255, 0.2);
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(3px);
}

/* Level medallion (hidden outside V2 via [hidden] set from JS). */
.lvl-medal[hidden] { display: none !important; }
body.v2 .lvl-medal {
  position: relative; flex: 0 0 auto;
  width: 52px; height: 52px; border-radius: 50%;
  border: 0; padding: 0; cursor: default;
  display: grid; place-items: center;
  background: conic-gradient(var(--gold) calc(var(--xp, 0) * 1%), rgba(255, 255, 255, 0.22) 0);
  filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.35));
}
body.v2 .lvl-medal .core {
  width: 42px; height: 42px; border-radius: 50%;
  background: linear-gradient(180deg, #486b2f, #2c4519);
  border: 2px solid rgba(255, 255, 255, 0.3);
  display: grid; place-items: center; font-size: 20px;
}
body.v2 .lvl-medal .lvl-tag {
  position: absolute; bottom: -6px; left: 50%; transform: translateX(-50%);
  font-family: var(--font-display); font-weight: 700; font-size: 10px; color: #2c1f08;
  background: linear-gradient(180deg, #ffe19a, var(--gold));
  padding: 1px 8px; border-radius: 999px; white-space: nowrap;
  box-shadow: 0 2px 0 rgba(0, 0, 0, 0.35);
}

/* Flying coin (harvest -> HUD). Fixed so it survives the field re-render. */
.v2-coin-fly {
  position: fixed; z-index: 60; pointer-events: none;
  width: 26px; height: 26px;
  background: url("assets/coin.png?v=3") center / contain no-repeat;
  image-rendering: pixelated;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.4));
}

/* ---------------- Wooden dock, docked at the bottom ---------------- */
/* The dock rides the bottom of the screen (like the production nav) so tab
   panels get the full height above it — no more squeezed sheets or the dead
   band the sky-dock left under short menus. */
body.v2 .tabs { display: none; }
body.v2 .bottom-nav {
  display: flex;
  position: fixed; left: 0; right: 0; top: auto;
  bottom: calc(8px + env(safe-area-inset-bottom));
  margin: 0 auto;
  width: min(430px, calc(100vw - 20px));
  background: linear-gradient(180deg, #52381f, #3a2a18);
  border: 1px solid rgba(255, 220, 160, 0.3);
  border-top: 1px solid rgba(255, 220, 160, 0.3);
  border-radius: 18px;
  padding: 7px 6px 8px;
  box-shadow: 0 8px 20px rgba(0, 0, 0, 0.4), inset 0 1px 0 rgba(255, 255, 255, 0.14);
  overflow-x: auto; overflow-y: visible;
  scrollbar-width: none;
  gap: 2px;
  z-index: 44;
}
body.v2 .nav-item {
  position: relative;
  flex: 1 0 auto; min-width: 56px;
  appearance: none; border: none; background: transparent; cursor: pointer;
  display: grid; justify-items: center; gap: 2px;
  font-family: var(--font-ui); font-weight: 800; font-size: 20px;
  color: #cbb591;
  padding: 4px 0 3px;
  border-radius: 10px;
  opacity: 0.78; filter: saturate(0.75);
}
body.v2 .nav-item span {
  font-size: 8.5px; line-height: 1.1; letter-spacing: 0.05em; text-transform: uppercase;
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
body.v2 .nav-item.active {
  color: #ffe9b0; opacity: 1; filter: none;
  background: rgba(255, 220, 160, 0.14);
}
body.v2 .nav-item[data-badge]:not([data-badge=""])::after {
  content: attr(data-badge);
  position: absolute; top: -3px; right: 3px;
  min-width: 16px; height: 16px; border-radius: 999px; padding: 0 4px;
  background: linear-gradient(180deg, #ff8a6a, #e04f2e);
  color: #fff; font-size: 9.5px; font-weight: 800; line-height: 16px;
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

/* ---------------- Panels are full-screen overlays over the stage --------- */
/* Player decision: every tab artwork is the FULL-SCREEN backdrop of its tab,
   never a banner inside a sheet. The panel covers the viewport (content slides
   up from the bottom), sits under the HUD/dock, and each tab swaps the
   backdrop below. Content scrolls over the art. */
body.v2 .col-panel {
  display: block;
  position: fixed; inset: 0; z-index: 40;
  /* The base .col-panel sets align-self:start, which makes an inset-stretched
     fixed box collapse to its content height — pin the height explicitly. */
  height: 100%; align-self: stretch;
  width: auto; max-height: none; margin: 0;
  overflow-y: auto; overscroll-behavior: contain;
  background: linear-gradient(180deg, #241a10, #38281a);
  image-rendering: pixelated;
  border: 0; border-radius: 0; box-shadow: none;
  /* Top padding clears the floating HUD; bottom padding clears the docked nav
     so the last row of a list is never hidden behind it. */
  padding: calc(104px + env(safe-area-inset-top)) 10px calc(84px + env(safe-area-inset-bottom));
  transform: translateY(102%);
  transition: transform 0.34s cubic-bezier(0.22, 1.1, 0.36, 1);
}
/* Backdrops por aba: a arte inteira cobre a tela, SEM véu escuro — as artes
   entram cheias. A legibilidade do conteúdo vem dos próprios cartões (madeira
   escura) e da sombra de texto nos títulos. */
body.v2.screen-market .col-panel {
  background: #241a10 url("assets/marketplace-portrait.png?v=2") center / cover no-repeat;
}
body.v2.screen-nfts .col-panel {
  background: #101a24 url("assets/nft-lab-portrait.png?v=1") center / cover no-repeat;
}
body.v2.screen-stake .col-panel {
  background: #09150d url("assets/greenhouse-portrait.png?v=1") center / cover no-repeat;
}
body.v2.screen-rank .col-panel {
  background: #14202e url("assets/rank-portrait.png?v=1") center / cover no-repeat;
}
/* Shrine: SÓ a imagem de fundo funcional (o palco interativo com os slots).
   Sem uma cópia decorativa em `cover` no painel — ela reaparecia embaixo do
   palco rolado e criava a imagem fantasma atrás das notas. Fundo chapado. */
body.v2.screen-shrine .col-panel {
  background: linear-gradient(180deg, #1a1030, #140b20);
}
body.v2.screen-shop .col-panel,
body.v2.screen-inventory .col-panel,
body.v2.screen-nfts .col-panel,
body.v2.screen-shrine .col-panel,
body.v2.screen-stake .col-panel,
body.v2.screen-market .col-panel,
body.v2.screen-rank .col-panel { transform: none; }

/* NFT Lab: cartões translúcidos para a arte do laboratório aparecer atrás
   (o conteúdo continua legível — vidro escuro + texto claro). */
body.v2.screen-nfts .col-panel .row {
  background: rgba(14, 22, 32, 0.60);
  border-color: rgba(150, 200, 255, 0.28);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.32);
}
body.v2.screen-nfts .col-panel .row .row-title span.name { color: #eef4ff; }
body.v2.screen-nfts .col-panel .row .row-meta { color: #c3d3e6; }
body.v2.screen-nfts .col-panel .row.selected {
  border-color: #8bd15a;
  background: rgba(58, 88, 40, 0.62);
  box-shadow: 0 0 0 2px rgba(139, 209, 90, 0.4);
}
body.v2.screen-nfts .col-panel .empty-state { color: #dfeaf6; }

/* Greenhouse: vidraria translúcida, mas LEGÍVEL — as cartas ficam mais opacas
   e todo texto solto sobre a arte clara ganha um chip escuro + sombra. */
body.v2.screen-stake .col-panel .row {
  background: rgba(8, 22, 13, 0.78);
  border-color: rgba(150, 220, 160, 0.32);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.4);
}
body.v2.screen-stake .col-panel .row .name { color: #f1fdec; text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6); }
body.v2.screen-stake .col-panel .row .row-meta { color: #cdeccf; }
/* Loose lines that sit straight on the bright artwork (intro, active-boost
   banner, stake note/preview) get their own dark chip so they stay readable. */
body.v2.screen-stake #stake-panel > p.muted,
body.v2.screen-stake .col-panel .stake-agg,
body.v2.screen-stake .col-panel .stake-note,
body.v2.screen-stake .col-panel .stake-preview {
  background: rgba(8, 20, 12, 0.70);
  border-radius: 10px;
  padding: 8px 11px;
  color: #eafbe6;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
  backdrop-filter: blur(3px);
  -webkit-backdrop-filter: blur(3px);
}
body.v2.screen-stake .col-panel .stake-agg { border-color: rgba(150, 230, 150, 0.4); }

/* Rank & Clans: castle artwork backdrop with the same translucent glass on the
   leaderboard rows and the clan/referral banners. */
body.v2.screen-rank .col-panel .row,
body.v2.screen-rank .col-panel .vault-banner {
  background: rgba(14, 24, 38, 0.62);
  border-color: rgba(150, 190, 255, 0.30);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.34);
}
body.v2.screen-rank .col-panel .row .name,
body.v2.screen-rank .col-panel .row .row-title span.name,
body.v2.screen-rank .col-panel .vault-banner { color: #eaf1ff; }
body.v2.screen-rank .col-panel .row .row-meta { color: #c3d3e6; }
body.v2.screen-rank .col-panel .empty-state { color: #dfeaf6; }

/* Marketplace: cartões translúcidos para a arte das barracas aparecer atrás
   (vidro escuro e quente + texto claro, casando com a cena). */
body.v2.screen-market .col-panel .row {
  background: rgba(24, 16, 8, 0.60);
  border-color: rgba(255, 220, 160, 0.28);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.34);
}
body.v2.screen-market .col-panel .row .name,
body.v2.screen-market .col-panel .row .row-title span.name { color: #fbf0d8; }
body.v2.screen-market .col-panel .row .row-meta { color: #e3d3ac; }
body.v2.screen-market .col-panel .empty-state { color: #f0e2c4; }

/* O palco do Shrine é interativo (slots sobre a arte). Ele preenche a tela
   inteira como a cena da fazenda: a largura é dirigida para que a altura da
   arte sempre cubra a viewport, ancorada embaixo e centralizada (as bordas
   laterais recortam, o santuário fica central). Os slots são % deste elemento,
   então continuam alinhados à arte em qualquer tamanho. Fica no z-index 0 do
   painel (col-panel z-40), logo abaixo do HUD (z-45) e do dock (z-44), como as
   fazendas — arte imersiva por baixo da moldura fixa. */
body.v2 #shrine-panel .shrine-stage {
  position: fixed; left: 50%; bottom: 0; transform: translateX(-50%);
  width: clamp(320px, max(100vw, calc(100vh * 0.5768)), 900px);   /* 852/1477 */
  width: clamp(320px, max(100vw, calc(100dvh * 0.5768)), 900px);
  margin: 0; border-radius: 0; box-shadow: none;
  z-index: 0;
}
/* Shrine V2: o texto e o mostruário de bônus flutuam sobre o céu pintado acima
   do santuário — o palco é a base e o overlay é click-through (não bloqueia os
   slots), com um véu que some de cima para baixo para o texto ficar legível. */
body.v2 #shrine-panel { position: relative; display: block; }
body.v2 #shrine-panel .shrine-sky {
  position: absolute; top: 0; left: 0; right: 0; z-index: 3;
  display: flex; flex-direction: column; gap: 8px;
  padding: 4px 10px 22px;
  pointer-events: none;
  background: linear-gradient(180deg,
    rgba(12, 7, 24, 0.82) 0%, rgba(12, 7, 24, 0.55) 45%, rgba(12, 7, 24, 0) 100%);
}
body.v2 #shrine-panel .shrine-sky .pill { pointer-events: auto; }
body.v2 #shrine-panel .shrine-sky .shrine-sub {
  color: #d6c9f5; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}
body.v2 #shrine-panel .shrine-sky .shrine-note {
  color: #eae3f7; text-shadow: 0 1px 3px rgba(0, 0, 0, 0.92);
}
body.v2 #shrine-panel .shrine-sky .shrine-warn {
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.9);
}
/* Minimizar/expandir as notas do shrine. Os mostradores de bônus (pills) ficam
   sempre visíveis; isto só dobra os parágrafos de explicação, e a escolha é
   lembrada. Fica no canto superior-direito sobre o céu (o pai é click-through,
   então o botão reativa o próprio ponteiro); a fileira de pills reserva espaço
   para nenhuma pill correr por baixo dele. */
body.v2 #shrine-panel .shrine-sky .shrine-head { padding-right: 38px; }
body.v2 #shrine-panel .shrine-notes-toggle {
  position: absolute; top: 6px; right: 8px;
  width: 30px; height: 30px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-size: 18px; font-weight: 800; line-height: 1;
  color: #f0e6ff; pointer-events: auto; cursor: pointer;
  background: rgba(30, 18, 52, 0.75);
  border: 1px solid rgba(214, 201, 245, 0.45);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.42);
}
body.v2 #shrine-panel .shrine-sky.notes-collapsed .shrine-notes-body { display: none; }
/* Greenhouse: a arte é o fundo do painel — o hero interno sai de cena. */
body.v2 .greenhouse-hero { display: none; }
body.v2 #tab-stake { background: transparent; }
/* Cream headings sit straight on the artwork now (no veil), so a soft dark
   halo keeps them readable over bright sky. */
body.v2 .col-panel .section-head h2,
body.v2 .col-panel .section-head h3 {
  color: #ffe9b0;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85), 0 0 10px rgba(0, 0, 0, 0.55);
}
body.v2 .col-panel .section-head .muted,
body.v2 .col-panel > .tab-panel > .muted {
  color: #f0e2c4;
  text-shadow: 0 1px 3px rgba(0, 0, 0, 0.85);
}
body.v2 .empty-state { color: #cbb591; }

/* The farm column stays on stage behind an open sheet (the mobile rules hide
   it per-screen; in V2 the field must always be visible). */
body.v2 .col-farm { display: block !important; }

/* ---------------- Farm-screen furniture ---------------- */
/* Event banner / daily / tip live in a slim scrollable column in the sky.
   With the dock now at the bottom, this starts right under the HUD and gets
   more headroom, so the streak/quest card is no longer clipped mid-row.
   The column itself is click-through (pointer-events:none) so its empty area
   never steals taps from the plots below — only the cards catch input. */
body.v2 .col-farm {
  position: fixed; z-index: 20;
  left: 0; right: 0; margin: 0 auto;
  top: calc(146px + env(safe-area-inset-top));   /* below the HUD + boost-chip row */
  width: min(430px, calc(100vw - 20px));
  max-height: 40vh;   /* fallback for webviews without dvh */
  max-height: 40dvh;
  overflow-y: auto; overscroll-behavior: contain;
  scrollbar-width: none;
  pointer-events: none;
  padding-right: 42px;   /* right lane reserved for the collapse handle */
}
body.v2 .col-farm > .section-head { display: none; }

/* Collapse handle: clears the event/streak/tip cards off the field. Lives in
   the reserved right lane of the sky column so it never covers card content.
   z-21 keeps it above the column but below open menu panels (z-40), so it only
   shows on the farm screen. */
.farm-cards-toggle { display: none; }
body.v2 .farm-cards-toggle {
  display: grid; place-items: center;
  position: fixed; z-index: 21;
  top: calc(148px + env(safe-area-inset-top));
  right: max(10px, calc(50% - 215px + 4px));
  width: 34px; height: 34px; border-radius: 50%;
  border: 1px solid rgba(255, 220, 160, 0.35);
  background: rgba(20, 14, 6, 0.72);
  color: #ffe9b0; font-size: 16px; font-weight: 800; line-height: 1;
  backdrop-filter: blur(4px);
  box-shadow: 0 3px 10px rgba(0, 0, 0, 0.4);
  cursor: pointer;
}
body.v2 .farm-cards-toggle::before { content: "\2013"; }        /* – minimize */
body.v2.cards-hidden .farm-cards-toggle::before { content: "\002B"; }  /* + restore */
body.v2.cards-hidden .col-farm { display: none !important; }
body.v2 .daily, body.v2 .tip, body.v2 .event-banner {
  /* Above the stage: #plots is a positioned CHILD of .col-farm (z 0), so its
     static siblings would otherwise paint underneath the full-screen scene. */
  position: relative; z-index: 2;
  pointer-events: auto;   /* re-enable input on the cards (column is click-through) */
  background: rgba(20, 14, 6, 0.72);
  border: 1px solid rgba(255, 220, 160, 0.25);
  color: #f5ead2;
  backdrop-filter: blur(4px);
  box-shadow: 0 4px 14px rgba(0, 0, 0, 0.3);
  margin-bottom: 8px;
}
body.v2 .tip-text { color: #f5ead2; }
body.v2 .tip-head { color: #ffd679; }
body.v2 .tip-icon { background: rgba(255, 220, 160, 0.15); border-color: rgba(255, 220, 160, 0.3); }
body.v2 .tip-next { background: rgba(255, 220, 160, 0.12); color: #f5ead2; border-color: rgba(255, 220, 160, 0.3); }
body.v2 .daily .muted { color: #cbb591; }
body.v2 .quest .q-top { color: #f5ead2; }
body.v2 .q-bar { background: rgba(255, 255, 255, 0.14); }
body.v2 .streak-badge { background: rgba(255, 220, 160, 0.14); border-color: rgba(255, 220, 160, 0.3); }
body.v2 .streak-badge small { color: #cbb591; }

/* Bulk actions float over the dirt path, lifted to clear the docked nav.
   Stays at z-20 (below the z-40 panels) so it hides under an open menu. */
body.v2 .farm-actions {
  position: fixed; z-index: 20;
  left: 0; right: 0; margin: 0 auto;
  bottom: calc(66px + env(safe-area-inset-bottom));
  width: min(430px, calc(100vw - 20px));
}
/* Farm switcher hovers just above the bulk actions. */
body.v2 .farm-switcher {
  position: fixed; z-index: 20;
  left: 0; right: 0; margin: 0 auto;
  bottom: calc(118px + env(safe-area-inset-bottom));
  width: min(430px, calc(100vw - 20px));
}
body.v2 .farm-switch-row {
  background: rgba(20, 14, 6, 0.72);
  border-color: rgba(255, 220, 160, 0.3);
  backdrop-filter: blur(4px);
}
body.v2 .farm-switch-row .farm-label { color: #ffe9b0; }

/* Toast clears the docked nav and the floating bulk-action bar. */
body.v2 #toast { bottom: calc(126px + env(safe-area-inset-bottom)); }

/* ---------------- V2: Moonbloom Shrine portrait stage ---------------- */
/* The portrait shrine art replaces the square one; slot coordinates come from
   SHRINE_SLOT_POS_V2 in app.js (same nine frames, measured on this art). */
body.v2 .shrine-stage {
  aspect-ratio: 852 / 1477;   /* top 20% sky trimmed off the art */
  background-image: url("assets/moonbloom-shrine-portrait.png?v=2");
  image-rendering: pixelated;
}


