:root { color: #e8e5dc; background: #101313; font-family: Arial, Helvetica, sans-serif; font-synthesis: none; --gold: #c9a34b; --gold-dim: #725e30; --ink: #25241f; --felt-top: #242829; --felt-bottom: #111414; --line: rgba(226, 220, 202, 0.16); --ivory: #eee9dc; --color-0: #b94737; --color-1: #3569a7; --color-2: #397b4e; --color-3: #b37d20; --color-4: #704487; } * { box-sizing: border-box; } html, body, #root { min-width: 1024px; min-height: 100%; margin: 0; } /* Below the supported minimum width/height the board no longer shrinks (app-shell keeps a 1024x720 floor), so allow scrolling instead of clipping content the user has no other way to reach. */ body { min-height: 100vh; overflow: auto; background: #101313; } button { color: inherit; font: inherit; } button:focus-visible { outline: 2px solid var(--gold); outline-offset: 4px; } .app-shell { position: relative; width: 100vw; min-width: 1024px; height: 100vh; min-height: 720px; overflow: hidden; isolation: isolate; background: radial-gradient(ellipse at 50% 42%, rgba(51, 57, 57, 0.78) 0%, rgba(30, 34, 34, 0.66) 47%, transparent 72%), linear-gradient(180deg, var(--felt-top), var(--felt-bottom)); } .app-shell::before { position: absolute; inset: 0; z-index: -1; content: ""; pointer-events: none; opacity: 0.42; background-image: repeating-radial-gradient(circle at 20% 30%, transparent 0 2px, rgba(255, 255, 255, 0.018) 3px, transparent 4px), repeating-linear-gradient(97deg, rgba(255, 255, 255, 0.012) 0 1px, transparent 1px 4px); mix-blend-mode: soft-light; } .score-plaque { position: absolute; left: 24px; /* Below the hand rows in stacking order: the hand's card layout keeps clear of the plaques at all supported widths, but this ensures a click always lands on a card, never the plaque, if that ever regresses. */ z-index: 6; width: 236px; height: 64px; padding: 10px 15px; display: flex; align-items: center; justify-content: space-between; border: 1px solid rgba(202, 190, 159, 0.22); border-radius: 14px; background: linear-gradient(145deg, rgba(8, 15, 14, 0.96), rgba(14, 24, 22, 0.94)); box-shadow: 0 16px 40px rgba(0, 0, 0, 0.18); } .score-plaque--rival { top: 14px; } .score-plaque--human { bottom: 14px; border-color: var(--gold); } .score-plaque div { min-width: 0; display: flex; flex-direction: column; gap: 7px; } .score-plaque strong { color: #efeee9; font: 700 14px/1 Arial, sans-serif; letter-spacing: 0.2em; } .score-plaque small { max-width: 155px; overflow: hidden; color: #858784; font: 500 9px/1 Arial, sans-serif; letter-spacing: 0.08em; text-overflow: ellipsis; white-space: nowrap; } .score-plaque > b { color: #e9e6dd; font: 700 30px/1 Georgia, serif; } .score-plaque--human > b { color: var(--gold); } .score-plaque i { display: inline-block; width: 6px; height: 6px; margin-left: 4px; transform: rotate(45deg) translateY(-2px); background: var(--gold); } .opponent-hand { position: absolute; top: 9px; left: 50%; z-index: 8; height: 58px; display: flex; transform: translateX(-50%); } .opponent-hand .card { margin-left: -14px; } .opponent-hand .card:first-child { margin-left: 0; } .menu-wrap { position: absolute; top: 16px; right: 24px; z-index: 20; } .menu-button { width: 92px; height: 39px; border: 1px solid var(--gold-dim); border-radius: 12px; background: rgba(7, 13, 12, 0.9); color: #e8e5dc; font: 700 10px Arial, sans-serif; letter-spacing: 0.18em; cursor: pointer; } .menu-button:hover { border-color: var(--gold); } .menu-popover { position: absolute; top: 47px; right: 0; width: 180px; padding: 8px; display: grid; gap: 6px; border: 1px solid rgba(201, 163, 75, 0.5); border-radius: 10px; background: rgba(8, 14, 13, 0.98); box-shadow: 0 18px 44px rgba(0, 0, 0, 0.45); } .menu-popover button { height: 36px; border: 1px solid rgba(255, 255, 255, 0.1); background: #111a18; color: #ddd9ce; font: 700 9px Arial, sans-serif; letter-spacing: 0.12em; cursor: pointer; } .menu-popover button:hover:not(:disabled) { border-color: var(--gold); } .menu-popover button:disabled { opacity: 0.3; cursor: default; } .menu-popover span { padding: 7px 4px 2px; color: #757a76; font: 8px Arial, sans-serif; letter-spacing: 0.08em; } .menu-seed { display: grid; gap: 4px; } .menu-seed span { padding: 4px 4px 0; color: var(--gold); } .menu-seed input { height: 32px; padding: 0 8px; border: 1px solid rgba(255, 255, 255, 0.14); border-radius: 4px; background: #0a1210; color: #ddd9ce; font: 11px/1 Arial, sans-serif; letter-spacing: 0.08em; } .menu-seed input:focus-visible { border-color: var(--gold); outline: none; } .table-center { position: absolute; top: 72px; bottom: 242px; left: 50%; width: clamp(610px, 43vw, 690px); transform: translateX(-50%); } .board { width: 100%; height: 100%; display: grid; grid-template-columns: repeat(5, minmax(0, 1fr)); } .lane { position: relative; min-width: 0; padding: 0 11px; display: grid; grid-template-rows: minmax(150px, 1fr) minmax(112px, 18%) 27px minmax(150px, 1fr); border: 1px solid color-mix(in srgb, var(--lane-color) 35%, transparent); border-radius: 8px; background: linear-gradient(180deg, color-mix(in srgb, var(--lane-color) 10%, transparent), color-mix(in srgb, var(--lane-color) 3%, transparent)); } .lane + .lane { margin-left: -2px; } .lane__zone, .lane__discard { position: relative; min-width: 0; padding: 0; display: flex; align-items: center; justify-content: center; border: 0; background: transparent; } button.lane__zone, button.lane__discard { width: 100%; cursor: default; } button.lane__zone:disabled, button.lane__discard:disabled { opacity: 1; } .lane__zone--opponent { align-items: flex-start; padding-top: 0; } .lane__zone--mine { align-items: flex-end; padding-bottom: 0; } .lane__discard { align-self: center; } .lane__name { align-self: center; color: rgba(226, 222, 211, 0.48); font: 700 10px Arial, sans-serif; letter-spacing: 0.2em; text-align: center; text-transform: uppercase; } .lane__ghost { width: 88px; height: 124px; display: grid; place-items: center; border: 1px solid rgba(231, 226, 210, 0.18); border-radius: 9px; color: color-mix(in srgb, var(--lane-color) 35%, #787b77); font: 42px/1 Georgia, serif; opacity: 0.45; } .lane__discard .lane__ghost { height: 122px; } .card-stack { position: relative; width: 88px; max-height: 100%; display: flex; flex-direction: column; align-items: center; } .card-stack .card + .card { margin-top: var(--stack-overlap, -94px); } .card-stack--opponent { justify-content: flex-start; } .card-stack--mine { justify-content: flex-end; } .score-chip { position: absolute; z-index: 9; min-width: 42px; padding: 5px 8px; border: 1px solid var(--gold-dim); border-radius: 10px; background: #0c1513; color: #ddd8ca; font: 700 10px Arial, sans-serif; text-align: center; } .lane__zone--opponent .score-chip { top: -5px; right: -5px; } .lane__zone--mine .score-chip { right: -5px; bottom: -5px; } .pile-count { position: absolute; right: 1px; bottom: 4px; z-index: 8; padding: 4px 7px; border: 1px solid var(--gold-dim); border-radius: 9px; background: #0b1211; color: #c8c0aa; font: 700 10px Arial, sans-serif; } .lane__zone.is-target, .lane__discard.is-target, .lane__discard.is-draw-target, .deck-stack.is-draw-target { cursor: pointer; animation: target-pulse 1.3s ease-in-out infinite; } .lane__zone.is-target .lane__ghost, .lane__discard.is-target .lane__ghost, .lane__discard.is-draw-target .lane__ghost, .lane__zone.is-chosen .lane__ghost, .lane__discard.is-chosen .lane__ghost { border-color: var(--gold); box-shadow: 0 0 0 2px rgba(201, 163, 75, 0.12), 0 0 30px color-mix(in srgb, var(--lane-color) 30%, transparent); opacity: 0.85; } .lane__zone.is-target .card, .lane__discard.is-target .card, .lane__discard.is-draw-target .card, .lane__zone.is-chosen .card, .lane__discard.is-chosen .card { box-shadow: 0 0 0 2px var(--gold), 0 0 28px rgba(201, 163, 75, 0.25); } @keyframes target-pulse { 50% { filter: brightness(1.22); } } /* Card travel between zones is played by the motion layer (src/ui/useCardMotion), which measures each card's old and new position and animates the difference. Only the flip cover it fades in and out lives here. */ .card__flip-cover { position: absolute; inset: -2px; z-index: 12; display: grid; place-items: center; border: 2px solid #67552d; border-radius: 11px; background: repeating-linear-gradient(135deg, #20252a 0 5px, #181c20 5px 10px); color: var(--gold); opacity: 0; pointer-events: none; } .card--compact .card__flip-cover { border-radius: 9px; } .card__flip-cover i { font: 24px/1 Georgia, serif; font-style: normal; } .card--back .card__flip-cover { display: none; } .motion-overlay { position: fixed; inset: 0; z-index: 30; pointer-events: none; } /* The hinted card, its destination, and its draw source. */ .card--hinted { box-shadow: 0 0 0 3px var(--gold), 0 0 26px rgba(201, 163, 75, 0.35); } .lane__zone.is-hinted, .lane__discard.is-hinted, .deck-stack.is-hinted { animation: target-pulse 1.6s ease-in-out infinite; } .lane__zone.is-hinted .lane__ghost, .lane__discard.is-hinted .lane__ghost { border-color: var(--gold); border-style: dashed; opacity: 0.9; } .lane__zone.is-hinted .card, .lane__discard.is-hinted .card, .deck-stack.is-hinted .card { box-shadow: 0 0 0 2px var(--gold), 0 0 26px rgba(201, 163, 75, 0.3); } @media (prefers-reduced-motion: reduce) { .lane__zone.is-target, .lane__discard.is-target, .lane__discard.is-draw-target, .lane__zone.is-hinted, .lane__discard.is-hinted, .deck-stack.is-hinted, .deck-stack.is-draw-target { animation: none; } } .card { --card-color: #888; position: relative; flex: 0 0 auto; width: 116px; height: 160px; padding: 0; overflow: hidden; border: 2px solid color-mix(in srgb, var(--card-color) 78%, #4c483d); border-radius: 11px; background: linear-gradient(145deg, #f4efe3, var(--ivory)); box-shadow: 0 8px 18px rgba(0, 0, 0, 0.38), inset 0 0 0 4px rgba(255, 255, 255, 0.35); color: var(--card-color); text-align: left; transition: transform 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease; } button.card { cursor: pointer; } button.card:not(:disabled):hover { z-index: 10; transform: translateY(-14px); filter: brightness(1.04); } button.card:disabled { cursor: default; } .card--selected { z-index: 11; transform: translateY(-24px); box-shadow: 0 0 0 3px var(--gold), 0 12px 28px rgba(0, 0, 0, 0.45), 0 0 34px rgba(201, 163, 75, 0.28); } .card__corner { position: absolute; left: 6px; display: flex; flex-direction: column; align-items: center; color: var(--card-color); font-family: Georgia, serif; } /* Cards overlap left-over-right, so the only strip that stays visible is each card's left edge -- exactly where the top corner sits. It carries a small ivory backing so the index reads even when it falls over the card behind it, which is what lets the hand overlap tightly and still be legible. */ .card__corner--top { top: 6px; z-index: 2; padding: 2px 5px 3px; border-radius: 7px; background: color-mix(in srgb, var(--ivory) 82%, transparent); box-shadow: 0 1px 3px rgba(0, 0, 0, 0.28); } .card__corner--bottom { right: 8px; bottom: 7px; left: auto; } .card__corner--top b { font-size: 20px; font-weight: 700; } .card__corner--top i { margin-top: 0; font-size: 13px; } .card__corner b { font-size: 18px; line-height: 1; } .card__corner i { margin-top: 1px; font-size: 12px; font-style: normal; line-height: 1; } .card__center { position: absolute; inset: 24px 14px; display: grid; place-content: center; justify-items: center; color: var(--card-color); font-family: Georgia, serif; } .card__center b { font-size: 48px; font-weight: 700; line-height: 0.9; } .card__center i { margin-top: 6px; font-size: 27px; font-style: normal; line-height: 1; } .card__center--handshake i { font-size: 44px; } .card__center small { margin-top: 8px; font: 700 8px Arial, sans-serif; letter-spacing: 0.14em; } .card::after { position: absolute; inset: 5px; border: 1px solid color-mix(in srgb, var(--card-color) 28%, transparent); border-radius: 7px; content: ""; pointer-events: none; } .card--compact { width: 88px; height: 124px; border-radius: 9px; } .card--compact .card__corner { left: 6px; } .card--compact .card__corner--bottom { right: 6px; left: auto; } .card--compact .card__corner b { font-size: 14px; } .card--compact .card__corner i { font-size: 9px; } .card--compact .card__center b { font-size: 34px; } .card--compact .card__center i { font-size: 20px; } .card--compact .card__center--handshake i { font-size: 31px; } .card--compact .card__center small { font-size: 6px; } /* Same footprint as a card back, so a revealed rival card sits in the hand row instead of bursting out of it. */ .card--mini { width: 44px; height: 58px; border-width: 2px; border-radius: 5px; } /* The rival's revealed cards overlap -14px, leaving a ~30px strip. The centered value is buried on every card but the top one, so a small top-left index rides in the visible strip -- the same trick as the player's hand, scaled down. */ .card--mini .card__corner--bottom { display: none; } .card--mini .card__corner--top { top: 3px; left: 3px; padding: 1px 3px 2px; border-radius: 5px; flex-direction: row; gap: 2px; align-items: baseline; } .card--mini .card__corner--top b { font-size: 13px; } .card--mini .card__corner--top i { font-size: 8px; } .card--mini .card__center { inset: 4px; top: 14px; } .card--mini .card__center b { font-size: 17px; } .card--mini .card__center i { margin-top: 2px; font-size: 10px; } .card--mini .card__center--handshake i { font-size: 16px; } .card--mini .card__center small { display: none; } .card--mini::after { inset: 3px; border-radius: 3px; } .card--mini .card__flip-cover { border-radius: 5px; } .card--back { width: 44px; height: 58px; padding: 4px; display: grid; place-items: center; border: 2px solid #67552d; border-radius: 5px; background: repeating-linear-gradient(135deg, #20252a 0 5px, #181c20 5px 10px); box-shadow: 0 6px 12px rgba(0, 0, 0, 0.4), inset 0 0 0 3px #171b1e; color: var(--gold); } .card--back::after { inset: 5px; border-color: rgba(201, 163, 75, 0.62); border-radius: 3px; } .card__back-frame { width: 26px; height: 26px; display: grid; place-items: center; border: 1px solid var(--gold-dim); border-radius: 50%; } .card__back-frame i { font: 18px/1 Georgia, serif; font-style: normal; } .card__count { position: absolute; right: 4px; bottom: 2px; font: 8px Arial, sans-serif; } .deck-stack { position: absolute; top: 35%; right: 4.4%; z-index: 7; width: 150px; padding: 0; display: flex; flex-direction: column; align-items: center; border: 0; background: transparent; } .deck-stack:disabled { opacity: 1; } .deck-stack .card--back { width: 88px; height: 122px; border-radius: 9px; box-shadow: 7px 8px 0 #171b1e, 12px 14px 25px rgba(0, 0, 0, 0.48), inset 0 0 0 5px #171b1e; } .deck-stack .card__back-frame { width: 56px; height: 56px; } .deck-stack .card__back-frame i { font-size: 38px; } .deck-stack strong { margin-top: 16px; color: #eee9de; font: 700 31px/1 Georgia, serif; } .deck-stack > span { margin-top: 5px; color: #7e817c; font: 700 9px Arial, sans-serif; letter-spacing: 0.2em; } .deck-stack.is-draw-target .card { box-shadow: 0 0 0 3px var(--gold), 7px 8px 0 #171b1e, 0 0 32px rgba(201, 163, 75, 0.3); } /* Insets keep the prompt clear of the controls parked at the right. */ .prompt-row { position: absolute; right: 330px; bottom: 202px; left: 330px; z-index: 7; display: flex; align-items: center; justify-content: center; gap: 14px; } .turn-prompt { min-width: 0; margin: 0; overflow: hidden; color: #dedbd3; font: 16px/1.2 Arial, sans-serif; text-align: center; text-overflow: ellipsis; white-space: nowrap; } .turn-prompt--thinking { color: #c6b887; } .turn-prompt--review { color: #9fb4c8; } .hint-button { height: 32px; padding: 0 14px; border: 1px solid var(--gold-dim); border-radius: 9px; background: rgba(7, 13, 12, 0.9); font: 700 9px Arial, sans-serif; letter-spacing: 0.16em; cursor: pointer; } .hint-button:hover:not(:disabled) { border-color: var(--gold); } .hint-button:disabled { opacity: 0.35; cursor: default; } .hint-button.is-active { border-color: var(--gold); color: var(--gold); } .human-hand { position: absolute; bottom: 30px; left: 50%; z-index: 8; height: 164px; display: flex; align-items: flex-end; justify-content: center; transform: translateX(-50%); } .human-hand .card { margin-left: 12px; } .human-hand .card:first-child { margin-left: 0; } .result-overlay { position: fixed; inset: 0; z-index: 40; display: grid; place-items: center; background: rgba(4, 8, 7, 0.78); backdrop-filter: blur(10px); } .result-card { width: min(520px, calc(100% - 40px)); max-height: calc(100vh - 40px); overflow-y: auto; padding: 32px 34px 26px; border: 1px solid var(--gold-dim); border-radius: 18px; background: #0b1211; box-shadow: 0 30px 80px rgba(0, 0, 0, 0.55); } .result-card__head { text-align: center; } .result-card__head p { margin: 0; color: #8d8d84; font: 700 9px Arial, sans-serif; letter-spacing: 0.2em; } .result-card__head h1 { margin: 10px 0 14px; color: #eee9dd; font: 700 32px Georgia, serif; } .result-card__head strong { display: block; color: var(--gold); font: 700 26px Georgia, serif; } .result-card__head i { color: #716b5b; font-style: normal; } .result-table { width: 100%; margin: 24px 0 20px; border-collapse: collapse; font: 12px Arial, sans-serif; } .result-table th, .result-table td { padding: 7px 6px; text-align: right; } .result-table thead th { color: #8d8d84; font: 700 9px Arial, sans-serif; letter-spacing: 0.14em; } .result-table thead tr:first-child th { border-bottom: 1px solid rgba(226, 220, 202, 0.14); } .result-table__subhead th { padding-top: 6px; color: #6d716e; } .result-table tbody th[scope="row"] { display: flex; align-items: center; gap: 8px; color: #cfcabd; font: 700 11px Arial, sans-serif; letter-spacing: 0.08em; text-align: left; } .result-table tbody th[scope="row"] i { color: var(--lane-color); font: 15px/1 Georgia, serif; font-style: normal; } .result-table tbody td { color: #ddd8ca; font: 700 13px Georgia, serif; } .result-table__detail { color: #7d817c !important; font: 11px Arial, sans-serif !important; } .result-table td.is-positive { color: #86c08c; } .result-table td.is-negative { color: #c98b7f; } .result-table tfoot th, .result-table tfoot td { padding-top: 12px; border-top: 1px solid rgba(226, 220, 202, 0.14); color: var(--gold); font: 700 15px Georgia, serif; } .result-table tfoot th { text-align: left; letter-spacing: 0.1em; } .result-card__foot { display: grid; gap: 14px; justify-items: center; } .result-card__foot small { color: #6d716e; font: 700 9px Arial, sans-serif; letter-spacing: 0.14em; } .result-card__foot div { display: flex; gap: 10px; } .result-card button { height: 42px; padding: 0 24px; border: 1px solid var(--gold-dim); border-radius: 10px; background: transparent; color: #ece8dc; font: 700 10px Arial, sans-serif; letter-spacing: 0.12em; cursor: pointer; } .result-card button:hover { border-color: var(--gold); } .result-card button.is-primary { border-color: var(--gold); color: var(--gold); } /* Player controls share the hand row's bottom edge and stay in the mirrored right-side keep-out reserved by the centered hand layout. */ .control-stack { position: absolute; right: 24px; bottom: 30px; z-index: 12; display: flex; width: 142px; flex-direction: column; align-items: stretch; gap: 8px; } .control-stack button { height: 32px; padding: 0 11px; display: flex; align-items: center; justify-content: center; gap: 6px; border: 1px solid var(--gold-dim); border-radius: 9px; background: rgba(7, 13, 12, 0.92); font: 700 13px/1 Georgia, serif; cursor: pointer; } .control-stack button span { font: 700 9px Arial, sans-serif; letter-spacing: 0.14em; } .control-stack button:hover:not(:disabled) { border-color: var(--gold); } .control-stack button:disabled { opacity: 0.3; cursor: default; } .control-stack__resume { border-color: var(--gold) !important; color: var(--gold); font: 700 9px Arial, sans-serif; letter-spacing: 0.14em; } .control-stack__score { visibility: hidden; } .control-stack__score.is-available { visibility: visible; } @media (max-width: 1250px) { .table-center { width: 600px; } .lane { padding: 0 7px; } .lane__ghost, .card--compact { width: 78px; height: 110px; } .human-hand .card { width: 98px; height: 142px; margin-left: 7px; } .human-hand { height: 146px; } .prompt-row { bottom: 177px; } .table-center { bottom: 210px; } /* Narrow viewports: the plaques are the keep-out that squeezes the hand row, so they become compact chips (model-name line dropped) to give the cards back their readable width. Mirrored by HAND_LAYOUTS in App.tsx. */ .score-plaque { left: 16px; width: 152px; height: 56px; padding: 8px 12px; } .score-plaque small { display: none; } .score-plaque strong { font-size: 12px; letter-spacing: 0.14em; } .score-plaque > b { font-size: 26px; } } @media (max-height: 820px) { .score-plaque { height: 54px; } .score-plaque--rival { top: 9px; } .opponent-hand { top: 5px; transform: translateX(-50%) scale(0.86); transform-origin: top center; } .table-center { top: 64px; bottom: 196px; } .human-hand { bottom: 18px; height: 138px; } .human-hand .card { width: 94px; height: 134px; } .prompt-row { bottom: 165px; } .control-stack { bottom: 18px; } .score-plaque--human { bottom: 9px; } .deck-stack { transform: scale(0.86); } } /* Match mode: which round is live, and what is already banked. The board only ever shows the round in play, so without this the score plaques would be the only hint that two more rounds are coming. */ .round-strip { position: absolute; top: 16px; left: 50%; transform: translateX(-50%); display: flex; align-items: center; gap: 8px; padding: 6px 12px; border-radius: 999px; background: rgba(18, 14, 10, 0.72); border: 1px solid rgba(214, 188, 140, 0.22); font-size: 11px; letter-spacing: 0.12em; color: rgba(214, 188, 140, 0.55); z-index: 4; pointer-events: none; } .round-strip span { font-weight: 700; } .round-strip span.is-done { color: rgba(214, 188, 140, 0.85); } .round-strip span.is-live { color: #f0d9a6; text-shadow: 0 0 10px rgba(240, 217, 166, 0.45); } .round-strip em { font-style: normal; margin-left: 4px; padding-left: 10px; border-left: 1px solid rgba(214, 188, 140, 0.22); color: rgba(214, 188, 140, 0.75); } .menu-modes { display: flex; gap: 6px; } .menu-modes button { flex: 1; font-size: 10px; } .menu-modes button.is-active { background: rgba(240, 217, 166, 0.16); color: #f0d9a6; border-color: rgba(240, 217, 166, 0.45); } /* A match's headline is the summed total; the table still breaks down the round in front of you, so the two have to be told apart. */ .result-card__banked { display: block; margin-top: 6px; font-size: 11px; letter-spacing: 0.1em; color: rgba(214, 188, 140, 0.55); } .result-table__match td, .result-table__match th { border-top: 1px solid rgba(214, 188, 140, 0.22); color: #f0d9a6; font-weight: 700; }