/* ========================================================================== */
/* MMO Client Styles                                                          */
/* ========================================================================== */

@keyframes td-earn-pop {
  0%   { transform: scale(1); }
  18%  { transform: scale(1.28) rotate(-4deg); }
  38%  { transform: scale(1.14) rotate(3deg); }
  58%  { transform: scale(1.07) rotate(-2deg); }
  78%  { transform: scale(1.03) rotate(1deg); }
  100% { transform: scale(1); }
}

.td-earn-pop {
  animation: td-earn-pop 0.38s cubic-bezier(0.36, 0.07, 0.19, 0.97) both;
}

@keyframes tdSplashPulse {
  0%, 100% { transform: scale(1); opacity: 0.85; }
  50%      { transform: scale(1.06); opacity: 1; }
}

@keyframes tdSpinGallery {
  to { transform: rotate(360deg); }
}

/* ========================================================================== */
/* In-Sector Store, Recovery Panel, And Mobile MMO Overlay                     */
/* ========================================================================== */

.td-mmo-store {
  display:flex;flex-direction:column;gap:10px;
  /* No padding-top: the scroll gutter it created showed cards sliding past
     above the sticky armory bar. The head carries the top inset instead. */
  padding:0 12px 12px;flex:1;overflow-y:auto;
}
.td-mmo-store-head {
  display:flex;align-items:flex-start;justify-content:space-between;gap:10px;
  padding-bottom:8px;border-bottom:1px solid rgba(125,211,252,0.18);
}
.td-mmo-eyebrow {
  color:#67e8f9;letter-spacing:.14em;font-family:'JetBrains Mono',monospace;
  font-size:.62rem;font-weight:800;text-transform:uppercase;
}
.td-mmo-head-title { color:#f8fafc;font-size:.96rem;font-weight:800;letter-spacing:-.01em;margin-top:2px; }
.td-mmo-head-coins {
  color:#fde68a;font-family:'JetBrains Mono',monospace;font-size:.74rem;
  background:rgba(251,191,36,0.08);border:1px solid rgba(251,191,36,0.32);
  border-radius:999px;padding:3px 9px;flex-shrink:0;
}
.td-mmo-ai-card {
  display:grid;grid-template-columns:14px 1fr auto;gap:10px;align-items:center;
  flex-shrink:0; /* last item in the flex-column grid — don't squish when capped */
  text-align:left;border:1px solid rgba(244,114,182,0.46);border-radius:14px;padding:6px 10px;
  color:#fce7f3;cursor:pointer;opacity:1;
  transition:transform .15s,box-shadow .15s,border-color .15s;
  background:
    radial-gradient(circle at top left,rgba(236,72,153,0.30),transparent 45%),
    linear-gradient(135deg,rgba(88,28,135,0.55),rgba(15,23,42,0.82));
  box-shadow:inset 0 0 0 1px rgba(255,255,255,0.05);
}
.td-mmo-ai-card:hover {
  transform:translateY(-1px);border-color:rgba(244,114,182,0.85);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,0.10),0 4px 20px rgba(236,72,153,0.30);
}
.td-mmo-ai-card:active { transform:translateY(0); }
.td-mmo-ai-glow {
  width:14px;height:24px;border-radius:999px;
  background:linear-gradient(180deg,#f9a8d4,#a855f7);
  box-shadow:0 0 16px rgba(236,72,153,0.50);
}
.td-mmo-ai-card strong { display:block;color:#fff1f2;font-size:.78rem;line-height:1.2; }
.td-mmo-ai-card small  { display:block;color:#fbcfe8;font-size:.62rem;line-height:1.2;margin-top:1px; }
.td-mmo-ai-badge       { color:#fdf2f8;font:900 .68rem/1 'JetBrains Mono',monospace;letter-spacing:.06em;white-space:nowrap; }
.td-mmo-section-title {
  display:flex;align-items:baseline;justify-content:space-between;
  color:#e2e8f0;font-weight:800;font-size:.74rem;letter-spacing:.05em;
  text-transform:uppercase;margin:4px 0 -2px;
}
.td-mmo-section-title small {
  color:#94a3b8;font:600 .62rem/1 'JetBrains Mono',monospace;text-transform:none;letter-spacing:.04em;
}
.td-mmo-store-grid { display:flex;flex-direction:column;gap:7px; }
.td-mmo-store-card {
  /* flex-shrink:0 — the grid is a flex column, and when it's height-capped on
     mobile (_capStoreGridMobile) the default shrink squished taller cards and
     clipped their stat tags. Keep every card at its natural height and let the
     grid scroll instead. */
  position:relative;display:flex;flex-direction:column;gap:4px;flex-shrink:0;
  text-align:left;border:1px solid rgba(148,163,184,0.22);border-radius:13px;
  padding:9px 10px;color:#e2e8f0;cursor:pointer;background:rgba(15,23,42,0.72);
  transition:border-color .14s,background .14s,transform .12s;
}
.td-mmo-store-card::before {
  content:'';position:absolute;left:0;top:14px;bottom:14px;width:3px;border-radius:0 3px 3px 0;
  background:var(--td-card-accent,#67e8f9);box-shadow:0 0 12px var(--td-card-accent,#67e8f9);
}
.td-mmo-store-card:hover:not(.locked),
.td-mmo-store-card.active {
  border-color:rgba(103,232,249,0.68);
  background:rgba(14,116,144,0.22);
}
.td-mmo-store-card.active { transform:translateY(-1px); }
.td-mmo-store-card.locked { opacity:.45;cursor:not-allowed; }
.td-mmo-store-card.unaffordable {
  border-color:rgba(248,113,113,0.55);
  background:linear-gradient(135deg,rgba(127,29,29,0.34),rgba(15,23,42,0.72));
}
.td-mmo-card-top {
  display:flex;align-items:baseline;justify-content:space-between;gap:8px;
}
.td-mmo-card-name {
  color:var(--td-card-accent,#f8fafc);font-family:'JetBrains Mono',monospace;
  font-weight:800;font-size:.78rem;letter-spacing:.02em;
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:65%;
  margin-right:auto; /* keeps cost pinned right when the hotkey badge is present */
}
.td-mmo-card-key {
  color:#94a3b8;font-family:'JetBrains Mono',monospace;font-size:.58rem;font-weight:700;
  background:rgba(255,255,255,0.05);border:1px solid rgba(148,163,184,0.30);
  border-bottom-width:2px;border-radius:4px;padding:1px 5px;flex-shrink:0;
  align-self:center;line-height:1.2;
}
.td-mmo-store-card.active .td-mmo-card-key {
  color:#cffafe;border-color:rgba(103,232,249,0.55);
}
.td-mmo-card-cost {
  color:#fde68a;font-family:'JetBrains Mono',monospace;font-size:.72rem;font-weight:700;
  background:rgba(251,191,36,0.08);border-radius:999px;padding:2px 7px;flex-shrink:0;
}
.td-mmo-card-cost.bad { color:#fecaca;background:rgba(239,68,68,0.18);border:1px solid rgba(248,113,113,0.38); }
.td-mmo-card-desc { color:#94a3b8;font-size:.66rem;line-height:1.4; }
.td-mmo-card-tags { display:flex;flex-wrap:wrap;gap:4px;margin-top:2px; }
.td-mmo-card-tag {
  color:#cbd5e1;font-family:'JetBrains Mono',monospace;font-size:.58rem;
  background:rgba(255,255,255,0.05);border:1px solid rgba(148,163,184,0.18);
  border-radius:999px;padding:1px 6px;letter-spacing:.04em;
}
.td-mmo-card-tag.special { color:#a7f3d0;border-color:rgba(34,197,94,0.32); }
.td-mmo-detail {
  border:1px solid rgba(34,197,94,0.40);border-radius:14px;padding:11px;
  background:linear-gradient(165deg,rgba(14,116,144,0.18),rgba(7,10,20,0.86));
  display:flex;flex-direction:column;gap:9px;
  animation:tdMmoDetailIn .16s ease-out;
}
@keyframes tdMmoDetailIn {
  from { opacity:0;transform:translateY(-4px); }
  to   { opacity:1;transform:translateY(0); }
}
/* Suppress the entrance animation when the same Tower Stats card is merely
   rebuilt (panel churn) rather than freshly opened — stops the ~1.5s flicker. */
.td-mmo-detail.no-anim { animation:none; }
/* Loop-swap reveal: the armory list is fully rebuilt when the player flips
   between Loop 1/2/3, and the scroll position is reapplied a frame later. This
   brief blur-in on the fresh grid masks that reposition so the swap reads as a
   deliberate dissolve instead of a flicker. */
@keyframes tdLoopSwap {
  0%   { opacity:0;filter:blur(7px);transform:translateY(5px); }
  100% { opacity:1;filter:blur(0);transform:translateY(0); }
}
.td-mmo-store-grid.loop-swap { animation:tdLoopSwap .24s ease-out; }
.td-mmo-detail-head { display:flex;align-items:flex-start;justify-content:space-between;gap:8px; }
.td-mmo-detail-name { color:#f8fafc;font-size:.92rem;font-weight:800; }
.td-mmo-detail-flavor { color:#94a3b8;font-size:.64rem;line-height:1.4;margin-top:2px; }
.td-mmo-detail-cost { color:#a7f3d0;font-family:'JetBrains Mono',monospace;font-size:.86rem;font-weight:800;text-align:right; }
.td-mmo-detail-cost.bad { color:#fca5a5; }
.td-mmo-stat-grid {
  display:grid;grid-template-columns:auto 1fr;gap:4px 12px;font-size:.72rem;
}
.td-mmo-stat-grid dt { color:#94a3b8;font-family:'JetBrains Mono',monospace;font-size:.66rem;letter-spacing:.04em;text-transform:uppercase; }
.td-mmo-stat-grid dd { margin:0;color:#f8fafc;font-family:'JetBrains Mono',monospace;text-align:right;font-size:.72rem; }
.td-mmo-ranks {
  display:grid;grid-template-columns:1fr 1fr;gap:7px;
}
.td-mmo-rank {
  display:grid;grid-template-columns:1fr auto;grid-template-areas:"label value" "slider slider";
  gap:3px 8px;align-items:center;border:1px solid rgba(255,255,255,0.08);border-radius:11px;
  padding:6px 8px 7px;background:linear-gradient(135deg,rgba(2,6,23,0.42),rgba(15,23,42,0.28));
}
.td-mmo-rank-label { grid-area:label;color:#d1fae5;font:900 .56rem/1 'JetBrains Mono',monospace;letter-spacing:.04em;text-transform:uppercase; }
.td-mmo-rank-val   { grid-area:value;color:#fde68a;font:900 .60rem/1 'JetBrains Mono',monospace;text-align:right; }
.td-mmo-rank input[type=range] {
  grid-area:slider;width:100%;height:16px;accent-color:#67e8f9;
  -webkit-appearance:none;appearance:none;background:transparent;
}
.td-mmo-rank input[type=range]::-webkit-slider-runnable-track {
  height:5px;border-radius:999px;
  background:linear-gradient(90deg,rgba(103,232,249,.75),rgba(34,197,94,.62));
  box-shadow:inset 0 0 0 1px rgba(255,255,255,0.08);
}
.td-mmo-rank input[type=range]::-webkit-slider-thumb {
  -webkit-appearance:none;appearance:none;width:14px;height:14px;margin-top:-5px;border-radius:50%;
  border:2px solid #ecfeff;background:#22d3ee;box-shadow:0 2px 8px rgba(103,232,249,.40);
}
.td-mmo-rank input[type=range]::-moz-range-track {
  height:5px;border-radius:999px;background:linear-gradient(90deg,rgba(103,232,249,.75),rgba(34,197,94,.62));
}
.td-mmo-rank input[type=range]::-moz-range-thumb {
  width:14px;height:14px;border-radius:50%;border:2px solid #ecfeff;background:#22d3ee;
}
.td-mmo-rank-actions { display:grid;grid-template-columns:1fr 1fr;gap:6px; }
.td-mmo-mini-btn {
  border:1px solid rgba(248,250,252,0.18);background:rgba(15,23,42,0.86);color:#f8fafc;
  border-radius:10px;padding:7px 9px;cursor:pointer;font:800 .66rem/1 'JetBrains Mono',monospace;letter-spacing:.04em;
}
.td-mmo-mini-btn:hover { border-color:rgba(103,232,249,0.6);background:rgba(14,116,144,0.30); }
.td-mmo-mini-btn.max {
  border-color:rgba(251,191,36,0.42);color:#fef3c7;
  background:linear-gradient(135deg,rgba(251,191,36,0.18),rgba(14,116,144,0.18));
}
.td-mmo-mini-btn.max:hover { border-color:rgba(251,191,36,0.78); }
.td-mmo-buy-row { display:flex;gap:8px; }
.td-mmo-buy-main {
  flex:1;min-height:42px;border:1px solid rgba(236,253,245,0.34);border-radius:12px;
  background:linear-gradient(135deg,#22c55e,#0891b2);color:#04111d;cursor:pointer;
  font:1000 .82rem/1 'JetBrains Mono',monospace;letter-spacing:.08em;text-transform:uppercase;
  box-shadow:0 0 20px rgba(34,197,94,0.18),inset 0 1px 0 rgba(255,255,255,0.32);
}
.td-mmo-buy-main:hover:not(:disabled) { transform:translateY(-1px);filter:brightness(1.08); }
.td-mmo-buy-main:disabled {
  cursor:not-allowed;color:#fee2e2;
  background:linear-gradient(135deg,rgba(127,29,29,.95),rgba(51,65,85,.95));
  box-shadow:none;opacity:.85;
}
.td-mmo-cancel {
  min-height:42px;padding:0 14px;border:1px solid rgba(248,113,113,0.55);
  color:#fee2e2;background:linear-gradient(135deg,rgba(127,29,29,.9),rgba(239,68,68,.72));
  border-radius:12px;cursor:pointer;
  font:900 .74rem/1 'JetBrains Mono',monospace;letter-spacing:.08em;text-transform:uppercase;
}
.td-mmo-store-foot {
  color:#94a3b8;font-size:.62rem;line-height:1.45;
  border-top:1px solid rgba(148,163,184,0.10);padding-top:8px;
}
/* Recovery / comeback panel */
.td-mmo-recover {
  border:1px solid rgba(248,113,113,0.42);border-radius:14px;padding:11px;
  background:radial-gradient(circle at top right,rgba(248,113,113,0.18),transparent 50%),
             linear-gradient(165deg,rgba(127,29,29,0.30),rgba(7,10,20,0.85));
  display:flex;flex-direction:column;gap:9px;
}
.td-mmo-recover h4 { margin:0;color:#fecaca;font-size:.96rem;font-weight:800; }
.td-mmo-recover p  { margin:0;color:#fda4af;font-size:.7rem;line-height:1.45; }
.td-mmo-comeback-bar {
  display:flex;flex-direction:column;gap:5px;
  padding:9px;border:1px solid rgba(167,243,208,0.22);border-radius:11px;
  background:rgba(2,6,23,0.42);
}
.td-mmo-comeback-bar header {
  display:flex;justify-content:space-between;align-items:baseline;
  color:#a7f3d0;font:800 .60rem/1 'JetBrains Mono',monospace;letter-spacing:.08em;text-transform:uppercase;
}
.td-mmo-comeback-bar header b { color:#fde68a;font-size:.72rem; }
.td-mmo-comeback-track {
  height:7px;border-radius:999px;background:rgba(15,23,42,0.78);overflow:hidden;
  border:1px solid rgba(148,163,184,0.18);
}
.td-mmo-comeback-fill {
  height:100%;background:linear-gradient(90deg,#22c55e,#67e8f9);
  box-shadow:0 0 12px rgba(34,197,94,0.42);transition:width .35s ease;
}
.td-mmo-reclaim-btn {
  width:100%;min-height:46px;border:1px solid rgba(103,232,249,0.6);border-radius:13px;
  background:linear-gradient(135deg,#22c55e,#0891b2);color:#04111d;cursor:pointer;
  font:1000 .82rem/1 'JetBrains Mono',monospace;letter-spacing:.10em;text-transform:uppercase;
  box-shadow:0 0 22px rgba(34,197,94,0.25),inset 0 1px 0 rgba(255,255,255,0.32);
}
.td-mmo-reclaim-btn:hover:not(:disabled) { transform:translateY(-1px);filter:brightness(1.10); }
.td-mmo-reclaim-btn:disabled {
  cursor:not-allowed;color:#fee2e2;
  background:linear-gradient(135deg,rgba(127,29,29,.85),rgba(51,65,85,.85));
  box-shadow:none;opacity:.85;
}
.td-mmo-dev-revive {
  width:100%;padding:7px 10px;border:1px dashed rgba(176,96,255,0.55);border-radius:10px;
  background:rgba(176,96,255,0.10);color:#ddd6fe;cursor:pointer;
  font:800 .66rem/1 'JetBrains Mono',monospace;letter-spacing:.08em;text-transform:uppercase;
}
.td-mmo-dev-revive:hover { background:rgba(176,96,255,0.20);border-style:solid; }
#tdWorldOverlay,
#tdWorldOverlay * {
  -webkit-text-size-adjust:100%;
  text-size-adjust:100%;
  -webkit-user-select:none;
  user-select:none;
  -webkit-touch-callout:none;
}
#tdWorldOverlay input,
#tdWorldOverlay textarea,
#tdWorldOverlay select,
#tdWorldOverlay [contenteditable="true"] {
  -webkit-user-select:text;
  user-select:text;
  -webkit-touch-callout:default;
}
/* World tracker hover — styled via CSS :hover (not JS mouseenter) so the
   glow stays steady when the per-tick re-render rebuilds the card nodes
   under the cursor. Accent colors arrive as inline custom properties;
   !important is needed to beat the inline base styles. */
#tdWorldTracker .td-world-tracker-card[role="button"]:hover,
#tdWorldTracker .td-world-tracker-card[role="button"]:focus-visible {
  border-color:var(--td-glow, rgba(56,212,184,0.9))!important;
  background:rgba(12,17,28,0.92)!important;
  box-shadow:0 0 12px -3px var(--td-glow, rgba(56,212,184,0.6));
  outline:none;
}
#tdWorldTracker .td-world-tracker-head:hover,
#tdWorldTracker .td-world-tracker-head:focus-visible {
  border-color:var(--td-hover-border, rgba(125,211,252,0.5))!important;
  color:var(--td-hover-color, #e0f2fe)!important;
  outline:none;
}
/* Each tracker card wears a colored accent rail on its left edge, tinted to the
   card's own status color (passed in as --td-accent). It gives the otherwise
   flat slate-on-black cards a spark of identity and improves scannability. */
#tdWorldTracker .td-tracker-accent {
  position:absolute;left:0;top:0;bottom:0;width:3px;
  border-radius:5px 0 0 5px;
  background:var(--td-accent, #38d4b8);
  box-shadow:0 0 6px -1px var(--td-accent, #38d4b8);
  pointer-events:none;
}
/* "Hot" cards (a live swarm on the front / enemies on the core) breathe so the
   eye is drawn to them. The card body throbs a soft halo, the rail brightens. */
#tdWorldTracker .td-tracker-hot { animation:tdTrackerCardPulse 1.6s ease-in-out infinite; }
#tdWorldTracker .td-tracker-hot .td-tracker-accent { animation:tdTrackerAccentPulse 1.6s ease-in-out infinite; }
/* Hover/focus is an intentional, steady selection cue. Suspend the ambient
   "hot" breathing animation while that cue is active so the two shadows do not
   fight each other and read as repeated select/deselect flicker. */
#tdWorldTracker .td-tracker-hot[role="button"]:hover,
#tdWorldTracker .td-tracker-hot[role="button"]:focus-visible {
  animation:none;
}
@keyframes tdTrackerCardPulse {
  0%,100% { box-shadow:0 0 0 0 rgba(0,0,0,0); }
  50%     { box-shadow:0 0 16px -5px var(--td-accent, #38d4b8); }
}
@keyframes tdTrackerAccentPulse {
  0%,100% { opacity:0.8; box-shadow:0 0 5px -1px var(--td-accent, #38d4b8); }
  50%     { opacity:1;   box-shadow:0 0 13px 0 var(--td-accent, #38d4b8); }
}
@media (prefers-reduced-motion: reduce) {
  #tdWorldTracker .td-tracker-hot,
  #tdWorldTracker .td-tracker-hot .td-tracker-accent { animation:none; }
}
.td-mobile-panel-handle,
.td-mobile-tracker-toggle,
.td-mobile-placement-bar,
.td-mobile-avatar-controls,
.td-mobile-control-deck,
.td-mobile-sector-editor { display:none; }
#tdWorldOverlay.td-mobile-layout {
  --td-mobile-sheet-peek:66px;
  --td-mobile-sheet-max:min(72dvh,430px);
}
/* Inside a sector the panel is dense — weapons, consumables, tower controls and
   the wave readout all live here — so the short core-map sheet (430px) crammed
   everything into an internal scroll. Let the expanded sheet rise almost
   full-screen in sector view so each option has room; the sheet still sizes to
   its content (height:auto), so sparse panels stay compact and only a loaded
   loadout grows tall. The core map keeps the shorter sheet — it only ever shows
   a sector blurb / claim button. */
#tdWorldOverlay.td-mobile-layout.td-view-sector {
  --td-mobile-sheet-max:calc(100dvh - 56px);
}
#tdWorldOverlay.td-mobile-layout * {
  backdrop-filter: none !important;
  -webkit-backdrop-filter: none !important;
}
#tdWorldOverlay.td-mobile-layout .td-mmo-topbar {
  gap:0.28rem!important;
  padding:calc(env(safe-area-inset-top,0px) + 0.22rem) calc(env(safe-area-inset-right,0px) + 0.6rem) 0.22rem calc(env(safe-area-inset-left,0px) + 0.4rem)!important;
  overflow-x:auto!important;
  overflow-y:hidden!important;
  -ms-overflow-style:none;
  scrollbar-width:none;
}
#tdWorldOverlay.td-mobile-layout .td-mmo-topbar::-webkit-scrollbar { display:none; }
#tdWorldOverlay.td-mobile-layout .td-mmo-title,
#tdWorldOverlay.td-mobile-layout .td-mmo-sep { display:none!important; }
#tdWorldOverlay.td-mobile-layout .td-mmo-topbar button,
#tdWorldOverlay.td-mobile-layout #tdXpDisplay,
#tdWorldOverlay.td-mobile-layout #tdCoinDisplay,
#tdWorldOverlay.td-mobile-layout #tdDevBadge {
  min-height:28px!important;
  padding:0.2rem 0.42rem!important;
  font-size:0.55rem!important;
  border-radius:6px!important;
}
/* Keep the music widget wide enough for both the track selector and mute toggle. */
#tdWorldOverlay.td-mobile-layout #tdMusicMount { max-width:none;overflow:visible;flex-shrink:0; }
#tdWorldOverlay.td-mobile-layout #tdMusicMount [data-td-music-mute] { min-height:28px; }
#tdMusicDrop,
#tdMusicDrop [data-td-music-track-list] {
  scrollbar-width: thin;
  scrollbar-color: rgba(103,232,249,0.34) transparent;
}
#tdMusicDrop::-webkit-scrollbar,
#tdMusicDrop [data-td-music-track-list]::-webkit-scrollbar { width: 7px; }
#tdMusicDrop::-webkit-scrollbar-track,
#tdMusicDrop [data-td-music-track-list]::-webkit-scrollbar-track { background: transparent; }
#tdMusicDrop::-webkit-scrollbar-thumb,
#tdMusicDrop [data-td-music-track-list]::-webkit-scrollbar-thumb {
  background: rgba(103,232,249,0.26);
  border-radius: 999px;
}
#tdMusicDrop::-webkit-scrollbar-thumb:hover,
#tdMusicDrop [data-td-music-track-list]::-webkit-scrollbar-thumb:hover { background: rgba(103,232,249,0.46); }
#tdWorldOverlay.td-mobile-layout #tdCanvasWrap {
  margin-right:0!important;
  touch-action:none;
}
#tdWorldOverlay.td-mobile-layout #tdWorldCanvas { touch-action:none; }
/* Sector view: shift the whole board square UP so its bottom edge clears the bottom
   control deck (the card + comms pills) — there's plenty of spare margin above the
   map to reclaim. THIS SINGLE VALUE is the knob: more negative = board higher. The
   wrap is overflow:hidden so the spare top is simply trimmed (it never spills over
   the top bar). A negative MARGIN is used rather than a transform on purpose: both
   touch aiming (getBoundingClientRect) and the board-space DOM overlays — tower
   popup, trade-menu anchor — read the shift (the latter via canvas.offsetTop, which
   ignores transforms but honours margins), so everything stays aligned. World view
   is excluded (its canvas fills the wrap); landscape gets a small value below. */
#tdWorldOverlay.td-mobile-layout.td-view-sector #tdWorldCanvas {
  margin-top:-104px;
}
#tdWorldOverlay.td-mobile-layout input,
#tdWorldOverlay.td-mobile-layout textarea,
#tdWorldOverlay.td-mobile-layout select {
  font-size:16px!important;
}
#tdWorldOverlay.td-mobile-layout #tdWorldTracker {
  left:0.48rem!important;
  right:0.48rem!important;
  top:2.9rem!important;
  max-width:none!important;
  display:none!important;
  grid-template-columns:repeat(2,minmax(0,1fr))!important;
  gap:0.28rem!important;
  pointer-events:auto!important;
}
#tdWorldOverlay.td-mobile-layout.td-mobile-tracker-open #tdWorldTracker {
  display:grid!important;
}
/* Inside a sector the world-map tracker is irrelevant (it tracks the core/swarm on
   the world map) and is force-hidden on entry. The STATUS toggle here drives the
   sector session dashboard instead, so keep the world tracker suppressed even when
   the tracker-open class is set, or both would stack on top of the sector. */
#tdWorldOverlay.td-mobile-layout.td-view-sector #tdWorldTracker,
#tdWorldOverlay.td-mobile-layout.td-view-sector.td-mobile-tracker-open #tdWorldTracker {
  display:none!important;
}
#tdWorldOverlay.td-mobile-layout #tdWorldTracker > div {
  min-width:0!important;
  padding:0.34rem 0.4rem!important;
  border-radius:6px!important;
}
/* Mobile has its own STATUS toggle: hide the desktop header tab and ignore
   the desktop collapsed state so the 2-col grid always shows every card. */
#tdWorldOverlay.td-mobile-layout #tdWorldTracker .td-world-tracker-head {
  display:none!important;
}
#tdWorldOverlay.td-mobile-layout #tdWorldTracker .td-world-tracker-card {
  display:block!important;
}
#tdWorldOverlay.td-mobile-layout .td-world-tracker-label {
  font-size:0.48rem!important;
  margin-bottom:0.1rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-world-tracker-value {
  font-size:0.64rem!important;
  white-space:normal!important;
  line-height:1.15!important;
}
#tdWorldOverlay.td-mobile-layout .td-world-tracker-card[data-countdown-level="soon"] .td-world-tracker-value {
  font-size:0.76rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-world-tracker-card[data-countdown-level="urgent"] .td-world-tracker-value {
  font-size:0.86rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-world-tracker-card[data-countdown-level="critical"] .td-world-tracker-value {
  font-size:0.96rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-world-tracker-sub {
  font-size:0.5rem!important;
  white-space:normal!important;
  line-height:1.15!important;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-tracker-toggle {
  display:flex;
  position:absolute;
  left:calc(0.48rem + env(safe-area-inset-left,0px));
  top:0.48rem;
  z-index:13;
  align-items:center;
  justify-content:center;
  min-height:34px;
  padding:0 0.72rem;
  border:1px solid rgba(125,211,252,0.38);
  border-radius:9px;
  background:rgba(7,10,20,0.88);
  color:#e0f2fe;
  font:900 0.6rem/1 'JetBrains Mono',monospace;
  letter-spacing:0.08em;
  box-shadow:0 8px 22px rgba(0,0,0,0.32);
  touch-action:manipulation;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-tracker-toggle[hidden] {
  display:none!important;
}
#tdWorldOverlay.td-mobile-layout.td-mobile-tracker-open .td-mobile-tracker-toggle {
  border-color:rgba(56,212,184,0.72);
  color:#ccfbf1;
  background:rgba(6,78,59,0.72);
}
/* ── Sector session dashboard (#td-session-earnings) ──────────────────────────
   Desktop shows the full TODAY / THIS RUN card grid and hides the slim strip. On
   compact mobile the grid collapses behind the same STATUS toggle the world
   tracker uses (.td-mobile-tracker-open); the slim one-line HUD strip — sector
   coord + THIS-RUN earned/spent/slain — stands in by default to keep the sector
   view uncluttered. Tapping STATUS swaps the strip for the full breakdown. */
#td-session-earnings .td-session-slim { display:none; }
#td-session-earnings .td-session-cols { display:flex; }
#tdWorldOverlay.td-mobile-layout #td-session-earnings .td-session-slim {
  display:flex;
  max-width:calc(100vw - 5.4rem);
  overflow:hidden;
}
#tdWorldOverlay.td-mobile-layout #td-session-earnings .td-session-cols { display:none; }
#tdWorldOverlay.td-mobile-layout.td-mobile-tracker-open #td-session-earnings .td-session-slim { display:none; }
#tdWorldOverlay.td-mobile-layout.td-mobile-tracker-open #td-session-earnings .td-session-cols { display:flex; }
/* Sector view: the STATUS toggle that used to reveal the full breakdown is gone,
   so show the full TODAY (day/cycle) + THIS-RUN stats here at ALL times — but lay
   them out as two SHORT horizontal rows (a TODAY row over a THIS-RUN row, each =
   its header followed by EARNED / SPENT / SLAIN side by side) instead of two tall
   columns, so the card stays low and stops eating the top of the small map. */
#tdWorldOverlay.td-mobile-layout.td-view-sector #td-session-earnings .td-session-slim { display:none!important; }
#tdWorldOverlay.td-mobile-layout.td-view-sector #td-session-earnings .td-session-cols {
  display:flex!important;
  flex-direction:column!important;      /* stack the two groups → TODAY row, THIS-RUN row */
  align-items:flex-end!important;
  gap:0.26rem!important;
}
#tdWorldOverlay.td-mobile-layout.td-view-sector #td-session-earnings .td-session-cols > div {
  flex-direction:row!important;         /* each group: header + the three stat cards in a line */
  align-items:center!important;
  gap:0.26rem!important;
}
#tdWorldOverlay.td-mobile-layout.td-view-sector #td-session-earnings .td-session-cols > div > div {
  min-width:0!important;                /* let the little cards hug their short values */
  padding:0.22rem 0.36rem!important;
}
#tdWorldOverlay.td-mobile-layout.td-view-sector #td-session-earnings .td-session-cols > div > div:first-child {
  min-width:3.4rem!important;           /* fixed header column so TODAY / THIS-RUN rows line up */
  padding:0!important;
  white-space:nowrap!important;
  text-align:left!important;
}
/* SECTOR (x, y) now rides in the slim HUD strip on mobile — drop the duplicate in
   the panel header so it no longer peeks at the bottom edge. Desktop keeps it. */
#tdWorldOverlay.td-mobile-layout .td-sector-hdr-coord { display:none!important; }
#tdWorldOverlay.td-mobile-layout #tdChatMount {
  left:0.48rem!important;
  right:0.48rem!important;
  /* Core-map default: sit low, just above the peeking panel handle. The panel
     peek already clears the home-indicator safe area, so we don't add it again
     (doing so floated the pill too high). */
  bottom:calc(var(--td-mobile-sheet-peek) + 0.45rem)!important;
  width:auto!important;
  max-height:34dvh;
}
/* Inside a sector dock the comms cluster (CHAT | ALERTS pills) in the deck's
   top-left, in the slot just ABOVE the analog stick: high enough to clear it so the
   pills stay tappable, low enough to sit inside the control deck. The stick is now
   128px tall on `safe + 0.7rem` padding + `0.6rem` margin (≈149px top), so anchor a
   hair above that. The matching left-shift (to line up with the lifted, inset stick)
   lives in the collapsed-pill rule below; alerts auto-follows chat. Landscape gets
   its own value in the @media block (smaller 104px stick). Single tunable number. */
#tdWorldOverlay.td-mobile-layout.td-view-sector #tdChatMount {
  bottom:calc(env(safe-area-inset-bottom,0px) + 156px)!important;
}
/* No panel occupying the bottom (fully hidden / none) on the core map: there's
   no peek to clear, so drop the comms cluster to the real bottom-left corner
   instead of leaving it floating a sheet-peek up. Sector view is excluded — it has
   its own low resting spot above. */
#tdWorldOverlay.td-mobile-layout.td-mobile-panel-away:not(.td-view-sector) #tdChatMount {
  bottom:calc(env(safe-area-inset-bottom,0px) + 0.5rem)!important;
}
/* "Slide up into place" for the comms cluster when the sector panel closes —
   chat + alerts both get .td-comms-slide-in (added in setMobilePanelExpanded on the
   open→closed transition), so they rise + fade in together as the sheet drops,
   matched to the panel's 0.2s slide. transform/opacity only, so it never disturbs
   the JS-set `bottom` on the alerts; settles at translateY(0) = the resting spot. */
@keyframes tdCommsSlideUp {
  from { transform:translateY(28px); opacity:0; }
  to   { transform:translateY(0);    opacity:1; }
}
#tdWorldOverlay.td-mobile-layout #tdChatMount.td-comms-slide-in,
#tdWorldOverlay.td-mobile-layout #tdAlertsMount.td-comms-slide-in {
  animation:tdCommsSlideUp 0.26s cubic-bezier(0.16, 1, 0.3, 1);
}
/* ── Collapsed chat: compact "CHAT +" pill (desktop + mobile) ──────────────── */
/* Shrink the mount to hug its content instead of the full 360px rectangle. */
#tdChatMount.td-chat-collapsed-state {
  width:auto!important;
  height:auto!important;
}
/* Wrap turns into a single horizontal pill row. */
#tdChatMount.td-chat-collapsed-state > div {
  flex-direction:row!important;
  align-items:center!important;
  cursor:pointer!important;
  border-color:rgba(56,212,184,0.45)!important;
}
/* Header is the pill body; message list + input row are hidden. */
#tdChatMount.td-chat-collapsed-state > div > div:first-child {
  border-bottom:none!important;
  padding:0.34rem 0.55rem!important;
}
#tdChatMount.td-chat-collapsed-state > div > div:not(:first-child) {
  display:none!important;
}
/* Inside the header: hide tabs + online count, reveal the "CHAT" label. */
#tdChatMount.td-chat-collapsed-state .td-chat-tab,
#tdChatMount.td-chat-collapsed-state .td-chat-count {
  display:none!important;
}
#tdChatMount.td-chat-collapsed-state .td-chat-collapsed-label {
  display:inline-block!important;
}
#tdChatMount.td-chat-collapsed-state .td-chat-collapse-btn {
  color:#38d4b8!important;
  font-size:1.05rem!important;
  font-weight:900!important;
  line-height:1!important;
  padding:0.12rem 0.5rem!important;
}
/* Mobile: keep the pill hugging the left edge rather than stretching full-width,
   and give it a larger, finger-friendly tap target with bigger text. */
