/* Solitaire's table, on the card room's felt (../cards/themes.css, ../cards/cards.css).
   It wears the player's table style like every card game here and adds only
   its own parts: the display face (Fraunces, SIL OFL), the empty places
   cards sit on, the table that scales its cards to fit, and the win.
   Steadiness first: the bar and the dock keep their sizes (the clock, the
   counts and the buttons live in places set aside for them), so the cards
   are the only thing that moves. docs/design-system.md, "Inside a game:
   Solitaire". */

@font-face {
  font-family: "Fraunces";
  src: url("fonts/fraunces-latin-700.d99d78cac1e8.woff2") format("woff2");
  font-weight: 700; font-style: normal; font-display: swap;
}

body.sol {
  --display: "Fraunces", Georgia, "Times New Roman", serif;
  --display-weight: 700;
}
[data-theme="retro"] body.sol { --display: Tahoma, Verdana, sans-serif; }
/* The house kit's sheets and toasts (../house/house.css) are drawn from the
   card room's tokens. Retro PC's are light gray: ink them dark, as the room's
   own sheets are (cards/themes.css). */
[data-theme="retro"] :is(.house-scrim, .house-toasts) { --ink: #000; --soft: #333; --turn: #000080; }

/* ── a deal on the table ─────────────────────────────────────────────── */
.felt.sol-play {
  height: calc(100dvh - 2 * var(--frame)); min-height: 0; overflow: hidden;
  display: grid; grid-template-columns: minmax(0, 1fr); grid-template-rows: auto minmax(0, 1fr) auto; gap: var(--s2);
  position: relative;
}
body:has(.sol-play) { overflow: hidden; }

/* (the bar, its title, its way home and its tools are the room's: room.css) */
.sol-bar .where { display: flex; align-items: center; gap: var(--s2); min-width: 0; flex: 1; }
.sol-bar .where .tag { flex: none; }
.sol-bar .tools { display: flex; align-items: center; gap: var(--s1); flex: none; flex-wrap: nowrap; }
.sol-bar .btn.quiet { white-space: nowrap; }
.sol-bar .timer { font-weight: 700; font-variant-numeric: tabular-nums; min-width: 5.4ch; text-align: right; padding-right: var(--s1); }
.sol-bar .pg { display: inline-flex; align-items: center; }
.sol-bar .pg .glyph { width: 14px; height: 14px; fill: currentColor; }
.sol-bar .pause { min-width: 36px; }
.sol-bar .pause .short { display: none; }
.sol-bar .narrow { display: none; }
/* (on a touch screen the bar's tools are a finger square, the ? and the paused glyph too) */
@media (pointer: coarse) { .sol-bar .tools .btn { min-width: 44px; } }
.sol-bar .btn.wide { width: auto; } /* (the room's .wide is "full width"; here it means "not on a phone") */

.sol-stage { position: relative; min-height: 0; min-width: 0; }
.sol-board { position: absolute; inset: 0; touch-action: none; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; outline: none; -webkit-tap-highlight-color: transparent; }
.sol-stage.covered .sol-board, .sol-stage.reading .sol-board { visibility: hidden; }
.sol-slots, .sol-cards, .sol-marks, .sol-notes { position: absolute; inset: 0; pointer-events: none; }
/* the card layer covers the whole board, so only the cards take presses: a press on an empty
   place has to fall through to the place (the empty stock redeals) */
.sol-cards { pointer-events: none; }
.sol-cards > .cd { pointer-events: auto; }
.sol-slots > *, .sol-marks > *, .sol-notes > * { position: absolute; left: 0; top: 0; }

/* the empty places (scoped: a button that wears .slot for its size, in a sheet or at home, isn't one) */
.sol-slots .slot {
  width: var(--cw); height: var(--ch); border-radius: var(--card-radius); pointer-events: auto;
  border: 1.5px dashed color-mix(in srgb, var(--ink) 30%, transparent);
  display: grid; place-content: center; justify-items: center; color: color-mix(in srgb, var(--ink) 42%, transparent);
  font: var(--display-weight) calc(var(--cw) * .5) / 1 var(--display);
}
.sol-slots .slot .sub { font-size: calc(var(--cw) * .3); line-height: 1; }
.sol-slots .slot.stock { cursor: pointer; }
.sol-slots .slot.stock.refill::after { content: '↻'; font: 700 calc(var(--cw) * .6) / 1 var(--ui-font); }
.sol-slots .slot.found .glyph { font-family: var(--ui-font); }

/* the cards */
.cd {
  position: absolute; left: 0; top: 0; width: var(--cw); height: var(--ch);
  transition: transform var(--m-glide, 250ms) var(--ease-out, cubic-bezier(.2, .7, .3, 1)), opacity .25s;
  will-change: transform; touch-action: none; -webkit-user-drag: none;
}
.cd.live { cursor: pointer; }
.cd .inner { position: absolute; inset: 0; }
.cd .card { position: absolute; inset: 0; width: 100%; height: 100%; transition: none; box-shadow: var(--card-shadow), 0 -1px 2px rgba(0, 0, 0, .25); }
.cd.down .face, .cd:not(.down) .back { visibility: hidden; }
/* A flip turns through the card's edge (240ms): the old face goes at the halfway point, the new one comes. */
.cd.turning .inner { animation: turn var(--m-flip, 240ms) ease-in-out var(--turn-delay, 0ms) both; }
.cd.turning.to-up .back, .cd.turning.to-down .face { animation: face-first var(--m-flip, 240ms) steps(1, end) var(--turn-delay, 0ms) both; }
.cd.turning.to-up .face, .cd.turning.to-down .back { animation: face-second var(--m-flip, 240ms) steps(1, end) var(--turn-delay, 0ms) both; }
@keyframes turn { 50% { transform: scaleX(.04); } }
@keyframes face-first { from { visibility: visible; } 50%, to { visibility: hidden; } }
@keyframes face-second { from { visibility: hidden; } 50%, to { visibility: visible; } }
.cd.gone { opacity: 0; pointer-events: none; }
.sol-board.still .cd { transition: none !important; }
.cd.drag { transition: none !important; cursor: grabbing; }
.cd.drag .card { box-shadow: 0 14px 22px rgba(0, 0, 0, .4); }
.sol-board.dragging { cursor: grabbing; }
.cd.nope .inner { animation: nope var(--m-nope, 360ms); }
@keyframes nope { 20%, 60% { transform: translateX(-4px); } 40%, 80% { transform: translateX(4px); } }

/* one row for a card's index, so a thin strip of an overlapped card still
   says what it is: "10♠", not "10" over a suit */
.sol .card .ix { display: flex; align-items: baseline; left: 6%; top: 3%; font-size: max(11px, calc(var(--cw) * .27)); line-height: 1; letter-spacing: -.06em; }
.sol .card .ix i { display: inline; font-size: .9em; }
.sol .card.small .ix { font-size: max(12px, calc(var(--cw) * .3)); }

/* a count on the stock; Pyramid's passes */
.sol-notes .count { display: flex; justify-content: center; pointer-events: none; z-index: 90; }
.sol-notes .count b {
  min-width: 1.9em; padding: 0 6px; border-radius: 99px; text-align: center; font: 800 12px/18px var(--ui-font);
  background: color-mix(in srgb, var(--room) 82%, transparent); color: var(--ink); font-variant-numeric: tabular-nums;
}
.sol-notes .pass { width: 140px; text-align: right; font-size: 13px; color: var(--soft); font-variant-numeric: tabular-nums; }

/* hints, targets, the card you chose, the keyboard's place */
.zmark { border-radius: var(--card-radius); }
.zmark.mk-target { outline: 3px solid var(--turn); background: color-mix(in srgb, var(--turn) 16%, transparent); }
.zmark.mk-hint { outline: 3px solid var(--turn); animation: glow 1s ease-in-out infinite alternate; }
.cd.mk-hint .face, .cd.mk-select .face { box-shadow: 0 0 0 3px var(--turn), var(--card-shadow); }
.cd.mk-hint .face { animation: glow 1s ease-in-out infinite alternate; }
.cd.mk-partner .face { box-shadow: 0 0 0 3px var(--turn), 0 0 14px 3px color-mix(in srgb, var(--turn) 55%, transparent); }
@keyframes glow { to { filter: brightness(1.18); } }
.cd.kbd .card, .sol-slots .slot.kbd { outline: 3px solid var(--focus, var(--ink)); outline-offset: 2px; box-shadow: 0 0 0 6px var(--room); }

/* paused */
.cover { position: absolute; inset: 0; z-index: 120; display: grid; place-content: center; justify-items: center; gap: var(--s3); }
.cover-title { font: var(--display-weight) var(--t-display) / 1 var(--display); }

/* the dock: what's going on, the buttons, the count */
.sol-dock { display: grid; gap: var(--s1); flex: none; }
.sol-dock .status { margin: 0; min-height: 1.5em; font-size: var(--t-note); line-height: 1.5; color: var(--soft); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.sol-dock .status span { display: block; overflow: hidden; text-overflow: ellipsis; }
.dockrow { display: grid; }
.dockrow > * { grid-area: 1 / 1; }
.actions, .resultrow { display: flex; align-items: center; gap: var(--s2); min-height: 44px; }
.resultrow { justify-content: flex-end; flex-wrap: wrap; }
.dockrow .off { visibility: hidden; pointer-events: none; }
.sol-dock .actions { justify-content: flex-start; margin-left: 0; }
.play-tools { display: flex; align-items: center; gap: var(--s2); }
.actions .play-tools .btn { min-width: 84px; }
.actions .hintbtn { min-width: 96px; }
.actions .hintbtn.finish { background: var(--btn); color: var(--btn-ink); border: var(--btn-edge); font-weight: var(--btn-weight); }
.moves { margin-left: auto; min-width: 9ch; text-align: right; color: var(--soft); font-size: var(--t-note); font-variant-numeric: tabular-nums; white-space: nowrap; }
/* Restart, New deal and Give up: quiet, in the dock where they can be found. A
   question ("Give up?") takes the button's own place at its own size (both
   words are in it, one unseen), and the button keeps its border so a disabled,
   dashed one doesn't change size. */
.deal-tools { display: flex; align-items: center; gap: 0; margin-left: var(--s3); }
.deal-tools .btn { border: 2px solid transparent; }
.deal-tools .btn[disabled] { border: 2px dashed color-mix(in srgb, var(--soft) 70%, transparent); text-decoration: none; }
.askbtn { display: inline-grid; place-items: center; }
.askbtn > span { grid-area: 1 / 1; white-space: nowrap; }
.askbtn:not(.ask) .q, .askbtn.ask .lab { visibility: hidden; }
.askbtn.ask {
  background: var(--confirm, var(--bad)); color: var(--confirm-ink); border-color: var(--confirm, var(--bad)); border-radius: var(--btn-radius); text-decoration: none; font-weight: 700;
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--confirm, var(--bad)) 35%, transparent);
}
.btn.busy { cursor: progress; opacity: .8; }

