Skip to main content

euv_ui/style/class/page/
fn.rs

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