diff --git a/server.ts b/server.ts
index cacb8e9e129ffc111e45c4d6d1abefd706ef2f0b..39639e64651d927f35ccbd200eb0c3834a44bd68 100644
--- a/server.ts
+++ b/server.ts
@@ -542,6 +542,10 @@ serve(async (req) => {
const css = await Deno.readTextFile("./static/style.css");
return new Response(css, { headers: { "content-type": "text/css" } });
}
+ if (url.pathname === "/palette.css") {
+ const css = await Deno.readTextFile("./static/palette.css");
+ return new Response(css, { headers: { "content-type": "text/css" } });
+ }
if (url.pathname === "/app.js") {
const js = await Deno.readTextFile("./static/app.js");
return new Response(js, { headers: { "content-type": "application/javascript" } });
diff --git a/static/app.js b/static/app.js
index b364517bbee794c02815d730f6bf455550a2acdf..a4732da6d60fee072cfc2bd35bf0be06bf834741 100644
--- a/static/app.js
+++ b/static/app.js
@@ -50,6 +50,9 @@ document.getElementById('leave-btn').addEventListener('click', () => {
items = [];
messageQueue = [];
listContainer.innerHTML = '';
+
+ // Clear URL when leaving room
+ history.replaceState(null, '', location.pathname);
});
document.getElementById('copy-btn').addEventListener('click', async () => {
@@ -229,6 +232,11 @@ function handleMessage(msg) {
}
isReady = true;
setUIEnabled(true);
+
+ // Update URL to include room code for easy copying
+ const newUrl = `${location.origin}${location.pathname}?room=${currentRoom}`;
+ history.replaceState(null, '', newUrl);
+
renderTitle();
render();
break;
@@ -305,6 +313,13 @@ function vote(itemId, voteType) {
const sorted = getSortedItems();
selectedPosition = sorted.findIndex(i => i.id === itemId);
+ // Keep the button visually pressed briefly to avoid flicker
+ const btn = document.querySelector(`[data-item-id="${itemId}"] [data-action="vote"][data-vote-type="${voteType}"]`);
+ if (btn) {
+ btn.classList.add('press-lock');
+ setTimeout(() => btn.classList.remove('press-lock'), 220);
+ }
+
lastAction = { type: 'vote', itemId, previousVote: currentVote };
if (currentVote === voteType) {
@@ -569,15 +584,31 @@ function render() {
// Sort: vetoed items last, then by score
const sorted = getSortedItems();
+ // Check if any votes have been cast
+ const hasAnyVotes = sorted.some(item => Object.keys(item.votes).length > 0);
+
+ // Calculate highest score among non-vetoed items
+ const nonVetoedItems = sorted.filter(item =>
+ !Object.values(item.votes).includes('veto')
+ );
+ const highestScore = nonVetoedItems.length > 0
+ ? Math.max(...nonVetoedItems.map(item =>
+ Object.values(item.votes).reduce((sum, v) =>
+ sum + (v === 'up' ? 1 : v === 'down' ? -1 : 0), 0)
+ ))
+ : -Infinity;
+
listContainer.innerHTML = sorted.map(item => {
const myVote = item.votes[userId];
const score = Object.values(item.votes).reduce((sum, v) =>
sum + (v === 'up' ? 1 : v === 'down' ? -1 : 0), 0);
const isVetoed = Object.values(item.votes).includes('veto');
const isSelected = item.id === selectedItemId;
+ const isTopVoted = hasAnyVotes && !isVetoed && score === highestScore && nonVetoedItems.length > 0;
return `
-
+
+ ${isTopVoted ? '
' : ''}
${escapeHtml(item.text)}
${score > 0 ? '+' : ''}${score}
@@ -662,6 +693,15 @@ listContainer.addEventListener('dblclick', (e) => {
editItem(itemId);
});
+// Minimal press-lock for non-vote buttons to smooth release
+document.addEventListener('click', (e) => {
+ const btn = e.target.closest('button');
+ if (!btn) return;
+ if (btn.classList.contains('vote-btn')) return; // handled in vote()
+ btn.classList.add('press-lock');
+ setTimeout(() => btn.classList.remove('press-lock'), 180);
+});
+
// Make functions global
window.vote = vote;
window.deleteItem = deleteItem;
diff --git a/static/index.html b/static/index.html
index 6df8731dc25e52aa79aa35c8398411c0a42a4782..94e15797ca7340aa7d8d6b1ee70b20c19822fc38 100644
--- a/static/index.html
+++ b/static/index.html
@@ -10,6 +10,7 @@ SPDX-License-Identifier: AGPL-3.0-or-later
Sift
+
diff --git a/static/palette.css b/static/palette.css
new file mode 100644
index 0000000000000000000000000000000000000000..ce44f16fe75b8b777f0d23cd9b502da643f73249
--- /dev/null
+++ b/static/palette.css
@@ -0,0 +1,113 @@
+/*
+ * SPDX-FileCopyrightText: Amolith
+ *
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+/*
+ Colors generated by Theme Machine | MIT License
+ https://tools.keithjgrant.com/theme-machine/
+*/
+:root {
+ --stone-1: oklch(98% 0.003 121);
+ --stone-2: oklch(97% 0.006 121);
+ --stone-3: oklch(93% 0.01 121);
+ --stone-4: oklch(84% 0.011 121);
+ --stone-5: oklch(80% 0.015 121);
+ --stone-6: oklch(71% 0.018 121);
+ --stone-7: oklch(66% 0.019 121);
+ --stone-8: oklch(58% 0.02 121);
+ --stone-9: oklch(53% 0.019 121);
+ --stone-10: oklch(49% 0.018 121);
+ --stone-11: oklch(42% 0.016 121);
+ --stone-12: oklch(35% 0.014 121);
+ --stone-13: oklch(27% 0.011 121);
+ --stone-14: oklch(20% 0.009 121);
+ --stone-15: oklch(16% 0.007 121);
+ --stone-16: oklch(10% 0.005 121);
+ --stone: var(--stone-8);
+
+ --ash-1: oklch(98% 0.003 301);
+ --ash-2: oklch(97% 0.006 301);
+ --ash-3: oklch(93% 0.01 301);
+ --ash-4: oklch(84% 0.011 301);
+ --ash-5: oklch(80% 0.015 301);
+ --ash-6: oklch(71% 0.018 301);
+ --ash-7: oklch(66% 0.019 301);
+ --ash-8: oklch(58% 0.02 301);
+ --ash-9: oklch(53% 0.019 301);
+ --ash-10: oklch(49% 0.018 301);
+ --ash-11: oklch(42% 0.016 301);
+ --ash-12: oklch(35% 0.014 301);
+ --ash-13: oklch(27% 0.011 301);
+ --ash-14: oklch(20% 0.009 301);
+ --ash-15: oklch(16% 0.007 301);
+ --ash-16: oklch(10% 0.005 301);
+ --ash: var(--ash-8);
+
+ --avocado-1: oklch(98% 0.018 121);
+ --avocado-2: oklch(97% 0.038 121);
+ --avocado-3: oklch(93% 0.062 121);
+ --avocado-4: oklch(84% 0.074 121);
+ --avocado-5: oklch(80% 0.099 121);
+ --avocado-6: oklch(71% 0.117 121);
+ --avocado-7: oklch(66% 0.124 121);
+ --avocado-8: oklch(58% 0.13 121);
+ --avocado-9: oklch(53% 0.124 121);
+ --avocado-10: oklch(49% 0.117 121);
+ --avocado-11: oklch(42% 0.105 121);
+ --avocado-12: oklch(35% 0.092 121);
+ --avocado-13: oklch(27% 0.074 121);
+ --avocado-14: oklch(20% 0.056 121);
+ --avocado-15: oklch(16% 0.043 121);
+ --avocado-16: oklch(10% 0.028 122);
+ --avocado: var(--avocado-8);
+
+ --lilac-1: oklch(97.9% 0.014 306);
+ --lilac-2: oklch(96.7% 0.024 311);
+ --lilac-3: oklch(92.7% 0.049 306);
+ --lilac-4: oklch(84% 0.074 301);
+ --lilac-5: oklch(80% 0.099 301);
+ --lilac-6: oklch(71% 0.117 301);
+ --lilac-7: oklch(66% 0.124 301);
+ --lilac-8: oklch(58% 0.13 301);
+ --lilac-9: oklch(53% 0.124 301);
+ --lilac-10: oklch(49% 0.117 301);
+ --lilac-11: oklch(42% 0.105 301);
+ --lilac-12: oklch(35% 0.092 301);
+ --lilac-13: oklch(27% 0.074 301);
+ --lilac-14: oklch(20% 0.056 301);
+ --lilac-15: oklch(16% 0.043 301);
+ --lilac-16: oklch(10% 0.031 301);
+ --lilac: var(--lilac-8);
+
+ --cranberry-1: oklch(98% 0.01 25);
+ --cranberry-2: oklch(96% 0.03 25);
+ --cranberry-3: oklch(92% 0.06 25);
+ --cranberry-4: oklch(84% 0.09 25);
+ --cranberry-5: oklch(80% 0.12 25);
+ --cranberry-6: oklch(72% 0.15 25);
+ --cranberry-7: oklch(66% 0.17 25);
+ --cranberry-8: oklch(58% 0.18 25);
+ --cranberry-9: oklch(53% 0.19 25);
+ --cranberry-10: oklch(49% 0.18 25);
+ --cranberry-11: oklch(42% 0.16 25);
+ --cranberry-12: oklch(35% 0.14 25);
+ --cranberry-13: oklch(28% 0.12 25);
+ --cranberry-14: oklch(22% 0.1 25);
+ --cranberry-15: oklch(17% 0.08 25);
+ --cranberry-16: oklch(12% 0.06 25);
+ --cranberry: var(--cranberry-8);
+ --danger-color: var(--cranberry-9);
+
+ --background-1: var(--stone-3);
+ --background-2: var(--stone-2);
+ --background-3: var(--ash-4);
+ --background-dark-1: var(--stone-14);
+ --background-dark-2: var(--stone-13);
+ --background-dark-3: var(--stone-11);
+ --text-1: var(--stone-12);
+ --text-2: var(--stone-13);
+ --brand-color: var(--avocado-8);
+ --shadow-color: var(--stone-16);
+}
\ No newline at end of file
diff --git a/static/style.css b/static/style.css
index 67b11c04ce2519dddf64e3cbfa5ecf766ae78012..a1ca4e433f54e8181a37db78c756b72c03c1dd92 100644
--- a/static/style.css
+++ b/static/style.css
@@ -6,43 +6,6 @@
:root {
color-scheme: light dark;
-
- /* Light theme (default) */
- --bg-page: #f5f5f5;
- --bg-surface: white;
- --bg-header-code: #e8f5e0;
-
- --text-primary: #333;
- --text-on-accent: white;
-
- --accent: #5a8c3a;
- --accent-hover: #4a7230;
- --accent-dark: #2d5016;
- --accent-danger: #b22222;
-
- --border: #ddd;
- --border-accent: #5a8c3a;
- --shadow: rgba(0, 0, 0, 0.1);
-}
-
-@media (prefers-color-scheme: dark) {
- :root {
- --bg-page: #1a1a1a;
- --bg-surface: #2a2a2a;
- --bg-header-code: #3a4a34;
-
- --text-primary: #e0e0e0;
- --text-on-accent: white;
-
- --accent: #7ab859;
- --accent-hover: #8cc96f;
- --accent-dark: #5a8c3a;
- --accent-danger: #d84444;
-
- --border: #444;
- --border-accent: #7ab859;
- --shadow: rgba(0, 0, 0, 0.3);
- }
}
* {
@@ -53,8 +16,8 @@
body {
font-family: "Atkinson Hyperlegible Next", system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif;
- background: var(--bg-page);
- color: var(--text-primary);
+ background: var(--background-1);
+ color: var(--text-1);
line-height: 1.6;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
@@ -78,7 +41,7 @@ body {
#start-screen h1 {
margin-bottom: 3rem;
- color: var(--accent-dark);
+ color: var(--avocado-11);
}
.buttons {
@@ -95,43 +58,69 @@ body {
button {
padding: 0.75rem 1.5rem;
- background: var(--accent);
- color: var(--text-on-accent);
+ background: var(--brand-color);
+ color: var(--stone-1);
border: none;
- border-radius: 6px;
+ border-radius: 8px;
cursor: pointer;
font-size: 1rem;
- transition: background 0.2s, transform 0.05s, box-shadow 0.2s;
+ position: relative;
+ --btn-color: var(--brand-color);
+ transform: translateY(0);
+ box-shadow:
+ 0 6px 0 color-mix(in oklch, var(--btn-color) 60%, black),
+ 0 12px 18px color-mix(in oklch, var(--stone-16) 30%, transparent),
+ inset 0 1px 0 color-mix(in oklch, white 20%, transparent);
+ transition:
+ transform 140ms cubic-bezier(0.2, 0.7, 0.1, 1),
+ box-shadow 140ms cubic-bezier(0.2, 0.7, 0.1, 1),
+ background 140ms ease;
}
button:hover {
- background: var(--accent-hover);
+ box-shadow:
+ 0 7px 0 color-mix(in oklch, var(--btn-color) 60%, black),
+ 0 14px 20px color-mix(in oklch, var(--stone-16) 35%, transparent),
+ inset 0 1px 0 color-mix(in oklch, white 25%, transparent);
}
button:active {
- transform: translateY(1px);
+ transform: translateY(4px);
+ box-shadow:
+ 0 2px 0 color-mix(in oklch, var(--btn-color) 60%, black),
+ 0 6px 12px color-mix(in oklch, var(--stone-16) 25%, transparent),
+ inset 0 -1px 0 color-mix(in oklch, var(--btn-color) 50%, black);
+}
+
+button.press-lock {
+ transform: translateY(4px);
+ box-shadow:
+ 0 2px 0 color-mix(in oklch, var(--btn-color) 60%, black),
+ 0 6px 12px color-mix(in oklch, var(--stone-16) 25%, transparent),
+ inset 0 -1px 0 color-mix(in oklch, var(--btn-color) 50%, black);
}
button:focus-visible,
input:focus-visible,
textarea:focus-visible {
- outline: 2px solid var(--border-accent);
+ outline: 2px solid var(--avocado-7);
outline-offset: 2px;
}
-input, textarea {
+input,
+textarea {
padding: 0.75rem;
- border: 1px solid var(--border);
+ border: 1px solid var(--stone-5);
border-radius: 6px;
font-size: 1rem;
font-family: inherit;
- background: var(--bg-surface);
- color: var(--text-primary);
+ background: var(--stone-1);
+ color: var(--text-1);
}
input::placeholder,
textarea::placeholder {
- color: color-mix(in srgb, var(--text-primary) 50%, transparent);
+ color: color-mix(in oklch, var(--text-1) 50%, transparent);
}
#join-code {
@@ -146,7 +135,7 @@ textarea::placeholder {
.expiry-notice {
font-size: 0.85rem;
- color: color-mix(in srgb, var(--text-primary) 60%, transparent);
+ color: color-mix(in oklch, var(--text-1) 60%, transparent);
margin-top: 1rem;
}
@@ -166,7 +155,7 @@ textarea::placeholder {
align-items: center;
margin-bottom: 2rem;
padding-bottom: 1rem;
- border-bottom: 2px solid var(--border-accent);
+ border-bottom: 2px solid var(--brand-color);
}
#list-screen header h2 {
@@ -178,33 +167,37 @@ textarea::placeholder {
align-items: center;
gap: 0.5rem;
font-size: 0.85rem;
- color: color-mix(in srgb, var(--text-primary) 70%, transparent);
+ color: color-mix(in oklch, var(--text-1) 70%, transparent);
}
.status-dot {
width: 8px;
height: 8px;
border-radius: 50%;
- background: #888;
+ background: var(--stone-8);
}
.status-dot.connected {
- background: #4caf50;
- box-shadow: 0 0 4px #4caf50;
+ background: var(--brand-color);
+ box-shadow: 0 0 4px color-mix(in oklch, var(--brand-color) 60%, transparent);
}
.status-dot.connecting {
- background: #ff9800;
+ background: var(--cranberry-7);
animation: pulse 1.5s ease-in-out infinite;
}
.status-dot.disconnected {
- background: #f44336;
+ background: var(--cranberry-12);
}
@keyframes pulse {
- 0%, 100% { opacity: 1; }
- 50% { opacity: 0.5; }
+ 0%, 100% {
+ opacity: 1;
+ }
+ 50% {
+ opacity: 0.5;
+ }
}
.header-actions {
@@ -214,15 +207,19 @@ textarea::placeholder {
#room-code {
font-family: monospace;
- background: var(--bg-header-code);
+ background: var(--background-2);
padding: 0.25rem 0.5rem;
border-radius: 6px;
}
-#copy-btn, #copy-link-btn, #set-title-btn, #reset-votes-btn {
- background: transparent;
- color: var(--text-primary);
- border: 1px solid var(--border);
+#copy-btn,
+#copy-link-btn,
+#set-title-btn,
+#reset-votes-btn {
+ background: var(--stone-1);
+ --btn-color: var(--stone-1);
+ color: var(--text-1);
+ border: none;
width: 40px;
height: 40px;
padding: 0;
@@ -231,9 +228,11 @@ textarea::placeholder {
place-items: center;
}
-#copy-btn:hover, #copy-link-btn:hover, #set-title-btn:hover, #reset-votes-btn:hover {
- background: var(--bg-header-code);
- border-color: var(--border-accent);
+#copy-btn:hover,
+#copy-link-btn:hover,
+#set-title-btn:hover,
+#reset-votes-btn:hover {
+ filter: brightness(1.03);
}
.header-actions button svg {
@@ -243,13 +242,14 @@ textarea::placeholder {
}
#leave-btn {
- background: transparent;
- color: var(--accent-dark);
- border: 1px solid var(--border-accent);
+ background: var(--stone-1);
+ --btn-color: var(--stone-1);
+ color: var(--avocado-12);
+ border: none;
}
#leave-btn:hover {
- background: var(--bg-header-code);
+ filter: brightness(1.03);
}
.add-section {
@@ -280,11 +280,12 @@ textarea::placeholder {
}
.list-item {
- background: var(--bg-surface);
+ position: relative;
+ background: var(--stone-1);
padding: 1rem;
margin-bottom: 0.5rem;
border-radius: 8px;
- box-shadow: 0 1px 3px var(--shadow);
+ box-shadow: 0 1px 3px color-mix(in oklch, var(--shadow-color) 20%, transparent);
display: flex;
justify-content: space-between;
align-items: center;
@@ -294,12 +295,13 @@ textarea::placeholder {
.list-item:hover {
transform: translateY(-1px);
- box-shadow: 0 4px 12px var(--shadow);
+ box-shadow: 0 4px 12px color-mix(in oklch, var(--shadow-color) 25%, transparent);
}
.list-item.selected {
- outline: 2px solid var(--border-accent);
+ outline: 2px solid var(--brand-color);
outline-offset: 2px;
+ border-radius: 10px;
}
.list-item.vetoed {
@@ -308,13 +310,15 @@ textarea::placeholder {
overflow: hidden;
}
-.list-item:has(.vote-btn.active) {
- border-left-color: var(--accent);
+.top-check {
+ position: absolute;
+ left: -40px;
+ top: 50%;
+ transform: translateY(-50%);
+ color: var(--avocado-9);
+ flex-shrink: 0;
}
-.list-item:has(.vote-btn.veto-active) {
- border-left-color: var(--accent-danger);
-}
.list-item-text {
flex: 1;
@@ -346,25 +350,40 @@ textarea::placeholder {
.delete-btn {
padding: 0.5rem;
font-size: 0.9rem;
- background: var(--accent-danger);
- opacity: 0.7;
+ background: var(--danger-color);
+ --btn-color: var(--danger-color);
+ color: var(--stone-1);
+ opacity: 0.8;
transition: opacity 0.2s, background 0.2s;
}
.delete-btn:hover {
opacity: 1;
- background: var(--accent-danger);
+ background: var(--cranberry-8);
}
.vote-btn.active {
- background: var(--accent-dark);
+ background: var(--avocado-11);
+ color: var(--stone-1);
+ transform: translateY(4px);
+ box-shadow:
+ 0 2px 0 color-mix(in oklch, var(--btn-color) 60%, black),
+ 0 6px 12px color-mix(in oklch, var(--stone-16) 25%, transparent),
+ inset 0 -1px 0 color-mix(in oklch, var(--btn-color) 50%, black);
}
.vote-btn.veto-active {
- background: var(--accent-danger);
+ background: var(--avocado-11);
+ color: var(--stone-1);
+ transform: translateY(4px);
+ box-shadow:
+ 0 2px 0 color-mix(in oklch, var(--btn-color) 60%, black),
+ 0 6px 12px color-mix(in oklch, var(--stone-16) 25%, transparent),
+ inset 0 -1px 0 color-mix(in oklch, var(--btn-color) 50%, black);
}
-.vote-btn svg, .delete-btn svg {
+.vote-btn svg,
+.delete-btn svg {
width: 16px;
height: 16px;
display: block;
@@ -374,8 +393,8 @@ textarea::placeholder {
min-width: 40px;
text-align: center;
font-weight: bold;
- color: var(--accent);
- background: var(--bg-header-code);
+ color: var(--brand-color);
+ background: var(--stone-2);
padding: 0.25rem 0.5rem;
border-radius: 999px;
}
@@ -387,7 +406,7 @@ textarea::placeholder {
left: 0;
width: 100%;
height: 100%;
- background: rgba(0, 0, 0, 0.5);
+ background: color-mix(in oklch, var(--stone-16) 60%, transparent);
display: flex;
align-items: center;
justify-content: center;
@@ -395,14 +414,14 @@ textarea::placeholder {
}
.modal-content {
- background: var(--bg-surface);
+ background: var(--stone-1);
padding: 2rem;
border-radius: 8px;
max-width: 500px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
- box-shadow: 0 4px 20px var(--shadow);
+ box-shadow: 0 4px 20px color-mix(in oklch, var(--shadow-color) 35%, transparent);
}
.modal-header {
@@ -411,17 +430,17 @@ textarea::placeholder {
align-items: center;
margin-bottom: 1.5rem;
padding-bottom: 0.5rem;
- border-bottom: 2px solid var(--border);
+ border-bottom: 2px solid var(--stone-5);
}
.modal-header h3 {
margin: 0;
- color: var(--accent-dark);
+ color: var(--avocado-12);
}
.modal-close {
background: transparent;
- color: var(--text-primary);
+ color: var(--text-1);
border: none;
font-size: 2rem;
line-height: 1;
@@ -432,11 +451,11 @@ textarea::placeholder {
}
.modal-close:hover {
- color: var(--accent-danger);
+ color: var(--cranberry-9);
}
.modal-body h4 {
- color: var(--accent);
+ color: var(--brand-color);
margin-top: 1rem;
margin-bottom: 0.5rem;
}
@@ -459,10 +478,10 @@ kbd {
padding: 0.2rem 0.4rem;
font-size: 0.85rem;
font-family: monospace;
- background: var(--bg-header-code);
- border: 1px solid var(--border);
+ background: var(--background-2);
+ border: 1px solid var(--stone-5);
border-radius: 4px;
- box-shadow: 0 1px 2px var(--shadow);
+ box-shadow: 0 1px 2px color-mix(in oklch, var(--shadow-color) 20%, transparent);
}
/* Screen reader only */
@@ -484,3 +503,165 @@ kbd {
animation: none !important;
}
}
+
+@media (prefers-color-scheme: dark) {
+ body {
+ background: var(--background-dark-1);
+ color: var(--stone-3);
+ }
+
+ button {
+ background: var(--avocado-9);
+ --btn-color: var(--avocado-9);
+ color: var(--stone-1);
+ }
+
+ button:hover {
+ background: var(--avocado-8);
+ }
+
+ input,
+ textarea {
+ background: var(--background-dark-2);
+ border: 1px solid var(--stone-9);
+ color: var(--stone-3);
+ }
+
+ input::placeholder,
+ textarea::placeholder {
+ color: color-mix(in oklch, var(--stone-3) 50%, transparent);
+ }
+
+ .expiry-notice {
+ color: color-mix(in oklch, var(--stone-3) 60%, transparent);
+ }
+
+ #list-screen header {
+ border-bottom: 2px solid var(--avocado-9);
+ }
+
+ .connection-status {
+ color: color-mix(in oklch, var(--stone-3) 60%, transparent);
+ }
+
+ .status-dot {
+ background: var(--stone-10);
+ }
+
+ .status-dot.connected {
+ background: var(--avocado-9);
+ box-shadow: 0 0 4px color-mix(in oklch, var(--avocado-9) 60%, transparent);
+ }
+
+ .status-dot.connecting {
+ background: var(--cranberry-8);
+ }
+
+ .status-dot.disconnected {
+ background: var(--cranberry-13);
+ }
+
+ #room-code {
+ background: var(--background-dark-2);
+ color: var(--stone-3);
+ }
+
+ #copy-btn,
+ #copy-link-btn,
+ #set-title-btn,
+ #reset-votes-btn {
+ background: var(--background-dark-2);
+ --btn-color: var(--background-dark-2);
+ color: var(--stone-3);
+ border: none;
+ }
+
+ #copy-btn:hover,
+ #copy-link-btn:hover,
+ #set-title-btn:hover,
+ #reset-votes-btn:hover {
+ filter: brightness(1.04);
+ }
+
+ #leave-btn {
+ background: var(--background-dark-2);
+ color: var(--stone-3);
+ border: none;
+ --btn-color: var(--background-dark-2);
+ }
+
+ #leave-btn:hover {
+ filter: brightness(1.04);
+ }
+
+ .list-item {
+ background: var(--background-dark-2);
+ box-shadow: 0 1px 3px color-mix(in oklch, var(--shadow-color) 30%, transparent);
+ }
+
+ .list-item:hover {
+ box-shadow: 0 4px 12px color-mix(in oklch, var(--shadow-color) 45%, transparent);
+ }
+
+ .list-item.selected {
+ outline-color: var(--avocado-9);
+ }
+
+
+ .delete-btn {
+ background: var(--cranberry-10);
+ --btn-color: var(--cranberry-10);
+ }
+
+ .delete-btn:hover {
+ background: var(--cranberry-9);
+ }
+
+ .vote-btn.active {
+ background: var(--avocado-11);
+ }
+
+ .vote-btn.veto-active {
+ background: var(--avocado-12);
+ }
+
+ .score {
+ color: var(--avocado-8);
+ background: var(--stone-14);
+ }
+
+ .modal {
+ background: color-mix(in oklch, var(--background-dark-3) 75%, transparent);
+ }
+
+ .modal-content {
+ background: var(--background-dark-2);
+ box-shadow: 0 4px 20px color-mix(in oklch, var(--shadow-color) 70%, transparent);
+ }
+
+ .modal-header {
+ border-bottom: 2px solid var(--stone-11);
+ }
+
+ .modal-header h3 {
+ color: var(--avocado-8);
+ }
+
+ .modal-close {
+ color: var(--stone-3);
+ }
+
+ .modal-close:hover {
+ color: var(--cranberry-8);
+ }
+
+ .modal-body h4 {
+ color: var(--avocado-8);
+ }
+
+ kbd {
+ background: var(--background-dark-2);
+ border: 1px solid var(--stone-11);
+ box-shadow: 0 1px 2px color-mix(in oklch, var(--shadow-color) 50%, transparent);
+ }
+}