/* Dungeon tile art — relative to this CSS file */
:root {
  --tile-art-back:     url('../assets/sprites/tiles/tile-unflipped2.1.png');
  --tile-art-revealed: url('../assets/sprites/tiles/tile-flipped2.1.png');
  --tile-art-brick:    url('../assets/sprites/tiles/download (29) (1).png');
  --tile-art-wood:     url('../assets/sprites/tiles/download (30).png');
  --tile-art-rubble:   url('../assets/sprites/tiles/download (31).png');
  --tile-art-plank:    url('../assets/sprites/tiles/download (32).png');
}

/* ── Grid container ── */
#grid-container {
  position: relative;
  flex: 1;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px 6px;
  background: transparent;
  overflow: visible;
  /* 3. Mild perspective tilt on the container — doesn't interfere with tile flip */
  perspective: 1200px;
}

/* Floor change: block interaction during transition */
#grid-container.floor-transition-active {
  pointer-events: none;
}

/* Clip overflow only during the slide so the grid doesn't bleed outside the container */
#grid-container.floor-transition-clipped {
  overflow: hidden;
}

/* Big "Floor N" splash during descent — fades out quickly after grid appears */
.floor-banner {
  position: absolute;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: center;
  justify-content: center;
  pointer-events: none;
  background: rgba(6, 4, 12, 0.62);
  opacity: 0;
  transition: opacity 0.32s ease;
}

.floor-banner.is-visible {
  opacity: 1;
}

.floor-banner.hidden {
  visibility: hidden;
}

.floor-banner-text {
  font-family: ui-sans-serif, system-ui, sans-serif;
  font-weight: 900;
  font-size: clamp(3rem, 20vw, 5.75rem);
  line-height: 1;
  letter-spacing: 0.06em;
  color: var(--torch-yellow, #f5c518);
  text-shadow:
    0 0 24px rgba(232, 132, 26, 0.95),
    0 0 56px rgba(232, 132, 26, 0.45),
    0 4px 0 #1a1208,
    0 6px 18px rgba(0, 0, 0, 0.85);
}

#grid-container > #grid {
  transform: rotateX(4deg);
  transform-origin: center top;
}

#grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr); /* cols set in JS; default matches base 5×6 */
  gap: 0;
  width: 100%;
  max-width: 360px;
  overflow: visible;
}

/* Ricochet target order badge */
.ricochet-marker {
  position: absolute;
  top: 2px;
  right: 2px;
  z-index: 8;
  min-width: 1.15em;
  height: 1.15em;
  padding: 0 4px;
  border-radius: 4px;
  background: rgba(0, 170, 210, 0.92);
  color: #fff;
  font-size: 0.72rem;
  font-weight: 800;
  line-height: 1.15em;
  text-align: center;
  box-shadow: 0 1px 0 rgba(0, 0, 0, 0.35);
  pointer-events: none;
}

/* ── Base tile ── */
.tile {
  aspect-ratio: 1;
  perspective: 700px;
  cursor: pointer;
  touch-action: none;   /* prevent browser scroll/zoom stealing the long-press */
  -webkit-user-select: none;
  user-select: none;
  /* Allow icon to overflow upward into the tile above */
  overflow: visible;
  position: relative;
  z-index: 1;
}

/* Each row stacks above the previous so overflowing icons render on top */
.tile:hover { z-index: 3; }

/* Revealed enemy and chest tiles float above all neighbors so their sprite isn't clipped */
.tile.is-enemy.revealed,
.tile-type-chest.revealed { z-index: 4; }

/* Reachable tiles sit above revealed neighbors so the drop shadow is visible */
.tile.reachable:not(.revealed) { z-index: 2; }

/* Echo Charm — hint glyph on adjacent hidden tiles */
.tile.echo-hint:not(.revealed)::after {
  content: attr(data-echo-hint);
  position: absolute;
  top: 2px;
  right: 2px;
  z-index: 6;
  font-size: 0.85rem;
  line-height: 1;
  filter: drop-shadow(0 0 3px rgba(0, 0, 0, 0.9));
  pointer-events: none;
}


.tile-inner {
  width: 100%;
  height: 100%;
  position: relative;
  transform-style: preserve-3d;
  transition: transform 0.42s cubic-bezier(0.35, 0.0, 0.25, 1.0);
  border-radius: 2px;
  overflow: visible;
}

