/* Doppelkopf — game-local styles.
 *
 * WHERE THE COLOURS CAME FROM
 * ---------------------------
 * Doppelkopf is a traditional game. There is no publisher, no wordmark and no box art, so
 * there is no brand palette to sample — inventing one is the honest move, and it is
 * invented from the game rather than from taste.
 *
 * --dk-accent  #ab7ce0  amethyst. Doppelkopf already names four colours of its own: the
 *              Queens are die Alte (♣, black), die Blaue (♠), die Rote (♥) and die Gelbe
 *              (♦) — see strategy/01_fuchstreff_top20.txt §5d, which uses "Blaue" and
 *              "Herz-Dame" as ordinary vocabulary. Chrome must not collide with a card
 *              MEANING, so the accent deliberately sits outside that black/blue/red/yellow
 *              set. Violet is also the one strong hue no neighbour on the portal owns:
 *              nearest is Joan #2f6bb5 at Δhue 58°, and six games already share the
 *              amber/gold band this game would otherwise have landed in.
 * --dk-tint    a muted baize green. The environment, not the accent — Doppelkopf is a
 *              Kneipe and club game and the table it is played on is green cloth. Tinting
 *              the shared wooden table with it reads as felt over wood.
 *
 * Everything below --dk-tint is the GAME'S OWN vocabulary and is namespaced. No new
 * --dk-* token is invented here: that namespace belongs to ../core/deckades.css, and a
 * game-local --dk-anything would silently win by source order.
 */

:root {
    --dk-accent:      #ab7ce0;
    --dk-accent-soft: rgba(171, 124, 224, 0.34);
    --dk-tint:        rgba(56, 96, 70, 0.26);
}

/* The game's own vocabulary ------------------------------------------------ */
:root {
    /* The four Queens, by the names the game gives them. Each differs in LIGHTNESS as
       well as hue, and none of them ever carries a game state on its own — every use is
       paired with the card face or a text label. */
    --doko-alte:  #e8e2d6;   /* ♣ "die Alte"  — pale, because clubs already read as black */
    --doko-blaue: #6f9fe0;   /* ♠ "die Blaue" */
    --doko-rote:  #e0645f;   /* ♥ "die Rote"  */
    --doko-gelbe: #d9b455;   /* ♦ "die Gelbe" */

    /* Re and Kontra. Violet and green differ in hue AND lightness, and neither is ever the
       only signal — every badge that uses them also spells the party out in words. */
    --doko-re:     #ab7ce0;
    --doko-kontra: #7fc4a8;

    --doko-card-w: 78px;
    --doko-seat-w: 132px;
}

/* The ONE exception to "emit no header CSS": on iOS a tap landing on the inline SVG can
   fail to fire the parent button. The shared sheet does not carry this rule, and it is
   about the button's CONTENTS rather than the header's appearance. */
.hdr-tool-btn svg { pointer-events: none; }

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

#game {
    position: absolute;
    inset: 0;
    touch-action: none;        /* the table never pans; taps are the only gesture on it */
    /* No cover art exists for a public-domain game, so there is no picture layer to blend.
       The felt is the shared table tinted into the game's own hue — never a flat colour.
       The near-black wash on top is what makes the CARDS the brightest thing on screen;
       it is warm rather than pure black, which would flatten the wood into a smudge. */
    background:
        linear-gradient(rgba(14, 11, 8, 0.62), rgba(10, 8, 6, 0.72)),
        linear-gradient(var(--dk-tint), var(--dk-tint)),
        var(--dk-table);
    background-blend-mode: normal, soft-light, normal;
    overflow: hidden;
}

/* The house mark on the felt: the two club Queens, the pair that decides Re.
 *
 * It is a SEPARATE layer, not another background on #game, for two reasons. #game already
 * blends three layers and a fourth would need its own blend mode threaded through a list
 * where a miscount silently re-blends the felt. And a mark that lives under the dark wash
 * would be invisible: it has to sit on top of the wash and be faint on its own terms.
 *
 * Faint is the whole specification. A table logo competes with the cards, and the cards must
 * stay the brightest thing on screen; at 0.055 it is legible when you look for it and gone
 * when you are reading a trick. It is also OFF-CENTRE-safe: sized from the smaller viewport
 * axis so it never grows into the hand fans on a wide screen. */
