diff --git a/src/styles.css b/src/styles.css index 8a7c263..a1baaee 100644 --- a/src/styles.css +++ b/src/styles.css @@ -1,3 +1,560 @@ +/* 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 {