forked from
tranquil.farm/tranquil-pds
Our Personal Data Server from scratch!
1@import "./tokens.css";
2
3@property --accent {
4 syntax: "<color>";
5 inherits: true;
6 initial-value: #1a1d1d;
7}
8
9@property --secondary {
10 syntax: "<color>";
11 inherits: true;
12 initial-value: #1a1d1d;
13}
14
15*,
16*::before,
17*::after {
18 box-sizing: border-box;
19}
20
21body {
22 margin: 0;
23 font-family:
24 "Space Grotesk", -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
25 font-size: var(--text-base);
26 line-height: var(--leading-normal);
27 color: var(--text-primary);
28 background: var(--bg-primary);
29 -webkit-font-smoothing: antialiased;
30 -moz-osx-font-smoothing: grayscale;
31 transition: background-color 0.3s ease;
32 overflow-wrap: anywhere;
33 word-break: break-word;
34}
35
36h1, h2, h3, h4, h5, h6 {
37 margin: 0;
38 line-height: var(--leading-tight);
39}
40
41h1 {
42 font-size: var(--text-2xl);
43}
44h2 {
45 font-size: var(--text-xl);
46}
47h3 {
48 font-size: var(--text-lg);
49}
50h4 {
51 font-size: var(--text-base);
52}
53
54p {
55 margin: 0;
56}
57
58a {
59 color: var(--accent);
60 text-decoration: underline;
61 text-underline-offset: 2px;
62}
63
64a:hover {
65 color: var(--accent-hover);
66}
67
68::selection {
69 background: var(--secondary-muted);
70}
71
72input,
73select,
74textarea {
75 font-family: inherit;
76 font-size: var(--text-base);
77 line-height: var(--leading-normal);
78 padding: var(--space-4);
79 border: 1px solid var(--border-dark);
80 border-radius: var(--radius-md);
81 background: var(--bg-input);
82 color: var(--text-primary);
83 transition:
84 border-color var(--transition-normal),
85 box-shadow var(--transition-normal);
86 width: 100%;
87}
88
89input:focus,
90select:focus,
91textarea:focus {
92 outline: none;
93 border-color: var(--accent);
94 box-shadow: var(--shadow-focus);
95}
96
97input:disabled,
98select:disabled,
99textarea:disabled {
100 background: var(--bg-input-disabled);
101 color: var(--text-muted);
102 cursor: not-allowed;
103}
104
105input::placeholder,
106textarea::placeholder {
107 color: var(--text-muted);
108}
109
110select {
111 cursor: pointer;
112 appearance: none;
113 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='%23666' d='M6 8L1 3h10z'/%3E%3C/svg%3E");
114 background-repeat: no-repeat;
115 background-position: right var(--space-4) center;
116 padding-right: var(--space-7);
117}
118
119button {
120 font-family: inherit;
121 font-size: var(--text-base);
122 font-weight: var(--font-medium);
123 line-height: var(--leading-normal);
124 padding: var(--space-4) var(--space-6);
125 border: none;
126 border-radius: var(--radius-md);
127 cursor: pointer;
128 transition:
129 background var(--transition-normal),
130 border-color var(--transition-normal),
131 opacity var(--transition-normal);
132 background: var(--accent);
133 color: var(--text-inverse);
134}
135
136button:hover:not(:disabled) {
137 background: var(--accent-hover);
138}
139
140button:disabled {
141 opacity: 0.6;
142 cursor: not-allowed;
143}
144
145button.secondary {
146 background: transparent;
147 color: var(--accent);
148 border: 1px solid var(--accent);
149}
150
151button.secondary:hover:not(:disabled) {
152 background: var(--accent);
153 color: var(--text-inverse);
154}
155
156button.tertiary {
157 background: transparent;
158 color: var(--text-secondary);
159 padding: var(--space-3) var(--space-4);
160}
161
162button.tertiary:hover:not(:disabled) {
163 color: var(--text-primary);
164 background: var(--bg-tertiary);
165}
166
167button.danger {
168 background: var(--error-text);
169}
170
171button.danger:hover:not(:disabled) {
172 background: #900;
173}
174
175button.danger-outline {
176 background: transparent;
177 border: 1px solid var(--error-border);
178 color: var(--error-text);
179}
180
181button.danger-outline:hover:not(:disabled) {
182 background: var(--error-bg);
183 border-color: var(--error-text);
184}
185
186button.ghost {
187 background: transparent;
188 color: var(--text-secondary);
189 border: 1px solid var(--border-dark);
190}
191
192button.ghost:hover:not(:disabled) {
193 background: var(--bg-secondary);
194 color: var(--text-primary);
195}
196
197button.link {
198 background: none;
199 border: none;
200 color: var(--accent);
201 padding: var(--space-2);
202 font-size: var(--text-sm);
203 font-weight: var(--font-normal);
204}
205
206button.link:hover:not(:disabled) {
207 background: none;
208 text-decoration: underline;
209}
210
211button.sm {
212 padding: var(--space-2) var(--space-3);
213 font-size: var(--text-xs);
214}
215
216button.icon {
217 background: none;
218 border: none;
219 color: var(--text-secondary);
220 padding: var(--space-1);
221 font-size: var(--text-base);
222}
223
224button.icon:hover:not(:disabled) {
225 background: none;
226 color: var(--text-primary);
227}
228
229label {
230 display: block;
231 font-size: var(--text-sm);
232 font-weight: var(--font-medium);
233 color: var(--text-primary);
234 margin-bottom: var(--space-2);
235}
236
237fieldset {
238 border: none;
239 border-left: 3px solid var(--accent);
240 border-radius: var(--radius-lg);
241 padding: var(--space-5);
242 padding-left: var(--space-6);
243 margin: 0;
244 background: var(--bg-secondary);
245}
246
247fieldset legend {
248 font-size: var(--text-xs);
249 font-weight: var(--font-semibold);
250 text-transform: uppercase;
251 letter-spacing: 0.05em;
252 padding: 0;
253 margin-left: calc(-1 * var(--space-1));
254 margin-bottom: var(--space-3);
255 color: var(--text-secondary);
256 float: left;
257 width: 100%;
258}
259
260fieldset legend + * {
261 clear: both;
262}
263
264code {
265 font-family: var(--font-mono);
266 font-size: 0.9em;
267 background: var(--bg-tertiary);
268 padding: var(--space-1) var(--space-2);
269 border-radius: var(--radius-sm);
270}
271
272pre {
273 font-family: var(--font-mono);
274 font-size: var(--text-sm);
275 background: var(--bg-tertiary);
276 padding: var(--space-4);
277 border-radius: var(--radius-md);
278 overflow-x: auto;
279 margin: 0;
280}
281
282hr {
283 border: none;
284 border-top: 1px solid var(--border-color);
285 margin: var(--space-6) 0;
286}
287
288.field {
289 display: flex;
290 flex-direction: column;
291 gap: var(--space-2);
292}
293
294.field + .field {
295 margin-top: var(--space-5);
296}
297
298.form-row .field + .field {
299 margin-top: 0;
300}
301
302.hint {
303 font-size: var(--text-xs);
304 color: var(--text-secondary);
305 margin-top: var(--space-1);
306}
307
308.hint.warning {
309 color: var(--warning-text);
310}
311
312.hint.error {
313 color: var(--error-text);
314}
315
316.hint.success {
317 color: var(--success-text);
318}
319
320.message {
321 padding: var(--space-4);
322 border-radius: var(--radius-md);
323 font-size: var(--text-sm);
324}
325
326.message.success {
327 background: var(--success-bg);
328 border: 1px solid var(--success-border);
329 color: var(--success-text);
330}
331
332.message.error {
333 background: var(--error-bg);
334 border: 1px solid var(--error-border);
335 color: var(--error-text);
336}
337
338.message.warning {
339 background: var(--warning-bg);
340 border: 1px solid var(--warning-border);
341 color: var(--warning-text);
342}
343
344.badge {
345 display: inline-block;
346 padding: var(--space-1) var(--space-3);
347 border-radius: var(--radius-md);
348 font-size: var(--text-xs);
349 font-weight: var(--font-medium);
350}
351
352.badge.success {
353 background: var(--success-bg);
354 color: var(--success-text);
355}
356
357.badge.warning {
358 background: var(--warning-bg);
359 color: var(--warning-text);
360}
361
362.badge.error {
363 background: var(--error-bg);
364 color: var(--error-text);
365}
366
367.badge.accent {
368 background: var(--accent);
369 color: var(--text-inverse);
370}
371
372.card {
373 background: var(--bg-card);
374 border: 1px solid var(--border-color);
375 border-radius: var(--radius-xl);
376 padding: var(--space-6);
377 overflow: hidden;
378 min-width: 0;
379}
380
381.section {
382 background: var(--bg-secondary);
383 border-radius: var(--radius-xl);
384 padding: var(--space-6);
385 overflow: hidden;
386 min-width: 0;
387}
388
389.section + .section {
390 margin-top: var(--space-6);
391}
392
393.page {
394 max-width: var(--width-lg);
395 margin: 0 auto;
396 padding: var(--space-7);
397}
398
399.page-sm {
400 max-width: var(--width-md);
401 margin: 0 auto;
402 padding: var(--space-7);
403}
404
405.page-lg {
406 max-width: var(--width-xl);
407 margin: 0 auto;
408 padding: var(--space-7);
409}
410
411.page-header {
412 margin-bottom: var(--space-6);
413}
414
415.page-header h1 {
416 margin: 0 0 var(--space-3) 0;
417}
418
419.page-header .subtitle {
420 color: var(--text-secondary);
421 margin: 0;
422}
423
424.loading {
425 display: flex;
426 flex-direction: column;
427 align-items: center;
428 gap: var(--space-4);
429 padding: var(--space-8);
430}
431
432.loading p {
433 color: var(--text-secondary);
434 margin: 0;
435}
436
437.back-link {
438 display: inline-block;
439 color: var(--text-secondary);
440 font-size: var(--text-sm);
441 margin-bottom: var(--space-3);
442 text-decoration: none;
443}
444
445.back-link:hover {
446 color: var(--accent);
447 text-decoration: none;
448}
449
450.text-muted {
451 color: var(--text-muted);
452}
453
454.text-secondary {
455 color: var(--text-secondary);
456}
457
458.text-sm {
459 font-size: var(--text-sm);
460}
461
462.text-xs {
463 font-size: var(--text-xs);
464}
465
466.text-center {
467 text-align: center;
468}
469
470.mono {
471 font-family: var(--font-mono);
472}
473
474.mt-4 {
475 margin-top: var(--space-4);
476}
477.mt-5 {
478 margin-top: var(--space-5);
479}
480.mt-6 {
481 margin-top: var(--space-6);
482}
483.mb-4 {
484 margin-bottom: var(--space-4);
485}
486.mb-5 {
487 margin-bottom: var(--space-5);
488}
489.mb-6 {
490 margin-bottom: var(--space-6);
491}
492
493.split-layout {
494 display: grid;
495 grid-template-columns: 1fr;
496 gap: var(--space-6);
497}
498
499@media (min-width: 800px) {
500 .split-layout {
501 grid-template-columns: 1fr 1fr;
502 align-items: start;
503 }
504 .split-layout.sidebar-right {
505 grid-template-columns: 1.5fr 1fr;
506 }
507 .split-layout.sidebar-left {
508 grid-template-columns: 1fr 1.5fr;
509 }
510}
511
512.split-layout > * {
513 min-width: 0;
514}
515
516.form-row {
517 display: grid;
518 grid-template-columns: 1fr;
519 gap: var(--space-4);
520}
521
522@media (min-width: 600px) {
523 .form-row {
524 grid-template-columns: repeat(2, 1fr);
525 }
526 .form-row.thirds {
527 grid-template-columns: repeat(3, 1fr);
528 }
529}
530
531.full-width {
532 grid-column: 1 / -1;
533}
534
535.info-panel {
536 background: var(--bg-secondary);
537 border-radius: var(--radius-xl);
538 padding: var(--space-6);
539 height: fit-content;
540 overflow: hidden;
541 min-width: 0;
542}
543
544.info-panel h3 {
545 margin: 0 0 var(--space-3) 0;
546 font-size: var(--text-base);
547 font-weight: var(--font-semibold);
548}
549
550.info-panel p {
551 margin: 0 0 var(--space-4) 0;
552 font-size: var(--text-sm);
553 color: var(--text-secondary);
554}
555
556.info-panel p:last-child {
557 margin-bottom: 0;
558}
559
560.spinner {
561 width: 40px;
562 height: 40px;
563 border: 3px solid var(--border-color);
564 border-top-color: var(--accent);
565 border-radius: 50%;
566 animation: spin 1s linear infinite;
567}
568
569.spinner.sm {
570 width: 20px;
571 height: 20px;
572 border-width: 2px;
573}
574
575.spinner.md {
576 width: 32px;
577 height: 32px;
578}
579
580.spinner.lg {
581 width: 60px;
582 height: 60px;
583 border-width: 4px;
584}
585
586@keyframes spin {
587 to {
588 transform: rotate(360deg);
589 }
590}
591
592.skeleton {
593 background: var(--bg-secondary);
594 border-radius: var(--radius-md);
595 animation: skeleton-pulse 1.5s ease-in-out infinite;
596}
597
598.skeleton-card {
599 height: 100px;
600 background: var(--bg-secondary);
601 border: 1px solid var(--border-color);
602 border-radius: var(--radius-xl);
603 animation: skeleton-pulse 1.5s ease-in-out infinite;
604}
605
606.skeleton-line {
607 height: var(--space-4);
608 background: var(--bg-secondary);
609 border-radius: var(--radius-sm);
610 animation: skeleton-pulse 1.5s ease-in-out infinite;
611}
612
613@keyframes skeleton-pulse {
614 0%, 100% { opacity: 1; }
615 50% { opacity: 0.5; }
616}
617
618.section-hint {
619 font-size: var(--text-sm);
620 color: var(--text-secondary);
621 margin: 0 0 var(--space-5) 0;
622}
623
624.radio-group {
625 display: flex;
626 flex-direction: column;
627 gap: var(--space-4);
628}
629
630.radio-label {
631 display: flex;
632 align-items: flex-start;
633 gap: var(--space-3);
634 cursor: pointer;
635 font-size: var(--text-base);
636 font-weight: var(--font-normal);
637 margin-bottom: 0;
638}
639
640.radio-label input[type="radio"] {
641 margin-top: var(--space-1);
642 width: auto;
643}
644
645.radio-content {
646 display: flex;
647 flex-direction: column;
648 gap: var(--space-1);
649}
650
651.radio-hint {
652 font-size: var(--text-xs);
653 color: var(--text-secondary);
654}
655
656.radio-label.disabled {
657 opacity: 0.5;
658 cursor: not-allowed;
659}
660
661.radio-hint.disabled-hint {
662 color: var(--warning-text);
663}
664
665.warning-box {
666 margin-top: var(--space-5);
667 padding: var(--space-5);
668 background: var(--warning-bg);
669 border: 1px solid var(--warning-border);
670 border-radius: var(--radius-lg);
671 font-size: var(--text-sm);
672}
673
674.warning-box strong {
675 display: block;
676 margin-bottom: var(--space-3);
677 color: var(--warning-text);
678}
679
680.warning-box ul {
681 margin: var(--space-4) 0 0 0;
682 padding-left: var(--space-5);
683}
684
685.warning-box li {
686 margin-bottom: var(--space-3);
687 line-height: var(--leading-normal);
688}
689
690.warning-box li:last-child {
691 margin-bottom: 0;
692}
693
694.migrate-callout {
695 display: flex;
696 gap: var(--space-4);
697 padding: var(--space-5);
698 background: var(--accent-muted);
699 border: 1px solid var(--accent);
700 border-radius: var(--radius-xl);
701 margin-bottom: var(--space-6);
702}
703
704.migrate-icon {
705 font-size: var(--text-2xl);
706 line-height: 1;
707 color: var(--accent);
708}
709
710.migrate-content {
711 flex: 1;
712}
713
714.migrate-content strong {
715 display: block;
716 color: var(--text-primary);
717 margin-bottom: var(--space-2);
718}
719
720.migrate-content p {
721 margin: 0 0 var(--space-3) 0;
722 font-size: var(--text-sm);
723 color: var(--text-secondary);
724 line-height: var(--leading-relaxed);
725}
726
727.migrate-link {
728 font-size: var(--text-sm);
729 font-weight: var(--font-medium);
730 color: var(--accent);
731 text-decoration: none;
732}
733
734.migrate-link:hover {
735 text-decoration: underline;
736}
737
738.app-password-step {
739 display: flex;
740 flex-direction: column;
741 gap: var(--space-5);
742 max-width: var(--width-md);
743 margin: 0 auto;
744}
745
746.app-password-step .warning-box {
747 margin-top: 0;
748}
749
750.app-password-step .warning-box p {
751 margin: 0;
752 color: var(--warning-text);
753}
754
755.app-password-display {
756 background: var(--bg-card);
757 border: 2px solid var(--accent);
758 border-radius: var(--radius-xl);
759 padding: var(--space-6);
760 text-align: center;
761}
762
763.app-password-label {
764 font-size: var(--text-sm);
765 color: var(--text-secondary);
766 margin-bottom: var(--space-4);
767}
768
769.app-password-code {
770 display: block;
771 font-size: var(--text-xl);
772 font-family: var(--font-mono);
773 letter-spacing: 0.1em;
774 padding: var(--space-5);
775 background: var(--bg-input);
776 border-radius: var(--radius-md);
777 margin-bottom: var(--space-4);
778 user-select: all;
779}
780
781.copy-btn {
782 padding: var(--space-3) var(--space-5);
783 font-size: var(--text-sm);
784}
785
786.checkbox-label {
787 display: flex;
788 align-items: center;
789 gap: var(--space-3);
790 cursor: pointer;
791 font-weight: var(--font-normal);
792}
793
794.checkbox-label input[type="checkbox"] {
795 width: auto;
796 padding: 0;
797}
798
799.form-section {
800 min-width: 0;
801}
802
803.form-links {
804 margin-top: var(--space-6);
805}
806
807.form-links .link-text {
808 text-align: center;
809 color: var(--text-secondary);
810}
811
812.form-links .link-text a {
813 color: var(--accent);
814}
815
816.contact-fields {
817 display: flex;
818 flex-direction: column;
819 gap: var(--space-4);
820}
821
822.contact-fields .field {
823 margin-bottom: 0;
824}
825
826.provider-badge {
827 display: flex;
828 align-items: center;
829 gap: var(--space-3);
830 padding: var(--space-4);
831 background: var(--bg-secondary);
832 border-radius: var(--radius-md);
833}
834
835.provider-details {
836 display: flex;
837 flex-direction: column;
838}
839
840.provider-name {
841 font-weight: var(--font-semibold);
842}
843
844.provider-username {
845 font-size: var(--text-sm);
846 color: var(--text-secondary);
847}
848
849.error-container {
850 text-align: center;
851 padding: var(--space-8);
852}
853
854.error-icon {
855 width: 48px;
856 height: 48px;
857 border-radius: 50%;
858 background: var(--error-text);
859 color: var(--text-inverse);
860 display: flex;
861 align-items: center;
862 justify-content: center;
863 font-size: var(--text-xl);
864 font-weight: var(--font-bold);
865 margin: 0 auto var(--space-4);
866}
867
868.error-container h2 {
869 margin-bottom: var(--space-2);
870}
871
872.error-container p {
873 color: var(--text-secondary);
874 margin-bottom: var(--space-6);
875}
876
877.info-list {
878 margin: 0;
879 padding-left: var(--space-5);
880}
881
882.info-list li {
883 margin-bottom: var(--space-2);
884 font-size: var(--text-sm);
885 color: var(--text-secondary);
886 line-height: var(--leading-relaxed);
887}
888
889.info-list li:last-child {
890 margin-bottom: 0;
891}
892
893.required {
894 color: var(--error-text);
895}