#game::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;              /* it is decoration; it must never eat a tap */
    z-index: 0;
    background: url('assets/table-mark.svg') center 46% / min(38vmin, 340px) no-repeat;
    opacity: 0.055;
}
/* NO rule is needed to lift the table's contents above the mark, and the obvious one is a trap:
   `#game > * { position: relative }` overrides the ABSOLUTE positioning every fan, badge and
   play zone depends on, and collapses the whole table into flow layout. It cost 43 layout-harness
   failures across all five viewports the moment it was written. The pseudo-element is the first
   thing in tree order, so at the same stacking level the real children already paint over it. */

#start-screen {
    background:
        linear-gradient(rgba(10, 8, 14, 0.80), rgba(8, 6, 11, 0.90)),
        linear-gradient(var(--dk-tint), var(--dk-tint)),
        var(--dk-table);
    background-blend-mode: normal, soft-light, normal;
}

/* ------------------------------------------------------------------ cards */
/* The game owns the card's BOX; ../core/cards/cards.css owns what is printed on it.
   --card-w must be declared here, and the element must be a positioning context. */

.doko-card {
    position: absolute;
    width: var(--card-w, var(--doko-card-w));
    height: calc(var(--card-w, var(--doko-card-w)) * 1.42);
    --card-w: var(--doko-card-w);
    border-radius: 7px;
    box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
    transition: transform 140ms ease, box-shadow 140ms ease, filter 140ms ease;
    will-change: transform;
}

/* cards.css styles what is PRINTED and explicitly leaves the face background to the game.
   Without this the wood grain shows straight through every card and the cards become the
   DIMMEST thing on the table instead of the brightest. */
.doko-card.dk-face {
    background: linear-gradient(160deg, #fdfaf3 0%, #f2ebdc 100%);
    border: 1px solid rgba(28, 20, 12, 0.30);
}
.doko-card.dk-back { border: 1px solid rgba(0, 0, 0, 0.35); }

/* Playability is carried by the CARD, which is why the status line never narrates it.
   Only a playable card takes a click: without this an opponent's face-down fan that merely
   OVERLAPS the human's hand silently swallows the tap, and the game reads as frozen. */
.doko-card { pointer-events: none; touch-action: none; }
.doko-card.playable { pointer-events: auto; cursor: pointer; }
.doko-card.playable:hover { filter: brightness(1.14); box-shadow: 0 8px 22px rgba(0, 0, 0, 0.65); z-index: 90; }
.doko-card.dim { filter: brightness(0.42) saturate(0.5); cursor: not-allowed; }
.doko-card.picked { outline: 2px solid var(--dk-accent); outline-offset: 1px; }

/* Card SIZE is set per card by placeCard(), because every seat on the ring scales
   independently and the human's hand never shrinks. The rule here is shadow only — an
   earlier version set --card-w on .doko-fan and silently shrank the human's own hand too,
   which then made every dealt card snap on landing. */
.doko-fan.opp .doko-card { box-shadow: 0 2px 6px rgba(0, 0, 0, 0.45); }

/* Rotation comes from placeCard() as an inline transform, so the hover lift has to be a
   filter rather than a transform or it would un-rotate the card. */
.doko-card { transform-origin: center center; }

.doko-ghost {
    position: fixed;
    z-index: 500;
    pointer-events: none;
    border-radius: 7px;
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.6);
}

/* ------------------------------------------------------------------ seats */

.doko-seat {
    position: absolute;
    width: var(--doko-seat-w);
    text-align: center;
    pointer-events: none;
    user-select: none;
}

