﻿/* ===== fichas: rectangulares (esquinas rectas) ===== */
/* ── Board-tile size: ONE knob ──────────────────────────────────────────────
   Every dimension of a tile ON THE TABLE (half, pips, padding, divider, corner
   radius, cast shadow) is derived from --board-tile-scale, so a single value
   resizes the whole piece with its proportions intact. At 1 these resolve to the
   exact numbers that were hard-coded here before, so the phone/tablet canvas and
   La Esquina's ambient demo render byte-identically — the desktop game screen is
   the only place that overrides the scale (see #game.native-desktop in game.css,
   and boardTileMetrics() in tile-metrics.js, which reads this same variable so the
   snake layout's footprints and gaps follow it).
   This knob is presentation only: it never touches the chain, the placement rules
   or the layout ALGORITHM — only the size of the pieces that algorithm arranges. */
:root {
  --board-tile-scale: 1;
  /* Authored (scale-1) sizes. The multiplication deliberately happens in the rules
     that USE these, not here: a var() inside a custom property is resolved where that
     property is DECLARED, so folding the scale in at :root would freeze it at 1 and a
     deeper override of --board-tile-scale would do nothing. */
  --board-half: 32px;
  --board-pip: 7px;
  --board-tile-pad: 3px;
  --board-tile-div: 1.5px;
  --board-tile-radius: 5px;
}
/* FLAT 2D face: a soft, single drop shadow for separation from the table plus a
   hairline edge for crispness — no glossy highlight, no heavy bevel. */