.tile.revealed .tile-inner {
  transform: rotateY(180deg);
}

.tile-back,
.tile-front {
  position: absolute;
  inset: 0;
  backface-visibility: hidden;
  -webkit-backface-visibility: hidden;
  border-radius: 2px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;  /* label + hp bar sit at bottom */
  gap: 2px;
  padding-bottom: 4px;
}

/* Back face — unrevealed: same texture but darkened */
.tile-back {
  background-color: #1a1a20;
  background-image: var(--tile-art-back);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  border: none;
  box-shadow: none;
}

/* Default: dark (not yet reachable) */
.tile-back::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0,0,0,0.7);
  pointer-events: none;
}

/* Reachable: lift the darkness — tile is lit and clickable */
.tile.reachable .tile-back::after {
  background: none;
}

/* Reachable tiles pop up with a dark shadow on all sides */
.tile.reachable:not(.revealed) .tile-back {
  box-shadow: 0 0 3px 3px rgba(0, 0, 0, 0.75);
}

/* Locked by monster: dark + X — pure CSS (no extra HTTP; old PNG confused “stuck at last GET” in server logs) */
.tile.locked .tile-back::after {
  background:
    linear-gradient(
      45deg,
      transparent 44%,
      rgba(210, 55, 55, 0.92) 46%,
      rgba(210, 55, 55, 0.92) 54%,
      transparent 56%
    ),
    linear-gradient(
      -45deg,
      transparent 44%,
      rgba(210, 55, 55, 0.92) 46%,
      rgba(210, 55, 55, 0.92) 54%,
      transparent 56%
    ),
    rgba(0, 0, 0, 0.62);
  background-size: 100% 100%, 100% 100%, 100% 100%;
}

/* Locked by monster + reachable: lit + X */
.tile.reachable.locked .tile-back::after {
  background:
    linear-gradient(
      45deg,
      transparent 44%,
      rgba(210, 55, 55, 0.92) 46%,
      rgba(210, 55, 55, 0.92) 54%,
      transparent 56%
    ),
    linear-gradient(
      -45deg,
      transparent 44%,
      rgba(210, 55, 55, 0.92) 46%,
      rgba(210, 55, 55, 0.92) 54%,
      transparent 56%
    ),
    rgba(0, 0, 0, 0.08);
  background-size: 100% 100%, 100% 100%, 100% 100%;
}

/* Front face — revealed content (floor art + type tint) */
.tile-front {
  transform: rotateY(180deg);
  /* 1. Top-edge highlight — light source from above */
  border-top: 1px solid rgba(255,255,255,0.22);
  border-left: 1px solid rgba(255,255,255,0.10);
  border-right: 0;
  /* 5. Tile thickness — dark bottom border = stone block depth */
  border-bottom: 0;
  background-color: #2a2418;
  background-size: cover, cover;
  background-position: center, center;
  background-repeat: no-repeat, no-repeat;
  overflow: visible;
  /* 4. Inset slab shadow — floor looks recessed */
  box-shadow:
    inset 0 3px 7px rgba(0,0,0,0.5),
    inset 0 -1px 0 rgba(255,255,255,0.04);
}

/* 2. Drop shadow on tile surface beneath floating enemy icons */
.tile.is-enemy.revealed .tile-front::after {
  content: '';
  position: absolute;
  bottom: 24px;
  left: 50%;
  transform: translateX(-50%);
  width: 55%;
  height: 6px;
  background: radial-gradient(ellipse, rgba(0,0,0,0.55) 0%, transparent 75%);
  border-radius: 50%;
  pointer-events: none;
  z-index: 1;
}


/* Enemy stat row — HP and damage displayed on tile face */
.tile-enemy-stats {
  display: flex;
  gap: 3px;
  align-items: center;
  justify-content: center;
  font-size: clamp(0.45rem, 2.2vw, 0.72rem);
  font-family: ui-sans-serif, system-ui, sans-serif;
  font-weight: 800;
  line-height: 1;
  white-space: nowrap;
  color: #fff;
  text-shadow: 0 0 4px #000, 0 1px 4px rgba(0,0,0,1);
  background: rgba(0,0,0,0.45);
  border-radius: 6px;
  padding: 2px 4px;
  margin-bottom: 3px;
}