#tdWorldOverlay.td-mobile-layout #tdChatMount.td-chat-collapsed-state {
  left:0.48rem!important;
  right:auto!important;
  max-height:none!important;
}
/* In-sector: shift the collapsed CHAT|ALERTS pill in off the left edge so it lines
   up with the inset, lifted analog stick beneath it (alerts auto-follows chat).
   Higher specificity than the rule above wins the left without disturbing the core
   map, where the pill keeps hugging the edge. */
#tdWorldOverlay.td-mobile-layout.td-view-sector #tdChatMount.td-chat-collapsed-state {
  left:0.85rem!important;
}
#tdWorldOverlay.td-mobile-layout #tdChatMount.td-chat-collapsed-state > div > div:first-child {
  min-height:38px!important;
  padding:0 0.8rem!important;
  gap:0.45rem!important;
}
#tdWorldOverlay.td-mobile-layout #tdChatMount.td-chat-collapsed-state .td-chat-collapsed-label {
  font-size:0.72rem!important;
}
#tdWorldOverlay.td-mobile-layout #tdChatMount.td-chat-collapsed-state .td-chat-collapse-btn {
  font-size:1.25rem!important;
  padding:0.15rem 0.6rem!important;
}
/* Combined comms bar: on mobile the collapsed ALERTS pill is parked right beside
   the collapsed CHAT pill (see _positionAlertMount). Match its height + rounding to
   the chat pill so the two segments read as one continuous tray bar. Only the
   collapsed pill is a direct <button> child — the expanded box is a div, so it's
   left untouched and floats full-width above chat as before. */
