/* ==========================================================================
   Tarok - table, hand and CSS cards
   ==========================================================================
   Cards are drawn entirely in CSS. No images, so nothing to load, nothing to
   licence, and they scale to any size. Every card face comes from one place in
   the JS (cardFace) so real artwork can be swapped in later without touching
   layout.

   Theme: uses the platform's semantic tokens from variables.css, so the table
   follows light/dark automatically.
   ========================================================================== */

.tk {
    /* Two layers on purpose. The -base pair is the size the reader picked; --tk-card-w/h is what
       cards actually use, so a descendant can restate it as a fraction of the base and rescale
       itself AND everything inside it (pips, numerals, figures are all shares of --tk-card-w).
       That is how .tk-card--mini shrinks with one rule instead of a second set of numbers.
       It has to be done with a separate base variable rather than a scale factor: var() inside
       a custom property is substituted where the property is DECLARED, so a scale set further
       down the tree would never reach a --tk-card-w declared up here. */
    --tk-card-w-base: 4.5rem;
    --tk-card-h-base: 6.6rem;
    --tk-card-w: var(--tk-card-w-base);
    --tk-card-h: var(--tk-card-h-base);
    --tk-radius: 0.5rem;
    --tk-felt: #1f6b4a;
    --tk-felt-edge: #17543a;
    /* Traditional two colours: clubs and spades black, hearts and diamonds red. */
    --tk-black: #1a1a1a;
    --tk-red: #c0392b;
    --tk-tarok: #8a6d1f;
    --tk-tarok-bg: #fdf6e3;
    /* Card face sizes, all expressed as a share of the card width so the reader's S/M/L control
       rescales them for free - no media queries, no second set of numbers.
       Face sizes are unitless RATIOS of the card width, multiplied at the point of use. They
       cannot be pre-multiplied lengths: var() inside a custom property is substituted where the
       property is declared, so a --tk-pip-size computed here would keep the full card's width
       and refuse to shrink inside .tk-card--mini. A bare number has no var() to bake. */
    --tk-pip-ratio: 0.26;
    /* The tarok numeral is the whole face of the card, so it gets room: 0.3 of the card width
       puts XIX at ~22px at size S and ~33px at size L. It also has to be this big for the font
       to work at all - see the note by .tk-card--tarok .tk-card__corner. */
    --tk-numeral-ratio: 0.3;
}

[data-theme="dark"] .tk {
    --tk-felt: #17402f;
    --tk-felt-edge: #0f2c20;
    --tk-tarok: #d9b551;
    --tk-tarok-bg: #2a2618;
    /* Cards stay white in both themes, so the suit colours barely change; the felt and
       the gold accents are what the theme drives. */
}

/* Reader-chosen card size (S/M/L header control). Each just rescales the two card
   variables, so every card - hand, trick, talon - follows. S is the comfortable baseline;
   M and L step up for anyone who finds the default hard to read. */
.tk[data-card-size="s"] {
    --tk-card-w-base: 4.5rem;
    --tk-card-h-base: 6.6rem;
}

.tk[data-card-size="m"] {
    --tk-card-w-base: 5.7rem;
    --tk-card-h-base: 8.35rem;
}

.tk[data-card-size="l"] {
    --tk-card-w-base: 6.9rem;
    --tk-card-h-base: 10.15rem;
}

.tk-size-btn.active {
    background: var(--tk-tarok);
    border-color: var(--tk-tarok);
    color: #1a1a1a;
}

/* --------------------------------------------------------------- the table */

.tk-table {
    background: radial-gradient(ellipse at 50% 40%, var(--tk-felt) 0%, var(--tk-felt-edge) 100%);
    border-radius: 1rem;
    padding: 1.25rem;
    display: flex;
    flex-direction: column;
    gap: 1rem;
    position: relative;
    container-type: inline-size;
}

/* The watch strip: a spectator ribbon and/or a live "N watching" count, sitting at the
   very top of the felt above the contract banner. */
.tk-watch {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.5rem;
    flex-wrap: wrap;
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.75);
}

.tk-watch--spectator {
    color: #fff;
    background: rgba(0, 0, 0, 0.28);
    border: 1px solid var(--tk-tarok);
    border-radius: 999px;
    padding: 0.3rem 0.9rem;
    align-self: center;
}

.tk-watch__eye {
    font-size: 1rem;
    line-height: 1;
}

.tk-watch__label {
    font-weight: 600;
    letter-spacing: 0.02em;
}

.tk-watch__count {
    opacity: 0.85;
}

.tk-watch--spectator .tk-watch__count::before {
    content: "·";
    margin-right: 0.5rem;
    opacity: 0.6;
}

.tk-hand--empty {
    display: none;
}

/* A seat's radelci - open information at a real table, so shown on the seat. */
.tk-seat__radelc {
    display: block;
    color: var(--tk-tarok);
    font-size: 0.7rem;
    letter-spacing: 0.12em;
    line-height: 1;
    margin-top: 0.15rem;
    cursor: help;
}

/* Table chat. A drawer pinned to the right edge, sliding in over the page rather than
   beside it in the flow - so opening it never reflows the felt mid-trick, and the same
   rules give a phone a near-full-width panel.

   Lives outside the game container so a game re-render never wipes a half-typed message.

   `hidden` is reserved for "there is nobody to talk to". Open/closed is the --open class,
   because display:none would kill the transition it is supposed to animate. */
.tk-chat {
    position: fixed;
    top: 0;
    right: 0;
    /* Above .floating-widgets-stack (site.css, z-index 9998), which is emitted after this
       element in the layout and would otherwise win a tie. */
    z-index: 10000;
    width: min(23rem, 92vw);
    height: 100dvh;
    background: var(--bs-body-bg, #fff);
    border-left: 1px solid rgba(128, 128, 128, 0.3);
    box-shadow: -0.5rem 0 1.5rem rgba(0, 0, 0, 0.18);
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    transform: translateX(100%);
    visibility: hidden;
    transition: transform 0.28s ease, visibility 0.28s;
}

.tk-chat--open {
    transform: none;
    visibility: visible;
}

.tk-chat[hidden] {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .tk-chat {
        transition: none;
    }
}

/* Title row: the heading plus a close button. The drawer covers the header button that
   opened it on a narrow screen, so it needs its own way out. */
.tk-chat__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.tk-chat__title {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--tk-tarok);
}

.tk-chat__close {
    flex: 0 0 auto;
    border: 0;
    background: none;
    color: inherit;
    opacity: 0.6;
    font-size: 1.1rem;
    line-height: 1;
    padding: 0.2rem 0.4rem;
    cursor: pointer;
}

.tk-chat__close:hover,
.tk-chat__close:focus-visible {
    opacity: 1;
}

/* Full height inside the drawer, unlike the old below-the-table panel which was capped. */
.tk-chat__list {
    flex: 1 1 auto;
    min-height: 0;
    overflow-y: auto;
    display: flex;
    flex-direction: column;
    gap: 0.3rem;
    font-size: 0.85rem;
    scroll-behavior: smooth;
}

/* A short conversation sits at the BOTTOM of the tall drawer, next to the input, rather
   than stranded at the top. A flexible spacer does it; justify-content: flex-end would
   make the overflowing case unscrollable at the top in several browsers. Being a pseudo
   element it stays out of childNodes, so the DOM-trimming loop never sees it. */
.tk-chat__list::before {
    content: '';
    flex: 1 1 auto;
    min-height: 0;
}

/* Header toggle: the way into the drawer, with an unread count riding on it. */
.tk-chat-toggle {
    position: relative;
}

