Skip to main content

euv_ui/style/class/page/
fn.rs

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