#tdWorldOverlay.td-mobile-layout #tdAlertsMount > button {
  min-height:38px!important;
  padding:0 0.8rem!important;
  border-radius:6px!important;
  font-size:0.62rem!important;
}
#tdWorldOverlay.td-mobile-layout #tdWorldPanel,
#tdWorldOverlay.td-mobile-layout #tdDevPanel {
  left:0!important;
  right:0!important;
  top:auto!important;
  bottom:0!important;
  width:100%!important;
  max-width:none!important;
  height:auto!important;
  max-height:min(var(--td-mobile-sheet-max), calc(100dvh - 76px))!important;
  border-left:0!important;
  border-top:1px solid rgba(125,211,252,0.28)!important;
  border-radius:15px 15px 0 0!important;
  box-shadow:0 -18px 44px rgba(0,0,0,0.46)!important;
  padding-bottom:env(safe-area-inset-bottom,0px)!important;
  transform:translateY(calc(100% - var(--td-mobile-sheet-peek)))!important;
  transition:transform 0.2s ease!important;
}
#tdWorldOverlay.td-mobile-layout #tdWorldPanel.td-sheet-expanded,
#tdWorldOverlay.td-mobile-layout #tdDevPanel.td-sheet-expanded {
  transform:translateY(0)!important;
}
#tdWorldOverlay.td-mobile-layout #tdWorldPanel.td-sheet-hidden,
#tdWorldOverlay.td-mobile-layout #tdDevPanel.td-sheet-hidden {
  transform:translateY(100%)!important;
}
/* Inside a sector, the COLLAPSED panel slides fully off-screen instead of leaving
   a 66px peek. That peek only showed the WORLD MAP button + a panel-top background
   strip, which sat over the bottom of the (small) map and cluttered the controls.
   Now collapsing reclaims that strip for the board and cleans up the bottom; the
   floating OPEN PANEL handle stays put to bring the panel — and WORLD MAP — back.
   Only the EXPANDED state is on-screen here (its own translateY(0) rule wins). */
