/* What is particular to cribbage-multiplayer.
 *
 * Everything shared with the other games is in ../shared/styles/core.css, which
 * the page loads first. This file loads after it, so anything said here wins —
 * that is the whole override mechanism, and it needs no !important.
 */

/* Cribbage - presentation.
 * Aims: strong contrast, visible focus, no colour-only meaning, respects
 * prefers-reduced-motion and prefers-contrast, and scales with the user's font size.
 */
:root {
  --bg: #10161d;
  --panel: #1a232e;
  --panel-2: #223040;
  --ink: #eef3f8;
  --ink-dim: #ccd8e4;
  --line: #3c4b5d;
  --accent: #6fd0ff;
  --accent-ink: #06212e;
  --good: #7ee08a;
  --bad: #ff9b9b;
  --card-bg: #f7f9fb;
  /* A card you cannot play. Light enough that a red suit still clears AA on it
   * — #c2ccd6 looked better and put the pips at 4.25:1, which is a fail. */
  --card-off: #ccd5de;
  --card-ink: #16202a;
  --card-red: #b3122a;
  --trump: #f0c04a;
  --bower: #7ad3a0;
  --bower-ink: #0d5c38;
  --felt: #1d5c43;
  --felt-edge: #123a2b;
  /* Ink for text sitting DIRECTLY on the felt, rather than on a panel.
   *
   * Deliberately not redefined for light mode, and that is the whole point:
   * the felt is dark green in both colour schemes, but --ink-dim flips to a
   * dark slate in light mode. Anything on the felt using --ink-dim was
   * therefore 1.41:1 in light mode — dark grey on dark green, well under the
   * 4.5:1 WCAG AA needs, and identically broken in all three games.
   *
   * It went unseen because the text it affects only appears when a hand runs
   * empty, which no screenshot and no audit had ever caught it doing. */
  --ink-on-felt: #e6eef6;
  --back-a: #2a4f7c;
  --back-b: #1b3557;
  --focus: #ffd54a;
  --radius: 8px;
}

@media (prefers-color-scheme: light) {
  :root {
    --bg: #f2f5f8;
    --panel: #ffffff;
    --panel-2: #e8eef4;
    --ink: #12181f;
    --ink-dim: #3b4a5b;
    --line: #b9c6d4;
    --accent: #14556f;
    --accent-ink: #ffffff;
    --good: #10662a;
    --bad: #a11226;
    --card-bg: #ffffff;
    --card-off: #ccd5de;
    --card-ink: #12181f;
    --card-red: #b3122a;
    --trump: #8a5a00;
    --bower: #1a7f4f;
    --bower-ink: #0d5c38;
    --felt: #1f6b4d;
    --felt-edge: #14503a;
    --back-a: #33608f;
    --back-b: #224060;
    --focus: #a35a00;
  }
}

/* Inline links in the notice are targets like any other, and at the default text
 * size a bare inline link is about 21px tall — under the 24px WCAG 2.2 minimum.
 * It only shows up when something measures it, because it looks perfectly fine
 * and is perfectly clickable with a mouse; the people it fails are the ones
 * aiming with a thumb or a head pointer. tests/layout.js measures it. */
.dev-notice a {
  color: var(--accent);
  font-weight: 600;
  display: inline-block;
  padding: .3rem 0;
  min-height: 24px;
}

/* The card the dealer took from the top of the kitty, sitting at the front of
 * the hand until they have put one back. Lifted and outlined so it reads as
 * "this is the new one" — a six card hand that all looks alike is exactly where
 * a dealer discards the card they meant to keep. */
.card.from-upcard {
  border-color: var(--accent);
  border-width: 3px;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--accent) 35%, transparent);
  transform: translateY(-.35rem);
}

.card.from-upcard .tag { color: var(--accent); font-weight: 800; }

/* A bower.
 *
 * The right and left bowers are the two highest cards in the game, and the left
 * one does not look like a trump at all — with spades trump the jack of clubs is
 * a spade, and a player scanning their hand for spades will not see it. So it is
 * marked, and marked the same way in both skins, because "it is obvious once you
 * know" is the whole problem: the moment you stop knowing is the moment you
 * throw it away.
 *
 * Marked visually here and named in the card's own aria-label, so neither
 * audience is depending on the other's channel. */
.card.bower-card {
  border-color: var(--bower);
  border-width: 3px;
  /* Colour and image set separately: a gradient alone leaves background-color
   * transparent, which is both a weak fallback and unmeasurable for contrast. */
  background-color: var(--card-bg);
  background-image: linear-gradient(180deg, color-mix(in srgb, var(--bower) 18%, var(--card-bg)) 0%, var(--card-bg) 55%);
}

.card.bower-card .tag { color: var(--bower-ink); font-weight: 800; }

.card.bower-card::before {
  content: "★";
  position: absolute; top: 1px; right: 4px;
  font-size: .8rem; line-height: 1;
  color: var(--bower-ink);
}

