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    }
1118
1119    pub c_home_btn_primary {
1120        display: "inline-flex";
1121        justify-content: "center";
1122        align-items: "center";
1123        gap: var!(space-sm);
1124        padding: format!("{} {}", var!(space-sm), var!(space-2xl));
1125        background: var!(accent);
1126        color: var!(text-on-accent);
1127        font-size: var!(font-base);
1128        font-weight: "600";
1129        text-decoration: "none";
1130        border: "1.5px solid transparent";
1131        cursor: "pointer";
1132        letter-spacing: "0.01em";
1133        vertical-align: "middle";
1134        min-height: var!(min-height-sm);
1135        :focus-visible {
1136            outline: "none";
1137        }
1138        :active {
1139            background: var!(accent);
1140            color: var!(text-on-accent);
1141            border-color: "1.5px solid transparent";
1142        }
1143    }
1144
1145    pub c_home_btn_secondary {
1146        display: "inline-flex";
1147        justify-content: "center";
1148        align-items: "center";
1149        gap: var!(space-sm);
1150        padding: format!("{} {}", var!(space-sm), var!(space-2xl));
1151        color: var!(accent);
1152        font-size: var!(font-base);
1153        font-weight: "600";
1154        text-decoration: "none";
1155        border: format!("1.5px solid {}", var!(accent));
1156        cursor: "pointer";
1157        letter-spacing: "0.01em";
1158        vertical-align: "middle";
1159        min-height: var!(min-height-sm);
1160        :focus-visible {
1161            outline: "none";
1162        }
1163        :active {
1164            background: "transparent";
1165            color: var!(accent);
1166            border-color: var!(accent);
1167        }
1168    }
1169
1170    // ═══════════════════════════════════════════════════════════════════════════
1171    // Home Page — Stats Row
1172    // ═══════════════════════════════════════════════════════════════════════════
1173
1174    pub c_home_stats {
1175        display: "grid";
1176        grid-template-columns: "repeat(4, 1fr)";
1177        gap: var!(space-md);
1178        margin-bottom: var!(space-xl);
1179        @media ((max-width: 767px)) {
1180            grid-template-columns: "repeat(2, 1fr)";
1181            gap: var!(space-sm);
1182        }
1183    }
1184
1185    pub c_home_stat_card {
1186        display: "flex";
1187        flex-direction: "column";
1188        align-items: "center";
1189        justify-content: "center";
1190        gap: var!(space-xs);
1191    }
1192
1193    pub c_home_stat_icon {
1194        font-size: var!(font-2xl);
1195    }
1196
1197    pub c_home_stat_value {
1198        font-size: var!(font-xl);
1199        font-weight: "800";
1200        color: var!(foreground);
1201        letter-spacing: "-0.01em";
1202    }
1203
1204    pub c_home_stat_label {
1205        font-size: var!(font-sm);
1206        color: var!(muted-foreground);
1207        font-weight: "500";
1208    }
1209
1210    // ═══════════════════════════════════════════════════════════════════════════
1211    // Home Page — Section & Feature Cards
1212    // ═══════════════════════════════════════════════════════════════════════════
1213
1214    pub c_home_section_title {
1215        font-size: var!(font-2xl);
1216        font-weight: "700";
1217        color: var!(foreground);
1218        margin: "0px";
1219        margin: format!("{} 0px", var!(gap-component));
1220        letter-spacing: "-0.02em";
1221    }
1222
1223    pub c_home_section_desc {
1224        font-size: var!(font-base);
1225        color: var!(foreground);
1226        margin: "0px";
1227        margin-bottom: var!(space-2xl);
1228    }
1229
1230    pub c_home_feature_grid {
1231        display: "grid";
1232        grid-template-columns: "repeat(2, 1fr)";
1233        gap: var!(space-md);
1234        @media ((max-width: 767px)) {
1235            grid-template-columns: "1fr";
1236        }
1237    }
1238
1239    pub c_feature_card {
1240        display: "flex";
1241        flex-direction: "column";
1242        gap: var!(space-sm);
1243        padding: "0px";
1244        overflow: "hidden";
1245    }
1246
1247    pub c_feature_header {
1248        display: "flex";
1249        align-items: "center";
1250        gap: var!(space-sm);
1251    }
1252
1253    pub c_feature_icon {
1254        font-size: var!(font-2xl);
1255        display: "flex";
1256        align-items: "center";
1257        justify-content: "center";
1258        line-height: "1";
1259        flex-shrink: "0";
1260    }
1261
1262    pub c_feature_name {
1263        font-size: var!(font-lg);
1264        font-weight: "600";
1265        color: var!(foreground);
1266        margin: "0px";
1267        overflow: "hidden";
1268        text-overflow: "ellipsis";
1269        white-space: "nowrap";
1270    }
1271
1272    pub c_feature_desc {
1273        font-size: var!(font-sm);
1274        color: var!(foreground);
1275        margin: "0px";
1276    }
1277
1278    // ═══════════════════════════════════════════════════════════════════════════
1279    // Home Page
1280    // ═══════════════════════════════════════════════════════════════════════════
1281
1282    pub(crate) c_text_ellipsis {
1283        overflow: "hidden";
1284        text-overflow: "ellipsis";
1285        white-space: "nowrap";
1286    }
1287
1288    pub c_info_row {
1289        display: "flex";
1290        align-items: "center";
1291        gap: var!(space-md);
1292        padding: format!("{} 0", var!(space-sm));
1293        overflow: "hidden";
1294    }
1295
1296    pub c_info_label {
1297        font-size: var!(font-sm);
1298        font-weight: "500";
1299        color: var!(muted-foreground);
1300        min-width: "72px";
1301        flex-shrink: "0";
1302        letter-spacing: "0.02em";
1303    }
1304
1305    pub c_info_value {
1306        c_text_ellipsis();
1307        font-size: var!(font-base);
1308        font-weight: "600";
1309        color: var!(foreground);
1310        font-family: "ui-monospace, monospace";
1311        flex: "1";
1312    }
1313
1314    pub c_info_link {
1315        c_text_ellipsis();
1316        font-size: var!(font-base);
1317        font-weight: "600";
1318        color: var!(accent);
1319        font-family: "ui-monospace, monospace";
1320        flex: "1";
1321        text-decoration: "none";
1322        transition: format!("opacity {} {}", var!(duration-fast), var!(ease-out));
1323        :hover {
1324            opacity: "1";
1325        }
1326    }
1327
1328    // ═══════════════════════════════════════════════════════════════════════════
1329    // Async / Loading States
1330    // ═══════════════════════════════════════════════════════════════════════════
1331
1332    pub(crate) c_loading_container {
1333        display: "flex";
1334        align-items: "center";
1335        justify-content: "center";
1336        gap: var!(gap-component);
1337        margin: format!("{} 0px", var!(gap-component));
1338        box-sizing: "border-box";
1339    }
1340
1341    pub c_spinner {
1342        width: "28px";
1343        height: "28px";
1344        border: format!("3px solid {}", var!(accent-muted));
1345        border-top: format!("3px solid {}", var!(accent));
1346        border-radius: "50%";
1347        flex-shrink: "0";
1348        animation: "euv-spin 0.8s linear infinite";
1349    }
1350
1351    pub(crate) c_loading_text_col {
1352        display: "flex";
1353        flex-direction: "column";
1354        gap: var!(space-xs);
1355    }
1356
1357    pub(crate) c_loading_title {
1358        color: var!(foreground);
1359        font-size: var!(font-md);
1360        font-weight: "500";
1361    }
1362
1363    pub(crate) c_loading_subtitle {
1364        color: var!(muted-foreground);
1365        font-size: var!(font-base);
1366    }
1367
1368    pub c_loading_overlay(background: &str) {
1369        position: "absolute";
1370        top: "0";
1371        left: "0";
1372        width: "100%";
1373        height: "100%";
1374        display: "flex";
1375        flex-direction: "column";
1376        align-items: "center";
1377        justify-content: "center";
1378        gap: var!(gap-component);
1379        background: background;
1380        z-index: "1";
1381        box-sizing: "border-box";
1382    }
1383
1384    pub c_error_container {
1385        display: "flex";
1386        align-items: "center";
1387        gap: var!(gap-element);
1388        margin-top: var!(gap-component);
1389        box-sizing: "border-box";
1390    }
1391
1392    pub c_error_icon {
1393        width: "20px";
1394        height: "20px";
1395        display: "flex";
1396        align-items: "center";
1397        justify-content: "center";
1398        flex-shrink: "0";
1399        color: var!(foreground);
1400        font-size: var!(font-sm);
1401        font-weight: "700";
1402    }
1403
1404    pub c_error_text {
1405        color: var!(foreground);
1406        font-size: var!(font-base);
1407    }
1408
1409    pub c_data_box {
1410        margin: format!("{} 0px", var!(gap-component));
1411        box-sizing: "border-box";
1412    }
1413
1414    pub c_data_pre {
1415        color: var!(foreground);
1416        font-size: var!(font-base);
1417        margin: "0px";
1418        white-space: "pre-wrap";
1419        word-break: "break-all";
1420        font-family: "ui-monospace, monospace";
1421    }
1422
1423    pub c_fetch_hint {
1424        color: "inherit";
1425        opacity: "1";
1426        font-size: var!(font-base);
1427        margin-bottom: var!(gap-component);
1428    }
1429
1430    // ═══════════════════════════════════════════════════════════════════════════
1431    // Log / Console Display
1432    // ═══════════════════════════════════════════════════════════════════════════
1433
1434    pub c_log_container {
1435        font-family: "ui-monospace, monospace";
1436        font-size: var!(font-base);
1437        margin-top: "0px";
1438        color: var!(foreground);
1439    }
1440
1441    pub c_log_item {
1442        padding: format!("{} 0px", var!(space-sm));
1443        font-size: var!(font-base);
1444        color: var!(foreground);
1445    }
1446}