#tdWorldOverlay.td-mobile-layout.td-view-sector #tdWorldPanel:not(.td-sheet-expanded) {
  transform:translateY(100%)!important;
}
#tdWorldOverlay.td-mobile-layout.td-mobile-panel-over-controls .td-mobile-avatar-controls,
#tdWorldOverlay.td-mobile-layout.td-mobile-panel-over-controls .td-mobile-control-deck,
#tdWorldOverlay.td-mobile-layout.td-mobile-panel-over-controls .td-mobile-placement-bar,
#tdWorldOverlay.td-mobile-layout.td-mobile-panel-over-controls .td-mobile-placement-bar.is-visible,
#tdWorldOverlay.td-mobile-layout.td-mobile-panel-over-controls .td-mobile-sector-editor {
  display:none!important;
  pointer-events:none!important;
}
#tdWorldOverlay.td-mobile-layout .td-sector-panel-header {
  padding:0.55rem 0.72rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-sector-panel-title {
  font-size:0.72rem!important;
  line-height:1.2!important;
}
#tdWorldOverlay.td-mobile-layout .td-sector-panel-body {
  padding:0.55rem 0.72rem calc(env(safe-area-inset-bottom,0px) + 0.65rem)!important;
  gap:0.55rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-sector-panel-meta {
  gap:0.36rem 0.6rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-sector-panel-actions {
  display:grid!important;
  grid-template-columns:repeat(2,minmax(0,1fr))!important;
  gap:0.42rem!important;
  margin-top:0.1rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-sector-panel-actions button {
  width:100%!important;
  min-height:46px;
  padding:0.48rem 0.4rem!important;
  border-radius:7px!important;
  font-size:0.82rem!important;
  line-height:1.18!important;
  white-space:normal;
  overflow-wrap:anywhere;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-panel-handle {
  display:flex;
  position:absolute;
  left:50%;
  bottom:calc(var(--td-mobile-sheet-peek) + env(safe-area-inset-bottom,0px) - 26px);
  z-index:38;
  transform:translateX(-50%);
  align-items:center;
  justify-content:center;
  gap:0.42rem;
  min-width:136px;
  min-height:40px;
  padding:0 0.92rem;
  border:1px solid rgba(125,211,252,0.62);
  border-radius:999px;
  background:linear-gradient(180deg,rgba(15,23,42,0.96),rgba(8,13,26,0.96));
  color:#e0f2fe;
  font:800 0.68rem/1 'JetBrains Mono',monospace;
  letter-spacing:0.08em;
  box-shadow:0 10px 26px rgba(0,0,0,0.42), inset 0 1px 0 rgba(255,255,255,0.14);
  touch-action:manipulation;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-panel-handle::before {
  content:'';
  width:0.54rem;
  height:0.54rem;
  border-left:2px solid currentColor;
  border-top:2px solid currentColor;
  opacity:0.9;
  transform:rotate(225deg) translateY(1px);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-panel-handle[aria-expanded="false"]::before {
  transform:rotate(45deg) translateY(1px);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-panel-handle:active {
  transform:translateX(-50%) translateY(1px);
  filter:brightness(1.12);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-panel-handle[hidden] { display:none!important; }
#tdWorldOverlay.td-mobile-layout.td-mobile-placement-mode .td-mobile-avatar-controls,
#tdWorldOverlay.td-mobile-layout.td-mobile-placement-mode .td-mobile-control-deck,
#tdWorldOverlay.td-mobile-layout.td-mobile-placement-mode .td-mobile-panel-handle {
  display:none!important;
  pointer-events:none!important;
}
#tdWorldOverlay.td-mobile-layout.td-mobile-sector-editing #tdChatMount,
#tdWorldOverlay.td-mobile-layout.td-mobile-sector-editing #tdAlertsMount,
#tdWorldOverlay.td-mobile-layout.td-mobile-sector-editing .td-mobile-avatar-controls,
#tdWorldOverlay.td-mobile-layout.td-mobile-sector-editing .td-mobile-control-deck,
#tdWorldOverlay.td-mobile-layout.td-mobile-sector-editing .td-mobile-placement-bar,
#tdWorldOverlay.td-mobile-layout.td-mobile-sector-editing .td-sector-refit-btn {
  display:none!important;
  pointer-events:none!important;
}
#tdWorldOverlay.td-mobile-layout.td-mobile-sector-editing .td-mobile-panel-handle[aria-expanded="false"] {
  display:none!important;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor {
  display:flex;
  position:absolute;
  left:calc(0.58rem + env(safe-area-inset-left,0px));
  right:calc(0.58rem + env(safe-area-inset-right,0px));
  bottom:calc(0.58rem + env(safe-area-inset-bottom,0px));
  z-index:39;
  flex-direction:column;
  gap:0.38rem;
  max-width:560px;
  margin:0 auto;
  padding:0.48rem;
  border:1px solid rgba(125,211,252,0.44);
  border-radius:15px;
  background:linear-gradient(180deg,rgba(15,23,42,0.96),rgba(7,10,20,0.97));
  box-shadow:0 14px 36px rgba(0,0,0,0.48),inset 0 1px 0 rgba(255,255,255,0.09);
  pointer-events:auto;
  touch-action:manipulation;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor-modes,
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor-actions {
  display:flex;
  gap:0.34rem;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor button {
  min-width:0;
  min-height:42px;
  flex:1 1 0;
  padding:0.32rem 0.28rem;
  border:1px solid rgba(125,211,252,0.3);
  border-radius:10px;
  background:rgba(15,23,42,0.86);
  color:#cbd5e1;
  font:900 0.61rem/1.05 'JetBrains Mono',monospace;
  letter-spacing:0.045em;
  white-space:normal;
  -webkit-user-select:none;
  user-select:none;
  -webkit-touch-callout:none;
  -webkit-tap-highlight-color:transparent;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor button.is-active {
  border-color:rgba(251,191,36,0.78);
  background:rgba(120,83,12,0.72);
  color:#fef3c7;
  box-shadow:inset 0 0 0 1px rgba(251,191,36,0.16);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor button:disabled {
  opacity:0.38;
  filter:saturate(0.45);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor .td-mobile-editor-tools {
  color:#a5f3fc;
  border-color:rgba(103,232,249,0.48);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor .td-mobile-editor-exit,
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor .td-mobile-editor-delete {
  color:#fecaca;
  border-color:rgba(248,113,113,0.48);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor .td-mobile-editor-save {
  color:#ecfdf5;
  border-color:rgba(56,212,184,0.65);
  background:rgba(6,95,70,0.78);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor .td-mobile-editor-save:not(:disabled) {
  box-shadow:0 0 18px rgba(56,212,184,0.18);
}
#tdWorldOverlay.td-mobile-layout .td-sector-editor-panel {
  padding:0.58rem 0.72rem calc(env(safe-area-inset-bottom,0px) + 0.72rem)!important;
  gap:0.46rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-sector-editor-panel .td-sector-editor-help {
  font-size:0.66rem!important;
  line-height:1.45!important;
}
#tdWorldOverlay.td-mobile-layout .td-sector-editor-panel .td-sector-editor-mode-row button,
#tdWorldOverlay.td-mobile-layout .td-sector-editor-panel > button {
  min-height:44px;
}
#tdWorldOverlay.td-mobile-layout .td-sector-editor-palette {
  display:grid!important;
  grid-template-columns:repeat(2,minmax(0,1fr));
  gap:0.38rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-sector-editor-palette button {
  min-height:46px;
  text-align:center!important;
  line-height:1.25;
  white-space:normal;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-actions {
  left:calc(0.72rem + env(safe-area-inset-left,0px))!important;
  right:calc(0.72rem + env(safe-area-inset-right,0px))!important;
  top:auto!important;
  bottom:calc(var(--td-mobile-sheet-peek) + env(safe-area-inset-bottom,0px) + 0.7rem)!important;
  min-width:0!important;
  width:auto!important;
  border-radius:13px!important;
  padding:0.72rem!important;
  z-index:37!important;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-sector-actions button {
  min-height:44px;
  border-radius:9px!important;
  font-size:0.74rem!important;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-placement-bar {
  display:none;
  position:absolute;
  left:calc(0.72rem + env(safe-area-inset-left,0px));
  right:calc(0.72rem + env(safe-area-inset-right,0px));
  bottom:calc(env(safe-area-inset-bottom,0px) + 0.75rem);
  z-index:39;
  width:auto;
  grid-template-columns:minmax(0,0.82fr) minmax(0,1.18fr);
  gap:0.5rem;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-placement-bar.is-visible {
  display:grid;
  align-items:center;
}
/* BACK TO TOWERS — the chain-placement exit. Styled as neutral panel
   navigation (slate/blue, smaller, secondary) rather than a destructive
   red cancel, since backing out never refunds already-placed towers. */
#tdWorldOverlay.td-mobile-layout .td-mobile-placement-cancel {
  width:auto;
  min-height:42px;
  border-radius:12px;
  border:1px solid rgba(125,211,252,0.5);
  background:rgba(30,41,59,0.9);
  color:#dbeafe;
  font:800 0.72rem/1.05 'JetBrains Mono',monospace;
  letter-spacing:0.04em;
  box-shadow:0 8px 22px rgba(0,0,0,0.32);
  touch-action:manipulation;
  padding:0 0.7rem;
  display:flex;
  align-items:center;
  justify-content:center;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-placement-confirm {
  width:auto;
  min-height:42px;
  border-radius:12px;
  border:1px solid rgba(56,212,184,0.62);
  background:rgba(12,94,82,0.88);
  color:#ecfdf5;
  font:900 0.82rem/1 'JetBrains Mono',monospace;
  box-shadow:0 8px 22px rgba(0,0,0,0.32);
  touch-action:manipulation;
  padding:0 0.8rem;
  display:flex;
  align-items:center;
  justify-content:center;
}
/* ── Contained control deck (in-sector, portrait) ──────────────────────────────
   One rounded card that frames the whole bottom control cluster so the movement +
   action controls read as a single clean panel rather than loose floating widgets.
   Purely cosmetic: it sits BELOW every interactive control (chat z10, the
   joystick/buttons z32, the OPEN PANEL handle z38) at z9 and never takes pointer
   events, so it changes nothing about input — it only supplies the frame. Created /
   removed alongside the avatar controls (sector + mobile only), so it never shows on
   the core map. Height is fixed (controls are fixed-size) and anchored to the bottom;
   it reaches up behind the comms + PISTOL row to enclose both rows symmetrically. */
#tdWorldOverlay.td-mobile-layout .td-mobile-control-deck {
  display:block;
  position:absolute;
  left:0.35rem;
  right:0.35rem;
  bottom:calc(env(safe-area-inset-bottom,0px) + 0.3rem);
  height:198px;
  z-index:9;
  pointer-events:none;
  border:1px solid rgba(125,211,252,0.20);
  border-radius:22px;
  background:linear-gradient(180deg,
    rgba(10,16,30,0.32) 0%,
    rgba(8,13,26,0.64) 46%,
    rgba(6,11,22,0.82) 100%);
  /* Keep the card's lift subtle and DOWNWARD — a large upward shadow bled ~40px
     onto the board's bottom edge above it and read as "covering" the map. */
  box-shadow:
    0 2px 14px rgba(0,0,0,0.34),
    inset 0 1px 0 rgba(255,255,255,0.05),
    inset 0 0 30px rgba(40,120,180,0.05);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-avatar-controls {
  display:flex;
  position:absolute;
  inset:auto 0 0 0;
  z-index:32;
  pointer-events:none;
  padding:0 0.72rem calc(env(safe-area-inset-bottom,0px) + 0.7rem);
  justify-content:space-between;
  align-items:flex-end;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-stick,
#tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster,
#tdWorldOverlay.td-mobile-layout .td-mobile-consumable-strip,
#tdWorldOverlay.td-mobile-layout .td-mobile-weapon {
  pointer-events:auto;
  touch-action:none;
}
/* Right-side control column: consumable strip stacked above the action grid.
   The wrapper itself stays click-through so the gap between the two never
   eats a map tap — only the strip + cluster inside it are interactive. */
#tdWorldOverlay.td-mobile-layout .td-mobile-action-stack {
  display:flex;
  flex-direction:column;
  align-items:flex-end;
  gap:0.42rem;
  pointer-events:none;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-consumable-strip {
  display:flex;
  flex-direction:row;
  gap:0.42rem;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-consumable-strip .td-mobile-consumable {
  min-width:52px;
  min-height:42px;
  padding:0 0.4rem;
  border:1px solid rgba(167,139,250,0.5);
  border-radius:12px;
  background:rgba(7,10,20,0.82);
  color:#ddd6fe;
  font:900 0.62rem/1 'JetBrains Mono',monospace;
  letter-spacing:0.03em;
  box-shadow:0 10px 24px rgba(0,0,0,0.34);
  touch-action:manipulation;
}
/* Weapon quick-cycle button — its own slim pill in the action stack, above the
   cluster (so it sits right beside FIRE). Shows the equipped weapon + ammo and
   cycles owned weapons on tap; replaces the in-panel weapon list on mobile. */
#tdWorldOverlay.td-mobile-layout .td-mobile-weapon {
  display:inline-flex;
  align-items:center;
  gap:0.42rem;
  min-height:42px;
  max-width:62vw;
  padding:0 0.7rem;
  border:1px solid rgba(103,232,249,0.5);
  border-radius:12px;
  background:rgba(7,10,20,0.82);
  color:#a5f3fc;
  font:900 0.62rem/1 'JetBrains Mono',monospace;
  letter-spacing:0.04em;
  box-shadow:0 10px 24px rgba(0,0,0,0.34);
  touch-action:manipulation;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-weapon .td-mobile-weapon-cyc {
  font-size:0.95rem;
  line-height:1;
  opacity:0.92;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-weapon .td-mobile-weapon-name {
  overflow:hidden;
  text-overflow:ellipsis;
  white-space:nowrap;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-weapon .td-mobile-weapon-ammo {
  color:#e2e8f0;
  opacity:0.85;
  flex-shrink:0;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-stick {
  width:128px;
  height:128px;
  /* Nudge the stick in off the left edge and up off the bottom so it sits more
     comfortably inside the deck (paired with the lifted chat/alerts above it).
     Sized to clear the centred OPEN PANEL handle on standard/large phones. */
  margin-left:0.3rem;
  margin-bottom:0.6rem;
  border-radius:50%;
  border:1px solid rgba(125,211,252,0.42);
  background:radial-gradient(circle,rgba(56,212,184,0.18),rgba(7,10,20,0.72));
  box-shadow:0 12px 30px rgba(0,0,0,0.38), inset 0 0 0 1px rgba(255,255,255,0.06);
  position:relative;
}
/* Faint inner guide ring — reads as a clean analog "dial" and hints at the knob's
   travel zone, without adding the busy directional chevrons from the old design. */
#tdWorldOverlay.td-mobile-layout .td-mobile-stick::before {
  content:'';
  position:absolute;
  left:50%;
  top:50%;
  width:62%;
  height:62%;
  transform:translate(-50%,-50%);
  border-radius:50%;
  border:1px solid rgba(125,211,252,0.14);
  pointer-events:none;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-stick-knob {
  position:absolute;
  left:50%;
  top:50%;
  width:50px;
  height:50px;
  margin:-25px 0 0 -25px;
  border-radius:50%;
  background:#67e8f9;
  box-shadow:0 0 18px rgba(103,232,249,0.45);
  transform:translate(0,0);
}
/* Stop iOS long-press from selecting/highlighting a button's label text
   and drop the grey tap flash while players hold FIRE/CHARGE/DASH down. */
#tdWorldOverlay.td-mobile-layout button,
#tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster,
#tdWorldOverlay.td-mobile-layout .td-mobile-stick {
  -webkit-user-select:none;
  user-select:none;
  -webkit-touch-callout:none;
  -webkit-tap-highlight-color:transparent;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster {
  display:grid;
  /* FIRE column stays wide/prominent; the DASH·CHARGE column is narrower and the
     gap is tighter so the secondaries cluster in close beside FIRE. */
  grid-template-columns:60px 50px;
  gap:0.32rem;
  justify-content:end;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster button {
  min-height:48px;
  border:1px solid rgba(125,211,252,0.38);
  border-radius:14px;
  background:rgba(7,10,20,0.82);
  color:#e0f2fe;
  font:900 0.62rem/1 'JetBrains Mono',monospace;
  letter-spacing:0.04em;
  box-shadow:0 10px 24px rgba(0,0,0,0.34);
  touch-action:manipulation;
}
#tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster .td-mobile-fire {
  /* Spans the right-hand stack (DASH / CHARGE) — AUTO was removed, so the grid
     now holds exactly these two secondaries and FIRE fills both rows. */
  grid-row:span 2;
  min-height:100px;
  color:#04111d;
  background:linear-gradient(180deg,#67e8f9,#22c55e);
  border-color:rgba(236,253,245,0.72);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster .td-mobile-charge {
  color:#fde68a;
  border-color:rgba(251,191,36,0.58);
}
#tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster .td-mobile-dash {
  color:#bfdbfe;
  border-color:rgba(79,143,255,0.58);
}
#tdWorldOverlay.td-mobile-layout .td-mmo-store {
  padding:0 12px 16px;
}
/* Mobile armory: cap the card grid to 5 cards (height set inline by
   _capStoreGridMobile) and scroll the rest, so OFFENSIVE (10) opens to the same
   sheet height as SUPPORT/DEFENSIVE (5) instead of pushing the sheet taller. */
#tdWorldOverlay.td-mobile-layout .td-mmo-store-grid-capped {
  overscroll-behavior:contain;
  -webkit-overflow-scrolling:touch;
  scrollbar-width:thin;
  scrollbar-color:rgba(103,232,249,0.3) transparent;
}
#tdWorldOverlay.td-mobile-layout .td-mmo-store-grid-capped::-webkit-scrollbar { width:5px; }
#tdWorldOverlay.td-mobile-layout .td-mmo-store-grid-capped::-webkit-scrollbar-thumb {
  background:rgba(103,232,249,0.22);border-radius:999px;
}
#tdWorldOverlay.td-mobile-layout .td-mmo-detail {
  padding:10px 12px 16px;
}
#tdWorldOverlay.td-mobile-layout .td-mmo-store-card,
#tdWorldOverlay.td-mobile-layout .td-mmo-ai-card,
#tdWorldOverlay.td-mobile-layout .td-mmo-buy-main,
#tdWorldOverlay.td-mobile-layout .td-mmo-cancel {
  min-height:44px;
}
@media (orientation:landscape) and (pointer:coarse) {
  #tdWorldOverlay.td-mobile-layout {
    --td-mobile-sheet-peek:54px;
    --td-mobile-sheet-max:min(70dvh,320px);
  }
  #tdWorldOverlay.td-mobile-layout #tdWorldTracker,
  #tdWorldOverlay.td-mobile-layout.td-mobile-tracker-open #tdWorldTracker { display:none!important; }
  #tdWorldOverlay.td-mobile-layout .td-mobile-tracker-toggle { display:none!important; }
  /* The deck card's fixed portrait height would swamp the short landscape board
     (and here the controls hug the left/right margins instead of stacking in two
     rows), so drop the frame in landscape — the controls stay exactly as before. */
  #tdWorldOverlay.td-mobile-layout .td-mobile-control-deck { display:none!important; }
  /* No deck card in landscape, so the big portrait board lift would just clip the
     short landscape board against the top bar — keep only the small nudge here. */
  #tdWorldOverlay.td-mobile-layout.td-view-sector #tdWorldCanvas { margin-top:-10px; }
  #tdWorldOverlay.td-mobile-layout .td-mobile-stick {
    width:104px;
    height:104px;
    margin-left:0;
    margin-bottom:0;
  }
  #tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster {
    grid-template-columns:54px 46px;
    gap:0.3rem;
  }
  #tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster button { min-height:44px; }
  #tdWorldOverlay.td-mobile-layout .td-mobile-action-cluster .td-mobile-fire { min-height:88px; }
  #tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor {
    left:calc(50% + 0.25rem);
    right:calc(0.55rem + env(safe-area-inset-right,0px));
    bottom:calc(0.45rem + env(safe-area-inset-bottom,0px));
    max-width:none;
    margin:0;
    padding:0.4rem;
  }
  #tdWorldOverlay.td-mobile-layout .td-mobile-sector-editor button {
    min-height:38px;
    font-size:0.56rem;
  }

  /* Landscape sector comms fix: the canvas is short and the Dynamic Island / front
     camera sits on the LEFT edge here, so the expanded chat box was running off the
     top and disappearing behind the notch. Inset the cluster past the left safe
     area, sit it just above the smaller landscape joystick, and cap the message
     list so the whole box stays on-screen below the top bar. */
  #tdWorldOverlay.td-mobile-layout.td-view-sector #tdChatMount {
    left:calc(0.48rem + env(safe-area-inset-left,0px))!important;
    bottom:calc(env(safe-area-inset-bottom,0px) + 124px)!important;
  }
  #tdWorldOverlay.td-mobile-layout.td-view-sector #tdChatMount .td-chat-list {
    max-height:26dvh!important;
    min-height:0!important;
  }
  /* Landscape: the COLLAPSED sheet is fully hidden, so the OPEN PANEL handle —
     normally centre-bottom — would float right over the board. Tuck it into the
     bottom-right margin, just left of the FIRE cluster, so it's out of the way.
     Only the collapsed handle moves; expanded (HIDE PANEL) keeps its lifted spot
     above the open sheet (the JS sets its bottom inline, so it isn't matched here).
     The action cluster is ~105px wide on a 0.72rem inset, so clear it by ~112px. */
  #tdWorldOverlay.td-mobile-layout.td-view-sector .td-mobile-panel-handle[aria-expanded="false"] {
    left:auto!important;
    right:calc(env(safe-area-inset-right,0px) + 0.72rem + 112px)!important;
    bottom:calc(env(safe-area-inset-bottom,0px) + 0.7rem)!important;
    transform:none!important;
    min-width:0!important;
    min-height:36px!important;
    padding:0 0.7rem!important;
  }
}

/* Loop selector styling */
.td-mmo-loop-selector {
  display: flex;
  gap: 4px;
  background: rgba(15, 23, 42, 0.6);
  border: 1px solid rgba(148, 163, 184, 0.18);
  border-radius: 999px;
  padding: 2px;
  align-items: center;
}
.td-mmo-loop-btn {
  border: none;
  background: transparent;
  color: #94a3b8;
  font-family: 'JetBrains Mono', monospace;
  font-size: 0.62rem;
  font-weight: 800;
  padding: 4px 8px;
  border-radius: 999px;
  cursor: pointer;
  display: flex;
  align-items: center;
  gap: 3px;
  transition: all 0.15s ease;
  text-transform: uppercase;
  letter-spacing: 0.02em;
}
.td-mmo-loop-btn:hover:not(.locked):not(.active) {
  color: #f8fafc;
  background: rgba(255, 255, 255, 0.05);
}
.td-mmo-loop-btn.active {
  color: #04111d;
  background: linear-gradient(135deg, #67e8f9, #22c55e);
  box-shadow: 0 0 8px rgba(103, 232, 249, 0.3);
}
.td-mmo-loop-btn.locked {
  opacity: 0.45;
  cursor: not-allowed;
  font-size: 0.58rem;
  color: #64748b;
}
.td-mmo-loop-btn.locked .lvl {
  font-size: 0.5rem;
  background: rgba(0, 0, 0, 0.3);
  padding: 1px 4px;
  border-radius: 4px;
  color: #94a3b8;
  margin-left: 2px;
}

/* =====================================================================
   iOS / MOBILE PERFORMANCE + FEEL PASS (additive — no visual redesign)
   ===================================================================== */

/* 1 ▸ Compositor-layer promotion for the chrome that floats above the
   sector/world canvas. The canvas repaints 30-40×/s on phones; keeping
   these surfaces on their own GPU layers means Safari composites them
   instead of re-painting them with every canvas frame. The bottom sheet
   already animates transform, so will-change also keeps its layer warm
   across open/close instead of re-rasterizing at each toggle. */
#tdWorldOverlay .td-mmo-topbar,
#tdWorldOverlay #tdChatMount,
#tdWorldOverlay #tdWorldTracker,
#tdWorldOverlay #tdWorldPanel,
#tdWorldOverlay #tdDevPanel,
#tdWorldOverlay .td-mobile-panel-handle,
#tdWorldOverlay .td-mobile-tracker-toggle,
#tdWorldOverlay .td-mobile-placement-bar,
#tdWorldOverlay .td-mobile-avatar-controls,
#tdWorldOverlay .td-mobile-control-deck {
  will-change: transform;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
}

/* The joystick knob is moved via inline transform every touch frame —
   promote it so the thumb tracking never leaves the compositor. */
#tdWorldOverlay .td-mobile-stick-knob {
  will-change: transform;
}

/* 2 ▸ Press feedback. Hover styles never fire on touch, so taps on the
   action buttons get an immediate springy response instead — pure
   transform/filter, so it stays composite-only. */
@media (pointer: coarse) {
  #tdWorldOverlay .td-mmo-topbar button:active,
  #tdWorldOverlay .td-mobile-sector-actions button:active,
  #tdWorldOverlay .td-sector-panel-actions button:active,
  #tdWorldOverlay .td-mobile-placement-confirm:active,
  #tdWorldOverlay .td-mobile-placement-cancel:active {
    transform: scale(0.96);
    filter: brightness(1.15);
  }
  #tdWorldOverlay .td-mobile-action-cluster button:active,
  #tdWorldOverlay .td-mobile-consumable-strip .td-mobile-consumable:active,
  #tdWorldOverlay .td-mobile-weapon:active {
    transform: scale(0.92);
    filter: brightness(1.2);
  }

  /* Momentum scrolling inside the sheet/store without dragging the page. */
  #tdWorldOverlay #tdWorldPanel,
  #tdWorldOverlay #tdDevPanel,
  #tdWorldOverlay .td-mmo-store {
    overscroll-behavior: contain;
  }
}

/* 3 ▸ Honor system-level reduced motion. */
@media (prefers-reduced-motion: reduce) {
  .td-earn-pop {
    animation: none !important;
  }
  #tdWorldOverlay #tdWorldPanel,
  #tdWorldOverlay #tdDevPanel {
    transition: none !important;
  }
}

/* =========================================================
   PLAYER-TO-PLAYER TRADING
   Floating avatar menu, incoming request prompt, trade window.
========================================================= */

/* Floating context menu above a clicked avatar (fixed where clicked) */
.td-trade-popup {
  position: absolute;
  transform: translate(-50%, -100%);
  z-index: 60;
  display: flex;
  align-items: center;
  gap: 0.45rem;
  padding: 0.4rem 0.55rem;
  background: rgba(7, 10, 20, 0.94);
  border: 1px solid rgba(251, 191, 36, 0.55);
  border-radius: 7px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5), 0 0 14px rgba(251, 191, 36, 0.18);
  font-family: 'JetBrains Mono', 'Courier New', monospace;
  animation: tdTradePop 0.14s ease-out;
}
@keyframes tdTradePop {
  from { opacity: 0; transform: translate(-50%, calc(-100% + 6px)); }
  to   { opacity: 1; transform: translate(-50%, -100%); }
}
.td-trade-popup::after {
  content: '';
  position: absolute;
  left: 50%;
  bottom: -6px;
  width: 10px;
  height: 10px;
  transform: translateX(-50%) rotate(45deg);
  background: rgba(7, 10, 20, 0.94);
  border-right: 1px solid rgba(251, 191, 36, 0.55);
  border-bottom: 1px solid rgba(251, 191, 36, 0.55);
}
.td-trade-popup-name {
  color: #e2e8f0;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.05em;
  white-space: nowrap;
}
.td-trade-popup-btn {
  border: 1px solid #fbbf24;
  background: rgba(251, 191, 36, 0.12);
  color: #fbbf24;
  font: 700 0.64rem/1 'JetBrains Mono', 'Courier New', monospace;
  letter-spacing: 0.06em;
  padding: 0.34rem 0.55rem;
  border-radius: 4px;
  cursor: pointer;
  white-space: nowrap;
}
.td-trade-popup-btn:hover:not(:disabled) { background: rgba(251, 191, 36, 0.28); }
.td-trade-popup-btn:disabled { opacity: 0.5; cursor: default; }
.td-trade-popup-close {
  border: none;
  background: none;
  color: #64748b;
  font-size: 0.72rem;
  cursor: pointer;
  padding: 0.15rem 0.25rem;
}
.td-trade-popup-close:hover { color: #e2e8f0; }

/* Incoming trade request — floats over the requester's head */
.td-trade-prompt {
  position: absolute;
  transform: translate(-50%, -100%);
  z-index: 61;
  width: max-content;
  max-width: 230px;
  padding: 0.55rem 0.7rem;
  background: rgba(7, 10, 20, 0.96);
  border: 1px solid rgba(56, 212, 184, 0.6);
  border-radius: 7px;
  box-shadow: 0 10px 28px rgba(0, 0, 0, 0.5), 0 0 16px rgba(56, 212, 184, 0.2);
  font-family: 'JetBrains Mono', 'Courier New', monospace;
  animation: tdTradePop 0.14s ease-out;
}
.td-trade-prompt-centered {
  left: 50% !important;
  top: 18% !important;
}
.td-trade-prompt-text {
  color: #e2e8f0;
  font-size: 0.66rem;
  line-height: 1.45;
  margin-bottom: 0.45rem;
}
.td-trade-prompt-actions { display: flex; gap: 0.4rem; }

/* Shared small buttons */
.td-trade-btn {
  border-radius: 4px;
  cursor: pointer;
  font: 700 0.66rem/1 'JetBrains Mono', 'Courier New', monospace;
  letter-spacing: 0.06em;
  padding: 0.42rem 0.7rem;
}
.td-trade-btn:disabled { opacity: 0.45; cursor: default; }
.td-trade-btn-go {
  border: 1px solid #38d4b8;
  background: rgba(56, 212, 184, 0.14);
  color: #38d4b8;
  flex: 1;
}
.td-trade-btn-go:hover:not(:disabled) { background: rgba(56, 212, 184, 0.3); }
.td-trade-btn-no {
  border: 1px solid #ef4444;
  background: rgba(239, 68, 68, 0.1);
  color: #f87171;
  flex: 1;
}
.td-trade-btn-no:hover:not(:disabled) { background: rgba(239, 68, 68, 0.25); }
.td-trade-btn-confirm {
  border: 1px solid #fbbf24;
  background: linear-gradient(180deg, rgba(251, 191, 36, 0.32), rgba(251, 191, 36, 0.16));
  color: #fde68a;
  flex: 2;
}
.td-trade-btn-confirm:hover:not(:disabled) { background: rgba(251, 191, 36, 0.4); }
.td-trade-btn-add {
  border: 1px dashed rgba(125, 211, 252, 0.5);
  background: rgba(56, 132, 255, 0.07);
  color: #7dd3fc;
  width: 100%;
  margin-top: 0.4rem;
  padding: 0.55rem 0.7rem;
  font-size: 0.7rem;
  border-radius: 7px;
}
.td-trade-btn-add:hover { background: rgba(56, 132, 255, 0.18); }

/* The trade window */
.td-trade-overlay {
  position: fixed;
  inset: 0;
  z-index: 2147483647;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 16px;
  background: radial-gradient(ellipse at center, rgba(8, 12, 26, 0.72), rgba(2, 4, 10, 0.9));
  -webkit-backdrop-filter: blur(5px);
  backdrop-filter: blur(5px);
  animation: td-fade-in 0.2s cubic-bezier(0.16, 1, 0.3, 1);
}
.td-trade-win {
  position: relative;
  width: min(840px, 100%);
  max-height: min(720px, calc(100vh - 32px));
  overflow-y: auto;
  background:
    radial-gradient(circle at 16% -10%, rgba(251, 191, 36, 0.08), transparent 42%),
    radial-gradient(circle at 88% 112%, rgba(56, 132, 255, 0.07), transparent 46%),
    linear-gradient(150deg, #0a1020 0%, #05070e 58%, #070b16 100%);
  border: 1px solid rgba(251, 191, 36, 0.5);
  border-radius: 14px;
  box-shadow:
    0 30px 90px rgba(0, 0, 0, 0.85),
    0 0 44px rgba(251, 191, 36, 0.1),
    inset 0 1px 0 rgba(255, 255, 255, 0.06);
  font-family: 'JetBrains Mono', 'Courier New', monospace;
  display: flex;
  flex-direction: column;
  animation: td-scale-up 0.25s cubic-bezier(0.16, 1, 0.3, 1);
}
.td-trade-head {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.95rem 1.15rem;
  border-bottom: 1px solid rgba(251, 191, 36, 0.22);
  background: linear-gradient(90deg, rgba(251, 191, 36, 0.1), rgba(251, 191, 36, 0.02) 55%, transparent);
}
.td-trade-head-icon {
  display: grid;
  place-items: center;
  width: 34px;
  height: 34px;
  border-radius: 9px;
  border: 1px solid rgba(251, 191, 36, 0.55);
  background: rgba(251, 191, 36, 0.1);
  color: #fbbf24;
  font-size: 1.05rem;
  font-weight: 800;
  box-shadow: 0 0 14px rgba(251, 191, 36, 0.18), inset 0 0 8px rgba(251, 191, 36, 0.08);
  flex-shrink: 0;
}
.td-trade-head-text {
  display: flex;
  flex-direction: column;
  gap: 3px;
  flex: 1;
  min-width: 0;
}
.td-trade-head-title {
  color: #fbbf24;
  font-size: 0.98rem;
  font-weight: 800;
  letter-spacing: 0.14em;
  line-height: 1;
  text-shadow: 0 0 10px rgba(251, 191, 36, 0.35);
}
.td-trade-head-partner {
  color: #94a3b8;
  font-size: 0.7rem;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.td-trade-head-partner b { color: #e2e8f0; font-weight: 700; }
.td-trade-head .td-trade-popup-close { font-size: 0.95rem; padding: 0.3rem 0.45rem; }

/* Lifecycle step strip — BUILD OFFERS → BOTH ACCEPT → CONFIRM */
.td-trade-steps {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.65rem 1.15rem;
  border-bottom: 1px solid rgba(148, 163, 184, 0.12);
  background: rgba(7, 10, 20, 0.5);
}
.td-trade-step {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: #475569;
  font-size: 0.6rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  white-space: nowrap;
}
.td-trade-step b {
  display: grid;
  place-items: center;
  width: 18px;
  height: 18px;
  border-radius: 50%;
  border: 1px solid rgba(148, 163, 184, 0.35);
  background: rgba(148, 163, 184, 0.06);
  color: #64748b;
  font-size: 0.58rem;
}
.td-trade-step.is-now { color: #fde68a; }
.td-trade-step.is-now b {
  border-color: #fbbf24;
  background: rgba(251, 191, 36, 0.16);
  color: #fbbf24;
  box-shadow: 0 0 10px rgba(251, 191, 36, 0.3);
}
.td-trade-step.is-done { color: #38d4b8; }
.td-trade-step.is-done b {
  border-color: rgba(56, 212, 184, 0.6);
  background: rgba(56, 212, 184, 0.12);
  color: #38d4b8;
}
.td-trade-step-line {
  flex: 1;
  min-width: 12px;
  height: 1px;
  background: linear-gradient(90deg, rgba(148, 163, 184, 0.28), rgba(148, 163, 184, 0.08));
}
.td-trade-cols {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 1px;
  background: rgba(251, 191, 36, 0.16);
  flex: 1;
}
.td-trade-col {
  background: #060912;
  padding: 1rem 1.15rem;
  display: flex;
  flex-direction: column;
  gap: 0.8rem;
  min-height: 270px;
  transition: box-shadow 0.25s ease;
}
.td-trade-col-me {
  background: #081020;
}
.td-trade-col.is-accepted {
  box-shadow: inset 0 0 0 1px rgba(56, 212, 184, 0.35), inset 0 0 28px rgba(56, 212, 184, 0.05);
}
.td-trade-col-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  color: #94a3b8;
  font-size: 0.66rem;
  font-weight: 800;
  letter-spacing: 0.12em;
}
.td-trade-col-head > span:first-child {
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.td-trade-col-me .td-trade-col-head { color: #7dd3fc; }
.td-trade-col-badge {
  flex-shrink: 0;
  font-size: 0.56rem;
  font-weight: 800;
  letter-spacing: 0.08em;
  padding: 3px 9px;
  border-radius: 999px;
  border: 1px solid rgba(148, 163, 184, 0.3);
  color: #64748b;
  background: rgba(148, 163, 184, 0.05);
  transition: all 0.2s ease;
}
.td-trade-col-badge.is-on {
  border-color: rgba(56, 212, 184, 0.55);
  color: #38d4b8;
  background: rgba(56, 212, 184, 0.1);
  box-shadow: 0 0 10px rgba(56, 212, 184, 0.18);
}
.td-trade-coins {
  display: flex;
  align-items: center;
  gap: 0.5rem;
  padding: 0.5rem 0.6rem;
  border-radius: 8px;
  border: 1px solid rgba(251, 191, 36, 0.22);
  background: rgba(251, 191, 36, 0.04);
  color: #fbbf24;
  font-size: 0.85rem;
  font-weight: 700;
}
.td-trade-coin-sign {
  display: grid;
  place-items: center;
  width: 22px;
  height: 22px;
  border-radius: 50%;
  border: 1px solid rgba(251, 191, 36, 0.5);
  background: radial-gradient(circle at 35% 30%, rgba(253, 230, 138, 0.35), rgba(251, 191, 36, 0.1));
  font-size: 0.7rem;
  flex-shrink: 0;
}
.td-trade-coin-input {
  width: 130px;
  background: rgba(251, 191, 36, 0.08);
  border: 1px solid rgba(251, 191, 36, 0.4);
  border-radius: 6px;
  color: #fde68a;
  font: 700 0.85rem 'JetBrains Mono', 'Courier New', monospace;
  padding: 0.4rem 0.5rem;
  outline: none;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.td-trade-coin-input:focus {
  border-color: #fbbf24;
  box-shadow: 0 0 0 2px rgba(251, 191, 36, 0.18);
}
.td-trade-coin-have { color: #64748b; font-size: 0.62rem; font-weight: 400; }
.td-trade-coin-ro { color: #fde68a; font-size: 0.85rem; }
.td-trade-items {
  display: flex;
  flex-wrap: wrap;
  gap: 0.35rem;
  align-content: flex-start;
  flex: 1;
}
.td-trade-chip {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  font-size: 0.68rem;
  color: #e2e8f0;
  padding: 0.42rem 0.6rem;
  border-radius: 7px;
  border: 1px solid rgba(148, 163, 184, 0.25);
  background: rgba(148, 163, 184, 0.04);
  max-width: 100%;
  transition: all 0.15s ease;
}
.td-trade-chip:hover {
  border-color: rgba(148, 163, 184, 0.45);
  background: rgba(148, 163, 184, 0.08);
}
.td-trade-chip-weapon     { border-color: rgba(6, 182, 212, 0.4);  background: rgba(6, 182, 212, 0.05); }
.td-trade-chip-weapon:hover { 
  border-color: rgba(6, 182, 212, 0.7);  
  background: rgba(6, 182, 212, 0.12);
  box-shadow: 0 0 10px rgba(6, 182, 212, 0.15);
  transform: translateY(-1px);
}
.td-trade-chip-consumable { border-color: rgba(168, 85, 247, 0.4); background: rgba(168, 85, 247, 0.05); }
.td-trade-chip-consumable:hover { 
  border-color: rgba(168, 85, 247, 0.7); 
  background: rgba(168, 85, 247, 0.12);
  box-shadow: 0 0 10px rgba(168, 85, 247, 0.15);
  transform: translateY(-1px);
}
.td-trade-chip-sector     { border-color: rgba(251, 191, 36, 0.4); background: rgba(251, 191, 36, 0.05); }
.td-trade-chip-sector:hover { 
  border-color: rgba(251, 191, 36, 0.7); 
  background: rgba(251, 191, 36, 0.12);
  box-shadow: 0 0 10px rgba(251, 191, 36, 0.15);
  transform: translateY(-1px);
}
.td-trade-chip-empty      { color: #475569; font-size: 0.62rem; font-style: italic; }
.td-trade-chip-x {
  border: none;
  background: none;
  color: #94a3b8;
  font-size: 0.6rem;
  cursor: pointer;
  padding: 0 0.1rem;
}
.td-trade-chip-x:hover { color: #f87171; }
/* My side: big accept toggle. Their side: quiet state banner. */
.td-trade-accept-btn {
  width: 100%;
  box-sizing: border-box;
  border-radius: 8px;
  border: 1px solid rgba(56, 212, 184, 0.5);
  background: rgba(56, 212, 184, 0.08);
  color: #38d4b8;
  font: 800 0.72rem/1.2 'JetBrains Mono', 'Courier New', monospace;
  letter-spacing: 0.08em;
  padding: 0.68rem 0.7rem;
  cursor: pointer;
  transition: background 0.15s, box-shadow 0.15s, transform 0.1s;
}
.td-trade-accept-btn:hover:not(:disabled) { background: rgba(56, 212, 184, 0.18); }
.td-trade-accept-btn:active:not(:disabled) { transform: scale(0.99); }
.td-trade-accept-btn:disabled { opacity: 0.45; cursor: default; }
.td-trade-accept-btn.is-on {
  background: linear-gradient(180deg, rgba(56, 212, 184, 0.28), rgba(56, 212, 184, 0.12));
  box-shadow: 0 0 16px rgba(56, 212, 184, 0.18), inset 0 0 10px rgba(56, 212, 184, 0.08);
  color: #a7f3d0;
}
.td-trade-accept-state {
  width: 100%;
  box-sizing: border-box;
  text-align: center;
  border-radius: 8px;
  border: 1px dashed rgba(148, 163, 184, 0.3);
  color: #64748b;
  font: 800 0.7rem/1.2 'JetBrains Mono', 'Courier New', monospace;
  letter-spacing: 0.08em;
  padding: 0.68rem 0.7rem;
  transition: all 0.2s ease;
}
.td-trade-accept-state.is-on {
  border: 1px solid rgba(56, 212, 184, 0.55);
  background: rgba(56, 212, 184, 0.1);
  color: #38d4b8;
  box-shadow: 0 0 14px rgba(56, 212, 184, 0.12);
}
.td-trade-status {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  padding: 0.65rem 1.15rem;
  color: #94a3b8;
  font-size: 0.68rem;
  line-height: 1.5;
  border-top: 1px solid rgba(251, 191, 36, 0.16);
  background: rgba(7, 10, 20, 0.4);
}
.td-trade-status::before {
  content: '';
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: currentColor;
  box-shadow: 0 0 8px currentColor;
  flex-shrink: 0;
  animation: tdTradeBlink 1.6s ease-in-out infinite;
}
.td-trade-status.is-ready    { color: #fde68a; }
.td-trade-status.is-settling { color: #7dd3fc; }
@keyframes tdTradeBlink {
  0%, 100% { opacity: 0.35; }
  50%      { opacity: 1; }
}

@keyframes td-fade-in {
  from { opacity: 0; }
  to { opacity: 1; }
}

@keyframes td-scale-up {
  from { transform: scale(0.96); opacity: 0; }
  to { transform: scale(1); opacity: 1; }
}
.td-trade-foot {
  display: flex;
  gap: 0.7rem;
  padding: 0.8rem 1.15rem 1rem;
}
.td-trade-foot .td-trade-btn {
  padding: 0.7rem 0.9rem;
  font-size: 0.78rem;
  border-radius: 8px;
}
/* Both sides accepted → the finish line glows so the next move is obvious. */
.td-trade-btn-confirm:not(:disabled) { animation: tdTradeReady 1.5s ease-in-out infinite; }
@keyframes tdTradeReady {
  0%, 100% { box-shadow: 0 0 6px rgba(251, 191, 36, 0.15); }
  50%      { box-shadow: 0 0 22px rgba(251, 191, 36, 0.45); }
}

/* Inventory / sector picker (sheet over the whole window) */
.td-trade-picker {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: rgba(5, 7, 14, 0.97);
  -webkit-backdrop-filter: blur(3px);
  backdrop-filter: blur(3px);
  border: 1px solid rgba(125, 211, 252, 0.35);
  display: flex;
  flex-direction: column;
  border-radius: 14px;
  animation: td-fade-in 0.15s ease-out;
}
.td-trade-picker-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0.8rem 1.15rem;
  color: #7dd3fc;
  font-size: 0.74rem;
  font-weight: 800;
  letter-spacing: 0.1em;
  border-bottom: 1px solid rgba(125, 211, 252, 0.2);
  background: linear-gradient(90deg, rgba(56, 132, 255, 0.08), transparent);
}
.td-trade-picker-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding: 0.6rem 0.8rem 0.9rem;
  display: flex;
  flex-direction: column;
  gap: 0.35rem;
}
.td-trade-picker-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 0.5rem;
  text-align: left;
  border: 1px solid rgba(148, 163, 184, 0.25);
  background: rgba(148, 163, 184, 0.05);
  color: #e2e8f0;
  border-radius: 7px;
  padding: 0.6rem 0.75rem;
  font: 600 0.7rem 'JetBrains Mono', 'Courier New', monospace;
  cursor: pointer;
  transition: border-color 0.12s, background 0.12s;
}
.td-trade-picker-row:hover { border-color: #7dd3fc; background: rgba(56, 132, 255, 0.12); }
.td-trade-picker-sub { color: #64748b; font-size: 0.62rem; }
.td-trade-picker-empty {
  color: #64748b;
  font-size: 0.68rem;
  line-height: 1.6;
  padding: 1.2rem 0.6rem;
  text-align: center;
}

@media (max-width: 600px) {
  .td-trade-win { max-height: calc(100dvh - 24px); }
  .td-trade-cols { grid-template-columns: 1fr; }
  .td-trade-col { min-height: 0; }
  .td-trade-steps { padding: 0.55rem 0.8rem; gap: 0.35rem; }
  .td-trade-step { font-size: 0.54rem; }
  .td-trade-head { padding: 0.8rem 0.9rem; }
  .td-trade-foot { padding: 0.7rem 0.9rem 0.85rem; }
}

/* =====================================================================
   SECTOR RIGHT PANEL — loadout dock + armory freeze-pane
   ===================================================================== */

/* Store head is now a single line: identity left, live balance right.
   It also carries the store's top inset (see .td-mmo-store). */
.td-mmo-store-head { align-items: center; padding: 12px 0 6px; }

/* Thin glowing scrollbar so the armory reads like a console viewport.
   min-height keeps an internal scroll area alive on short windows so the
   freeze-pane below still has somewhere to pin. */
.td-mmo-store {
  min-height: 200px;
  scrollbar-width: thin;
  scrollbar-color: rgba(103,232,249,0.3) transparent;
}
.td-mmo-store::-webkit-scrollbar { width: 7px; }
.td-mmo-store::-webkit-scrollbar-track { background: transparent; }
.td-mmo-store::-webkit-scrollbar-thumb { background: rgba(103,232,249,0.22); border-radius: 999px; }
.td-mmo-store::-webkit-scrollbar-thumb:hover { background: rgba(103,232,249,0.42); }

/* ── Armory freeze-pane: the section title + Loop selector stay pinned
   to the top of the scrolling store, so the loop can be switched without
   scrolling back up. Negative margins span the store's gutters so cards
   slide cleanly underneath. ── */
.td-mmo-armory-bar {
  position: sticky;
  top: -1px;
  z-index: 7;
  align-items: center;
  margin: 0 -12px;
  padding: 7px 12px;
  background: linear-gradient(180deg, rgba(12,20,34,0.99), rgba(10,16,28,0.94));
  border-bottom: 1px solid rgba(103,232,249,0.22);
  box-shadow: 0 12px 18px -14px rgba(0,0,0,0.9);
  backdrop-filter: blur(5px);
  -webkit-backdrop-filter: blur(5px);
}

/* Mk-tier accents — the active loop pill wears its tier's color. */
.td-mmo-loop-btn.active[data-loop="2"] {
  background: linear-gradient(135deg, #fde68a, #f59e0b);
  box-shadow: 0 0 8px rgba(251,191,36,0.38);
}
.td-mmo-loop-btn.active[data-loop="3"] {
  background: linear-gradient(135deg, #c084fc, #7c3aed);
  color: #f5f3ff;
  box-shadow: 0 0 8px rgba(168,85,247,0.45);
}

/* ── Loadout dock — owned weapons/consumables as compact single-line rows
   with inline EQUIP / USE, replacing the old stacked cards. Weapons and
   consumables are separate groups, each with its own collapse toggle. ── */
.td-gear { display: flex; flex-direction: column; gap: 7px; }
.td-gear-group { display: flex; flex-direction: column; gap: 5px; }
.td-gear-head {
  display: flex; align-items: center; gap: 7px; width: 100%;
  border: none; background: transparent; padding: 1px 2px; cursor: pointer;
  color: #5a7090; font: 800 0.58rem/1 'JetBrains Mono',monospace;
  letter-spacing: 0.12em; text-transform: uppercase;
  transition: color .15s;
}
.td-gear-head:hover { color: #9fb4d0; }
.td-gear-head-chevron { font-size: 0.5rem; transition: transform .15s ease; }
.td-gear-group.collapsed .td-gear-head-chevron { transform: rotate(-90deg); }
.td-gear-head-line { flex: 1; height: 1px; background: linear-gradient(90deg, rgba(90,112,144,0.35), transparent); }
.td-gear-head-sum {
  color: #7d93b2; font-size: 0.56rem; font-weight: 700; letter-spacing: 0.05em;
  max-width: 55%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.td-gear-grid { display: grid; grid-template-columns: repeat(2, minmax(0,1fr)); gap: 5px; }
.td-gear-item {
  --g: #67e8f9;
  display: flex; align-items: center; gap: 5px; min-width: 0; min-height: 26px;
  padding: 3px 5px 3px 7px; border-radius: 7px;
  border: 1px solid rgba(148,163,184,0.20);
  background: rgba(15,23,42,0.66);
  transition: border-color .14s, box-shadow .14s;
}
.td-gear-item:hover { border-color: rgba(148,163,184,0.45); }
.td-gear-item.is-on {
  border-color: var(--g);
  box-shadow: inset 0 0 12px -8px var(--g), 0 0 10px -6px var(--g);
}
.td-gear-dot {
  flex-shrink: 0; width: 5px; height: 5px; border-radius: 50%;
  background: var(--g); box-shadow: 0 0 5px var(--g);
}
.td-gear-name {
  flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: #aebed6; font: 800 0.6rem/1.15 'JetBrains Mono',monospace; letter-spacing: 0.03em;
}
.td-gear-item.is-on .td-gear-name { color: var(--g); }
.td-gear-ammo {
  flex-shrink: 0; max-width: 62px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  color: #5a7090; font: 700 0.54rem/1 'JetBrains Mono',monospace;
}
.td-gear-ammo.low { color: #f5a623; }
.td-gear-qty { flex-shrink: 0; color: #fde68a; font: 800 0.56rem/1 'JetBrains Mono',monospace; }
.td-gear-btn {
  flex-shrink: 0; border: 1px solid rgba(148,163,184,0.32); border-radius: 6px;
  background: rgba(2,6,23,0.5); color: #cbd5e1; cursor: pointer;
  font: 800 0.62rem/1 'JetBrains Mono',monospace; letter-spacing: 0.06em;
  padding: 6px 10px;
  transition: border-color .12s, color .12s, background .12s, transform .1s;
}
.td-gear-btn:hover { border-color: var(--g); color: var(--g); background: rgba(2,6,23,0.85); }
.td-gear-btn:active { transform: scale(0.94); }
.td-gear-check {
  flex-shrink: 0; color: var(--g); font-size: 0.62rem; font-weight: 900; padding: 0 3px;
  text-shadow: 0 0 6px var(--g);
}

/* Desktop sector gutter quick gear. Hidden on compact/mobile layouts; JS also
   hides it when the right gutter is too narrow so the sector square stays clear. */
.td-sector-gear-dock {
  position: absolute;
  right: 10px;
  bottom: 14px;
  z-index: 8;
  display: flex;
  flex-direction: column;
  gap: 7px;
  pointer-events: auto;
  font-family: 'JetBrains Mono', monospace;
}
.td-sector-gear-dock[hidden],
#tdWorldOverlay.td-mobile-layout .td-sector-gear-dock {
  display: none !important;
}
.td-sector-gear-card {
  --g: #67e8f9;
  min-width: 0;
  border: 1px solid rgba(148,163,184,0.24);
  border-radius: 7px;
  background: rgba(6, 9, 15, 0.84);
  box-shadow: 0 5px 18px rgba(0,0,0,0.44), inset 0 0 18px -14px var(--g);
  color: #dbe7f6;
}
button.td-sector-gear-card,
.td-sector-gear-main,
.td-sector-gear-use,
.td-sector-gear-cycle {
  cursor: pointer;
}
button.td-sector-gear-card {
  display: flex;
  flex-direction: column;
  gap: 3px;
  width: 100%;
  padding: 8px 9px;
  text-align: left;
}
.td-sector-gear-card--item,
.td-sector-gear-card--split {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: stretch;
  overflow: hidden;
}
.td-sector-gear-main,
.td-sector-gear-use,
.td-sector-gear-cycle {
  min-width: 0;
  border: 0;
  background: transparent;
  color: inherit;
  font: inherit;
}
.td-sector-gear-main {
  display: flex;
  flex-direction: column;
  gap: 3px;
  padding: 8px 7px 8px 9px;
  text-align: left;
}
.td-sector-gear-use {
  padding: 0 10px;
  border-left: 1px solid rgba(251,191,36,0.36);
  color: #fde68a;
  font-weight: 900;
}
.td-sector-gear-cycle {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 11px;
  border-left: 1px solid rgba(148, 163, 184, 0.24);
  color: var(--g);
  cursor: pointer;
  outline: none;
}
.td-sector-gear-kicker {
  color: var(--g);
  font-size: 0.5rem;
  font-weight: 900;
  line-height: 1;
  letter-spacing: 0;
}
.td-sector-gear-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  color: #f8fafc;
  font-size: 0.62rem;
  font-weight: 900;
  line-height: 1.15;
  letter-spacing: 0;
}
.td-sector-gear-meta {
  color: #8fa4c2;
  font-size: 0.54rem;
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0;
}
.td-sector-gear-meta.is-low { color: #f5a623; }
.td-sector-gear-card:hover {
  border-color: var(--g);
  background: rgba(8, 13, 24, 0.92);
}
.td-sector-gear-use:hover {
  background: rgba(251,191,36,0.12);
}
.td-sector-gear-cycle:hover {
  background: rgba(255, 255, 255, 0.05);
}
.td-rotation-arrows {
  display: inline-block;
  animation: td-rotate-spin 3s linear infinite;
  transform-origin: center;
  transition: animation-duration 0.2s ease;
}
.td-sector-gear-cycle:hover .td-rotation-arrows {
  animation-duration: 1.2s;
}
@keyframes td-rotate-spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}
@media (pointer: coarse) {
  .td-gear-item { min-height: 34px; }
  .td-gear-btn { padding: 8px 11px; }
}
