/* The platform's default painted affordance (docs/design/interaction-vocabulary.md → The affordance layer).
   A game that does nothing still shows its legal moves on desktop AND touch — visible affordances are the
   default a game opts out of, not a polish item it must remember (the Connect4 failure mode this fixes). A game
   restyles these markers in its own stylesheet; it never re-derives the marking.

   FLIP-SAFETY (the load-bearing constraint): the stage's snapshot() records getBoundingClientRect() of every
   [data-piece-id]/[data-container] element, so a transform baked into a keyed node at snapshot time corrupts
   that piece's travel. The marker classes below (.tat-tappable / .tat-actionable / .tat-legal-target / .tat-selected /
   .tat-focused) therefore use OUTLINE / BOX-SHADOW / OPACITY ONLY — never transform. See
   docs/design/client-animation.md → The interaction layer and tat-stage.js:snapshot. */

/* The token palette a game overrides to restyle the default paint. Each reads a CSS custom property with a
   fallback, so a game that sets --tat-target in its own sheet recolours every target without touching this one. */
:root {
    --tat-target: var(--accent-blue); /* the persistent legal-target marker — tracks the app accent (WebClientOptions.AccentBlue) */
    --tat-target-soft: color-mix(in srgb, var(--accent-blue) 28%, transparent);
    --tat-actionable: color-mix(in srgb, var(--accent-blue) 16%, transparent);
    --tat-selected: #f5c542;        /* the accumulated multi-select sources */
    --tat-selected-soft: rgba(245, 197, 66, 0.32);
    /* The two tones the focus ring is painted in. A ring only exists if it contrasts with what it is drawn on,
       and an outline is one stroke of one colour, so the choice is which of the two the board's own table
       calls for — see the block below. Both stay in the warm family the selected marker owns, so a focus ring
       never reads as the cool legal-target set. */
    --tat-focus-on-dark: #f5c542;   /* the affordance gold: 4.5-12:1 on the tables a board paints dark */
    --tat-focus-on-light: #6b4500;  /* a deep amber: 3.9-7.9:1 on the tables a board paints light or mid */
    --tat-focus: var(--tat-focus-on-dark);   /* the focus ring on the focused piece */
}

/* The focus ring on the table's half of the two canvases (docs/design/theming.md → Two canvases), stated
   beside the marker it governs and held to the selector list in ThemeColors.TableScope.

   THE RING FOLLOWS THE TABLE, NOT THE CANVAS. The shell is navy and the platform's own tabletop is pale
   (--stage-mat, app.css), so the table scope takes the deep tone: a board that paints nothing gets a ring that
   reads on the tabletop under it, and so do the two portalled cards, which are pale whatever board is behind
   them. But the mat is a game's to repaint, and a board that paints a DARK table states
   `--tat-focus: var(--tat-focus-on-dark)` beside its own --stage-mat, in the same block and for the same
   reason. Ten mats, each measured against the tone its sheet selects; the floor is 3:1, a non-text UI
   component. A new board inherits the deep tone, which is the right default for a table left as the platform
   paints it.

   Three things are asked of a board that states it, and MatFocusToneCssTests holds all three: the value NAMES
   one of the two tones above rather than inventing a third gold that happens to clear the floor; it is stated
   in the SAME RULE as the mat it was measured against, which is what makes the contrast audit's flat read of
   a cascade-less sheet a true reading rather than a convention; and it is stated ONCE, which
   ContrastAudit.EnsureUnconditional is the other half of. The declaration itself is irreducible — CSS cannot
   see a colour's luminance, and a :root-level derivation would resolve one value for a catalog of ten
   different mats — so what is shared here is the reasoning, and each board carries only its own two figures.

   The focus ring is the only marker that answers the table this way. --tat-selected keeps the gold everywhere,
   which is what separates "the piece I picked up" from "the pieces I have gathered" by hue rather than by ring
   geometry alone. */
.match-surface,
.game-room,
.rich-tip,
.rules-inspect-card {
    --tat-focus: var(--tat-focus-on-light);
}

/* Every element the player may tap, drag, or focus — the broad tap-delivery set (every entry point). Carries
   the pointer cursor; the drag layer adds a grab cursor for drag sources. This is the class the JS delivery
   selectors read (closest('.tat-tappable')), so it never narrows — narrowing the visual outline can never take
   an element out of the delivery set (#807). Outline/shadow/opacity only (no transform). */
.tat-tappable {
    cursor: pointer;
}

/* A subtle cue on the entry points — the elements a tap could begin a move with. Persistent (not hover-gated)
   so it reads on touch; faint so it never competes with the board's own art. The narrow visual set recomputed
   against the filled prefix, so a focused flow drops the outline on re-focus-only sources while keeping the
   confirm/staged element cued (#723). Outline only (no transform). */