.domino { display: inline-flex; flex-direction: column; background: linear-gradient(160deg, #fbf6ea, var(--ivory)); border-radius: 2px; padding: 3px; box-shadow: 0 1px 3px rgba(0,0,0,.3), inset 0 0 0 1px rgba(0,0,0,.1); }
.half { width: 36px; height: 36px; position: relative; display: grid; grid-template-columns: repeat(3, 1fr); grid-template-rows: repeat(3, 1fr); padding: 4px; gap: 1px; }
/* one vertical container, halves stacked (incl. doubles 6 over 6) â€” never side-by-side */
.domino .half:first-child { border-bottom: 2px solid var(--ivory-shade); }
.board-tile { padding: calc(var(--board-tile-pad) * var(--board-tile-scale)); }
.board-tile .half {
  width: calc(var(--board-half) * var(--board-tile-scale));
  height: calc(var(--board-half) * var(--board-tile-scale));
  padding: calc(var(--board-tile-pad) * var(--board-tile-scale));
}
.board-tile .pip {
  width: calc(var(--board-pip) * var(--board-tile-scale));
  height: calc(var(--board-pip) * var(--board-tile-scale));
}

/* Board chain — STRUCTURAL positioning (the board's layout contract).
   board.js positions every tile by setting `left`/`top` on its `.chain-tile`
   slot, which only works if the slot is absolutely positioned inside the
   absolutely-positioned chain layer. These rules MUST live with the tile
   component (tiles.css is loaded by every page that renders a board — the live
   game, La Esquina's ambient demo, and any harness) rather than in game.css,
   which the game screen loads but La Esquina does not. Without them the slots
   fall back to `position: static` and stack vertically in normal flow instead
   of following the snake path (tiles pile up at the first corner). */
.chain { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
/* The chain layer carries the board's "keep the snake on the table" pan (see
   measureViewOffset in board.js). Transitioned so that when a growing snake reaches an
   edge the view slides, instead of every tile jumping to new coordinates at once. */
/* The board's view transform lives here: a pan that keeps the snake on the table, and a
   fit factor that views a chain too big for the board from further back (see
   measureViewOffset in board.js). Both are set as one `transform`, and the origin MUST be
   the layer's top-left — board.js computes the pan from the scaled bounding box, which is
   only correct when the scale grows away from (0,0) rather than from the layer's centre.
   (With the pan alone this was moot: a translate is origin-independent.) */
.chain-layer { position: absolute; inset: 0; transform-origin: 0 0; transition: transform 320ms cubic-bezier(.25,.7,.25,1); }
@media (prefers-reduced-motion: reduce) { .chain-layer { transition: none; } }
.chain-tile { position: absolute; }

.chain-tile {
  display: flex; align-items: center; justify-content: center;
  overflow: visible;
  margin: 0; padding: 0;
  box-sizing: border-box;
}
.chain-tile .board-tile {
  position: relative; left: auto; top: auto; margin: 0; flex-shrink: 0;
  transform-origin: center center;
  /* FLAT 2D bone piece: ivory face, no diagonal sheen. Size and position are
     untouched (border-radius/background never affect the box model). */
  border-radius: calc(var(--board-tile-radius) * var(--board-tile-scale));
  background: #f9f2e2;
  /* Just a hairline edge to keep the piece crisp against the table — no highlight/
     shade bevel. The (much softer, now) cast shadow lives on the SLOT below, so it
     never rotates with the tile. No size/position change. */
  box-shadow: inset 0 0 0 1px rgba(74, 48, 20, .2);
}
/* The tile "sitting on the table": ONE soft, subtle shadow — flat 2D, not a raised
   3D bevel. Applied to the SLOT (never rotated → always points down) and scoped to
   real board slots — the fly-ghost keeps its own drop-shadow. This is also what
   visually separates adjacent dominoes so the snake stays readable, so it's kept
   (softened, not removed). Shadows never affect layout. */
.chain-layer .chain-tile {
  border-radius: calc(var(--board-tile-radius) * var(--board-tile-scale));
  box-shadow: 0 calc(2px * var(--board-tile-scale)) calc(4px * var(--board-tile-scale)) rgba(0, 0, 0, .3);
}
.chain-tile .board-tile.horiz { transform: rotate(90deg); }
.chain-tile .board-tile.flipped:not(.horiz) { transform: rotate(180deg); }
.chain-tile .board-tile.horiz.flipped { transform: rotate(90deg) rotate(180deg); }
/* Placement: a smooth drop that lands and SETTLES. The soft overshoot in the easing (…,1.12) gives
   a subtle bounce without an extra keyframe, so the transform still resolves cleanly to --bt-rest
   (the tile's oriented resting transform). Kept understated — not exaggerated. */
.board-tile.placing { animation: dropIn .46s cubic-bezier(.22, .86, .3, 1.12) both; }
/* flying tile clone (hand/panel -> table); overlay, unclipped by the board */
.fly-ghost { filter: drop-shadow(0 3px 6px rgba(0,0,0,.35)); will-change: transform; }
@keyframes dropIn {
  0%   { transform: translateY(calc(-22px * var(--board-tile-scale))) scale(1.06); opacity: 0; }
  60%  { opacity: 1; }
  100% { transform: var(--bt-rest, none); opacity: 1; }
}

/* Winning-moment hook (future Capicúa celebration) — SCAFFOLD ONLY, not triggered anywhere yet.
   Future code can add `.win-glow` to placed tiles for a stronger celebratory shine without
   redesigning the tile system. Left inert so it has zero cost until deliberately used. */
.board-tile.win-glow { animation: tileWinGlow 1.1s ease-in-out infinite; }
@keyframes tileWinGlow {
  0%, 100% { filter: none; }
  50%      { filter: drop-shadow(0 0 6px rgba(255, 216, 138, .7)); }
}
.pip { width: 6px; height: 6px; border-radius: 50%; align-self: center; justify-self: center; background: var(--pipc); box-shadow: inset 0 0 0 1px rgba(0,0,0,.2); }

/* Flat center divider between a board tile's two halves — a plain line, so the piece
   still reads as one bone with a scored line (rotates with the tile), without a
   raised/grooved 3D look. */
.board-tile .half:first-child {
  border-bottom: calc(var(--board-tile-div) * var(--board-tile-scale)) solid rgba(108, 80, 44, .42);
}
.p-tl { grid-area: 1/1; } .p-tc { grid-area: 1/2; } .p-tr { grid-area: 1/3; }
.p-ml { grid-area: 2/1; } .p-mc { grid-area: 2/2; } .p-mr { grid-area: 2/3; }
.p-bl { grid-area: 3/1; } .p-bc { grid-area: 3/2; } .p-br { grid-area: 3/3; }
