Skip to main content

euv_ui/style/class/page/
fn.rs

1use super::*;
2
3class! {
4
5    // ═══════════════════════════════════════════════════════════════════════════
6    // Page Banner (unified header with emoji icon)
7    // ═══════════════════════════════════════════════════════════════════════════
8
9    pub(crate) c_page {
10        position: "relative";
11        text-align: "center";
12        box-sizing: "border-box";
13    }
14
15
16    pub(crate) c_page_glow {
17        position: "absolute";
18        top: "-50%";
19        left: "50%";
20        transform: "translateX(-50%)";
21        width: "400px";
22        max-width: "100%";
23        height: "400px";
24        pointer-events: "none";
25    }
26
27
28    pub(crate) c_page_content {
29        position: "relative";
30        z-index: "1";
31    }
32
33
34    pub(crate) c_page_icon {
35        font-size: "36px";
36        padding-bottom: var!(space-md);
37        @media ((max-width: 767px)) {
38            font-size: "40px";
39        }
40    }
41
42
43    pub(crate) c_page_title {
44        font-size: var!(font-4xl);
45        font-weight: "800";
46        letter-spacing: "-0.03em";
47        margin: "0px";
48        color: var!(foreground);
49        margin-bottom: var!(space-sm);
50        @media ((max-width: 767px)) {
51            font-size: var!(font-3xl);
52        }
53    }
54
55
56    pub(crate) c_page_subtitle {
57        font-size: var!(font-lg);
58        color: var!(muted-foreground);
59        margin: "0px auto";
60        margin-bottom: var!(space-sm);
61        max-width: "560px";
62        opacity: "1";
63        @media ((max-width: 767px)) {
64            font-size: var!(font-base);
65        }
66    }
67
68
69    // ═══════════════════════════════════════════════════════════════════════════
70    // Camera Page
71    // ═══════════════════════════════════════════════════════════════════════════
72
73    pub c_camera_video_container {
74        margin: format!("{} 0", var!(space-lg));
75    }
76
77
78    pub c_camera_video_active {
79        width: "100%";
80        background: "#000";
81        aspect-ratio: "16 / 9";
82        object-fit: "cover";
83        border: format!("2px solid {}", var!(accent));
84        box-sizing: "border-box";
85    }
86
87
88    pub c_camera_video_hidden {
89        width: "100%";
90        aspect-ratio: "16 / 9";
91        display: "none";
92    }
93
94
95    pub c_camera_video_placeholder {
96        width: "100%";
97        aspect-ratio: "16 / 9";
98        border: format!("2px dashed {}", var!(border));
99        display: "flex";
100        align-items: "center";
101        justify-content: "center";
102        box-sizing: "border-box";
103    }
104
105
106    pub c_camera_placeholder_content {
107        display: "flex";
108        flex-direction: "column";
109        align-items: "center";
110        gap: var!(space-md);
111    }
112
113
114    pub c_camera_placeholder_icon {
115        font-size: var!(font-4xl);
116        opacity: "1";
117    }
118
119
120    pub c_camera_placeholder_text {
121        font-size: var!(font-base);
122        color: "inherit";
123        opacity: "1";
124    }
125
126
127    pub c_camera_error_box {
128        margin: format!("{} 0px", var!(gap-component));
129        color: var!(foreground);
130        font-size: var!(font-base);
131        word-break: "break-all";
132        overflow-wrap: "break-word";
133        box-sizing: "border-box";
134    }
135
136
137    pub c_camera_scan_result_box {
138        margin-top: var!(gap-component);
139        box-sizing: "border-box";
140    }
141
142
143    pub c_camera_scan_result_label {
144        font-size: var!(font-sm);
145        font-weight: "600";
146        color: var!(foreground);
147        margin-bottom: var!(space-xs);
148    }
149
150
151    pub c_camera_scan_result_value {
152        font-size: var!(font-base);
153        color: "inherit";
154        word-break: "break-all";
155        overflow-wrap: "break-word";
156    }
157
158
159    // ═══════════════════════════════════════════════════════════════════════════
160    // Canvas Drawing Board
161    // ═══════════════════════════════════════════════════════════════════════════
162
163    pub c_canvas_preview_container {
164        margin: format!("{} 0", var!(space-lg));
165        overflow: "hidden";
166        border: format!("2px solid {}", var!(border));
167        background: "#ffffff";
168        aspect-ratio: "9 / 16";
169        display: "flex";
170        align-items: "center";
171        justify-content: "center";
172        box-sizing: "border-box";
173    }
174
175
176    pub c_canvas_placeholder {
177        color: var!(muted-foreground);
178        font-size: var!(font-sm);
179        text-align: "center";
180        padding: var!(space-lg);
181    }
182
183
184    pub c_canvas_preview_image {
185        width: "100%";
186        height: "100%";
187        object-fit: "cover";
188        display: "block";
189    }
190
191
192    pub c_canvas_container_fullscreen {
193        width: "100%";
194        height: "100%";
195        background: var!(background);
196        display: "flex";
197        flex-direction: "column";
198        position: "fixed";
199        top: "0";
200        left: "0";
201        z-index: "10002";
202        padding: format!("{} {} {} {}", var!(padding-shell-top), var!(space-lg), var!(padding-shell-bottom), var!(space-lg));
203        box-sizing: "border-box";
204    }
205
206
207    pub c_canvas_drawing_fullscreen_wrapper {
208        flex: "1";
209        display: "flex";
210        align-items: "center";
211        justify-content: "center";
212        overflow: "hidden";
213        padding: var!(space-xs);
214    }
215
216
217    pub c_canvas_drawing_fullscreen {
218        border: format!("2px solid {}", var!(border));
219        display: "block";
220        cursor: "crosshair";
221        touch-action: "none";
222    }
223
224
225    pub c_canvas_fullscreen_toolbar {
226        display: "flex";
227        flex-direction: "column";
228        align-items: "stretch";
229        width: "100%";
230        padding: format!("{} {}", var!(space-xs), "0px");
231        flex-shrink: "0";
232        gap: var!(space-xs);
233    }
234
235
236    pub c_canvas_fullscreen_toolbar_row_top {
237        display: "flex";
238        align-items: "center";
239        height: var!(mobile-header-height);
240        width: "100%";
241        gap: var!(space-sm);
242    }
243
244
245    pub c_canvas_fullscreen_toolbar_color_wrapper {
246        display: "flex";
247        align-items: "center";
248        justify-content: "center";
249        flex: "1";
250        min-width: "0";
251    }
252
253
254    pub c_canvas_color_input_fullscreen {
255        width: "100%";
256        height: "42px";
257        border: format!("1px solid {}", var!(border));
258        cursor: "pointer";
259        padding: format!("{}", var!(space-xs));
260    }
261
262
263    pub c_canvas_fullscreen_toolbar_row_bottom {
264        display: "flex";
265        align-items: "center";
266        width: "100%";
267    }
268
269
270    pub c_canvas_fullscreen_range_input {
271        flex: "1 1 0%";
272        min-width: "120px";
273        cursor: "pointer";
274        -webkit-appearance: "none";
275        appearance: "none";
276        border: "none";
277        outline: "none";
278        height: "24px";
279        ::-webkit-slider-runnable-track {
280            height: "6px";
281            background: format!("linear-gradient(to right, {} 0%, {} var(--value,50%), {} var(--value,50%), {} 100%)", var!(foreground), var!(foreground), var!(border), var!(border));
282            border-radius: "3px";
283            border: "none";
284        }
285        ::-webkit-slider-thumb {
286            width: "20px";
287            height: "20px";
288            background: var!(background);
289            border: format!("2px solid {}", var!(accent));
290            border-radius: "50%";
291            cursor: "pointer";
292            -webkit-appearance: "none";
293            margin-top: "-7px";
294        }
295        ::-moz-range-track {
296            height: "6px";
297            background: format!("linear-gradient(to right, {} 0%, {} var(--value,50%), {} var(--value,50%), {} 100%)", var!(foreground), var!(foreground), var!(border), var!(border));
298            border-radius: "3px";
299            border: "none";
300        }
301        ::-moz-range-thumb {
302            width: "20px";
303            height: "20px";
304            background: var!(background);
305            border: format!("2px solid {}", var!(accent));
306            border-radius: "50%";
307            cursor: "pointer";
308        }
309    }
310
311
312    pub c_canvas_fullscreen_toolbar_button {
313        flex: "0 0 auto";
314        overflow: "hidden";
315    }
316
317
318    // ═══════════════════════════════════════════════════════════════════════════
319    // Game Fullscreen (2D / 3D)
320    // ═══════════════════════════════════════════════════════════════════════════
321
322    // Fullscreen overlay container for the 2D and 3D game pages.
323    //
324    // Mirrors `c_canvas_container_fullscreen` so the safe-area caching
325    // pass in `UseEuvLayout::apply_cached_insets` can pick this selector
326    // up alongside the canvas one. Differs in that the game overlay holds
327    // the *same* `<canvas>` element that the inline page mounts (no
328    // canvas re-creation), so the running game loop, balls, cubes, FPS
329    // counter and other reactive state survive the fullscreen toggle
330    // without reset.
331    pub c_game_container_fullscreen {
332        width: "100%";
333        height: "100%";
334        background: var!(background);
335        display: "flex";
336        flex-direction: "column";
337        position: "fixed";
338        top: "0";
339        left: "0";
340        z-index: "10002";
341        padding: format!(
342        "{} {} {} {}",
343        var!(padding-shell-top),
344        var!(space-lg),
345        var!(padding-shell-bottom),
346        var!(space-lg)
347        );
348        box-sizing: "border-box";
349    }
350
351
352    // Toolbar wrapping the fullscreen exit button on game pages.
353    //
354    // Game pages only need an `Exit` button here (no color picker / line
355    // width control like the canvas drawing board), so the layout is a
356    // single horizontal row at the bottom of the overlay.
357    pub c_game_fullscreen_toolbar {
358        display: "flex";
359        align-items: "center";
360        justify-content: "flex-end";
361        width: "100%";
362        padding: format!("{} {} {} {}", var!(space-xs), var!(space-lg), var!(space-xs), var!(space-lg));
363        flex-shrink: "0";
364        gap: var!(space-sm);
365        box-sizing: "border-box";
366    }
367
368
369    // Wrapper that fills the fullscreen game container with the canvas.
370    //
371    // The game's `<canvas>` backing buffer is 600x400 (3:2). The canvas
372    // itself has `width: 100%; height: 100%` so it fills this wrapper
373    // exactly, and `object-fit: contain` on the canvas class makes the
374    // browser uniformly scale the backing buffer to fit while preserving
375    // its 3:2 aspect ratio. Without `object-fit: contain`, the canvas
376    // would be stretched to whatever shape the wrapper has, making balls
377    // render as horizontally-ovoid ellipses (e.g. on 1280x800 viewports
378    // → 1.6:1, slightly squashed vertically). The letterbox bars appear
379    // inside the canvas element rather than around an outer wrapper, so
380    // the canvas always fills the fullscreen container with the backing
381    // buffer uniformly scaled to its native aspect ratio.
382    pub c_game_fullscreen_canvas_letterbox {
383        position: "relative";
384        width: "100%";
385        max-width: "100%";
386        max-height: "100%";
387        height: "100%";
388        display: "flex";
389        align-items: "center";
390        justify-content: "center";
391    }
392
393
394    // ═══════════════════════════════════════════════════════════════════════════
395    // Custom Attrs Demo
396    // ═══════════════════════════════════════════════════════════════════════════
397
398    pub c_custom_attrs_demo {
399        // Use the theme foreground token (not `inherit`) so the text inside
400        // the dynamic demo block stays readable when the block itself
401        // applies a user-supplied background (e.g. `background-color: #000000`)
402        // that otherwise paints the inherited text the same colour.
403        color: var!(foreground);
404        box-sizing: "border-box";
405    }
406
407
408    pub c_demo_text {
409        color: var!(foreground);
410        margin-bottom: var!(gap-component);
411    }
412
413
414    pub c_demo_text_muted {
415        color: var!(foreground);
416        opacity: "1";
417        font-size: var!(font-base);
418        margin-bottom: "0px";
419    }
420
421
422    // ═══════════════════════════════════════════════════════════════════════════
423    // Conditional Rendering Demo
424    // ═══════════════════════════════════════════════════════════════════════════
425
426    pub c_toggle_content {
427        margin-top: var!(gap-component);
428        color: "inherit";
429    }
430
431
432    pub c_toggle_title {
433        margin-top: "0px";
434        color: var!(accent);
435        font-size: var!(font-md);
436    }
437
438
439    pub c_role_button_row {
440        display: "flex";
441        flex-wrap: "nowrap";
442        gap: var!(gap-element);
443        margin-bottom: var!(gap-component);
444    }
445
446
447    pub c_role_guest_text {
448        color: var!(foreground);
449        font-size: var!(font-base);
450    }
451
452
453    pub c_role_user_text {
454        color: var!(foreground);
455        font-size: var!(font-base);
456    }
457
458
459    pub c_role_admin_text {
460        color: var!(foreground);
461        font-size: var!(font-base);
462    }
463
464
465    // ═══════════════════════════════════════════════════════════════════════════
466    // 404 Not Found
467    // ═══════════════════════════════════════════════════════════════════════════
468
469    pub c_render_count_text {
470        font-size: var!(font-base);
471        color: "inherit";
472        margin-bottom: var!(gap-component);
473    }
474
475
476    // ═══════════════════════════════════════════════════════════════════════════
477    // Event Demo
478    // ═══════════════════════════════════════════════════════════════════════════
479
480    pub c_event_result {
481        font-size: var!(font-base);
482        color: "inherit";
483        margin-top: var!(gap-element);
484    }
485
486
487    pub c_event_highlight {
488        font-weight: "600";
489        color: var!(accent);
490    }
491
492
493    pub c_event_info_grid {
494        display: "grid";
495        grid-template-columns: "1fr 1fr";
496        gap: var!(gap-element);
497        margin-top: var!(gap-component);
498        @media ((max-width: 767px)) {
499            grid-template-columns: "1fr";
500            gap: var!(gap-element);
501        }
502    }
503
504
505    pub c_event_info_row {
506        display: "flex";
507        align-items: "center";
508        gap: var!(space-sm);
509        overflow: "hidden";
510    }
511
512
513    pub c_event_info_label {
514        font-size: var!(font-base);
515        font-weight: "600";
516        color: var!(foreground);
517        flex-shrink: "0";
518    }
519
520
521    pub c_event_info_value {
522        c_text_ellipsis();
523        font-size: var!(font-base);
524        font-weight: "600";
525        color: var!(accent);
526        font-family: "ui-monospace, monospace";
527        flex: "1";
528    }
529
530
531    pub c_event_mouse_area {
532        min-height: "120px";
533        padding: format!("{} 0px", var!(space-xl));
534        border: format!("2px dashed {}", var!(border));
535        cursor: "crosshair";
536        text-align: "center";
537        user-select: "none";
538        color: "inherit";
539    }
540
541
542    pub c_event_drag_zone {
543        min-height: "100px";
544        padding: format!("{} 0px", var!(space-xl));
545        border: format!("2px dashed {}", var!(border));
546        text-align: "center";
547        user-select: "none";
548        color: var!(foreground);
549    }
550
551
552    pub c_event_drag_zone_active {
553        min-height: "100px";
554        padding: format!("{} 0px", var!(space-xl));
555        border: format!("2px dashed {}", var!(border));
556        text-align: "center";
557        user-select: "none";
558        color: var!(foreground);
559    }
560
561
562    pub c_event_drag_item {
563        display: "inline-block";
564        padding: format!("{} {}", var!(space-sm), var!(space-xl));
565        background: var!(accent);
566        color: var!(text-on-accent);
567        font-size: var!(font-base);
568        font-weight: "500";
569        cursor: "grab";
570        margin: var!(space-sm);
571    }
572
573
574    pub c_event_drop_zone {
575        border: format!("2px dashed {}", var!(border));
576        padding: format!("{} {}", var!(space-4xl), var!(space-xl));
577        text-align: "center";
578        cursor: "pointer";
579    }
580
581
582    pub c_event_drop_zone_active {
583        border: format!("2px dashed {}", var!(accent));
584        padding: format!("{} {}", var!(space-4xl), var!(space-xl));
585        text-align: "center";
586        cursor: "pointer";
587        background: var!(accent-muted);
588    }
589
590
591    pub c_event_drop_icon {
592        font-size: var!(font-5xl);
593        display: "block";
594        padding-bottom: var!(space-md);
595    }
596
597
598    pub c_event_drop_text {
599        font-size: var!(font-lg);
600        font-weight: "500";
601        color: "inherit";
602        padding-bottom: var!(space-md);
603    }
604
605
606    pub c_event_drop_hint {
607        font-size: var!(font-base);
608        color: "inherit";
609        opacity: "1";
610        margin: "0px";
611    }
612
613
614    pub c_event_wheel_zone {
615        min-height: "120px";
616        padding: format!("{} 0px", var!(space-xl));
617        border: format!("2px dashed {}", var!(border));
618        text-align: "center";
619        overflow: "auto";
620        color: var!(foreground);
621    }
622
623
624    pub c_event_clipboard_area {
625        color: var!(foreground);
626    }
627
628
629    pub c_event_touch_zone {
630        min-height: "120px";
631        padding: format!("{} 0px", var!(space-xl));
632        border: format!("2px dashed {}", var!(accent));
633        text-align: "center";
634        touch-action: "none";
635        user-select: "none";
636        color: var!(accent);
637    }
638
639
640    pub c_event_form_area {
641        padding: format!("{} 0px", var!(space-lg));
642        color: var!(foreground);
643    }
644
645
646    pub c_event_media_area {
647        padding: format!("{} 0px", var!(space-lg));
648        color: var!(foreground);
649        max-width: "100%";
650        overflow: "hidden";
651    }
652
653
654    pub c_event_audio {
655        width: "100%";
656        max-width: "100%";
657    }
658
659
660    pub c_event_video_area {
661        color: var!(foreground);
662        width: "100%";
663        overflow: "hidden";
664    }
665
666
667    pub c_event_video {
668        width: "100%";
669        max-width: "100%";
670    }
671
672
673    pub c_event_image_area {
674        padding: format!("{} 0px", var!(space-lg));
675        color: "inherit";
676        width: "100%";
677        overflow: "hidden";
678        display: "flex";
679        flex-direction: "column";
680        align-items: "center";
681        gap: var!(space-md);
682    }
683
684
685    pub c_event_image {
686        width: "200px";
687        max-width: "100%";
688        object-fit: "contain";
689        display: "block";
690    }
691
692
693    pub c_event_url_text {
694        text-align: "center";
695        font-size: var!(font-sm);
696        color: "inherit";
697        opacity: "1";
698        font-family: "ui-monospace, monospace";
699        word-break: "break-all";
700        width: "100%";
701    }
702
703
704    // ═══════════════════════════════════════════════════════════════════════════
705    // Timer Demo
706    // ═══════════════════════════════════════════════════════════════════════════
707
708    pub c_timer_display {
709        text-align: "center";
710        padding: var!(space-xl);
711        margin: format!("{} 0px", var!(gap-component));
712        color: "inherit";
713    }
714
715
716    pub c_timer_value {
717        font-size: var!(font-base);
718        font-weight: "700";
719        color: var!(accent);
720        letter-spacing: "0.04em";
721        font-family: "ui-monospace, monospace";
722    }
723
724
725    pub c_timer_controls {
726        display: "flex";
727        flex-wrap: "wrap";
728        gap: var!(gap-element);
729    }
730
731
732    pub c_timer_done {
733        text-align: "center";
734        margin-top: var!(gap-component);
735        font-size: var!(font-lg);
736        font-weight: "600";
737        color: var!(foreground);
738    }
739
740
741    // ═══════════════════════════════════════════════════════════════════════════
742    // Browser API Demo
743    // ═══════════════════════════════════════════════════════════════════════════
744
745    pub c_browser_api_row {
746        display: "grid";
747        grid-template-columns: "1fr 1fr";
748        gap: var!(gap-component);
749        margin-bottom: var!(gap-component);
750        @media ((max-width: 767px)) {
751            grid-template-columns: "1fr";
752        }
753    }
754
755
756    pub c_browser_api_actions {
757        display: "flex";
758        flex-wrap: "wrap";
759        gap: var!(gap-element);
760        margin: format!("{} 0px", var!(gap-component));
761    }
762
763
764    pub c_browser_result_box {
765        margin-top: var!(gap-component);
766        font-size: var!(font-base);
767        word-break: "break-all";
768        color: "inherit";
769    }
770
771
772    pub c_browser_result_label {
773        font-weight: "600";
774        color: var!(accent);
775    }
776
777
778    pub c_browser_result_value {
779        color: "inherit";
780    }
781
782
783    pub c_browser_info_grid {
784        display: "grid";
785        gap: var!(gap-component);
786        margin-top: var!(gap-component);
787        @media ((max-width: 767px)) {
788            grid-template-columns: "1fr";
789        }
790    }
791
792
793    pub c_browser_info_item {
794        display: "flex";
795        flex-direction: "column";
796        gap: var!(space-xs);
797        color: "inherit";
798    }
799
800
801    pub c_browser_info_label {
802        font-size: var!(font-sm);
803        font-weight: "600";
804        color: "inherit";
805        opacity: "1";
806        text-transform: "uppercase";
807        letter-spacing: "0.05em";
808    }
809
810
811    pub c_browser_info_value {
812        font-size: var!(font-base);
813        color: "inherit";
814        word-break: "break-all";
815        font-family: "ui-monospace, monospace";
816    }
817
818
819    // ═══════════════════════════════════════════════════════════════════════════
820    // Keep-Alive Demo
821    // ═══════════════════════════════════════════════════════════════════════════
822
823    pub c_keep_alive_tab_bar {
824        display: "flex";
825        border-bottom: format!("1px dashed {}", var!(border));
826        margin-bottom: var!(gap-component);
827        gap: var!(gap-element);
828    }
829
830
831    pub c_keep_alive_tab_panel {
832        padding: format!("{} 0px", var!(gap-element));
833    }
834
835
836    pub c_keep_alive_panel_title {
837        margin-top: "0px";
838        color: var!(accent);
839        font-size: var!(font-md);
840        margin-bottom: var!(gap-element);
841    }
842
843
844    pub c_keep_alive_demo_text {
845        color: "inherit";
846        font-size: var!(font-base);
847        margin-bottom: var!(gap-component);
848    }
849
850
851    pub c_keep_alive_counter_display {
852        display: "flex";
853        justify-content: "center";
854        align-items: "center";
855        margin: format!("{} 0px", var!(space-xl));
856    }
857
858
859    pub c_keep_alive_counter_value {
860        font-size: var!(font-base);
861        font-weight: "700";
862        font-variant-numeric: "tabular-nums";
863        color: var!(accent);
864        text-align: "center";
865    }
866
867
868    pub c_keep_alive_counter_controls {
869        display: "flex";
870        flex-wrap: "wrap";
871        gap: format!("{}", var!(space-md));
872    }
873
874
875    pub c_keep_alive_form_group {
876        margin-bottom: var!(gap-component);
877    }
878
879
880    pub c_keep_alive_form_preview {
881        margin-top: var!(gap-component);
882        background: var!(accent-muted);
883    }
884
885
886    pub c_keep_alive_preview_label {
887        font-size: var!(font-base);
888        font-weight: "600";
889        color: var!(accent);
890        margin: format!("0px 0px {} 0px", var!(space-xs));
891    }
892
893
894    // ═══════════════════════════════════════════════════════════════════════════
895    // Binding Demo
896    // ═══════════════════════════════════════════════════════════════════════════
897
898    pub c_binding_child_box {
899        display: "flex";
900        flex-direction: "column";
901        gap: var!(gap-component);
902        margin-top: var!(gap-component);
903    }
904
905
906    pub c_binding_child_label {
907        font-size: var!(font-base);
908        font-weight: "600";
909        color: var!(accent);
910        text-transform: "uppercase";
911        letter-spacing: "0.05em";
912    }
913
914
915    pub c_binding_parent_box {
916        display: "flex";
917        flex-direction: "column";
918        gap: var!(gap-component);
919        margin-top: var!(gap-component);
920    }
921
922
923    pub c_binding_section_title {
924        margin-top: var!(gap-component);
925        margin-bottom: var!(gap-element);
926        color: var!(accent);
927        font-size: var!(font-md);
928        font-weight: "600";
929    }
930
931
932    pub c_binding_temp_converter {
933        display: "flex";
934        align-items: "flex-end";
935        gap: var!(gap-component);
936        flex-wrap: "wrap";
937        margin-top: var!(gap-component);
938    }
939
940
941    pub c_binding_temp_field {
942        flex: "1";
943        min-width: "120px";
944    }
945
946
947    pub c_binding_temp_arrow {
948        font-size: "20px";
949        font-weight: "700";
950        color: var!(accent);
951        padding-bottom: "10px";
952    }
953
954
955    pub c_binding_color_mixer {
956        margin-top: var!(gap-component);
957    }
958
959
960    pub c_binding_color_preview {
961        width: "100%";
962        height: "80px";
963        display: "flex";
964        align-items: "center";
965        justify-content: "center";
966        margin-bottom: var!(gap-component);
967    }
968
969
970    pub c_binding_color_hex {
971        font-family: "ui-monospace, monospace";
972        font-size: var!(font-xl);
973        font-weight: "700";
974        color: var!(text-on-accent);
975        letter-spacing: "0.02em";
976    }
977
978
979    pub c_binding_slider_row {
980        display: "flex";
981        align-items: "center";
982        gap: format!("{}", var!(space-md));
983        margin-bottom: var!(space-sm);
984    }
985
986
987    pub c_binding_slider_label {
988        font-size: var!(font-base);
989        font-weight: "700";
990        min-width: var!(font-sm);
991    }
992
993
994    pub c_binding_slider {
995        flex: "1";
996        height: "24px";
997        padding: "0px";
998        cursor: "pointer";
999        -webkit-appearance: "none";
1000        appearance: "none";
1001        border: "none";
1002        outline: "none";
1003        ::-webkit-slider-runnable-track {
1004            height: "6px";
1005            background: format!("linear-gradient(to right, {} 0%, {} var(--value,50%), {} var(--value,50%), {} 100%)", var!(foreground), var!(foreground), var!(border), var!(border));
1006            border-radius: "3px";
1007            border: "none";
1008        }
1009        ::-webkit-slider-thumb {
1010            width: "20px";
1011            height: "20px";
1012            background: var!(background);
1013            border: format!("2px solid {}", var!(accent));
1014            border-radius: "50%";
1015            cursor: "pointer";
1016            -webkit-appearance: "none";
1017            margin-top: "-7px";
1018        }
1019        : active::-webkit-slider-thumb {
1020            transform: "scale(0.92)";
1021        }
1022        ::-moz-range-track {
1023            height: "6px";
1024            background: format!("linear-gradient(to right, {} 0%, {} var(--value,50%), {} var(--value,50%), {} 100%)", var!(foreground), var!(foreground), var!(border), var!(border));
1025            border-radius: "3px";
1026            border: "none";
1027        }
1028        ::-moz-range-thumb {
1029            width: "20px";
1030            height: "20px";
1031            background: var!(background);
1032            border: format!("2px solid {}", var!(accent));
1033            border-radius: "50%";
1034            cursor: "pointer";
1035        }
1036        : active::-moz-range-thumb {
1037            transform: "scale(0.92)";
1038        }
1039    }
1040
1041
1042    pub c_binding_slider_value {
1043        font-size: var!(font-base);
1044        font-weight: "500";
1045        color: "inherit";
1046        min-width: "32px";
1047        text-align: "right";
1048        font-family: "ui-monospace, monospace";
1049    }
1050
1051
1052    pub c_binding_typed_prop_value {
1053        font-family: "ui-monospace, monospace";
1054        font-size: var!(font-base);
1055        font-weight: "600";
1056        color: var!(accent);
1057        padding: format!("1px {}", var!(space-sm));
1058    }
1059
1060
1061    pub c_binding_typed_prop_group {
1062        display: "flex";
1063        align-items: "center";
1064        gap: var!(space-sm);
1065    }
1066
1067
1068    pub c_binding_typed_warning {
1069        font-size: var!(font-base);
1070        font-weight: "500";
1071        color: var!(foreground);
1072        margin-bottom: "0px";
1073    }
1074
1075
1076    pub c_binding_form_label {
1077        display: "block";
1078        color: "inherit";
1079        font-weight: "500";
1080        font-size: var!(font-base);
1081    }
1082
1083
1084    pub c_binding_demo_text {
1085        color: "inherit";
1086        margin: "0px"
1087    }
1088
1089
1090    pub c_binding_compact_button {
1091        display: "inline-flex";
1092        justify-content: "center";
1093        align-items: "center";
1094        height: "42px";
1095        padding: format!("0px {}", var!(space-md));
1096        background: var!(accent);
1097        color: var!(text-on-accent);
1098        border: format!("1px solid {}", var!(accent));
1099        cursor: "pointer";
1100        font-size: var!(font-sm);
1101        font-weight: "600";
1102        outline: "none";
1103        white-space: "nowrap";
1104        user-select: "none";
1105        -webkit-user-select: "none";
1106        box-sizing: "border-box";
1107        :hover {
1108            background: var!(accent);
1109        }
1110        :focus-visible {
1111            outline: "none";
1112        }
1113        :active {
1114            background: var!(accent);
1115            color: var!(text-on-accent);
1116            border-color: var!(accent);
1117        }
1118    }
1119
1120
1121    // ═══════════════════════════════════════════════════════════════════════════
1122    // Custom Attrs - Dynamic Style
1123    // ═══════════════════════════════════════════════════════════════════════════
1124
1125    pub c_attrs_dynamic_demo(prop_key: &str, prop_value: &str) {
1126        {
1127            prop_key
1128        }
1129        : prop_value;
1130        // No layout defaults: this class lives on a `<p>` whose own margin /
1131        // spacing is controlled by its parent's typography rules, and pinning
1132        // any colour here would shadow the user-supplied dynamic property.
1133        // Users are expected to set `color` / `background` / `font-*` /
1134        // etc. via the two CSS Property Key / Value inputs above; whatever
1135        // they type becomes the literal CSS rule applied to the paragraph.
1136    }
1137
1138
1139    // ═══════════════════════════════════════════════════════════════════════════
1140    // Dynamic Component Demo
1141    // ═══════════════════════════════════════════════════════════════════════════
1142
1143    pub c_dynamic_component_tab_bar {
1144        display: "flex";
1145        flex-wrap: "wrap";
1146        gap: var!(gap-element);
1147        margin-bottom: var!(gap-component);
1148    }
1149
1150
1151    pub c_dynamic_component_panel {
1152        display: "block";
1153        min-height: var!(min-height-sm);
1154        margin-top: var!(gap-component);
1155    }
1156
1157
1158    // ═══════════════════════════════════════════════════════════════════════════
1159    // Sticky & CSS Effects Demo
1160    // ═══════════════════════════════════════════════════════════════════════════
1161
1162    // ═══════════════════════════════════════════════════════════════════════════
1163    // Home Page — Section
1164    // ═══════════════════════════════════════════════════════════════════════════
1165
1166    pub c_home {
1167        position: "relative";
1168        text-align: "center";
1169        margin-bottom: var!(space-xl);
1170        flex: "1";
1171        display: "flex";
1172        flex-direction: "column";
1173        justify-content: "center";
1174        @media ((max-width: 767px)) {
1175            margin-bottom: var!(space-lg);
1176            flex: "0 0 auto";
1177            justify-content: "flex-start";
1178        }
1179    }
1180
1181
1182    pub c_home_content {
1183        position: "relative";
1184        z-index: "1";
1185    }
1186
1187
1188    pub c_home_badge_row {
1189        display: "inline-flex";
1190        align-items: "center";
1191        gap: var!(space-sm);
1192        margin-bottom: var!(space-md);
1193    }
1194
1195
1196    pub c_home_badge {
1197        display: "inline-flex";
1198        justify-content: "center";
1199        align-items: "center";
1200        padding: format!("{} {}", var!(space-xs), var!(space-sm));
1201        color: var!(accent);
1202        font-size: var!(font-xs);
1203        font-weight: "600";
1204        letter-spacing: "0.05em";
1205        border: format!("1px solid {}", var!(accent));
1206    }
1207
1208
1209    pub c_home_title {
1210        font-size: var!(font-5xl);
1211        font-weight: "800";
1212        letter-spacing: "-0.03em";
1213        margin: "0px";
1214        color: var!(foreground);
1215        margin-bottom: var!(space-xs);
1216        @media ((max-width: 767px)) {
1217            font-size: var!(font-4xl);
1218        }
1219    }
1220
1221
1222    pub c_home_subtitle {
1223        font-size: var!(font-lg);
1224        color: var!(foreground);
1225        margin: "0px auto";
1226        max-width: "520px";
1227        margin-bottom: var!(space-lg);
1228        @media ((max-width: 767px)) {
1229            font-size: var!(font-base);
1230        }
1231    }
1232
1233
1234    pub c_home_actions {
1235        display: "flex";
1236        gap: var!(space-md);
1237        justify-content: "center";
1238        flex-wrap: "wrap";
1239    }
1240
1241
1242    pub c_home_btn_primary {
1243        display: "inline-flex";
1244        justify-content: "center";
1245        align-items: "center";
1246        gap: var!(space-sm);
1247        padding: format!("{} {}", var!(space-sm), var!(space-2xl));
1248        background: var!(accent);
1249        color: var!(text-on-accent);
1250        font-size: var!(font-base);
1251        font-weight: "600";
1252        text-decoration: "none";
1253        border: "1.5px solid transparent";
1254        cursor: "pointer";
1255        letter-spacing: "0.01em";
1256        vertical-align: "middle";
1257        min-height: var!(min-height-sm);
1258        :focus-visible {
1259            outline: "none";
1260        }
1261        :active {
1262            background: var!(accent);
1263            color: var!(text-on-accent);
1264            border-color: "1.5px solid transparent";
1265        }
1266    }
1267
1268
1269    pub c_home_btn_secondary {
1270        display: "inline-flex";
1271        justify-content: "center";
1272        align-items: "center";
1273        gap: var!(space-sm);
1274        padding: format!("{} {}", var!(space-sm), var!(space-2xl));
1275        color: var!(accent);
1276        font-size: var!(font-base);
1277        font-weight: "600";
1278        text-decoration: "none";
1279        border: format!("1.5px solid {}", var!(accent));
1280        cursor: "pointer";
1281        letter-spacing: "0.01em";
1282        vertical-align: "middle";
1283        min-height: var!(min-height-sm);
1284        :focus-visible {
1285            outline: "none";
1286        }
1287        :active {
1288            background: "transparent";
1289            color: var!(accent);
1290            border-color: var!(accent);
1291        }
1292    }
1293
1294
1295    // ═══════════════════════════════════════════════════════════════════════════
1296    // Home Page — Stats Row
1297    // ═══════════════════════════════════════════════════════════════════════════
1298
1299    pub c_home_stats {
1300        display: "grid";
1301        grid-template-columns: "repeat(4, 1fr)";
1302        gap: var!(space-md);
1303        margin-bottom: var!(space-xl);
1304        @media ((max-width: 767px)) {
1305            grid-template-columns: "repeat(2, 1fr)";
1306            gap: var!(space-sm);
1307        }
1308    }
1309
1310
1311    pub c_home_stat_card {
1312        display: "flex";
1313        flex-direction: "column";
1314        align-items: "center";
1315        justify-content: "center";
1316        gap: var!(space-xs);
1317    }
1318
1319
1320    pub c_home_stat_icon {
1321        font-size: var!(font-2xl);
1322    }
1323
1324
1325    pub c_home_stat_value {
1326        font-size: var!(font-xl);
1327        font-weight: "800";
1328        color: var!(foreground);
1329        letter-spacing: "-0.01em";
1330    }
1331
1332
1333    pub c_home_stat_label {
1334        font-size: var!(font-sm);
1335        color: var!(muted-foreground);
1336        font-weight: "500";
1337    }
1338
1339
1340    // ═══════════════════════════════════════════════════════════════════════════
1341    // Home Page — Section & Feature Cards
1342    // ═══════════════════════════════════════════════════════════════════════════
1343
1344    pub c_home_section_title {
1345        font-size: var!(font-2xl);
1346        font-weight: "700";
1347        color: var!(foreground);
1348        margin: "0px";
1349        margin: format!("{} 0px", var!(gap-component));
1350        letter-spacing: "-0.02em";
1351    }
1352
1353
1354    pub c_home_section_desc {
1355        font-size: var!(font-base);
1356        color: var!(foreground);
1357        margin: "0px";
1358        margin-bottom: var!(space-2xl);
1359    }
1360
1361
1362    pub c_home_feature_grid {
1363        display: "grid";
1364        grid-template-columns: "repeat(2, 1fr)";
1365        gap: var!(space-md);
1366        @media ((max-width: 767px)) {
1367            grid-template-columns: "1fr";
1368        }
1369    }
1370
1371
1372    pub c_feature_card {
1373        display: "flex";
1374        flex-direction: "column";
1375        gap: var!(space-sm);
1376        padding: "0px";
1377        overflow: "hidden";
1378    }
1379
1380
1381    pub c_feature_header {
1382        display: "flex";
1383        align-items: "center";
1384        gap: var!(space-sm);
1385    }
1386
1387
1388    pub c_feature_icon {
1389        font-size: var!(font-2xl);
1390        display: "flex";
1391        align-items: "center";
1392        justify-content: "center";
1393        line-height: "1";
1394        flex-shrink: "0";
1395    }
1396
1397
1398    pub c_feature_name {
1399        font-size: var!(font-lg);
1400        font-weight: "600";
1401        color: var!(foreground);
1402        margin: "0px";
1403        overflow: "hidden";
1404        text-overflow: "ellipsis";
1405        white-space: "nowrap";
1406    }
1407
1408
1409    pub c_feature_desc {
1410        font-size: var!(font-sm);
1411        color: var!(foreground);
1412        margin: "0px";
1413    }
1414
1415    // ═══════════════════════════════════════════════════════════════════════════
1416    // Home Page
1417    // ═══════════════════════════════════════════════════════════════════════════
1418
1419    pub(crate) c_text_ellipsis {
1420        overflow: "hidden";
1421        text-overflow: "ellipsis";
1422        white-space: "nowrap";
1423    }
1424
1425    pub c_info_row {
1426        display: "flex";
1427        align-items: "center";
1428        gap: var!(space-md);
1429        padding: format!("{} 0", var!(space-sm));
1430        overflow: "hidden";
1431    }
1432
1433    pub c_info_label {
1434        font-size: var!(font-sm);
1435        font-weight: "500";
1436        color: var!(muted-foreground);
1437        min-width: "72px";
1438        flex-shrink: "0";
1439        letter-spacing: "0.02em";
1440    }
1441
1442    pub c_info_value {
1443        c_text_ellipsis();
1444        font-size: var!(font-base);
1445        font-weight: "600";
1446        color: var!(foreground);
1447        font-family: "ui-monospace, monospace";
1448        flex: "1";
1449    }
1450
1451    pub c_info_link {
1452        c_text_ellipsis();
1453        font-size: var!(font-base);
1454        font-weight: "600";
1455        color: var!(accent);
1456        font-family: "ui-monospace, monospace";
1457        flex: "1";
1458        text-decoration: "none";
1459        transition: format!("opacity {} {}", var!(duration-fast), var!(ease-out));
1460        :hover {
1461            opacity: "1";
1462        }
1463    }
1464
1465    // ═══════════════════════════════════════════════════════════════════════════
1466    // Async / Loading States
1467    // ═══════════════════════════════════════════════════════════════════════════
1468
1469    pub(crate) c_loading_container {
1470        display: "flex";
1471        align-items: "center";
1472        justify-content: "center";
1473        gap: var!(gap-component);
1474        margin: format!("{} 0px", var!(gap-component));
1475        box-sizing: "border-box";
1476    }
1477
1478    pub c_spinner {
1479        width: "28px";
1480        height: "28px";
1481        border: format!("3px solid {}", var!(accent-muted));
1482        border-top: format!("3px solid {}", var!(accent));
1483        border-radius: "50%";
1484        flex-shrink: "0";
1485        animation: "euv-spin 0.8s linear infinite";
1486    }
1487
1488    pub(crate) c_loading_text_col {
1489        display: "flex";
1490        flex-direction: "column";
1491        gap: var!(space-xs);
1492    }
1493
1494    pub(crate) c_loading_title {
1495        color: var!(foreground);
1496        font-size: var!(font-md);
1497        font-weight: "500";
1498    }
1499
1500    pub(crate) c_loading_subtitle {
1501        color: var!(muted-foreground);
1502        font-size: var!(font-base);
1503    }
1504
1505    pub c_loading_overlay(background: &str) {
1506        position: "absolute";
1507        top: "0";
1508        left: "0";
1509        width: "100%";
1510        height: "100%";
1511        display: "flex";
1512        flex-direction: "column";
1513        align-items: "center";
1514        justify-content: "center";
1515        gap: var!(gap-component);
1516        background: background;
1517        z-index: "1";
1518        box-sizing: "border-box";
1519    }
1520
1521    pub c_error_container {
1522        display: "flex";
1523        align-items: "center";
1524        gap: var!(gap-element);
1525        margin-top: var!(gap-component);
1526        box-sizing: "border-box";
1527    }
1528
1529    pub c_error_icon {
1530        width: "20px";
1531        height: "20px";
1532        display: "flex";
1533        align-items: "center";
1534        justify-content: "center";
1535        flex-shrink: "0";
1536        color: var!(foreground);
1537        font-size: var!(font-sm);
1538        font-weight: "700";
1539    }
1540
1541    pub c_error_text {
1542        color: var!(foreground);
1543        font-size: var!(font-base);
1544    }
1545
1546    pub c_data_box {
1547        margin: format!("{} 0px", var!(gap-component));
1548        box-sizing: "border-box";
1549    }
1550
1551    pub c_data_pre {
1552        color: var!(foreground);
1553        font-size: var!(font-base);
1554        margin: "0px";
1555        white-space: "pre-wrap";
1556        word-break: "break-all";
1557        font-family: "ui-monospace, monospace";
1558    }
1559
1560    pub c_fetch_hint {
1561        color: "inherit";
1562        opacity: "1";
1563        font-size: var!(font-base);
1564        margin-bottom: var!(gap-component);
1565    }
1566
1567    // ═══════════════════════════════════════════════════════════════════════════
1568    // Log / Console Display
1569    // ═══════════════════════════════════════════════════════════════════════════
1570
1571    pub c_log_container {
1572        font-family: "ui-monospace, monospace";
1573        font-size: var!(font-base);
1574        margin-top: "0px";
1575        color: var!(foreground);
1576    }
1577
1578    pub c_log_item {
1579        padding: format!("{} 0px", var!(space-sm));
1580        font-size: var!(font-base);
1581        color: var!(foreground);
1582    }
1583}