.doko-badge {
    display: inline-block;
    padding: 5px 10px 6px;
    border-radius: var(--dk-radius);
    background: var(--dk-panel);
    border: 1px solid var(--dk-panel-line);
    box-shadow: var(--dk-panel-shadow);
    font: 600 12px/1.35 var(--dk-font-ui);
    color: var(--dk-panel-text);
    white-space: nowrap;
}
.doko-badge.turn { border-color: var(--dk-accent); box-shadow: 0 0 0 1px var(--dk-accent-soft), var(--dk-panel-shadow); }
.doko-badge .doko-name { display: block; font-weight: 700; }
.doko-badge .doko-sub  { display: block; opacity: 0.72; font-weight: 500; font-size: 11px; }
.doko-badge .doko-ai   { opacity: 0.55; font-weight: 500; }

/* A declared party is never colour ALONE — the label spells out Re / Kontra. */
.doko-badge .doko-party { font-weight: 700; }
.doko-badge .doko-party.re     { color: var(--doko-re); }
.doko-badge .doko-party.kontra { color: var(--doko-kontra); }

.doko-dealer {
    display: inline-block;
    margin-left: 5px;
    padding: 0 5px;
    border-radius: 3px;
    background: var(--dk-accent-soft);
    font-size: 10px;
    letter-spacing: 0.04em;
}

/* ----------------------------------------------------------------- centre */

.doko-trickzone {
    position: absolute;
    pointer-events: none;
}

.doko-typemark {
    position: absolute;
    left: 50%;
    transform: translateX(-50%);
    font: 600 13px/1 var(--dk-font-ui);
    letter-spacing: 0.10em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.16);
    pointer-events: none;
    user-select: none;
    white-space: nowrap;
}

/* -------------------------------------------------------- the action bar */
/* One flex row in the strip BOTTOM_M already reserved for it: the human's badge, the status
   line and the Re/Kontra buttons. Three floating boxes fighting over the same corner is
   what the first version of this file did, and every screenshot found a new collision. */

#doko-actionbar {
    position: absolute;
    left: 10px;
    right: 10px;
    bottom: 4px;
    height: 46px;
    display: flex;
    align-items: center;
    gap: 12px;
    z-index: 220;
    pointer-events: none;      /* only the buttons inside take clicks */
}
#doko-actionbar .doko-bar-left  { flex: 0 0 auto; }
#doko-actionbar .doko-bar-mid { flex: 1 1 auto; }   /* spacer only — the turn line lives
                                                       in #status-line, above the hand */
#doko-actionbar .doko-bar-right { flex: 0 0 auto; display: flex; gap: 7px; pointer-events: auto; }

@media (max-height: 460px) {
    /* No room for the badge beside everything else — the ranking panel and the fan already
       carry what it says, and the status line is the part that changes. */
    #doko-actionbar .doko-bar-left { display: none; }
}

.doko-call {
    /* >=44px tall: the platform minimum tap target, and the only thing on the table a
       finger has to hit besides a card. */
    min-height: 44px;
    min-width: 44px;
    touch-action: manipulation;
    padding: 5px 14px;
    border-radius: var(--dk-radius);
    border: 1px solid var(--dk-accent-soft);
    background: var(--dk-panel);
    color: var(--dk-panel-text);
    font: 600 12px var(--dk-font-ui);
    cursor: pointer;
    white-space: nowrap;
}
.doko-call:hover { border-color: var(--dk-accent); background: var(--dk-panel-dim); }
.doko-call small { display: block; opacity: 0.55; font-weight: 500; font-size: 10px; }

/* --------------------------------------------------------- ranking panel */

#doko-ranking {
    position: fixed;
    top: 84px;
    right: 12px;
    width: 156px;
    z-index: 200;
    pointer-events: none;      /* the tool panels open at this corner and must win */
    user-select: none;
}

#doko-ranking .doko-rank-row {
    position: absolute;
    left: 0; right: 0;
    height: 36px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 0 10px;
    box-sizing: border-box;
    border-radius: var(--dk-radius);
    background: var(--dk-panel);
    border: 1px solid var(--dk-panel-line);
    font: 600 12px var(--dk-font-ui);
    color: var(--dk-panel-text);
    transition: top 420ms cubic-bezier(.22,.75,.3,1);
}
#doko-ranking .doko-rank-row.me { border-color: var(--dk-accent-soft); }
#doko-ranking .doko-rank-pts { font-variant-numeric: tabular-nums; }
#doko-ranking .doko-rank-pts.neg { color: var(--dk-msg-alert); }
#doko-ranking .doko-rank-pts.pos { color: var(--dk-msg-good); }