.tile-enemy-stats .stat-hp  { color: #ff5555; text-shadow: 0 0 5px #000, 0 1px 4px rgba(0,0,0,1); }
.tile-enemy-stats .stat-dmg { color: #ffd040; text-shadow: 0 0 5px #000, 0 1px 4px rgba(0,0,0,1); }

/* Orthogonal threat clue (enemies + trap weight) — Mamono-style, N/E/S/W only */
.tile-front .tile-threat-clue {
  position: absolute;
  top: 3px;
  right: 4px;
  z-index: 6;
  min-width: 1.15em;
  text-align: center;
  font-weight: 900;
  font-size: clamp(0.62rem, 3.4vw, 0.92rem);
  line-height: 1;
  font-variant-numeric: tabular-nums;
  pointer-events: none;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.9), 0 0 6px rgba(0, 0, 0, 0.6);
}
.tile-front .tile-threat-clue.threat-clue-safe {
  color: #8ef4a0;
}
.tile-front .tile-threat-clue.threat-clue-risk {
  color: #ffc266;
}
.tile-front .tile-threat-clue.hidden {
  display: none;
}

/* ── Slime split ── */
.tile-icon-wrap.slime-split {
  display: flex;
  flex-direction: row;
  align-items: flex-end;
  justify-content: center;
  gap: 2px;
}

.slime-half {
  width: 46% !important;
  height: auto !important;
  object-fit: contain;
}

/* ── Per-type icon placement ── */

/* Chest: centered in the tile */
.tile-type-chest .tile-icon-wrap {
  top: 0;
  bottom: 0;
  height: 100%;
  align-items: center;
}

/* Magic chest: same icon sizing as regular chest (class is tile-type-magic_chest from type magic_chest) */
.tile-type-magic_chest .tile-icon-wrap {
  top: 0;
  bottom: 0;
  height: 100%;
  align-items: center;
}

/* Exit: framed stairs art — fill tile face like chest */
.tile-type-exit .tile-icon-wrap {
  top: 0;
  bottom: 0;
  height: 100%;
  align-items: center;
}

/* Trap: cobweb emoji centered on tile face */
.tile-type-trap .tile-icon-wrap {
  top: 0;
  bottom: 0;
  height: 100%;
  align-items: center;
  justify-content: center;
}

/* Rest floor specials — centered icons */
.tile-type-well .tile-icon-wrap,
.tile-type-anvil .tile-icon-wrap,
.tile-type-rope .tile-icon-wrap {
  top: 0;
  bottom: 0;
  height: 100%;
  align-items: center;
  justify-content: center;
}

/* Gold coin: gentle float, no big overflow */
.tile-type-gold .tile-icon-wrap {
  top: -10%;
  bottom: 22px;
}

/* Shrine, merchant, checkpoint: slight lift but not full enemy overflow */
.tile-type-shrine .tile-icon-wrap,
.tile-type-event .tile-icon-wrap,
.tile-type-checkpoint .tile-icon-wrap {
  top: -12%;
  bottom: 22px;
}

/* Revealed icon art — sits just above the hp/dmg stats */
.tile-icon-wrap {
  display: flex;
  align-items: flex-end;
  justify-content: center;
  position: absolute;
  bottom: 28px;           /* sit above label + stats + hp bar */
  left: 0;
  right: 0;
  top: 4%;                /* reduced upward overflow — keeps enemy closer to stats */
  pointer-events: none;
  z-index: 2;
}

.tile-icon-img {
  max-width: min(88%, 90px);
  max-height: 100%;
  width: auto;
  height: auto;
  object-fit: contain;
  pointer-events: none;
  filter:
    drop-shadow(0 -2px 0 rgba(0, 0, 0, 0.55))
    drop-shadow(0 3px 5px rgba(0, 0, 0, 0.80))
    drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55))
    drop-shadow(0 0 1px rgba(0, 0, 0, 0.95));
}

.tile-icon-fallback .tile-emoji {
  line-height: 1;
  font-size: 1.85rem;
  filter:
    drop-shadow(0 -1px 0 rgba(0, 0, 0, 0.55))
    drop-shadow(0 3px 5px rgba(0, 0, 0, 0.80))
    drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55));
}

