style.css

  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}