@media (max-width: 900px) { #doko-ranking { display: none; } }

/* ------------------------------------------------------------- overlays */

.doko-score-table { width: 100%; border-collapse: collapse; margin: 10px 0 4px; }
.doko-score-table td { padding: 3px 0; font: 500 13px var(--dk-font-ui); }
.doko-score-table td.n { text-align: right; font-variant-numeric: tabular-nums; }
.doko-score-table tr.sum td { border-top: 1px solid var(--dk-panel-line); padding-top: 7px; font-weight: 700; }
/* A superseded figure is SHOWN, struck through — the player counted it during the deal
   and needs to see where it went. Omitting it is worse than showing it crossed out. */
.doko-score-table tr.forfeited td { opacity: 0.5; text-decoration: line-through; }
.doko-score-table tr.forfeited td.why { text-decoration: none; opacity: 0.7; font-style: italic; }

.doko-augen { display: flex; gap: 18px; justify-content: center; margin: 6px 0 2px; }
.doko-augen b { font-size: 22px; font-variant-numeric: tabular-nums; }
.doko-augen .re b     { color: var(--doko-re); }
.doko-augen .kontra b { color: var(--doko-kontra); }

/* --------------------------------------------------------- reserve dialog */

.doko-reserve-opts { display: flex; flex-direction: column; gap: 7px; margin-top: 10px; }
.doko-reserve-opts button {
    min-height: 44px;
    touch-action: manipulation;
    padding: 9px 12px;
    border-radius: var(--dk-radius);
    border: 1px solid var(--dk-panel-line);
    background: var(--dk-panel-dim);
    color: var(--dk-panel-text);
    font: 600 13px var(--dk-font-ui);
    text-align: left;
    cursor: pointer;
}
.doko-reserve-opts button:hover { border-color: var(--dk-accent); }
.doko-reserve-opts .doko-solo-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 7px; }

/* ----------------------------------------------- the "Rules" launch link */
/* NOT .start-play: those are launch buttons and the shared sheet gives them width:100%,
   which would make a one-word link the widest control on the card. */
.rules-link {
    align-self: center;
    display: inline-block;
    width: auto;
    padding: 7px 16px;
    text-align: center;
    white-space: nowrap;
    border: 1px solid var(--dk-accent-soft);
    border-radius: var(--dk-radius);
    color: var(--dk-panel-text);
    text-decoration: none;
    font: 600 13px var(--dk-font-ui);
}
.rules-link:hover { border-color: var(--dk-accent); color: #fff; }

/* ---------------------------------------------------- prefers-reduced-motion */
/* The JS flag in game.js covers movement JS drives. A CSS transition on a repositioned
   element is INVISIBLE to it and keeps gliding at full length — which is the real
   accessibility defect, and also why a layout test can catch an element mid-transit and
   report a collision that does not exist. Both halves are needed. */
@media (prefers-reduced-motion: reduce) {
    #doko-ranking .doko-rank-row { transition: none; }
    .doko-card { transition: none; }
    .doko-ghost { display: none; }
}

/* The dealt ghost that uncovers the player's own hand. render() has already drawn the real,
   face-up card underneath; fading the back away is what turns the deal into "you pick your
   cards up". Not a flip — see the note in animateDeal() about deal order vs sorted order. */
.doko-ghost.doko-deal-uncover {
    transition: opacity 200ms ease-out;
    opacity: 0;
}
@media (prefers-reduced-motion: reduce) {
    /* The JS drops these without animating; kill the transition too, so a ghost that is
       already mid-fade when the setting changes cannot linger over a live card. */
    .doko-ghost.doko-deal-uncover { transition: none; }
}
