/* The shelf (web/shelf.js; docs/UI_GUIDE.md, Screen sizes): the viewer's hand, drawn by the shell.
   shelf.js sets on .tray: --w, --h (a card's size), --tuck (the part of the fan below the window's
   edge); on each .tray-card: --x, --y (its place, raised by the focus or the lift), --r (its turn),
   --s (its scale), and --ex, --ey (where a card dealt in comes from). Amber only for what can be
   played now: a playable card's edge, the lifted card, its places on the board, the cord. */

.tray { --tray-move: calc(150ms * var(--gc-motion)); }
.tray[hidden] { display: none; }
.tray, .tray * { touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; }

/* Tablets and desktops: a fan along the bottom of the board, over it (and its windows), under the
   decision card. Only the cards take the pointer: the board stays pannable around them. */
.tray.fan { position: absolute; z-index: 25; bottom: calc(var(--safe-b) + var(--tray-base, 0px) - var(--tuck, 0px)); height: calc(var(--h) * 1.45 + 24px);
            pointer-events: none; }
.tray.fan .tray-track { position: absolute; inset: 0; }

/* Phones (and a portrait tablet): a flat row, the sheet's first thing; it scrolls when the cards
   can't overlap enough to fit (each keeps 44 px or more to tap). */
.tray.row { position: relative; margin: 0 -14px 4px; height: calc(var(--h) * 1.12 + 14px); overflow-x: auto; overflow-y: hidden;
            scrollbar-width: none; overscroll-behavior: contain; }
.tray.row::-webkit-scrollbar { display: none; }
.tray.row .tray-track { position: relative; height: 100%; min-width: 100%; }

/* The same hand while the sheet is folded (a bot's or another player's turn): a strip of small
   cards on the sheet, above its handle, their lower part tucked in (about 46 px of the board). */
.tray.folded { position: relative; flex: none; height: calc(var(--h) * .6 + 6px); overflow-x: auto; overflow-y: hidden;
              scrollbar-width: none; overscroll-behavior: contain; border-bottom: 1px solid var(--gc-rule); }
.tray.folded::-webkit-scrollbar { display: none; }
.tray.folded .tray-track { position: relative; height: 100%; min-width: 100%; }
.tray.folded .tray-card { bottom: calc(var(--h) * -.4); }
.tray.folded .tray-face { box-shadow: 0 0 0 1px var(--gc-rule-strong), 0 2px 6px rgba(0, 0, 0, .4); }

.tray-card { position: absolute; left: 50%; bottom: 4px; width: var(--w); height: var(--h); margin-left: calc(var(--w) / -2);
             transform-origin: 50% 100%; transform: translate(var(--x, 0px), var(--y, 0px)) rotate(var(--r, 0deg)) scale(var(--s, 1));
             transition: transform var(--tray-move) var(--gc-ease-out), opacity var(--gc-dur-quick) var(--gc-ease-out);
             pointer-events: auto; }
.tray.fan .tray-card { bottom: 0; }
.tray-card.entering { transition: none; opacity: 0;
                      transform: translate(calc(var(--x, 0px) + var(--ex, 0px)), calc(var(--y, 0px) + var(--ey, 0px))) rotate(9deg) scale(.7); }
.tray-card.dealing { transition-duration: var(--gc-dur-slow), var(--gc-dur-base); }
.tray-card.leaving { opacity: 0; pointer-events: none; transform: translate(var(--x, 0px), calc(var(--y, 0px) + 36px)) scale(.9);
                     transition-duration: calc(.3s * var(--gc-motion)); }
.tray-card.taken { visibility: hidden; }

/* The card itself: a button with the card's art. */
.tray-face { all: unset; box-sizing: border-box; display: block; width: 100%; height: 100%; overflow: hidden; cursor: pointer;
             border-radius: var(--gc-tray-radius, var(--gc-r-m)); background: var(--gc-panel);
             box-shadow: 0 0 0 1px var(--gc-rule-strong), 0 6px 16px rgba(0, 0, 0, .42);
             transition: box-shadow var(--gc-dur-quick) var(--gc-ease-out), filter var(--gc-dur-quick) var(--gc-ease-out); }