.tat-actionable {
    outline: 1px solid var(--tat-actionable);
    outline-offset: -1px;
}

/* The keyboard focus ring on every entry point — the platform half of a contract with the games. A game that
   suppresses or outshines the actionable cue on a marked element at >= (0,2,0) specificity owns restating a
   visible focus ring for it (a same-sheet :focus-visible rule painting outline/box-shadow, or a
   :not(:focus-visible) carve-out in the suppress itself): game sheets load after this one, so their rule wins
   the tie against .tat-actionable, and a cue override that forgets the ring takes the keyboard cursor away.
   Outline only, no transition — FLIP-safe (MarkerMotionConformanceTests), and focus must land, not fade. */
.tat-tappable:focus-visible {
    outline: 3px solid var(--tat-focus);
    outline-offset: 2px;
}

/* The persistent legal-target marker: what a tap would complete the move against right now. Shown without hover
   so a touch screen sees its legal options (the whole point of the default paint). A ring via box-shadow keeps
   the element's measured rect intact (outline/shadow do not shift layout or corrupt snapshot). */
.tat-legal-target {
    box-shadow: inset 0 0 0 2px var(--tat-target), 0 0 0 2px var(--tat-target-soft);
}

/* The cue, off. A board that paints its own "you can act here" mark — Othello's pulsing dot, Connect 4's ready
   disc, Alchemy's gold ring — wants the two platform cue markers gone from underneath it, and nothing else
   about the element changed. The board says so by putting this class on the element in its own markup; it is
   the platform's class, so a game never writes the suppress and never re-derives which rings it must spare.

   THE CASCADE SLOT IS THE CONTRACT, which is what makes this one class instead of a rule per board carrying two
   :not()s. It is (0,1,0) — the lowest weight a class can have — and it sits here, so:

     - it is LATER than .tat-actionable and .tat-legal-target at equal weight, so it wins those ties and the two
       cue markers go, which is the whole of what it is for;
     - it is LOWER than .tat-tappable:focus-visible at (0,2,0), so the tab stop's ring outranks it;
     - it is EARLIER than .tat-kbd-cursor at equal weight, so the roving cursor an arrow key moves keeps its
       ring — the second ring a hand-written suppress has to remember, and the one the marking pass paints
       WITHOUT focusing anything, so no :focus-visible carve-out would have covered it;
     - it is EARLIER than .tat-selected and .tat-focused too, so a gathered source and a held piece still show.

   And it can never reach a game's own paint: every game sheet loads after this one, so a game rule meets it at
   (0,1,0) and wins the tie, at any higher weight and wins outright. The set of declarations this class can
   suppress is therefore closed by position — the platform rules above it — rather than by promise. The one
   member of that set outside this file is the resting shadow of the tactile piece treatment
   (.tat-piece--interactive, app.css, linked earlier): a board wanting both puts them on different elements,
   which is already the pair-of-boxes shape that treatment asks for.

   Reduced motion and FLIP: none of its business — it declares no transition and no transform. */
.tat-cue-off {
    outline: none;
    box-shadow: none;
}

/* The accumulated multi-select sources (Splendor's staged take): the gems the player has gathered, awaiting a
   confirm. A warm ring distinguishes them from the cool legal-target set. */
.tat-selected {
    box-shadow: inset 0 0 0 2px var(--tat-selected), 0 0 0 2px var(--tat-selected-soft);
}

/* The focus ring on the piece the player picked up — the source whose legal targets are lit. A gold ring marks
   the one focused element. Layered with box-shadow so it composes with the target marker when an element is
   both focused and a legal target. */
.tat-focused {
    box-shadow: inset 0 0 0 2px var(--tat-focus), 0 0 0 3px var(--tat-selected-soft);
}

/* The roving keyboard cursor's current target: a bright ring on the one legal target the cursor rests on,
   layered over the tat-legal-target marker. Outline-only (FLIP-safe — outline does not shift layout or corrupt
   snapshot). Enter/Space commits this target; Arrow keys move the ring to the next/previous legal target. */
.tat-kbd-cursor {
    outline: 3px solid var(--tat-focus);
    outline-offset: 1px;
}

/* Respect reduced motion / the E2E harness: no transition is set on any marker class, so this is a
   belt-and-braces guard for any future transition added to one. */
@media (prefers-reduced-motion: reduce) {
    .tat-actionable, .tat-legal-target, .tat-selected, .tat-focused {
        transition: none;
    }
}

/* The multi-select confirm/clear chrome (Splendor's staged take): a small bar rendered by the InteractionLayer
   alongside the board. The confirm is enabled only when the gathered sources match a complete move; the clear
   drops the selection. FLIP-safe: outline/box-shadow only — these are platform-owned buttons, never keyed board
   elements. */
