/* ============================================================
   Tin Mil mini-app

   Warm paper and a teal brand — a partner surface again, owing nothing to the
   wallet's yellow or the bank's red. Like the other two games the whole screen
   is one fixed, non-scrolling board: a puzzle that scrolls under the thumb
   loses the tap that was meant for a tile.
   ============================================================ */
:root {
  --tm-page: #F6F2E9;
  --tm-brand: #168A80;
  --tm-brand-dark: #0E635C;
  --tm-ink: #3F4A47;
  --tm-ink-soft: #8A938F;
  --tm-tile: #FFFDF8;
  --tm-tile-edge: #D9D0BE;
  --tm-felt: #E7E0D2;
}

.tm-app {
  position: relative;
  display: flex;
  flex-direction: column;
  flex: 1;
  min-height: 100%;
  overflow: hidden;
  background: var(--tm-page);
  color: var(--tm-ink);
  user-select: none;
  -webkit-user-select: none;
}
.tm-app:focus { outline: none; }

/* Same rule, same reason as the other two games: an author `display`
   declaration silently beats the browser's own `[hidden] { display: none }`,
   and an overlay that ships that way covers the board and eats every tap. */
.tm-app [hidden] { display: none !important; }

/* The cover carries its own Play button, so nothing live sits behind it. */
.tm-app.on-cover .tm-hud,
.tm-app.on-cover .tm-tray,
.tm-app.on-cover .tm-props { display: none; }

/* ---------- host chrome ---------- */
/* Above every overlay on purpose: whatever the mini-app puts on screen, the
   way out stays tappable. */
.tm-top {
  position: relative;
  z-index: 7;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 10px 12px 4px;
  flex-shrink: 0;
}
.tm-brand { display: inline-flex; align-items: center; gap: 8px; min-width: 0; }
.tm-brand img { width: 26px; height: 26px; border-radius: 8px; display: block; }
.tm-brand span { font-size: 14px; font-weight: 700; }

.tm-capsule {
  display: inline-flex;
  align-items: center;
  height: 30px;
  padding: 0 3px;
  border-radius: 999px;
  background: rgba(63, 74, 71, 0.08);
  border: 1px solid rgba(63, 74, 71, 0.14);
}
.tm-capsule-btn {
  display: inline-grid;
  place-items: center;
  width: 30px;
  height: 28px;
  border: 0;
  background: none;
  color: var(--tm-ink);
  cursor: pointer;
}
.tm-capsule-split { width: 1px; height: 14px; background: rgba(63, 74, 71, 0.22); }

/* ---------- HUD ---------- */
.tm-hud {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 4px 14px 8px;
  flex-shrink: 0;
}
.tm-chip {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  height: 26px;
  padding: 0 11px;
  border-radius: 999px;
  background: rgba(22, 138, 128, 0.12);
  color: var(--tm-brand-dark);
  font-size: 12px;
  font-weight: 700;
}
.tm-clock { margin-left: auto; font-variant-numeric: tabular-nums; }

/* ---------- board ---------- */
.tm-stage {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 12px;
  min-height: 0;
}
/* z-index here is load-bearing, not decoration. Tiles carry an inline
   z-index derived from their layer (up to 42), and `position: relative` alone
   does NOT open a stacking context — so without this the tiles compete with
   the whole screen and render on top of the end cards, which sit at 6. The
   lost card shipped that way once: it was "visible" to any DOM check while
   being completely buried under the board. */
.tm-grid {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: 360px;
  aspect-ratio: 1 / 1;
  border-radius: 14px;
  background: var(--tm-felt);
  box-shadow: inset 0 0 0 1px rgba(63, 74, 71, 0.07);
  /* The container the emoji size against, so a face keeps its proportion to
     its tile on any phone without a resize listener. */
  container-type: inline-size;
}
.tm-tiles { position: absolute; inset: 4%; }

/* Positioned with left/top percentages, set inline. Percentage translate would
   resolve against the tile's own box rather than the board — the bug that once
   stopped Tape Ball's ball from moving at all. */
