/* =====================================================================
   TATO TRASH EMPIRE - look & feel
   Night-in-the-alley palette: deep blue dark, moonlit teal, trash green.
   Chunky cartoon panels with hard outlines and a fat bottom shadow, so
   everything reads as a pressable plastic button on a phone.
   ===================================================================== */

:root {
  --bg:        #0e1320;
  --bg-2:      #131a2b;
  --panel:     #1c2438;
  --panel-2:   #232d45;
  --line:      #0a0e18;

  --teal:      #2fd6a5;
  --teal-dk:   #12836a;
  --moon:      #e8f4c8;
  --lime:      #9ee84f;
  --lime-dk:   #4d8c1d;
  --amber:     #ffc247;
  --amber-dk:  #a86e10;
  --pink:      #ff6b9d;
  --blue:      #4aa8ff;
  --purple:    #b07cff;

  --text:      #eaf1ff;
  --muted:     #8fa0c0;

  --r:   14px;
  --r-s: 10px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }

html, body {
  width: 100%;
  height: 100%;
  background: var(--bg);
  color: var(--text);
  font-family: "Segoe UI", system-ui, -apple-system, "Trebuchet MS", sans-serif;
  font-weight: 700;
  overflow: hidden;
  overscroll-behavior: none;
  -webkit-user-select: none;
  user-select: none;
  -webkit-tap-highlight-color: transparent;
}