.tile-emoji {
  line-height: 1;
  font-size: 1.85rem;
  filter:
    drop-shadow(0 -1px 0 rgba(0, 0, 0, 0.55))
    drop-shadow(0 3px 5px rgba(0, 0, 0, 0.80))
    drop-shadow(0 6px 14px rgba(0, 0, 0, 0.55));
}

.tile-label {
  font-size: 0.48rem;
  letter-spacing: 0.8px;
  text-transform: uppercase;
  opacity: 0.92;
  font-family: sans-serif;
  color: rgba(255,255,255,0.85);
  text-shadow: 0 1px 3px rgba(0,0,0,0.9);
}

/* Enemy HP bar on tile front */
.tile-hp-bar {
  width: 75%;
  height: 3px;
  background: rgba(0,0,0,0.5);
  border-radius: 2px;
  overflow: hidden;
  margin-top: 1px;
}

.tile-hp-fill {
  height: 100%;
  background: #cc2222;
  border-radius: 2px;
  transition: width 0.2s ease;
}

/* ── Tile type styles ── */

/* All revealed tiles: plain floor art by default */
.tile-front {
  background-image: var(--tile-art-revealed);
  background-size: cover;
  background-position: center;
}

.tile-front::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.58);
  pointer-events: none;
  z-index: 0;
}

.tile-front > * {
  position: relative;
  z-index: 1;
}

.tile-front.type-slain {
  background-image: var(--tile-art-revealed);
  border-color: #2a2a2a;
}

/* Darken the background without affecting the icon */
.tile-front.type-slain::before {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(0, 0, 0, 0.58);
  pointer-events: none;
  z-index: 0;
}

/* Anchor ashes to the floor — centered, no upward overflow */
.tile-front.type-slain .tile-icon-wrap {
  top: auto;
  bottom: 8px;
  height: 65%;
  align-items: flex-end;
  justify-content: center;
  z-index: 1;
}

.tile-front.type-slain .tile-icon-img {
  width: 80%;
  height: auto;
  object-fit: contain;
  filter: drop-shadow(0 -2px 0 rgba(0, 0, 0, 0.55))
          drop-shadow(0 0 1px rgba(0, 0, 0, 0.95));
}

.tile-front.type-enemy-fast { animation: pulse-danger 1.1s ease-in-out infinite; }
.tile-front.type-boss        { animation: pulse-danger 0.8s ease-in-out infinite; }

.tile-front.is-boss .tile-label {
  color: #dd88ff;
  font-weight: bold;
}