.tray-face img, .tray-face > svg { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.tray-text { display: grid; place-items: center; height: 100%; padding: 8px; text-align: center; font-size: 12.5px; color: var(--gc-text); }
.tray-face:focus-visible { outline: 2px solid var(--gc-signal); outline-offset: 3px; }
/* Not playable now: dimmed (still there to look at and hold to zoom). Playable: a thin amber edge. */
.tray-card.idle .tray-face { filter: saturate(.6) brightness(.74); cursor: default; }
/* (--gc-tray-radius, --gc-tray-can, -attn, -sel: a game's own corners and edges for its cards) */
.tray-card.can .tray-face { box-shadow: var(--gc-tray-can, 0 0 0 1.5px var(--gc-signal)), 0 6px 16px rgba(0, 0, 0, .42); }
.tray-card.attention .tray-face { animation: tray-breathe 1.6s ease-in-out infinite; }
@keyframes tray-breathe { 50% { box-shadow: var(--gc-tray-attn, 0 0 0 2.5px var(--gc-signal), 0 0 18px var(--gc-signal-soft)), 0 6px 16px rgba(0, 0, 0, .42); } }
/* Lifted: an amber edge and a halo. */
.tray-card.sel .tray-face { box-shadow: var(--gc-tray-sel, 0 0 0 3px var(--gc-signal), 0 0 0 5px rgba(0, 0, 0, .5), 0 0 22px var(--gc-signal-soft)), 0 12px 24px rgba(0, 0, 0, .5); }
.tray-card.carried .tray-face { opacity: .35; }
[data-motion="reduced"] .tray-card.attention .tray-face { animation: none; box-shadow: 0 0 0 2.5px var(--gc-signal), 0 6px 16px rgba(0, 0, 0, .42); }

/* The card above a finger scrubbing the row. */
.tray-peek { position: fixed; z-index: 62; pointer-events: none; border-radius: var(--gc-r-l); overflow: hidden;
             box-shadow: 0 0 0 1px var(--gc-rule-strong), var(--gc-shadow); }
.tray-peek[hidden] { display: none; }
.tray-peek .tray-face { border-radius: 0; box-shadow: none; filter: none; }

/* A card on its way (a ghost of it), a card carried. */
.tray-ghost, .tray-carry { position: fixed; z-index: 62; margin: 0; pointer-events: none; border-radius: var(--gc-tray-radius, var(--gc-r-m));
                           box-shadow: 0 18px 36px rgba(0, 0, 0, .5), 0 4px 10px rgba(0, 0, 0, .35); }
.tray-carry { left: 0; top: 0; will-change: transform; }
body.tray-dragging, body.tray-dragging * { cursor: grabbing !important; }

/* The cord from a card to the pointer; its cap brightens over a place the card can go. */
.tray-tether { position: fixed; inset: 0; width: 100vw; height: 100vh; z-index: 62; pointer-events: none; overflow: visible; }
.tt-shadow { fill: none; stroke: rgba(0, 0, 0, .42); stroke-width: 7; stroke-linecap: round; transform: translate(0, 3px); }
.tt-cord { fill: none; stroke: var(--gc-signal); stroke-width: 3.5; stroke-linecap: round; }
.tt-ring { fill: var(--gc-glass); stroke: var(--gc-signal); stroke-width: 2.5; }
.tt-arrow { fill: var(--gc-signal); }
.tray-tether.over .tt-ring { fill: var(--gc-signal); stroke: var(--gc-text); }
.tray-tether.over .tt-arrow { fill: var(--gc-signal-ink); }

/* A lifted card's places on the board: the shell's target look (amber dashes; solid under the
   pointer). SVG ones as an outline in the effects layer, HTML ones by their own outline. */
.tray-marks .gc-target { fill: var(--gc-signal-soft); stroke: var(--gc-target-stroke, var(--gc-signal)); stroke-width: 3; stroke-dasharray: 9 6;
                         animation: march 1s linear infinite; pointer-events: none; }
.tray-marks .gc-target.over { stroke-dasharray: none; stroke-width: 4; fill: var(--gc-target-over, rgba(242, 182, 64, .3)); }
/* A game's look may mark the places by their corners instead (--gc-target-corners: inline, and
   --gc-target-stroke: transparent to drop the dashes), or draw them itself (--gc-target-outline:
   none: the outline is kept, unseen, and still takes the over class). */
.tray-marks .gc-target { display: var(--gc-target-outline, inline); }
.tray-marks .gc-target-corners { display: var(--gc-target-corners, none); fill: none; stroke: var(--gc-signal); stroke-width: 4;
                                 stroke-linecap: square; pointer-events: none; filter: drop-shadow(0 0 5px var(--gc-signal-soft)); }
.tray-marks .gc-target.over + .gc-target-corners { stroke-width: 6; }
:not(svg *).gc-target { outline: 2px dashed var(--gc-signal); outline-offset: -3px; }
:not(svg *).gc-target.over { outline-style: solid; }
[data-motion="reduced"] .tray-marks .gc-target { animation: none; }

/* What a pick from the hand does (the tray's intent, shelf.js caption()): a caption over the cards.
   A pick that loses the card (discard, trash, give, pay) in --gc-bad with a ✕; a play with the
   signal's dot; anything else (reveal, return, choose) quiet. */
.tray-intent { display: flex; align-items: center; gap: 6px; font: 600 12.5px/1.25 var(--gc-font-ui); color: var(--gc-text-2); }
.tray-intent[hidden] { display: none; }
.tray-intent::before { content: ""; flex: none; width: 7px; height: 7px; border-radius: 50%; background: var(--gc-text-3); }
.tray-intent[data-tone="play"]::before { background: var(--gc-signal); }
.tray-intent[data-tone="bad"] { color: var(--gc-bad); }
.tray-intent[data-tone="bad"]::before { content: "✕"; width: auto; height: auto; border-radius: 0; background: none; font-weight: 800; }
/* The fan: a pill over its middle card, under the cards (a card raised covers it; its own mark speaks then). */
.tray.fan .tray-intent { position: absolute; z-index: 0; left: 50%; bottom: calc(var(--h) + 10px); transform: translateX(-50%);
                         padding: var(--gc-note-pad, 5px 12px); border-radius: var(--gc-note-radius, 999px); white-space: nowrap; pointer-events: none;
                         background: var(--gc-note-bg, var(--gc-glass)); box-shadow: var(--gc-note-ring, 0 0 0 1px var(--gc-rule-strong)), var(--gc-shadow);
                         border-image: var(--gc-note-frame, none); }
html[data-corners] .tray.fan .tray-intent { font: var(--gc-note-font, 600 12.5px/1.25 var(--gc-font-ui)); text-transform: var(--gc-corner-case, none); letter-spacing: var(--gc-corner-spacing, normal); }
html[data-corners] .tray-intent::before { clip-path: var(--gc-seat-shape, none); border-radius: var(--gc-note-dot-radius, 50%); }
.tray.fan .tray-intent[data-tone="bad"] { box-shadow: 0 0 0 1.5px var(--gc-bad), var(--gc-shadow); }
/* (over the flip buttons above the cards, when there are any) */
.tray.fan:has(.tray-card > .tray-flip) .tray-intent { bottom: calc(var(--h) + 22px); }
/* The sheet's row: a line over it. */
.tray-intent:not(.tray *) { margin: 0 0 4px; }

/* A card pressed (touch: before the finger lifts), hovered, focused, lifted or dragged shows what
   picking it does. Loses it (data-tone="bad"): a red edge and glow, a veil and a ✕, the verb's badge.
   Neutral (reveal, return, choose): a light edge and the verb's badge. A play: the lift alone. */
.tray-face { position: relative; container-type: inline-size; }
/* The cards' glare, where the game asks for it (--gc-tray-glare: block): a sheen sweeping across a
   card once as it is hovered, focused or lifted (transform only), and a holographic highlight that
   follows the pointer over it (--gx, --gy, --ga from shelf.js), screened over the card. */
.tray-face:not([data-tone="bad"]):not([data-tone="neutral"])::before, .tray-face:not([data-tone="bad"]):not([data-tone="neutral"])::after { content: ""; position: absolute; inset: 0; pointer-events: none; display: var(--gc-tray-glare, none); mix-blend-mode: screen; border-radius: inherit; }
.tray-face:not([data-tone="bad"]):not([data-tone="neutral"])::before { opacity: var(--gc-tray-glare-sheen, .5); background: linear-gradient(105deg, transparent 30%, rgba(255, 255, 255, .5) 46%, rgba(255, 255, 255, .14) 55%, transparent 66%); transform: translateX(-110%); }
.tray-card:is(.focus, .sel) .tray-face:not([data-tone="bad"]):not([data-tone="neutral"])::before { animation: tray-glare 760ms cubic-bezier(.3, .6, .3, 1) both; }
@keyframes tray-glare { from { transform: translateX(-110%); } to { transform: translateX(110%); } }
.tray-face:not([data-tone="bad"]):not([data-tone="neutral"])::after { opacity: 0; transition: opacity var(--gc-dur-quick, 160ms) ease;
  background: radial-gradient(circle at var(--gx, 50%) var(--gy, 22%), rgba(255, 255, 255, .5), rgba(255, 255, 255, .14) 18%, transparent 42%),
    linear-gradient(var(--ga, 115deg), transparent 26%, rgba(255, 110, 190, .2) 38%, rgba(120, 210, 255, .24) 50%, rgba(255, 230, 130, .2) 62%, transparent 74%); }
.tray-card:is(.focus, .sel) .tray-face:not([data-tone="bad"]):not([data-tone="neutral"])::after { opacity: var(--gc-tray-glare-holo, .45); }
html[data-motion="reduced"] .tray-face:not([data-tone="bad"]):not([data-tone="neutral"])::before, html.lowpower .tray-face:not([data-tone="bad"]):not([data-tone="neutral"])::before { animation: none; display: none; }
/* (a card whose pick loses it or does something else: its marks instead, below) */
.tray-face:is([data-tone="bad"], [data-tone="neutral"])::before, .tray-face:is([data-tone="bad"], [data-tone="neutral"])::after { content: none; }
:is(.tray-card.can:is(.focus, .sel, .dragging), .tray-peek) .tray-face[data-tone="bad"] {
  box-shadow: 0 0 0 3px var(--gc-bad), 0 0 0 5px rgba(0, 0, 0, .45), 0 0 26px var(--gc-bad-soft), 0 12px 24px rgba(0, 0, 0, .5); }
:is(.tray-card.can:is(.focus, .sel, .dragging), .tray-peek) .tray-face[data-tone="bad"]::before {
  content: "✕"; position: absolute; inset: 0; display: grid; place-items: center; padding-bottom: 14%;
  font: 800 38cqw/1 var(--gc-font-ui); color: var(--gc-on-bad); background: var(--gc-bad-veil);
  text-shadow: 0 0 .14em var(--gc-bad), 0 2px 8px rgba(0, 0, 0, .55); pointer-events: none; }
:is(.tray-card.can:is(.focus, .sel, .dragging), .tray-peek) .tray-face:is([data-tone="bad"], [data-tone="neutral"])::after {
  content: attr(data-verb); position: absolute; left: 50%; bottom: 7%; transform: translateX(-50%); max-width: 88%;
  padding: 3px 9px; border-radius: 999px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; pointer-events: none;
  font: 700 11px/1.3 var(--gc-font-ui); letter-spacing: .05em; text-transform: uppercase;
  background: var(--gc-glass); color: var(--gc-text); box-shadow: 0 0 0 1px var(--gc-rule-strong), 0 2px 6px rgba(0, 0, 0, .4); }
:is(.tray-card.can:is(.focus, .sel, .dragging), .tray-peek) .tray-face[data-tone="bad"]::after {
  background: var(--gc-bad); color: var(--gc-on-bad); box-shadow: 0 2px 6px rgba(0, 0, 0, .45); }
:is(.tray-card.can:is(.focus, .sel, .dragging), .tray-peek) .tray-face[data-tone="neutral"] {
  box-shadow: 0 0 0 2.5px var(--gc-text-2), 0 0 0 4.5px rgba(0, 0, 0, .4), 0 12px 24px rgba(0, 0, 0, .5); }
/* (The strip's small cards: no marks; the larger copy above the finger has them.) */
.tray.folded .tray-face::before, .tray.folded .tray-face::after { content: none !important; }

/* While a drag is over a place with several options: their names by the pointer. */
.tray-drop-hint { position: fixed; z-index: 63; padding: 5px 12px; border-radius: 999px; pointer-events: none; white-space: nowrap;
                  font: 600 12.5px/1.25 var(--gc-font-ui); color: var(--gc-text); background: var(--gc-glass);
                  box-shadow: 0 0 0 1.5px var(--gc-signal), var(--gc-shadow); }
.tray-drop-hint[hidden] { display: none; }

/* In the decision card: the lifted card's options. */
.tray-pick { display: flex; flex-direction: column; gap: 8px; margin: 2px 0 10px; padding: 10px 12px; border-radius: var(--gc-r-m);
             background: var(--gc-panel); border: 1px solid var(--gc-rule); }
.tray-pick-head { display: flex; align-items: center; gap: 8px; }
.tray-pick-head b { flex: 1; min-width: 0; font-size: 14px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tray-pick .chips { display: flex; flex-wrap: wrap; gap: 6px; }
.tray-pick .tm-x { margin-right: 6px; }
.tray-pick .chip-btn.tone-bad { border-color: var(--gc-bad); }

/* A lifted card's own two-way choice (tray card `flip`), on its corner; a game's look through tokens. */
.tray-flip { position: absolute; top: -14px; right: -14px; z-index: 3; width: 44px; height: 48px; padding: 0; border: 0; cursor: pointer;
  display: grid; place-items: center; color: var(--gc-tray-flip-ink, var(--gc-signal-ink));
  background: var(--gc-tray-flip-bg, var(--gc-signal)); border-radius: var(--gc-tray-flip-radius, 50%);
  box-shadow: var(--gc-tray-flip-shadow, 0 2px 8px rgba(0, 0, 0, .45)); transition: transform var(--gc-dur-tap) ease; }
.tray-flip:hover { transform: scale(1.06); }
.tray-flip[aria-pressed="true"] { transform: rotate(180deg); }
.tray-flip:focus-visible { outline: 2px solid var(--gc-signal); outline-offset: 2px; }
/* The flip, on every card that has one (lifted or not): a drag handle, a slim bar just above the
   middle of the card's top edge, no icon (a phone's grabber); quiet at rest, brighter and wider under
   the pointer, filled once the card is turned. The button around it is an invisible strip touching the
   card (no gap for the pointer to fall through, which would drop the raised card), centred on the card
   unless the next card would cover it there (--step); its hit area reaches up and sideways, never down
   over the card (where a card is held to be dragged), 44 px tall on touch screens.
   --gc-tray-handle-*: a game's own colours. */
.tray-card > .tray-flip { width: 46px; height: 14px; top: -13px; right: auto; left: min(50%, calc(var(--step, 100%) - 27px)); translate: -50% 0; z-index: 4;
  border-radius: 0; background: none; box-shadow: none; color: inherit; }
.tray-card > .tray-flip svg { display: none; }
.tray-card > .tray-flip::after { content: ""; position: absolute; left: 50%; top: 50%; width: 32px; height: 4px; translate: -50% -50%; border-radius: 2px;
  background: var(--gc-tray-handle-bg, rgba(242, 240, 244, .42)); box-shadow: 0 1px 3px rgba(0, 0, 0, .5);
  transition: width var(--gc-dur-quick, 160ms) ease, background var(--gc-dur-quick, 160ms) ease; }
.tray-card > .tray-flip:hover { transform: none; }
.tray-card > .tray-flip:hover::after, .tray-card > .tray-flip:focus-visible::after { width: 40px; background: var(--gc-tray-handle-hover, rgba(242, 240, 244, .8)); }
.tray-card > .tray-flip[aria-pressed="true"] { transform: none; }
.tray-card > .tray-flip[aria-pressed="true"]::after { background: var(--gc-tray-handle-on, var(--gc-signal)); }
.tray-card > .tray-flip:focus-visible { outline: none; }
.tray-card > .tray-flip::before { content: ""; position: absolute; inset: -8px -8px 0; }
@media (pointer: coarse) { .tray-card > .tray-flip::before { inset: -30px -8px 0; } }
/* (Two-player bands held upright: the hand stands right under the near player's plate, so the flip
   sits on the middle of the card's bottom edge instead: clear of the plate, under the thumb; its hit
   area reaching down.) */
@media (max-aspect-ratio: 1/1) {
  html[data-bands] .tray-card > .tray-flip { top: auto; bottom: -13px; }
  html[data-bands] .tray-card > .tray-flip::before { inset: 0 -8px -8px; }
}
