/* board.css — the diamond board.

   HOW SCALING WORKS, and why there is no per-breakpoint layout:

   The stage is one box with an aspect-ratio, sized to whatever space the shell gives it.
   Every card is positioned and sized as a PERCENTAGE of that box, so the whole board is
   resolution-independent: one geometry definition drives a phone and a desktop
   identically, and "mobile" is a consequence of the container being smaller rather than
   a separate layout that can drift out of sync.

   The diamond is tall and narrow (8 rows, 4 columns), so the stage is too — roughly
   0.37 wide for its height. That is why base.css puts the panels BESIDE the board in
   landscape: stacked above and below, a wide screen would leave the board height-starved
   with most of the width empty.

   There are NO geometry numbers in this file. Card size and stage aspect are derived
   from the layout data in config/constants.js and written onto the stage element as
   custom properties by render/board.js, so there is nothing here to drift out of sync
   with the JS. Percentages resolve against the stage because slots are absolutely
   positioned inside it.
*/

.vm-board {
  display: grid;
  place-items: center;
  min-height: 0;               /* lets the grid row actually shrink */
  min-width: 0;
  /* The dealer-draw note is positioned against this box. It is a SIBLING of the stage,
     never a child: render/board.js reconciles the stage's children by card id, and a
     non-card child there would be treated as a card that had left the board. */
  position: relative;
}

/* DURING THE DRAW ONLY, the note gets a reserved row of its own above the cards instead of
   floating over them. It never took pointer events, so it was not literally swallowing
   taps — but it sat over the bottom rows of a forty-card spread, hiding the very cards it
   was asking the player to choose between, which amounts to the same thing from the
   player's side. Reserved rather than floating: the row exists, the stage gets what is
   left, and the two cannot overlap by construction.

   Scoped to .vm-is-drawing so the board keeps its full height for the actual game — the
   note is hidden then, and reserving space for a hidden element would shrink every card
   for the whole match. */
.vm-is-drawing .vm-board {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  /* The gap has to clear HALF A CARD, not just a few pixels: the scatter centres cards on
     its own fractions with translate(-50%, -50%), so a card sitting near the top of the
     stage still extends half its own height above the stage's edge. Measured, not guessed
     — at 6px one card poked 26px into the note's row, and at 5.5vh it still did. */
  gap: clamp(56px, 11vh, 104px);
}

.vm-is-drawing .vm-draw-note {
  position: static;
  transform: none;
  order: -1;                   /* above the cards, whatever the DOM order says */
  flex: 0 0 auto;
  max-width: min(46ch, 100%);
}

.vm-is-drawing .vm-stage {
  flex: 1 1 auto;
  min-height: 0;
}

.vm-stage {
  position: relative;
  aspect-ratio: var(--vm-stage-aspect, 0.37);
  height: 100%;
  max-height: 100%;
  max-width: 100%;
  /* aspect-ratio resolves against whichever axis is constrained, so the stage stays
     inside both a short landscape viewport and a narrow portrait one without media
     queries deciding which. */
}

.vm-slot {
  position: absolute;
  /* --vm-slot-tilt is 0 for both fixed layouts and non-zero only for the dealer draw's
     tossed scatter, so this composes rather than branching. */
  transform: translate(-50%, -50%) rotate(var(--vm-slot-tilt, 0deg));
  width: var(--vm-card-w);
  height: var(--vm-card-h);
  /* left/top are set inline per slot from slotToStageFraction() */
}

/* Stacking follows reading order so overlapping cards layer downward-and-rightward,
   the way a hand of overlapping sticky notes actually sits. */
.vm-slot { z-index: var(--vm-z, 1); }

.vm-card {
  width: 100%;
  height: 100%;
  border-radius: 9px;
  filter: drop-shadow(0 2px 4px rgb(0 0 0 / 0.45));
}

.vm-card-svg { display: block; width: 100%; height: 100%; }

/* Text inside the SVG inherits the app font rather than the SVG default serif. */
.vm-card-text, .vm-card-form {
  font-family: Inter, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
}