.tat-multiselect-bar {
    display: flex;
    gap: 0.5rem;
    justify-content: center;
    padding: 0.5rem;
}

.tat-multiselect-bar__confirm,
.tat-multiselect-bar__clear {
    border: 2px solid var(--tat-target);
    border-radius: 0.5rem;
    padding: 0.4rem 1.2rem;
    font-weight: 600;
    cursor: pointer;
    background: var(--tat-target-soft);
    color: inherit;
}

.tat-multiselect-bar__confirm:not(:disabled) {
    background: var(--tat-target);
    color: var(--text-on-accent);
}

.tat-multiselect-bar__confirm:disabled,
.tat-multiselect-bar__clear:disabled {
    opacity: 0.4;
    cursor: default;
}

/* --- Menu mode: every legal move as a control -----------------------------------------------
   The panel the InteractionLayer renders when the room's moves list is open
   (docs/design/interaction-vocabulary.md → Menu mode). It is chrome floated over the room, never part of a
   board's composition — nothing here sizes against the stage's fit box, so a board's layout is untouched
   whether the list is open or shut.

   Position: fixed to the viewport rather than to the stage, because it is a dialog and the stage is a scroll
   surface a long list would ride away on. Its own scroll is capped against the viewport so the options stay
   reachable on a phone. */
.tat-move-menu__scrim {
    position: fixed;
    inset: 0;
    z-index: var(--z-room-overlay);
    background: color-mix(in srgb, var(--scrim) 30%, transparent);
}

.tat-move-menu {
    position: fixed;
    z-index: calc(var(--z-room-overlay) + 1);
    right: 1rem;
    bottom: 1rem;
    top: 4.5rem;
    width: min(22rem, calc(100% - 2rem));
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    overflow-y: auto;
    overscroll-behavior: contain;
    padding: 0.9rem;
    border-radius: 0.9rem;
    background: var(--bg-elevated);
    border: 1px solid var(--border-color);
    box-shadow: var(--shadow-lg);
    color: var(--text-primary);
}

.tat-move-menu__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
}

.tat-move-menu__title {
    margin: 0;
    font-size: 1rem;
    font-weight: 700;
}

.tat-move-menu__status {
    margin: 0;
    font-size: 0.8rem;
    color: var(--text-secondary);
}

.tat-move-menu__staged {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.45rem 0.6rem;
    border-radius: 0.5rem;
    background: var(--tat-target-soft);
}

.tat-move-menu__trail {
    margin: 0;
    font-size: 0.85rem;
    font-weight: 600;
}

.tat-move-menu__group {
    display: flex;
    flex-direction: column;
    gap: 0.35rem;
}

.tat-move-menu__heading {
    margin: 0;
    font-size: 0.78rem;
    font-weight: 700;
    letter-spacing: 0.04em;
    text-transform: uppercase;
    color: var(--text-secondary);
}

.tat-move-menu__help,
.tat-move-menu__empty,
.tat-move-menu__partial {
    margin: 0;
    font-size: 0.78rem;
    line-height: 1.35;
    color: var(--text-secondary);
}

.tat-move-menu__partial {
    padding-top: 0.5rem;
    border-top: 1px solid var(--border-color);
}

.tat-move-menu__options {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
    margin: 0;
    padding: 0;
    list-style: none;
}

/* Every control in the panel keeps the room's 44px tap floor, the same one the room's own menu rows hold. */
.tat-move-menu__pick,
.tat-move-menu__clear,
.tat-move-menu__confirm,
.tat-move-menu__close {
    min-height: var(--room-control);
    padding: 0.5rem 0.75rem;
    border-radius: 0.5rem;
    border: 1px solid var(--border-color);
    background: var(--bg-hover);
    color: var(--text-primary);
    font-size: 0.88rem;
    font-weight: 600;
    text-align: left;
    cursor: pointer;
}

.tat-move-menu__pick {
    width: 100%;
    display: flex;
    align-items: baseline;
    justify-content: space-between;
    gap: 0.5rem;
}

/* A pick that plays the whole move says so beside its name, so a keyboard player knows which press is a step and
   which is a commitment. Rendered only where the panel is mixed — where every option commits, the status line
   carries it once (MoveMenu.razor). */
.tat-move-menu__pick-note {
    flex: none;
    font-size: 0.72rem;
    font-weight: 500;
    letter-spacing: 0.02em;
    text-transform: uppercase;
    color: var(--text-secondary);
}

.tat-move-menu__pick:hover,
.tat-move-menu__clear:hover,
.tat-move-menu__confirm:hover,
.tat-move-menu__close:hover {
    border-color: var(--tat-target);
}

.tat-move-menu__confirm {
    background: var(--tat-target);
    color: var(--text-on-accent);
    text-align: center;
}

.tat-move-menu__close,
.tat-move-menu__clear {
    flex: none;
    text-align: center;
}
