diff --git a/solitaire_server/web/game.css b/solitaire_server/web/game.css index ff43283..217425d 100644 --- a/solitaire_server/web/game.css +++ b/solitaire_server/web/game.css @@ -1,21 +1,28 @@ /* Solitaire Quest — interactive game page. - Palette and card styles mirror replay.css; adds drag, selection, - HUD, and win-overlay layers. */ + Palette mirrors the Bevy app's Terminal (base16-eighties) design system. + Card faces/backs are PNG images served from /assets/cards/. */ + +@font-face { + font-family: "FiraMono"; + src: url("/assets/fonts/main.ttf") format("truetype"); +} :root { - --bg: #0f0a1f; - --felt: #0f4c30; - --panel: #1a0f2e; - --panel-hi: #2d1b69; - --text: #f5f0ff; - --text-muted: #b5a8d5; - --accent: #ffd23f; - --red: #cc3344; - --black: #1a0f2e; - --card-bg: #ffffff; - --card-border: #ccc; + --bg: #151515; + --felt: #0f5232; + --panel: #202020; + --panel-hi: #2a2a2a; + --text: #d0d0d0; + --text-muted: #a0a0a0; + --accent: #a54242; + --accent-hi: #c25e5e; + --red: #fb9fb1; + --black: #151515; + --drop-success: #acc267; + --card-bg: #f8f5f0; + --card-border: #c8b8a0; --card-w: 80px; - --card-h: 112px; + --card-h: 120px; --gap: 12px; --fan: 28px; } @@ -23,7 +30,7 @@ * { box-sizing: border-box; margin: 0; padding: 0; } body { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Helvetica, Arial, sans-serif; + font-family: "FiraMono", "Fira Mono", monospace; background: var(--bg); color: var(--text); min-height: 100vh; @@ -66,7 +73,7 @@ button { font-family: inherit; transition: background 120ms; } -button:hover { background: var(--accent); color: var(--black); } +button:hover { background: var(--accent); color: var(--text); } button:disabled { opacity: 0.4; cursor: default; } .toggle-label { @@ -84,25 +91,32 @@ button:disabled { opacity: 0.4; cursor: default; } main { flex: 1; display: flex; - justify-content: center; - align-items: flex-start; - padding: 20px; - overflow-x: auto; + flex-direction: column; + overflow: hidden; min-width: 0; } +/* Full-bleed felt surface — flex:1 reliably fills main's remaining height. */ #board { - position: relative; + flex: 1; background: var(--felt); - border-radius: 12px; - padding: 20px; - /* 7 columns wide */ - width: calc(7 * var(--card-w) + 6 * var(--gap) + 40px); - /* top row + generous fan budget for a 13-card column */ - height: calc(var(--card-h) + 28px + var(--card-h) + 12 * var(--fan) + 40px); + display: flex; + align-items: center; + justify-content: center; + overflow: hidden; cursor: default; } +/* Natural-size coordinate space for cards and slots. + The CSS transform scale is applied here, not on #board. */ +#card-area { + position: relative; + flex-shrink: 0; + width: calc(7 * var(--card-w) + 6 * var(--gap) + 40px); + height: calc(var(--card-h) + 28px + var(--card-h) + 12 * var(--fan) + 40px); + touch-action: none; /* prevent browser scroll/pan from stealing pointer events */ +} + /* Empty-pile slot markers */ .slot { position: absolute; @@ -114,8 +128,8 @@ main { } .slot.drop-active { - border-color: var(--accent); - background: rgba(255, 210, 63, 0.08); + border-color: var(--drop-success); + background: rgba(172, 194, 103, 0.10); } /* ── Cards ───────────────────────────────────────────────────────────── */ @@ -125,13 +139,15 @@ main { top: 0; left: 0; width: var(--card-w); height: var(--card-h); - background: var(--card-bg); + background-color: var(--card-bg); + background-size: cover; + background-position: center; + background-repeat: no-repeat; border: 1px solid var(--card-border); border-radius: 6px; box-shadow: 0 2px 5px rgba(0,0,0,0.35); - padding: 4px 6px; - font-weight: 600; - line-height: 1; + padding: 0; + overflow: hidden; cursor: grab; transition: transform 260ms cubic-bezier(0.22, 1, 0.36, 1), opacity 200ms ease, @@ -142,40 +158,12 @@ main { .card:active { cursor: grabbing; } .card.face-down { - background: - repeating-linear-gradient( - 45deg, - #482f97 0, #482f97 6px, - #2d1b69 6px, #2d1b69 12px - ); + background-color: #2d1b69; color: transparent; border-color: #4a3a8a; cursor: default; } -.card .corner { - position: absolute; - font-size: 14px; - line-height: 1.1; - text-align: center; -} -.card .corner.top { top: 4px; left: 6px; } -/* No rotation — ♠ rotated 180° is indistinguishable from ♥ */ -.card .corner.bottom { bottom: 4px; right: 6px; text-align: right; } - -.card.red { color: var(--red); } -.card.black { color: var(--black); } - -.card .center { - position: absolute; - top: 50%; left: 50%; - transform: translate(-50%, -50%); - font-size: 28px; -} - -/* Stock pile: pointer cursor since it's a click target, not draggable */ -.card.stock-card { cursor: pointer; } - /* Selected / being-dragged state */ .card.selected { box-shadow: 0 0 0 2px var(--accent), 0 4px 12px rgba(0,0,0,0.5); @@ -185,14 +173,19 @@ main { /* Drop-target highlight on cards (top of a tableau column) */ .card.drop-target { - box-shadow: 0 0 0 2px var(--accent), 0 4px 12px rgba(0,0,0,0.5); + box-shadow: 0 0 0 2px var(--drop-success), 0 4px 12px rgba(0,0,0,0.5); } -/* Recycle indicator on empty stock — JS sets transform to position it */ +/* Recycle indicator on empty stock — sized to match the slot, symbol centred */ .recycle-label { position: absolute; top: 0; left: 0; - font-size: 26px; + width: var(--card-w); + height: var(--card-h); + display: flex; + align-items: center; + justify-content: center; + font-size: 32px; color: rgba(255,255,255,0.3); pointer-events: none; } @@ -202,7 +195,7 @@ main { #win-overlay { position: fixed; inset: 0; - background: rgba(10, 5, 20, 0.75); + background: rgba(21, 21, 21, 0.92); display: flex; align-items: center; justify-content: center; diff --git a/solitaire_server/web/game.html b/solitaire_server/web/game.html index f66ea14..b847fb8 100644 --- a/solitaire_server/web/game.html +++ b/solitaire_server/web/game.html @@ -28,7 +28,9 @@
-
+
+
+