1/*
2 * SPDX-FileCopyrightText: Amolith <amolith@secluded.site>
3 *
4 * SPDX-License-Identifier: AGPL-3.0-or-later
5 */
6
7:root {
8 color-scheme: light dark;
9}
10
11* {
12 box-sizing: border-box;
13 margin: 0;
14 padding: 0;
15}
16
17body {
18 font-family: "Atkinson Hyperlegible Next", system-ui, -apple-system, Segoe UI, Roboto, Ubuntu, Cantarell, Noto Sans, sans-serif;
19 background: var(--background-1);
20 color: var(--text-1);
21 line-height: 1.6;
22 -webkit-font-smoothing: antialiased;
23 -moz-osx-font-smoothing: grayscale;
24}
25
26#app {
27 max-width: 800px;
28 margin: 0 auto;
29 padding: 2rem 1rem;
30}
31
32.hidden {
33 display: none !important;
34}
35
36/* Start screen */
37#start-screen {
38 text-align: center;
39 padding: 4rem 2rem;
40}
41
42#start-screen h1 {
43 margin-bottom: 3rem;
44 color: var(--avocado-11);
45}
46
47.buttons {
48 display: flex;
49 flex-direction: column;
50 gap: 1rem;
51 align-items: center;
52}
53
54.join-section {
55 display: flex;
56 gap: 0.5rem;
57}
58
59button {
60 padding: 0.75rem 1.5rem;
61 background: var(--brand-color);
62 color: var(--stone-1);
63 border: none;
64 border-radius: 8px;
65 cursor: pointer;
66 font-size: 1rem;
67 position: relative;
68 --btn-color: var(--brand-color);
69 transform: translateY(0);
70 box-shadow:
71 0 6px 0 color-mix(in oklch, var(--btn-color) 60%, black),
72 0 12px 18px color-mix(in oklch, var(--stone-16) 30%, transparent),
73 inset 0 1px 0 color-mix(in oklch, white 20%, transparent);
74 transition:
75 transform 140ms cubic-bezier(0.2, 0.7, 0.1, 1),
76 box-shadow 140ms cubic-bezier(0.2, 0.7, 0.1, 1),
77 background 140ms ease;
78}
79
80button:hover {
81 box-shadow:
82 0 7px 0 color-mix(in oklch, var(--btn-color) 60%, black),
83 0 14px 20px color-mix(in oklch, var(--stone-16) 35%, transparent),
84 inset 0 1px 0 color-mix(in oklch, white 25%, transparent);
85}
86
87button:active {
88 transform: translateY(4px);
89 box-shadow:
90 0 2px 0 color-mix(in oklch, var(--btn-color) 60%, black),
91 0 6px 12px color-mix(in oklch, var(--stone-16) 25%, transparent),
92 inset 0 -1px 0 color-mix(in oklch, var(--btn-color) 50%, black);
93}
94
95button.press-lock {
96 transform: translateY(4px);
97 box-shadow:
98 0 2px 0 color-mix(in oklch, var(--btn-color) 60%, black),
99 0 6px 12px color-mix(in oklch, var(--stone-16) 25%, transparent),
100 inset 0 -1px 0 color-mix(in oklch, var(--btn-color) 50%, black);
101}
102
103button:focus-visible,
104input:focus-visible,
105textarea:focus-visible {
106 outline: 2px solid var(--avocado-7);
107 outline-offset: 2px;
108}
109
110input,
111textarea {
112 padding: 0.75rem;
113 border: 1px solid var(--stone-5);
114 border-radius: 6px;
115 font-size: 1rem;
116 font-family: inherit;
117 background: var(--stone-1);
118 color: var(--text-1);
119}
120
121input::placeholder,
122textarea::placeholder {
123 color: color-mix(in oklch, var(--text-1) 50%, transparent);
124}
125
126#join-code {
127 width: 200px;
128 text-transform: uppercase;
129 letter-spacing: 0.08em;
130}
131
132#join-code::placeholder {
133 text-transform: none;
134}
135
136.expiry-notice {
137 font-size: 0.85rem;
138 color: color-mix(in oklch, var(--text-1) 60%, transparent);
139 margin-top: 1rem;
140}
141
142#start-screen .expiry-notice {
143 text-align: center;
144}
145
146#list-screen .expiry-notice {
147 margin: 0.5rem 0 0 0;
148 font-size: 0.8rem;
149}
150
151/* List screen */
152#list-screen header {
153 display: flex;
154 justify-content: space-between;
155 align-items: center;
156 margin-bottom: 2rem;
157 padding-bottom: 1rem;
158 border-bottom: 2px solid var(--brand-color);
159}
160
161#list-screen header h2 {
162 margin-bottom: 0.25rem;
163}
164
165.connection-status {
166 display: flex;
167 align-items: center;
168 gap: 0.5rem;
169 font-size: 0.85rem;
170 color: color-mix(in oklch, var(--text-1) 70%, transparent);
171}
172
173.status-dot {
174 width: 8px;
175 height: 8px;
176 border-radius: 50%;
177 background: var(--stone-8);
178}
179
180.status-dot.connected {
181 background: var(--brand-color);
182 box-shadow: 0 0 4px color-mix(in oklch, var(--brand-color) 60%, transparent);
183}
184
185.status-dot.connecting {
186 background: var(--cranberry-7);
187 animation: pulse 1.5s ease-in-out infinite;
188}
189
190.status-dot.disconnected {
191 background: var(--cranberry-12);
192}
193
194@keyframes pulse {
195 0%, 100% {
196 opacity: 1;
197 }
198 50% {
199 opacity: 0.5;
200 }
201}
202
203.header-actions {
204 display: flex;
205 gap: 0.5rem;
206}
207
208#room-code {
209 font-family: monospace;
210 background: var(--background-2);
211 padding: 0.25rem 0.5rem;
212 border-radius: 6px;
213}
214
215#copy-btn,
216#copy-link-btn,
217#set-title-btn,
218#reset-votes-btn {
219 background: var(--stone-1);
220 --btn-color: var(--stone-1);
221 color: var(--text-1);
222 border: none;
223 width: 40px;
224 height: 40px;
225 padding: 0;
226 border-radius: 999px;
227 display: grid;
228 place-items: center;
229}
230
231#copy-btn:hover,
232#copy-link-btn:hover,
233#set-title-btn:hover,
234#reset-votes-btn:hover {
235 filter: brightness(1.03);
236}
237
238.header-actions button svg {
239 width: 20px;
240 height: 20px;
241 display: block;
242}
243
244#leave-btn {
245 background: var(--stone-1);
246 --btn-color: var(--stone-1);
247 color: var(--avocado-12);
248 border: none;
249}
250
251#leave-btn:hover {
252 filter: brightness(1.03);
253}
254
255.add-section {
256 display: flex;
257 gap: 0.5rem;
258 margin-bottom: 1rem;
259}
260
261.add-section input {
262 flex: 1;
263}
264
265.bulk-section {
266 margin-bottom: 2rem;
267}
268
269.bulk-section textarea {
270 width: 100%;
271 min-height: 100px;
272 margin-bottom: 0.5rem;
273 resize: vertical;
274}
275
276/* Tie breaker */
277#tie-breaker {
278 display: flex;
279 align-items: center;
280 gap: 1rem;
281 margin-bottom: 1.5rem;
282 padding: 1rem;
283 background: var(--stone-2);
284 border-radius: 8px;
285}
286
287#break-tie-btn {
288 flex-shrink: 0;
289}
290
291#tie-break-result {
292 font-weight: 500;
293 color: var(--brand-color);
294}
295
296/* List items */
297#list-container.disabled {
298 pointer-events: none;
299 opacity: 0.6;
300}
301
302.list-item {
303 position: relative;
304 background: var(--stone-1);
305 padding: 1rem;
306 margin-bottom: 0.5rem;
307 border-radius: 8px;
308 box-shadow: 0 1px 3px color-mix(in oklch, var(--shadow-color) 20%, transparent);
309 display: flex;
310 justify-content: space-between;
311 align-items: center;
312 transition: transform 0.3s ease, box-shadow 0.2s ease;
313 border-left: 3px solid transparent;
314}
315
316.list-item:hover {
317 transform: translateY(-1px);
318 box-shadow: 0 4px 12px color-mix(in oklch, var(--shadow-color) 25%, transparent);
319}
320
321.list-item.selected {
322 outline: 2px solid var(--brand-color);
323 outline-offset: 2px;
324 border-radius: 10px;
325}
326
327.list-item.vetoed {
328 opacity: 0.4;
329 max-height: 3rem;
330 overflow: hidden;
331}
332
333.top-check {
334 position: absolute;
335 left: -40px;
336 top: 50%;
337 transform: translateY(-50%);
338 color: var(--avocado-9);
339 flex-shrink: 0;
340}
341
342
343.list-item-text {
344 flex: 1;
345 padding-right: 1rem;
346 cursor: pointer;
347 user-select: none;
348}
349
350.list-item-text:hover {
351 opacity: 0.9;
352}
353
354.edit-input {
355 flex: 1;
356 margin-right: 1rem;
357}
358
359.list-item-actions {
360 display: flex;
361 gap: 0.5rem;
362 flex-shrink: 0;
363}
364
365.vote-btn {
366 padding: 0.5rem;
367 font-size: 0.9rem;
368}
369
370.delete-btn {
371 padding: 0.5rem;
372 font-size: 0.9rem;
373 background: var(--danger-color);
374 --btn-color: var(--danger-color);
375 color: var(--stone-1);
376 opacity: 0.8;
377 transition: opacity 0.2s, background 0.2s;
378}
379
380.delete-btn:hover {
381 opacity: 1;
382 background: var(--cranberry-8);
383}
384
385.vote-btn.active {
386 background: var(--avocado-11);
387 color: var(--stone-1);
388 transform: translateY(4px);
389 box-shadow:
390 0 2px 0 color-mix(in oklch, var(--btn-color) 60%, black),
391 0 6px 12px color-mix(in oklch, var(--stone-16) 25%, transparent),
392 inset 0 -1px 0 color-mix(in oklch, var(--btn-color) 50%, black);
393}
394
395.vote-btn.veto-active {
396 background: var(--avocado-11);
397 color: var(--stone-1);
398 transform: translateY(4px);
399 box-shadow:
400 0 2px 0 color-mix(in oklch, var(--btn-color) 60%, black),
401 0 6px 12px color-mix(in oklch, var(--stone-16) 25%, transparent),
402 inset 0 -1px 0 color-mix(in oklch, var(--btn-color) 50%, black);
403}
404
405.vote-btn svg,
406.delete-btn svg {
407 width: 16px;
408 height: 16px;
409 display: block;
410}
411
412.score {
413 min-width: 40px;
414 text-align: center;
415 font-weight: bold;
416 color: var(--brand-color);
417 background: var(--stone-2);
418 padding: 0.25rem 0.5rem;
419 border-radius: 999px;
420}
421
422/* Modal */
423.modal {
424 position: fixed;
425 top: 0;
426 left: 0;
427 width: 100%;
428 height: 100%;
429 background: color-mix(in oklch, var(--stone-16) 60%, transparent);
430 display: flex;
431 align-items: center;
432 justify-content: center;
433 z-index: 1000;
434}
435
436.modal-content {
437 background: var(--stone-1);
438 padding: 2rem;
439 border-radius: 8px;
440 max-width: 500px;
441 width: 90%;
442 max-height: 80vh;
443 overflow-y: auto;
444 box-shadow: 0 4px 20px color-mix(in oklch, var(--shadow-color) 35%, transparent);
445}
446
447.modal-header {
448 display: flex;
449 justify-content: space-between;
450 align-items: center;
451 margin-bottom: 1.5rem;
452 padding-bottom: 0.5rem;
453 border-bottom: 2px solid var(--stone-5);
454}
455
456.modal-header h3 {
457 margin: 0;
458 color: var(--avocado-12);
459}
460
461.modal-close {
462 background: transparent;
463 color: var(--text-1);
464 border: none;
465 font-size: 2rem;
466 line-height: 1;
467 padding: 0;
468 width: 2rem;
469 height: 2rem;
470 cursor: pointer;
471}
472
473.modal-close:hover {
474 color: var(--cranberry-9);
475}
476
477.modal-body h4 {
478 color: var(--brand-color);
479 margin-top: 1rem;
480 margin-bottom: 0.5rem;
481}
482
483.modal-body h4:first-child {
484 margin-top: 0;
485}
486
487.modal-body ul {
488 margin: 0;
489 padding-left: 1.5rem;
490}
491
492.modal-body li {
493 margin-bottom: 0.5rem;
494}
495
496kbd {
497 display: inline-block;
498 padding: 0.2rem 0.4rem;
499 font-size: 0.85rem;
500 font-family: monospace;
501 background: var(--background-2);
502 border: 1px solid var(--stone-5);
503 border-radius: 4px;
504 box-shadow: 0 1px 2px color-mix(in oklch, var(--shadow-color) 20%, transparent);
505}
506
507/* Screen reader only */
508.sr-only {
509 position: absolute;
510 width: 1px;
511 height: 1px;
512 padding: 0;
513 margin: -1px;
514 overflow: hidden;
515 clip: rect(0, 0, 0, 0);
516 white-space: nowrap;
517 border-width: 0;
518}
519
520/* Source link */
521.source-link {
522 display: block;
523 text-align: center;
524 margin-top: 2rem;
525 font-size: 0.85rem;
526 color: color-mix(in oklch, var(--text-1) 50%, transparent);
527 text-decoration: none;
528 transition: color 0.2s ease;
529}
530
531.source-link:hover {
532 color: var(--brand-color);
533 text-decoration: underline;
534}
535
536@media (prefers-reduced-motion: reduce) {
537 * {
538 transition: none !important;
539 animation: none !important;
540 }
541}
542
543@media (prefers-color-scheme: dark) {
544 body {
545 background: var(--background-dark-1);
546 color: var(--stone-3);
547 }
548
549 button {
550 background: var(--avocado-9);
551 --btn-color: var(--avocado-9);
552 color: var(--stone-1);
553 }
554
555 button:hover {
556 background: var(--avocado-8);
557 }
558
559 input,
560 textarea {
561 background: var(--background-dark-2);
562 border: 1px solid var(--stone-9);
563 color: var(--stone-3);
564 }
565
566 input::placeholder,
567 textarea::placeholder {
568 color: color-mix(in oklch, var(--stone-3) 50%, transparent);
569 }
570
571 .expiry-notice {
572 color: color-mix(in oklch, var(--stone-3) 60%, transparent);
573 }
574
575 #list-screen header {
576 border-bottom: 2px solid var(--avocado-9);
577 }
578
579 .connection-status {
580 color: color-mix(in oklch, var(--stone-3) 60%, transparent);
581 }
582
583 .status-dot {
584 background: var(--stone-10);
585 }
586
587 .status-dot.connected {
588 background: var(--avocado-9);
589 box-shadow: 0 0 4px color-mix(in oklch, var(--avocado-9) 60%, transparent);
590 }
591
592 .status-dot.connecting {
593 background: var(--cranberry-8);
594 }
595
596 .status-dot.disconnected {
597 background: var(--cranberry-13);
598 }
599
600 #room-code {
601 background: var(--background-dark-2);
602 color: var(--stone-3);
603 }
604
605 #copy-btn,
606 #copy-link-btn,
607 #set-title-btn,
608 #reset-votes-btn {
609 background: var(--background-dark-2);
610 --btn-color: var(--background-dark-2);
611 color: var(--stone-3);
612 border: none;
613 }
614
615 #copy-btn:hover,
616 #copy-link-btn:hover,
617 #set-title-btn:hover,
618 #reset-votes-btn:hover {
619 filter: brightness(1.04);
620 }
621
622 #leave-btn {
623 background: var(--background-dark-2);
624 color: var(--stone-3);
625 border: none;
626 --btn-color: var(--background-dark-2);
627 }
628
629 #leave-btn:hover {
630 filter: brightness(1.04);
631 }
632
633 .list-item {
634 background: var(--background-dark-2);
635 box-shadow: 0 1px 3px color-mix(in oklch, var(--shadow-color) 30%, transparent);
636 }
637
638 #tie-breaker {
639 background: var(--background-dark-2);
640 }
641
642 #tie-break-result {
643 color: var(--avocado-8);
644 }
645
646 .list-item:hover {
647 box-shadow: 0 4px 12px color-mix(in oklch, var(--shadow-color) 45%, transparent);
648 }
649
650 .list-item.selected {
651 outline-color: var(--avocado-9);
652 }
653
654
655 .delete-btn {
656 background: var(--cranberry-10);
657 --btn-color: var(--cranberry-10);
658 }
659
660 .delete-btn:hover {
661 background: var(--cranberry-9);
662 }
663
664 .vote-btn.active {
665 background: var(--avocado-11);
666 }
667
668 .vote-btn.veto-active {
669 background: var(--avocado-12);
670 }
671
672 .score {
673 color: var(--avocado-8);
674 background: var(--stone-14);
675 }
676
677 .modal {
678 background: color-mix(in oklch, var(--background-dark-3) 75%, transparent);
679 }
680
681 .modal-content {
682 background: var(--background-dark-2);
683 box-shadow: 0 4px 20px color-mix(in oklch, var(--shadow-color) 70%, transparent);
684 }
685
686 .modal-header {
687 border-bottom: 2px solid var(--stone-11);
688 }
689
690 .modal-header h3 {
691 color: var(--avocado-8);
692 }
693
694 .modal-close {
695 color: var(--stone-3);
696 }
697
698 .modal-close:hover {
699 color: var(--cranberry-8);
700 }
701
702 .modal-body h4 {
703 color: var(--avocado-8);
704 }
705
706 kbd {
707 background: var(--background-dark-2);
708 border: 1px solid var(--stone-11);
709 box-shadow: 0 1px 2px color-mix(in oklch, var(--shadow-color) 50%, transparent);
710 }
711
712 .source-link {
713 color: color-mix(in oklch, var(--stone-3) 50%, transparent);
714 }
715
716 .source-link:hover {
717 color: var(--avocado-9);
718 }
719}