Update
This commit is contained in:
432
static/css/layout.css
Normal file
432
static/css/layout.css
Normal file
@@ -0,0 +1,432 @@
|
||||
:root {
|
||||
--ui-scale: 1.06;
|
||||
--base-font-size: clamp(16px, 0.35vw + 0.9rem, 20px);
|
||||
}
|
||||
|
||||
#desktop {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
padding: 4.3rem 1rem 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.mobile-control-strip {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
z-index: 50;
|
||||
padding: 0.45rem 0.55rem;
|
||||
}
|
||||
|
||||
.ui-controls {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.theme-picker {
|
||||
min-width: 9rem;
|
||||
}
|
||||
|
||||
.desktop-taskbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.config-window {
|
||||
width: min(78rem, 100%);
|
||||
}
|
||||
|
||||
.intro-copy {
|
||||
margin-bottom: 0.7rem;
|
||||
}
|
||||
|
||||
.room-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.65rem;
|
||||
}
|
||||
|
||||
.config-layout {
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
grid-template-columns: minmax(0, 1fr) 24rem;
|
||||
}
|
||||
|
||||
.config-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.field-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 0.6rem;
|
||||
}
|
||||
|
||||
.field-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.number-input-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.number-with-unit .input-unit {
|
||||
min-width: 2rem;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.preview-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.55rem;
|
||||
}
|
||||
|
||||
.preview-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.preview-board {
|
||||
min-height: 13rem;
|
||||
padding: 0.6rem;
|
||||
}
|
||||
|
||||
.preview-cards {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.preview-card {
|
||||
width: 3.15rem;
|
||||
height: 4.45rem;
|
||||
border-radius: 0.32rem;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
user-select: none;
|
||||
cursor: grab;
|
||||
transition: transform 170ms ease;
|
||||
}
|
||||
|
||||
.preview-card.dragging {
|
||||
opacity: 0.65;
|
||||
}
|
||||
|
||||
.preview-card.wiggle {
|
||||
animation: wiggle 250ms linear infinite;
|
||||
}
|
||||
|
||||
@keyframes wiggle {
|
||||
0% { transform: rotate(-2deg); }
|
||||
50% { transform: rotate(2deg); }
|
||||
100% { transform: rotate(-2deg); }
|
||||
}
|
||||
|
||||
.preview-card-remove {
|
||||
position: absolute;
|
||||
top: -0.35rem;
|
||||
right: -0.35rem;
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
opacity: 0;
|
||||
transition: opacity 120ms ease, transform 120ms ease;
|
||||
transform: scale(0.86);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.preview-card:hover .preview-card-remove,
|
||||
.preview-card-remove:focus {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.preview-card.is-removing {
|
||||
animation: card-pop-out 190ms ease forwards;
|
||||
}
|
||||
|
||||
@keyframes card-pop-out {
|
||||
from { opacity: 1; transform: scale(1); }
|
||||
to { opacity: 0; transform: scale(0.58) rotate(-10deg); }
|
||||
}
|
||||
|
||||
.card-editor {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.card-editor-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.deck-tools-row {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
width: 2.45rem;
|
||||
min-width: 2.45rem;
|
||||
height: 2.15rem;
|
||||
padding: 0.1rem;
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.icon-btn img {
|
||||
width: 1.05rem;
|
||||
height: 1.05rem;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.preset-modal-overlay {
|
||||
position: fixed;
|
||||
inset: 0;
|
||||
z-index: 70;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
|
||||
.preset-modal-window {
|
||||
width: min(40rem, 92vw);
|
||||
}
|
||||
|
||||
.preset-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.35rem;
|
||||
max-height: 11rem;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.preset-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 0.5rem;
|
||||
padding: 0.35rem;
|
||||
}
|
||||
|
||||
.preset-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.preset-modal-actions {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.35rem;
|
||||
}
|
||||
|
||||
.import-pane {
|
||||
margin-top: 0.5rem;
|
||||
}
|
||||
|
||||
.import-pane textarea {
|
||||
resize: vertical;
|
||||
}
|
||||
|
||||
.actions-row {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 0.4rem;
|
||||
}
|
||||
|
||||
.room-desktop {
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.room-grid {
|
||||
width: min(78rem, 100%);
|
||||
display: grid;
|
||||
gap: 0.75rem;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
}
|
||||
|
||||
.room-main-window,
|
||||
.side-panel-window {
|
||||
min-height: 40rem;
|
||||
}
|
||||
|
||||
.room-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 0.55rem;
|
||||
}
|
||||
|
||||
.voting-board {
|
||||
min-height: 14rem;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 0.5rem;
|
||||
padding: 0.6rem;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.vote-card {
|
||||
width: 4.3rem;
|
||||
height: 6rem;
|
||||
border-radius: 0.4rem;
|
||||
cursor: pointer;
|
||||
transition: transform 120ms ease;
|
||||
}
|
||||
|
||||
.vote-card:hover {
|
||||
transform: translateY(-0.2rem);
|
||||
}
|
||||
|
||||
.vote-summary-window {
|
||||
margin-top: 0.7rem;
|
||||
}
|
||||
|
||||
.vote-summary-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.45rem;
|
||||
}
|
||||
|
||||
.summary-metrics {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
.side-panel-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.55rem;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.participants-scroll {
|
||||
flex: 1;
|
||||
min-height: 13rem;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.participant-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 0.35rem;
|
||||
}
|
||||
|
||||
.side-controls {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.45rem;
|
||||
}
|
||||
|
||||
.links-block {
|
||||
display: grid;
|
||||
gap: 0.2rem;
|
||||
}
|
||||
|
||||
.admin-controls {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.join-window {
|
||||
position: fixed;
|
||||
z-index: 60;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: min(27rem, 92vw);
|
||||
}
|
||||
|
||||
.skeleton-line,
|
||||
.skeleton-board,
|
||||
.skeleton-table,
|
||||
.skeleton-list,
|
||||
.skeleton-controls {
|
||||
height: 1.2rem;
|
||||
}
|
||||
|
||||
.skeleton-board {
|
||||
height: 15rem;
|
||||
}
|
||||
|
||||
.skeleton-table {
|
||||
height: 8rem;
|
||||
}
|
||||
|
||||
.skeleton-list {
|
||||
height: 20rem;
|
||||
margin-bottom: 0.45rem;
|
||||
}
|
||||
|
||||
.skeleton-controls {
|
||||
height: 9rem;
|
||||
}
|
||||
|
||||
@media (min-width: 900px) {
|
||||
.mobile-control-strip {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.desktop-taskbar {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: flex-start;
|
||||
min-height: 2.5rem;
|
||||
padding: 0.3rem 0.55rem;
|
||||
}
|
||||
|
||||
#desktop {
|
||||
padding: 1rem 1rem 3.4rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.config-layout,
|
||||
.room-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.room-main-window,
|
||||
.side-panel-window {
|
||||
min-height: unset;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
#desktop {
|
||||
align-items: flex-start;
|
||||
padding-top: 3.65rem;
|
||||
}
|
||||
|
||||
.field-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.summary-metrics {
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 2560px), (min-resolution: 2dppx) {
|
||||
:root {
|
||||
--ui-scale: 1.24;
|
||||
}
|
||||
}
|
||||
181
static/css/main.css
Normal file
181
static/css/main.css
Normal file
@@ -0,0 +1,181 @@
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: calc(var(--base-font-size) * var(--ui-scale));
|
||||
}
|
||||
|
||||
body {
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-family: var(--font-main);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.mobile-control-strip,
|
||||
.taskbar {
|
||||
background: var(--surface-window);
|
||||
border-top: var(--window-border-width) solid var(--border-outer);
|
||||
box-shadow: var(--window-shadow);
|
||||
}
|
||||
|
||||
.taskbar {
|
||||
position: fixed;
|
||||
left: 0;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
z-index: 45;
|
||||
}
|
||||
|
||||
input,
|
||||
select,
|
||||
textarea,
|
||||
button {
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
.window {
|
||||
background: var(--surface-window);
|
||||
border: var(--window-border-width) solid var(--border-outer);
|
||||
box-shadow: var(--window-shadow);
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
background: var(--title-bg);
|
||||
color: var(--title-text);
|
||||
padding: 0.25rem 0.45rem;
|
||||
font-size: 1rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.title-bar-controls {
|
||||
display: inline-flex;
|
||||
gap: 0.12rem;
|
||||
}
|
||||
|
||||
.title-bar-controls button {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
font-size: 0.72rem;
|
||||
line-height: 0.6rem;
|
||||
border: var(--control-border-width) solid var(--border-outer);
|
||||
background: var(--surface-control);
|
||||
color: var(--text-primary);
|
||||
}
|
||||
|
||||
.window-content {
|
||||
padding: 0.75rem;
|
||||
}
|
||||
|
||||
.btn {
|
||||
border: var(--control-border-width) solid var(--border-outer);
|
||||
background: var(--surface-control);
|
||||
color: var(--text-primary);
|
||||
box-shadow: var(--button-shadow);
|
||||
padding: 0.3rem 0.65rem;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
box-shadow: var(--button-shadow-active);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
input[type="password"],
|
||||
select,
|
||||
textarea {
|
||||
background: var(--surface-input);
|
||||
color: var(--text-primary);
|
||||
border: var(--input-border-width) solid var(--border-input);
|
||||
padding: 0.35rem 0.45rem;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
input:focus,
|
||||
select:focus,
|
||||
textarea:focus {
|
||||
outline: none;
|
||||
box-shadow: var(--focus-ring);
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-outer-spin-button,
|
||||
input[type="number"]::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.status-line {
|
||||
background: var(--surface-status);
|
||||
border: var(--input-border-width) solid var(--border-input);
|
||||
padding: 0.32rem 0.5rem;
|
||||
min-height: 1.8rem;
|
||||
}
|
||||
|
||||
.participant-list {
|
||||
list-style: none;
|
||||
background: var(--surface-input);
|
||||
border: var(--input-border-width) solid var(--border-input);
|
||||
}
|
||||
|
||||
.participant-item {
|
||||
border-bottom: 1px dashed var(--border-muted);
|
||||
}
|
||||
|
||||
.participant-item:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.summary-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: var(--surface-input);
|
||||
}
|
||||
|
||||
.summary-table th,
|
||||
.summary-table td {
|
||||
border: 1px solid var(--border-muted);
|
||||
padding: 0.35rem 0.45rem;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.vote-card,
|
||||
.preview-card {
|
||||
border: var(--card-border-width) solid var(--card-border);
|
||||
background: var(--card-bg);
|
||||
color: var(--card-text);
|
||||
}
|
||||
|
||||
.vote-card.is-selected {
|
||||
outline: var(--selected-outline);
|
||||
outline-offset: -0.35rem;
|
||||
}
|
||||
|
||||
.vote-card.impact {
|
||||
animation: vote-impact 170ms ease;
|
||||
}
|
||||
|
||||
@keyframes vote-impact {
|
||||
0% { transform: scale(1); }
|
||||
40% { transform: scale(0.91); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
@@ -1,721 +0,0 @@
|
||||
:root {
|
||||
--desktop-bg: #008080;
|
||||
--window-bg: #c0c0c0;
|
||||
--window-text: #000000;
|
||||
--border-light: #ffffff;
|
||||
--border-dark: #000000;
|
||||
--border-mid-light: #dfdfdf;
|
||||
--border-mid-dark: #808080;
|
||||
--title-bg: #000080;
|
||||
--title-text: #ffffff;
|
||||
--input-bg: #ffffff;
|
||||
--status-bg: #b3b3b3;
|
||||
--board-bg: #0f6d3d;
|
||||
--card-bg: #ffffff;
|
||||
--card-text: #000000;
|
||||
}
|
||||
|
||||
[data-theme="dark"] {
|
||||
--desktop-bg: #0a0a0a;
|
||||
--window-bg: #2b2b2b;
|
||||
--window-text: #e0e0e0;
|
||||
--border-light: #555555;
|
||||
--border-dark: #000000;
|
||||
--border-mid-light: #3a3a3a;
|
||||
--border-mid-dark: #1a1a1a;
|
||||
--title-bg: #000000;
|
||||
--title-text: #00ff00;
|
||||
--input-bg: #111111;
|
||||
--status-bg: #1b1b1b;
|
||||
--board-bg: #0b2f16;
|
||||
--card-bg: #171717;
|
||||
--card-text: #00ff66;
|
||||
}
|
||||
|
||||
* {
|
||||
box-sizing: border-box;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
font-family: 'VT323', monospace;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--desktop-bg);
|
||||
color: var(--window-text);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
background-image: radial-gradient(circle, rgba(0, 0, 0, 0.12) 1px, transparent 1px);
|
||||
background-size: 4px 4px;
|
||||
}
|
||||
|
||||
#desktop {
|
||||
flex: 1;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 28px 16px 40px;
|
||||
}
|
||||
|
||||
.top-bar {
|
||||
position: fixed;
|
||||
top: 12px;
|
||||
right: 12px;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
.window {
|
||||
background-color: var(--window-bg);
|
||||
border: 2px solid;
|
||||
border-color: var(--border-light) var(--border-dark) var(--border-dark) var(--border-light);
|
||||
padding: 2px;
|
||||
box-shadow: inset 1px 1px var(--border-mid-light), inset -1px -1px var(--border-mid-dark);
|
||||
}
|
||||
|
||||
.title-bar {
|
||||
background-color: var(--title-bg);
|
||||
color: var(--title-text);
|
||||
padding: 2px 4px;
|
||||
font-size: 1.25rem;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
letter-spacing: 0.8px;
|
||||
}
|
||||
|
||||
.title-bar-controls {
|
||||
display: inline-flex;
|
||||
gap: 2px;
|
||||
}
|
||||
|
||||
.title-bar-controls button {
|
||||
background: var(--window-bg);
|
||||
border: 1px solid;
|
||||
border-color: var(--border-light) var(--border-dark) var(--border-dark) var(--border-light);
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
font-size: 0.8rem;
|
||||
line-height: 10px;
|
||||
text-align: center;
|
||||
color: var(--window-text);
|
||||
font-weight: bold;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.window-content {
|
||||
padding: 12px;
|
||||
}
|
||||
|
||||
.room-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.field-group {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.field-group label,
|
||||
legend {
|
||||
font-size: 1.2rem;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
input[type="text"],
|
||||
input[type="number"],
|
||||
input[type="password"],
|
||||
select {
|
||||
background: var(--input-bg);
|
||||
color: var(--window-text);
|
||||
border: 2px solid;
|
||||
border-color: var(--border-dark) var(--border-light) var(--border-light) var(--border-dark);
|
||||
padding: 5px 6px;
|
||||
font-size: 1.2rem;
|
||||
width: 100%;
|
||||
outline: none;
|
||||
}
|
||||
|
||||
input:focus,
|
||||
select:focus {
|
||||
box-shadow: inset 0 0 0 1px var(--title-bg);
|
||||
}
|
||||
|
||||
input[type="number"] {
|
||||
appearance: textfield;
|
||||
-moz-appearance: textfield;
|
||||
}
|
||||
|
||||
input[type="number"]::-webkit-outer-spin-button,
|
||||
input[type="number"]::-webkit-inner-spin-button {
|
||||
-webkit-appearance: none;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.number-input-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
background: var(--input-bg);
|
||||
border: 2px solid;
|
||||
border-color: var(--border-dark) var(--border-light) var(--border-light) var(--border-dark);
|
||||
padding: 0 6px;
|
||||
min-height: 38px;
|
||||
}
|
||||
|
||||
.number-input-wrap input[type="number"] {
|
||||
border: 0;
|
||||
box-shadow: none;
|
||||
background: transparent;
|
||||
padding: 5px 0;
|
||||
}
|
||||
|
||||
.number-with-unit {
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.input-unit {
|
||||
font-size: 1rem;
|
||||
opacity: 0.8;
|
||||
min-width: 26px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
.btn {
|
||||
background: var(--window-bg);
|
||||
color: var(--window-text);
|
||||
border: 2px solid;
|
||||
border-color: var(--border-light) var(--border-dark) var(--border-dark) var(--border-light);
|
||||
box-shadow: inset 1px 1px var(--border-mid-light), inset -1px -1px var(--border-mid-dark);
|
||||
padding: 4px 12px;
|
||||
font-size: 1.2rem;
|
||||
cursor: pointer;
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.btn:active {
|
||||
border-color: var(--border-dark) var(--border-light) var(--border-light) var(--border-dark);
|
||||
box-shadow: inset 1px 1px var(--border-mid-dark), inset -1px -1px var(--border-mid-light);
|
||||
padding: 5px 11px 3px 13px;
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.actions-row {
|
||||
text-align: right;
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.status-line {
|
||||
background: var(--status-bg);
|
||||
border: 2px solid;
|
||||
border-color: var(--border-dark) var(--border-light) var(--border-light) var(--border-dark);
|
||||
padding: 5px 8px;
|
||||
font-size: 1.1rem;
|
||||
min-height: 30px;
|
||||
}
|
||||
|
||||
.hidden {
|
||||
display: none !important;
|
||||
}
|
||||
|
||||
/* Config page */
|
||||
.config-window {
|
||||
width: 100%;
|
||||
max-width: 980px;
|
||||
}
|
||||
|
||||
.intro-copy {
|
||||
font-size: 1.3rem;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
|
||||
.config-layout {
|
||||
display: grid;
|
||||
grid-template-columns: minmax(0, 1fr) 340px;
|
||||
gap: 12px;
|
||||
align-items: start;
|
||||
}
|
||||
|
||||
.config-panel {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.field-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr 1fr;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.options-box {
|
||||
padding: 8px;
|
||||
}
|
||||
|
||||
.options-box legend {
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
.option-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
font-size: 1.2rem;
|
||||
margin: 6px 0;
|
||||
}
|
||||
|
||||
.option-item input[type="checkbox"] {
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
accent-color: #000080;
|
||||
}
|
||||
|
||||
[data-theme="dark"] .option-item input[type="checkbox"] {
|
||||
accent-color: #00aa00;
|
||||
}
|
||||
|
||||
.preview-window {
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.preview-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
}
|
||||
|
||||
.preview-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.preview-board {
|
||||
background: var(--board-bg);
|
||||
border: 2px solid;
|
||||
border-color: var(--border-dark) var(--border-light) var(--border-light) var(--border-dark);
|
||||
border-radius: 2px;
|
||||
min-height: 190px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.preview-cards {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 8px;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.preview-card {
|
||||
position: relative;
|
||||
width: 50px;
|
||||
height: 72px;
|
||||
background: var(--card-bg);
|
||||
border: 2px solid #000;
|
||||
border-radius: 5px;
|
||||
color: var(--card-text);
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
font-size: 1.5rem;
|
||||
font-weight: bold;
|
||||
box-shadow: 1px 1px 0 rgba(0, 0, 0, 0.5);
|
||||
user-select: none;
|
||||
transition: transform 180ms ease;
|
||||
cursor: grab;
|
||||
}
|
||||
|
||||
.preview-card.dragging {
|
||||
opacity: 0.6;
|
||||
}
|
||||
|
||||
.preview-card.wiggle {
|
||||
animation: wiggle 250ms linear infinite;
|
||||
}
|
||||
|
||||
@keyframes wiggle {
|
||||
0% { transform: rotate(-2deg); }
|
||||
50% { transform: rotate(2deg); }
|
||||
100% { transform: rotate(-2deg); }
|
||||
}
|
||||
|
||||
.preview-card-remove {
|
||||
position: absolute;
|
||||
top: -6px;
|
||||
right: -6px;
|
||||
width: 18px;
|
||||
height: 18px;
|
||||
border: 1px solid;
|
||||
border-color: var(--border-light) var(--border-dark) var(--border-dark) var(--border-light);
|
||||
background: #a40000;
|
||||
color: #fff;
|
||||
font-size: 0.8rem;
|
||||
line-height: 14px;
|
||||
opacity: 0;
|
||||
transform: scale(0.85);
|
||||
pointer-events: none;
|
||||
transition: opacity 130ms ease, transform 130ms ease;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.preview-card:hover .preview-card-remove,
|
||||
.preview-card-remove:focus {
|
||||
opacity: 1;
|
||||
transform: scale(1);
|
||||
pointer-events: auto;
|
||||
}
|
||||
|
||||
.preview-card.is-removing {
|
||||
animation: card-pop-out 190ms ease forwards;
|
||||
}
|
||||
|
||||
@keyframes card-pop-out {
|
||||
from {
|
||||
opacity: 1;
|
||||
transform: scale(1) rotate(0deg);
|
||||
}
|
||||
to {
|
||||
opacity: 0;
|
||||
transform: scale(0.58) rotate(-10deg);
|
||||
}
|
||||
}
|
||||
|
||||
.hint-text {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.card-editor {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.card-editor label {
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.card-editor-row {
|
||||
display: grid;
|
||||
grid-template-columns: 1fr auto auto;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.deck-tools-row {
|
||||
display: flex;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.icon-btn {
|
||||
min-width: 36px;
|
||||
padding-left: 8px;
|
||||
padding-right: 8px;
|
||||
}
|
||||
|
||||
.preset-picker {
|
||||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.preset-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
max-height: 150px;
|
||||
overflow-y: auto;
|
||||
margin-bottom: 8px;
|
||||
}
|
||||
|
||||
.preset-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
gap: 8px;
|
||||
padding: 6px;
|
||||
border: 1px dashed var(--border-mid-dark);
|
||||
}
|
||||
|
||||
.preset-meta {
|
||||
font-size: 1rem;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
.preset-actions {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.preset-actions .btn {
|
||||
font-size: 1rem;
|
||||
padding: 2px 8px;
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.import-btn {
|
||||
margin-left: 0;
|
||||
}
|
||||
|
||||
.import-pane {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.import-pane textarea {
|
||||
width: 100%;
|
||||
resize: vertical;
|
||||
background: var(--input-bg);
|
||||
color: var(--window-text);
|
||||
border: 2px solid;
|
||||
border-color: var(--border-dark) var(--border-light) var(--border-light) var(--border-dark);
|
||||
padding: 6px;
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
/* Room page */
|
||||
.room-desktop {
|
||||
align-items: stretch;
|
||||
justify-content: center;
|
||||
padding-top: 60px;
|
||||
}
|
||||
|
||||
.room-grid {
|
||||
width: min(1180px, 100%);
|
||||
display: grid;
|
||||
gap: 12px;
|
||||
grid-template-columns: 2fr 1fr;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.room-main-window,
|
||||
.side-panel-window {
|
||||
min-height: 640px;
|
||||
}
|
||||
|
||||
.room-meta {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-bottom: 10px;
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.voting-board {
|
||||
background: var(--board-bg);
|
||||
border: 2px solid;
|
||||
border-color: var(--border-dark) var(--border-light) var(--border-light) var(--border-dark);
|
||||
min-height: 230px;
|
||||
padding: 12px;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 10px;
|
||||
align-content: flex-start;
|
||||
}
|
||||
|
||||
.vote-card {
|
||||
width: 72px;
|
||||
height: 100px;
|
||||
border-radius: 6px;
|
||||
border: 2px solid #000;
|
||||
background: var(--card-bg);
|
||||
color: var(--card-text);
|
||||
font-size: 2rem;
|
||||
box-shadow: 2px 2px 0 rgba(0, 0, 0, 0.45);
|
||||
cursor: pointer;
|
||||
transition: transform 120ms ease;
|
||||
}
|
||||
|
||||
.vote-card:hover {
|
||||
transform: translateY(-3px);
|
||||
}
|
||||
|
||||
.vote-card.is-selected {
|
||||
outline: 2px dotted currentColor;
|
||||
outline-offset: -6px;
|
||||
}
|
||||
|
||||
.vote-card.impact {
|
||||
animation: vote-impact 170ms ease;
|
||||
}
|
||||
|
||||
@keyframes vote-impact {
|
||||
0% { transform: scale(1); }
|
||||
40% { transform: scale(0.91); }
|
||||
100% { transform: scale(1); }
|
||||
}
|
||||
|
||||
.vote-summary-window {
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.vote-summary-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.summary-table {
|
||||
width: 100%;
|
||||
border-collapse: collapse;
|
||||
background: var(--input-bg);
|
||||
}
|
||||
|
||||
.summary-table th,
|
||||
.summary-table td {
|
||||
border: 1px solid var(--border-mid-dark);
|
||||
padding: 6px 8px;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.summary-metrics {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
font-size: 1.1rem;
|
||||
}
|
||||
|
||||
.side-panel-content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 10px;
|
||||
height: calc(100% - 4px);
|
||||
}
|
||||
|
||||
.participants-scroll {
|
||||
flex: 1;
|
||||
min-height: 250px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.participant-list {
|
||||
list-style: none;
|
||||
background: var(--input-bg);
|
||||
border: 2px solid;
|
||||
border-color: var(--border-dark) var(--border-light) var(--border-light) var(--border-dark);
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.participant-item {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
padding: 5px;
|
||||
border-bottom: 1px dashed var(--border-mid-dark);
|
||||
font-size: 1.15rem;
|
||||
}
|
||||
|
||||
.participant-item:last-child {
|
||||
border-bottom: 0;
|
||||
}
|
||||
|
||||
.side-controls {
|
||||
margin-top: auto;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.links-block {
|
||||
display: grid;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.links-block input {
|
||||
font-size: 1rem;
|
||||
}
|
||||
|
||||
.admin-controls {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
}
|
||||
|
||||
.join-window {
|
||||
position: fixed;
|
||||
z-index: 30;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
width: min(420px, 92vw);
|
||||
}
|
||||
|
||||
#join-error {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.skeleton-line,
|
||||
.skeleton-board,
|
||||
.skeleton-table,
|
||||
.skeleton-list,
|
||||
.skeleton-controls {
|
||||
background: linear-gradient(90deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.08));
|
||||
background-size: 220% 100%;
|
||||
animation: skeleton-shimmer 1.2s ease infinite;
|
||||
border: 1px solid var(--border-mid-dark);
|
||||
}
|
||||
|
||||
.skeleton-line {
|
||||
height: 18px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.skeleton-line.short {
|
||||
width: 40%;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.skeleton-board {
|
||||
height: 250px;
|
||||
}
|
||||
|
||||
.skeleton-table {
|
||||
height: 140px;
|
||||
}
|
||||
|
||||
.skeleton-list {
|
||||
height: 350px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
.skeleton-controls {
|
||||
height: 180px;
|
||||
}
|
||||
|
||||
@keyframes skeleton-shimmer {
|
||||
from { background-position: 0 0; }
|
||||
to { background-position: -200% 0; }
|
||||
}
|
||||
|
||||
@media (max-width: 960px) {
|
||||
.config-layout,
|
||||
.room-grid {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.room-main-window,
|
||||
.side-panel-window {
|
||||
min-height: unset;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 720px) {
|
||||
#desktop {
|
||||
align-items: flex-start;
|
||||
padding-top: 56px;
|
||||
}
|
||||
|
||||
.field-row {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
.actions-row {
|
||||
display: flex;
|
||||
justify-content: flex-end;
|
||||
gap: 8px;
|
||||
}
|
||||
|
||||
.summary-metrics {
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.btn {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
79
static/css/themes/modern.css
Normal file
79
static/css/themes/modern.css
Normal file
@@ -0,0 +1,79 @@
|
||||
:root[data-ui-theme="modern"] {
|
||||
--font-main: 'Segoe UI', 'Inter', Arial, sans-serif;
|
||||
--desktop-bg: #e8edf4;
|
||||
--desktop-pattern: linear-gradient(135deg, #eef3f8 0%, #dde7f2 100%);
|
||||
--surface-window: #ffffff;
|
||||
--surface-control: #f1f4f8;
|
||||
--surface-input: #ffffff;
|
||||
--surface-status: #f8fafc;
|
||||
--text-primary: #101828;
|
||||
--title-bg: #175cd3;
|
||||
--title-text: #ffffff;
|
||||
--border-outer: #c4ced9;
|
||||
--border-input: #b8c3d2;
|
||||
--border-muted: #d5dde8;
|
||||
--window-border-width: 1px;
|
||||
--control-border-width: 1px;
|
||||
--input-border-width: 1px;
|
||||
--window-shadow: 0 12px 30px rgba(16, 24, 40, 0.14);
|
||||
--button-shadow: none;
|
||||
--button-shadow-active: none;
|
||||
--focus-ring: 0 0 0 2px rgba(23, 92, 211, 0.22);
|
||||
--card-bg: #ffffff;
|
||||
--card-text: #101828;
|
||||
--card-border: #b8c3d2;
|
||||
--card-border-width: 1px;
|
||||
--selected-outline: 2px solid #175cd3;
|
||||
--modal-overlay: rgba(15, 23, 42, 0.35);
|
||||
}
|
||||
|
||||
:root[data-ui-theme="modern"][data-theme="dark"] {
|
||||
--desktop-bg: #0b1220;
|
||||
--desktop-pattern: linear-gradient(140deg, #111b2c 0%, #09101d 100%);
|
||||
--surface-window: #111827;
|
||||
--surface-control: #1f2937;
|
||||
--surface-input: #0f172a;
|
||||
--surface-status: #172033;
|
||||
--text-primary: #e5edf7;
|
||||
--title-bg: #1d4ed8;
|
||||
--title-text: #ffffff;
|
||||
--border-outer: #334155;
|
||||
--border-input: #3f5169;
|
||||
--border-muted: #334155;
|
||||
--window-shadow: 0 14px 34px rgba(0, 0, 0, 0.45);
|
||||
--focus-ring: 0 0 0 2px rgba(96, 165, 250, 0.34);
|
||||
--card-bg: #1e293b;
|
||||
--card-text: #e5edf7;
|
||||
--card-border: #334155;
|
||||
}
|
||||
|
||||
:root[data-ui-theme="modern"] body {
|
||||
background-color: var(--desktop-bg);
|
||||
background-image: var(--desktop-pattern);
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
:root[data-ui-theme="modern"] .window,
|
||||
:root[data-ui-theme="modern"] .vote-card,
|
||||
:root[data-ui-theme="modern"] .preview-card,
|
||||
:root[data-ui-theme="modern"] .btn,
|
||||
:root[data-ui-theme="modern"] input,
|
||||
:root[data-ui-theme="modern"] select,
|
||||
:root[data-ui-theme="modern"] textarea {
|
||||
border-radius: 0.45rem;
|
||||
}
|
||||
|
||||
:root[data-ui-theme="modern"] .preview-board,
|
||||
:root[data-ui-theme="modern"] .voting-board {
|
||||
background: linear-gradient(180deg, #0f6f54 0%, #0a5c45 100%);
|
||||
border: 1px solid var(--border-input);
|
||||
}
|
||||
|
||||
:root[data-ui-theme="modern"][data-theme="dark"] .preview-board,
|
||||
:root[data-ui-theme="modern"][data-theme="dark"] .voting-board {
|
||||
background: linear-gradient(180deg, #0b3e33 0%, #082d25 100%);
|
||||
}
|
||||
|
||||
:root[data-ui-theme="modern"] .preset-modal-overlay {
|
||||
background: var(--modal-overlay);
|
||||
}
|
||||
66
static/css/themes/no-theme.css
Normal file
66
static/css/themes/no-theme.css
Normal file
@@ -0,0 +1,66 @@
|
||||
:root[data-ui-theme="none"] {
|
||||
--font-main: ui-monospace, monospace;
|
||||
--desktop-bg: #ffffff;
|
||||
--desktop-pattern: none;
|
||||
--surface-window: transparent;
|
||||
--surface-control: #f5f5f5;
|
||||
--surface-input: #ffffff;
|
||||
--surface-status: #ffffff;
|
||||
--text-primary: #000000;
|
||||
--title-bg: transparent;
|
||||
--title-text: #000000;
|
||||
--border-outer: #bdbdbd;
|
||||
--border-input: #bdbdbd;
|
||||
--border-muted: #d3d3d3;
|
||||
--window-border-width: 1px;
|
||||
--control-border-width: 1px;
|
||||
--input-border-width: 1px;
|
||||
--window-shadow: none;
|
||||
--button-shadow: none;
|
||||
--button-shadow-active: none;
|
||||
--focus-ring: 0 0 0 1px #777777;
|
||||
--card-bg: #ffffff;
|
||||
--card-text: #000000;
|
||||
--card-border: #bdbdbd;
|
||||
--card-border-width: 1px;
|
||||
--selected-outline: 1px dashed #000000;
|
||||
--modal-overlay: rgba(0, 0, 0, 0.2);
|
||||
}
|
||||
|
||||
:root[data-ui-theme="none"][data-theme="dark"] {
|
||||
--desktop-bg: #111111;
|
||||
--surface-window: transparent;
|
||||
--surface-control: #232323;
|
||||
--surface-input: #161616;
|
||||
--surface-status: #161616;
|
||||
--text-primary: #e8e8e8;
|
||||
--title-bg: transparent;
|
||||
--title-text: #e8e8e8;
|
||||
--border-outer: #4a4a4a;
|
||||
--border-input: #4a4a4a;
|
||||
--border-muted: #3a3a3a;
|
||||
--focus-ring: 0 0 0 1px #9a9a9a;
|
||||
--card-bg: #161616;
|
||||
--card-text: #e8e8e8;
|
||||
--card-border: #4a4a4a;
|
||||
}
|
||||
|
||||
:root[data-ui-theme="none"] body {
|
||||
background-color: var(--desktop-bg);
|
||||
background-image: none;
|
||||
}
|
||||
|
||||
:root[data-ui-theme="none"] .title-bar-controls,
|
||||
:root[data-ui-theme="none"] .icon-btn img {
|
||||
display: none;
|
||||
}
|
||||
|
||||
:root[data-ui-theme="none"] .window,
|
||||
:root[data-ui-theme="none"] .preview-board,
|
||||
:root[data-ui-theme="none"] .voting-board {
|
||||
border-style: dashed;
|
||||
}
|
||||
|
||||
:root[data-ui-theme="none"] .preset-modal-overlay {
|
||||
background: var(--modal-overlay);
|
||||
}
|
||||
88
static/css/themes/win98.css
Normal file
88
static/css/themes/win98.css
Normal file
@@ -0,0 +1,88 @@
|
||||
:root:not([data-ui-theme]),
|
||||
:root[data-ui-theme="win98"] {
|
||||
--font-main: 'VT323', monospace;
|
||||
--desktop-bg: #008080;
|
||||
--desktop-pattern: radial-gradient(circle, rgba(0, 0, 0, 0.12) 1px, transparent 1px);
|
||||
--surface-window: #c0c0c0;
|
||||
--surface-control: #c0c0c0;
|
||||
--surface-input: #ffffff;
|
||||
--surface-status: #b3b3b3;
|
||||
--text-primary: #000000;
|
||||
--title-bg: #000080;
|
||||
--title-text: #ffffff;
|
||||
--border-outer: #000000;
|
||||
--border-input: #000000;
|
||||
--border-muted: #808080;
|
||||
--window-border-width: 2px;
|
||||
--control-border-width: 1px;
|
||||
--input-border-width: 2px;
|
||||
--window-shadow: inset 1px 1px #dfdfdf, inset -1px -1px #808080;
|
||||
--button-shadow: inset 1px 1px #dfdfdf, inset -1px -1px #808080;
|
||||
--button-shadow-active: inset 1px 1px #808080, inset -1px -1px #dfdfdf;
|
||||
--focus-ring: inset 0 0 0 1px #000080;
|
||||
--card-bg: #ffffff;
|
||||
--card-text: #000000;
|
||||
--card-border: #000000;
|
||||
--card-border-width: 2px;
|
||||
--selected-outline: 2px dotted currentColor;
|
||||
--modal-overlay: rgba(0, 0, 0, 0.45);
|
||||
}
|
||||
|
||||
:root[data-ui-theme="win98"][data-theme="dark"] {
|
||||
--desktop-bg: #0a0a0a;
|
||||
--desktop-pattern: radial-gradient(circle, rgba(0, 255, 80, 0.08) 1px, transparent 1px);
|
||||
--surface-window: #2b2b2b;
|
||||
--surface-control: #2b2b2b;
|
||||
--surface-input: #111111;
|
||||
--surface-status: #1b1b1b;
|
||||
--text-primary: #e0e0e0;
|
||||
--title-bg: #000000;
|
||||
--title-text: #00ff66;
|
||||
--border-outer: #000000;
|
||||
--border-input: #555555;
|
||||
--border-muted: #3b3b3b;
|
||||
--window-shadow: inset 1px 1px #3a3a3a, inset -1px -1px #1a1a1a;
|
||||
--button-shadow: inset 1px 1px #3a3a3a, inset -1px -1px #1a1a1a;
|
||||
--button-shadow-active: inset 1px 1px #1a1a1a, inset -1px -1px #3a3a3a;
|
||||
--focus-ring: inset 0 0 0 1px #00ff66;
|
||||
--card-bg: #171717;
|
||||
--card-text: #00ff66;
|
||||
--card-border: #555555;
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--desktop-bg);
|
||||
background-image: var(--desktop-pattern);
|
||||
background-size: 4px 4px;
|
||||
}
|
||||
|
||||
.preview-board,
|
||||
.voting-board {
|
||||
background: #0f6d3d;
|
||||
border: 2px solid #000;
|
||||
}
|
||||
|
||||
:root[data-ui-theme="win98"][data-theme="dark"] .preview-board,
|
||||
:root[data-ui-theme="win98"][data-theme="dark"] .voting-board {
|
||||
background: #0a2c14;
|
||||
}
|
||||
|
||||
.preset-modal-overlay {
|
||||
background: var(--modal-overlay);
|
||||
}
|
||||
|
||||
.skeleton-line,
|
||||
.skeleton-board,
|
||||
.skeleton-table,
|
||||
.skeleton-list,
|
||||
.skeleton-controls {
|
||||
background: linear-gradient(90deg, rgba(255, 255, 255, 0.08), rgba(255, 255, 255, 0.22), rgba(255, 255, 255, 0.08));
|
||||
background-size: 220% 100%;
|
||||
border: 1px solid var(--border-muted);
|
||||
animation: skeleton-shimmer 1.2s ease infinite;
|
||||
}
|
||||
|
||||
@keyframes skeleton-shimmer {
|
||||
from { background-position: 0 0; }
|
||||
to { background-position: -200% 0; }
|
||||
}
|
||||
@@ -13,7 +13,6 @@ const SPECIAL_CARD_ORDER = {
|
||||
'☕': 3,
|
||||
};
|
||||
|
||||
const themeToggleBtn = document.getElementById('theme-toggle');
|
||||
const roomConfigForm = document.getElementById('room-config-form');
|
||||
const statusLine = document.getElementById('config-status');
|
||||
const scaleSelect = document.getElementById('estimation-scale');
|
||||
@@ -29,14 +28,14 @@ const usernameInput = document.getElementById('username');
|
||||
const savePresetButton = document.getElementById('save-preset');
|
||||
const pickerToggleButton = document.getElementById('preset-picker-toggle');
|
||||
const shareDeckButton = document.getElementById('share-deck');
|
||||
const presetPicker = document.getElementById('preset-picker');
|
||||
const presetModalOverlay = document.getElementById('preset-modal-overlay');
|
||||
const presetModalCloseButton = document.getElementById('preset-modal-close');
|
||||
const presetModalDoneButton = document.getElementById('preset-modal-done');
|
||||
const presetList = document.getElementById('preset-list');
|
||||
const importToggleButton = document.getElementById('import-toggle');
|
||||
const importPane = document.getElementById('import-pane');
|
||||
const importInput = document.getElementById('import-b64');
|
||||
const importApplyButton = document.getElementById('import-apply');
|
||||
|
||||
let isDarkMode = false;
|
||||
let nextCardID = 1;
|
||||
let currentCards = [];
|
||||
let draggingCardID = '';
|
||||
@@ -48,17 +47,6 @@ if (savedUsername && !usernameInput.value) {
|
||||
usernameInput.value = savedUsername;
|
||||
}
|
||||
|
||||
themeToggleBtn.addEventListener('click', () => {
|
||||
isDarkMode = !isDarkMode;
|
||||
if (isDarkMode) {
|
||||
document.documentElement.setAttribute('data-theme', 'dark');
|
||||
themeToggleBtn.textContent = 'Light Mode';
|
||||
return;
|
||||
}
|
||||
|
||||
document.documentElement.removeAttribute('data-theme');
|
||||
themeToggleBtn.textContent = 'Dark Mode';
|
||||
});
|
||||
|
||||
function parseNumericCard(value) {
|
||||
if (!/^-?\d+(\.\d+)?$/.test(value)) {
|
||||
@@ -341,13 +329,13 @@ function renderPresetList() {
|
||||
}
|
||||
|
||||
function showPresetPicker() {
|
||||
presetPicker.classList.remove('hidden');
|
||||
presetModalOverlay.classList.remove('hidden');
|
||||
pickerToggleButton.setAttribute('aria-expanded', 'true');
|
||||
renderPresetList();
|
||||
}
|
||||
|
||||
function hidePresetPicker() {
|
||||
presetPicker.classList.add('hidden');
|
||||
presetModalOverlay.classList.add('hidden');
|
||||
pickerToggleButton.setAttribute('aria-expanded', 'false');
|
||||
}
|
||||
|
||||
@@ -414,7 +402,7 @@ savePresetButton.addEventListener('click', () => {
|
||||
});
|
||||
|
||||
pickerToggleButton.addEventListener('click', () => {
|
||||
if (presetPicker.classList.contains('hidden')) {
|
||||
if (presetModalOverlay.classList.contains('hidden')) {
|
||||
showPresetPicker();
|
||||
return;
|
||||
}
|
||||
@@ -464,20 +452,15 @@ importApplyButton.addEventListener('click', () => {
|
||||
}
|
||||
});
|
||||
|
||||
document.addEventListener('click', (event) => {
|
||||
const target = event.target;
|
||||
if (!(target instanceof Element)) {
|
||||
return;
|
||||
presetModalOverlay.addEventListener('click', (event) => {
|
||||
if (event.target === presetModalOverlay) {
|
||||
hidePresetPicker();
|
||||
}
|
||||
if (presetPicker.classList.contains('hidden')) {
|
||||
return;
|
||||
}
|
||||
if (presetPicker.contains(target) || pickerToggleButton.contains(target)) {
|
||||
return;
|
||||
}
|
||||
hidePresetPicker();
|
||||
});
|
||||
|
||||
presetModalCloseButton.addEventListener('click', hidePresetPicker);
|
||||
presetModalDoneButton.addEventListener('click', hidePresetPicker);
|
||||
|
||||
customCardInput.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
event.preventDefault();
|
||||
|
||||
@@ -3,7 +3,6 @@ const USERNAME_KEY = 'scrumPoker.username';
|
||||
const roomID = document.body.dataset.roomId;
|
||||
const params = new URLSearchParams(window.location.search);
|
||||
|
||||
const themeToggleBtn = document.getElementById('theme-toggle');
|
||||
const roomSkeleton = document.getElementById('room-skeleton');
|
||||
const roomGrid = document.getElementById('room-grid');
|
||||
const roomTitle = document.getElementById('room-title');
|
||||
@@ -28,8 +27,6 @@ const joinRoleInput = document.getElementById('join-role');
|
||||
const joinPasswordInput = document.getElementById('join-password');
|
||||
const joinAdminTokenInput = document.getElementById('join-admin-token');
|
||||
const joinError = document.getElementById('join-error');
|
||||
|
||||
let isDarkMode = false;
|
||||
let participantID = params.get('participantId') || '';
|
||||
let adminToken = params.get('adminToken') || '';
|
||||
let eventSource = null;
|
||||
@@ -38,17 +35,6 @@ const savedUsername = localStorage.getItem(USERNAME_KEY) || '';
|
||||
joinUsernameInput.value = savedUsername;
|
||||
joinAdminTokenInput.value = adminToken;
|
||||
|
||||
themeToggleBtn.addEventListener('click', () => {
|
||||
isDarkMode = !isDarkMode;
|
||||
if (isDarkMode) {
|
||||
document.documentElement.setAttribute('data-theme', 'dark');
|
||||
themeToggleBtn.textContent = 'Light Mode';
|
||||
return;
|
||||
}
|
||||
|
||||
document.documentElement.removeAttribute('data-theme');
|
||||
themeToggleBtn.textContent = 'Dark Mode';
|
||||
});
|
||||
|
||||
function setJoinError(message) {
|
||||
if (!message) {
|
||||
|
||||
75
static/js/ui-controls.js
Normal file
75
static/js/ui-controls.js
Normal file
@@ -0,0 +1,75 @@
|
||||
(() => {
|
||||
const THEME_KEY = 'scrumPoker.ui.theme';
|
||||
const MODE_KEY = 'scrumPoker.ui.mode';
|
||||
const DEFAULT_THEME = 'win98';
|
||||
|
||||
function applyTheme(theme) {
|
||||
const normalized = theme || DEFAULT_THEME;
|
||||
document.documentElement.setAttribute('data-ui-theme', normalized);
|
||||
}
|
||||
|
||||
function applyMode(mode) {
|
||||
if (mode === 'dark') {
|
||||
document.documentElement.setAttribute('data-theme', 'dark');
|
||||
return;
|
||||
}
|
||||
document.documentElement.removeAttribute('data-theme');
|
||||
}
|
||||
|
||||
function getCurrentMode() {
|
||||
return document.documentElement.getAttribute('data-theme') === 'dark' ? 'dark' : 'light';
|
||||
}
|
||||
|
||||
function syncControls() {
|
||||
const theme = document.documentElement.getAttribute('data-ui-theme') || DEFAULT_THEME;
|
||||
const mode = getCurrentMode();
|
||||
|
||||
document.querySelectorAll('[data-role="theme-picker"]').forEach((el) => {
|
||||
el.value = theme;
|
||||
});
|
||||
|
||||
document.querySelectorAll('[data-role="mode-toggle"]').forEach((el) => {
|
||||
el.textContent = mode === 'dark' ? 'Light Mode' : 'Dark Mode';
|
||||
});
|
||||
}
|
||||
|
||||
function initUIControls() {
|
||||
if (window.__uiControlsInitialized) {
|
||||
syncControls();
|
||||
return;
|
||||
}
|
||||
window.__uiControlsInitialized = true;
|
||||
|
||||
const savedTheme = localStorage.getItem(THEME_KEY) || DEFAULT_THEME;
|
||||
const savedMode = localStorage.getItem(MODE_KEY) || 'light';
|
||||
applyTheme(savedTheme);
|
||||
applyMode(savedMode);
|
||||
syncControls();
|
||||
|
||||
document.querySelectorAll('[data-role="theme-picker"]').forEach((picker) => {
|
||||
picker.addEventListener('change', (event) => {
|
||||
const value = event.target.value || DEFAULT_THEME;
|
||||
localStorage.setItem(THEME_KEY, value);
|
||||
applyTheme(value);
|
||||
syncControls();
|
||||
});
|
||||
});
|
||||
|
||||
document.querySelectorAll('[data-role="mode-toggle"]').forEach((button) => {
|
||||
button.addEventListener('click', () => {
|
||||
const next = getCurrentMode() === 'dark' ? 'light' : 'dark';
|
||||
localStorage.setItem(MODE_KEY, next);
|
||||
applyMode(next);
|
||||
syncControls();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
window.initUIControls = initUIControls;
|
||||
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', initUIControls, { once: true });
|
||||
} else {
|
||||
initUIControls();
|
||||
}
|
||||
})();
|
||||
Reference in New Issue
Block a user