body {
  /* the alley: a faint moon glow at the top, grime at the bottom */
  background:
    radial-gradient(120% 60% at 50% -10%, #223055 0%, transparent 60%),
    var(--bg);
}

#app {
  position: relative;
  width: 100%;
  max-width: 560px;
  height: 100%;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  padding: env(safe-area-inset-top) 0 env(safe-area-inset-bottom);
  /* Plain gradient, no pattern. This used to carry two repeating
     gradients as "brick courses" - 1px white lines every 26px and 52px.
     At 1.7% opacity they were meant to be subliminal, but a 1px line is
     never subliminal: the phone snaps it to a whole pixel and it lands
     at full strength, so the background read as a grid of pale
     rectangles rather than as an alley wall. */
  background:
    radial-gradient(120% 70% at 50% 0%, #1b2440 0%, var(--bg-2) 55%, #0f1523 100%);
  box-shadow: 0 0 0 1px #000, 0 0 40px #000;
}

.hidden { display: none !important; }
.muted  { color: var(--muted); font-size: 12px; }

/* ------------------------------ HEADER ------------------------------ */
#top {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 10px;
  background: linear-gradient(#26314d, #1a2236);
  border-bottom: 3px solid var(--line);
}

.avatar {
  position: relative;
  width: 40px; height: 40px;
  flex: 0 0 40px;
  font-size: 24px;
  border-radius: var(--r-s);
  background: linear-gradient(#3d4f7d, #212b45);
  border: 3px solid var(--line);
  display: grid;
  place-items: center;
  font-size: 28px;
}
.avatar-badge {
  position: absolute; top: -8px; right: -8px;
  width: 22px; height: 22px;
  border-radius: 50%;
  background: var(--pink);
  border: 2px solid var(--line);
  display: grid; place-items: center;
  font-size: 13px; color: #fff;
}

.wallet { flex: 1; display: flex; gap: 6px; min-width: 0; }

.coin {
  flex: 0 1 auto;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 4px;
  padding: 6px 8px;
  border-radius: 999px;
  border: 3px solid var(--line);
  background: linear-gradient(#36436a, #222c46);
  font-size: 14.5px;
  white-space: nowrap;
  overflow: hidden;
}
.coin-ico { font-size: 15.5px; flex: 0 0 auto; }
.coin-val { min-width: 0; overflow: hidden; text-overflow: ellipsis; }
/* The raccoon chip holds a count AND a rate, so it gets the lion's share.
   Stars and cards are one short number each and shrink to suit. */
.coin-rat     { background: linear-gradient(#3c5a4e, #1e3329); flex: 1 1 auto; }
.coin-star    { background: linear-gradient(#6a5a2a, #3d3216); }
.coin-card    { background: linear-gradient(#4a3a6a, #271e3d); }

/* --------------------------- RESOURCE BAR --------------------------- */
/* One box per harvested thing, and under them the bulk step. This sits
   below #tasks and above #pages, so it never scrolls away - the plastic
   count and the buy step are the two things you look at while you are
   halfway down the row list. */
#res-bar {
  padding: 8px 10px;
  background: linear-gradient(#17324a, #102232);
  border-bottom: 3px solid var(--line);
}
.res-boxes { display: flex; gap: 8px; }
.res {
  flex: 1;
  min-width: 0;
  display: flex;
  align-items: center;
  gap: 7px;
  padding: 6px 11px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  background: linear-gradient(#24405a, #16293c);
  color: var(--text);
  font: inherit;
  cursor: pointer;
  box-shadow: 0 3px 0 var(--line);
}
/* the box of the zone you are standing in */
.res.on { background: linear-gradient(#2c5570, #173347); }
.res:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--line); }
.res-ico { font-size: 20px; flex: 0 0 auto; }
.res-val {
  flex: 1; min-width: 0;
  text-align: left;
  font-size: 21px;
  color: var(--moon);
  text-shadow: 0 2px 0 var(--line);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* The bulk step hangs off the right, under the boxes. It is hidden rather
   than removed off the collect page: dropping it would change the height of
   a bar that sits above the pages, so every page below would jump. */
.res-tools { display: flex; justify-content: flex-end; margin-top: 7px; visibility: hidden; }
#res-bar.buying .res-tools { visibility: visible; }

.icon-btn {
  flex: 0 0 34px;
  width: 34px; height: 34px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  background: linear-gradient(#36436a, #222c46);
  color: var(--text);
  font-size: 18px;
  cursor: pointer;
}

/* ------------------------------ RANK -------------------------------- */
/* One box per pack opened this level. Fill them all and the way out of
   the level lights up. */
#rank {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 7px 10px;
  background: linear-gradient(#232d45, #1a2236);
  border-bottom: 3px solid var(--line);
}
.rank-level {
  flex: 0 0 auto;
  font-size: 11px;
  color: var(--moon);
  letter-spacing: .5px;
}
.rank-boxes {
  flex: 1;
  display: flex;
  gap: 3px;
}
.rank-box {
  flex: 1;
  height: 14px;
  border-radius: 3px;
  background: #0d1220;
  border: 2px solid var(--line);
  transition: background .2s;
}
.rank-box.on {
  background: linear-gradient(var(--amber), var(--amber-dk));
}
#rank.full .rank-box.on {
  background: linear-gradient(var(--lime), var(--lime-dk));
}
.rank-btn {
  flex: 0 0 auto;
  padding: 4px 9px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  background: linear-gradient(var(--lime), var(--lime-dk));
  color: #16290a;
  font: inherit;
  font-size: 9px;
  line-height: 1.15;
  letter-spacing: .5px;
  cursor: pointer;
  box-shadow: 0 3px 0 var(--line);
  animation: shake 1.6s infinite;
}

/* the one "come and get it" wobble in the game */
@keyframes shake {
  0%, 70%, 100% { transform: rotate(0) }
  75% { transform: rotate(-6deg) scale(1.05) }
  80% { transform: rotate(6deg)  scale(1.05) }
  85% { transform: rotate(-4deg) scale(1.03) }
  90% { transform: rotate(4deg)  scale(1.03) }
}

/* ------------------------------ TASKS ------------------------------- */
/* One band, three columns. Each column carries two layouts and shows
   exactly one: the job while it runs, and the pack once it is finished.
   A finished task hands its whole cell to the pack. */
#tasks {
  display: flex;
  gap: 10px;
  padding: 8px 10px 10px;
  background: linear-gradient(#1f2a42, #182034);
  border-bottom: 3px solid var(--line);
}
.task {
  flex: 1 1 0;
  min-width: 0;
  display: flex;
  /* A HEIGHT OF ITS OWN, not one borrowed from a sibling. The cells used
     to be sized by whichever of the three was still running, so when all
     three finished at once every .task-todo was display:none, nothing
     was left to set the height, and the packs collapsed to nothing -
     three cells reading CLICK TO CLAIM with no pack above them. */
  height: 76px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  background: linear-gradient(#26314d, #1a2236);
}

/* ---- the job, while it is running ---- */
.task-todo {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 5px;
  padding: 6px 7px;
}
.task.done .task-todo { display: none; }

/* icon and wording on one line: the icon already says which pile, so
   the text only has to carry the number. The pair is centred as a
   group, so a short label does not sit off in the corner. */
.task-head {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 5px;
  min-width: 0;
}
.task-text {
  flex: 0 1 auto;
  min-width: 0;
  font-size: 9.5px;
  line-height: 1.2;
  text-align: center;
  color: var(--text);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* The count sits ON the bar rather than under it - the same trick the
   collection rows use for their timer. One line instead of two, so the
   bar can be thick enough to read the number off. */
/* .task .task-bar, not .task-bar: the generic .bar rule is further down
   the file and carries the same specificity, so it would win on height. */
.task .task-bar { width: 100%; height: 18px; position: relative; }
.task-count {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 10.5px;
  color: #fff;
  /* an outline, not a drop shadow: this text crosses from the dark
     track onto bright lime as the bar fills, and has to hold up on both */
  text-shadow: 0 0 3px #000, 0 0 2px #000, 0 1px 1px #000;
  pointer-events: none;
}

/* where the work happens. Dimmed: it is a signpost, not a prize. */
.task-goal {
  flex: 0 0 auto;
  width: 20px; height: 20px;
  display: grid; place-items: center;
  font-size: 15px; line-height: 1;
  color: var(--text);
}
.task-goal svg { display: block; width: 100%; height: 100%; opacity: .6; }
.task-tick { opacity: .4; }

/* ---- the prize, once it is finished ---- */
.task-claim {
  flex: 1;
  min-width: 0;
  display: none;            /* flex, once .task is .done */
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  gap: 3px;
  padding: 5px 4px 6px;
  border: 0;
  border-radius: 7px;
  background: none;
  font: inherit;
  color: var(--lime);
  cursor: pointer;
  animation: pack-wiggle 1.9s infinite;
}
.task.done { background: linear-gradient(#2d4a3a, #1b3026); border-color: var(--lime-dk); }
.task.done .task-claim { display: flex; }
.task-claim:active { transform: scale(.94); animation: none; }

.task-pack { flex: 1; min-height: 0; display: grid; place-items: center; }
.task-pack svg {
  display: block;
  height: 100%;
  width: auto;
  /* neutral, not amber: the pack's own colour is what states its rarity,
     so the lift under it must not tint a white common pack gold */
  filter: drop-shadow(0 0 9px rgba(255, 255, 255, .32));
}
.task-claim-label {
  font-size: 8.5px;
  letter-spacing: .6px;
  line-height: 1.1;
  text-align: center;
}

/* A slow lean, not the chest's rattle. The pack is paper - it should
   look like it is being offered, not like it is about to explode. */
@keyframes pack-wiggle {
  0%, 72%, 100% { transform: rotate(0) }
  80%           { transform: rotate(-3deg) }
  90%           { transform: rotate(3deg) }
}

/* ---- a level with no tasks left ---- */
.task.spent { opacity: .45; }

.bar {
  height: 12px;
  border-radius: 999px;
  background: #090d18;
  border: 2px solid var(--line);
  box-shadow: inset 0 2px 4px rgba(0, 0, 0, .55);
  overflow: hidden;
}
/* One green, lit from above by the gradient alone.
   Two things have been taken off this:
     - the diagonal stripes, which stood still while the bar grew, so
       every step the fill took read as the stripes jerking
     - a 2px white inset highlight across the top. A hard bright edge on
       a rounded shape that is re-measured every frame never rasterises
       the same way twice, so it crawled and sparkled along the top of
       the bar. The gradient gives the same lit look with no edge for
       the light to catch on. */
.bar-fill {
  position: relative;
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(#b6f072, var(--lime) 45%, var(--lime-dk));
  transition: width .18s linear;
}

/* ------------------------------ PAGES ------------------------------- */
#pages { flex: 1; min-height: 0; position: relative; }
.page {
  position: absolute; inset: 0;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 10px 10px 18px;
}

.zone-bar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 8px; margin-bottom: 10px;
  font-size: 13px;
}
.section-h { font-size: 13px; margin: 16px 0 6px; color: var(--moon); }
.section-p { font-size: 11px; color: var(--muted); margin-bottom: 8px; font-weight: 600; }
.foot-note {
  margin-top: 14px; text-align: center;
  font-size: 11px; font-weight: 600; color: var(--muted);
  line-height: 1.5;
}

/* One button that cycles x1 -> 10% -> 50% -> MAX, rather than four that
   are always three-quarters wrong. It is styled as the live setting, not
   as a menu, so it always reads as "this is what a buy costs right now". */
.bulk-btn {
  min-width: 62px;
  padding: 5px 13px;
  border-radius: 999px;
  border: 3px solid var(--line);
  background: linear-gradient(var(--teal), var(--teal-dk));
  color: #04241c;
  font: inherit; font-size: 13px;
  letter-spacing: .5px;
  cursor: pointer;
  box-shadow: 0 3px 0 var(--line);
}
.bulk-btn:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--line); }

/* ------------------------------- ROWS ------------------------------- */
.row {
  display: flex;
  gap: 9px;
  padding: 9px;
  margin-bottom: 11px;
  border-radius: var(--r);
  border: 3px solid var(--line);
  /* a lit top edge and a dark floor: the panel reads as a physical slab
     instead of a flat rectangle */
  background:
    linear-gradient(rgba(255,255,255,.07), rgba(255,255,255,0) 40%),
    linear-gradient(var(--panel-2), var(--panel));
  box-shadow: 0 5px 0 var(--line), inset 0 1px 0 rgba(255,255,255,.09);
}

/* the tappable pile of trash on the left, with the count of raccoons
   working it and the lifetime haul underneath */
/* 62px, not 76px: every pixel here comes off the Buy button, and at
   "BUY x100 RACCOONS · 🦝 100 · ♻️ 1 M" that button is the tightest
   thing on a 375px screen. The disc is still large enough to tap. */
.row-left { flex: 0 0 62px; width: 62px; display: flex; flex-direction: column; gap: 5px; }

/* A round, light-blue disc with the drawn item on it. It goes a deeper
   blue the moment there are stars waiting to be picked up. */
.row-tap {
  position: relative;
  height: 62px;
  border-radius: 50%;
  border: 3px solid var(--line);
  background:
    radial-gradient(circle at 50% 22%, #cfe9ff 0%, #8ecbf2 55%, #5aa7d8 100%);
  box-shadow: inset 0 -5px 10px rgba(20, 60, 100, .35);
  display: grid; place-items: center;
  cursor: pointer;
  transition: transform .08s, background .3s;
}
.row-tap:active { transform: scale(.92); }
.row-tap.auto   { cursor: default; }
.row-tap.has-stars {
  background:
    radial-gradient(circle at 50% 22%, #6fb3e8 0%, #2f6fae 55%, #17457a 100%);
  box-shadow: inset 0 -5px 10px rgba(6, 28, 55, .5), 0 0 16px rgba(74, 168, 255, .5);
}
.row-emoji { display: block; width: 50px; height: 50px; }
.row-emoji svg { display: block; width: 100%; height: 100%; }

/* stars land on the pile and wait there to be picked up */
.row-stars {
  position: absolute; left: -8px; top: -9px;
  display: flex; align-items: center; gap: 2px;
  padding: 2px 7px;
  border-radius: 999px;
  background: linear-gradient(var(--amber), var(--amber-dk));
  border: 3px solid var(--line);
  color: #2b1c00;
  font-size: 11px;
  box-shadow: 0 0 12px rgba(255, 194, 71, .6);
  animation: nudge 1s infinite;
}

.row-tap-hint {
  position: absolute; bottom: -6px; right: -6px;
  padding: 1px 6px;
  border-radius: 999px;
  background: var(--amber);
  border: 2px solid var(--line);
  color: #2b1c00;
  font-size: 9px;
  animation: nudge 1.1s infinite;
}
/* a run is already out - the pile will not take another tap yet */
.row-tap-hint.busy {
  background: #3b4666;
  color: var(--muted);
  animation: none;
}
@keyframes nudge {
  0%, 100% { transform: translateY(0) }
  50%      { transform: translateY(-3px) }
}

/* how many raccoons are on the pile, filling up to the next star */
.row-stock {
  position: relative;
  text-align: center;
  font-size: 11px;
  padding: 3px 2px;
  border-radius: 999px;
  background: #0d1220;
  border: 2px solid var(--line);
  overflow: hidden;
}
.row-stock-fill {
  position: absolute; left: 0; top: 0; bottom: 0;
  width: 0%;
  background: linear-gradient(#6b5a22, #4a3d16);
  transition: width .2s linear;
}
.row-stock-num {
  position: relative;
  color: var(--moon);
  text-shadow: 0 1px 2px #000;
}

.row-main { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 6px; }

.row-head {
  display: flex; align-items: baseline; justify-content: space-between; gap: 6px;
  font-size: 13px;
}
.row-out { font-size: 11px; color: var(--teal); white-space: nowrap; }
.row-out.idle { color: var(--muted); }

/* The collection bar: one sweep is one cycle. It is driven by
   UI.refreshBars() on every animation frame, so it must not carry a
   width transition - the browser would still be easing towards the last
   value when the next one lands, and the sweep would drag behind the
   timer. */
.row-bar { position: relative; height: 16px; }
.row-bar .bar-fill { transition: none; }
.row-timer {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  font-size: 10px;
  color: var(--text);
  text-shadow: 0 1px 2px #000;
  pointer-events: none;
}

/* Too fast to watch: the bar stops sweeping and just glows, so the row
   reads as a solid stream instead of a strobe light. */
.row.instant .row-bar .bar-fill {
  background: linear-gradient(90deg, var(--lime-dk), var(--lime), var(--lime-dk));
  background-size: 200% 100%;
  animation: stream 1.1s linear infinite;
}
.row.instant .row-timer {
  color: #06251c;
  text-shadow: none;
  letter-spacing: 1px;
}
@keyframes stream {
  from { background-position: 0 0 }
  to   { background-position: -200% 0 }
}

/* who is running this pile - the one line that says it is automated */
.row-mgr {
  font-size: 10px;
  font-weight: 600;
  padding: 3px 7px;
  border-radius: 999px;
  border: 2px solid var(--line);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.row-mgr.on  { background: linear-gradient(#2c5f4f, #18382f); color: var(--teal); }
.row-mgr.on b { color: var(--moon); font-weight: 700; }
.row-mgr.off { background: #1a2133; color: var(--muted); }

.buy-btn {
  display: flex; align-items: center; justify-content: space-between;
  gap: 6px;
  padding: 10px 8px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  /* a sheen across the top half, the way a moulded plastic button
     catches the light */
  background:
    linear-gradient(rgba(255,255,255,.35), rgba(255,255,255,0) 52%),
    linear-gradient(var(--lime), var(--lime-dk));
  color: #16290a;
  font: inherit; font-size: 13px;
  text-shadow: 0 1px 0 rgba(255, 255, 255, .25);
  cursor: pointer;
  box-shadow: 0 3px 0 var(--line);
}
.buy-btn:active { transform: translateY(2px); box-shadow: 0 1px 0 var(--line); }
.buy-btn[disabled] {
  background: linear-gradient(#3b4666, #273250);
  color: var(--muted);
  cursor: not-allowed;
}
/* The label is the part that gives way. Without min-width:0 a flex item
   refuses to shrink below its own text, so "BUY x100 K RACCOONS" pushed
   the price clean off the end of the button instead of clipping. */
.buy-label {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.buy-cost {
  flex: 0 0 auto;
  font-size: 11px;
  padding: 2px 6px;
  border-radius: 999px;
  background: rgba(10, 14, 24, .28);
  white-space: nowrap;
}

/* locked row */
.row.locked {
  background: linear-gradient(#1a2032, #141a29);
}
.row.locked .row-tap {
  background: #141a29;
  filter: grayscale(1);
  cursor: default;
}
.lock-body { flex: 1; min-width: 0; display: flex; flex-direction: column; justify-content: center; gap: 5px; }
.lock-title { font-size: 13px; color: var(--muted); }
.lock-req   { font-size: 11px; color: var(--amber); font-weight: 600; }
.lock-body .bar-fill {
  background: linear-gradient(#ffdc92, var(--amber) 45%, var(--amber-dk));
}

/* ----------------------------- MANAGERS ----------------------------- */
.card-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 8px;
}
/* A portrait card: the raccoon fills the frame, the rarity is the
   frame's colour, and the name sits under it whether you own him yet
   or not. */
.card {
  position: relative;
  border-radius: 10px;
  cursor: pointer;
  overflow: hidden;
  line-height: 0;
}
.card svg { display: block; width: 100%; height: auto; }

.card-lock {
  position: absolute; inset: 0;
  display: none;
  place-items: center;
  font-size: 26px;
  background: rgba(8, 12, 22, .45);
}

/* not hired yet: you can see who he is and what he does, but the card
   will not open */
.card.locked { cursor: default; }
/* Only the portrait greys out. The frame and the rarity label keep their
   colour, so you can see which rarity is still missing, and the name stays
   readable through the overlay. */
.card.locked .card-art { filter: grayscale(1) brightness(.62); }
.card.locked .card-lock { display: grid; }

.card.up-ready { animation: card-glow 1.4s infinite; }
@keyframes card-glow {
  0%,100% { box-shadow: 0 4px 0 var(--line); }
  50%     { box-shadow: 0 4px 0 var(--line), 0 0 14px var(--lime); }
}

/* ------------------------------ DEN --------------------------------- */
.den {
  border-radius: var(--r);
  border: 3px solid var(--line);
  background: linear-gradient(#26364f, #17203a);
  padding: 10px;
  box-shadow: 0 5px 0 var(--line);
}
.den-art {
  min-height: 96px;
  display: flex; flex-wrap: wrap; align-content: center; justify-content: center;
  gap: 2px;
  font-size: 22px;
  line-height: 1;
}
.den-caption { margin-top: 6px; text-align: center; font-size: 11px; font-weight: 600; color: var(--muted); }

.mile {
  display: flex; align-items: center; gap: 8px;
  padding: 8px;
  margin-bottom: 8px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  background: linear-gradient(var(--panel-2), var(--panel));
}
.mile.done { background: linear-gradient(#25493c, #16302a); }
.mile-ico { font-size: 20px; }
.mile-body { flex: 1; min-width: 0; }
.mile-title { font-size: 12px; margin-bottom: 4px; }
.mile-sub { font-size: 11px; color: var(--muted); font-weight: 600; }

.trade {
  display: flex; align-items: center; gap: 8px;
  padding: 8px;
  margin-bottom: 8px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  background: linear-gradient(var(--panel-2), var(--panel));
  box-shadow: 0 4px 0 var(--line);
}
.trade-ico { font-size: 24px; flex: 0 0 34px; text-align: center; }
.trade-body { flex: 1; min-width: 0; }
.trade-title { font-size: 12px; }
.trade-gain { font-size: 11px; color: var(--teal); font-weight: 600; }
.trade-btn {
  flex: 0 0 auto;
  padding: 8px 10px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  background: linear-gradient(var(--amber), var(--amber-dk));
  color: #2b1c00;
  font: inherit; font-size: 11px;
  cursor: pointer;
  box-shadow: 0 3px 0 var(--line);
  text-align: center;
  line-height: 1.3;
}
.trade-btn[disabled] {
  background: linear-gradient(#3b4666, #273250);
  color: var(--muted);
  cursor: not-allowed;
}
/* the next step is within reach - say so loudly, it is easy to miss */
.trade.ready {
  border-color: var(--amber);
  background: linear-gradient(#4a3c1c, #2a2413);
  animation: trade-glow 1.6s infinite;
}
@keyframes trade-glow {
  0%, 100% { box-shadow: 0 4px 0 var(--line); }
  50%      { box-shadow: 0 4px 0 var(--line), 0 0 16px rgba(255, 194, 71, .55); }
}
.trade-lvl { font-size: 10px; color: var(--muted); font-weight: 600; }

/* ------------------------------- NAV -------------------------------- */
#nav {
  display: flex;
  border-top: 3px solid var(--line);
  background: linear-gradient(#232d45, #161d2e);
}
.nav-btn {
  position: relative;
  flex: 1;
  display: flex; flex-direction: column; align-items: center; gap: 2px;
  padding: 7px 2px 9px;
  border: 0;
  border-right: 3px solid var(--line);
  background: transparent;
  color: var(--muted);
  font: inherit;
  cursor: pointer;
}
.nav-btn:last-child { border-right: 0; }
.nav-ico { display: block; width: 24px; height: 24px; color: var(--muted); }
.nav-ico svg { display: block; width: 100%; height: 100%; }
.nav-btn b { font-size: 9px; letter-spacing: .5px; }
.nav-btn.active { background: linear-gradient(#35496e, #1e2941); color: var(--moon); }
.nav-btn.active .nav-ico { color: var(--teal); }
.dot {
  position: absolute; top: 5px; right: 22%;
  width: 10px; height: 10px; border-radius: 50%;
  background: var(--pink); border: 2px solid var(--line);
}

/* ------------------------------- FX --------------------------------- */
#fx { position: fixed; inset: 0; pointer-events: none; z-index: 40; overflow: hidden; }
.float {
  position: absolute;
  font-size: 15px;
  color: var(--lime);
  text-shadow: 0 2px 0 var(--line);
  animation: float-up .9s ease-out forwards;
}
@keyframes float-up {
  0%   { transform: translate(-50%, 0) scale(.8); opacity: 1; }
  100% { transform: translate(-50%, -70px) scale(1.1); opacity: 0; }
}

/* stars are never promised in advance, so they announce themselves */
.star-burst {
  position: absolute;
  left: 50%; top: 32%;
  transform: translate(-50%, -50%);
  padding: 10px 18px;
  border-radius: var(--r);
  border: 3px solid var(--line);
  background: linear-gradient(var(--amber), var(--amber-dk));
  color: #2b1c00;
  font-size: 20px;
  box-shadow: 0 6px 0 var(--line), 0 0 30px rgba(255, 194, 71, .5);
  animation: star-pop 1.4s ease-out forwards;
}
@keyframes star-pop {
  0%   { transform: translate(-50%, -50%) scale(.4); opacity: 0; }
  18%  { transform: translate(-50%, -50%) scale(1.12); opacity: 1; }
  30%  { transform: translate(-50%, -50%) scale(1); }
  75%  { transform: translate(-50%, -50%) scale(1); opacity: 1; }
  100% { transform: translate(-50%, -120%) scale(.9); opacity: 0; }
}

/* ------------------------------ MODAL ------------------------------- */
#modal-root {
  position: fixed; inset: 0; z-index: 50;
  background: rgba(4, 7, 14, .78);
  display: grid; place-items: center;
  padding: 16px;
}
.modal {
  width: 100%;
  max-width: 420px;
  max-height: 86vh;
  overflow-y: auto;
  border-radius: var(--r);
  border: 3px solid var(--line);
  background: linear-gradient(var(--panel-2), var(--panel));
  box-shadow: 0 8px 0 var(--line), 0 0 60px #000;
  padding: 14px;
  text-align: center;
  animation: pop .18s ease-out;
}
@keyframes pop { from { transform: scale(.88); opacity: 0 } to { transform: scale(1); opacity: 1 } }
.modal h2 { font-size: 17px; margin-bottom: 4px; color: var(--moon); }
.modal p  { font-size: 12px; font-weight: 600; color: var(--muted); line-height: 1.5; }
.modal-cards {
  display: flex; flex-wrap: wrap; justify-content: center; gap: 8px;
  margin: 12px 0;
}
.loot {
  width: 86px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  background: linear-gradient(#3e5480, #1f2a42);
  padding: 6px;
  animation: pop .25s ease-out backwards;
}
.loot-art { border-radius: 8px; overflow: hidden; }
.loot-art svg { display: block; width: 100%; height: auto; }
.loot-name { font-size: 9px; margin-top: 3px; }
.loot-qty  { font-size: 11px; color: var(--amber); }
.loot.new  { background: linear-gradient(#3f7d5f, #1c3d2f); }
.loot.rare { border-color: var(--blue); box-shadow: 0 0 14px rgba(74, 168, 255, .55); }
.loot.epic { border-color: var(--purple); box-shadow: 0 0 16px rgba(176, 124, 255, .6); }
.loot-rarity { font-size: 8px; color: var(--muted); letter-spacing: .5px; }
.loot.rare .loot-rarity { color: var(--blue); }
.loot.epic .loot-rarity { color: var(--purple); }

.modal-rarity {
  font-size: 10px; letter-spacing: 1px;
  color: var(--muted);
  margin-bottom: 2px;
}
.modal-rarity.rare { color: var(--blue); }
.modal-rarity.epic { color: var(--purple); }

.loot-new-tag { font-size: 8px; color: var(--lime); }
.loot-stars {
  font-size: 15px; color: var(--amber);
  margin: 2px 0 4px;
}

.modal-portrait { width: 176px; margin: 10px auto; }
.modal-portrait svg { display: block; width: 100%; height: auto; }

/* ---- the pack, and the beat before the loot ---- */
.pack-stage {
  width: 104px; margin: 14px auto 6px;
}
.pack-stage svg { display: block; width: 100%; height: auto; overflow: visible; }

/* The glow has to be off everywhere, not just here, because the task
   strip renders the same SVG with no .pack-stage around it. */
.pack-glow { opacity: 0; }

/* Sealed -> torn, in one beat: the foil lifts off the tear line, turns
   as it goes, and fades; the body is already ragged underneath because
   both halves are cut from the same zigzag.

   This replaced a treasure chest that took four attempts and never
   worked. A box has to show its INSIDE to look open, which needs
   perspective, and the browser flattens real 3D on SVG groups. A pack
   has no inside - it only tears, and a tear is a translate and a rotate
   in the plane of the screen. Nothing here can go wrong the way the lid
   did. */
.pack-stage .pack-top { transform-origin: 28px 26px; }
.pack-stage.open .pack-top {
  transform: translate(-7px, -30px) rotate(-17deg);
  opacity: 0;
  transition: transform .42s cubic-bezier(.3, 1.2, .5, 1),
              opacity .3s linear .12s;
}

/* the body takes the tug - without it the foil moves and the pack just
   sits there, which reads as an image swap rather than something opening */
.pack-stage .pack-body { transform-origin: 28px 77px; }
.pack-stage.open .pack-body { animation: pack-jolt .42s cubic-bezier(.3, 1.4, .6, 1); }
@keyframes pack-jolt {
  0%   { transform: translateY(0)   scaleY(1); }
  28%  { transform: translateY(2px) scaleY(.94); }
  62%  { transform: translateY(0)   scaleY(1.03); }
  100% { transform: translateY(0)   scaleY(1); }
}

/* blurred, or the flat circle reads as a disc behind the pack */
.pack-stage .pack-glow { filter: blur(9px); transition: opacity .4s; }
.pack-stage.open .pack-glow { opacity: 1; animation: pack-pulse 1.4s ease-out infinite; }
@keyframes pack-pulse {
  0%, 100% { opacity: .5; transform: scale(1); }
  50%      { opacity: 1;  transform: scale(1.12); }
}

/* everything under the pack waits for the foil */
.pending { opacity: 0; pointer-events: none; }
.modal-cards, .loot-stars, .modal .btn { transition: opacity .3s; }
.stat-line {
  display: flex; justify-content: space-between;
  font-size: 12px; padding: 6px 0;
  border-bottom: 2px solid #0e1425;
}
.stat-line b { color: var(--teal); }

.btn {
  display: block; width: 100%;
  margin-top: 12px;
  padding: 11px;
  border-radius: var(--r-s);
  border: 3px solid var(--line);
  background: linear-gradient(var(--lime), var(--lime-dk));
  color: #16290a;
  font: inherit; font-size: 14px;
  cursor: pointer;
  box-shadow: 0 4px 0 var(--line);
}
.btn:active { transform: translateY(2px); box-shadow: 0 2px 0 var(--line); }
.btn[disabled] {
  background: linear-gradient(#3b4666, #273250);
  color: var(--muted); cursor: not-allowed;
}
.btn-ghost {
  background: linear-gradient(#36436a, #222c46);
  color: var(--text);
}

/* Cheat buttons. Deliberately ugly so nobody mistakes them for the game. */
.dev-panel {
  margin-top: 14px;
  padding: 8px;
  border: 3px dashed var(--pink);
  border-radius: var(--r-s);
  background: rgba(255, 107, 157, .07);
}
.dev-title {
  font-size: 10px;
  letter-spacing: 2px;
  color: var(--pink);
  margin-bottom: 6px;
}
.dev-btn {
  margin-top: 6px;
  padding: 8px;
  font-size: 11px;
  background: linear-gradient(#6a3a52, #3d1e2d);
  color: #ffd9e6;
  box-shadow: 0 3px 0 var(--line);
}
.dev-btn:first-of-type { margin-top: 0; }