.tm-tile {
  position: absolute;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid var(--tm-tile-edge);
  border-radius: 9px;
  background: var(--tm-tile);
  box-shadow: 0 1px 2px rgba(63, 74, 71, 0.16);
  cursor: pointer;
  touch-action: manipulation;
  transition: transform 0.12s ease, opacity 0.12s ease;
}
/* Noto Color Emoji is pinned in index.html. The system fallbacks are listed
   after it only so a failed font load degrades to the platform's own emoji
   rather than to tofu. */
.tm-face {
  font-family: 'Noto Color Emoji', 'Apple Color Emoji', 'Segoe UI Emoji', sans-serif;
  line-height: 1;
  pointer-events: none;
  user-select: none;
}
.tm-tile .tm-face {
  font-size: 30px;
  font-size: 10cqw;
}

/* A covered tile is not merely un-clickable, it has to LOOK un-clickable, or
   the player taps it repeatedly and concludes the game is broken. */
.tm-tile.blocked {
  cursor: default;
  filter: brightness(0.74) saturate(0.55);
}
.tm-tile.blocked img { opacity: 0.85; }

.tm-tile.taken {
  transform: scale(0.72);
  opacity: 0;
  pointer-events: none;
}
@media (prefers-reduced-motion: reduce) {
  .tm-tile { transition: none; }
}

/* ---------- tray ---------- */
.tm-tray {
  display: flex;
  justify-content: center;
  gap: 5px;
  padding: 10px 12px 4px;
  flex-shrink: 0;
}
.tm-slot {
  display: grid;
  place-items: center;
  width: 40px;
  height: 44px;
  border-radius: 9px;
  border: 1px dashed rgba(63, 74, 71, 0.26);
  background: rgba(63, 74, 71, 0.04);
}
.tm-slot {
  /* Survivors slide into their new place after a match rather than snapping
     left; the offset is set by the FLIP pass in paintTray. */
  transition: transform 0.22s ease;
}
.tm-slot.filled {
  border-style: solid;
  border-color: var(--tm-tile-edge);
  background: var(--tm-tile);
  box-shadow: 0 1px 2px rgba(63, 74, 71, 0.14);
}
.tm-slot .tm-face { font-size: 24px; }

/* Claimed, but its tile is still travelling. The space is held so nothing
   else lands in it, and the face appears only on arrival. */
.tm-slot.reserved {
  border-style: solid;
  border-color: rgba(22, 138, 128, 0.35);
  background: rgba(22, 138, 128, 0.07);
}

/* Three of a kind: swell, then go. The animation runs on copies floating over
   the slots rather than on the slots themselves, so the tray is free for the
   next tap the instant the match is made. */
.tm-ghost.tm-pop {
  border-color: var(--tm-brand);
  background: rgba(22, 138, 128, 0.16);
  box-shadow: 0 2px 10px rgba(22, 138, 128, 0.32);
  animation: tm-pop 0.3s ease forwards;
}
@keyframes tm-pop {
  0% { transform: scale(1); opacity: 1; }
  38% { transform: scale(1.2); opacity: 1; }
  100% { transform: scale(0.35); opacity: 0; }
}

/* The copy that travels from the board to the tray. */
.tm-ghost {
  position: absolute;
  z-index: 6;
  display: grid;
  place-items: center;
  border: 1px solid var(--tm-tile-edge);
  border-radius: 9px;
  background: var(--tm-tile);
  box-shadow: 0 6px 16px rgba(63, 74, 71, 0.28);
  pointer-events: none;
  transform-origin: center;
}
.tm-ghost.go {
  transition: transform 0.28s cubic-bezier(0.34, 0.8, 0.4, 1), box-shadow 0.28s ease;
  box-shadow: 0 1px 3px rgba(63, 74, 71, 0.18);
}

@media (prefers-reduced-motion: reduce) {
  .tm-slot { transition: none; }
  .tm-ghost.go { transition: none; }
  .tm-ghost.tm-pop { animation: none; }
}
/* One slot left is the moment the game is actually decided — say so. */
.tm-tray.danger .tm-slot { border-color: rgba(214, 90, 62, 0.55); }