.card.from-upcard.bower-card { box-shadow: 0 0 0 3px color-mix(in srgb, var(--bower) 40%, transparent); }

/* A seat sitting out because its partner is playing alone. Not "disabled" —
 * they are still at the table and their row still carries a score. */
tr.sitting-out th[scope="row"] { font-style: italic; }

@media (forced-colors: active) {
  .card.trump { border-style: double; }
  .card.from-upcard { border-style: dashed; }
  .card.bower-card { outline: 3px solid; outline-offset: 1px; }
  .trick li.winning { border-style: dashed; }
}

/* ---------- optional two-column desktop layout ----------
 * Off by default; Settings > Appearance > Desktop layout turns it on.
 *
 * CSS Grid auto-placement is row-major, so panels fill left-to-right in exact
 * DOM order. Nothing is repositioned and no `order` is used, so reading order
 * and visual order stay identical — which is the whole reason this is grid and
 * not absolute positioning.
 *
 * 64rem in a media query is always 1024px regardless of the user's font size,
 * so phones and tablets are untouched whatever this is set to.
 */
@media (min-width: 64rem) {
  .layout-two-col #game-section {
    display: grid;
    grid-template-columns: 1fr 1fr;
    column-gap: 1.25rem;
    align-items: start;
  }
  /* Anything that reads as a full-width band stays one. The rest pairs up:
   * hand | seats, then current trick | last trick. */
  .layout-two-col #game-section > h2,
  .layout-two-col #game-section > #status,
  .layout-two-col #game-section > #action-section,
  .layout-two-col #game-section > .toolbar,
  .layout-two-col #game-section > #starter-section,
  .layout-two-col #game-section > #crib-section,
  .layout-two-col #game-section > #score-section,
  .layout-two-col #game-section > section[aria-labelledby="players-h"],
  .layout-two-col #game-section > section[aria-labelledby="log-h"] {
    grid-column: 1 / -1;
  }
}

/* THE CONNECTION, WHEN THERE IS SOMETHING WRONG WITH IT.
 *
 * Nothing is shown while it is healthy — a standing "connected" badge is noise
 * on screen and worse in a screen reader's tab order. When it appears it is
 * news, so it is styled as a warning and it stays put rather than passing by in
 * a live region: somebody who missed the announcement has to be able to find it
 * again, and somebody who heard it has to be able to check. */
.net-line {
  margin: .5rem 0;
  padding: .55rem .8rem;
  border: 1px solid var(--bad);
  border-left: 5px solid var(--bad);
  border-radius: var(--radius);
  background: var(--panel);
  color: var(--ink);
  font-weight: 600;
}

.net-line:focus-visible { outline: 3px solid var(--focus); outline-offset: 3px; }

/* The result headline. It carries the whole outcome in a sentence, and the chips
 * above it are decoration that repeats the numbers for anybody reading by eye. */
.result-headline { font-weight: 700; color: var(--ink); font-size: 1.05rem; }

/* The score table. Your own side's row is marked, because "which of these two
 * rows is me" is the question it exists to answer. */
#score-table tr.you th[scope="row"] { color: var(--accent); }

/* ---------- the cribbage board ----------
 *
 * Decoration, and hidden from assistive technology entirely — the Score table
 * carries both numbers and the distance still to go, which is the same
 * information without a hundred and twenty-one holes to walk through. It is here
 * because a board is what cribbage looks like, and a player with some sight uses
 * the relative position of two pegs to see a game slipping away far faster than
 * they read two numbers.
 *
 * A wooden board drawn in SVG by renderBoard(): streets of thirty holes in
 * fives, running out and back with a curved turn at each end, start holes at the
 * top left and the game hole at the bottom left, the way a continuous board is
 * laid out. Each player has two pegs and they leapfrog — the back peg jumps past
 * the front one — so the gap between them is the last score, as at a table.
 *
 * The holes are one path per lane rather than a node per hole: 242 elements for
 * two players would be noise in the DOM, none of it readable. The board is wood
 * in both colour schemes, so its colours are its own rather than the theme's,
 * and the peg colours are gold and blue because they stay apart for every kind
 * of colour vision as well as in brightness.
 */
.board {
  --wood-1: #93602f;
  --wood-2: #6c431e;
  --wood-edge: #3a220c;
  --wood-hole: #1f1107;
  --wood-ink: #fbeed8;
  --peg-mine: #ffc53d;
  --peg-theirs: #5cc3ff;
  --peg-edge: #1a0f05;
  margin: .75rem 0 1rem;
  padding: .7rem .8rem .8rem;
  background: var(--panel);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  display: grid;
  gap: .5rem;
}

.board-legend {
  display: flex;
  flex-wrap: wrap;
  gap: .25rem 1.5rem;
  margin: 0;
  padding: 0;
  list-style: none;
}

.board-key { display: flex; align-items: baseline; gap: .45rem; font-size: .95rem; }