/* the cascade */
.sol-cascade { position: fixed; inset: 0; z-index: 40; pointer-events: none; overflow: hidden; transition: opacity 1.4s ease; }
.sol-cascade.fading { opacity: 0; }
.sol-cascade .card { position: fixed; left: 0; top: 0; margin: 0; width: var(--cw); height: var(--ch); transition: none; box-shadow: var(--card-shadow), 0 -1px 2px rgba(0, 0, 0, .25); }

/* the result sheet's four buttons fit on one row (the kit’s is 480px) */
.house-scrim-result .house-sheet.house-result { --house-sheet-width: 680px; }

/* ── how to play (the house sheet) ───────────────────────────────────── */
.sol-sample { display: flex; align-items: center; flex-wrap: wrap; gap: 10px; margin: 10px 0 12px; }
.sol-sample .then { color: var(--_soft, var(--soft)); font-size: var(--t-note); }
.house-body .rules { margin: 8px 0; padding-left: 20px; }
.house-body .rules li { margin: 6px 0; }
/* on a wide screen it opens into two columns */
.sol-howto { columns: 2 22em; column-gap: var(--s4); }
.sol-howto > * { break-inside: avoid; }
.sol-howto > h3:first-child { margin-top: 0; }
.sol-howto h3 { break-after: avoid; }