/* ---------- props ---------- */
.tm-props {
  display: flex;
  justify-content: center;
  gap: 8px;
  padding: 6px 12px 2px;
  flex-shrink: 0;
}
.tm-prop {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  height: 36px;
  padding: 0 14px 0 11px;
  border: 1px solid rgba(22, 138, 128, 0.32);
  border-radius: 999px;
  background: rgba(22, 138, 128, 0.08);
  color: var(--tm-brand-dark);
  font-size: 12px;
  font-weight: 700;
  cursor: pointer;
}
.tm-prop b {
  display: inline-grid;
  place-items: center;
  min-width: 17px;
  height: 17px;
  border-radius: 999px;
  background: var(--tm-brand);
  color: #FFF;
  font-size: 10px;
}
.tm-prop.spent {
  opacity: 0.4;
  cursor: default;
  border-color: rgba(63, 74, 71, 0.2);
  background: rgba(63, 74, 71, 0.05);
  color: var(--tm-ink-soft);
}
.tm-prop.spent b { background: var(--tm-ink-soft); }

/* ---------- foot ---------- */
.tm-foot { flex-shrink: 0; padding: 8px 14px calc(10px + env(safe-area-inset-bottom)); }

/* ---------- cover ---------- */
.tm-cover {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--tm-page);
}
.tm-cover-inner { text-align: center; padding: 0 22px; }
.tm-cover-logo {
  width: 96px;
  height: 96px;
  border-radius: 24px;
  box-shadow: 0 10px 28px rgba(22, 138, 128, 0.3);
}
.tm-cover-title { margin-top: 16px; font-size: 26px; font-weight: 800; }
.tm-cover-tag { margin-top: 6px; font-size: 14px; color: var(--tm-ink-soft); }
.tm-cover-best { margin-top: 10px; font-size: 13px; color: var(--tm-ink-soft); }
.tm-cover-best b { color: var(--tm-ink); font-weight: 800; font-variant-numeric: tabular-nums; }
.tm-start {
  margin-top: 20px;
  height: 46px;
  padding: 0 46px;
  border: 0;
  border-radius: 12px;
  background: var(--tm-brand);
  color: #FFF;
  font-size: 15px;
  font-weight: 700;
  cursor: pointer;
}
.tm-start:active { transform: translateY(1px); }
.tm-cover-links {
  margin-top: 16px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  font-size: 13px;
  color: var(--tm-ink-soft);
}
.tm-cover-links button {
  border: 0;
  background: none;
  color: var(--tm-ink);
  font-size: 13px;
  font-weight: 600;
  text-decoration: underline;
  cursor: pointer;
}

/* ---------- leaderboard ---------- */
.tm-board { display: flex; flex-direction: column; gap: 2px; margin-top: 4px; }
.tm-board-compact { margin: 14px 0 18px; }
.tm-board-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 9px;
  background: rgba(63, 74, 71, 0.05);
  font-size: 14px;
}
.tm-board-row.you {
  background: rgba(22, 138, 128, 0.16);
  border: 1px solid rgba(22, 138, 128, 0.45);
  font-weight: 700;
}
.tm-board-rank { width: 22px; color: var(--tm-ink-soft); font-weight: 700; }
.tm-board-name { flex: 1; min-width: 0; }
.tm-board-score { font-weight: 800; font-variant-numeric: tabular-nums; }
.tm-board-empty {
  margin-top: 10px;
  font-size: 12px;
  color: var(--tm-ink-soft);
  text-align: center;
}

.tm-sheet-body p { margin: 0 0 10px; font-size: 14px; line-height: 1.55; }
.tm-sheet-hint { color: var(--tm-ink-soft); font-size: 13px; }
.tm-sheet-note {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-top: 12px;
  font-size: 11px;
  color: var(--tm-ink-soft);
}

/* ---------- end cards ---------- */
.tm-card {
  position: absolute;
  inset: 0;
  z-index: 6;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 22px;
  background: rgba(246, 242, 233, 0.94);
  backdrop-filter: blur(3px);
}
.tm-card-inner { width: 100%; max-width: 320px; text-align: center; }
.tm-card-title { font-size: 21px; font-weight: 800; }
.tm-card-label { margin-top: 14px; font-size: 13px; color: var(--tm-ink-soft); }
.tm-card-score {
  font-size: 44px;
  font-weight: 800;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.tm-card-sub { margin-top: 8px; font-size: 12px; color: var(--tm-ink-soft); line-height: 1.5; }
