mobile bluesky app made with flutter
lazurite.stormlightlabs.org/
mobile
bluesky
flutter
1/* Oxocarbon Theme Variables */
2:root {
3 /* Oxocarbon Light Palette */
4 --oxo-light-bg: #ffffff;
5 --oxo-light-surface: #f4f4f4;
6 --oxo-light-surface-variant: #e0e0e0;
7 --oxo-light-border: #d1d1d1;
8 --oxo-light-text-primary: #161616;
9 --oxo-light-text-secondary: #525252;
10 --oxo-light-text-muted: #8d8d8d;
11
12 /* Oxocarbon Dark Palette */
13 --oxo-dark-bg: #161616;
14 --oxo-dark-surface: #262626;
15 --oxo-dark-surface-variant: #393939;
16 --oxo-dark-border: #525252;
17 --oxo-dark-text-primary: #f4f4f4;
18 --oxo-dark-text-secondary: #c6c6c6;
19 --oxo-dark-text-muted: #a8a8a8;
20
21 /* Accent Colors (BlueSky inspired) */
22 --accent-primary: #0066ff;
23 --accent-primary-hover: #0052cc;
24 --accent-secondary: #0ea5e9;
25 --accent-success: #22c55e;
26 --accent-error: #ef4444;
27 --accent-warning: #f59e0b;
28
29 /* Default to light theme */
30 --bg: var(--oxo-light-bg);
31 --surface: var(--oxo-light-surface);
32 --surface-variant: var(--oxo-light-surface-variant);
33 --border: var(--oxo-light-border);
34 --text-primary: var(--oxo-light-text-primary);
35 --text-secondary: var(--oxo-light-text-secondary);
36 --text-muted: var(--oxo-light-text-muted);
37}
38
39/* Oxocarbon Dark */
40[data-theme="dark"] {
41 --bg: var(--oxo-dark-bg);
42 --surface: var(--oxo-dark-surface);
43 --surface-variant: var(--oxo-dark-surface-variant);
44 --border: var(--oxo-dark-border);
45 --text-primary: var(--oxo-dark-text-primary);
46 --text-secondary: var(--oxo-dark-text-secondary);
47 --text-muted: var(--oxo-dark-text-muted);
48}
49
50/* Catppuccin Theme Variables */
51:root {
52 /* Catppuccin Latte (Light) */
53 --ctp-latte-bg: #eff1f5;
54 --ctp-latte-surface: #e6e9ef;
55 --ctp-latte-surface-variant: #ccd0da;
56 --ctp-latte-border: #bcc0cc;
57 --ctp-latte-text-primary: #4c4f69;
58 --ctp-latte-text-secondary: #6c6f85;
59 --ctp-latte-text-muted: #9ca0b0;
60
61 /* Catppuccin Mocha (Dark) */
62 --ctp-mocha-bg: #1e1e2e;
63 --ctp-mocha-surface: #181825;
64 --ctp-mocha-surface-variant: #313244;
65 --ctp-mocha-border: #45475a;
66 --ctp-mocha-text-primary: #cdd6f4;
67 --ctp-mocha-text-secondary: #a6adc8;
68 --ctp-mocha-text-muted: #7f849c;
69}
70
71/* Catppuccin Latte */
72[data-theme="catppuccin-latte"] {
73 --bg: var(--ctp-latte-bg);
74 --surface: var(--ctp-latte-surface);
75 --surface-variant: var(--ctp-latte-surface-variant);
76 --border: var(--ctp-latte-border);
77 --text-primary: var(--ctp-latte-text-primary);
78 --text-secondary: var(--ctp-latte-text-secondary);
79 --text-muted: var(--ctp-latte-text-muted);
80 --accent-primary: #7287fd;
81 --accent-primary-hover: #5c6ee6;
82 --accent-secondary: #209fb5;
83 --accent-success: #40a02b;
84 --accent-error: #d20f39;
85 --accent-warning: #fe640b;
86}
87
88/* Catppuccin Mocha */
89[data-theme="catppuccin-mocha"] {
90 --bg: var(--ctp-mocha-bg);
91 --surface: var(--ctp-mocha-surface);
92 --surface-variant: var(--ctp-mocha-surface-variant);
93 --border: var(--ctp-mocha-border);
94 --text-primary: var(--ctp-mocha-text-primary);
95 --text-secondary: var(--ctp-mocha-text-secondary);
96 --text-muted: var(--ctp-mocha-text-muted);
97 --accent-primary: #b4befe;
98 --accent-primary-hover: #9aa3e6;
99 --accent-secondary: #74c7ec;
100 --accent-success: #a6e3a1;
101 --accent-error: #f38ba8;
102 --accent-warning: #fab387;
103}
104
105/* Nord Theme Variables */
106:root {
107 /* Nord Snow Storm (Light) */
108 --nord-light-bg: #eceff4;
109 --nord-light-surface: #e5e9f0;
110 --nord-light-surface-variant: #d8dee9;
111 --nord-light-border: #c2c8d4;
112 --nord-light-text-primary: #2e3440;
113 --nord-light-text-secondary: #434c5e;
114 --nord-light-text-muted: #4c566a;
115
116 /* Nord Polar Night (Dark) */
117 --nord-dark-bg: #2e3440;
118 --nord-dark-surface: #3b4252;
119 --nord-dark-surface-variant: #434c5e;
120 --nord-dark-border: #4c566a;
121 --nord-dark-text-primary: #eceff4;
122 --nord-dark-text-secondary: #d8dee9;
123 --nord-dark-text-muted: #a5abb6;
124}
125
126/* Nord Snow Storm */
127[data-theme="nord-light"] {
128 --bg: var(--nord-light-bg);
129 --surface: var(--nord-light-surface);
130 --surface-variant: var(--nord-light-surface-variant);
131 --border: var(--nord-light-border);
132 --text-primary: var(--nord-light-text-primary);
133 --text-secondary: var(--nord-light-text-secondary);
134 --text-muted: var(--nord-light-text-muted);
135 --accent-primary: #5e81ac;
136 --accent-primary-hover: #4c6d96;
137 --accent-secondary: #88c0d0;
138 --accent-success: #a3be8c;
139 --accent-error: #bf616a;
140 --accent-warning: #d08770;
141}
142
143/* Nord Polar Night */
144[data-theme="nord-dark"] {
145 --bg: var(--nord-dark-bg);
146 --surface: var(--nord-dark-surface);
147 --surface-variant: var(--nord-dark-surface-variant);
148 --border: var(--nord-dark-border);
149 --text-primary: var(--nord-dark-text-primary);
150 --text-secondary: var(--nord-dark-text-secondary);
151 --text-muted: var(--nord-dark-text-muted);
152 --accent-primary: #88c0d0;
153 --accent-primary-hover: #6fb0c2;
154 --accent-secondary: #81a1c1;
155 --accent-success: #a3be8c;
156 --accent-error: #bf616a;
157 --accent-warning: #d08770;
158}
159
160/* Rosé Pine Theme Variables */
161:root {
162 /* Rosé Pine Dawn (Light) */
163 --rose-light-bg: #faf4ed;
164 --rose-light-surface: #fffaf3;
165 --rose-light-surface-variant: #f2e9e1;
166 --rose-light-border: #dfdad9;
167 --rose-light-text-primary: #575279;
168 --rose-light-text-secondary: #797593;
169 --rose-light-text-muted: #9893a5;
170
171 /* Rosé Pine Main (Dark) */
172 --rose-dark-bg: #191724;
173 --rose-dark-surface: #1f1d2e;
174 --rose-dark-surface-variant: #26233a;
175 --rose-dark-border: #524f67;
176 --rose-dark-text-primary: #e0def4;
177 --rose-dark-text-secondary: #908caa;
178 --rose-dark-text-muted: #6e6a86;
179}
180
181/* Rosé Pine Dawn */
182[data-theme="rose-pine-dawn"] {
183 --bg: var(--rose-light-bg);
184 --surface: var(--rose-light-surface);
185 --surface-variant: var(--rose-light-surface-variant);
186 --border: var(--rose-light-border);
187 --text-primary: var(--rose-light-text-primary);
188 --text-secondary: var(--rose-light-text-secondary);
189 --text-muted: var(--rose-light-text-muted);
190 --accent-primary: #d7827e;
191 --accent-primary-hover: #c56d69;
192 --accent-secondary: #56949f;
193 --accent-success: #286983;
194 --accent-error: #b4637a;
195 --accent-warning: #ea9d34;
196}
197
198/* Rosé Pine Main */
199[data-theme="rose-pine-moon"] {
200 --bg: var(--rose-dark-bg);
201 --surface: var(--rose-dark-surface);
202 --surface-variant: var(--rose-dark-surface-variant);
203 --border: var(--rose-dark-border);
204 --text-primary: var(--rose-dark-text-primary);
205 --text-secondary: var(--rose-dark-text-secondary);
206 --text-muted: var(--rose-dark-text-muted);
207 --accent-primary: #ebbcba;
208 --accent-primary-hover: #d9a8a6;
209 --accent-secondary: #9ccfd8;
210 --accent-success: #31748f;
211 --accent-error: #eb6f92;
212 --accent-warning: #f6c177;
213}
214
215/* Base Reset */
216*, *::before, *::after {
217 box-sizing: border-box;
218 margin: 0;
219 padding: 0;
220}
221
222html {
223 font-size: 16px;
224 -webkit-font-smoothing: antialiased;
225 -moz-osx-font-smoothing: grayscale;
226}
227
228/* Font Variables */
229:root {
230 --font-heading: 'Lora', Georgia, 'Times New Roman', serif;
231 --font-body: 'DM Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
232 --font-mono: 'JetBrains Mono', 'IBM Plex Mono', 'Fira Code', monospace;
233}
234
235body {
236 font-family: var(--font-body);
237 background-color: var(--bg);
238 color: var(--text-primary);
239 line-height: 1.5;
240 min-height: 100vh;
241}
242
243/* Typography */
244h1, h2, h3, h4, h5, h6 {
245 font-family: var(--font-heading);
246 font-weight: 600;
247 color: var(--text-primary);
248}
249
250p {
251 color: var(--text-secondary);
252}
253
254/* Mobile Container */
255.mobile-container {
256 max-width: 414px;
257 margin: 0 auto;
258 min-height: 100vh;
259 background-color: var(--bg);
260 position: relative;
261 border-left: 1px solid var(--border);
262 border-right: 1px solid var(--border);
263}
264
265@media (max-width: 414px) {
266 .mobile-container {
267 border: none;
268 }
269}
270
271/* Navigation Bar */
272.nav-bar {
273 position: fixed;
274 bottom: 0;
275 left: 50%;
276 transform: translateX(-50%);
277 width: 100%;
278 max-width: 414px;
279 background-color: var(--surface);
280 border-top: 1px solid var(--border);
281 display: flex;
282 justify-content: space-around;
283 padding: 12px 0 24px;
284 z-index: 100;
285}
286
287.nav-item {
288 display: flex;
289 flex-direction: column;
290 align-items: center;
291 gap: 4px;
292 padding: 8px 16px;
293 color: var(--text-secondary);
294 text-decoration: none;
295 transition: color 0.2s ease;
296}
297
298.nav-item:hover,
299.nav-item.active {
300 color: var(--accent-primary);
301}
302
303.nav-item svg {
304 width: 24px;
305 height: 24px;
306}
307
308.nav-item span {
309 font-size: 12px;
310 font-weight: 500;
311}
312
313/* Header */
314.header {
315 position: sticky;
316 top: 0;
317 background-color: var(--bg);
318 border-bottom: 1px solid var(--border);
319 padding: 12px 16px;
320 z-index: 50;
321 display: flex;
322 align-items: center;
323 justify-content: space-between;
324}
325
326.header-title {
327 font-size: 18px;
328 font-weight: 600;
329}
330
331.header-action {
332 background: none;
333 border: none;
334 color: var(--accent-primary);
335 font-size: 14px;
336 font-weight: 600;
337 cursor: pointer;
338 padding: 8px 12px;
339}
340
341/* Buttons */
342.btn {
343 display: inline-flex;
344 align-items: center;
345 justify-content: center;
346 gap: 8px;
347 padding: 12px 24px;
348 border-radius: 9999px;
349 font-size: 15px;
350 font-weight: 600;
351 cursor: pointer;
352 transition: all 0.2s ease;
353 border: none;
354 width: 100%;
355}
356
357.btn-primary {
358 background-color: var(--accent-primary);
359 color: white;
360}
361
362.btn-primary:hover {
363 background-color: var(--accent-primary-hover);
364}
365
366.btn-secondary {
367 background-color: var(--surface);
368 color: var(--text-primary);
369 border: 1px solid var(--border);
370}
371
372.btn-secondary:hover {
373 background-color: var(--surface-variant);
374}
375
376.btn-outline {
377 background-color: transparent;
378 color: var(--accent-primary);
379 border: 1.5px solid var(--accent-primary);
380}
381
382.btn-outline:hover {
383 background-color: rgba(0, 102, 255, 0.1);
384}
385
386/* Cards */
387.card {
388 background-color: var(--surface);
389 border-radius: 12px;
390 padding: 16px;
391 border: 1px solid var(--border);
392}
393
394/* Inputs */
395.input {
396 width: 100%;
397 padding: 12px 16px;
398 border: 1px solid var(--border);
399 border-radius: 8px;
400 background-color: var(--surface);
401 color: var(--text-primary);
402 font-size: 15px;
403 transition: border-color 0.2s ease;
404}
405
406.input:focus {
407 outline: none;
408 border-color: var(--accent-primary);
409}
410
411.input::placeholder {
412 color: var(--text-muted);
413}
414
415/* Divider */
416.divider {
417 height: 1px;
418 background-color: var(--border);
419 margin: 16px 0;
420}
421
422/* Avatar */
423.avatar {
424 width: 48px;
425 height: 48px;
426 border-radius: 50%;
427 background-color: var(--surface-variant);
428 display: flex;
429 align-items: center;
430 justify-content: center;
431 font-weight: 600;
432 color: var(--text-secondary);
433 flex-shrink: 0;
434}
435
436.avatar-sm {
437 width: 40px;
438 height: 40px;
439 font-size: 14px;
440}
441
442.avatar-lg {
443 width: 80px;
444 height: 80px;
445 font-size: 28px;
446}
447
448/* Post Card */
449.post-card {
450 padding: 16px;
451 border-bottom: 1px solid var(--border);
452 background-color: var(--bg);
453}
454
455.post-header {
456 display: flex;
457 gap: 12px;
458 margin-bottom: 12px;
459}
460
461.post-author {
462 flex: 1;
463}
464
465.post-author-name {
466 font-weight: 600;
467 color: var(--text-primary);
468 font-size: 15px;
469}
470
471.post-author-handle {
472 color: var(--text-secondary);
473 font-size: 14px;
474}
475
476.post-timestamp {
477 color: var(--text-muted);
478 font-size: 13px;
479}
480
481.post-content {
482 color: var(--text-primary);
483 font-size: 15px;
484 line-height: 1.5;
485 margin-bottom: 12px;
486}
487
488.post-facet {
489 color: var(--accent-primary);
490 text-decoration: none;
491}
492
493.post-facet:hover {
494 text-decoration: underline;
495}
496
497.post-actions {
498 display: flex;
499 gap: 24px;
500}
501
502.post-action {
503 display: flex;
504 align-items: center;
505 gap: 6px;
506 color: var(--text-secondary);
507 font-size: 13px;
508 background: none;
509 border: none;
510 cursor: pointer;
511 transition: color 0.2s ease;
512}
513
514.post-action:hover {
515 color: var(--accent-primary);
516}
517
518.post-action svg {
519 width: 20px;
520 height: 20px;
521}
522
523/* Settings Items */
524.settings-item {
525 display: flex;
526 align-items: center;
527 justify-content: space-between;
528 padding: 16px;
529 border-bottom: 1px solid var(--border);
530 cursor: pointer;
531 transition: background-color 0.2s ease;
532}
533
534.settings-item:hover {
535 background-color: var(--surface);
536}
537
538.settings-item-left {
539 display: flex;
540 align-items: center;
541 gap: 12px;
542}
543
544.settings-item-icon {
545 width: 24px;
546 height: 24px;
547 color: var(--text-secondary);
548}
549
550.settings-item-content {
551 display: flex;
552 flex-direction: column;
553}
554
555.settings-item-title {
556 font-weight: 500;
557 color: var(--text-primary);
558 font-size: 15px;
559}
560
561.settings-item-subtitle {
562 color: var(--text-secondary);
563 font-size: 13px;
564}
565
566.settings-item-right {
567 display: flex;
568 align-items: center;
569 gap: 8px;
570}
571
572/* Toggle Switch */
573.toggle {
574 width: 48px;
575 height: 28px;
576 background-color: var(--surface-variant);
577 border-radius: 14px;
578 position: relative;
579 cursor: pointer;
580 transition: background-color 0.3s ease;
581}
582
583.toggle.active {
584 background-color: var(--accent-primary);
585}
586
587.toggle-thumb {
588 position: absolute;
589 top: 2px;
590 left: 2px;
591 width: 24px;
592 height: 24px;
593 background-color: white;
594 border-radius: 50%;
595 transition: transform 0.3s ease;
596 box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
597}
598
599.toggle.active .toggle-thumb {
600 transform: translateX(20px);
601}
602
603/* Theme Preview */
604.theme-preview {
605 width: 40px;
606 height: 40px;
607 border-radius: 8px;
608 border: 2px solid var(--border);
609 cursor: pointer;
610 transition: all 0.2s ease;
611}
612
613.theme-preview:hover,
614.theme-preview.active {
615 border-color: var(--accent-primary);
616 transform: scale(1.05);
617}
618
619.theme-preview-light {
620 background: linear-gradient(135deg, #ffffff 50%, #f4f4f4 50%);
621}
622
623.theme-preview-dark {
624 background: linear-gradient(135deg, #161616 50%, #262626 50%);
625}
626
627.theme-preview-catppuccin-latte {
628 background: linear-gradient(135deg, #eff1f5 50%, #e6e9ef 50%);
629}
630
631.theme-preview-catppuccin-mocha {
632 background: linear-gradient(135deg, #1e1e2e 50%, #181825 50%);
633}
634
635.theme-preview-nord-light {
636 background: linear-gradient(135deg, #eceff4 50%, #e5e9f0 50%);
637}
638
639.theme-preview-nord-dark {
640 background: linear-gradient(135deg, #2e3440 50%, #3b4252 50%);
641}
642
643.theme-preview-rose-pine-dawn {
644 background: linear-gradient(135deg, #faf4ed 50%, #fffaf3 50%);
645}
646
647.theme-preview-rose-pine-moon {
648 background: linear-gradient(135deg, #191724 50%, #1f1d2e 50%);
649}
650
651/* Scrollbar Styling */
652::-webkit-scrollbar {
653 width: 6px;
654}
655
656::-webkit-scrollbar-track {
657 background: var(--surface);
658}
659
660::-webkit-scrollbar-thumb {
661 background: var(--surface-variant);
662 border-radius: 3px;
663}
664
665::-webkit-scrollbar-thumb:hover {
666 background: var(--border);
667}
668
669/* Safe Area for Mobile */
670.safe-area-bottom {
671 padding-bottom: 88px;
672}
673
674/* Screen Content Padding */
675.screen-content {
676 padding: 16px;
677}
678
679/* Debug Badge */
680.debug-badge {
681 display: inline-flex;
682 align-items: center;
683 gap: 4px;
684 padding: 4px 8px;
685 background-color: var(--accent-warning);
686 color: #161616;
687 font-size: 11px;
688 font-weight: 600;
689 border-radius: 4px;
690 text-transform: uppercase;
691}
692
693/* OAuth Provider Button */
694.oauth-btn {
695 display: flex;
696 align-items: center;
697 justify-content: center;
698 gap: 12px;
699 padding: 14px 24px;
700 border-radius: 9999px;
701 border: 1.5px solid var(--border);
702 background-color: var(--surface);
703 color: var(--text-primary);
704 font-size: 15px;
705 font-weight: 600;
706 cursor: pointer;
707 transition: all 0.2s ease;
708 width: 100%;
709}
710
711.oauth-btn:hover {
712 background-color: var(--surface-variant);
713 border-color: var(--text-secondary);
714}
715
716.oauth-btn svg {
717 width: 20px;
718 height: 20px;
719}
720
721/* Link */
722.link {
723 color: var(--accent-primary);
724 text-decoration: none;
725 font-weight: 500;
726}
727
728.link:hover {
729 text-decoration: underline;
730}
731
732/* Empty State */
733.empty-state {
734 display: flex;
735 flex-direction: column;
736 align-items: center;
737 justify-content: center;
738 padding: 48px 24px;
739 text-align: center;
740}
741
742.empty-state-icon {
743 width: 64px;
744 height: 64px;
745 color: var(--text-muted);
746 margin-bottom: 16px;
747}
748
749.empty-state-title {
750 font-size: 18px;
751 font-weight: 600;
752 color: var(--text-primary);
753 margin-bottom: 8px;
754}
755
756.empty-state-text {
757 color: var(--text-secondary);
758 font-size: 14px;
759 max-width: 280px;
760}