.tile-hp-bar.boss-hp { height: 5px; }
.tile-hp-bar.boss-hp .tile-hp-fill { background: #aa00ee; }

/* ── Tile colours — only active when body.tile-colors is set ── */
body.tile-colors .tile-front.type-empty {
  background-image:
    linear-gradient(180deg, rgba(14,16,26,0.45), rgba(22,22,34,0.58)),
    var(--tile-art-revealed);
  color: var(--text-dim);
}
body.tile-colors .tile-front.type-gold {
  background-image:
    linear-gradient(145deg, rgba(37,26,0,0.72), rgba(61,45,0,0.80)),
    var(--tile-art-revealed);
  border-color: #7a6010;
}
body.tile-colors .tile-front.type-chest {
  background-image:
    linear-gradient(145deg, rgba(40,21,0,0.72), rgba(74,40,0,0.80)),
    var(--tile-art-revealed);
  border-color: #7a4010;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.5), inset 0 0 12px rgba(180,100,0,0.2);
}
body.tile-colors .tile-front.type-checkpoint {
  background-image:
    linear-gradient(145deg, rgba(0,21,40,0.72), rgba(0,32,64,0.80)),
    var(--tile-art-revealed);
  border-color: #1a5080;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.5), inset 0 0 14px rgba(0,100,200,0.2);
}
body.tile-colors .tile-front.type-exit {
  background-image:
    linear-gradient(145deg, rgba(0,21,8,0.72), rgba(0,40,16,0.80)),
    var(--tile-art-revealed);
  border-color: #185030;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.5), inset 0 0 16px rgba(0,160,60,0.2);
}
body.tile-colors .tile-front.type-trap {
  background-image:
    linear-gradient(145deg, rgba(26,16,32,0.78), rgba(45,26,56,0.85)),
    var(--tile-art-revealed);
  border-color: #5a2a7a;
}
body.tile-colors .tile-front.type-slain {
  background-image: var(--tile-art-revealed);
}
body.tile-colors .tile-front.type-enemy {
  background-image:
    linear-gradient(145deg, rgba(42,8,8,0.78), rgba(74,16,16,0.86)),
    var(--tile-art-revealed);
  border-color: #6a1818;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.5), inset 0 0 14px rgba(160,0,0,0.25);
}
body.tile-colors .tile-front.type-enemy-fast {
  background-image:
    linear-gradient(145deg, rgba(56,8,8,0.80), rgba(100,16,16,0.88)),
    var(--tile-art-revealed);
  border-color: #aa1818;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.5), inset 0 0 18px rgba(220,0,0,0.35);
}
body.tile-colors .tile-front.type-boss {
  background-image:
    linear-gradient(145deg, rgba(26,0,48,0.84), rgba(56,0,96,0.90)),
    var(--tile-art-revealed);
  border-color: #9900cc;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.5), inset 0 0 24px rgba(160,0,220,0.4), 0 0 10px rgba(140,0,200,0.3);
}
body.tile-colors .tile-front.type-shrine {
  background-image:
    linear-gradient(145deg, rgba(0,26,16,0.72), rgba(0,48,32,0.80)),
    var(--tile-art-revealed);
  border-color: #00aa66;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.5), inset 0 0 14px rgba(0,180,100,0.2);
}
body.tile-colors .tile-front.type-event {
  background-image:
    linear-gradient(145deg, rgba(26,21,0,0.72), rgba(48,40,0,0.80)),
    var(--tile-art-revealed);
  border-color: #aa8800;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.5), inset 0 0 14px rgba(180,140,0,0.2);
}
body.tile-colors .tile-front.type-blockage {
  background-image:
    linear-gradient(145deg, rgba(18,15,10,0.6), rgba(30,26,18,0.7)),
    var(--tile-art-revealed);
  border-color: #5a5040;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.6);
}

/* Blockage icon fills the tile face */
.tile-type-blockage .tile-icon-wrap {
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

.tile-type-blockage .tile-icon-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 6px;
}

/* Open pit — always revealed; same fill treatment as rubble */
body.tile-colors .tile-front.type-hole {
  background-image:
    linear-gradient(145deg, rgba(12,18,40,0.55), rgba(20,28,52,0.65)),
    var(--tile-art-revealed);
  border-color: #3a4868;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.65);
}

.tile-type-hole .tile-icon-wrap {
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
}

.tile-type-hole .tile-icon-img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  border-radius: 6px;
}

body.tile-colors .tile-front.type-well {
  background-image:
    linear-gradient(145deg, rgba(0,32,48,0.78), rgba(0,56,72,0.86)),
    var(--tile-art-revealed);
  border-color: #2088aa;
  box-shadow: inset 0 3px 7px rgba(0,0,0,0.5), inset 0 0 16px rgba(0,140,200,0.25);
}
body.tile-colors .tile-front.type-anvil {
  background-image:
    linear-gradient(145deg, rgba(28,28,32,0.82), rgba(48,48,56,0.88)),
    var(--tile-art-revealed);
  border-color: #5a5a66;
}
body.tile-colors .tile-front.type-war-banner {
  background: linear-gradient(165deg, rgba(90, 30, 35, 0.55) 0%, rgba(22, 14, 18, 0.96) 100%);
  box-shadow: inset 0 0 0 1px rgba(200, 90, 90, 0.35);
}

body.tile-colors .tile-front.type-rope {
  background-image:
    linear-gradient(145deg, rgba(40,32,20,0.78), rgba(64,52,36,0.85)),
    var(--tile-art-revealed);
  border-color: #8a7048;
}

/* ── Tile states ── */

/* Revealed, resolved — block taps on “finished” tiles (damage dealt, loot taken, etc.) */
.tile.revealed {
  cursor: default;
  pointer-events: none;
}

