/* Game-agnostic chrome for the pieces-in-motion layer that js/tat-stage.js drives for every game: the overlay
   that hosts ghosts (a piece vanishing into a lid), floating score popups, and the announcement catalog
   (sting / chapter / herald / fanfare). Every game's board relies on it, so it is a shared framework sheet, not
   a per-game one. See docs/design/client-animation.md and docs/design/treatment-rendering.md. */

/* The positioning context the overlay layer absolutely-positions itself within — held for any stage, rather
   than depending on each game's root class remembering to set it. */
[data-tat-stage] { position: relative; }

.tat-overlay {
    position: absolute;
    inset: 0;
    pointer-events: none;
    z-index: var(--z-room-overlay);
}

/* A ghost is a clone of a game piece, so it keeps that piece's own classes (e.g. .azul-tile, which sets
   position: relative). Scope its positioning under the overlay so it wins over the piece rule regardless of
   stylesheet load order; the travel offset/size are set inline by the JS.

   One modifier rides alongside and is deliberately unstyled here: .tat-ghost--arriving marks the clone the
   arrival pass flies in for a piece drawn from a concealed source (treatment-rendering.md → Arrival). Every
   other ghost is a piece leaving or crossing the board, so a game whose sheet treats a clone differently
   depending on which of those it is has no other way to tell them apart — the same hook role tat-lift-armed
   plays for the board. The platform asks nothing extra of it. */
.tat-overlay .tat-ghost {
    position: absolute;
    margin: 0;
}

/* A floating score popup, positioned in VIEWPORT coordinates. That is only correct because js/tat-stage.js
   appends it to document.body rather than to the board's overlay: `position: fixed` resolves against the
   nearest ancestor that establishes a containing block for fixed descendants, and a popup parented inside the
   board would take one from any ancestor carrying a transform, a filter, or PAINT containment — the room's
   boxes are one `contain: paint` away from silently re-anchoring every popup in the app. (`container-type` is
   not such an ancestor — measured in both engines against the controls that are; the table is on
   .game-room__fit in css/room.css. So the room's fit box, whatever containment a game asks it for, cannot
   move a popup.) Keep the body append and this rule together: either alone is wrong. */
.tat-popup {
    position: fixed;
    z-index: var(--z-room-overlay);   /* above the room (z-55): a popup is a transient flourish that may anchor to a sidebar plaque */
    font-family: var(--font-display, inherit);
    font-weight: 800;
    font-size: 1.05rem;
    text-shadow: 0 2px 6px rgba(0, 0, 0, 0.75);
    white-space: nowrap;
}
.tat-popup--gain { color: var(--stage-gain); }
.tat-popup--loss { color: var(--stage-loss); }
.tat-popup--neutral { color: #e6edf5; }
/* End-of-game bonuses (rows / columns / colours) pop in the score's own gold, a touch larger, so the
   final tally reads as a distinct celebratory burst rather than more in-play scoring. */
.tat-popup--bonus {
    color: var(--accent-gold, #f5c542);
    font-size: 1.25rem;
    text-shadow: 0 0 10px color-mix(in srgb, var(--accent-gold) 55%, transparent), 0 2px 6px rgba(0, 0, 0, 0.8);
}

/* An announcement (Flourish kind "banner"). Two independent axes ride one element: the treatment picks the
   shape — how big a moment this is — and the variant picks the colour. The base holds only what all four
   treatments share; each treatment below owns its own size, chrome and placement. The JS keyframes restate
   the centring translate as the first function of every transform, so a treatment's motion composes onto it
   rather than replacing it. */
.tat-banner {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    font-family: var(--font-display, inherit);
    font-weight: 800;
    color: #e6edf5;
    text-shadow: 0 2px 10px rgba(0, 0, 0, 0.85);
}

/* Sting — the punctuation for a move-scale moment ("Bust!", "Pass"): a centered pill that pops and fades. */
.tat-banner--sting {
    font-size: 1.4rem;
    padding: 0.4rem 1.2rem;
    border-radius: 0.75rem;
    background: rgba(0, 0, 0, 0.45);
}

/* Chapter — a structural boundary (a round turning over). A full-width band rather than a pill, because it
   punctuates the game rather than a move: the table is meant to look up from its own board. */
.tat-banner--chapter {
    left: 0;
    right: 0;
    transform: translateY(-50%);
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.15rem;
    text-align: center;
    font-size: 2rem;
    letter-spacing: 0.06em;
    padding: 1rem 1.5rem;
    background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, 0.62) 22%, rgba(0, 0, 0, 0.62) 78%, rgba(0, 0, 0, 0) 100%);
}
.tat-banner-title { display: block; }
/* The subtitle carries the detail under the headline ("Alice places first"), so it reads as supporting text:
   lighter, smaller, and in the seat's hue when the announcement names one. */