.board-key-name { font-weight: 700; }

.board-key-togo { color: var(--ink-dim); font-size: .88rem; }

.board-swatch {
  flex: none;
  align-self: center;
  width: .8rem;
  height: .8rem;
  border-radius: 50%;
  border: 1px solid var(--peg-edge);
  background: var(--peg-theirs);
}

.board-key.mine .board-swatch { background: var(--peg-mine); }

.board-svg {
  display: block;
  width: 100%;
  max-width: 50rem;
  height: auto;
  margin: 0 auto;
  filter: drop-shadow(0 .15rem .25rem rgba(0, 0, 0, .35));
}

.board-wood { stroke: var(--wood-edge); stroke-width: 1.5; }
.board-wood-a { stop-color: var(--wood-1); }
.board-wood-b { stop-color: var(--wood-2); }
.board-grain { fill: none; stroke-width: .6; stroke: rgba(0, 0, 0, .13); }
.board-grain.light { stroke: rgba(255, 236, 200, .08); }

/* The inlaid track each player's pegs run along, tinted with that player's peg
 * colour so a lane can be followed round a turn by eye. */
.board-groove { fill: none; stroke-width: 8; stroke-linecap: round; stroke-linejoin: round; opacity: .3; }
.board-groove.mine { stroke: var(--peg-mine); }
.board-groove.theirs { stroke: var(--peg-theirs); }

.board-holes { fill: var(--wood-hole); }
.board-game-hole { fill: var(--wood-hole); stroke: var(--wood-ink); stroke-width: .7; }
.board-label { fill: var(--wood-ink); font: 700 6.5px system-ui, "Segoe UI", Roboto, sans-serif; }

.board-peg-body { stroke: var(--peg-edge); stroke-width: .8; fill: var(--peg-theirs); }
.board-peg.mine .board-peg-body { fill: var(--peg-mine); }
.board-peg-shine { fill: #fff; opacity: .6; }
.board-peg-shadow { fill: #000; opacity: .35; }
/* The back peg is where the last score started from. Dimmed a little so the
 * eye goes to the front peg first; it is still plainly a peg. */
.board-peg.back { opacity: .7; }

@media (prefers-reduced-motion: no-preference) {
  .board-peg { transition: transform .5s cubic-bezier(.3, .7, .3, 1); }
}

@media (forced-colors: active) {
  .board-svg { filter: none; }
  .board-wood { fill: Canvas; stroke: CanvasText; }
  .board-grain, .board-peg-shine, .board-peg-shadow { display: none; }
  .board-groove { opacity: 1; stroke: Canvas; }
  .board-holes, .board-label { fill: CanvasText; }
  .board-game-hole { fill: Canvas; stroke: CanvasText; }
  .board-peg-body, .board-peg.mine .board-peg-body { stroke: CanvasText; stroke-width: 1.2; }
  .board-peg.mine .board-peg-body { fill: Highlight; }
  .board-peg.theirs .board-peg-body { fill: LinkText; }
  .board-peg.back { opacity: 1; }
  .board-swatch { forced-color-adjust: none; border-color: CanvasText; background: LinkText; }
  .board-key.mine .board-swatch { background: Highlight; }
}

/* The running count, which is the single number a cribbage player holds in their
 * head all the way through the play. Big, because it changes constantly and is
 * the thing being glanced at. */
.count-line {
  margin: .3rem 0 .6rem;
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
}

/* The scoring shout, on the table where the count is.
 *
 * The rule this follows: anything the announcer says that changes the game has
 * to be visible too. "Fifteen for two" was spoken and then gone, and the only
 * visible trace was a number in the score column moving by two, which tells you
 * that something scored but never what. Sitting directly under the count, in
 * the words a player would use, it is the same information both people get.
 *
 * Plain --ink on the section background, exactly like .count-line above it, so
 * it inherits a contrast that is already measured; the colour is in the rule at
 * the side and carries nothing on its own. */
.score-call {
  margin: 0 0 .6rem;
  padding: .3rem 0 .3rem .6rem;
  border-left: .3rem solid var(--good);
  font-size: 1.15rem;
  font-weight: 700;
  color: var(--ink);
}

/* Both hands laid out for the count. The rows are the shared .reveal-row, so
 * this is only the gap between one player's four cards and the next player's. */
#count-hands .reveal-row { margin-bottom: .35rem; }

#count-hands .card { cursor: default; }

/* The starter, and cards chosen to go to the crib. `aria-pressed` already gets
 * the lift and the outline from the shared rules above; this adds the label
 * colour so the two states do not depend on position alone. */
.card.starter-card { border-color: var(--trump); border-width: 3px; }

.card.starter-card .tag { color: #8a5a00; font-weight: 800; }

.card[aria-pressed="true"] .tag { color: var(--accent); font-weight: 800; }

/* A hand that has been laid down and counted is no longer interactive, but it is
 * still worth reading. */
#crib .card, #starter .card { cursor: default; }