/*
 * Long-press still needs pointer events (TileEngine wires hold on the tile root).
 * Without this, .tile.revealed’s pointer-events: none swallows all input — trap modal
 * and info cards never open for trap / gold / empty / heart / camp / rest specials.
 */
.tile.revealed.tile-type-trap,
.tile.revealed.tile-type-gold,
.tile.revealed.tile-type-heart,
.tile.revealed.tile-type-checkpoint,
.tile.revealed.tile-type-well,
.tile.revealed.tile-type-anvil,
.tile.revealed.tile-type-forge {
  pointer-events: all;
  cursor: pointer;
}

/* Open pit — tap for message / info card */
.tile.revealed.tile-type-hole {
  pointer-events: all;
  cursor: pointer;
}

/* Revealed empty floor — long-press for info only; no pointer cursor or hover lift */
.tile.revealed.tile-type-empty {
  pointer-events: all;
  cursor: default;
  /* Stack above neighbor chest/enemy faces (.tile-type-chest.revealed / .is-enemy use z-index: 4) so
     overflow sprites cannot read as “chest on this tile” (e.g. after banner → empty). */
  z-index: 5;
}

.tile.revealed.tile-type-empty:hover {
  z-index: 6;
}

/* Revealed sub-floor entry — tap to descend */
.tile.revealed.tile-type-sub_floor_entry {
  cursor: pointer;
  pointer-events: all;
}

/* Enemy war banner — visible on unrevealed tile back; tap twice when revealed to destroy */
.tile-war-banner-fly {
  position: absolute;
  left: 50%;
  top: 38%;
  transform: translate(-50%, -50%);
  font-size: clamp(1.2rem, 4.2vw, 1.75rem);
  line-height: 1;
  filter: drop-shadow(0 2px 6px rgba(0, 0, 0, 0.9));
  pointer-events: none;
  z-index: 3;
  animation: war-banner-fly 2.6s ease-in-out infinite;
}

@keyframes war-banner-fly {
  0%, 100% { transform: translate(-50%, -50%) rotate(-5deg); }
  50%       { transform: translate(-50%, -58%) rotate(5deg); }
}

.tile.revealed.war-banner-ready {
  cursor: pointer;
  pointer-events: all;
}

/* Revealed exit — second tap to descend / escape */
.tile.revealed.exit-pending {
  cursor: pointer;
  pointer-events: all;
}

/* Revealed rope — second tap to exit run with gold */
.tile.revealed.rope-pending {
  cursor: pointer;
  pointer-events: all;
}

/* Revealed chest — tap to collect loot */
.tile.revealed.chest-ready {
  cursor: pointer;
  pointer-events: all;
}

@keyframes magic-chest-pulse {
  0%, 100% { box-shadow: 0 0 8px 2px rgba(255,210,0,0.5), inset 0 0 6px rgba(255,210,0,0.15); }
  50%       { box-shadow: 0 0 18px 6px rgba(255,210,0,0.85), inset 0 0 12px rgba(255,210,0,0.3); }
}

.tile-type-magic_chest.revealed.chest-ready.magic-chest-has-keys .tile-front {
  animation: magic-chest-pulse 1.6s ease-in-out infinite;
}

.tile-front.type-magic-chest .tile-label {
  text-transform: none;
  font-size: 0.4rem;
  letter-spacing: 0.25px;
  white-space: nowrap;
}

/* Magic chest: JS adds .magic-chest-opening while chest.gif plays */
@keyframes magic-chest-open-burst {
  0% { filter: brightness(1); }
  30% { filter: brightness(1.28) saturate(1.1); }
  100% { filter: brightness(1); }
}

.tile.magic-chest-opening .tile-front.type-magic-chest {
  animation: magic-chest-open-burst 1s ease-out;
}

.tile.tile-type-magic_chest.revealed.chest-ready.magic-chest-animating {
  pointer-events: none;
}

/* Revealed event tile — tap to open encounter */
.tile.revealed.event-pending {
  cursor: pointer;
  pointer-events: all;
}

/* Revealed enemy still alive — tappable in FLOOR_EXPLORE */
.tile.revealed.enemy-alive {
  cursor: pointer;
  pointer-events: all;
}

.tile.revealed.enemy-alive .tile-front {
  box-shadow: inset 0 0 10px rgba(160,0,0,0.3), 0 0 6px rgba(140,0,0,0.2);
}