.tat-banner-subtitle {
    display: block;
    font-size: 0.95rem;
    font-weight: 600;
    letter-spacing: 0.02em;
    color: var(--tat-announce-seat, rgba(230, 237, 245, 0.78));
}

/* Herald — whose moment this is, and the only announcement addressed to one viewer rather than to the table.
   It is the largest thing the catalog says, because it marks the end of a wait: the player has been watching
   other people take their turns and has to be told the table is theirs again, over whatever else is on screen.
   It rides the overlay layer, so all that size is painted above the board without taking any part in its
   layout.

   Sized in cqw, never the viewport: the design studio renders the room inside a pane narrower than the
   browser, where a viewport-sized headline would overflow it. The overlay it rides is a direct child of the
   per-game stage root, so those cqw answer whichever container sits nearest above it — the game's own board
   container where it declares one (Stone Age's .sa, Dominion's .dom), the room's fit box where the game
   contains it (Othello), otherwise the room. A cq unit cannot name its container the way a query can, so that
   is a documented fact rather than a declared one: see theming.md → Container names. Every one of those boxes
   is inside the pane, and a share of a box inside the pane is all the clamp needs to keep the headline
   readable. Tinted with the seat's own
   palette hue and carrying a rule down its leading edge, so the colour agrees with the plaque and the log. The
   edge is held in a custom property because a variant restates it (below) to keep it out of the valence's
   border shorthand, and the two must not be able to describe different rules. */
.tat-banner--herald {
    --tat-herald-edge: 0.4rem solid var(--tat-announce-seat, #e6edf5);
    font-size: clamp(2rem, 7cqw, 4rem);
    letter-spacing: 0.04em;
    padding: 0.5rem 1.5rem 0.5rem 1.25rem;
    border-radius: 0.75rem;
    border-left: var(--tat-herald-edge);
    background: rgba(0, 0, 0, 0.62);
    color: var(--tat-announce-seat, #e6edf5);
    white-space: nowrap;
}

/* Fanfare — a claim or a milestone, in the same gold the end-of-game bonus popups speak (.tat-popup--bonus),
   larger and glowing so a celebration never reads as a penalty. */
.tat-banner--fanfare {
    font-size: 1.75rem;
    padding: 0.5rem 1.4rem;
    border-radius: 0.85rem;
    color: var(--accent-gold, #f5c542);
    background: rgba(0, 0, 0, 0.5);
    border: 1px solid color-mix(in srgb, var(--accent-gold) 45%, transparent);
    text-shadow: 0 0 14px color-mix(in srgb, var(--accent-gold) 55%, transparent), 0 2px 8px rgba(0, 0, 0, 0.8);
}

/* A banner's variant tints it to the moment's valence — a loss reads red, a gain reads green — so the
   centered callout carries the same colour language as the score popups alongside it. Orthogonal to the
   treatments above and stated after them, so equal-specificity source order lets the colour win over the
   treatment's own. */
.tat-banner--loss { color: var(--stage-loss-pale); }
.tat-banner--gain { color: var(--stage-gain-pale); }

/* The valence also fills and outlines the boxed treatments — the pill shapes whose chrome is a small block
   the text sits inside. A chapter is excluded rather than forgotten: it is a full-bleed band whose gradient
   fades to transparent at both edges, and a flat fill behind a 1px outline drawn across the whole stage would
   read as a box rather than a boundary, losing the one thing that distinguishes the treatment. Matched
   through :where(), whose own weight is zero, so each selector still counts as a single class — equal to the
   treatment rules above and later in source order, which is what lets the valence's fill win over theirs. */
:where(.tat-banner--sting, .tat-banner--herald, .tat-banner--fanfare).tat-banner--loss {
    border: 1px solid rgba(229, 62, 62, 0.5);
    background: rgba(70, 16, 16, 0.6);
}
:where(.tat-banner--sting, .tat-banner--herald, .tat-banner--fanfare).tat-banner--gain {
    border: 1px solid rgba(72, 187, 120, 0.5);
    background: rgba(16, 50, 30, 0.55);
}

/* A herald keeps its seat-tinted leading edge whatever its valence: the seat is the one thing that treatment
   exists to say, and the border shorthand above would otherwise reset the edge to the valence's hairline. Two
   classes, so it outranks the single-class valence rules whatever their order; the valence still owns the fill
   and the other three edges. */
.tat-banner--herald.tat-banner--loss,
.tat-banner--herald.tat-banner--gain {
    border-left: var(--tat-herald-edge);
}