/* ── home ────────────────────────────────────────────────────────────── */
.felt.sol-home { gap: 0; }
.home-bar .tools { align-items: center; }
/* (its column, kicker, title and lead are the room's page skeleton: .lobby in room.css) */
.sol-wrap { flex: 1; }
.sol .waiting { margin: var(--s4) 0; }

.picker { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--s2); }
.gamepick {
  appearance: none; cursor: pointer; text-align: left; color: var(--ink); background: var(--panel); border: var(--field-edge); border-radius: 12px;
  padding: var(--s2) 12px 12px; display: flex; flex-direction: column; gap: var(--s1); min-width: 0;
}
.gamepick:hover { background: color-mix(in srgb, var(--ink) 8%, var(--panel)); }
.gamepick[aria-pressed="true"] { background: var(--pick-tint); box-shadow: var(--pick-ring); }
.gamepick:focus-visible { outline: 2px solid var(--focus, var(--ink)); outline-offset: 3px; box-shadow: 0 0 0 5px var(--room); }
.gamepick .art { width: 100%; height: auto; aspect-ratio: 72 / 40; display: block; margin-bottom: var(--s1); }
.art .c { fill: var(--card); stroke: color-mix(in srgb, #000 38%, transparent); stroke-width: .5; }
.art .c.back { fill: var(--back); }
.gamepick .gname { font: var(--display-weight) var(--t-heading) / 1.2 var(--display); }
.gamepick .gblurb { font-size: var(--t-note); line-height: 1.35; color: color-mix(in srgb, var(--soft) 45%, var(--ink)); min-height: 4.05em; }
.gamepick .grate { font-size: 13px; color: color-mix(in srgb, var(--soft) 45%, var(--ink)); font-variant-numeric: tabular-nums; margin-top: auto; padding-top: var(--s1); }
.drawrow .house-setting { border-bottom: 0; padding: 0; }

.section-head { display: flex; justify-content: space-between; align-items: baseline; gap: var(--s2); flex-wrap: wrap; margin-bottom: var(--panel-gap); }
.section-head h2 { font: var(--display-weight) var(--t-heading) / var(--lh-heading) var(--display); }
.endless .note { flex: 1 1 14em; font-size: var(--t-note); }
.endless .note p { margin: 0; }
.endless .house-setting { margin-top: var(--s2); padding-bottom: 0; border-bottom: 0; }
.sol .row { display: flex; align-items: center; gap: var(--s2); flex-wrap: wrap; }
.resume { display: grid; gap: var(--s1); font-size: var(--t-note); }
.resume .label { font-size: var(--t-label); font-weight: 600; }
.resume ul { list-style: none; padding: 0; margin: 0; }
.resume li { padding: 3px 0; }
.resume a { color: var(--ink); text-underline-offset: 3px; }

/* ── phones: the table is the screen ─────────────────────────────────── */
@media (max-width: 640px) {
  .felt.sol-play { height: 100dvh; padding-top: max(var(--bar-top), env(safe-area-inset-top)); padding-bottom: max(var(--bar-top), env(safe-area-inset-bottom)); gap: 4px; }
  .sol-bar .wide { display: none; }
  .sol-bar .narrow { display: inline-flex; min-width: 36px; }
  .sol-bar .tools { gap: 0; }
  /* the dock's tools take two rows: Undo and Hint with the count, then Restart, New deal and Give up */
  .actions { flex-wrap: wrap; row-gap: 0; }
  .play-tools { order: 1; }
  .moves { order: 2; }
  .deal-tools { order: 3; flex: 1 0 100%; margin-left: 0; justify-content: space-between; }
  .deal-tools .btn { flex: 1 1 0; padding-inline: 4px; }
  .picker { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .gamepick .gblurb { min-height: 0; }
}
@media (max-width: 480px) { .sol-bar .where .tag { display: none; } }
/* (on a narrow phone the bar has no room for Stats: it's beside the deal instead) */
.endless .to-stats { display: none; }
@media (max-width: 400px) { .home-bar .tool-stats { display: none; } .endless .to-stats { display: inline-flex; } }
/* home's bar: the account link (a long name) gives way before anything else */
.home-bar .tools { flex: 0 1 auto; min-width: 0; }
.home-bar .tools .btn { flex: none; }
.home-bar .tools .btn:last-child { flex: 0 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.sol-bar .title .short { display: none; }
@media (max-width: 400px) {
  .sol-bar .pause .long { display: none; }
  .sol-bar .pause .short { display: inline; }
}
/* (from 400px down the short name, and the clock gives up its spare width, so "Klondike · D3" isn't
   cut short beside tools a finger wide) */
@media (max-width: 400px) {
  .sol-bar .title .long { display: none; }
  .sol-bar .title .short { display: inline; }
  .sol-bar .timer { min-width: 4.2ch; padding-right: 0; }
}
@media (max-width: 380px) {
  .sol-bar .tag { font-size: 9px; padding: 3px 4px; }
  .actions .play-tools .btn { min-width: 72px; padding-inline: 10px; }
}
/* phones on their side: the bar and the dock stand down the left, and the table has the whole height */
@media (orientation: landscape) and (max-height: 520px) {
  /* (the table fills the screen, so the page's own 10px margin goes: a wide phone would lose the bottom 20px) */
  #app:has(> .sol-play) { padding: 0; }
  .felt.sol-play {
    height: 100dvh; padding: max(6px, env(safe-area-inset-top)) max(8px, env(safe-area-inset-right)) 6px max(8px, env(safe-area-inset-left));
    grid-template-columns: 168px minmax(0, 1fr); grid-template-rows: auto 1fr auto; grid-template-areas: "bar stage" ". stage" "dock stage"; column-gap: var(--s2);
    border-radius: 0; border-width: 0;
  }
  /* (the play screen's bar becomes a rail; a home's bar stays a bar) */
  .sol-play .sol-bar { grid-area: bar; flex-direction: column; align-items: stretch; gap: 2px; }
  .sol-play .sol-bar .where { flex: none; }
  .sol-play .sol-bar .title { font-size: 16px; }
  .sol-play .sol-bar .tools { flex-wrap: wrap; justify-content: space-between; }
  .sol-play .sol-bar .timer { order: -1; flex: 1 0 100%; text-align: left; }
  .sol-play .sol-bar .wide { display: none; }
  .sol-play .sol-bar .narrow { display: inline-flex; min-width: 44px; }
  .sol-play .sol-bar .pause .long { display: none; }
  .sol-play .sol-bar .pause .short { display: inline; }
  .sol-play .sol-bar .optbtn .long { display: none; }
  .sol-play .sol-bar .optbtn .short { display: inline; font-size: 18px; line-height: 1; }
  .sol-stage { grid-area: stage; }
  .sol-dock { grid-area: dock; }
  /* (the rail is narrow: what to do next wraps, rather than being cut short) */
  .sol-dock .status, .sol-dock .status span { white-space: normal; }
  /* the dock's buttons share the column: Undo and Hint, then the quiet ones in rows that wrap */
  .actions { flex-wrap: wrap; row-gap: 0; }
  .actions .play-tools .btn { min-width: 0; padding-inline: 10px; }
  .deal-tools { flex: 1 0 100%; margin-left: 0; flex-wrap: wrap; }
  .deal-tools .btn { padding-inline: 6px; }
  .moves { margin-left: 0; text-align: left; min-width: 0; }
  .resultrow { justify-content: flex-start; }
}
@media (prefers-reduced-motion: reduce) {
  .cd { transition: none !important; }
  .cd.turning .inner, .cd.turning .face, .cd.turning .back, .cd.nope .inner, .zmark.mk-hint, .cd.mk-hint .face { animation: none; }
  .sol-cascade { transition: none; }
}