/* Combat commitment — player is locked in with this enemy (melee / ambush / ability) */
.tile.combat-engaged {
  position: relative;
  z-index: 3;
  outline: 3px solid #e02020;
  outline-offset: -2px;
  border-radius: inherit;
  box-shadow:
    0 0 0 1px rgba(40, 0, 0, 0.5),
    0 0 14px rgba(220, 40, 40, 0.75);
}

.tile.combat-engaged .tile-front {
  box-shadow:
    inset 0 0 14px rgba(200, 30, 30, 0.45),
    0 0 10px rgba(200, 40, 40, 0.5);
}

/* Active combat — enemy tile tappable (tap = fight action) */
.tile.active-combat {
  pointer-events: all !important;
  cursor: pointer;
}

.tile.active-combat .tile-front {
  box-shadow:
    inset 0 0 18px rgba(220,0,0,0.35),
    0 0 12px rgba(200,0,0,0.4);
  animation: pulse-danger 0.9s ease-in-out infinite;
}

/* Locked tile — X overlay handles the visual; just block interaction */
.tile.locked {
  pointer-events: none;
  cursor: not-allowed;
}

.tile.locked .tile-back {
  border-color: #1a1a24;
}

/* Engineer turret placement + deployed marker */
#grid-container.engineer-place-mode {
  cursor: crosshair;
}

.tile.engineer-turret {
  outline: 2px solid rgba(90, 160, 255, 0.95);
  outline-offset: -2px;
  pointer-events: all;
  cursor: pointer;
}

.tile.engineer-turret-tesla {
  outline-color: rgba(180, 120, 255, 0.95);
}

/* Tesla perimeter — always visible in Tesla mode */
.tile.turret-perimeter {
  outline: 2px solid rgba(180, 120, 255, 0.85);
  outline-offset: -2px;
}

.tile.turret-perimeter .tile-back,
.tile.turret-perimeter .tile-front {
  box-shadow: inset 0 0 10px 2px rgba(160, 80, 255, 0.35);
}

/* Turret sprite + stats overlay */
.turret-overlay {
  position: absolute;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  pointer-events: none;
  z-index: 3;
}

.turret-sprite {
  width: 70%;
  height: auto;
  object-fit: contain;
  flex: 1;
  min-height: 0;
}

.turret-level-badge {
  position: absolute;
  top: 3px;
  left: 4px;
  font-size: 0.55rem;
  font-weight: 700;
  color: #fff;
  background: rgba(0, 0, 0, 0.65);
  border-radius: 3px;
  padding: 1px 3px;
  line-height: 1;
  letter-spacing: 0.03em;
}

/* ── Sub-floor tile types ───────────────────────────────────── */
.tile-type-sub_floor_entry .tile-front,
.tile-type-sub_floor_entry .tile-face,
.tile-front.type-sub-floor-entry {
  background: url('../assets/ui/subfloor-entry.png') center/cover no-repeat;
}
.tile-type-stairs_up .tile-face,
.tile-type-stairs_up.tile-front,
.tile-front.type-stairs-up {
  background: url('../assets/ui/subfloor-stairs-up.png') center/cover no-repeat;
}
/* Sub-floor unrevealed tile back — alternating variants */
.sub-floor-grid .tile-back {
  background: url('../assets/ui/subfloor-tile-back-1.png') center/cover no-repeat;
}
.sub-floor-grid .tile:nth-child(2n) .tile-back {
  background: url('../assets/ui/subfloor-tile-back-2.png') center/cover no-repeat;
}

/*
 * Sub-floor pointer-events override.
 * The main .tile.revealed rule blocks all taps (main grid handles interactivity
 * per-type via more-specific selectors). In the sub-floor every revealed tile
 * must stay tappable — the JS router (_onSubFloorTileTap) decides what each tap
 * does. Slain tiles (.sf-tile-slain added by markSubFloorTileSlain) are the only
 * exception: nothing to do on a defeated enemy.
 */
.sub-floor-grid .tile.revealed {
  pointer-events: all;
  cursor: pointer;
}
.sub-floor-grid .tile.sf-tile-slain {
  pointer-events: none !important;
  cursor: default;
}