.tk-chat-toggle__badge {
    position: absolute;
    top: -0.35rem;
    right: -0.35rem;
    min-width: 1.05rem;
    padding: 0 0.25rem;
    border-radius: 999px;
    background: var(--bs-danger, #dc3545);
    color: #fff;
    font-size: 0.65rem;
    font-weight: 700;
    line-height: 1.05rem;
    text-align: center;
}

.tk-chat-toggle__badge[hidden] {
    display: none;
}

.tk-chat__empty {
    opacity: 0.6;
    font-style: italic;
}

.tk-chat__msg {
    display: flex;
    gap: 0.4rem;
    flex-wrap: wrap;
    line-height: 1.35;
}

.tk-chat__who {
    font-weight: 600;
    white-space: nowrap;
}

.tk-chat__who::after {
    content: ":";
}

.tk-chat__msg--mine .tk-chat__who {
    color: var(--tk-tarok);
}

/* Messages that landed while the drawer was shut. The badge says how many; this says
   which. Cleared when the drawer closes again, so the mark never goes stale. */
.tk-chat__msg--new {
    background: rgba(217, 181, 81, 0.14);
    border-left: 2px solid var(--tk-tarok);
    border-radius: 0 var(--tk-radius) var(--tk-radius) 0;
    margin-left: -0.4rem;
    padding: 0.15rem 0.35rem 0.15rem 0.4rem;
}

/* The rule drawn above the first of them: "------ NEW ------". */
.tk-chat__newline {
    display: flex;
    align-items: center;
    gap: 0.5rem;
    margin: 0.2rem 0;
    color: var(--tk-tarok);
    font-size: 0.68rem;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: 0.1em;
}

.tk-chat__newline::before,
.tk-chat__newline::after {
    content: '';
    flex: 1 1 auto;
    height: 1px;
    background: currentColor;
    opacity: 0.45;
}

/* Sits inside the name span, before its colon, so a watcher reads as "Ana (watching):". */
.tk-chat__tag {
    font-weight: 400;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    opacity: 0.65;
    margin-left: 0.3rem;
}

.tk-chat__tag::before {
    content: "(";
}

.tk-chat__tag::after {
    content: ")";
}

.tk-chat__body {
    overflow-wrap: anywhere;
    flex: 1 1 8rem;
}

.tk-chat__form {
    display: flex;
    gap: 0.5rem;
}

.tk-chat__input {
    flex: 1 1 auto;
}

/* Send is drawn as a tarok card: white face, gold bar along the top edge, and the same
   lift-on-hover as a playable card. Mirrors .tk-card / .tk-card--tarok deliberately - the
   deck is this feature's whole visual identity, and a stock Bootstrap pill looked pasted on.
   Cards stay white in both themes (see the note by .tk-card--tarok), so does this. */
.tk-chat__send {
    flex: 0 0 auto;
    position: relative;
    padding: 0.55rem 0.9rem 0.45rem;
    border: 1px solid rgba(0, 0, 0, 0.25);
    border-radius: var(--tk-radius);
    background: #fff;
    color: #1a1a1a;
    font-weight: 600;
    line-height: 1;
    letter-spacing: 0.02em;
    user-select: none;
    cursor: pointer;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.tk-chat__send::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: linear-gradient(90deg, var(--tk-tarok), #e3c273);
    border-radius: var(--tk-radius) var(--tk-radius) 0 0;
}

.tk-chat__send:hover,
.tk-chat__send:focus-visible {
    transform: translateY(-2px);
    box-shadow: 0 6px 14px rgba(0, 0, 0, 0.35);
    outline: none;
}

.tk-chat__send:active {
    transform: translateY(0);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

@media (prefers-reduced-motion: reduce) {
    .tk-chat__send {
        transition: none;
    }

    .tk-chat__send:hover,
    .tk-chat__send:focus-visible {
        transform: none;
    }
}

.tk-chat__note {
    font-size: 0.8rem;
    opacity: 0.7;
}

/* ------------------------------------------------------------ side docks */

/* Card tracker (left) and stats & hints (right): read-only companions to the felt.
   Mobile-first: both start as the exact same slide-in drawer as #tk-chat (fixed,
   translateX, own close button), just on the opposite edges and without an audience
   gate - they are useful even in a solo game against bots, so nothing here is ever
   `hidden`. On a wide-enough screen (see .tk-dock--pinned below) JS adds a second
   class that turns the same box into a permanent, non-modal panel beside the felt. */
.tk-dock {
    position: fixed;
    top: 0;
    z-index: 10000;
    /* Narrower than chat (23rem) - these panels are read-only, no input row to fit. */
    width: min(20rem, 88vw);
    height: 100dvh;
    background: var(--bs-body-bg, #fff);
    padding: 0.75rem;
    display: flex;
    flex-direction: column;
    gap: 0.6rem;
    overflow-y: auto;
    visibility: hidden;
    transition: transform 0.28s ease, visibility 0.28s;
}

.tk-dock--tracker {
    left: 0;
    border-right: 1px solid rgba(128, 128, 128, 0.3);
    box-shadow: 0.5rem 0 1.5rem rgba(0, 0, 0, 0.18);
    transform: translateX(-100%);
}

.tk-dock--hints {
    right: 0;
    border-left: 1px solid rgba(128, 128, 128, 0.3);
    box-shadow: -0.5rem 0 1.5rem rgba(0, 0, 0, 0.18);
    transform: translateX(100%);
}

.tk-dock--open {
    transform: none;
    visibility: visible;
}

.tk-dock[hidden] {
    display: none;
}

@media (prefers-reduced-motion: reduce) {
    .tk-dock {
        transition: none;
    }
}

.tk-dock__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
}

.tk-dock__title {
    font-weight: 600;
    font-size: 0.9rem;
    color: var(--tk-tarok);
}

.tk-dock__close {
    flex: 0 0 auto;
    border: 0;
    background: none;
    color: inherit;
    opacity: 0.6;
    font-size: 1.1rem;
    line-height: 1;
    padding: 0.2rem 0.4rem;
    cursor: pointer;
}

.tk-dock__close:hover,
.tk-dock__close:focus-visible {
    opacity: 1;
}

.tk-dock__empty {
    opacity: 0.6;
    font-style: italic;
    font-size: 0.85rem;
}

/* Pinned mode: on a screen wide enough that the centred .container (1320px max,
   Bootstrap's xxl cap - see header.css) leaves real margin on both sides, both docks
   sit in that margin instead of sliding over the felt. 1920px is where a 16rem dock +
   gap comfortably clears the container edge on both sides at once: half the container
   (660px) + a 1rem gap + a 16rem dock + a 1rem breathing margin from the viewport edge,
   doubled, rounds up to a full-HD-and-above breakpoint. Below it, or whenever fullscreen
   mode has removed the container's margins entirely (see body.tk-fullscreen below),
   JS never adds --pinned and the panel stays a normal drawer. */
:root {
    --tk-dock-w: 16rem;
}

@media (min-width: 1920px) {
    .tk-dock--pinned {
        position: fixed;
        top: var(--dynamic-header-offset, calc(var(--header-height, 64px) + 1rem));
        width: var(--tk-dock-w);
        height: auto;
        max-height: calc(100vh - var(--dynamic-header-offset, calc(var(--header-height, 64px) + 1rem)) - 1rem);
        border-radius: 0.75rem;
        border: 1px solid rgba(128, 128, 128, 0.25);
        box-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.12);
        transform: none;
        visibility: visible;
        transition: none;
    }

    .tk-dock--tracker.tk-dock--pinned {
        left: calc(50% - 660px - 1rem - var(--tk-dock-w));
        border-right-width: 1px;
    }

    .tk-dock--hints.tk-dock--pinned {
        right: calc(50% - 660px - 1rem - var(--tk-dock-w));
        border-left-width: 1px;
    }
}

/* Card tracker content: a stable chip grid so a card is always found in the same cell,
   whatever has been played - shape must never reshuffle mid-hand. */
/* The tracker's sections (four suit grids, the trump grid, the counts, the close button)
   stack as flex children with real breathing room between them - the panel was cramped
   when they butted straight up against each other. Scoped to the tracker so the hints
   panel keeps its own tight, dashed-separator row rhythm. */
.tk-dock--tracker .tk-dock__body {
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.tk-tracker__group {
    display: flex;
    flex-direction: column;
    gap: 0.25rem;
}

.tk-tracker__label {
    display: flex;
    align-items: center;
    font-size: 0.7rem;
    font-weight: 600;
    opacity: 0.7;
    text-transform: uppercase;
    letter-spacing: 0.04em;
}

/* The suit glyph / joker icon ahead of each group's name - full opacity and suit-tinted,
   so it reads at a glance even though the label text itself is muted. */
.tk-tracker__label-icon {
    margin-right: 0.35rem;
    font-size: 0.85rem;
    font-style: normal;
    opacity: 1;
}

.tk-tracker__label-icon--red {
    color: var(--tk-red);
}

.tk-tracker__label-icon--trump {
    color: var(--tk-tarok);
}

[data-theme="dark"] .tk-tracker__label-icon--red {
    color: #e8776a;
}

.tk-tracker__grid {
    display: grid;
    grid-template-columns: repeat(8, 1fr);
    gap: 0.2rem;
}

/* minmax(0, 1fr), not plain 1fr: a five-letter trump numeral (XVIII) has a min-content
   width wider than its share of the row, and plain 1fr would let that column swell and
   knock the whole grid out of alignment. minmax(0, ...) pins every column to an equal
   width and lets the numeral shrink to fit instead. */
.tk-tracker__grid--trump {
    grid-template-columns: repeat(11, minmax(0, 1fr));
}

/* Unlike .tk-card (real card art, deliberately white in both themes), these chips are a
   data readout, not a card face - they follow the site theme like the rest of the dock.
   Light mode: white squares, the same black/red the real cards use. Dark mode below pairs
   a dark square with LIGHT text - never reuse --tk-black on a dark chip, that pairing is
   what made clubs/spades invisible before this was theme-aware. */
.tk-tracker__chip {
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    /* The box is sized by the grid column (aspect-ratio: 1), so the numeral can grow for
       legibility without nudging the chip's footprint. */
    font-size: 0.88rem;
    font-weight: 700;
    border-radius: 0.25rem;
    border: 1px solid rgba(0, 0, 0, 0.25);
    background: #fff;
    color: var(--tk-black);
}

.tk-tracker__chip--red {
    color: var(--tk-red);
}

.tk-tracker__chip--trump {
    color: var(--tk-tarok);
    border-color: var(--tk-tarok);
}

/* Trumps carry roman numerals up to five letters wide (XVIII) in an 11-across grid, so
   they can't take the big pip-numeral size - they get their own compact size and are
   kept on a single line (the minmax grid above guarantees the box width). */
.tk-tracker__grid--trump .tk-tracker__chip {
    font-size: 0.62rem;
    letter-spacing: -0.02em;
    white-space: nowrap;
    overflow: hidden;
}

[data-theme="dark"] .tk-tracker__chip {
    background: #262626;
    border-color: rgba(255, 255, 255, 0.15);
    color: #e6e6e6;
}

[data-theme="dark"] .tk-tracker__chip--red {
    color: #e8776a;
}

[data-theme="dark"] .tk-tracker__chip--trump {
    background: #262626;
    color: var(--tk-tarok);
    border-color: var(--tk-tarok);
}

.tk-tracker__chip-icon {
    font-size: 1.05rem;
    line-height: 1;
}

/* Gone, not just dimmed - the grid must keep its shape as the hand progresses (same slot,
   same suit row, forever), so a played card empties out into a hollow dashed outline with
   a bold cross over it rather than a merely greyed-out copy of itself. Suit/trump colour
   and the K/Q/V/J figure are hidden entirely (color: transparent, inherited by the icon
   too) - once a card is gone which one it was stops mattering at a glance; the tooltip
   still has the detail. Solid colours, not opacity, for the same dark-mode reason as
   .tk-card--muted: opacity fades a light mark toward invisible on a dark page. */
.tk-tracker__chip--played {
    position: relative;
    background: transparent;
    border: 1px dashed rgba(0, 0, 0, 0.3);
    color: transparent;
}

.tk-tracker__chip--played::after {
    content: '\2715';
    position: absolute;
    inset: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 0.95rem;
    font-weight: 700;
    color: rgba(0, 0, 0, 0.4);
}

/* Restates color: transparent (not just border) - [data-theme="dark"] .tk-tracker__chip--red
   and --trump above are two-selector rules and would otherwise outrank the plain single-class
   .tk-tracker__chip--played and leave the old icon/numeral showing through in dark mode. */
[data-theme="dark"] .tk-tracker__chip--played {
    border-color: rgba(255, 255, 255, 0.3);
    color: transparent;
}

[data-theme="dark"] .tk-tracker__chip--played::after {
    color: rgba(255, 255, 255, 0.4);
}

/* The talon is shown face-up to the whole table once picked up - a card marked here is
   still live (could be played by anyone later) but no longer just "somewhere unseen".
   An inset ring rather than a new fill/border colour, so it layers over the suit/trump
   colouring instead of replacing it - the icon and its identity stay exactly as readable
   as any other unplayed card. Reuses --color-primary-500, the same token .tk-card--selected
   already uses for "flagged" cards elsewhere on this felt. */
.tk-tracker__chip--talon-seen {
    box-shadow: inset 0 0 0 2px var(--color-primary-500);
}

/* The cards still in your own hand - ringed just like the talon you took (same primary
   token, same inset ring) so your whole holding reads as one set and everything without a
   ring is, at a glance, still out with the opponents. A card that is both yours and part of
   the shown talon simply carries the one ring; the two rules paint the same colour. */
.tk-tracker__chip--mine {
    box-shadow: inset 0 0 0 2px var(--color-primary-500);
}

/* The "... left" tallies read as a curated summary panel, set apart from the card grids
   above by a hairline rule and a little inset padding rather than just sitting flush. */
.tk-tracker__counts {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
    font-size: 0.82rem;
    margin: 0;
    padding-top: 0.85rem;
    border-top: 1px solid rgba(128, 128, 128, 0.22);
}

.tk-tracker__counts dt {
    opacity: 0.75;
    display: flex;
    align-items: center;
}

.tk-tracker__counts dd {
    font-weight: 700;
    display: inline;
    margin: 0 0 0 0.3rem;
    font-variant-numeric: tabular-nums;
}

.tk-tracker__counts > div {
    display: flex;
    justify-content: space-between;
    align-items: center;
}

/* The suit glyph / joker / star ahead of each tally - full opacity and colour-keyed like
   the group headings, so a suit's count is instantly matchable to its grid above. */
.tk-tracker__count-icon {
    display: inline-flex;
    justify-content: center;
    width: 1.1rem;
    margin-right: 0.4rem;
    font-size: 0.9rem;
    font-style: normal;
    line-height: 1;
    opacity: 1;
}

.tk-tracker__count-icon--red {
    color: var(--tk-red);
}

.tk-tracker__count-icon--trump {
    color: var(--tk-tarok);
}

[data-theme="dark"] .tk-tracker__count-icon--red {
    color: #e8776a;
}

/* A full-width, thumb-sized way to dismiss the tracker from the bottom of the panel,
   where the reader ends up after scanning the tallies - the header × is small and easy
   to overshoot on a phone. */
.tk-tracker__close-btn {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 0.4rem;
    width: 100%;
    margin-top: 0.25rem;
    padding: 0.65rem 1rem;
    border: 1px solid rgba(128, 128, 128, 0.3);
    border-radius: 0.5rem;
    background: rgba(128, 128, 128, 0.08);
    color: inherit;
    font-size: 0.85rem;
    font-weight: 600;
    cursor: pointer;
    transition: background 0.15s ease, border-color 0.15s ease;
}

.tk-tracker__close-btn:hover,
.tk-tracker__close-btn:focus-visible {
    background: rgba(128, 128, 128, 0.16);
    border-color: rgba(128, 128, 128, 0.45);
}

.tk-tracker__close-btn-icon {
    font-size: 1.2rem;
    line-height: 1;
    opacity: 0.8;
}

/* Stats & hints content. */
.tk-hints__stat {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    font-size: 0.85rem;
    padding: 0.2rem 0;
    border-bottom: 1px dashed rgba(128, 128, 128, 0.2);
}

.tk-hints__stat strong {
    font-variant-numeric: tabular-nums;
}

.tk-hints__note {
    font-size: 0.8rem;
    line-height: 1.4;
    padding: 0.4rem 0.5rem;
    border-left: 2px solid var(--tk-tarok);
    background: rgba(217, 181, 81, 0.1);
    border-radius: 0 0.4rem 0.4rem 0;
}

.tk-hints__note + .tk-hints__note {
    margin-top: 0.35rem;
}

/* ------------------------------------------------------- edge dock tabs */

/* The tracker and hints toggles are pulled out of the header and pinned to the screen
   edge their drawer slides in from - tracker on the left, hints on the right - vertically
   centred, so each tab reads as the door to its panel. z-index sits just under the dock's
   10000, so when a drawer opens it slides over (and hides) its own tab. `hidden` (set by
   table.js on a table with a real opponent) still wins via display:none. */
.tk-edge-toggle {
    position: fixed;
    top: 50%;
    z-index: 9998;
    display: flex;
    align-items: center;
    justify-content: center;
    width: 2.4rem;
    height: 3.2rem;
    padding: 0;
    border: 1px solid rgba(128, 128, 128, 0.3);
    background: var(--bs-body-bg, #fff);
    color: var(--tk-tarok);
    font-size: 1.1rem;
    cursor: pointer;
    box-shadow: 0 0.25rem 0.9rem rgba(0, 0, 0, 0.18);
    transition: background 0.15s ease, border-color 0.15s ease, transform 0.15s ease;
}

/* Same guard the docks use: display:flex above would otherwise beat the UA `hidden`
   attribute, so an explicit [hidden] rule keeps table.js's gating (no tools at a table
   with a real opponent) working regardless of the cascade. */
.tk-edge-toggle[hidden] {
    display: none;
}

.tk-edge-toggle--left {
    left: 0;
    /* Round only the outer (into-the-felt) corners, drop the flush edge border - it reads
       as a tab growing out of the screen edge rather than a floating button. */
    border-left: 0;
    border-radius: 0 0.7rem 0.7rem 0;
    transform: translateY(-50%);
}

.tk-edge-toggle--right {
    right: 0;
    border-right: 0;
    border-radius: 0.7rem 0 0 0.7rem;
    transform: translateY(-50%);
}

/* A small nudge out from the edge on hover/focus - the tab leans toward you. Keeps the
   vertical centring by restating translateY. */
.tk-edge-toggle--left:hover,
.tk-edge-toggle--left:focus-visible {
    background: var(--tk-tarok);
    border-color: var(--tk-tarok);
    color: #1a1a1a;
    transform: translateY(-50%) translateX(3px);
}

.tk-edge-toggle--right:hover,
.tk-edge-toggle--right:focus-visible {
    background: var(--tk-tarok);
    border-color: var(--tk-tarok);
    color: #1a1a1a;
    transform: translateY(-50%) translateX(-3px);
}

/* Drawer open: the tab is behind its own drawer on a narrow screen, but in pinned desktop
   mode (docks in the page margin) it stays visible, so give it the active gold fill. */
.tk-edge-toggle.active {
    background: var(--tk-tarok);
    border-color: var(--tk-tarok);
    color: #1a1a1a;
}

[data-theme="dark"] .tk-edge-toggle {
    background: #1f1f1f;
    border-color: rgba(255, 255, 255, 0.18);
}

@media (max-width: 576px) {
    .tk-edge-toggle {
        width: 2.1rem;
        height: 2.9rem;
        font-size: 1rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .tk-edge-toggle {
        transition: none;
    }
}

/* The platform's feedback/support floating heart (BugReport widget, bottom-left) is not
   wanted on the game surface - it crowds the tracker tab's left edge. This stylesheet only
   loads on the tarok views, so this hides it on tarok pages alone. */
#bugreport-widget {
    display: none !important;
}

/* Leaving the table gives up your seat, so it reads as neutral until you reach for it
   and turns red under the cursor - the one destructive control in the header. */
.tk-leave:hover,
.tk-leave:focus-visible {
    background-color: var(--bs-danger, #dc3545);
    border-color: var(--bs-danger, #dc3545);
    color: #fff;
}

/* ------------------------------------------------------------- fullscreen */

/* The website builder's expand mode, borrowed wholesale: a body class hides the site
   chrome and lifts the centered container's width cap so the felt gets the whole viewport.
   Body-scoped, and this stylesheet is only registered by the three tarok views, so nothing
   here can reach another page. The tarok view nests its own .container inside the layout's
   (views/layouts/main.php), hence both selectors. */
body.tk-fullscreen header,
body.tk-fullscreen footer,
body.tk-fullscreen .breadcrumb,
body.tk-fullscreen .language-switcher-floating,
body.tk-fullscreen #section-nav,
body.tk-fullscreen #mascot-container,
body.tk-fullscreen .floating-widgets-stack,
body.tk-fullscreen .my-section-nav-trigger,
body.tk-fullscreen .my-section-nav-backdrop,
body.tk-fullscreen .my-section-nav {
    /* MySectionNavWidget (the "Profile" pill) is mounted as a layout-level sibling
       of <header>, not inside it - position: fixed, so hiding header alone misses it. */
    display: none !important;
}

body.tk-fullscreen main {
    /* body.has-sticky-header pads main to clear the now-hidden header. */
    padding-top: 0 !important;
}

body.tk-fullscreen main > .container,
body.tk-fullscreen .tk.container {
    max-width: 100% !important;
}

body.tk-fullscreen .tk.container {
    /* The page's own py-4 survives main's padding-top: 0 above (it's the .tk element's
       own padding, not main's) - fullscreen has no header to clear, so trim it down to
       a little breathing room instead of the full 1.5rem. */
    padding-top: 0.5rem !important;
}

/* Fullscreen removes the container's side margins entirely, so a pinned dock would sit
   on top of the felt instead of beside it. table.js already avoids adding --pinned in
   this state; this is the CSS-side backstop in case the class briefly lags a resize. */
body.tk-fullscreen .tk-dock--pinned {
    position: fixed;
    top: 0;
    height: 100dvh;
    max-height: none;
    border-radius: 0;
    box-shadow: -0.5rem 0 1.5rem rgba(0, 0, 0, 0.18);
    transform: translateX(100%);
    visibility: hidden;
}

body.tk-fullscreen .tk-dock--tracker.tk-dock--pinned {
    left: 0;
    right: auto;
    box-shadow: 0.5rem 0 1.5rem rgba(0, 0, 0, 0.18);
    transform: translateX(-100%);
}

body.tk-fullscreen .tk-dock--pinned.tk-dock--open {
    transform: none;
    visibility: visible;
}

.tk-seats {
    display: flex;
    justify-content: space-around;
    gap: 0.5rem;
    flex-wrap: wrap;
}

.tk-seat {
    color: #fff;
    text-align: center;
    padding: 0.4rem 0.7rem;
    border-radius: 0.5rem;
    background: rgba(0, 0, 0, 0.25);
    min-width: 6rem;
    font-size: 0.85rem;
    line-height: 1.3;
    transition: box-shadow 0.2s ease, background 0.2s ease;
}

.tk-seat--turn {
    background: rgba(255, 255, 255, 0.18);
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.55);
}

.tk-seat--you {
    font-weight: 600;
}

/* The seat playing the game, against everyone else at the table. */
.tk-seat--declarer {
    border: 1px solid var(--tk-tarok);
}

.tk-seat--declarer .tk-seat__name::before {
    content: '★ ';
    color: var(--tk-tarok);
}

/* The declarer's silent partner (4 players). Only ever styled once the engine has
   revealed the partnership - for opponents that is when the called king is played. */
.tk-seat--partner {
    border: 1px solid rgba(227, 194, 115, 0.6);
}

.tk-seat--partner .tk-seat__name::before {
    content: '🤝 ';
}

.tk-seat__name {
    display: block;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tk-seat__meta {
    display: block;
    opacity: 0.75;
    font-size: 0.75rem;
}

/* What this seat called during the auction. */
.tk-seat__bid {
    display: inline-block;
    margin-top: 0.35rem;
    padding: 0.1rem 0.5rem;
    border-radius: 999px;
    font-size: 0.75rem;
    font-weight: 600;
    line-height: 1.4;
}

/* A live bid - somebody has taken a game. */
.tk-seat__bid--bid {
    background: rgba(227, 194, 115, 0.2);
    color: var(--tk-tarok);
    border: 1px solid rgba(227, 194, 115, 0.45);
}

/* The current high bidder - the one everyone else has to beat. */
.tk-seat__bid--holder {
    background: var(--tk-tarok);
    color: #2a2205;
    border: 1px solid transparent;
}

/* Out of the auction. */
.tk-seat__bid--pass {
    background: rgba(255, 255, 255, 0.08);
    color: rgba(255, 255, 255, 0.55);
    border: 1px solid rgba(255, 255, 255, 0.15);
}

/* Who took the game. In tarok the declarer plays alone against the rest, so this is
   the first thing you need to know when you look at the table. */
.tk-contract {
    display: flex;
    align-items: baseline;
    justify-content: center;
    gap: 0.6rem;
    flex-wrap: wrap;
    color: #fff;
}

.tk-contract__game {
    font-size: 1.05rem;
    font-weight: 700;
    letter-spacing: 0.02em;
}

.tk-contract__who {
    font-size: 0.8rem;
    padding: 0.15rem 0.5rem;
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.3);
    color: var(--tk-tarok);
    border: 1px solid rgba(227, 194, 115, 0.5);
}

.tk-contract__who--you {
    background: rgba(227, 194, 115, 0.9);
    color: #2a2205;
    border-color: transparent;
    font-weight: 600;
}

/* The called king (4 players): a small label + the king's face, so everyone can see
   which king was named and watch for the partnership reveal. */
.tk-contract__king {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
}

.tk-contract__king-label {
    font-size: 0.75rem;
    color: var(--tk-tarok);
    text-transform: lowercase;
}

.tk-contract__side {
    font-size: 0.8rem;
    color: rgba(255, 255, 255, 0.85);
    font-style: italic;
}

/* --------------------------------------------- announcements + kontra chips */

/* A running read-out of what has been called and doubled, both on the felt banner and
   above the acting player's own controls. Public information, kept in view all hand. */
.tk-ann-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 0.35rem;
    align-items: center;
}

.tk-contract__ann {
    margin-left: 0.25rem;
}

.tk-ann-chip {
    font-size: 0.72rem;
    padding: 0.12rem 0.5rem;
    border-radius: 999px;
    white-space: nowrap;
    border: 1px solid transparent;
}

.tk-ann-chip--bonus {
    background: rgba(227, 194, 115, 0.9);
    color: #2a2205;
    font-weight: 600;
}

.tk-ann-chip--kontra {
    background: rgba(192, 57, 43, 0.85);
    color: #fff;
    text-transform: lowercase;
}

/* Declare step: the bonus toggles, select-then-confirm like the discard picker. */
.tk-ann-options {
    justify-content: center;
}

.tk-ann-opt--on {
    background: var(--tk-tarok);
    border-color: var(--tk-tarok);
    color: #2a2205;
    font-weight: 600;
}

/* The trick: a single centred row, cards in the order they were played. */
.tk-trick {
    display: flex;
    justify-content: center;
    align-items: flex-end;
    gap: 0.6rem;
    min-height: calc(var(--tk-card-h) + 1.5rem);
    flex-wrap: wrap;
}

.tk-trick--past .tk-card {
    opacity: 0.85;
}

.tk-trick__slot {
    text-align: center;
}

.tk-trick__seat {
    color: rgba(255, 255, 255, 0.85);
    font-size: 0.72rem;
    margin-bottom: 0.25rem;
    white-space: nowrap;
}

.tk-trick__empty {
    color: rgba(255, 255, 255, 0.55);
    font-size: 0.9rem;
    padding: 1rem;
}

/* --------------------------------------------------------------- the cards */

.tk-card {
    width: var(--tk-card-w);
    height: var(--tk-card-h);
    border-radius: var(--tk-radius);
    background: #fff;
    border: 1px solid rgba(0, 0, 0, 0.25);
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
    display: inline-flex;
    flex-direction: column;
    justify-content: space-between;
    align-items: center;
    padding: 0.3rem 0.25rem;
    font-weight: 600;
    line-height: 1;
    user-select: none;
    position: relative;
    flex: 0 0 auto;
    transition: transform 0.15s ease, box-shadow 0.15s ease;
}

.tk-card__corner {
    align-self: flex-start;
    font-size: 0.8rem;
    /* The fan shows only the left strip of a card, so the corner must never wrap or
       spill - it is the only part of an overlapped card you can actually read. */
    max-width: 100%;
    white-space: nowrap;
    overflow: hidden;
}

.tk-card__corner--bottom {
    align-self: flex-end;
    transform: rotate(180deg);
}

.tk-card__pip {
    font-size: 1.6rem;
}

/* An empty middle. A tarok carries its numeral only in the corners, so this is the spacer that
   keeps them pinned top and bottom - and the slot future tarok artwork drops into. */
.tk-card__mid {
    flex: 1 1 auto;
    align-self: stretch;
}

/* The pip field - the middle of a number card. It is the flex box's stretchy middle child,
   so it fills exactly the space between the two corner indices and a pip can never land
   under one. Positions come from PIP_LAYOUT in the JS and are percentages of THIS box, not
   of the card. */
.tk-card__pips {
    position: relative;
    flex: 1 1 auto;
    align-self: stretch;
    width: 100%;
}

.tk-card__pip-mark {
    position: absolute;
    transform: translate(-50%, -50%);
    font-size: calc(var(--tk-card-w) * var(--tk-pip-ratio));
    line-height: 1;
}

/* A real deck stands its lower-half pips on their heads - the reference photo of the 9 of
   clubs shows it plainly, stems down on top and stems up below. We can only honour that for
   clubs and diamonds. Unicode's heart and spade are very nearly each other's inverse: an
   upside-down spade has a heart's silhouette and an upside-down heart has a spade's, so
   rotating them would fill half of every spade card with black hearts and half of every
   heart card with red spades. In a game about following suit that is not cosmetic.
   Diamonds are symmetric, so the rotation there is free and costs nothing to keep uniform. */
.tk-card--clubs .tk-card__pip-mark--lower,
.tk-card--diamonds .tk-card__pip-mark--lower {
    transform: translate(-50%, -50%) rotate(180deg);
}

/* The red 1 is a single pip with the whole card to itself, and a real deck draws it large.
   Without this it would be the one rank that got SMALLER than the glyph it replaced. */
.tk-card__pips--single .tk-card__pip-mark {
    font-size: calc(var(--tk-card-w) * 0.44);
}

/* Figure cards. Font Awesome's chess set is already loaded by the layout and happens to be the
   tarok hierarchy exactly - King, Dame, Cavalier on horseback, Fant on foot - and Tabler's
   joker is the Skis, a jester's cap and bells. Being font glyphs they inherit colour, so one
   set of icons covers all sixteen courts: black for clubs and spades, red for hearts and
   diamonds, grey when muted, with no per-suit rules at all. The small pip below a court keeps
   clubs telling apart from spades; the Skis has no suit and so goes solo. */
.tk-card__figure {
    flex: 1 1 auto;
    align-self: stretch;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.05rem;
}

.tk-card__fig {
    font-size: calc(var(--tk-card-w) * 0.46);
    line-height: 1;
}

/* No suit pip underneath, so the figure can take the room it saves. */
.tk-card__figure--solo .tk-card__fig {
    font-size: calc(var(--tk-card-w) * 0.56);
}

.tk-card__figure-suit {
    font-size: calc(var(--tk-card-w) * 0.2);
    line-height: 1;
}

/* Two-colour deck: black suits and red suits. */
.tk-card--spades,
.tk-card--clubs { color: var(--tk-black); }

.tk-card--hearts,
.tk-card--diamonds { color: var(--tk-red); }

/* Taroks are white with black numerals like every other card - a real deck does not
   tint its trumps. They are marked instead by a gold bar along the top edge, which
   stays visible when the hand is fanned and the rest of the card is covered. */
.tk-card--tarok {
    background: #fff;
    color: #1a1a1a;
    border-color: rgba(0, 0, 0, 0.25);
}

.tk-card--tarok::before {
    content: '';
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    height: 4px;
    background: linear-gradient(90deg, var(--tk-tarok), #e3c273);
    border-radius: var(--tk-radius) var(--tk-radius) 0 0;
}

/* Tarok numerals are the card. Bodoni Moda 700 is a true Didone - one thick stroke, one
   hairline, flat unbracketed serifs - which is what the real Industrie und Glueck deck uses
   and why its numerals read as straight letters rather than as decoration.
   The numeral lives in the corners only; the middle is left empty for artwork. */
.tk-card--tarok .tk-card__corner {
    font-family: var(--font-family-bodoni-moda);
    font-weight: 700;
    font-size: calc(var(--tk-card-w) * var(--tk-numeral-ratio));
    /* Optical sizing is left on AUTO deliberately, and it is doing real work here. Bodoni's
       opsz axis is its stroke-contrast dial, and contrast is a trap at small sizes: a hairline
       narrower than one device pixel antialiases to pale grey or vanishes, which is exactly how
       XIX ends up looking like X|X. `auto` sets opsz from the rendered size (~16 at card size S,
       ~25 at size L), so each card size gets as much contrast as its pixels can actually carry.
       Do NOT pin this with font-variation-settings: 'opsz' - a fixed high value looks right in a
       mockup and breaks the thin strokes on the real table. */
    font-optical-sizing: auto;
    /* Bodoni gives its I generous side bearings, which is right for words and wrong for Roman
       numerals: III came out as three separate strokes with air between them rather than one
       numeral. Pulled in until the strokes group without touching. */
    letter-spacing: -0.06em;
}

/* Long numerals step down so they never clip. VIII, XIII and XVII are four glyphs; XVIII is
   five, and Bodoni is a wide face. The tighter tracking above bought enough room to keep these
   close to full size, which matters: a smaller numeral has fewer pixels to render a hairline in. */
.tk-card--num4 .tk-card__corner { font-size: calc(var(--tk-card-w) * var(--tk-numeral-ratio) * 0.9); }
.tk-card--num5 .tk-card__corner { font-size: calc(var(--tk-card-w) * var(--tk-numeral-ratio) * 0.8); }

/* Skis, Mond and Pagat - the trula. Worth 5 each and worth spotting. */
.tk-card--honour {
    box-shadow: 0 0 0 2px var(--tk-tarok), 0 1px 4px rgba(0, 0, 0, 0.4);
}

/* A slightly reduced card for reference displays like the talon strip. It renders exactly the
   same content as a full card - pip field, court figure, corner numeral - so it stays readable;
   0.55 was small enough that a card became a suit glyph and nothing else. Every size inside it
   is a share of --tk-card-w, so scaling the box scales the contents with it. */
.tk-card--mini {
    --tk-card-w: calc(var(--tk-card-w-base) * 0.82);
    --tk-card-h: calc(var(--tk-card-h-base) * 0.82);
    padding: 0.2rem 0.2rem;
    border-radius: 0.4rem;
}

.tk-card--mini .tk-card__corner--bottom { display: none; }

/* -------------------------------------------------- the talon on the table */

/* A slim reference strip pinned at the top of the felt. Stays put whatever the trick
   area does below it. */
.tk-talon-strip {
    display: flex;
    align-items: center;
    justify-content: center;
    flex-wrap: wrap;
    gap: 0.5rem;
    padding-bottom: 0.6rem;
    margin-bottom: 0.2rem;
    border-bottom: 1px solid rgba(255, 255, 255, 0.08);
}

.tk-talon-strip__label {
    color: rgba(255, 255, 255, 0.7);
    font-size: 0.75rem;
    font-weight: 600;
}

.tk-talon-strip__group {
    display: flex;
    align-items: center;
    gap: 0.15rem;
    padding: 0.25rem;
    border-radius: 0.45rem;
    position: relative;
}

/* The group the declarer picked up - highlighted, and labelled with who took it. */
.tk-talon-strip__group--taken {
    background: rgba(227, 194, 115, 0.18);
    border: 1px solid rgba(227, 194, 115, 0.55);
}

/* The rest went to the opponents. */
.tk-talon-strip__group--rejected {
    opacity: 0.55;
    border: 1px solid transparent;
}

.tk-talon-strip__who {
    color: var(--tk-tarok);
    font-size: 0.65rem;
    font-weight: 600;
    white-space: nowrap;
    margin-left: 0.15rem;
}

/* On a phone the revealed talon must stay the small reference it is. The plain mini sizes off
   --tk-card-w-base, which skips the phone shrink applied to .tk, so the mini ends up BIGGER
   than the hand on mobile. Pin it small here (mobile only - desktop keeps the normal mini).
   Contents follow since they are shares of --tk-card-w. (0,2,0) beats .tk-card--mini (0,1,0). */
@media (max-width: 48rem) {
    .tk-talon-strip .tk-card {
        --tk-card-w: 2.7rem;
        --tk-card-h: 4rem;
    }
}

/* --------------------------------------------------- trick -> winner animation */

/* A completed trick is held on screen, then the cards fly to the seat that won it.
   Without this the bots resolve a whole trick inside one request and you never see
   what was played. The transform is set inline in JS from the winning seat's real
   position, so it works whatever the layout does. */
.tk-card--flying {
    /* Duration must match FLIGHT_MS in web/js/tarok/table.js. The fade is held back so
       the cards stay readable for most of the journey instead of vanishing at once. */
    transition: transform 0.7s cubic-bezier(0.4, 0, 0.2, 1), opacity 0.7s ease-in 0.2s;
    opacity: 0;
    z-index: 20;
}

.tk-trick__slot--winner .tk-card {
    box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.85), 0 4px 10px rgba(0, 0, 0, 0.45);
}

/* --------------------------------------------------- card drop-in (a card played) */

/* When a card lands in the centre pile it drops onto the felt rather than teleporting
   in. Direction reads who played it: your own card rises from your hand below the felt;
   every opponent's falls in from the seat row above. Duration ~360ms - long enough to
   register, short enough to keep play brisk even when a solo table's bot replies cascade
   in (each later card gets an inline animation-delay from JS). */
.tk-card--drop {
    animation-duration: 0.42s;
    animation-timing-function: cubic-bezier(0.2, 0.7, 0.3, 1);
    animation-fill-mode: both;
    z-index: 15;
}

.tk-card--drop-self {
    animation-name: tk-drop-self;
}

.tk-card--drop-other {
    animation-name: tk-drop-other;
}

/* Your card travels a long way up from the hand at the bottom of the screen, so the rise
   is generous - it should clearly read as coming from your own cards. */
@keyframes tk-drop-self {
    from {
        opacity: 0;
        transform: translateY(90px) scale(1.18);
    }
    55% {
        opacity: 1;
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1);
    }
}

/* Opponents' cards fall in from the seat row above the felt. */
@keyframes tk-drop-other {
    from {
        opacity: 0;
        transform: translateY(-80px) scale(1.18) rotate(-6deg);
    }
    55% {
        opacity: 1;
    }
    to {
        opacity: 1;
        transform: translateY(0) scale(1) rotate(0);
    }
}

/* Reduced motion: keep the reveal, drop the travel. The card still fades up in place so
   a new play is not silent, but nothing slides across the felt. */
@media (prefers-reduced-motion: reduce) {
    .tk-card--drop {
        animation-name: tk-drop-fade;
        animation-duration: 0.2s;
    }
}

@keyframes tk-drop-fade {
    from { opacity: 0; }
    to { opacity: 1; }
}

.tk-seat--collecting {
    background: rgba(255, 255, 255, 0.3);
    box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.8);
}

/* Skis is the one tarok that prints a WORD rather than a numeral (a real Skis carries no
   number), and a word needs to be small enough to fit. Deliberately scoped to --named and
   not --honour: Pagat and Mond are in the trula too, and they now print I and XXI, which
   must keep the full numeral size. */
.tk-card--named .tk-card__corner {
    font-size: calc(var(--tk-card-w) * var(--tk-numeral-ratio) * 0.62);
    letter-spacing: -0.02em;
}

/* --------------------------------------------------------------- your hand */

.tk-hand {
    display: flex;
    /* "safe" so a fanned hand that is wider than the screen falls back to flex-start instead
       of centring: plain "center" pushes the overflow off BOTH edges and the browser cannot
       scroll to the part that spills off the left, so the first cards become unreachable. */
    justify-content: safe center;
    /* overflow-y is hidden below (it must be, to pair with overflow-x: auto), so a
       lifted/selected card and its check badge would clip at the top. Reserve room:
       max lift is 1.1rem (selected + hover) plus the badge overhangs 0.55rem above
       the card, so ~1.9rem of headroom keeps both fully visible.
       The 1.5rem side padding gives the first/last cards breathing room from the screen
       edge so they are easy to tap (a scroll container honours end padding here). */
    padding: 1.9rem 1.5rem 1.25rem;
    min-height: calc(var(--tk-card-h) + 2rem);
    flex-wrap: nowrap;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-padding-inline: 1.5rem;
    /* Break the hand out of the centred content column to the full viewport width, so the
       fanned cards (and their scroll room on a phone) get the whole screen. Standard
       full-bleed: 100vw wide, pulled back by half the gap between the column and the
       viewport edge on each side. */
    width: 100vw;
    max-width: 100vw;
    margin-left: calc(50% - 50vw);
    margin-right: calc(50% - 50vw);
}

/* Fan the hand. 16 cards will not fit side by side on a phone, so they overlap
   and the hovered/focused card lifts clear.
   The overlap is 32%, not more, and that number is load-bearing: number cards carry no corner
   index any more, so the only way to read your own hand is to count pips. The left column sits
   at 25% of the card and the centre column at 50%, and it is the centre column that separates
   7 from 8 and 9 from 10 - hide it and half your hand becomes ambiguous. Showing 68% of each
   card clears the centre column with room to spare. */
/* Only while it is your turn does the scrub own the horizontal axis: let JS see the drag
   and auto-scroll the fan itself. On other turns the hand scrolls natively so you can still
   peek at your off-screen cards. Vertical drags always fall through to page scroll. */
.tk-hand--scrub {
    touch-action: pan-y;
}

.tk-hand .tk-card {
    margin-right: calc(var(--tk-card-w) * -0.22);
}

.tk-hand .tk-card:last-child {
    margin-right: 0;
}

/* No cards left: collapse rather than leaving a card-height hole between the table and
   the score sheet. */
.tk-hand:empty {
    min-height: 0;
    padding: 0;
}

/* Live coaching line under the hand while it is your turn: "Pick a card..." then, once a
   card is armed, "Tap the highlighted card again to play it." Updated in step with a scrub
   without a full re-render (see updateHandHint). */
.tk-hand-hint {
    text-align: center;
    font-size: 0.8rem;
    color: var(--text-muted);
    padding: 0 1rem 0.5rem;
    margin-top: -0.5rem;
}

.tk-card--playable {
    cursor: pointer;
}

/* The hover lift is gated to real hovering pointers (a mouse). On touch, browsers emulate a
   sticky :hover on the last-touched card, so mid-scrub the card you started on would stay
   lifted while the card under your finger also lifts - two raised cards at once. Only the
   pick (.tk-card--selected) and keyboard focus lift on touch. */
@media (hover: hover) {
    .tk-card--playable:hover {
        transform: translateY(-0.9rem);
        box-shadow: 0 6px 14px rgba(0, 0, 0, 0.4);
        z-index: 5;
        outline: none;
    }
}

.tk-card--playable:focus-visible {
    transform: translateY(-0.9rem);
    box-shadow: 0 0 0 3px var(--color-primary-500), 0 6px 14px rgba(0, 0, 0, 0.4);
    z-index: 5;
    outline: none;
}

/* Not legal this trick: still readable, clearly not available. Showing them rather
   than hiding them is what lets a player learn the rules.
   Deliberately NOT opacity - a white card at 40% opacity over a dark page turns dark
   grey and becomes unreadable, and after a suit lead that is most of your hand. Dim
   the card's own colours instead so it stays a card. */
.tk-card--muted {
    background: #c8c8c8;
    border-color: rgba(0, 0, 0, 0.2);
    box-shadow: none;
    cursor: not-allowed;
}

/* Dimmed but still legible as black or red against the grey card. */
.tk-card--muted.tk-card--spades,
.tk-card--muted.tk-card--clubs { color: #4a4a4a; }

.tk-card--muted.tk-card--hearts,
.tk-card--muted.tk-card--diamonds { color: #9a6660; }

.tk-card--muted::before {
    opacity: 0.3;
}

.tk-card--muted.tk-card--honour {
    box-shadow: 0 0 0 2px rgba(138, 109, 31, 0.45);
}

/* --------------------------------------------------------------- prompts */

.tk-prompt {
    background: var(--bg-secondary);
    border: 1px solid var(--border-default);
    border-radius: 0.75rem;
    padding: 1rem;
}

.tk-prompt__title {
    font-weight: 600;
    margin-bottom: 0.15rem;
}

.tk-prompt__hint {
    color: var(--text-secondary);
    font-size: 0.875rem;
    margin-bottom: 0.75rem;
}

/* The 3-vs-4 players picker: two selectable cards (icon + title + description). The real
   radio is visually hidden; the label is the card, and :has(:checked) paints the choice. */
.tk-choice {
    display: flex;
    gap: 0.75rem;
}

/* Space-filler mode: the row grows to eat the leftover height in a shorter form, and its
   cards stretch with it (default align-items: stretch), so two side-by-side forms line up
   at the same bottom edge. */
.tk-choice--grow {
    flex: 1 1 auto;
}

.tk-choice__card {
    flex: 1 1 0;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin: 0;
    padding: 0.85rem 1rem;
    border: 1px solid var(--border-default);
    border-radius: 0.75rem;
    background: var(--bg-primary);
    cursor: pointer;
    transition: transform 0.15s ease, border-color 0.15s ease, box-shadow 0.15s ease, background 0.15s ease;
}

.tk-choice__input {
    position: absolute;
    width: 1px;
    height: 1px;
    opacity: 0;
    pointer-events: none;
}

.tk-choice__icon {
    flex: 0 0 auto;
    width: 2.5rem;
    height: 2.5rem;
    display: flex;
    align-items: center;
    justify-content: center;
    border-radius: 0.6rem;
    background: var(--bg-secondary);
    color: var(--text-secondary);
    font-size: 1.1rem;
    transition: background 0.15s ease, color 0.15s ease, transform 0.2s ease;
}

.tk-choice__body {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.tk-choice__title {
    font-weight: 600;
    line-height: 1.2;
}

.tk-choice__desc {
    font-size: 0.8rem;
    color: var(--text-secondary);
    line-height: 1.25;
}

.tk-choice__card:hover {
    border-color: var(--tk-tarok);
    transform: translateY(-2px);
    box-shadow: 0 6px 16px rgba(0, 0, 0, 0.18);
}

.tk-choice__card:hover .tk-choice__icon {
    transform: scale(1.08);
}

/* On phones a full-width form still leaves the two side-by-side choice cards too
   narrow (the title wraps to "3 / players"), so stack them vertically. */
@media (max-width: 480px) {
    .tk-choice {
        flex-direction: column;
    }
}

.tk-choice__card:has(.tk-choice__input:checked) {
    border-color: var(--tk-tarok);
    background: var(--tk-tarok-bg);
    box-shadow: inset 0 0 0 2px var(--tk-tarok);
}

.tk-choice__card:has(.tk-choice__input:checked) .tk-choice__icon {
    background: var(--tk-tarok);
    color: #fff;
}

/* The native radio is hidden, so surface keyboard focus on the card itself. */
.tk-choice__card:focus-within {
    outline: 2px solid var(--tk-tarok);
    outline-offset: 2px;
}

@media (max-width: 420px) {
    .tk-choice {
        flex-direction: column;
    }
}

.tk-choices {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
}

/* Picked for the discard but not yet committed. Deliberately loud - these cards are
   about to leave your hand, and the points you bury count toward your own pile. */
.tk-card--selected {
    transform: translateY(-0.75rem);
    box-shadow: 0 0 0 3px var(--color-primary-500), 0 8px 16px rgba(0, 0, 0, 0.45);
    z-index: 6;
}

.tk-card--selected::after {
    content: '✓';
    position: absolute;
    top: -0.55rem;
    right: -0.55rem;
    width: 1.4rem;
    height: 1.4rem;
    border-radius: 50%;
    background: var(--color-primary-500);
    color: #fff;
    font-size: 0.85rem;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 1px 3px rgba(0, 0, 0, 0.4);
}

@media (hover: hover) {
    .tk-card--playable.tk-card--selected:hover {
        transform: translateY(-1.1rem);
    }
}

.tk-confirm {
    display: flex;
    align-items: center;
    gap: 0.75rem;
    margin-top: 1rem;
    padding-top: 0.85rem;
    border-top: 1px solid var(--border-default);
}

.tk-confirm__count {
    font-variant-numeric: tabular-nums;
    font-weight: 600;
    color: var(--text-secondary);
}

.tk-confirm .btn:disabled {
    opacity: 0.5;
    cursor: not-allowed;
}

/* The discard grid wraps, so cards need breathing room for the lift and the tick. */
.tk-prompt .tk-choices .tk-card {
    margin: 0.6rem 0.15rem 0.2rem;
}

.tk-talon-group {
    display: flex;
    gap: 0.25rem;
    padding: 0.5rem;
    border: 2px solid var(--border-default);
    border-radius: 0.6rem;
    background: var(--bg-primary);
    cursor: pointer;
    transition: border-color 0.15s ease, transform 0.15s ease;
}

/* Talon-take: all groups on a single row whatever their size, so the whole talon reads
   at a glance. Cards are a touch larger than the default mini for readability; the row
   scrolls sideways rather than wrapping if a very narrow screen cannot hold all six. */
.tk-talon-take {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 0.85rem;
    padding: 0.35rem 0.1rem;
}

.tk-talon-take .tk-talon-group {
    flex: 0 0 auto;
    padding: 0.4rem;
}

.tk-talon-group:hover {
    border-color: var(--color-primary-500);
    transform: translateY(-2px);
}

/* --------------------------------------------------------------- log + score */

.tk-log {
    max-height: 12rem;
    overflow-y: auto;
    font-size: 0.85rem;
    color: var(--text-secondary);
}

.tk-log__line {
    padding: 0.15rem 0;
    border-bottom: 1px solid var(--border-muted);
}

/* --------------------------------------------------- end-of-hand result panel */

.tk-result__verdict {
    font-size: 1.15rem;
    font-weight: 700;
    margin: 0.4rem 0 0.15rem;
}

.tk-result__verdict--win { color: var(--color-success-600, #16a34a); }
.tk-result__verdict--lose { color: var(--color-danger-600, #dc2626); }
/* A watcher is on nobody's side, so the verdict states the fact without taking one. */
.tk-result__verdict--flat { color: var(--tk-tarok); }

.tk-result__note {
    color: var(--text-secondary);
    font-size: 0.9rem;
    margin-bottom: 0.3rem;
}

.tk-result__bars {
    margin: 0.85rem 0;
}

.tk-pts {
    display: flex;
    align-items: center;
    gap: 0.6rem;
    margin: 0.35rem 0;
}

.tk-pts__label {
    flex: 0 0 40%;
    font-size: 0.85rem;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.tk-pts__bar {
    position: relative;
    flex: 1;
    height: 0.7rem;
    background: var(--bg-tertiary);
    border-radius: 999px;
    overflow: visible;
}

.tk-pts__fill {
    height: 100%;
    border-radius: 999px;
    background: var(--text-tertiary);
    transition: width 0.4s ease;
}

/* The declarer's own bar is the one you watch against the 36 line. */
.tk-pts__fill--decl {
    background: var(--color-primary-500);
}

.tk-pts__need {
    position: absolute;
    top: -0.2rem;
    bottom: -0.2rem;
    width: 2px;
    background: var(--tk-tarok);
}

.tk-pts__val {
    flex: 0 0 auto;
    font-variant-numeric: tabular-nums;
    font-size: 0.85rem;
    font-weight: 600;
}

.tk-result__need-note {
    font-size: 0.78rem;
    color: var(--text-tertiary);
    margin-top: 0.3rem;
}

.tk-result__chips {
    display: flex;
    align-items: center;
    flex-wrap: wrap;
    gap: 0.4rem;
    margin: 0.6rem 0;
}

.tk-result__chips-label {
    font-size: 0.85rem;
    color: var(--text-secondary);
}

.tk-chip {
    padding: 0.15rem 0.55rem;
    border-radius: 999px;
    font-size: 0.8rem;
    font-weight: 600;
    background: rgba(227, 194, 115, 0.18);
    color: var(--tk-tarok);
    border: 1px solid rgba(227, 194, 115, 0.4);
}

.tk-result__sheet-head {
    margin: 0.9rem 0 0.25rem;
    font-size: 0.85rem;
    font-weight: 600;
    color: var(--text-secondary);
}

.tk-result__you {
    font-weight: 700;
}

.tk-result__you::before {
    content: '▸ ';
    color: var(--tk-tarok);
}

.tk-sheet {
    width: 100%;
    font-variant-numeric: tabular-nums;
}

.tk-sheet td {
    padding: 0.25rem 0;
    border-bottom: 1px solid var(--border-muted);
}

.tk-sheet td:last-child {
    text-align: right;
    font-weight: 600;
}

/* Full score-sheet grid: every player score column (header + deltas + totals) is
   right-aligned so the numbers line up, not just the last one. */
.tk-sheet th.tk-num,
.tk-sheet td.tk-num {
    text-align: right;
}

.tk-sheet tr:last-child td {
    border-bottom: none;
    border-top: 2px solid var(--border-default);
    font-size: 1.05rem;
}

.tk-positive { color: var(--color-success-600, #16a34a); }
.tk-negative { color: var(--color-danger-600, #dc2626); }

/* --------------------------------------------------------------- responsive */

@container (max-width: 40rem) {
    .tk-seat {
        min-width: 4.5rem;
        font-size: 0.75rem;
    }
}

@media (max-width: 36rem) {
    /* Shrink for the phone, but off the reader's S/M/L base rather than a fixed size, or the
       S/M/L control (which only moves --tk-card-w-base) would do nothing on mobile. S keeps
       the old 3.2rem look (4.5 * 0.71); M and L now step up here too. */
    .tk {
        --tk-card-w: calc(var(--tk-card-w-base) * 0.71);
        --tk-card-h: calc(var(--tk-card-h-base) * 0.71);
    }

    .tk-hand .tk-card {
        margin-right: calc(var(--tk-card-w) * -0.38);
    }

    .tk-table {
        padding: 0.75rem;
    }
}

@media (prefers-reduced-motion: reduce) {
    .tk-card,
    .tk-seat,
    .tk-talon-group {
        transition: none;
    }

    .tk-card--playable:hover {
        transform: none;
    }

    /* The trick is still HELD on screen - only the flight is removed. Skipping the
       pause as well would put the "you cannot see what was played" problem straight
       back for exactly the people least able to track fast movement. */
    .tk-card--flying {
        transition: opacity 0.2s ease;
        transform: none !important;
    }
}

/* --------------------------------------------------------- waiting room (M2) */

.tk-waiting {
    background: var(--bg-secondary);
    border: 1px solid var(--border-default);
    border-radius: 0.75rem;
    padding: 1.5rem;
    max-width: 32rem;
    margin: 0 auto;
    display: flex;
    flex-direction: column;
    gap: 1rem;
}

.tk-share {
    background: var(--bg-primary);
    border: 1px dashed var(--border-default);
    border-radius: 0.5rem;
    padding: 0.85rem 1rem;
}

.tk-share__label {
    color: var(--text-secondary);
    font-size: 0.85rem;
    margin-bottom: 0.35rem;
}

.tk-share__row {
    display: flex;
    align-items: center;
    gap: 0.75rem;
}

.tk-share__code {
    font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    font-size: 1.6rem;
    font-weight: 700;
    letter-spacing: 0.25em;
    color: var(--tk-tarok);
}

/* The direct-link row sits under the code, with its own "Or share this link" label. */
.tk-share__row + .tk-share__label {
    margin-top: 0.75rem;
}

.tk-share__link {
    flex: 1 1 auto;
    min-width: 0;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-family: ui-monospace, "SFMono-Regular", Menlo, Consolas, monospace;
    font-size: 0.85rem;
    color: var(--text-secondary);
}

.tk-share__link--tap {
    cursor: pointer;
    color: var(--tk-tarok);
}

.tk-share__row--link .btn {
    flex: 0 0 auto;
}

.tk-waiting__seats {
    display: flex;
    flex-direction: column;
    gap: 0.4rem;
}

.tk-waiting__seat {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.5rem;
    padding: 0.6rem 0.85rem;
    border: 1px solid var(--border-default);
    border-radius: 0.5rem;
    background: var(--bg-primary);
}

.tk-waiting__seat--you {
    border-color: var(--tk-tarok);
    box-shadow: inset 0 0 0 1px var(--tk-tarok);
}

.tk-waiting__seat--empty {
    border-style: dashed;
    color: var(--text-tertiary);
    background: transparent;
}

.tk-waiting__seat-name {
    font-weight: 600;
}

.tk-waiting__seat--empty .tk-waiting__seat-name {
    font-weight: 400;
    font-style: italic;
}

.tk-waiting__actions {
    display: flex;
    flex-wrap: wrap;
    gap: 0.5rem;
    align-items: center;
}

.tk-waiting__pulse {
    animation: tk-pulse 1.6s ease-in-out infinite;
}

@keyframes tk-pulse {
    0%, 100% { opacity: 0.55; }
    50% { opacity: 1; }
}

/* Presence: an absent player greys out at the table and in the waiting room. */
.tk-seat--away {
    opacity: 0.5;
}

.tk-seat__away {
    color: var(--text-tertiary);
    font-size: 0.8rem;
    font-style: italic;
}

/* "Thinking" robot next to an away human - the computer is covering their turns.
   Reuses the tk-pulse opacity keyframe (reduced-motion guarded below). */
.tk-seat__robot {
    margin-left: 0.35rem;
    color: var(--tk-tarok, #8a6d1f);
    font-size: 0.85rem;
    cursor: help;
    animation: tk-pulse 1.6s ease-in-out infinite;
}

/* Presence toasts - stacked, auto-dismissing corner notices. */
.tk-toast {
    position: fixed;
    left: 50%;
    bottom: 1.25rem;
    transform: translateX(-50%);
    z-index: 1080;
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
    align-items: center;
    pointer-events: none;
}

.tk-toast__item {
    max-width: min(90vw, 26rem);
    padding: 0.55rem 1rem;
    border-radius: 999px;
    background: var(--bg-inverse, #1a1a1a);
    color: var(--text-inverse, #fff);
    font-size: 0.9rem;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.25);
    opacity: 0;
    transform: translateY(0.5rem);
    transition: opacity 0.25s ease, transform 0.25s ease;
}

.tk-toast__item--in {
    opacity: 1;
    transform: translateY(0);
}

@media (prefers-reduced-motion: reduce) {
    .tk-seat__robot {
        animation: none;
    }
    .tk-toast__item {
        transition: none;
    }
}

/* --------------------------------------------------------------- lobby (M2) */

.tk-lobby-list {
    display: flex;
    flex-direction: column;
    gap: 0.5rem;
}

.tk-lobby-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 0.75rem;
    padding: 0.7rem 0.95rem;
    border: 1px solid var(--border-default);
    border-radius: 0.5rem;
    background: var(--bg-secondary);
}

.tk-lobby-row__main {
    display: flex;
    flex-direction: column;
    min-width: 0;
}

.tk-lobby-row__host {
    font-weight: 600;
}

.tk-lobby-row__meta {
    color: var(--text-secondary);
    font-size: 0.85rem;
}

.tk-lobby-row__join {
    margin: 0;
    flex: 0 0 auto;
}

@media (prefers-reduced-motion: reduce) {
    .tk-waiting__pulse {
        animation: none;
    }
}

/* Bot marker on a seat during play - so a computer player never passes for a human. */
.tk-seat__bot {
    color: var(--text-tertiary);
    font-size: 0.75rem;
    font-weight: 500;
    text-transform: lowercase;
}

/* Wide screens spell it out; phones show just the robot icon (below). */
.tk-seat__bot-icon {
    display: none;
}

@media (max-width: 36rem) {
    .tk-seat__bot-text {
        display: none;
    }

    .tk-seat__bot-icon {
        display: inline;
    }
}

/* Your own rooms in the lobby - accented and badged so you spot them instantly. */
.tk-lobby-row--mine {
    border-color: var(--tk-tarok);
    box-shadow: inset 0 0 0 1px var(--tk-tarok);
}

.tk-lobby-row__badge {
    display: inline-block;
    font-size: 0.7rem;
    font-weight: 600;
    text-transform: uppercase;
    letter-spacing: 0.03em;
    color: var(--tk-tarok);
    border: 1px solid var(--tk-tarok);
    border-radius: 0.35rem;
    padding: 0.05rem 0.4rem;
    vertical-align: middle;
}

/* ------------------------------------------------------------------ leaderboard
   The ranking board and the "your rank" strip. --tk-tarok is the gold accent the
   light/dark themes already drive, so the board inherits the felt look for free. */
.tk-rank-me {
    display: flex;
    align-items: baseline;
    flex-wrap: wrap;
    gap: 0.35rem 1rem;
    padding: 0.85rem 1.15rem;
    border: 1px solid var(--tk-tarok);
    border-radius: var(--tk-radius);
    background: var(--tk-tarok-bg);
}

.tk-rank-me__label {
    font-size: 0.85rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    opacity: 0.75;
}

.tk-rank-me__value {
    font-size: 1.5rem;
    font-weight: 700;
    color: var(--tk-tarok);
}

.tk-rank-me__meta {
    font-size: 0.9rem;
    opacity: 0.85;
}

.tk-board {
    --bs-table-hover-bg: rgba(138, 109, 31, 0.08);
}

.tk-board__rank {
    width: 3rem;
    text-align: center;
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
}

.tk-board__name {
    font-weight: 600;
}

.tk-board__rating {
    font-weight: 700;
    font-variant-numeric: tabular-nums;
    color: var(--tk-tarok);
}

.tk-board__you {
    display: inline-block;
    font-size: 0.7rem;
    text-transform: uppercase;
    letter-spacing: 0.04em;
    padding: 0.05rem 0.4rem;
    border: 1px solid var(--tk-tarok);
    border-radius: 0.35rem;
    color: var(--tk-tarok);
    vertical-align: middle;
}

.tk-board__row--me {
    background: var(--tk-tarok-bg);
}

.tk-board__row--me td {
    border-bottom-color: var(--tk-tarok);
}

/* ------------------------------------------------------------------ felt centre
   The middle of the felt now hosts whatever the hand asks of you: the bid/king/talon
   controls, a blinking "your turn" flag above the trick, or a quiet "waiting" line. */
.tk-center {
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 0.75rem;
    min-height: calc(var(--tk-card-h) + 2.5rem);
    width: 100%;
}

/* When the felt centre is holding the decision controls, give the box a translucent
   panel so it reads over the green felt rather than the page background. */
.tk-center--prompt .tk-prompt {
    background: rgba(0, 0, 0, 0.34);
    border-color: rgba(255, 255, 255, 0.18);
    color: #fff;
    max-width: 38rem;
    text-align: center;
    backdrop-filter: blur(2px);
}

.tk-center--prompt .tk-prompt__hint {
    color: rgba(255, 255, 255, 0.75);
}

.tk-center--prompt .tk-choices {
    justify-content: center;
}

.tk-center__waiting {
    color: rgba(255, 255, 255, 0.6);
    font-size: 0.9rem;
    font-style: italic;
}

/* The blinking call-to-act, small, sitting above the cards. */
.tk-turnflag {
    display: inline-flex;
    flex-direction: column;
    align-items: center;
    gap: 0.05rem;
    padding: 0.3rem 0.9rem;
    border: 1px solid var(--tk-tarok);
    border-radius: 999px;
    background: rgba(0, 0, 0, 0.3);
    animation: tk-turnflag-blink 1.15s ease-in-out infinite;
}

.tk-turnflag__title {
    font-weight: 700;
    font-size: 0.9rem;
    color: var(--tk-tarok);
    letter-spacing: 0.02em;
}

.tk-turnflag__hint {
    font-size: 0.72rem;
    color: rgba(255, 255, 255, 0.7);
}

@keyframes tk-turnflag-blink {
    0%, 100% { opacity: 1; box-shadow: 0 0 0 0 rgba(217, 181, 81, 0.0); }
    50% { opacity: 0.55; box-shadow: 0 0 12px 1px rgba(217, 181, 81, 0.35); }
}

@media (prefers-reduced-motion: reduce) {
    .tk-turnflag {
        animation: none;
        border-color: var(--tk-tarok);
    }
}

/* The end-of-hand scoresheet, framed on the felt like the bid controls: a translucent
   dark panel so the green shows through, with the muted greys lifted to stay legible. */
.tk-center--result {
    width: 100%;
}

.tk-center--result .tk-result {
    width: 100%;
    max-width: 34rem;
    text-align: left;
    color: #fff;
    background: rgba(10, 20, 15, 0.82);
    border-color: rgba(255, 255, 255, 0.16);
    box-shadow: 0 6px 24px rgba(0, 0, 0, 0.35);
    backdrop-filter: blur(3px);
}

.tk-center--result .tk-result__note,
.tk-center--result .tk-result__sheet-head,
.tk-center--result .tk-result__chips-label {
    color: rgba(255, 255, 255, 0.78);
}

.tk-center--result .tk-result__need-note {
    color: rgba(255, 255, 255, 0.55);
}

.tk-center--result .tk-pts__bar {
    background: rgba(255, 255, 255, 0.14);
}

.tk-center--result .tk-sheet td {
    border-bottom-color: rgba(255, 255, 255, 0.12);
}

.tk-center--result .tk-sheet tr:last-child td {
    border-top-color: rgba(255, 255, 255, 0.3);
}

/* Win/lose greens and reds pop brighter on the dark felt than the page defaults. */
.tk-center--result .tk-result__verdict--win,
.tk-center--result .tk-positive { color: #34d399; }
.tk-center--result .tk-result__verdict--lose,
.tk-center--result .tk-negative { color: #f87171; }

/* ---- "Wilder" discard on the felt: gold selection, springy hover, a live confirm ---- */
.tk-center--prompt .tk-card--selected {
    transform: translateY(-0.9rem) scale(1.04);
    box-shadow: 0 0 0 3px var(--tk-tarok),
                0 0 18px 2px rgba(217, 181, 81, 0.55),
                0 10px 20px rgba(0, 0, 0, 0.5);
}

.tk-center--prompt .tk-card--selected::after {
    background: linear-gradient(135deg, #f7dd8a, var(--tk-tarok));
    color: #1a1a1a;
    animation: tk-pick-pop 0.3s ease-out;
}

.tk-center--prompt .tk-card--playable:hover {
    transform: translateY(-0.55rem) rotate(-2deg);
    box-shadow: 0 0 14px 1px rgba(217, 181, 81, 0.4), 0 8px 16px rgba(0, 0, 0, 0.45);
}

.tk-center--prompt .tk-card--playable.tk-card--selected:hover {
    transform: translateY(-1.15rem) scale(1.05) rotate(-1deg);
}

@keyframes tk-pick-pop {
    0% { transform: scale(0) rotate(-30deg); }
    70% { transform: scale(1.35) rotate(8deg); }
    100% { transform: scale(1) rotate(0); }
}

/* The confirm button comes alive the instant the full set is chosen. */
.tk-center--prompt .tk-confirm {
    border-top-color: rgba(255, 255, 255, 0.18);
    justify-content: center;
}

.tk-center--prompt .tk-confirm__count {
    color: rgba(255, 255, 255, 0.85);
    font-size: 1.05rem;
}

.tk-center--prompt .tk-confirm .btn:not(:disabled) {
    background: linear-gradient(135deg, #f7dd8a, var(--tk-tarok));
    border-color: var(--tk-tarok);
    color: #1a1a1a;
    font-weight: 700;
    animation: tk-confirm-pulse 1.1s ease-in-out infinite;
}

@keyframes tk-confirm-pulse {
    0%, 100% { box-shadow: 0 0 0 0 rgba(217, 181, 81, 0); transform: translateY(0); }
    50% { box-shadow: 0 0 18px 4px rgba(217, 181, 81, 0.55); transform: translateY(-1px); }
}

@media (prefers-reduced-motion: reduce) {
    .tk-center--prompt .tk-card--selected::after,
    .tk-center--prompt .tk-confirm .btn:not(:disabled) {
        animation: none;
    }
}

/* ==========================================================================
   Standalone app (tarok.eventure.si) - slim skin + landing page
   ==========================================================================
   Chrome and landing styles for the standalone Tarok host. The game surfaces
   (.tk table/hub) are unchanged; these only dress the layouts/tarok.php shell
   and views/tarok/landing.php. All colours come from the platform semantic
   tokens so light/dark follows automatically. --tk-tarok is the gold accent
   already defined on .tk above.
   ========================================================================== */

.tarok-app {
    background: var(--bg-primary);
    color: var(--text-primary);
}

.tarok-app__header {
    padding: 0.4rem 0;
    background: var(--header-bg, var(--bg-secondary));
    border-bottom: 1px solid var(--header-border, var(--border-default));
}

.tarok-app__brand {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    gap: 0.05rem;
}

/* Right group: everything on one inline row - language codes + user chip, then
   theme, leaderboard and log out. Below 480px it stacks into two right-aligned
   rows (language + user on top, controls beneath) so it never crowds on a phone. */
.tarok-app__nav {
    display: flex;
    flex-direction: row;
    align-items: center;
    gap: 0.6rem;
}

@media (max-width: 480px) {
    .tarok-app__nav {
        flex-direction: column;
        align-items: flex-end;
        gap: 0.15rem;
    }
}

/* Top-right row: language codes + the signed-in user chip, kept compact. */
.tarok-app__brand-meta {
    display: flex;
    align-items: center;
    justify-content: flex-end;
    gap: 0.6rem;
}

/* Tighter language codes here than the platform default (shared language.css). */
.tarok-app .tarok-app__brand-meta .language-text-toggle {
    gap: 0.1rem;
    padding: 0;
}

.tarok-app .tarok-app__brand-meta .language-toggle-link {
    padding: 0 0.15rem;
}

.tarok-app__wordmark {
    display: inline-flex;
    align-items: center;
    font-weight: 800;
    font-size: 1.25rem;
    letter-spacing: 0.01em;
    text-decoration: none;
    color: var(--text-primary);
}

.tarok-app__wordmark:hover {
    color: var(--tk-tarok);
}

/* The fancy logo: the "Tarok" word in the same italic Bodoni Moda Didone the card
   numerals use, so the wordmark echoes the deck. The heart stays sans/red. */
.tarok-app__wordmark-text {
    font-family: var(--font-family-bodoni-moda);
    font-style: italic;
    font-weight: 700;
    font-size: 1.5rem;
    letter-spacing: 0;
}

.tarok-app__wordmark .fa-heart {
    color: var(--tk-red, #c0392b);
}

.tarok-app__user {
    display: inline-flex;
    align-items: center;
    color: var(--text-secondary);
    font-size: 0.8rem;
    line-height: 1;
}

/* Keep the language + theme toggles vertically centred with the buttons. */
.tarok-app__toggle {
    display: inline-flex;
    align-items: center;
}

.tarok-app__footer {
    padding: 1.5rem 0;
    background: var(--footer-bg, var(--bg-secondary));
    border-top: 1px solid var(--footer-border, var(--border-default));
}

/* Centered, stacked lines: brand line, discovery links, then rules. */
.tarok-app__footer-inner {
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 0.6rem;
}

.tarok-app__footer-left {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.4rem;
}

.tarok-app__footer-brand-line {
    display: inline-flex;
    align-items: center;
    gap: 0.35rem;
    white-space: nowrap;
}

.tarok-app__footer-mark {
    font-weight: 700;
    color: var(--text-primary);
}

.tarok-app__footer-dim {
    color: var(--text-secondary);
    font-size: 0.9rem;
}

/* The platform, emphasised - the one link that should stand out down here. */
.tarok-app__footer-brand {
    font-weight: 700;
    color: var(--tk-tarok, #8a6d1f);
    text-decoration: none;
}

.tarok-app__footer-brand:hover {
    text-decoration: underline;
}

.tarok-app__footer-links {
    display: flex;
    flex-wrap: wrap;
    justify-content: center;
    align-items: center;
    gap: 0.4rem 0.9rem;
    font-size: 0.85rem;
}

.tarok-app__footer-links a {
    color: var(--text-secondary);
    text-decoration: none;
}

.tarok-app__footer-links a:hover {
    color: var(--text-primary);
}

/* Thin separators between the discovery links. */
.tarok-app__footer-links a + a {
    position: relative;
    padding-left: 0.9rem;
}

.tarok-app__footer-links a + a::before {
    content: "";
    position: absolute;
    left: 0;
    top: 50%;
    transform: translateY(-50%);
    height: 0.8em;
    border-left: 1px solid var(--border-default);
}

/* ----- Landing ----------------------------------------------------------- */

.tarok-landing__hero {
    padding: clamp(3rem, 8vw, 6rem) 0 clamp(2rem, 5vw, 3.5rem);
    background:
        radial-gradient(120% 120% at 50% 0%, rgba(138, 109, 31, 0.12), transparent 60%),
        var(--bg-primary);
}

.tarok-landing__title {
    font-weight: 800;
    font-size: clamp(2rem, 5vw, 3.25rem);
    margin-bottom: 0.75rem;
}

.tarok-landing__lead {
    max-width: 42rem;
    margin: 0 auto 1.75rem;
    font-size: clamp(1.05rem, 2vw, 1.25rem);
    color: var(--text-secondary);
}

.tarok-landing__steps {
    padding: clamp(2rem, 5vw, 3.5rem) 0;
}

.tarok-landing__step {
    padding: 1.5rem;
    background: var(--card-bg);
    border: 1px solid var(--card-border, var(--border-default));
    border-radius: var(--border-radius-lg, 0.75rem);
    box-shadow: var(--card-shadow, none);
    text-align: center;
}

.tarok-landing__step-icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 3rem;
    height: 3rem;
    margin-bottom: 1rem;
    border-radius: 50%;
    background: var(--tk-tarok-bg, #fdf6e3);
    color: var(--tk-tarok, #8a6d1f);
    font-size: 1.25rem;
}

.tarok-landing__step-title {
    margin-bottom: 0.5rem;
}

.tarok-landing__step-desc {
    color: var(--text-secondary);
}

/* Logged-in quick-start: a symmetric 2x2 matrix of tappable cards. */
.tarok-quickstart {
    display: grid;
    grid-template-columns: repeat(2, 1fr);
    gap: 0.85rem;
    max-width: 30rem;
}

.tarok-quickstart__form {
    margin: 0;
    display: flex;
}

.tarok-quickstart__btn {
    flex: 1 1 auto;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 0.3rem;
    width: 100%;
    padding: 1.25rem 1rem;
    border: 1px solid var(--card-border, var(--border-default));
    border-radius: var(--border-radius-lg, 0.9rem);
    background: var(--card-bg);
    color: var(--text-primary);
    box-shadow: var(--card-shadow, none);
    cursor: pointer;
    transition: transform 0.15s ease, box-shadow 0.15s ease, border-color 0.15s ease;
}

.tarok-quickstart__btn:hover,
.tarok-quickstart__btn:focus-visible {
    transform: translateY(-3px);
    border-color: var(--tk-tarok, #8a6d1f);
    box-shadow: 0 10px 24px rgba(0, 0, 0, 0.14);
    outline: none;
}

.tarok-quickstart__icon {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    width: 2.6rem;
    height: 2.6rem;
    margin-bottom: 0.15rem;
    border-radius: 50%;
    font-size: 1.15rem;
}

/* A quiet colour cue so the two modes read apart without breaking symmetry. */
.tarok-quickstart__btn[data-mode="cpu"] .tarok-quickstart__icon {
    background: var(--tk-tarok-bg, #fdf6e3);
    color: var(--tk-tarok, #8a6d1f);
}

.tarok-quickstart__btn[data-mode="friends"] .tarok-quickstart__icon {
    background: rgba(59, 130, 246, 0.12);
    color: #3b82f6;
}

.tarok-quickstart__title {
    font-weight: 700;
    font-size: 0.98rem;
    line-height: 1.2;
    text-align: center;
}

.tarok-quickstart__count {
    color: var(--text-secondary);
    font-size: 0.82rem;
}

@media (max-width: 400px) {
    .tarok-quickstart { grid-template-columns: 1fr; }
}

@media (prefers-reduced-motion: reduce) {
    .tarok-quickstart__btn { transition: none; }
    .tarok-quickstart__btn:hover,
    .tarok-quickstart__btn:focus-visible { transform: none; }
}

.tarok-landing__rooms {
    padding: clamp(2rem, 5vw, 3.5rem) 0;
}

.tarok-landing__rooms-list {
    max-width: 34rem;
}

.tarok-landing__board {
    padding: clamp(2rem, 5vw, 3.5rem) 0;
    background: var(--bg-secondary);
}

.tarok-landing__board-list {
    max-width: 32rem;
    margin: 0 auto;
    padding: 0;
    list-style: none;
    counter-reset: tarok-rank;
}

.tarok-landing__board-row {
    counter-increment: tarok-rank;
    display: flex;
    align-items: center;
    gap: 0.75rem;
    padding: 0.6rem 0.9rem;
    border-bottom: 1px solid var(--border-default);
}

.tarok-landing__board-row:last-child {
    border-bottom: 0;
}

.tarok-landing__board-row::before {
    content: counter(tarok-rank);
    flex: 0 0 1.6rem;
    font-weight: 700;
    color: var(--tk-tarok, #8a6d1f);
    text-align: center;
}

.tarok-landing__board-name {
    flex: 1 1 auto;
    font-weight: 600;
}

.tarok-landing__board-rating {
    color: var(--text-secondary);
    font-size: 0.9rem;
    white-space: nowrap;
}

.tarok-landing__outro {
    padding: clamp(2.5rem, 6vw, 4rem) 0;
}

/* ----- Landing FAQ ------------------------------------------------------- */
.tarok-landing__faq {
    padding: clamp(2rem, 5vw, 3.5rem) 0;
    background: var(--bg-secondary);
}

.tarok-landing__faq-list {
    max-width: 44rem;
}

.tarok-landing__faq-item {
    border-bottom: 1px solid var(--border-default);
}

.tarok-landing__faq-q {
    margin: 0;
    font-size: 1rem;
}

.tarok-landing__faq-toggle {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 1rem;
    width: 100%;
    padding: 1rem 0.25rem;
    background: none;
    border: 0;
    text-align: left;
    font: inherit;
    font-weight: 600;
    color: var(--text-primary);
    cursor: pointer;
}

.tarok-landing__faq-icon {
    flex: 0 0 auto;
    font-size: 0.85rem;
    color: var(--text-secondary);
    transition: transform 0.2s ease;
}

.tarok-landing__faq-toggle:not(.collapsed) .tarok-landing__faq-icon {
    transform: rotate(180deg);
}

.tarok-landing__faq-a {
    padding: 0 0.25rem 1.1rem;
    color: var(--text-secondary);
    line-height: 1.6;
}
