The table is a control surface, but the browser treats it as a document, so dragging across it painted card numbers and labels blue and popped a copy menu on a mobile long-press. Selection is now off across .app-shell and turned back on only for input/textarea -- in practice the seed field, the one place you would actually want to select and copy text. user-select touches neither click nor focus, so every button and card still responds. Verified in a browser: dragging across the hand and the score plaque selects nothing, while the seed field still selects and copies. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XBQKgvBbxbheiTF1AVy1Sh
804 lines
24 KiB
CSS
804 lines
24 KiB
CSS
: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; }
|
|
|
|
/* The table is a control surface, not a document. Dragging across it should never
|
|
paint a card's number blue or pop a long-press copy menu on mobile. Selection is
|
|
off everywhere and turned back on only for text you would actually want to copy
|
|
or edit -- in practice the seed field. user-select does not touch click or focus,
|
|
so every button still works. */
|
|
.app-shell {
|
|
user-select: none;
|
|
-webkit-user-select: none;
|
|
-webkit-touch-callout: none;
|
|
}
|
|
|
|
.app-shell input,
|
|
.app-shell textarea {
|
|
user-select: text;
|
|
-webkit-user-select: text;
|
|
}
|
|
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;
|
|
}
|