diff --git a/src/main.ts b/src/main.ts index a3a016f..0c640ed 100644 --- a/src/main.ts +++ b/src/main.ts @@ -789,122 +789,127 @@ function renderNewGameModal() { return ` - + `; diff --git a/src/styles.css b/src/styles.css index 07f7621..8a7c263 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,560 +1,3 @@ -/* Grid-based TV-Optimized Layout Framework */ - -:root { - color-scheme: dark; - font-family: Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif; - background: - radial-gradient(circle at top, rgba(48, 72, 104, 0.35), transparent 42%), - linear-gradient(180deg, #0b1220 0%, #070b13 100%); - color: #f4f7fb; - - /* Layout constants */ - --bottom-bar-height: 100px; - --sidebar-min-width: 280px; - --sidebar-max-width: 380px; - --gap-size: 0.75rem; - --padding-size: 0.75rem; -} - -* { - box-sizing: border-box; - margin: 0; - padding: 0; -} - -html, body { - height: 100%; - width: 100%; - overflow: hidden; - background: transparent; -} - -/* Main App Container - fills viewport accounting for browser chrome */ -#app { - width: 100%; - height: 100%; - display: flex; - align-items: center; - justify-content: center; - padding: 0.5rem; -} - -#app > * { - width: 100%; - height: calc(100vh - 100px); - max-width: 100%; - max-height: calc(100vh - 100px); - min-width: 0; - min-height: 0; -} - -/* Main Layout Grid */ -.layout { - width: 100%; - height: 100%; - display: grid; - grid-template-areas: - "main sidebar" - "bottom bottom"; - grid-template-columns: 1fr minmax(var(--sidebar-min-width), var(--sidebar-max-width)); - grid-template-rows: 1fr var(--bottom-bar-height); - gap: var(--gap-size); - padding: var(--padding-size); - overflow: hidden; -} - -/* Game Area - Main left section */ -.game-area { - grid-area: main; - display: flex; - flex-direction: column; - min-width: 0; - min-height: 0; - overflow: hidden; -} - -/* Board shell fills the game area */ -.board-shell { - flex: 1; - display: flex; - align-items: center; - justify-content: center; - border-radius: 1.25rem; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(9, 16, 29, 0.72); - backdrop-filter: blur(20px); - padding: 0.5rem; - min-height: 0; - overflow: hidden; -} - -/* Board - fits within shell */ -.board { - position: relative; - width: 100%; - height: 100%; - max-width: 100%; - max-height: 100%; - aspect-ratio: var(--board-columns) / var(--board-rows); - display: grid; - grid-template-columns: repeat(var(--board-columns), 1fr); - grid-template-rows: repeat(var(--board-rows), 1fr); - gap: clamp(2px, 0.3cqmin, 4px); - margin: 0 auto; -} - -/* Sidebar - Right panel */ -.sidebar { - grid-area: sidebar; - display: flex; - flex-direction: column; - gap: 0.75rem; - min-width: 0; - overflow: hidden; -} - -/* Bottom bar - Fixed height player scores */ -.scoreboard { - grid-area: bottom; - display: grid; - grid-template-columns: repeat(var(--player-count, 3), 1fr); - gap: 0.75rem; - height: 100%; - overflow: hidden; -} - -.score-card { - border: 1px solid rgba(255, 255, 255, 0.1); - border-radius: 1rem; - padding: 0.75rem 1rem; - background: linear-gradient(180deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.02)); - box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06); - display: flex; - flex-direction: column; - justify-content: center; - min-height: 0; -} - -.score-card.active { - border-color: color-mix(in srgb, var(--player-color) 55%, white); - box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.08), 0 0 24px var(--player-glow); -} - -/* Sidebar panels */ -.panel { - border-radius: 1.25rem; - border: 1px solid rgba(255, 255, 255, 0.08); - background: rgba(9, 16, 29, 0.72); - backdrop-filter: blur(20px); - padding: 0.75rem; - display: flex; - flex-direction: column; - min-height: 0; -} - -.controls-panel { - flex: 1; - display: flex; - flex-direction: column; - gap: 0.6rem; - overflow: auto; -} - -.log-panel { - max-height: 120px; - flex-shrink: 0; -} - -/* Cell styling */ -.cell { - position: relative; - background: rgba(255, 255, 255, 0.03); - border-radius: clamp(4px, 15%, 0.6rem); - border: 1px solid rgba(255, 255, 255, 0.05); - overflow: hidden; - min-width: 0; - min-height: 0; -} - -.cell__shade { - position: absolute; - inset: 0; - background: linear-gradient(180deg, rgba(255, 255, 255, 0.03), var(--column-tint)); -} - -.cell__root-ring { - position: absolute; - inset: 18% 18%; - border: 1px dashed rgba(255, 255, 255, 0.28); - border-radius: 999px; -} - -.cell__node, -.cell__target-label { - position: absolute; - inset: 50% auto auto 50%; - transform: translate(-50%, -50%); -} - -.cell__node { - width: min(40%, 1.4rem); - height: min(40%, 1.4rem); - min-width: 8px; - min-height: 8px; - border-radius: 50%; - background: var(--node-color); - box-shadow: 0 0 0 0.15rem rgba(255, 255, 255, 0.06), 0 0 1rem var(--node-glow); -} - -.cell.selected { - border-color: rgba(255, 255, 255, 0.55); - box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.22); -} - -.cell.pending { - border-color: rgba(255, 255, 255, 0.28); - box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 0 18px rgba(255, 255, 255, 0.08); -} - -.cell.pending .cell__node { - box-shadow: 0 0 0 0.18rem rgba(255, 255, 255, 0.08), 0 0 1.1rem var(--node-glow), 0 0 1.5rem rgba(255, 255, 255, 0.08); -} - -.cell.target { - border-color: rgba(255, 255, 255, 0.22); - background: rgba(255, 255, 255, 0.05); -} - -.cell.target:hover { - transform: translateY(-1px); -} - -.cell__target-label { - width: min(60%, 1.5rem); - height: min(60%, 1.5rem); - display: grid; - place-items: center; - border-radius: 999px; - background: rgba(255, 255, 255, 0.09); - border: 1px solid rgba(255, 255, 255, 0.18); - font-weight: 700; - font-size: clamp(0.6rem, 2cqmin, 0.9rem); -} - -/* Board overlays */ -.board__lines { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - pointer-events: none; - filter: drop-shadow(0 0 8px rgba(255, 255, 255, 0.18)); - z-index: 1; -} - -.board__fx { - position: absolute; - inset: 0; - width: 100%; - height: 100%; - pointer-events: none; - z-index: 4; -} - -.board__drop-layer { - position: absolute; - inset: 0; - pointer-events: none; - overflow: hidden; - z-index: 5; -} - -.board__energy-layer { - position: absolute; - inset: 0; - pointer-events: none; - z-index: 4; -} - -.board__energy-cell { - position: absolute; - border-radius: clamp(4px, 15%, 0.6rem); - background: - radial-gradient(circle at 50% 50%, rgba(255, 255, 255, 0.95), color-mix(in srgb, var(--flash-color) 70%, #ffe08a) 34%, rgba(255, 224, 138, 0.18) 72%, transparent 100%), - linear-gradient(180deg, rgba(255, 255, 255, 0.18), transparent); - box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.12), 0 0 18px color-mix(in srgb, var(--flash-color) 55%, #ffe08a); - opacity: 0; -} - -.board__energy-cell--sunlight { - inset: 12%; - background: - linear-gradient(180deg, rgba(255, 244, 214, 0.05), rgba(255, 244, 214, 0.008)), - radial-gradient(circle at 50% 50%, rgba(255, 242, 196, 0.11), color-mix(in srgb, var(--flash-color) 10%, #ffe3a3) 42%, rgba(255, 221, 128, 0.03) 72%, transparent 100%); - box-shadow: inset 0 0 0 1px rgba(255, 245, 224, 0.02), 0 0 6px color-mix(in srgb, var(--flash-color) 8%, #ffe3a3); -} - -.board--sunlight .board__energy-cell--sunlight, -.board--branches .board__energy-cell, -.board--bonus .board__energy-cell--bonus { - animation: energy-cell-flash 0.48s ease forwards; - animation-delay: var(--flash-delay, 0ms); -} - -.board__energy-cell--bonus { - box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.18), 0 0 22px rgba(255, 216, 94, 0.9); -} - -.board--bonus .board__drop--bonus { - animation: sunlight-drop 0.85s cubic-bezier(0.2, 0.7, 0.2, 1) forwards; -} - -.board__drop-core, -.board__drop-spark { - position: absolute; - inset: 0; - border-radius: 999px; -} - -.board__drop-core { - background: radial-gradient(circle at 35% 30%, rgba(255, 255, 255, 0.98), color-mix(in srgb, var(--drop-color) 72%, #ffe38a) 45%, rgba(255, 227, 138, 0.18) 100%); - box-shadow: 0 0 18px color-mix(in srgb, var(--drop-color) 40%, #ffe38a), 0 0 32px rgba(255, 236, 174, 0.65); -} - -.board__drop-spark { - inset: 35%; - border: 1px solid rgba(255, 248, 220, 0.95); - opacity: 0.9; -} - -.board__drop-spark--a { transform: translate(-0.8rem, -0.15rem) scale(0.55); } -.board__drop-spark--b { transform: translate(0.75rem, -0.1rem) scale(0.45); } -.board__drop-spark--c { transform: translate(0.1rem, -0.75rem) scale(0.35); } - -.board__root-burst, -.board__disease-mark, -.board__sunbeam-burst { - opacity: 0; -} - -.board__root-burst circle, -.board__sunbeam-burst { - fill: color-mix(in srgb, var(--burst-color, #ffd85e) 70%, white); - stroke: rgba(255, 255, 255, 0.65); - stroke-width: 0.35; -} - -.board__root-burst text { - fill: #08111c; - font-size: 2.1px; - font-weight: 800; -} - -.board__disease-mark circle { - fill: rgba(162, 255, 142, 0.2); - stroke: rgba(162, 255, 142, 0.9); - stroke-width: 0.35; -} - -.board__disease-mark path { - stroke: rgba(162, 255, 142, 1); - stroke-width: 0.5; - stroke-linecap: round; -} - -.board--branches .board__root-burst, -.board--events .board__root-burst, -.board--events .board__disease-mark, -.board--bonus .board__sunbeam-burst, -.board--events .board__sunbeam-burst { - animation: pop-fade 0.8s ease forwards; - animation-delay: var(--trace-delay, 0ms); -} - -.board__sunbeam-burst text { - fill: #08111c; - font-size: 2.1px; - font-weight: 800; -} - -/* Score card content */ -.score-card__head, -.score-card__numbers, -.panel__title-row, -.button-row, -.setup-grid, -.toggle-row, -.active-turn { - display: flex; - align-items: center; -} - -.score-card__head, -.panel__title-row, -.button-row, -.toggle-row { - justify-content: space-between; -} - -.score-card__identity { - display: flex; - align-items: center; - gap: 0.5rem; -} - -.score-card__head h2, -.panel h1, -.panel h2, -.active-turn h2 { - margin: 0; - font-size: clamp(0.9rem, 2.5cqmin, 1.2rem); -} - -.score-card__numbers { - margin-top: 0.5rem; - gap: 0.75rem; -} - -.score-card__footer { - margin-top: 0.5rem; - padding-top: 0.4rem; - border-top: 1px solid rgba(255, 255, 255, 0.08); - color: rgba(231, 238, 247, 0.72); - font-size: 0.75rem; -} - -.score-card__numbers div { - display: grid; - gap: 0.1rem; -} - -.score-card__numbers span, -.eyebrow, -label span, -.log-list p, -.status-panel p, -.active-turn p, -.effect-empty { - color: rgba(231, 238, 247, 0.72); -} - -.score-card__meta { - font-size: 0.75rem; - color: rgba(231, 238, 247, 0.7); -} - -.score-card__numbers strong { - font-size: 1.2rem; -} - -.score-value { - display: inline-block; -} - -.score-value.changed { - animation: score-pop 0.7s ease; -} - -.player-dot { - width: 0.85rem; - height: 0.85rem; - border-radius: 999px; - background: var(--player-color); - box-shadow: 0 0 16px var(--player-glow); -} - -/* Sidebar content */ -.panel__actions { - display: flex; - gap: 0.5rem; -} - -.eyebrow { - margin: 0 0 0.25rem; - font-size: 0.75rem; - letter-spacing: 0.1em; - text-transform: uppercase; -} - -.button-row { - gap: 0.5rem; -} - -.button-row button, -.ghost-button { - min-height: 2.4rem; - padding: 0.5rem 0.75rem; - border-radius: 0.85rem; - background: #f4f7fb; - color: #0a1020; - font-weight: 700; - font-size: 0.9rem; - border: none; - cursor: pointer; -} - -.ghost-button, -#finish-game { - background: rgba(255, 255, 255, 0.08); - color: #f4f7fb; - border: 1px solid rgba(255, 255, 255, 0.1); -} - -button:disabled { - opacity: 0.45; - cursor: not-allowed; -} - -.log-list { - display: grid; - gap: 0.4rem; - font-size: 0.8rem; - overflow: auto; -} - -.log-list p, -.status-panel p, -.active-turn p { - margin: 0; -} - -.event-note { - color: #ffd577; -} - -.active-turn { - flex-direction: column; - align-items: flex-start; - gap: 0.25rem; - padding: 0.6rem; - border-radius: 0.85rem; - background: linear-gradient(135deg, color-mix(in srgb, var(--player-color) 22%, rgba(255, 255, 255, 0.04)), rgba(255, 255, 255, 0.04)); - border: 1px solid color-mix(in srgb, var(--player-color) 35%, rgba(255, 255, 255, 0.08)); -} - -/* Form elements */ -button, -input, -select { - font: inherit; -} - -input[type="number"], -input[type="text"], -select { - width: 100%; - min-height: 2.4rem; - padding: 0.5rem 0.75rem; - border-radius: 0.75rem; - border: 1px solid rgba(255, 255, 255, 0.12); - background: rgba(255, 255, 255, 0.05); - color: #f4f7fb; - font-size: 0.9rem; -} - -input[type="range"] { - width: 100%; -} /* Modal styles */ .modal-backdrop { @@ -579,6 +22,212 @@ input[type="range"] { padding: 1rem; } +/* Setup Modal - Redesigned */ +.setup-modal { + display: flex; + flex-direction: column; + max-width: 900px; + padding: 0; +} + +.modal-header { + display: flex; + align-items: flex-start; + justify-content: space-between; + gap: 1rem; + padding: 1.25rem 1.5rem; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); +} + +.modal-header__title h1 { + font-size: 1.5rem; + font-weight: 700; + margin: 0; +} + +.modal-body { + flex: 1; + overflow-y: auto; + padding: 1.5rem; + display: flex; + flex-direction: column; + gap: 1.5rem; +} + +.modal-footer { + display: flex; + justify-content: flex-end; + gap: 0.75rem; + padding: 1rem 1.5rem; + border-top: 1px solid rgba(255, 255, 255, 0.08); + background: rgba(255, 255, 255, 0.02); +} + +/* Setup Sections */ +.setup-section { + display: flex; + flex-direction: column; + gap: 0.75rem; +} + +.setup-section__title { + font-size: 0.875rem; + font-weight: 600; + text-transform: uppercase; + letter-spacing: 0.05em; + color: rgba(255, 255, 255, 0.6); + margin: 0; + padding-bottom: 0.25rem; + border-bottom: 1px solid rgba(255, 255, 255, 0.08); +} + +.setup-section__help { + font-size: 0.875rem; + color: rgba(255, 255, 255, 0.5); + margin: 0; +} + +/* Setup Grid */ +.setup-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); + gap: 1rem; +} + +.setup-grid--2col { + grid-template-columns: repeat(2, 1fr); +} + +.setup-grid--3col { + grid-template-columns: repeat(3, 1fr); +} + +@media (max-width: 600px) { + .setup-grid, + .setup-grid--2col, + .setup-grid--3col { + grid-template-columns: 1fr; + } +} + +/* Setup Field */ +.setup-field { + display: flex; + flex-direction: column; + gap: 0.375rem; +} + +.setup-field__label { + font-size: 0.8125rem; + font-weight: 500; + color: rgba(255, 255, 255, 0.7); +} + +.setup-field__input { + display: flex; + align-items: center; + gap: 0.75rem; +} + +.setup-field__value { + font-size: 1.125rem; + font-weight: 700; + min-width: 1.5rem; +} + +.setup-field--range input[type="range"] { + flex: 1; +} + +.setup-field--checkbox { + flex-direction: row; + align-items: center; + gap: 0.75rem; +} + +.setup-field--checkbox .setup-field__label { + margin: 0; +} + +.setup-field input[type="number"], +.setup-field input[type="text"], +.setup-field select { + width: 100%; + min-height: 2.25rem; + padding: 0.5rem 0.625rem; + border-radius: 0.5rem; + border: 1px solid rgba(255, 255, 255, 0.12); + background: rgba(255, 255, 255, 0.05); + color: #f4f7fb; + font-size: 0.9375rem; +} + +.setup-field input[type="checkbox"] { + width: 1.25rem; + height: 1.25rem; + accent-color: #4a9eff; +} + +/* Player List */ +.player-list { + display: flex; + flex-direction: column; + gap: 0.5rem; +} + +.player-row { + display: flex; + align-items: center; + justify-content: space-between; + padding: 0.625rem 0.875rem; + background: rgba(255, 255, 255, 0.03); + border: 1px solid rgba(255, 255, 255, 0.06); + border-radius: 0.625rem; +} + +.player-row__info { + display: flex; + align-items: center; + gap: 0.625rem; +} + +.player-row__name { + font-weight: 600; +} + +.player-row__actions { + display: flex; + gap: 0.375rem; +} + +.player-row__actions .mini-button { + min-height: 1.75rem; + padding: 0.25rem 0.5rem; + font-size: 0.875rem; +} + +/* Mini button for player reordering */ +.mini-button { + min-height: 2rem; + padding: 0.375rem 0.625rem; + border-radius: 0.5rem; + background: rgba(255, 255, 255, 0.08); + color: #f4f7fb; + border: 1px solid rgba(255, 255, 255, 0.1); + font-weight: 600; + font-size: 0.875rem; + cursor: pointer; +} + +.mini-button:hover { + background: rgba(255, 255, 255, 0.12); +} + +.mini-button:disabled { + opacity: 0.35; + cursor: not-allowed; +} + .draft-panel { position: fixed; top: 1rem;