Skip to main content

euv_ui/style/class/page/
fn.rs

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