/* Hit target. On the 20-card layout at phone width a card is around 45px wide, right at
   the comfortable-touch minimum. The slot itself must stay EXACTLY card-sized — giving it
   a min-width would stretch the card inside it — so the extra reach comes from a
   pseudo-element centred on the slot. It is not an event target itself, so a click on it
   reports the slot as event.target, which is what the delegated listener matches on. */
.vm-slot::after {
  content: '';
  position: absolute;
  inset: 50%;
  width: max(100%, 44px);
  height: max(100%, 44px);
  transform: translate(-50%, -50%);
  pointer-events: none;
}

.vm-slot.is-selectable::after { pointer-events: auto; }
.vm-slot.is-selectable { cursor: pointer; }
.vm-slot:not(.is-selectable) { pointer-events: none; }

/* Lift on hover, but only where hovering is real — on a touch screen :hover sticks after
   a tap and leaves a card looking permanently raised. */
@media (hover: hover) {
  .vm-slot.is-selectable:hover .vm-card {
    transform: translateY(-4px);
    filter: drop-shadow(0 6px 10px rgb(0 0 0 / 0.55));
  }
}

.vm-card { transition: transform 140ms ease, filter 140ms ease; }

/* The first pick. Marked by a lift AND a ring AND aria-pressed — never colour alone, and
   never by something a card's own colour could swallow. */
.vm-slot.is-selected { z-index: 999; }

.vm-slot.is-selected .vm-card {
  transform: translateY(-7px) scale(1.04);
  filter: drop-shadow(0 10px 16px rgb(0 0 0 / 0.6));
  outline: 3px solid var(--vm-accent);
  outline-offset: 2px;
  border-radius: 10px;
}

.vm-slot.is-selectable:focus-visible {
  outline: 3px solid var(--vm-accent);
  outline-offset: 3px;
  border-radius: 12px;
}

/* A face-up card rises above its neighbours, so the overlap cannot clip the word the
   player is trying to read. Driven by a class the renderer sets, not by inspecting the
   card's markup. */
.vm-slot.is-revealed { z-index: 900; }

/* ------------------------------------------------ landscape: lay the board down ----

   THE SLOT COORDINATES ARE NOT TOUCHED. `config/layouts.js` is final and load-bearing for
   the engine's tests — the 1-2-3-4-4-3-2-1 and 1-2-3-3-2-1 diamonds and their
   centre-outward refill order are the same in every orientation.

   The diamond is 8 rows tall and 4 columns wide, so upright it is about 0.36 as wide as it
   is tall. That is right on a phone and wrong on a desktop, where it leaves the board
   height-starved with empty space either side. Landscape lays it on its side so the long
   axis of the shape runs along the long axis of the screen.

   THIS IS NO LONGER A ROTATION, AND THAT IS THE FIX.

   It used to be `transform: rotate(-90deg)` on the stage with every card counter-rotated
   back. That version shipped broken: a transform changes what is painted, not what is
   measured, so the stage kept the TALL box's height in a much shorter panel. A grid item
   taller than its area is not centred, it is start-aligned — so the painted board dropped
   out of the bottom of its panel and off the screen, by up to 150px at ordinary window
   sizes, while every scrollWidth/clientWidth check went on reporting a perfect fit because
   those read the untransformed box.

   render/board.js now transposes the layout instead (config/constants.js's
   transposeLayout), so the stage's box IS the board's box in both axes and there is
   nothing left here to get out of step. The stage sizes itself the ordinary way, from the
   aspect-ratio the renderer derives, and `.vm-slot` needs no counter-rotation because
   nothing rotated in the first place. */

@media (min-width: 700px) and (min-aspect-ratio: 1 / 1) {
  /* The panel is measured so the stage can be sized against BOTH of its axes at once.
     `max-height` alone does not do this: on a box whose height comes from aspect-ratio,
     clamping the height just breaks the ratio, and the board went on overflowing a short
     panel by ~77px. Taking the min of the two candidate widths is the only form that
     satisfies both. */
  .vm-board { container-type: size; }

  .vm-stage {
    width: min(100cqw, calc(100cqh * var(--vm-stage-aspect, 1.44)));
    height: auto;
    max-width: none;
    max-height: none;
  }
}
