Skip to main content

euv_ui/style/class/
fn.rs

1use super::*;
2
3class! {
4    // ═══════════════════════════════════════════════════════════════════════════
5    // Layout Shell
6    // ═══════════════════════════════════════════════════════════════════════════
7
8    pub c_app_root {
9        display: "flex";
10        height: "100%";
11        padding-bottom: var!(safe-area-inset-bottom);
12        font-family: "system-ui, -apple-system, sans-serif";
13        background: var!(background);
14        color: var!(foreground);
15        user-select: "none";
16        -webkit-user-select: "none";
17        -webkit-font-smoothing: "antialiased";
18        -moz-osx-font-smoothing: "grayscale";
19        text-rendering: "optimizeLegibility";
20        scrollbar-color: format!("{} {}", var!(scrollbar-thumb), var!(scrollbar-track));
21        ::-webkit-scrollbar-thumb {
22            background: var!(scrollbar-thumb);
23            border: "none";
24            border-radius: "0px";
25        }
26        ::-webkit-scrollbar-thumb:hover {
27            background: var!(scrollbar-thumb-hover);
28        }
29        ::-webkit-scrollbar-thumb:active {
30            background: var!(scrollbar-thumb-active);
31        }
32
33        // ═══════════════════════════════════════════════════════════════════════════
34        // CSS Reset — Cross-browser normalization
35        // ═══════════════════════════════════════════════════════════════════════════
36
37        *, *::before, *::after {
38            box-sizing: "border-box";
39        }
40        h1, h2, h3, h4, h5, h6, p, ul, ol, dl, dd, figure, blockquote, pre, hr {
41            margin: "0px";
42            padding: "0px";
43        }
44        ul, ol {
45            list-style: "none";
46            padding: "0px";
47            margin: "0px";
48        }
49        a {
50            color: "inherit";
51            text-decoration: "none";
52        }
53        button {
54            appearance: "none";
55            -webkit-appearance: "none";
56            -moz-appearance: "none";
57            background: "transparent";
58            border: "none";
59            padding: "0px";
60            margin: "0px";
61            font: "inherit";
62            color: "inherit";
63            cursor: "pointer";
64            outline: "none";
65            font-family: "inherit";
66            ::-moz-focus-inner {
67                border: "0px";
68                padding: "0px";
69            }
70        }
71        input, textarea, select, button {
72            font: "inherit";
73            font-family: "inherit";
74            font-size: "inherit";
75            line-height: "normal";
76            margin: "0px";
77            padding: "0px";
78            border: "none";
79            outline: "none";
80            background: "transparent";
81            color: "inherit";
82            appearance: "none";
83            -webkit-appearance: "none";
84            -moz-appearance: "none";
85        }
86        input[type="text"], input[type="number"], input[type="email"], input[type="password"], input[type="search"], input[type="tel"], input[type="url"] {
87            appearance: "none";
88            -webkit-appearance: "none";
89            -moz-appearance: "none";
90            border-radius: "0px";
91        }
92        input[type="search"]::-webkit-search-cancel-button, input[type="search"]::-webkit-search-decoration {
93            -webkit-appearance: "none";
94            appearance: "none";
95        }
96        input[type="number"] {
97            -moz-appearance: "textfield";
98        }
99        input[type="number"]::-webkit-outer-spin-button, input[type="number"]::-webkit-inner-spin-button {
100            -webkit-appearance: "none";
101            appearance: "none";
102            margin: "0px";
103        }
104        textarea {
105            appearance: "none";
106            -webkit-appearance: "none";
107            -moz-appearance: "none";
108            resize: "vertical";
109            font-family: "inherit";
110        }
111        select {
112            appearance: "none";
113            -webkit-appearance: "none";
114            -moz-appearance: "none";
115            background-image: "none";
116            border-radius: "0px";
117        }
118        img, svg, video, canvas, audio, iframe, embed, object {
119            display: "block";
120            max-width: "100%";
121        }
122        table {
123            border-collapse: "collapse";
124            border-spacing: "0px";
125        }
126        hr {
127            border: "none";
128            margin: "0px";
129        }
130        :focus-visible {
131            outline: "none";
132        }
133        : focus:not(: focus-visible) {
134            outline: "none";
135        }
136        h1, h2, h3, h4, h5, h6 {
137            font-weight: "inherit";
138            font-size: "inherit";
139        }
140        strong, b {
141            font-weight: "700";
142        }
143        em, i {
144            font-style: "italic";
145        }
146        code, pre, kbd, samp {
147            font-family: "ui-monospace, monospace";
148        }
149        @media ((max-width: 767px)) {
150            input, select, textarea {
151                font-size: "16px";
152            }
153        }
154    }
155
156    pub c_mobile_app_root {
157        display: "flex";
158        flex-direction: "column";
159        width: "100%";
160        height: "100%";
161        font-family: "system-ui, -apple-system, sans-serif";
162        background: var!(background);
163        color: var!(foreground);
164        padding: format!("0px {} {} {}", var!(safe-area-inset-right), var!(padding-shell-bottom), var!(safe-area-inset-left));
165        scrollbar-color: format!("{} {}", var!(scrollbar-thumb), var!(scrollbar-track));
166        ::-webkit-scrollbar-thumb {
167            background: var!(scrollbar-thumb);
168            border: "none";
169            border-radius: "0px";
170        }
171        ::-webkit-scrollbar-thumb:hover {
172            background: var!(scrollbar-thumb-hover);
173        }
174        ::-webkit-scrollbar-thumb:active {
175            background: var!(scrollbar-thumb-active);
176        }
177    }
178
179    // ═══════════════════════════════════════════════════════════════════════════
180    // Navigation - Desktop Sidebar
181    // ═══════════════════════════════════════════════════════════════════════════
182
183    pub c_app_nav {
184        // Adaptive sidebar width — `clamp()` keeps the column ≥ the historic
185        // 248px floor (no regression on dense sidebar trees) and ≤ 320px on
186        // roomy viewports, so longer English titles like "Internationalization"
187        // stop wrapping at the historic fixed 248px.
188        width: var!(nav-width);
189        background: var!(background);
190        border-left: format!("2px solid {}", var!(border));
191        display: "flex";
192        flex-direction: "column";
193        // Pin the sidebar to the viewport while the main column scrolls.
194        // Without this the whole row flex container scrolls as a single
195        // block and the nav appears to slide off-screen with the content.
196        // `align-self: stretch` (the row flex default) is overridden by
197        // `flex-start` so the sticky height is the natural 100vh and not
198        // stretched to match the (much taller) main column.
199        position: "sticky";
200        top: "0px";
201        align-self: "flex-start";
202        height: "100vh";
203        flex-shrink: "0";
204        padding-top: var!(safe-area-inset-top);
205        @media ((max-width: 767px)) {
206            display: "none";
207        }
208    }
209
210    pub c_nav_header {
211        padding: format!("{} {}", var!(space-xl), var!(edge-gutter-nav));
212        @media ((max-width: 767px)) {
213            padding: format!("{} {}", var!(space-xl), var!(edge-gutter-mobile));
214        }
215        width: "100%";
216        box-sizing: "border-box";
217        font-size: var!(font-xl);
218        font-weight: "700";
219        color: var!(foreground);
220        letter-spacing: "-0.02em";
221        display: "flex";
222        align-items: "center";
223        gap: format!("{}", var!(space-md));
224        flex-shrink: "0";
225        text-decoration: "none";
226        cursor: "pointer";
227        position: "relative";
228        ::after {
229            content: "''";
230            position: "absolute";
231            bottom: "0px";
232            left: var!(edge-gutter-nav);
233            right: var!(edge-gutter-nav);
234            height: "1px";
235            background: format!("linear-gradient(90deg, transparent, {}, transparent)", var!(border));
236        }
237        @media ((max-width: 767px)) {
238            ::after {
239                left: var!(edge-gutter-mobile);
240                right: var!(edge-gutter-mobile);
241            }
242        }
243    }
244
245    pub c_nav_brand_title {
246        font-size: var!(font-xl);
247        font-weight: "700";
248        color: var!(foreground);
249        letter-spacing: "-0.02em";
250    }
251
252    pub c_euv_logo {
253        display: "flex";
254        background: var!(accent);
255        align-items: "center";
256        justify-content: "center";
257        color: var!(text-on-accent);
258        font-weight: "700";
259        border: "none";
260        cursor: "pointer";
261        padding: "0px";
262        flex-shrink: "0";
263        position: "relative";
264    }
265
266    pub c_euv_logo_nav {
267        width: "32px";
268        height: "32px";
269        font-size: var!(font-lg);
270    }
271
272    pub c_euv_logo_fab {
273        width: "36px";
274        height: "36px";
275        font-size: var!(font-xl);
276        @media ((max-width: 767px)) {
277            width: "44px";
278            height: "44px";
279        }
280    }
281
282    pub c_nav_section_label {
283        padding: format!("{} {} {} {}", var!(space-md), var!(edge-gutter-nav), var!(space-xs), var!(edge-gutter-nav));
284        @media ((max-width: 767px)) {
285            padding: format!("{} {} {} {}", var!(space-md), var!(edge-gutter-mobile), var!(space-xs), var!(edge-gutter-mobile));
286        }
287        margin: "0px";
288        font-size: var!(font-xs);
289        font-weight: "700";
290        color: var!(foreground);
291        text-transform: "uppercase";
292        letter-spacing: "0.10em";
293        flex-shrink: "0";
294    }
295
296    pub c_nav_items_scroll {
297        flex: "1";
298        overflow-y: "auto";
299        contain: "content";
300        scrollbar-color: format!("{} {}", var!(scrollbar-thumb), var!(scrollbar-track));
301        ::-webkit-scrollbar-thumb {
302            background: var!(scrollbar-thumb);
303            border: "none";
304            border-radius: "0px";
305        }
306        ::-webkit-scrollbar-thumb:hover {
307            background: var!(scrollbar-thumb-hover);
308        }
309        ::-webkit-scrollbar-thumb:active {
310            background: var!(scrollbar-thumb-active);
311        }
312    }
313
314    pub c_nav_theme_toggle {
315        padding: format!("{} {}", var!(space-md), var!(edge-gutter-nav));
316        flex-shrink: "0";
317        margin-top: "auto";
318        @media ((max-width: 767px)) {
319            display: "none";
320        }
321    }
322
323    // Optional row in the nav column / drawer for locale switchers or similar
324    // widgets, placed between the brand header and the section label.
325    pub c_nav_locale_row {
326        padding: format!("{} {}", var!(space-md), var!(edge-gutter-nav));
327        @media ((max-width: 767px)) {
328            padding: format!("{} {}", var!(space-md), var!(edge-gutter-mobile));
329        }
330        flex-shrink: "0";
331    }
332
333    pub c_nav_locale_button {
334        width: "100%";
335        height: "36px";
336        padding: "0px";
337        cursor: "pointer";
338        outline: "none";
339        border: format!("1px dashed {}", var!(border));
340        background: "transparent";
341        color: var!(foreground);
342        display: "flex";
343        align-items: "center";
344        justify-content: "center";
345        // The trigger mirrors the sidebar's hover affordance: the dashed
346        // border thickens to the foreground colour and a translucent wash
347        // derived from the text colour appears behind the label. The wash is
348        // `color-mix` on `foreground` rather than `accent-muted`, because in
349        // the monochrome palette `accent-muted` resolves to the same value as
350        // `background` (white on light, black on dark) and would be invisible.
351        :hover {
352            border-color: var!(foreground);
353            background: format!("color-mix(in srgb, {} 8%, transparent)", var!(foreground));
354        }
355        :focus-visible {
356            outline: "none";
357        }
358        // `:active` must not reset the hover styles: it only fires while the
359        // pointer is held, and zeroing the background there is what made the
360        // click look like nothing happened.
361        :active {
362            border-color: var!(foreground);
363            background: format!("color-mix(in srgb, {} 12%, transparent)", var!(foreground));
364        }
365    }
366
367    // Open state of the locale switcher: the same solid treatment the sidebar
368    // gives its current page, so "menu is open" reads as strongly as
369    // "this is the page you are on".
370    pub c_nav_locale_button_open {
371        width: "100%";
372        height: "36px";
373        padding: "0px";
374        cursor: "pointer";
375        outline: "none";
376        border: format!("1px solid {}", var!(accent));
377        display: "flex";
378        align-items: "center";
379        justify-content: "center";
380        // Background and text colour are a matched pair: the fill is the
381        // accent, so the label must be the colour that reads on top of it.
382        // Setting one without the other is what produces invisible text.
383        background: var!(accent);
384        color: var!(text-on-accent);
385        :hover {
386            background: var!(accent);
387            color: var!(text-on-accent);
388            border-color: var!(accent);
389        }
390        :focus-visible {
391            outline: "none";
392        }
393        :active {
394            background: var!(accent);
395            color: var!(text-on-accent);
396            border-color: var!(accent);
397        }
398    }
399
400    pub c_nav_theme_button {
401        width: "100%";
402        height: "36px";
403        padding: "0px";
404        cursor: "pointer";
405        outline: "none";
406        border: format!("1px dashed {}", var!(border));
407        display: "flex";
408        align-items: "center";
409        justify-content: "center";
410        :focus-visible {
411            outline: "none";
412        }
413        :active {
414            background: "transparent";
415            border-color: var!(border);
416        }
417    }
418
419    pub c_theme_icon_sun {
420        width: "20px";
421        height: "20px";
422        background-repeat: "no-repeat";
423        background-position: "center";
424        background-size: "20px 20px";
425        background-image: "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='%23ffffff' stroke='%23ffffff' stroke-width='1.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='5'/%3E%3Cline x1='12' y1='1' x2='12' y2='4'/%3E%3Cline x1='12' y1='20' x2='12' y2='23'/%3E%3Cline x1='4.22' y1='4.22' x2='6.34' y2='6.34'/%3E%3Cline x1='17.66' y1='17.66' x2='19.78' y2='19.78'/%3E%3Cline x1='1' y1='12' x2='4' y2='12'/%3E%3Cline x1='20' y1='12' x2='23' y2='12'/%3E%3Cline x1='4.22' y1='19.78' x2='6.34' y2='17.66'/%3E%3Cline x1='17.66' y1='6.34' x2='19.78' y2='4.22'/%3E%3C/svg%3E\")";
426        transition: format!("transform {} {}", var!(duration-normal), var!(ease-out));
427    }
428
429    pub c_theme_icon_moon {
430        width: "20px";
431        height: "20px";
432        background-repeat: "no-repeat";
433        background-position: "center";
434        background-size: "20px 20px";
435        background-image: "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='20' height='20' viewBox='0 0 24 24' fill='%23000000' stroke='none' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M21 13A9 9 0 1 1 11 3a7 7 0 0 0 10 10z'/%3E%3C/svg%3E\")";
436        transition: format!("transform {} {}", var!(duration-normal), var!(ease-out));
437    }
438
439    pub c_nav_footer {
440        padding: format!("{} {}", var!(space-lg), var!(edge-gutter-nav));
441        @media ((max-width: 767px)) {
442            padding: format!("{} {}", var!(space-lg), var!(edge-gutter-mobile));
443        }
444        position: "relative";
445        font-size: var!(font-xs);
446        color: var!(muted-foreground);
447        flex-shrink: "0";
448        text-decoration: "none";
449        display: "flex";
450        align-items: "center";
451        // Center the "Built with X" attribution line inside the sidebar so
452        // it visually balances with the centered brand header above and the
453        // centered theme toggle divider. `justify-content: center` works
454        // here because the link itself is a single row of inline text —
455        // when it wraps to multiple lines on narrow sidebars the lines stay
456        // grouped because `flex-direction` is the default `row`.
457        justify-content: "center";
458        gap: var!(space-xs);
459        cursor: "pointer";
460        text-align: "center";
461        transition: format!("opacity {} {}", var!(duration-fast), var!(ease-out));
462        opacity: "1";
463        :hover {
464            opacity: "1";
465        }
466    }
467
468    pub c_nav_footer_divider {
469        position: "absolute";
470        top: "0";
471        left: var!(edge-gutter-nav);
472        right: var!(edge-gutter-nav);
473        height: "1px";
474        background: format!("linear-gradient(90deg, transparent, {}, transparent)", var!(border));
475        @media ((max-width: 767px)) {
476            left: var!(edge-gutter-mobile);
477            right: var!(edge-gutter-mobile);
478        }
479    }
480
481    pub c_nav_footer_text {
482        font-weight: "400";
483        letter-spacing: "0.02em";
484    }
485
486    pub c_nav_footer_brand {
487        font-weight: "700";
488        color: var!(accent);
489    }
490
491    pub c_nav_item_active {
492        display: "flex";
493        align-items: "center";
494        gap: var!(space-sm);
495        padding: format!("{} {}", var!(space-md), var!(edge-gutter-nav));
496        @media ((max-width: 767px)) {
497            padding: format!("{} {}", var!(space-md), var!(edge-gutter-mobile));
498        }
499        text-decoration: "none";
500        font-size: var!(font-base);
501        color: var!(text-on-accent);
502        font-weight: "600";
503        background: var!(accent);
504    }
505
506    pub c_nav_item_inactive {
507        display: "flex";
508        align-items: "center";
509        gap: var!(space-sm);
510        padding: format!("{} {}", var!(space-md), var!(edge-gutter-nav));
511        @media ((max-width: 767px)) {
512            padding: format!("{} {}", var!(space-md), var!(edge-gutter-mobile));
513        }
514        text-decoration: "none";
515        font-size: var!(font-base);
516        color: var!(foreground);
517        font-weight: "400";
518        :hover {
519            background: var!(accent-muted);
520            color: var!(accent);
521            box-shadow: format!("inset 4px 0 0 0 {}", var!(foreground));
522        }
523    }
524
525    pub c_nav_item_icon {
526        flex-shrink: "0";
527        width: "20px";
528        text-align: "center";
529    }
530
531    pub c_nav_item_label {
532        flex: "1";
533        overflow: "hidden";
534        text-overflow: "ellipsis";
535        white-space: "nowrap";
536        color: "inherit";
537    }
538
539    // ═══════════════════════════════════════════════════════════════════════════
540    // Main Content Area
541    // ═══════════════════════════════════════════════════════════════════════════
542
543    pub c_app_main {
544        flex: "1";
545        height: "100%";
546        overflow: "auto";
547        padding: format!("{} {} {} {}", var!(padding-main-top), var!(edge-gutter), var!(padding-main-bottom), var!(edge-gutter));
548        scrollbar-color: format!("{} {}", var!(scrollbar-thumb), var!(scrollbar-track));
549        ::-webkit-scrollbar {
550            width: "6px";
551        }
552        ::-webkit-scrollbar-thumb {
553            background: var!(scrollbar-thumb);
554            border: "none";
555            border-radius: "0px";
556        }
557        ::-webkit-scrollbar-thumb:hover {
558            background: var!(scrollbar-thumb-hover);
559        }
560        ::-webkit-scrollbar-thumb:active {
561            background: var!(scrollbar-thumb-active);
562        }
563        @media ((max-width: 767px)) {
564            padding: format!("{} {} {} {}", var!(padding-main-top-mobile), var!(edge-gutter-mobile), var!(padding-main-bottom), var!(edge-gutter-mobile));
565            scrollbar-width: "none";
566            ::-webkit-scrollbar {
567                width: "0px";
568            }
569        }
570    }
571
572    pub c_page_router {
573        flex: "1";
574        display: "flex";
575        flex-direction: "column";
576    }
577
578    pub c_page_container {
579        width: "100%";
580        margin: "0px auto";
581        max-width: var!(content-max-width);
582    }
583
584    // ═══════════════════════════════════════════════════════════════════════════
585    // Page Banner (unified header with emoji icon)
586    // ═══════════════════════════════════════════════════════════════════════════
587
588    pub c_page {
589        position: "relative";
590        text-align: "center";
591        box-sizing: "border-box";
592    }
593
594    pub c_page_glow {
595        position: "absolute";
596        top: "-50%";
597        left: "50%";
598        transform: "translateX(-50%)";
599        width: "400px";
600        max-width: "100%";
601        height: "400px";
602        pointer-events: "none";
603    }
604
605    pub c_page_content {
606        position: "relative";
607        z-index: "1";
608    }
609
610    pub c_page_icon {
611        font-size: "36px";
612        padding-bottom: var!(space-md);
613        @media ((max-width: 767px)) {
614            font-size: "40px";
615        }
616    }
617
618    pub c_page_title {
619        font-size: var!(font-4xl);
620        font-weight: "800";
621        letter-spacing: "-0.03em";
622        margin: "0px";
623        color: var!(foreground);
624        margin-bottom: var!(space-sm);
625        @media ((max-width: 767px)) {
626            font-size: var!(font-3xl);
627        }
628    }
629
630    pub c_page_subtitle {
631        font-size: var!(font-lg);
632        color: var!(muted-foreground);
633        margin: "0px auto";
634        margin-bottom: var!(space-sm);
635        max-width: "560px";
636        opacity: "1";
637        @media ((max-width: 767px)) {
638            font-size: var!(font-base);
639        }
640    }
641
642    // ═══════════════════════════════════════════════════════════════════════════
643    // Card Component
644    // ═══════════════════════════════════════════════════════════════════════════
645
646    pub c_card {
647        color: var!(foreground);
648        box-sizing: "border-box";
649    }
650
651    pub c_card_title {
652        margin: format!("{} 0px", var!(gap-component));
653        color: var!(foreground);
654        font-size: var!(font-lg);
655        font-weight: "600";
656        padding-bottom: var!(gap-component);
657        border-bottom: format!("1px dashed {}", var!(border));
658        letter-spacing: "-0.01em";
659        @media ((max-width: 767px)) {
660            font-size: var!(font-md);
661        }
662    }
663
664    // ═══════════════════════════════════════════════════════════════════════════
665    // Buttons
666    // ═══════════════════════════════════════════════════════════════════════════
667
668    pub c_primary_button {
669        display: "flex";
670        justify-content: "center";
671        align-items: "center";
672        gap: var!(space-sm);
673        width: "100%";
674        height: "42px";
675        background: var!(accent);
676        color: var!(text-on-accent);
677        border: "1px solid transparent";
678        padding: format!("0px {}", var!(space-2xl));
679        cursor: "pointer";
680        font-size: var!(font-base);
681        font-weight: "500";
682        letter-spacing: "0.02em";
683        text-align: "center";
684        outline: "none";
685        box-sizing: "border-box";
686        white-space: "nowrap";
687        overflow: "hidden";
688        text-overflow: "ellipsis";
689        user-select: "none";
690        -webkit-user-select: "none";
691        :focus-visible {
692            outline: "none";
693        }
694        :disabled {
695            background: var!(muted-foreground);
696            cursor: "not-allowed";
697            opacity: "1";
698        }
699        :hover {
700            background: var!(accent);
701        }
702        :active {
703            background: var!(accent);
704            color: var!(text-on-accent);
705            border-color: "transparent";
706        }
707        @media ((max-width: 767px)) {
708            max-width: "100%";
709            padding: format!("{} {}", var!(space-lg), var!(space-xl));
710            font-size: var!(font-md);
711        }
712    }
713
714    pub c_modal_close_button {
715        display: "flex";
716        justify-content: "center";
717        align-items: "center";
718        color: "inherit";
719        border: "none";
720        padding: format!("{} {}", var!(space-sm), var!(space-md));
721        cursor: "pointer";
722        font-size: "20px";
723        font-weight: "400";
724        vertical-align: "middle";
725        outline: "none";
726        opacity: "1";
727        flex-shrink: "0";
728        transition: format!("opacity {} {}", var!(duration-fast), var!(ease-out));
729        :hover {
730            opacity: "1";
731        }
732        :active {
733            opacity: "1";
734        }
735        :focus {
736            outline: "none";
737        }
738    }
739
740    // ═══════════════════════════════════════════════════════════════════════════
741    // Button Controls Container
742    // ═══════════════════════════════════════════════════════════════════════════
743
744    pub c_button_controls {
745        display: "flex";
746        flex-wrap: "wrap";
747        gap: var!(gap-element);
748        margin-top: var!(gap-component);
749        margin-bottom: var!(gap-component);
750    }
751
752    // ═══════════════════════════════════════════════════════════════════════════
753    // Euv Button Variants
754    // ═══════════════════════════════════════════════════════════════════════════
755
756    pub c_euv_button_primary_md {
757        display: "flex";
758        justify-content: "center";
759        align-items: "center";
760        gap: var!(space-sm);
761        flex: "1 1 120px";
762        height: "42px";
763        padding: format!("0px {}", var!(space-xl));
764        background: var!(accent);
765        color: var!(text-on-accent);
766        cursor: "pointer";
767        font-size: var!(font-base);
768        font-weight: "500";
769        outline: "none";
770        white-space: "nowrap";
771        user-select: "none";
772        -webkit-user-select: "none";
773        box-sizing: "border-box";
774        :disabled {
775            background: var!(muted-foreground);
776            cursor: "not-allowed";
777            opacity: "1";
778        }
779    }
780
781    pub c_euv_button_outline_md {
782        display: "flex";
783        justify-content: "center";
784        align-items: "center";
785        gap: var!(space-sm);
786        flex: "1 1 120px";
787        height: "42px";
788        padding: format!("0px {}", var!(space-xl));
789        color: var!(foreground);
790        border: format!("1px solid {}", var!(border));
791        cursor: "pointer";
792        font-size: var!(font-base);
793        font-weight: "500";
794        outline: "none";
795        white-space: "nowrap";
796        user-select: "none";
797        -webkit-user-select: "none";
798        box-sizing: "border-box";
799        :focus-visible {
800            outline: "none";
801        }
802        :disabled {
803            background: var!(muted-foreground);
804            cursor: "not-allowed";
805            opacity: "1";
806        }
807    }
808
809    // ═══════════════════════════════════════════════════════════════════════════
810    // Badges
811    // ═══════════════════════════════════════════════════════════════════════════
812
813    pub c_badge {
814        display: "inline-flex";
815        justify-content: "center";
816        align-items: "center";
817        color: var!(text-on-accent);
818        padding: format!("{} {}", var!(space-2xs), var!(space-sm));
819        border: format!("1px solid {}", var!(accent));
820        font-size: var!(font-xs);
821        font-weight: "600";
822        cursor: "pointer";
823        text-align: "center";
824        background: var!(accent);
825        :focus-visible {
826            outline: "none";
827        }
828        @media ((max-width: 767px)) {
829            padding: format!("{} {}", var!(space-2xs), var!(space-xs));
830            font-size: var!(font-xs);
831        }
832    }
833
834    pub c_badge_outline {
835        display: "inline-flex";
836        justify-content: "center";
837        align-items: "center";
838        color: var!(foreground);
839        padding: format!("{} {}", var!(space-2xs), var!(space-sm));
840        font-size: var!(font-xs);
841        font-weight: "600";
842        cursor: "pointer";
843        text-align: "center";
844        border: format!("1.5px solid {}", var!(border));
845        @media ((max-width: 767px)) {
846            padding: format!("{} {}", var!(space-2xs), var!(space-xs));
847            font-size: var!(font-xs);
848        }
849    }
850
851    pub c_euv_tag_solid_black {
852        display: "inline-block";
853        vertical-align: "middle";
854        text-align: "center";
855        line-height: "1";
856        color: var!(text-on-accent);
857        padding: format!("{} {}", var!(space-xs), var!(space-md));
858        font-size: var!(font-sm);
859        font-weight: "600";
860        cursor: "pointer";
861        background: var!(accent);
862        border: format!("1px solid {}", var!(accent));
863        box-sizing: "border-box";
864    }
865
866    pub c_euv_tag_solid_white {
867        display: "inline-block";
868        vertical-align: "middle";
869        text-align: "center";
870        line-height: "1";
871        color: var!(foreground);
872        padding: format!("{} {}", var!(space-2xs), var!(space-sm));
873        font-size: var!(font-xs);
874        font-weight: "600";
875        cursor: "pointer";
876        border: format!("1.5px solid {}", var!(accent));
877        box-sizing: "border-box";
878    }
879
880    // ═══════════════════════════════════════════════════════════════════════════
881    // Euv Tag Variants (semantic colour tags)
882    // ═══════════════════════════════════════════════════════════════════════════
883
884    pub c_euv_tag_outline_black {
885        display: "inline-block";
886        vertical-align: "middle";
887        text-align: "center";
888        line-height: "1";
889        color: var!(accent);
890        padding: format!("{} {}", var!(space-2xs), var!(space-sm));
891        font-size: var!(font-xs);
892        font-weight: "600";
893        cursor: "pointer";
894        border: format!("1.5px solid {}", var!(accent));
895        box-sizing: "border-box";
896    }
897
898    pub c_euv_tag_outline_white {
899        display: "inline-block";
900        vertical-align: "middle";
901        text-align: "center";
902        line-height: "1";
903        color: var!(foreground);
904        padding: format!("{} {}", var!(space-xs), var!(space-md));
905        font-size: var!(font-sm);
906        font-weight: "600";
907        cursor: "pointer";
908        border: format!("1.5px solid {}", var!(border));
909        box-sizing: "border-box";
910    }
911
912    // ═══════════════════════════════════════════════════════════════════════════
913    // Form Elements
914    // ═══════════════════════════════════════════════════════════════════════════
915
916    pub c_euv_input_wrapper {
917        width: "100%";
918        margin: format!("{} 0px", var!(gap-element));
919    }
920
921    pub c_form_label {
922        display: "block";
923        margin-bottom: var!(space-sm);
924        color: "inherit";
925        font-weight: "500";
926        font-size: var!(font-base);
927    }
928
929    pub c_inline_input_row {
930        display: "flex";
931        align-items: "center";
932        gap: var!(gap-component);
933    }
934
935    pub c_euv_input {
936        width: "100%";
937        min-height: var!(min-height-base);
938        padding: format!("0px {}", var!(space-lg));
939        border: format!("1px solid {}", var!(border));
940        font-size: var!(font-base);
941        line-height: "normal";
942        box-sizing: "border-box";
943        outline: "none";
944        color: var!(foreground);
945        appearance: "none";
946        -webkit-appearance: "none";
947        -moz-appearance: "none";
948        vertical-align: "middle";
949        :hover {
950            border-color: var!(accent);
951            background: var!(accent-muted);
952        }
953        :focus {
954            outline: "none";
955            border-color: var!(accent);
956            background: var!(accent-muted);
957        }
958    }
959
960    pub c_euv_input_no_transition {
961        width: "100%";
962        min-height: var!(min-height-base);
963        padding: format!("0px {}", var!(space-lg));
964        border: format!("1px solid {}", var!(border));
965        font-size: var!(font-base);
966        line-height: "normal";
967        box-sizing: "border-box";
968        outline: "none";
969        color: var!(foreground);
970        appearance: "none";
971        -webkit-appearance: "none";
972        -moz-appearance: "none";
973        vertical-align: "middle";
974    }
975
976    pub c_euv_input_error {
977        width: "100%";
978        min-height: var!(min-height-base);
979        padding: format!("0px {}", var!(space-lg));
980        border: format!("1px solid {}", var!(foreground));
981        font-size: var!(font-base);
982        line-height: "normal";
983        box-sizing: "border-box";
984        outline: "none";
985        color: var!(foreground);
986        appearance: "none";
987        -webkit-appearance: "none";
988        -moz-appearance: "none";
989        vertical-align: "middle";
990        :focus {
991            outline: "none";
992            border-color: var!(foreground);
993        }
994    }
995
996    pub c_form_checkbox {
997        cursor: "pointer";
998        width: var!(space-lg);
999        height: var!(space-lg);
1000    }
1001
1002    pub c_form_checkbox_label {
1003        font-size: var!(font-base);
1004        color: "inherit";
1005        cursor: "pointer";
1006    }
1007
1008    pub c_form_checkbox_row {
1009        margin: format!("{} 0px", var!(gap-component));
1010        display: "flex";
1011        align-items: "center";
1012        gap: var!(gap-element);
1013    }
1014
1015    pub c_select_input {
1016        width: "100%";
1017        min-height: var!(min-height-base);
1018        padding: format!("0px {}", var!(space-lg));
1019        border: format!("1px solid {}", var!(border));
1020        font-size: var!(font-base);
1021        line-height: "normal";
1022        box-sizing: "border-box";
1023        outline: "none";
1024        cursor: "pointer";
1025        appearance: "none";
1026        -webkit-appearance: "none";
1027        -moz-appearance: "none";
1028        color: var!(foreground);
1029        vertical-align: "middle";
1030        background-image: "url(\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 12 12'%3E%3Cpath fill='currentColor' d='M6 8L1 3h10z'/%3E%3C/svg%3E\")";
1031        background-repeat: "no-repeat";
1032        background-position: "right 14px center";
1033        :focus {
1034            outline: "none";
1035            border-color: var!(accent);
1036            background: var!(accent-muted);
1037        }
1038    }
1039
1040    pub c_textarea_input {
1041        width: "100%";
1042        max-width: "100%";
1043        padding: format!("{} {}", var!(space-md), var!(space-lg));
1044        border: format!("1px solid {}", var!(border));
1045        font-size: var!(font-base);
1046        line-height: "normal";
1047        box-sizing: "border-box";
1048        outline: "none";
1049        resize: "vertical";
1050        overflow-x: "hidden";
1051        word-wrap: "break-word";
1052        font-family: "inherit";
1053        color: var!(foreground);
1054        appearance: "none";
1055        -webkit-appearance: "none";
1056        -moz-appearance: "none";
1057        :hover {
1058            border-color: var!(accent);
1059            background: var!(accent-muted);
1060        }
1061        :focus {
1062            outline: "none";
1063            border-color: var!(accent);
1064            background: var!(accent-muted);
1065        }
1066    }
1067
1068    pub c_textarea_input_error {
1069        width: "100%";
1070        max-width: "100%";
1071        padding: format!("{} {}", var!(space-md), var!(space-lg));
1072        border: format!("1px solid {}", var!(foreground));
1073        font-size: var!(font-base);
1074        line-height: "normal";
1075        box-sizing: "border-box";
1076        outline: "none";
1077        resize: "vertical";
1078        overflow-x: "hidden";
1079        word-wrap: "break-word";
1080        font-family: "inherit";
1081        color: var!(foreground);
1082        appearance: "none";
1083        -webkit-appearance: "none";
1084        -moz-appearance: "none";
1085        :focus {
1086            outline: "none";
1087            border-color: var!(foreground);
1088        }
1089    }
1090
1091    pub c_textarea_counter {
1092        text-align: "right";
1093        margin-top: var!(space-xs);
1094        margin-bottom: var!(gap-component);
1095    }
1096
1097    pub c_textarea_counter_text {
1098        font-size: var!(font-sm);
1099        color: "inherit";
1100        opacity: "1";
1101    }
1102
1103    pub c_field_error_text {
1104        color: var!(foreground);
1105        font-size: var!(font-base);
1106        margin-top: var!(space-xs);
1107        margin-bottom: var!(space-sm);
1108    }
1109
1110    // ═══════════════════════════════════════════════════════════════════════════
1111    // Status Boxes
1112    // ═══════════════════════════════════════════════════════════════════════════
1113
1114    pub c_error_box {
1115        margin: format!("{} 0px", var!(gap-component));
1116        background: var!(accent-muted);
1117        color: var!(foreground);
1118        font-size: var!(font-base);
1119        box-sizing: "border-box";
1120    }
1121
1122    pub c_success_box {
1123        margin: format!("{} 0px", var!(gap-component));
1124        background: var!(accent-muted);
1125        color: var!(foreground);
1126        font-size: var!(font-base);
1127        box-sizing: "border-box";
1128    }
1129
1130    // ═══════════════════════════════════════════════════════════════════════════
1131    // Counter / Signals Demo
1132    // ═══════════════════════════════════════════════════════════════════════════
1133
1134    pub c_counter_row {
1135        display: "grid";
1136        grid-template-columns: "1fr 1fr";
1137        align-items: "center";
1138        gap: var!(gap-component);
1139        @media ((max-width: 767px)) {
1140            grid-template-columns: "1fr";
1141        }
1142    }
1143
1144    pub c_counter_text {
1145        font-size: var!(font-base);
1146        color: "inherit";
1147        margin-bottom: var!(gap-component);
1148    }
1149
1150    pub c_counter_value {
1151        font-weight: "700";
1152        color: var!(accent);
1153        font-size: var!(font-base);
1154    }
1155
1156    pub c_counter_value_row {
1157        margin-top: var!(space-sm);
1158        word-break: "break-all";
1159        overflow-wrap: "anywhere";
1160        font-size: var!(font-base);
1161        color: "inherit";
1162        font-weight: "400";
1163    }
1164
1165    pub c_badge_row {
1166        display: "flex";
1167        gap: var!(gap-inline);
1168        flex-wrap: "wrap";
1169        align-items: "center";
1170    }
1171
1172    pub c_badge_hint {
1173        margin-bottom: var!(gap-component);
1174        color: "inherit";
1175        opacity: "1";
1176        font-size: var!(font-base);
1177    }
1178
1179    // ═══════════════════════════════════════════════════════════════════════════
1180    // Home Page
1181    // ═══════════════════════════════════════════════════════════════════════════
1182
1183    pub c_text_ellipsis {
1184        overflow: "hidden";
1185        text-overflow: "ellipsis";
1186        white-space: "nowrap";
1187    }
1188
1189    pub c_info_row {
1190        display: "flex";
1191        align-items: "center";
1192        gap: var!(space-md);
1193        padding: format!("{} 0", var!(space-sm));
1194        overflow: "hidden";
1195    }
1196
1197    pub c_info_label {
1198        font-size: var!(font-sm);
1199        font-weight: "500";
1200        color: var!(muted-foreground);
1201        min-width: "72px";
1202        flex-shrink: "0";
1203        letter-spacing: "0.02em";
1204    }
1205
1206    pub c_info_value {
1207        c_text_ellipsis();
1208        font-size: var!(font-base);
1209        font-weight: "600";
1210        color: var!(foreground);
1211        font-family: "ui-monospace, monospace";
1212        flex: "1";
1213    }
1214
1215    pub c_info_link {
1216        c_text_ellipsis();
1217        font-size: var!(font-base);
1218        font-weight: "600";
1219        color: var!(accent);
1220        font-family: "ui-monospace, monospace";
1221        flex: "1";
1222        text-decoration: "none";
1223        transition: format!("opacity {} {}", var!(duration-fast), var!(ease-out));
1224        :hover {
1225            opacity: "1";
1226        }
1227    }
1228
1229    // ═══════════════════════════════════════════════════════════════════════════
1230    // Camera Page
1231    // ═══════════════════════════════════════════════════════════════════════════
1232
1233    pub c_camera_video_container {
1234        margin: format!("{} 0", var!(space-lg));
1235    }
1236
1237    pub c_camera_video_active {
1238        width: "100%";
1239        background: "#000";
1240        aspect-ratio: "16 / 9";
1241        object-fit: "cover";
1242        border: format!("2px solid {}", var!(accent));
1243        box-sizing: "border-box";
1244    }
1245
1246    pub c_camera_video_hidden {
1247        width: "100%";
1248        aspect-ratio: "16 / 9";
1249        display: "none";
1250    }
1251
1252    pub c_camera_video_placeholder {
1253        width: "100%";
1254        aspect-ratio: "16 / 9";
1255        border: format!("2px dashed {}", var!(border));
1256        display: "flex";
1257        align-items: "center";
1258        justify-content: "center";
1259        box-sizing: "border-box";
1260    }
1261
1262    pub c_camera_placeholder_content {
1263        display: "flex";
1264        flex-direction: "column";
1265        align-items: "center";
1266        gap: var!(space-md);
1267    }
1268
1269    pub c_camera_placeholder_icon {
1270        font-size: var!(font-4xl);
1271        opacity: "1";
1272    }
1273
1274    pub c_camera_placeholder_text {
1275        font-size: var!(font-base);
1276        color: "inherit";
1277        opacity: "1";
1278    }
1279
1280    pub c_camera_error_box {
1281        margin: format!("{} 0px", var!(gap-component));
1282        color: var!(foreground);
1283        font-size: var!(font-base);
1284        word-break: "break-all";
1285        overflow-wrap: "break-word";
1286        box-sizing: "border-box";
1287    }
1288
1289    pub c_camera_scan_result_box {
1290        margin-top: var!(gap-component);
1291        box-sizing: "border-box";
1292    }
1293
1294    pub c_camera_scan_result_label {
1295        font-size: var!(font-sm);
1296        font-weight: "600";
1297        color: var!(foreground);
1298        margin-bottom: var!(space-xs);
1299    }
1300
1301    pub c_camera_scan_result_value {
1302        font-size: var!(font-base);
1303        color: "inherit";
1304        word-break: "break-all";
1305        overflow-wrap: "break-word";
1306    }
1307
1308    // ═══════════════════════════════════════════════════════════════════════════
1309    // Canvas Drawing Board
1310    // ═══════════════════════════════════════════════════════════════════════════
1311
1312    pub c_canvas_preview_container {
1313        margin: format!("{} 0", var!(space-lg));
1314        overflow: "hidden";
1315        border: format!("2px solid {}", var!(border));
1316        background: "#ffffff";
1317        aspect-ratio: "9 / 16";
1318        display: "flex";
1319        align-items: "center";
1320        justify-content: "center";
1321        box-sizing: "border-box";
1322    }
1323
1324    pub c_canvas_placeholder {
1325        color: var!(muted-foreground);
1326        font-size: var!(font-sm);
1327        text-align: "center";
1328        padding: var!(space-lg);
1329    }
1330
1331    pub c_canvas_preview_image {
1332        width: "100%";
1333        height: "100%";
1334        object-fit: "cover";
1335        display: "block";
1336    }
1337
1338    pub c_canvas_container_fullscreen {
1339        width: "100%";
1340        height: "100%";
1341        background: var!(background);
1342        display: "flex";
1343        flex-direction: "column";
1344        position: "fixed";
1345        top: "0";
1346        left: "0";
1347        z-index: "10002";
1348        padding: format!("{} {} {} {}", var!(padding-shell-top), var!(space-lg), var!(padding-shell-bottom), var!(space-lg));
1349        box-sizing: "border-box";
1350    }
1351
1352    pub c_canvas_drawing_fullscreen_wrapper {
1353        flex: "1";
1354        display: "flex";
1355        align-items: "center";
1356        justify-content: "center";
1357        overflow: "hidden";
1358        padding: var!(space-xs);
1359    }
1360
1361    pub c_canvas_drawing_fullscreen {
1362        border: format!("2px solid {}", var!(border));
1363        display: "block";
1364        cursor: "crosshair";
1365        touch-action: "none";
1366    }
1367
1368    pub c_canvas_fullscreen_toolbar {
1369        display: "flex";
1370        flex-direction: "column";
1371        align-items: "stretch";
1372        width: "100%";
1373        padding: format!("{} {}", var!(space-xs), "0px");
1374        flex-shrink: "0";
1375        gap: var!(space-xs);
1376    }
1377
1378    pub c_canvas_fullscreen_toolbar_row_top {
1379        display: "flex";
1380        align-items: "center";
1381        height: var!(mobile-header-height);
1382        width: "100%";
1383        gap: var!(space-sm);
1384    }
1385
1386    pub c_canvas_fullscreen_toolbar_color_wrapper {
1387        display: "flex";
1388        align-items: "center";
1389        justify-content: "center";
1390        flex: "1";
1391        min-width: "0";
1392    }
1393
1394    pub c_canvas_color_input_fullscreen {
1395        width: "100%";
1396        height: "42px";
1397        border: format!("1px solid {}", var!(border));
1398        cursor: "pointer";
1399        padding: format!("{}", var!(space-xs));
1400    }
1401
1402    pub c_canvas_fullscreen_toolbar_row_bottom {
1403        display: "flex";
1404        align-items: "center";
1405        width: "100%";
1406    }
1407
1408    pub c_canvas_fullscreen_range_input {
1409        flex: "1 1 0%";
1410        min-width: "120px";
1411        cursor: "pointer";
1412        -webkit-appearance: "none";
1413        appearance: "none";
1414        border: "none";
1415        outline: "none";
1416        height: "24px";
1417        ::-webkit-slider-runnable-track {
1418            height: "6px";
1419            background: format!("linear-gradient(to right, {} 0%, {} var(--value,50%), {} var(--value,50%), {} 100%)", var!(foreground), var!(foreground), var!(border), var!(border));
1420            border-radius: "3px";
1421            border: "none";
1422        }
1423        ::-webkit-slider-thumb {
1424            width: "20px";
1425            height: "20px";
1426            background: var!(background);
1427            border: format!("2px solid {}", var!(accent));
1428            border-radius: "50%";
1429            cursor: "pointer";
1430            -webkit-appearance: "none";
1431            margin-top: "-7px";
1432        }
1433        ::-moz-range-track {
1434            height: "6px";
1435            background: format!("linear-gradient(to right, {} 0%, {} var(--value,50%), {} var(--value,50%), {} 100%)", var!(foreground), var!(foreground), var!(border), var!(border));
1436            border-radius: "3px";
1437            border: "none";
1438        }
1439        ::-moz-range-thumb {
1440            width: "20px";
1441            height: "20px";
1442            background: var!(background);
1443            border: format!("2px solid {}", var!(accent));
1444            border-radius: "50%";
1445            cursor: "pointer";
1446        }
1447    }
1448
1449    pub c_canvas_fullscreen_toolbar_button {
1450        flex: "0 0 auto";
1451        overflow: "hidden";
1452    }
1453
1454    // ═══════════════════════════════════════════════════════════════════════════
1455    // Game Fullscreen (2D / 3D)
1456    // ═══════════════════════════════════════════════════════════════════════════
1457
1458    // Fullscreen overlay container for the 2D and 3D game pages.
1459    //
1460    // Mirrors `c_canvas_container_fullscreen` so the safe-area caching
1461    // pass in `UseEuvLayout::apply_cached_insets` can pick this selector
1462    // up alongside the canvas one. Differs in that the game overlay holds
1463    // the *same* `<canvas>` element that the inline page mounts (no
1464    // canvas re-creation), so the running game loop, balls, cubes, FPS
1465    // counter and other reactive state survive the fullscreen toggle
1466    // without reset.
1467    pub c_game_container_fullscreen {
1468        width: "100%";
1469        height: "100%";
1470        background: var!(background);
1471        display: "flex";
1472        flex-direction: "column";
1473        position: "fixed";
1474        top: "0";
1475        left: "0";
1476        z-index: "10002";
1477        padding: format!(
1478        "{} {} {} {}",
1479        var!(padding-shell-top),
1480        var!(space-lg),
1481        var!(padding-shell-bottom),
1482        var!(space-lg)
1483        );
1484        box-sizing: "border-box";
1485    }
1486
1487    // Toolbar wrapping the fullscreen exit button on game pages.
1488    //
1489    // Game pages only need an `Exit` button here (no color picker / line
1490    // width control like the canvas drawing board), so the layout is a
1491    // single horizontal row at the bottom of the overlay.
1492    pub c_game_fullscreen_toolbar {
1493        display: "flex";
1494        align-items: "center";
1495        justify-content: "flex-end";
1496        width: "100%";
1497        padding: format!("{} {} {} {}", var!(space-xs), var!(space-lg), var!(space-xs), var!(space-lg));
1498        flex-shrink: "0";
1499        gap: var!(space-sm);
1500        box-sizing: "border-box";
1501    }
1502
1503    // Wrapper that fills the fullscreen game container with the canvas.
1504    //
1505    // The game's `<canvas>` backing buffer is 600x400 (3:2). The canvas
1506    // itself has `width: 100%; height: 100%` so it fills this wrapper
1507    // exactly, and `object-fit: contain` on the canvas class makes the
1508    // browser uniformly scale the backing buffer to fit while preserving
1509    // its 3:2 aspect ratio. Without `object-fit: contain`, the canvas
1510    // would be stretched to whatever shape the wrapper has, making balls
1511    // render as horizontally-ovoid ellipses (e.g. on 1280x800 viewports
1512    // → 1.6:1, slightly squashed vertically). The letterbox bars appear
1513    // inside the canvas element rather than around an outer wrapper, so
1514    // the canvas always fills the fullscreen container with the backing
1515    // buffer uniformly scaled to its native aspect ratio.
1516    pub c_game_fullscreen_canvas_letterbox {
1517        position: "relative";
1518        width: "100%";
1519        max-width: "100%";
1520        max-height: "100%";
1521        height: "100%";
1522        display: "flex";
1523        align-items: "center";
1524        justify-content: "center";
1525    }
1526
1527    // ═══════════════════════════════════════════════════════════════════════════
1528    // Custom Attrs Demo
1529    // ═══════════════════════════════════════════════════════════════════════════
1530
1531    pub c_custom_attrs_demo {
1532        // Use the theme foreground token (not `inherit`) so the text inside
1533        // the dynamic demo block stays readable when the block itself
1534        // applies a user-supplied background (e.g. `background-color: #000000`)
1535        // that otherwise paints the inherited text the same colour.
1536        color: var!(foreground);
1537        box-sizing: "border-box";
1538    }
1539
1540    pub c_demo_text {
1541        color: var!(foreground);
1542        margin-bottom: var!(gap-component);
1543    }
1544
1545    pub c_demo_text_muted {
1546        color: var!(foreground);
1547        opacity: "1";
1548        font-size: var!(font-base);
1549        margin-bottom: "0px";
1550    }
1551
1552    // ═══════════════════════════════════════════════════════════════════════════
1553    // Async / Loading States
1554    // ═══════════════════════════════════════════════════════════════════════════
1555
1556    pub c_loading_container {
1557        display: "flex";
1558        align-items: "center";
1559        justify-content: "center";
1560        gap: var!(gap-component);
1561        margin: format!("{} 0px", var!(gap-component));
1562        box-sizing: "border-box";
1563    }
1564
1565    pub c_spinner {
1566        width: "28px";
1567        height: "28px";
1568        border: format!("3px solid {}", var!(accent-muted));
1569        border-top: format!("3px solid {}", var!(accent));
1570        border-radius: "50%";
1571        flex-shrink: "0";
1572        animation: "euv-spin 0.8s linear infinite";
1573    }
1574
1575    pub c_loading_text_col {
1576        display: "flex";
1577        flex-direction: "column";
1578        gap: var!(space-xs);
1579    }
1580
1581    pub c_loading_title {
1582        color: var!(foreground);
1583        font-size: var!(font-md);
1584        font-weight: "500";
1585    }
1586
1587    pub c_loading_subtitle {
1588        color: var!(muted-foreground);
1589        font-size: var!(font-base);
1590    }
1591
1592    pub c_loading_overlay(background: &str) {
1593        position: "absolute";
1594        top: "0";
1595        left: "0";
1596        width: "100%";
1597        height: "100%";
1598        display: "flex";
1599        flex-direction: "column";
1600        align-items: "center";
1601        justify-content: "center";
1602        gap: var!(gap-component);
1603        background: background;
1604        z-index: "1";
1605        box-sizing: "border-box";
1606    }
1607
1608    pub c_error_container {
1609        display: "flex";
1610        align-items: "center";
1611        gap: var!(gap-element);
1612        margin-top: var!(gap-component);
1613        box-sizing: "border-box";
1614    }
1615
1616    pub c_error_icon {
1617        width: "20px";
1618        height: "20px";
1619        display: "flex";
1620        align-items: "center";
1621        justify-content: "center";
1622        flex-shrink: "0";
1623        color: var!(foreground);
1624        font-size: var!(font-sm);
1625        font-weight: "700";
1626    }
1627
1628    pub c_error_text {
1629        color: var!(foreground);
1630        font-size: var!(font-base);
1631    }
1632
1633    pub c_data_box {
1634        margin: format!("{} 0px", var!(gap-component));
1635        box-sizing: "border-box";
1636    }
1637
1638    pub c_data_pre {
1639        color: var!(foreground);
1640        font-size: var!(font-base);
1641        margin: "0px";
1642        white-space: "pre-wrap";
1643        word-break: "break-all";
1644        font-family: "ui-monospace, monospace";
1645    }
1646
1647    pub c_fetch_hint {
1648        color: "inherit";
1649        opacity: "1";
1650        font-size: var!(font-base);
1651        margin-bottom: var!(gap-component);
1652    }
1653
1654    // ═══════════════════════════════════════════════════════════════════════════
1655    // Conditional Rendering Demo
1656    // ═══════════════════════════════════════════════════════════════════════════
1657
1658    pub c_toggle_content {
1659        margin-top: var!(gap-component);
1660        color: "inherit";
1661    }
1662
1663    pub c_toggle_title {
1664        margin-top: "0px";
1665        color: var!(accent);
1666        font-size: var!(font-md);
1667    }
1668
1669    pub c_role_button_row {
1670        display: "flex";
1671        flex-wrap: "nowrap";
1672        gap: var!(gap-element);
1673        margin-bottom: var!(gap-component);
1674    }
1675
1676    pub c_role_guest_text {
1677        color: var!(foreground);
1678        font-size: var!(font-base);
1679    }
1680
1681    pub c_role_user_text {
1682        color: var!(foreground);
1683        font-size: var!(font-base);
1684    }
1685
1686    pub c_role_admin_text {
1687        color: var!(foreground);
1688        font-size: var!(font-base);
1689    }
1690
1691    // ═══════════════════════════════════════════════════════════════════════════
1692    // Tabs
1693    // ═══════════════════════════════════════════════════════════════════════════
1694
1695    pub c_tab_bar {
1696        display: "flex";
1697        border-bottom: format!("1px dashed {}", var!(border));
1698        margin-bottom: var!(gap-component);
1699        gap: var!(gap-element);
1700        @media ((max-width: 767px)) {
1701            flex-wrap: "wrap";
1702        }
1703    }
1704
1705    pub c_tab_item_active {
1706        padding: format!("{} {}", var!(space-md), var!(space-xl));
1707        cursor: "pointer";
1708        border-bottom: format!("2px solid {}", var!(accent));
1709        color: var!(text-on-accent);
1710        background: var!(accent);
1711        font-size: var!(font-base);
1712        font-weight: "500";
1713        // iOS WebKit: tap on a non-button element inside a scrollable
1714        // container can be silently dropped because iOS interprets the
1715        // touch as the start of a scroll gesture and never dispatches the
1716        // synthetic `click`. `touch-action: manipulation` tells iOS this
1717        // element only responds to taps and panning — no double-tap-zoom
1718        // wait, no scroll-gesture disambiguation. `user-select: none`
1719        // additionally suppresses the iOS text-selection bubble that
1720        // would otherwise intercept the tap. See ui/src/style/css/fn.rs
1721        // for the global reset and PR that documents the iOS repro.
1722        touch-action: "manipulation";
1723        user-select: "none";
1724        -webkit-user-select: "none";
1725    }
1726
1727    pub c_tab_item_inactive {
1728        padding: format!("{} {}", var!(space-md), var!(space-xl));
1729        cursor: "pointer";
1730        border-bottom: "2px solid transparent";
1731        color: "inherit";
1732        font-size: var!(font-base);
1733        font-weight: "500";
1734        // iOS WebKit fix — see c_tab_item_active above for the rationale.
1735        touch-action: "manipulation";
1736        user-select: "none";
1737        -webkit-user-select: "none";
1738        :hover {
1739            background: var!(accent-muted);
1740            color: var!(accent);
1741        }
1742    }
1743
1744    pub c_tab_content {
1745        padding: format!("{} 0px", var!(gap-element));
1746    }
1747
1748    pub c_tab_text {
1749        color: "inherit";
1750        font-size: var!(font-base);
1751        margin-bottom: var!(gap-element);
1752    }
1753
1754    pub c_tab_text_muted {
1755        color: "inherit";
1756        opacity: "1";
1757        font-size: var!(font-base);
1758    }
1759
1760    pub c_tab_text_input {
1761        color: "inherit";
1762        font-size: var!(font-base);
1763        margin-bottom: var!(gap-component);
1764    }
1765
1766    // ═══════════════════════════════════════════════════════════════════════════
1767    // List
1768    // ═══════════════════════════════════════════════════════════════════════════
1769
1770    pub c_list_input {
1771        width: "100%";
1772        flex: "1";
1773        height: "42px";
1774        padding: format!("0px {}", var!(space-lg));
1775        border: format!("1px solid {}", var!(border));
1776        font-size: var!(font-base);
1777        line-height: "normal";
1778        box-sizing: "border-box";
1779        outline: "none";
1780        color: var!(foreground);
1781        appearance: "none";
1782        -webkit-appearance: "none";
1783        -moz-appearance: "none";
1784        vertical-align: "middle";
1785        :hover {
1786            border-color: var!(accent);
1787            background: var!(accent-muted);
1788        }
1789        :focus {
1790            outline: "none";
1791            border-color: var!(accent);
1792            background: var!(accent-muted);
1793        }
1794    }
1795
1796    pub c_list_input_error {
1797        width: "100%";
1798        flex: "1";
1799        height: "42px";
1800        padding: format!("0px {}", var!(space-lg));
1801        border: format!("1px solid {}", var!(foreground));
1802        font-size: var!(font-base);
1803        line-height: "normal";
1804        box-sizing: "border-box";
1805        outline: "none";
1806        color: var!(foreground);
1807        appearance: "none";
1808        -webkit-appearance: "none";
1809        -moz-appearance: "none";
1810        vertical-align: "middle";
1811        :focus {
1812            outline: "none";
1813            border-color: var!(foreground);
1814        }
1815    }
1816
1817    pub c_list_error_text {
1818        color: var!(foreground);
1819        font-size: var!(font-base);
1820        margin: format!("{} 0px", var!(gap-element));
1821    }
1822
1823    pub c_inline_input_button_wrap {
1824        flex-shrink: "0";
1825    }
1826
1827    pub c_list_ul {
1828        list-style: "none";
1829        padding: "0px";
1830        margin: "0px";
1831        margin-top: var!(gap-component);
1832    }
1833
1834    pub c_list_item {
1835        display: "flex";
1836        justify-content: "space-between";
1837        align-items: "center";
1838        gap: var!(gap-component);
1839        min-height: var!(min-height-base);
1840        margin: format!("{} 0px", var!(gap-element));
1841    }
1842
1843    pub c_list_item_text {
1844        flex: "1";
1845        overflow: "hidden";
1846        text-overflow: "ellipsis";
1847        white-space: "nowrap";
1848        font-size: var!(font-base);
1849        color: "inherit";
1850        min-width: "0";
1851    }
1852
1853    pub c_list_item_button {
1854        max-width: "120px";
1855        flex-shrink: "0";
1856    }
1857
1858    // ═══════════════════════════════════════════════════════════════════════════
1859    // Log / Console Display
1860    // ═══════════════════════════════════════════════════════════════════════════
1861
1862    pub c_log_container {
1863        font-family: "ui-monospace, monospace";
1864        font-size: var!(font-base);
1865        margin-top: "0px";
1866        color: var!(foreground);
1867    }
1868
1869    pub c_log_item {
1870        padding: format!("{} 0px", var!(space-sm));
1871        font-size: var!(font-base);
1872        color: var!(foreground);
1873    }
1874
1875    // ═══════════════════════════════════════════════════════════════════════════
1876    // 404 Not Found
1877    // ═══════════════════════════════════════════════════════════════════════════
1878
1879    pub c_render_count_text {
1880        font-size: var!(font-base);
1881        color: "inherit";
1882        margin-bottom: var!(gap-component);
1883    }
1884
1885    // ═══════════════════════════════════════════════════════════════════════════
1886    // Event Demo
1887    // ═══════════════════════════════════════════════════════════════════════════
1888
1889    pub c_event_result {
1890        font-size: var!(font-base);
1891        color: "inherit";
1892        margin-top: var!(gap-element);
1893    }
1894
1895    pub c_event_highlight {
1896        font-weight: "600";
1897        color: var!(accent);
1898    }
1899
1900    pub c_event_info_grid {
1901        display: "grid";
1902        grid-template-columns: "1fr 1fr";
1903        gap: var!(gap-element);
1904        margin-top: var!(gap-component);
1905        @media ((max-width: 767px)) {
1906            grid-template-columns: "1fr";
1907            gap: var!(gap-element);
1908        }
1909    }
1910
1911    pub c_event_info_row {
1912        display: "flex";
1913        align-items: "center";
1914        gap: var!(space-sm);
1915        overflow: "hidden";
1916    }
1917
1918    pub c_event_info_label {
1919        font-size: var!(font-base);
1920        font-weight: "600";
1921        color: var!(foreground);
1922        flex-shrink: "0";
1923    }
1924
1925    pub c_event_info_value {
1926        c_text_ellipsis();
1927        font-size: var!(font-base);
1928        font-weight: "600";
1929        color: var!(accent);
1930        font-family: "ui-monospace, monospace";
1931        flex: "1";
1932    }
1933
1934    pub c_event_mouse_area {
1935        min-height: "120px";
1936        padding: format!("{} 0px", var!(space-xl));
1937        border: format!("2px dashed {}", var!(border));
1938        cursor: "crosshair";
1939        text-align: "center";
1940        user-select: "none";
1941        color: "inherit";
1942    }
1943
1944    pub c_event_drag_zone {
1945        min-height: "100px";
1946        padding: format!("{} 0px", var!(space-xl));
1947        border: format!("2px dashed {}", var!(border));
1948        text-align: "center";
1949        user-select: "none";
1950        color: var!(foreground);
1951    }
1952
1953    pub c_event_drag_zone_active {
1954        min-height: "100px";
1955        padding: format!("{} 0px", var!(space-xl));
1956        border: format!("2px dashed {}", var!(border));
1957        text-align: "center";
1958        user-select: "none";
1959        color: var!(foreground);
1960    }
1961
1962    pub c_event_drag_item {
1963        display: "inline-block";
1964        padding: format!("{} {}", var!(space-sm), var!(space-xl));
1965        background: var!(accent);
1966        color: var!(text-on-accent);
1967        font-size: var!(font-base);
1968        font-weight: "500";
1969        cursor: "grab";
1970        margin: var!(space-sm);
1971    }
1972
1973    pub c_event_drop_zone {
1974        border: format!("2px dashed {}", var!(border));
1975        padding: format!("{} {}", var!(space-4xl), var!(space-xl));
1976        text-align: "center";
1977        cursor: "pointer";
1978    }
1979
1980    pub c_event_drop_zone_active {
1981        border: format!("2px dashed {}", var!(accent));
1982        padding: format!("{} {}", var!(space-4xl), var!(space-xl));
1983        text-align: "center";
1984        cursor: "pointer";
1985        background: var!(accent-muted);
1986    }
1987
1988    pub c_event_drop_icon {
1989        font-size: var!(font-5xl);
1990        display: "block";
1991        padding-bottom: var!(space-md);
1992    }
1993
1994    pub c_event_drop_text {
1995        font-size: var!(font-lg);
1996        font-weight: "500";
1997        color: "inherit";
1998        padding-bottom: var!(space-md);
1999    }
2000
2001    pub c_event_drop_hint {
2002        font-size: var!(font-base);
2003        color: "inherit";
2004        opacity: "1";
2005        margin: "0px";
2006    }
2007
2008    pub c_event_wheel_zone {
2009        min-height: "120px";
2010        padding: format!("{} 0px", var!(space-xl));
2011        border: format!("2px dashed {}", var!(border));
2012        text-align: "center";
2013        overflow: "auto";
2014        color: var!(foreground);
2015    }
2016
2017    pub c_event_clipboard_area {
2018        color: var!(foreground);
2019    }
2020
2021    pub c_event_touch_zone {
2022        min-height: "120px";
2023        padding: format!("{} 0px", var!(space-xl));
2024        border: format!("2px dashed {}", var!(accent));
2025        text-align: "center";
2026        touch-action: "none";
2027        user-select: "none";
2028        color: var!(accent);
2029    }
2030
2031    pub c_event_form_area {
2032        padding: format!("{} 0px", var!(space-lg));
2033        color: var!(foreground);
2034    }
2035
2036    pub c_event_media_area {
2037        padding: format!("{} 0px", var!(space-lg));
2038        color: var!(foreground);
2039        max-width: "100%";
2040        overflow: "hidden";
2041    }
2042
2043    pub c_event_audio {
2044        width: "100%";
2045        max-width: "100%";
2046    }
2047
2048    pub c_event_video_area {
2049        color: var!(foreground);
2050        width: "100%";
2051        overflow: "hidden";
2052    }
2053
2054    pub c_event_video {
2055        width: "100%";
2056        max-width: "100%";
2057    }
2058
2059    pub c_event_image_area {
2060        padding: format!("{} 0px", var!(space-lg));
2061        color: "inherit";
2062        width: "100%";
2063        overflow: "hidden";
2064        display: "flex";
2065        flex-direction: "column";
2066        align-items: "center";
2067        gap: var!(space-md);
2068    }
2069
2070    pub c_event_image {
2071        width: "200px";
2072        max-width: "100%";
2073        object-fit: "contain";
2074        display: "block";
2075    }
2076
2077    pub c_event_url_text {
2078        text-align: "center";
2079        font-size: var!(font-sm);
2080        color: "inherit";
2081        opacity: "1";
2082        font-family: "ui-monospace, monospace";
2083        word-break: "break-all";
2084        width: "100%";
2085    }
2086
2087    // ═══════════════════════════════════════════════════════════════════════════
2088    // Timer Demo
2089    // ═══════════════════════════════════════════════════════════════════════════
2090
2091    pub c_timer_display {
2092        text-align: "center";
2093        padding: var!(space-xl);
2094        margin: format!("{} 0px", var!(gap-component));
2095        color: "inherit";
2096    }
2097
2098    pub c_timer_value {
2099        font-size: var!(font-base);
2100        font-weight: "700";
2101        color: var!(accent);
2102        letter-spacing: "0.04em";
2103        font-family: "ui-monospace, monospace";
2104    }
2105
2106    pub c_timer_controls {
2107        display: "flex";
2108        flex-wrap: "wrap";
2109        gap: var!(gap-element);
2110    }
2111
2112    pub c_timer_done {
2113        text-align: "center";
2114        margin-top: var!(gap-component);
2115        font-size: var!(font-lg);
2116        font-weight: "600";
2117        color: var!(foreground);
2118    }
2119
2120    // ═══════════════════════════════════════════════════════════════════════════
2121    // Modal
2122    // ═══════════════════════════════════════════════════════════════════════════
2123
2124    pub c_modal_overlay {
2125        position: "fixed";
2126        top: "0px";
2127        left: "0px";
2128        width: "100%";
2129        height: "100%";
2130        background: var!(bg-overlay);
2131        contain: "layout style paint";
2132        display: "flex";
2133        align-items: "center";
2134        justify-content: "center";
2135        z-index: "1000";
2136        animation: format!("euv-fade-in {} {}", var!(duration-modal-overlay), var!(ease-out));
2137        @media ((max-width: 767px)) {
2138            align-items: "center";
2139            justify-content: "center";
2140        }
2141    }
2142
2143    pub c_modal_content {
2144        background: var!(background);
2145        padding: "0px";
2146        max-width: "480px";
2147        width: "90%";
2148        animation: format!("euv-scale-in-modal {} {}", var!(duration-modal-content), var!(ease-bounce));
2149        overflow: "hidden";
2150        color: var!(foreground);
2151        box-sizing: "border-box";
2152        @media ((max-width: 767px)) {
2153            max-width: "100%";
2154            width: "calc(100% - 32px)";
2155            max-height: "85vh";
2156            overflow-y: "auto";
2157        }
2158    }
2159
2160    pub c_modal_header {
2161        display: "flex";
2162        justify-content: "space-between";
2163        align-items: "center";
2164        padding: format!("{} {} 0px {}", var!(space-md), var!(space-xl), var!(space-xl));
2165    }
2166
2167    pub c_modal_title {
2168        margin: "0px";
2169        font-size: var!(font-xl);
2170        font-weight: "600";
2171        color: "inherit";
2172    }
2173
2174    pub c_modal_body {
2175        padding: format!("0px {} {} {}", var!(space-xl), var!(space-md), var!(space-xl));
2176        color: "inherit";
2177    }
2178
2179    pub c_modal_actions {
2180        display: "flex";
2181        flex-wrap: "wrap";
2182        gap: var!(space-md);
2183        margin: format!("{} 0px", var!(space-md));
2184    }
2185
2186    // ═══════════════════════════════════════════════════════════════════════════
2187    // Animation Demo
2188    // ═══════════════════════════════════════════════════════════════════════════
2189
2190    pub c_anim_fade_in {
2191        margin-top: var!(gap-component);
2192        animation: format!("euv-fade-in 0.5s {}", var!(ease-out));
2193        font-size: var!(font-base);
2194        color: "inherit";
2195    }
2196
2197    pub c_anim_spin_container {
2198        display: "flex";
2199        justify-content: "center";
2200        align-items: "center";
2201        margin: format!("{} 0px", var!(space-lg));
2202        min-height: "80px";
2203    }
2204
2205    pub c_anim_spin {
2206        font-size: var!(font-5xl);
2207        animation: "euv-spin 1.5s linear infinite";
2208        display: "inline-block";
2209        @media ((max-width: 767px)) {
2210            font-size: var!(font-4xl);
2211        }
2212    }
2213
2214    pub c_anim_spin_stopped {
2215        font-size: var!(font-5xl);
2216        display: "inline-block";
2217        opacity: "1";
2218        @media ((max-width: 767px)) {
2219            font-size: var!(font-4xl);
2220        }
2221    }
2222
2223    pub c_anim_pulse_container {
2224        display: "flex";
2225        justify-content: "center";
2226        align-items: "center";
2227        margin: format!("{} 0px", var!(space-lg));
2228        min-height: "80px";
2229    }
2230
2231    pub c_anim_pulse {
2232        font-size: var!(font-5xl);
2233        animation: "euv-pulse 1.5s ease-in-out infinite";
2234        display: "inline-block";
2235        color: var!(foreground);
2236        @media ((max-width: 767px)) {
2237            font-size: var!(font-4xl);
2238        }
2239    }
2240
2241    pub c_anim_pulse_stopped {
2242        font-size: var!(font-5xl);
2243        display: "inline-block";
2244        opacity: "1";
2245        color: var!(foreground);
2246        @media ((max-width: 767px)) {
2247            font-size: var!(font-4xl);
2248        }
2249    }
2250
2251    pub c_progress_container {
2252        width: "100%";
2253        height: "12px";
2254        margin: format!("{} 0px", var!(space-lg));
2255        overflow: "hidden";
2256    }
2257
2258    pub c_progress_bar_running {
2259        height: "100%";
2260        background: var!(accent);
2261        animation: format!("euv-progress 1.6s {} forwards", var!(ease-in-out));
2262    }
2263
2264    pub c_progress_bar_stopped {
2265        height: "100%";
2266        background: var!(accent);
2267        width: "0%";
2268    }
2269
2270    pub c_anim_scale_box {
2271        margin: format!("{} 0px", var!(gap-component));
2272        padding: var!(space-xl);
2273        background: var!(accent);
2274        cursor: "pointer";
2275        transition: format!("transform {} {}", var!(duration-normal), var!(ease-out));
2276    }
2277
2278    // ═══════════════════════════════════════════════════════════════════════════
2279    // Browser API Demo
2280    // ═══════════════════════════════════════════════════════════════════════════
2281
2282    pub c_browser_api_row {
2283        display: "grid";
2284        grid-template-columns: "1fr 1fr";
2285        gap: var!(gap-component);
2286        margin-bottom: var!(gap-component);
2287        @media ((max-width: 767px)) {
2288            grid-template-columns: "1fr";
2289        }
2290    }
2291
2292    pub c_browser_api_actions {
2293        display: "flex";
2294        flex-wrap: "wrap";
2295        gap: var!(gap-element);
2296        margin: format!("{} 0px", var!(gap-component));
2297    }
2298
2299    pub c_browser_result_box {
2300        margin-top: var!(gap-component);
2301        font-size: var!(font-base);
2302        word-break: "break-all";
2303        color: "inherit";
2304    }
2305
2306    pub c_browser_result_label {
2307        font-weight: "600";
2308        color: var!(accent);
2309    }
2310
2311    pub c_browser_result_value {
2312        color: "inherit";
2313    }
2314
2315    pub c_browser_info_grid {
2316        display: "grid";
2317        gap: var!(gap-component);
2318        margin-top: var!(gap-component);
2319        @media ((max-width: 767px)) {
2320            grid-template-columns: "1fr";
2321        }
2322    }
2323
2324    pub c_browser_info_item {
2325        display: "flex";
2326        flex-direction: "column";
2327        gap: var!(space-xs);
2328        color: "inherit";
2329    }
2330
2331    pub c_browser_info_label {
2332        font-size: var!(font-sm);
2333        font-weight: "600";
2334        color: "inherit";
2335        opacity: "1";
2336        text-transform: "uppercase";
2337        letter-spacing: "0.05em";
2338    }
2339
2340    pub c_browser_info_value {
2341        font-size: var!(font-base);
2342        color: "inherit";
2343        word-break: "break-all";
2344        font-family: "ui-monospace, monospace";
2345    }
2346
2347    // ═══════════════════════════════════════════════════════════════════════════
2348    // VConsole Panel
2349    // ═══════════════════════════════════════════════════════════════════════════
2350
2351    pub c_vconsole_badge {
2352        position: "absolute";
2353        top: "-6px";
2354        right: "-8px";
2355        min-width: "18px";
2356        height: "18px";
2357        background: var!(background);
2358        color: var!(foreground);
2359        font-size: "10px";
2360        font-weight: "600";
2361        display: "flex";
2362        align-items: "center";
2363        justify-content: "center";
2364        padding: format!("0px {}", var!(space-xs));
2365        border: format!("1px solid {}", var!(accent));
2366        pointer-events: "none";
2367        transition: format!("transform {} {}, opacity {} {}", var!(duration-normal), var!(ease-out), var!(duration-normal), var!(ease-out));
2368    }
2369
2370    pub c_vconsole_overlay {
2371        position: "fixed";
2372        top: "0px";
2373        left: "0px";
2374        right: "0px";
2375        bottom: "0px";
2376        z-index: "10000";
2377        background: var!(bg-overlay);
2378        contain: "layout style paint";
2379        transition: format!("opacity {} {}", var!(duration-overlay), var!(ease-out));
2380    }
2381
2382    pub c_vconsole_overlay_hidden {
2383        opacity: "0";
2384        pointer-events: "none";
2385    }
2386
2387    pub c_vconsole_panel {
2388        position: "fixed";
2389        bottom: "0px";
2390        left: "0px";
2391        right: "0px";
2392        height: format!("calc(76vh - {})", var!(safe-area-inset-bottom));
2393        background: var!(background);
2394        z-index: "10001";
2395        display: "flex";
2396        flex-direction: "column";
2397        contain: "layout style paint";
2398        will-change: "transform";
2399        transition: format!("transform {} {}", var!(duration-overlay), var!(ease-out));
2400        overflow: "hidden";
2401        padding: format!("{} {}", var!(padding-main-top), var!(edge-gutter));
2402        @media ((max-width: 767px)) {
2403            padding: format!("{} {}", var!(space-md), var!(edge-gutter-mobile));
2404        }
2405    }
2406
2407    pub c_vconsole_panel_closed {
2408        transform: "translateY(100%)";
2409        will-change: "auto";
2410    }
2411
2412    pub c_vconsole_fab {
2413        position: "fixed";
2414        bottom: format!("calc({} + {})", var!(edge-gutter-bottom), var!(safe-area-inset-bottom));
2415        right: var!(edge-gutter);
2416        z-index: "9999";
2417        @media ((max-width: 767px)) {
2418            bottom: format!("calc({} + {})", var!(edge-gutter-mobile), var!(safe-area-inset-bottom));
2419            right: var!(edge-gutter-mobile);
2420        }
2421    }
2422
2423    pub c_vconsole_header {
2424        display: "flex";
2425        justify-content: "space-between";
2426        align-items: "center";
2427        flex-shrink: "0";
2428    }
2429
2430    pub c_vconsole_title {
2431        color: var!(foreground);
2432        font-size: var!(font-md);
2433        font-weight: "600";
2434        margin: "0px";
2435        letter-spacing: "0.03em";
2436        display: "flex";
2437        align-items: "center";
2438        gap: var!(space-sm);
2439    }
2440
2441    pub c_vconsole_title_dot {
2442        width: "8px";
2443        height: "8px";
2444        background: var!(accent);
2445        display: "inline-block";
2446        animation: "euv-pulse 2s ease-in-out infinite";
2447    }
2448
2449    pub c_vconsole_header_actions {
2450        display: "flex";
2451        gap: var!(space-sm);
2452        align-items: "center";
2453    }
2454
2455    pub c_vconsole_clear_button {
2456        display: "inline-flex";
2457        justify-content: "center";
2458        align-items: "center";
2459        color: var!(foreground);
2460        padding: format!("{} {}", var!(space-2xs), var!(space-sm));
2461        font-size: var!(font-xs);
2462        font-weight: "600";
2463        cursor: "pointer";
2464        text-align: "center";
2465        border: format!("1.5px solid {}", var!(border));
2466        margin-left: "auto";
2467        :focus-visible {
2468            outline: "none";
2469        }
2470    }
2471
2472    pub c_vconsole_close_button {
2473        display: "inline-flex";
2474        justify-content: "center";
2475        align-items: "center";
2476        color: var!(foreground);
2477        padding: format!("{} {}", var!(space-xs), var!(space-md));
2478        cursor: "pointer";
2479        font-size: var!(font-sm);
2480        font-weight: "400";
2481        text-align: "center";
2482        white-space: "nowrap";
2483        user-select: "none";
2484        -webkit-user-select: "none";
2485        vertical-align: "middle";
2486        outline: "none";
2487        transition: format!("all {} {}", var!(duration-fast), var!(ease-out));
2488        :hover {
2489            border-color: var!(foreground);
2490            color: var!(foreground);
2491            background: var!(background);
2492        }
2493        :focus-visible {
2494            outline: "none";
2495        }
2496        :active {
2497            background: "transparent";
2498            color: var!(foreground);
2499            border-color: var!(border);
2500        }
2501    }
2502
2503    pub c_vconsole_body {
2504        flex: "1";
2505        overflow-y: "auto";
2506        contain: "content";
2507        padding-bottom: var!(space-md);
2508        font-family: "ui-monospace, monospace";
2509        font-size: var!(font-xs);
2510    }
2511
2512    pub c_vconsole_log_item {
2513        display: "flex";
2514        align-items: "center";
2515        padding: format!("{} 0px", var!(space-sm));
2516        border-bottom: format!("1px dashed {}", var!(border));
2517        color: var!(foreground);
2518        font-size: var!(font-xs);
2519        word-break: "break-all";
2520    }
2521
2522    pub c_vconsole_empty {
2523        color: var!(muted-foreground);
2524        font-size: var!(font-xs);
2525        text-align: "center";
2526        padding: format!("{} 0px", var!(space-4xl));
2527        overflow: "hidden";
2528    }
2529
2530    pub c_vconsole_empty_hidden {
2531        height: "0";
2532        overflow: "hidden";
2533        padding: "0";
2534    }
2535
2536    pub c_vconsole_log_list {
2537        overflow: "hidden";
2538    }
2539
2540    pub c_vconsole_log_list_hidden {
2541        height: "0";
2542        overflow: "hidden";
2543    }
2544
2545    pub c_vconsole_count {
2546        color: var!(muted-foreground);
2547        font-size: var!(font-sm);
2548        font-weight: "400";
2549    }
2550
2551    pub c_vconsole_filter_bar {
2552        display: "flex";
2553        gap: var!(space-sm);
2554        padding: format!("{} 0px", var!(space-sm));
2555        border-bottom: format!("1px dashed {}", var!(border));
2556        flex-shrink: "0";
2557        align-items: "center";
2558    }
2559
2560    pub c_vconsole_filter_badge {
2561        display: "inline-flex";
2562        justify-content: "center";
2563        align-items: "center";
2564        color: var!(text-on-accent);
2565        padding: format!("{} {}", var!(space-2xs), var!(space-sm));
2566        border: format!("1px solid {}", var!(accent));
2567        font-size: var!(font-xs);
2568        font-weight: "600";
2569        cursor: "pointer";
2570        text-align: "center";
2571        background: var!(accent);
2572        :focus-visible {
2573            outline: "none";
2574        }
2575    }
2576
2577    pub c_vconsole_filter_badge_outline {
2578        display: "inline-flex";
2579        justify-content: "center";
2580        align-items: "center";
2581        color: var!(foreground);
2582        padding: format!("{} {}", var!(space-2xs), var!(space-sm));
2583        font-size: var!(font-xs);
2584        font-weight: "600";
2585        cursor: "pointer";
2586        text-align: "center";
2587        border: format!("1.5px solid {}", var!(border));
2588    }
2589
2590    pub c_vconsole_level_badge {
2591        padding: format!("{} {}", var!(space-2xs), var!(space-sm));
2592        font-size: var!(font-xs);
2593        margin-right: var!(space-sm);
2594        letter-spacing: "0.05em";
2595        color: var!(foreground);
2596        border: "1px solid currentColor";
2597        wrap: "nowrap";
2598        flex-shrink: "0";
2599    }
2600
2601    // ═══════════════════════════════════════════════════════════════════════════
2602    // Mobile Layout
2603    // ═══════════════════════════════════════════════════════════════════════════
2604
2605    pub c_mobile_header {
2606        display: "flex";
2607        align-items: "center";
2608        justify-content: "space-between";
2609        padding: format!("var(--euv-mobile-safe-top, 0px) {} 0px {}", var!(edge-gutter-mobile), var!(edge-gutter-mobile));
2610        height: format!("calc({} + var(--euv-mobile-safe-top, 0px))", var!(mobile-header-height));
2611        flex-shrink: "0";
2612        position: "sticky";
2613        top: "0px";
2614        z-index: "100";
2615        contain: "content";
2616        background: var!(background);
2617        border-bottom: format!("1px solid {}", var!(border));
2618    }
2619
2620    pub c_mobile_header_left {
2621        display: "flex";
2622        align-items: "center";
2623        gap: format!("{}", var!(space-md));
2624    }
2625
2626    pub c_mobile_header_logo {
2627        display: "flex";
2628        align-items: "center";
2629        gap: format!("{}", var!(space-sm));
2630        text-decoration: "none";
2631        color: var!(foreground);
2632    }
2633
2634    pub c_mobile_menu_button {
2635        width: "40px";
2636        height: "40px";
2637        border: "none";
2638        cursor: "pointer";
2639        font-size: "22px";
2640        font-weight: "700";
2641        display: "flex";
2642        align-items: "center";
2643        justify-content: "center";
2644        color: var!(foreground);
2645        padding: "0px";
2646        :active {
2647            background: "transparent";
2648            color: var!(foreground);
2649        }
2650    }
2651
2652    pub c_mobile_theme_button {
2653        width: "40px";
2654        height: "40px";
2655        border: "none";
2656        cursor: "pointer";
2657        display: "flex";
2658        align-items: "center";
2659        justify-content: "center";
2660        padding: "0px";
2661        :active {
2662            background: "transparent";
2663        }
2664    }
2665
2666    pub c_mobile_menu_button_active {
2667        width: "40px";
2668        height: "40px";
2669        border: "none";
2670        cursor: "pointer";
2671        font-size: "22px";
2672        font-weight: "700";
2673        display: "flex";
2674        align-items: "center";
2675        justify-content: "center";
2676        color: var!(accent);
2677        padding: "0px";
2678        :active {
2679            background: var!(background);
2680            color: var!(accent);
2681        }
2682    }
2683
2684    pub c_mobile_drawer_close_button {
2685        width: "32px";
2686        height: "32px";
2687        border: "none";
2688        cursor: "pointer";
2689        font-size: "18px";
2690        font-weight: "500";
2691        display: "flex";
2692        align-items: "center";
2693        justify-content: "center";
2694        color: var!(muted-foreground);
2695        padding: "0px";
2696        transition: format!("color {} {}", var!(duration-fast), var!(ease-out));
2697        :hover {
2698            color: var!(foreground);
2699        }
2700        :active {
2701            color: var!(muted-foreground);
2702        }
2703    }
2704
2705    pub c_mobile_overlay {
2706        position: "fixed";
2707        top: "0px";
2708        left: "0px";
2709        width: "100%";
2710        height: "100%";
2711        background: var!(bg-overlay);
2712        z-index: "200";
2713        contain: "layout style paint";
2714        transition: format!("opacity {} {}", var!(duration-overlay), var!(ease-out));
2715    }
2716
2717    pub c_mobile_overlay_hidden {
2718        opacity: "0";
2719        pointer-events: "none";
2720    }
2721
2722    pub c_mobile_nav_drawer {
2723        position: "fixed";
2724        top: "0px";
2725        left: "0px";
2726        width: "240px";
2727        max-width: "100%";
2728        height: "100%";
2729        background: var!(background);
2730        z-index: "201";
2731        display: "flex";
2732        flex-direction: "column";
2733        padding-top: "var(--euv-mobile-safe-top, 0px)";
2734        padding-bottom: var!(padding-shell-bottom);
2735        contain: "layout style paint";
2736        will-change: "transform";
2737        transition: format!("transform {} {}", var!(duration-overlay), var!(ease-out));
2738        overflow: "hidden";
2739    }
2740
2741    pub c_mobile_nav_drawer_closed {
2742        transform: "translateX(-100%)";
2743    }
2744
2745    pub c_mobile_nav_drawer_header {
2746        display: "flex";
2747        align-items: "center";
2748        justify-content: "space-between";
2749        padding: format!("0px {}", var!(edge-gutter-mobile));
2750        height: var!(mobile-header-height);
2751        flex-shrink: "0";
2752        position: "relative";
2753        ::after {
2754            content: "''";
2755            position: "absolute";
2756            bottom: "0px";
2757            left: var!(edge-gutter-mobile);
2758            right: var!(edge-gutter-mobile);
2759            height: "1px";
2760            background: format!("linear-gradient(90deg, transparent, {}, transparent)", var!(border));
2761        }
2762    }
2763
2764    pub c_mobile_main {
2765        c_app_main();
2766        ::-webkit-scrollbar {
2767            width: "0px";
2768        }
2769    }
2770
2771    // ═══════════════════════════════════════════════════════════════════════════
2772    // Keep-Alive Demo
2773    // ═══════════════════════════════════════════════════════════════════════════
2774
2775    pub c_keep_alive_tab_bar {
2776        display: "flex";
2777        border-bottom: format!("1px dashed {}", var!(border));
2778        margin-bottom: var!(gap-component);
2779        gap: var!(gap-element);
2780    }
2781
2782    pub c_keep_alive_tab_panel {
2783        padding: format!("{} 0px", var!(gap-element));
2784    }
2785
2786    pub c_keep_alive_panel_title {
2787        margin-top: "0px";
2788        color: var!(accent);
2789        font-size: var!(font-md);
2790        margin-bottom: var!(gap-element);
2791    }
2792
2793    pub c_keep_alive_demo_text {
2794        color: "inherit";
2795        font-size: var!(font-base);
2796        margin-bottom: var!(gap-component);
2797    }
2798
2799    pub c_keep_alive_counter_display {
2800        display: "flex";
2801        justify-content: "center";
2802        align-items: "center";
2803        margin: format!("{} 0px", var!(space-xl));
2804    }
2805
2806    pub c_keep_alive_counter_value {
2807        font-size: var!(font-base);
2808        font-weight: "700";
2809        font-variant-numeric: "tabular-nums";
2810        color: var!(accent);
2811        text-align: "center";
2812    }
2813
2814    pub c_keep_alive_counter_controls {
2815        display: "flex";
2816        flex-wrap: "wrap";
2817        gap: format!("{}", var!(space-md));
2818    }
2819
2820    pub c_keep_alive_form_group {
2821        margin-bottom: var!(gap-component);
2822    }
2823
2824    pub c_keep_alive_form_preview {
2825        margin-top: var!(gap-component);
2826        background: var!(accent-muted);
2827    }
2828
2829    pub c_keep_alive_preview_label {
2830        font-size: var!(font-base);
2831        font-weight: "600";
2832        color: var!(accent);
2833        margin: format!("0px 0px {} 0px", var!(space-xs));
2834    }
2835
2836    // ═══════════════════════════════════════════════════════════════════════════
2837    // File Upload
2838    // ═══════════════════════════════════════════════════════════════════════════
2839
2840    pub c_file_upload_input_hidden {
2841        position: "absolute";
2842        width: "1px";
2843        height: "1px";
2844        padding: "0px";
2845        margin: "-1px";
2846        overflow: "hidden";
2847        clip: "rect(0, 0, 0, 0)";
2848        white-space: "nowrap";
2849        border: "0px";
2850    }
2851
2852    pub c_file_upload_options {
2853        margin: format!("{} 0px", var!(gap-component));
2854    }
2855
2856    pub c_file_upload_item {
2857        display: "flex";
2858        align-items: "center";
2859        gap: format!("{}", var!(space-md));
2860        margin: format!("{} 0px", var!(space-sm));
2861        font-size: var!(font-base);
2862        color: "inherit";
2863    }
2864
2865    pub c_file_upload_item_index {
2866        font-size: var!(font-sm);
2867        font-weight: "600";
2868        color: var!(accent);
2869        min-width: "24px";
2870    }
2871
2872    pub c_file_upload_item_name {
2873        color: "inherit";
2874        word-break: "break-all";
2875    }
2876
2877    // ═══════════════════════════════════════════════════════════════════════════
2878    // Binding Demo
2879    // ═══════════════════════════════════════════════════════════════════════════
2880
2881    pub c_binding_child_box {
2882        display: "flex";
2883        flex-direction: "column";
2884        gap: var!(gap-component);
2885        margin-top: var!(gap-component);
2886    }
2887
2888    pub c_binding_child_label {
2889        font-size: var!(font-base);
2890        font-weight: "600";
2891        color: var!(accent);
2892        text-transform: "uppercase";
2893        letter-spacing: "0.05em";
2894    }
2895
2896    pub c_binding_parent_box {
2897        display: "flex";
2898        flex-direction: "column";
2899        gap: var!(gap-component);
2900        margin-top: var!(gap-component);
2901    }
2902
2903    pub c_binding_section_title {
2904        margin-top: var!(gap-component);
2905        margin-bottom: var!(gap-element);
2906        color: var!(accent);
2907        font-size: var!(font-md);
2908        font-weight: "600";
2909    }
2910
2911    pub c_binding_temp_converter {
2912        display: "flex";
2913        align-items: "flex-end";
2914        gap: var!(gap-component);
2915        flex-wrap: "wrap";
2916        margin-top: var!(gap-component);
2917    }
2918
2919    pub c_binding_temp_field {
2920        flex: "1";
2921        min-width: "120px";
2922    }
2923
2924    pub c_binding_temp_arrow {
2925        font-size: "20px";
2926        font-weight: "700";
2927        color: var!(accent);
2928        padding-bottom: "10px";
2929    }
2930
2931    pub c_binding_color_mixer {
2932        margin-top: var!(gap-component);
2933    }
2934
2935    pub c_binding_color_preview {
2936        width: "100%";
2937        height: "80px";
2938        display: "flex";
2939        align-items: "center";
2940        justify-content: "center";
2941        margin-bottom: var!(gap-component);
2942    }
2943
2944    pub c_binding_color_hex {
2945        font-family: "ui-monospace, monospace";
2946        font-size: var!(font-xl);
2947        font-weight: "700";
2948        color: var!(text-on-accent);
2949        letter-spacing: "0.02em";
2950    }
2951
2952    pub c_binding_slider_row {
2953        display: "flex";
2954        align-items: "center";
2955        gap: format!("{}", var!(space-md));
2956        margin-bottom: var!(space-sm);
2957    }
2958
2959    pub c_binding_slider_label {
2960        font-size: var!(font-base);
2961        font-weight: "700";
2962        min-width: var!(font-sm);
2963    }
2964
2965    pub c_binding_slider {
2966        flex: "1";
2967        height: "24px";
2968        padding: "0px";
2969        cursor: "pointer";
2970        -webkit-appearance: "none";
2971        appearance: "none";
2972        border: "none";
2973        outline: "none";
2974        ::-webkit-slider-runnable-track {
2975            height: "6px";
2976            background: format!("linear-gradient(to right, {} 0%, {} var(--value,50%), {} var(--value,50%), {} 100%)", var!(foreground), var!(foreground), var!(border), var!(border));
2977            border-radius: "3px";
2978            border: "none";
2979        }
2980        ::-webkit-slider-thumb {
2981            width: "20px";
2982            height: "20px";
2983            background: var!(background);
2984            border: format!("2px solid {}", var!(accent));
2985            border-radius: "50%";
2986            cursor: "pointer";
2987            -webkit-appearance: "none";
2988            margin-top: "-7px";
2989        }
2990        : active::-webkit-slider-thumb {
2991            transform: "scale(0.92)";
2992        }
2993        ::-moz-range-track {
2994            height: "6px";
2995            background: format!("linear-gradient(to right, {} 0%, {} var(--value,50%), {} var(--value,50%), {} 100%)", var!(foreground), var!(foreground), var!(border), var!(border));
2996            border-radius: "3px";
2997            border: "none";
2998        }
2999        ::-moz-range-thumb {
3000            width: "20px";
3001            height: "20px";
3002            background: var!(background);
3003            border: format!("2px solid {}", var!(accent));
3004            border-radius: "50%";
3005            cursor: "pointer";
3006        }
3007        : active::-moz-range-thumb {
3008            transform: "scale(0.92)";
3009        }
3010    }
3011
3012    pub c_binding_slider_value {
3013        font-size: var!(font-base);
3014        font-weight: "500";
3015        color: "inherit";
3016        min-width: "32px";
3017        text-align: "right";
3018        font-family: "ui-monospace, monospace";
3019    }
3020
3021    pub c_binding_typed_prop_value {
3022        font-family: "ui-monospace, monospace";
3023        font-size: var!(font-base);
3024        font-weight: "600";
3025        color: var!(accent);
3026        padding: format!("1px {}", var!(space-sm));
3027    }
3028
3029    pub c_binding_typed_prop_group {
3030        display: "flex";
3031        align-items: "center";
3032        gap: var!(space-sm);
3033    }
3034
3035    pub c_binding_typed_warning {
3036        font-size: var!(font-base);
3037        font-weight: "500";
3038        color: var!(foreground);
3039        margin-bottom: "0px";
3040    }
3041
3042    pub c_binding_form_label {
3043        display: "block";
3044        color: "inherit";
3045        font-weight: "500";
3046        font-size: var!(font-base);
3047    }
3048
3049    pub c_binding_demo_text {
3050        color: "inherit";
3051        margin: "0px"
3052    }
3053
3054    pub c_binding_compact_button {
3055        display: "inline-flex";
3056        justify-content: "center";
3057        align-items: "center";
3058        height: "42px";
3059        padding: format!("0px {}", var!(space-md));
3060        background: var!(accent);
3061        color: var!(text-on-accent);
3062        border: format!("1px solid {}", var!(accent));
3063        cursor: "pointer";
3064        font-size: var!(font-sm);
3065        font-weight: "600";
3066        outline: "none";
3067        white-space: "nowrap";
3068        user-select: "none";
3069        -webkit-user-select: "none";
3070        box-sizing: "border-box";
3071        :hover {
3072            background: var!(accent);
3073        }
3074        :focus-visible {
3075            outline: "none";
3076        }
3077        :active {
3078            background: var!(accent);
3079            color: var!(text-on-accent);
3080            border-color: var!(accent);
3081        }
3082    }
3083
3084    // ═══════════════════════════════════════════════════════════════════════════
3085    // Custom Attrs - Dynamic Style
3086    // ═══════════════════════════════════════════════════════════════════════════
3087
3088    pub c_attrs_dynamic_demo(prop_key: &str, prop_value: &str) {
3089        {
3090            prop_key
3091        }
3092        : prop_value;
3093        // No layout defaults: this class lives on a `<p>` whose own margin /
3094        // spacing is controlled by its parent's typography rules, and pinning
3095        // any colour here would shadow the user-supplied dynamic property.
3096        // Users are expected to set `color` / `background` / `font-*` /
3097        // etc. via the two CSS Property Key / Value inputs above; whatever
3098        // they type becomes the literal CSS rule applied to the paragraph.
3099    }
3100
3101    // ═══════════════════════════════════════════════════════════════════════════
3102    // Dynamic Component Demo
3103    // ═══════════════════════════════════════════════════════════════════════════
3104
3105    pub c_dynamic_component_tab_bar {
3106        display: "flex";
3107        flex-wrap: "wrap";
3108        gap: var!(gap-element);
3109        margin-bottom: var!(gap-component);
3110    }
3111
3112    pub c_dynamic_component_panel {
3113        display: "block";
3114        min-height: var!(min-height-sm);
3115        margin-top: var!(gap-component);
3116    }
3117
3118    // ═══════════════════════════════════════════════════════════════════════════
3119    // Virtual List
3120    // ═══════════════════════════════════════════════════════════════════════════
3121
3122    pub c_virtual_list_status {
3123        display: "flex";
3124        gap: var!(gap-component);
3125        padding: format!("{} 0px", var!(gap-component));
3126        flex-wrap: "nowrap";
3127        overflow: "hidden";
3128        text-overflow: "ellipsis";
3129        white-space: "nowrap";
3130        @media ((max-width: 767px)) {
3131            gap: var!(gap-component-mobile);
3132        }
3133    }
3134
3135    pub c_virtual_list_status_item {
3136        font-size: var!(font-base);
3137        color: "inherit";
3138        overflow: "hidden";
3139        text-overflow: "ellipsis";
3140        white-space: "nowrap";
3141    }
3142
3143    pub c_virtual_list_status_value {
3144        font-weight: "700";
3145        color: var!(accent);
3146        font-family: "ui-monospace, monospace";
3147    }
3148
3149    pub c_virtual_list_container {
3150        flex: "1";
3151        height: "666px";
3152        max-height: "666px";
3153        overflow-y: "auto";
3154    }
3155
3156    pub c_virtual_list_card {
3157        flex: "1";
3158        padding: var!(space-xl);
3159        color: var!(foreground);
3160        display: "flex";
3161        flex-direction: "column";
3162        @media ((max-width: 767px)) {
3163            padding: var!(space-lg);
3164        }
3165    }
3166
3167    pub c_virtual_list_row {
3168        display: "flex";
3169        align-items: "center";
3170        gap: var!(space-lg);
3171        height: "100%";
3172        box-sizing: "border-box";
3173    }
3174
3175    pub c_virtual_list_row_index {
3176        min-width: "36px";
3177        font-size: var!(font-sm);
3178        font-weight: "600";
3179        color: var!(accent);
3180        font-family: "ui-monospace, monospace";
3181        flex-shrink: "0";
3182        display: "flex";
3183        align-items: "center";
3184    }
3185
3186    pub c_virtual_list_row_label {
3187        font-size: var!(font-base);
3188        font-weight: "500";
3189        color: "inherit";
3190        min-width: "120px";
3191        flex-shrink: "0";
3192        overflow: "hidden";
3193        text-overflow: "ellipsis";
3194        white-space: "nowrap";
3195        display: "flex";
3196        align-items: "center";
3197    }
3198
3199    pub c_virtual_list_row_description {
3200        font-size: var!(font-base);
3201        color: "inherit";
3202        opacity: "1";
3203        overflow: "hidden";
3204        text-overflow: "ellipsis";
3205        white-space: "nowrap";
3206        flex: "1";
3207        display: "flex";
3208        align-items: "center";
3209    }
3210
3211    // ═══════════════════════════════════════════════════════════════════════════
3212    // Unified Layout Primitives
3213    // ═══════════════════════════════════════════════════════════════════════════
3214
3215    pub c_element_stack {
3216        display: "flex";
3217        flex-direction: "column";
3218        gap: var!(gap-element);
3219    }
3220
3221    pub c_switcher {
3222        display: "flex";
3223        gap: var!(gap-component);
3224        flex-wrap: "wrap";
3225        @media ((max-width: 767px)) {
3226            flex-direction: "column";
3227            gap: var!(gap-component-mobile);
3228        }
3229    }
3230
3231    pub c_switcher_col {
3232        flex: "1";
3233        min-width: "200px";
3234        @media ((max-width: 767px)) {
3235            min-width: "100%";
3236        }
3237    }
3238
3239    // ═══════════════════════════════════════════════════════════════════════════
3240    // Unified Description / Hint Text
3241    // ═══════════════════════════════════════════════════════════════════════════
3242
3243    pub c_hint {
3244        color: "inherit";
3245        opacity: "1";
3246        font-size: var!(font-base);
3247        margin-bottom: var!(gap-component);
3248    }
3249
3250    // ═══════════════════════════════════════════════════════════════════════════
3251    // Network Demo
3252    // ═══════════════════════════════════════════════════════════════════════════
3253
3254    pub c_net_messages_empty {
3255        color: "inherit";
3256        opacity: "1";
3257        padding: var!(space-xl);
3258        text-align: "center";
3259        font-size: var!(font-base);
3260    }
3261
3262    pub c_net_messages_list {
3263        display: "flex";
3264        flex-direction: "column";
3265        gap: var!(space-xs);
3266    }
3267
3268    pub c_net_message_item {
3269        display: "flex";
3270        align-items: "baseline";
3271        gap: var!(gap-element);
3272        justify-content: "space-between";
3273    }
3274
3275    pub c_net_message_index {
3276        color: var!(accent);
3277        font-size: var!(font-sm);
3278        font-weight: "600";
3279        white-space: "nowrap";
3280        flex-shrink: "0";
3281    }
3282
3283    pub c_net_message_data {
3284        color: "inherit";
3285        font-size: var!(font-base);
3286        word-break: "break-all";
3287        overflow-wrap: "break-word";
3288        flex: "1";
3289        min-width: "0";
3290    }
3291
3292    // ═══════════════════════════════════════════════════════════════════════════
3293    // WebSocket Demo
3294    // ═══════════════════════════════════════════════════════════════════════════
3295
3296    pub c_ws_message_input {
3297        width: "100%";
3298        flex: "1";
3299        height: "42px";
3300        padding: format!("0px {}", var!(space-lg));
3301        color: var!(foreground);
3302        border: format!("1px solid {}", var!(border));
3303        font-size: var!(font-base);
3304        line-height: "normal";
3305        box-sizing: "border-box";
3306        outline: "none";
3307        appearance: "none";
3308        -webkit-appearance: "none";
3309        -moz-appearance: "none";
3310        vertical-align: "middle";
3311        :hover {
3312            border-color: var!(accent);
3313            background: var!(accent-muted);
3314        }
3315        :focus {
3316            outline: "none";
3317            border-color: var!(accent);
3318            background: var!(accent-muted);
3319        }
3320    }
3321
3322    pub c_ws_message_time {
3323        color: var!(foreground);
3324        font-size: var!(font-sm);
3325        white-space: "nowrap";
3326        flex-shrink: "0";
3327        margin-left: "auto";
3328    }
3329
3330    // ═══════════════════════════════════════════════════════════════════════════
3331    // Sticky & CSS Effects Demo
3332    // ═══════════════════════════════════════════════════════════════════════════
3333
3334    // ═══════════════════════════════════════════════════════════════════════════
3335    // Home Page — Section
3336    // ═══════════════════════════════════════════════════════════════════════════
3337
3338    pub c_home {
3339        position: "relative";
3340        text-align: "center";
3341        margin-bottom: var!(space-xl);
3342        flex: "1";
3343        display: "flex";
3344        flex-direction: "column";
3345        justify-content: "center";
3346        @media ((max-width: 767px)) {
3347            margin-bottom: var!(space-lg);
3348            flex: "0 0 auto";
3349            justify-content: "flex-start";
3350        }
3351    }
3352
3353    pub c_home_content {
3354        position: "relative";
3355        z-index: "1";
3356    }
3357
3358    pub c_home_badge_row {
3359        display: "inline-flex";
3360        align-items: "center";
3361        gap: var!(space-sm);
3362        margin-bottom: var!(space-md);
3363    }
3364
3365    pub c_home_badge {
3366        display: "inline-flex";
3367        justify-content: "center";
3368        align-items: "center";
3369        padding: format!("{} {}", var!(space-xs), var!(space-sm));
3370        color: var!(accent);
3371        font-size: var!(font-xs);
3372        font-weight: "600";
3373        letter-spacing: "0.05em";
3374        border: format!("1px solid {}", var!(accent));
3375    }
3376
3377    pub c_home_title {
3378        font-size: var!(font-5xl);
3379        font-weight: "800";
3380        letter-spacing: "-0.03em";
3381        margin: "0px";
3382        color: var!(foreground);
3383        margin-bottom: var!(space-xs);
3384        @media ((max-width: 767px)) {
3385            font-size: var!(font-4xl);
3386        }
3387    }
3388
3389    pub c_home_subtitle {
3390        font-size: var!(font-lg);
3391        color: var!(foreground);
3392        margin: "0px auto";
3393        max-width: "520px";
3394        margin-bottom: var!(space-lg);
3395        @media ((max-width: 767px)) {
3396            font-size: var!(font-base);
3397        }
3398    }
3399
3400    pub c_home_actions {
3401        display: "flex";
3402        gap: var!(space-md);
3403        justify-content: "center";
3404        flex-wrap: "wrap";
3405    }
3406
3407    pub c_home_btn_primary {
3408        display: "inline-flex";
3409        justify-content: "center";
3410        align-items: "center";
3411        gap: var!(space-sm);
3412        padding: format!("{} {}", var!(space-sm), var!(space-2xl));
3413        background: var!(accent);
3414        color: var!(text-on-accent);
3415        font-size: var!(font-base);
3416        font-weight: "600";
3417        text-decoration: "none";
3418        border: "1.5px solid transparent";
3419        cursor: "pointer";
3420        letter-spacing: "0.01em";
3421        vertical-align: "middle";
3422        min-height: var!(min-height-sm);
3423        :focus-visible {
3424            outline: "none";
3425        }
3426        :active {
3427            background: var!(accent);
3428            color: var!(text-on-accent);
3429            border-color: "1.5px solid transparent";
3430        }
3431    }
3432
3433    pub c_home_btn_secondary {
3434        display: "inline-flex";
3435        justify-content: "center";
3436        align-items: "center";
3437        gap: var!(space-sm);
3438        padding: format!("{} {}", var!(space-sm), var!(space-2xl));
3439        color: var!(accent);
3440        font-size: var!(font-base);
3441        font-weight: "600";
3442        text-decoration: "none";
3443        border: format!("1.5px solid {}", var!(accent));
3444        cursor: "pointer";
3445        letter-spacing: "0.01em";
3446        vertical-align: "middle";
3447        min-height: var!(min-height-sm);
3448        :focus-visible {
3449            outline: "none";
3450        }
3451        :active {
3452            background: "transparent";
3453            color: var!(accent);
3454            border-color: var!(accent);
3455        }
3456    }
3457
3458    // ═══════════════════════════════════════════════════════════════════════════
3459    // Home Page — Stats Row
3460    // ═══════════════════════════════════════════════════════════════════════════
3461
3462    pub c_home_stats {
3463        display: "grid";
3464        grid-template-columns: "repeat(4, 1fr)";
3465        gap: var!(space-md);
3466        margin-bottom: var!(space-xl);
3467        @media ((max-width: 767px)) {
3468            grid-template-columns: "repeat(2, 1fr)";
3469            gap: var!(space-sm);
3470        }
3471    }
3472
3473    pub c_home_stat_card {
3474        display: "flex";
3475        flex-direction: "column";
3476        align-items: "center";
3477        justify-content: "center";
3478        gap: var!(space-xs);
3479    }
3480
3481    pub c_home_stat_icon {
3482        font-size: var!(font-2xl);
3483    }
3484
3485    pub c_home_stat_value {
3486        font-size: var!(font-xl);
3487        font-weight: "800";
3488        color: var!(foreground);
3489        letter-spacing: "-0.01em";
3490    }
3491
3492    pub c_home_stat_label {
3493        font-size: var!(font-sm);
3494        color: var!(muted-foreground);
3495        font-weight: "500";
3496    }
3497
3498    // ═══════════════════════════════════════════════════════════════════════════
3499    // Home Page — Section & Feature Cards
3500    // ═══════════════════════════════════════════════════════════════════════════
3501
3502    pub c_home_section_title {
3503        font-size: var!(font-2xl);
3504        font-weight: "700";
3505        color: var!(foreground);
3506        margin: "0px";
3507        margin: format!("{} 0px", var!(gap-component));
3508        letter-spacing: "-0.02em";
3509    }
3510
3511    pub c_home_section_desc {
3512        font-size: var!(font-base);
3513        color: var!(foreground);
3514        margin: "0px";
3515        margin-bottom: var!(space-2xl);
3516    }
3517
3518    pub c_home_feature_grid {
3519        display: "grid";
3520        grid-template-columns: "repeat(2, 1fr)";
3521        gap: var!(space-md);
3522        @media ((max-width: 767px)) {
3523            grid-template-columns: "1fr";
3524        }
3525    }
3526
3527    pub c_feature_card {
3528        display: "flex";
3529        flex-direction: "column";
3530        gap: var!(space-sm);
3531        padding: "0px";
3532        overflow: "hidden";
3533    }
3534
3535    pub c_feature_header {
3536        display: "flex";
3537        align-items: "center";
3538        gap: var!(space-sm);
3539    }
3540
3541    pub c_feature_icon {
3542        font-size: var!(font-2xl);
3543        display: "flex";
3544        align-items: "center";
3545        justify-content: "center";
3546        line-height: "1";
3547        flex-shrink: "0";
3548    }
3549
3550    pub c_feature_name {
3551        font-size: var!(font-lg);
3552        font-weight: "600";
3553        color: var!(foreground);
3554        margin: "0px";
3555        overflow: "hidden";
3556        text-overflow: "ellipsis";
3557        white-space: "nowrap";
3558    }
3559
3560    pub c_feature_desc {
3561        font-size: var!(font-sm);
3562        color: var!(foreground);
3563        margin: "0px";
3564    }
3565
3566    // ═══════════════════════════════════════════════════════════════════════════
3567    // Global Utilities
3568    // ═══════════════════════════════════════════════════════════════════════════
3569
3570    // Dev-only readouts produced by `euv_debug`. The base wrapper
3571    // establishes the inline-flex layout so the label and the value
3572    // share a baseline; the `code` / `pre` value elements apply
3573    // monospace font and wrap behaviour for the two modes
3574    // (`expanded: false` = single-line `code`, `expanded: true` =
3575    // multi-line `pre`).
3576    pub c_debug {
3577        display: "flex";
3578        flex-direction: "row";
3579        align-items: "baseline";
3580        gap: var!(space-sm);
3581        padding: var!(space-xs);
3582        border: format!("1px dashed {}", var!(accent-muted));
3583        border-radius: var!(radius-sm);
3584        background: var!(surface-muted);
3585        font-family: "ui-monospace, SFMono-Regular, monospace";
3586        font-size: var!(font-sm);
3587        color: var!(foreground);
3588        margin: format!("{} 0px", var!(space-xs));
3589    }
3590
3591    pub c_debug_label {
3592        font-weight: "600";
3593        color: var!(accent);
3594        flex-shrink: "0";
3595    }
3596
3597    pub c_debug_value {
3598        font-family: "ui-monospace, SFMono-Regular, monospace";
3599        color: var!(foreground);
3600        margin: "0px";
3601    }
3602
3603    // ═══════════════════════════════════════════════════════════════════════════
3604    // euv_navbar
3605    // ═══════════════════════════════════════════════════════════════════════════
3606
3607    pub c_euv_navbar {
3608        position: "fixed";
3609        top: "0px";
3610        left: "0px";
3611        right: "0px";
3612        height: "56px";
3613        display: "flex";
3614        align-items: "center";
3615        gap: var!(gap-element);
3616        padding: format!("0px {}", var!(edge-gutter));
3617        border-bottom: format!("1px solid {}", var!(border));
3618        background: var!(background);
3619        z-index: "100";
3620        @media ((max-width: 767px)) {
3621            padding: format!("0px {}", var!(edge-gutter-mobile));
3622        }
3623    }
3624
3625    pub c_euv_navbar_brand {
3626        display: "flex";
3627        align-items: "center";
3628        gap: var!(gap-element);
3629        font-size: var!(font-lg);
3630        font-weight: "700";
3631        letter-spacing: "-0.02em";
3632        color: var!(foreground);
3633        cursor: "pointer";
3634        flex-shrink: "0";
3635    }
3636
3637    pub c_euv_navbar_logo {
3638        width: "32px";
3639        height: "32px";
3640        display: "flex";
3641        align-items: "center";
3642        justify-content: "center";
3643        background: var!(accent);
3644        color: var!(text-on-accent);
3645        font-size: var!(font-lg);
3646        flex-shrink: "0";
3647    }
3648
3649    pub c_euv_navbar_links {
3650        display: "flex";
3651        align-items: "center";
3652        gap: var!(gap-section);
3653        margin-left: "auto";
3654        @media ((max-width: 767px)) {
3655            display: "none";
3656        }
3657    }
3658
3659    pub c_euv_navbar_link {
3660        font-size: var!(font-sm);
3661        font-weight: "500";
3662        color: var!(foreground);
3663        padding: format!("{} {}", var!(space-xs), var!(space-sm));
3664        border-bottom: "2px solid transparent";
3665        cursor: "pointer";
3666        :hover {
3667            color: var!(accent);
3668        }
3669    }
3670
3671    pub c_euv_navbar_link_active {
3672        font-size: var!(font-sm);
3673        font-weight: "600";
3674        color: var!(accent);
3675        padding: format!("{} {}", var!(space-xs), var!(space-sm));
3676        border-bottom: format!("2px solid {}", var!(accent));
3677        cursor: "pointer";
3678    }
3679
3680    pub c_euv_navbar_actions {
3681        display: "flex";
3682        align-items: "center";
3683        gap: var!(gap-element);
3684        margin-left: var!(gap-section);
3685        @media ((max-width: 767px)) {
3686            margin-left: "auto";
3687        }
3688    }
3689
3690    pub c_euv_navbar_icon_button {
3691        width: "36px";
3692        height: "36px";
3693        display: "flex";
3694        align-items: "center";
3695        justify-content: "center";
3696        border: format!("1px dashed {}", var!(border));
3697        cursor: "pointer";
3698        font-size: var!(font-base);
3699        :hover {
3700            background: var!(accent-muted);
3701        }
3702    }
3703
3704    pub c_euv_navbar_menu_button {
3705        display: "none";
3706        width: "40px";
3707        height: "40px";
3708        align-items: "center";
3709        justify-content: "center";
3710        font-size: var!(font-xl);
3711        cursor: "pointer";
3712        transition: format!("background {} {}", var!(duration-fast), var!(ease-out));
3713        @media ((max-width: 767px)) {
3714            display: "flex";
3715        }
3716    }
3717
3718    pub c_euv_navbar_menu_button_active {
3719        display: "none";
3720        width: "40px";
3721        height: "40px";
3722        align-items: "center";
3723        justify-content: "center";
3724        font-size: var!(font-xl);
3725        cursor: "pointer";
3726        background: var!(accent-muted);
3727        transition: format!("background {} {}", var!(duration-fast), var!(ease-out));
3728        @media ((max-width: 767px)) {
3729            display: "flex";
3730        }
3731    }
3732
3733    // ═══════════════════════════════════════════════════════════════════════════
3734    // euv_dropdown
3735    // ═══════════════════════════════════════════════════════════════════════════
3736
3737    pub c_euv_dropdown {
3738        position: "relative";
3739    }
3740
3741    pub c_euv_dropdown_menu {
3742        position: "absolute";
3743        top: "44px";
3744        right: "0px";
3745    /* `width: 100%` instead of `min-width: 140px` so the menu
3746                                                                                                                                                           matches the dropdown container (and therefore the
3747                                                                                                                                                           trigger button) width exactly. With only `min-width`,
3748                                                                                                                                                           a trigger wider than 140px (e.g. the 206px-wide
3749                                                                                                                                                           nav-column locale switcher button) leaves a large
3750                                                                                                                                                           empty gap on the left of the menu, since `right: 0`
3751                                                                                                                                                           anchors only the right edge to the container. With
3752                                                                                                                                                           `width: 100%`, the menu's left edge lines up with the
3753                                                                                                                                                           trigger's left edge. The default minimum content width
3754                                                                                                                                                           is still guaranteed by the inner items' own padding,
3755                                                                                                                                                           so we keep the rule without an explicit min. */
3756        width: "100%";
3757        background: var!(background);
3758        border: format!("1px solid {}", var!(border));
3759        box-shadow: var!(shadow-accent-lg);
3760        flex-direction: "column";
3761        z-index: "101";
3762    }
3763
3764    pub c_euv_dropdown_menu_open {
3765        display: "flex";
3766    }
3767
3768    pub c_euv_dropdown_menu_closed {
3769        display: "none";
3770    }
3771
3772    pub c_euv_dropdown_item {
3773        padding: format!("{} {}", var!(space-sm), var!(space-lg));
3774        font-size: var!(font-sm);
3775        text-align: "left";
3776        cursor: "pointer";
3777        // Hover mirrors the sidebar's affordance (see `c_euv_sidebar_link`):
3778        // an inset 3px bar painted inside the padding box, which never
3779        // participates in layout and therefore never shifts the label. A
3780        // translucent wash is deliberately NOT used — `accent-muted` resolves
3781        // to the same value as `background` in the monochrome palette
3782        // (white on light, black on dark), so a background there is
3783        // invisible. `color-mix` derives the wash from the actual text colour
3784        // so it reads in both themes.
3785        :hover {
3786            background: format!("color-mix(in srgb, {} 8%, transparent)", var!(foreground));
3787            box-shadow: format!("inset 3px 0 0 0 {}", var!(foreground));
3788        }
3789    }
3790
3791    pub c_euv_dropdown_item_active {
3792        padding: format!("{} {}", var!(space-sm), var!(space-lg));
3793        font-size: var!(font-sm);
3794        text-align: "left";
3795        cursor: "pointer";
3796        font-weight: "600";
3797        // The selected item wears the accent fill and the text colour that
3798        // reads on top of it, the same pairing the sidebar's `_active` link
3799        // uses. The inset bar is dropped: the full-width fill already carries
3800        // the current-page signal, and a bar in the same monochrome accent
3801        // would be invisible against it.
3802        background: var!(accent);
3803        color: var!(text-on-accent);
3804        :hover {
3805            background: var!(accent);
3806            color: var!(text-on-accent);
3807            box-shadow: "none";
3808        }
3809    }
3810
3811    // ═══════════════════════════════════════════════════════════════════════════
3812    // euv_sidebar
3813    // ═══════════════════════════════════════════════════════════════════════════
3814
3815    pub c_euv_sidebar_group {
3816        margin-bottom: var!(space-xs);
3817    }
3818
3819    pub c_euv_sidebar_group_title {
3820        display: "flex";
3821        align-items: "center";
3822        justify-content: "space-between";
3823        width: "100%";
3824        // Symmetric horizontal padding so the text and the dashed border of
3825        // any nested children line up on the left edge (see sidebar_children
3826        // below). Left padding equals `border-left-width + padding-left` of
3827        // the children container — that's the "text and the dashed border
3828        // share the same x" requirement.
3829        padding: format!("{} {}", var!(space-md), var!(space-md));
3830        font-size: var!(font-base);
3831        font-weight: "400";
3832        cursor: "pointer";
3833        text-align: "left";
3834        // Hover: inset 3px shadow bar between the dashed tree guide and the
3835        // title text. Using `box-shadow inset` instead of a real border
3836        // avoids any layout change so the text x-position never moves on
3837        // hover (see comment on `c_euv_sidebar_link:hover`).
3838        :hover {
3839            box-shadow: format!("inset 3px 0 0 0 {}", var!(foreground));
3840        }
3841    }
3842
3843    pub c_euv_sidebar_group_title_active {
3844        background: var!(accent);
3845        color: var!(text-on-accent);
3846        font-weight: "600";
3847        :hover {
3848            box-shadow: "none";
3849        }
3850    }
3851
3852    pub c_euv_sidebar_group_arrow {
3853        font-size: var!(font-xs);
3854        color: var!(muted-foreground);
3855        transition: format!("transform {} {}", var!(duration-fast), var!(ease-out));
3856    }
3857
3858    pub c_euv_sidebar_group_arrow_open {
3859        transform: "rotate(90deg)";
3860    }
3861
3862    pub c_euv_sidebar_group_arrow_active {
3863        color: var!(text-on-accent);
3864    }
3865
3866    pub c_euv_sidebar_children {
3867        display: "flex";
3868        flex-direction: "column";
3869        // Compact nesting: keep the dashed tree guide on the left of every
3870        // nesting level, but trim its indent so the child's text sits just
3871        // to the right of the dashed border instead of a full 33px gutter
3872        // away (the old `margin-left: 20px` + `padding-left: 12px` setup).
3873        // The numbers chosen (margin 8 + border 1 + padding 8 = 17px) are
3874        // large enough to read as a distinct level but small enough that
3875        // three-deep trees still fit in a 248–320px sidebar.
3876        margin-left: var!(space-sm);
3877        padding-left: var!(space-sm);
3878        border-left: format!("1px dashed {}", var!(border));
3879        animation: format!("euv-fade-in {} {}", var!(duration-normal), var!(ease-out));
3880    }
3881
3882    pub c_euv_sidebar_link {
3883        display: "block";
3884        padding: format!("{} {}", var!(space-md), var!(space-md));
3885        font-size: var!(font-base);
3886        color: var!(foreground);
3887        font-weight: "400";
3888        cursor: "pointer";
3889        // Hover: paint a 3px solid bar *between* the dashed tree guide and
3890        // the link's text. We use `inset box-shadow` rather than a real
3891        // `border-left` because borders participate in the box's layout
3892        // (they grow the border-edge and require compensating padding to
3893        // keep the text x-position stable — and `calc(12px + 3px - 3px)`
3894        // rounds inconsistently across browsers, causing sub-pixel text
3895        // shifts on hover). An inset shadow is painted *inside* the
3896        // existing padding box without changing layout, so the text never
3897        // moves. The dashed parent border is also untouched.
3898        :hover {
3899            box-shadow: format!("inset 3px 0 0 0 {}", var!(foreground));
3900        }
3901    }
3902
3903    pub c_euv_sidebar_link_active {
3904        display: "block";
3905        padding: format!("{} {}", var!(space-md), var!(space-md));
3906        font-size: var!(font-base);
3907        background: var!(accent);
3908        color: var!(text-on-accent);
3909        font-weight: "600";
3910        cursor: "pointer";
3911        // Active link: when the cursor is over it, the accent background
3912        // must dominate. Drop the inset bar entirely so the accent fill
3913        // carries the visual weight; on dark accent, an inset bar in the
3914        // foreground color is invisible and only competes for the eye's
3915        // focus. The accent fill + bold text already announce "you are
3916        // here".
3917        :hover {
3918            box-shadow: "none";
3919        }
3920    }
3921
3922    // ═══════════════════════════════════════════════════════════════════════════
3923    // euv_toc
3924    // ═══════════════════════════════════════════════════════════════════════════
3925
3926    pub c_euv_toc {
3927        // The outer `c_euv_doc_toc` column is already sticky in
3928        // `c_app_main`'s scroll context — adding another sticky offset here
3929        // would double the offset and the TOC would slide past the top of
3930        // the scrollable area instead of staying pinned. Keep the inner
3931        // toc purely as a layout container.
3932        display: "flex";
3933        flex-direction: "column";
3934        gap: var!(space-xs);
3935        border-left: format!("1px solid {}", var!(border));
3936        padding-left: var!(space-lg);
3937    }
3938
3939    pub c_euv_toc_title {
3940        font-size: var!(font-xs);
3941        font-weight: "700";
3942        text-transform: "uppercase";
3943        letter-spacing: "0.08em";
3944        color: var!(muted-foreground);
3945        margin-bottom: var!(space-xs);
3946    }
3947
3948    pub c_euv_toc_link {
3949        font-size: var!(font-sm);
3950        color: var!(muted-foreground);
3951        cursor: "pointer";
3952        line-height: "1.5";
3953        :hover {
3954            color: var!(accent);
3955        }
3956    }
3957
3958    pub c_euv_toc_link_nested {
3959        c_euv_toc_link();
3960        padding-left: var!(space-lg);
3961    }
3962
3963    // ═══════════════════════════════════════════════════════════════════════════
3964    // euv_pagination
3965    // ═══════════════════════════════════════════════════════════════════════════
3966
3967    pub c_euv_pagination {
3968        // CSS grid with two equal columns gives us perfect 50/50 widths
3969        // regardless of the link content length, which flex with `1 1
3970        // auto` cannot (each link starts at its own content size). The
3971        // mobile breakpoint stacks the grid to a single column so each
3972        // link sizes to its content.
3973        display: "grid";
3974        grid-template-columns: "1fr 1fr";
3975        gap: var!(gap-component);
3976        // ~`space-2xl` (1.5rem) above the pagination — comfortable
3977        // breathing room without a huge gap before prev/next. The original
3978        // `space-4xl` (2.5rem) margin was doubled by a `padding-top` in the
3979        // docs app override, leaving ~100px of empty space above the
3980        // pagination boxes which made the page feel bottom-heavy.
3981        margin-top: var!(space-2xl);
3982        // `min-width: 0` lets prev/next text actually use ellipsis when the
3983        // container is narrow — without it the grid track blows out the row.
3984        min-width: "0px";
3985        @media ((max-width: 767px)) {
3986            grid-template-columns: "minmax(0, 1fr)";
3987        }
3988    }
3989
3990    pub c_euv_pagination_link {
3991        // `min-width: 0` lets long labels ellipsize on the desktop row
3992        // layout. `overflow: hidden` is required to actually apply ellipsis
3993        // when content is wider than the link.
3994        min-width: "0px";
3995        border: format!("1px solid {}", var!(border));
3996        padding: var!(space-lg);
3997        cursor: "pointer";
3998        display: "flex";
3999        flex-direction: "column";
4000        gap: var!(space-2xs);
4001        overflow: "hidden";
4002        :hover {
4003            border-color: var!(accent);
4004        }
4005    }
4006
4007    pub c_euv_pagination_label {
4008        font-size: var!(font-xs);
4009        color: var!(muted-foreground);
4010        text-transform: "uppercase";
4011        letter-spacing: "0.08em";
4012    }
4013
4014    pub c_euv_pagination_text {
4015        font-size: var!(font-base);
4016        font-weight: "600";
4017        color: var!(accent);
4018        // Ellipsize when the link is too narrow for the page title. The
4019        // outer `.c_euv_pagination_link` already sets `overflow: hidden`
4020        // and `min-width: 0`, so a single `text-overflow: ellipsis` here
4021        // is enough — without `white-space: nowrap` the text wraps to
4022        // multiple lines and the ellipsis never kicks in.
4023        white-space: "nowrap";
4024        overflow: "hidden";
4025        text-overflow: "ellipsis";
4026        min-width: "0px";
4027    }
4028
4029    pub c_euv_pagination_next {
4030        text-align: "right";
4031    }
4032
4033    pub c_euv_pagination_spacer {
4034        flex: "1";
4035    }
4036
4037    // ═══════════════════════════════════════════════════════════════════════════
4038    // euv_drawer
4039    // ═══════════════════════════════════════════════════════════════════════════
4040
4041    pub c_euv_drawer_overlay {
4042        position: "fixed";
4043        top: "0px";
4044        left: "0px";
4045        right: "0px";
4046        bottom: "0px";
4047        background: var!(bg-overlay);
4048        z-index: "200";
4049        transition: format!("opacity {} {}, visibility {} {}", var!(duration-overlay), var!(ease-out), var!(duration-overlay), var!(ease-out));
4050    }
4051
4052    pub c_euv_drawer_overlay_open {
4053        opacity: "1";
4054        visibility: "visible";
4055    }
4056
4057    pub c_euv_drawer_overlay_closed {
4058        opacity: "0";
4059        visibility: "hidden";
4060    }
4061
4062    pub c_euv_drawer {
4063        position: "fixed";
4064        top: "0px";
4065        left: "0px";
4066        bottom: "0px";
4067        width: "260px";
4068        background: var!(background);
4069        border-right: format!("1px solid {}", var!(border));
4070        z-index: "201";
4071        overflow-y: "auto";
4072        padding: var!(space-xl);
4073        transition: format!("transform {} {}, visibility {} {}", var!(duration-normal), var!(ease-out), var!(duration-normal), var!(ease-out));
4074    }
4075
4076    pub c_euv_drawer_open {
4077        transform: "translateX(0px)";
4078        visibility: "visible";
4079    }
4080
4081    pub c_euv_drawer_closed {
4082        transform: "translateX(-100%)";
4083        visibility: "hidden";
4084    }
4085
4086    // ═══════════════════════════════════════════════════════════════════════════
4087    // euv_markdown / euv_footer
4088    // ═══════════════════════════════════════════════════════════════════════════
4089
4090    pub c_euv_markdown {
4091        width: "100%";
4092        min-width: "0px";
4093    }
4094
4095    pub c_euv_footer {
4096        // Footer sits at the natural end of the article column. The user
4097        // reaches it by scrolling to the bottom of the article — no sticky
4098        // or fixed positioning. This matches the desktop behavior and
4099        // Avoid any layout interference on mobile (where a sticky footer
4100        // would overlap the last lines of content while scrolling).
4101        // `space-2xl` (1.5rem) above the footer matches the gap between
4102        // article and pagination, keeping a consistent rhythm in the
4103        // tail block. The previous `space-7xl` (5rem) was far beyond the
4104        // typography scale and made the footer feel detached from the
4105        // pagination.
4106        margin-top: var!(space-2xl);
4107        // `space-lg` top/bottom (1rem) — enough padding for the dashed
4108        // border to breathe without pushing the text far from the rule.
4109        padding: format!("{} 0px", var!(space-lg));
4110        border-top: format!("1px dashed {}", var!(border));
4111        text-align: "center";
4112        font-size: var!(font-sm);
4113        color: var!(muted-foreground);
4114    }
4115
4116    // ═══════════════════════════════════════════════════════════════════════════
4117    // euv_result / euv_doc_layout
4118    // ═══════════════════════════════════════════════════════════════════════════
4119
4120    pub c_euv_result {
4121        display: "flex";
4122        flex-direction: "column";
4123        align-items: "center";
4124        justify-content: "center";
4125        text-align: "center";
4126        gap: var!(space-md);
4127        padding: format!("{} {}", var!(space-4xl), var!(space-md));
4128        min-height: "50vh";
4129    }
4130
4131    pub c_euv_result_code {
4132        font-size: var!(font-6xl);
4133        font-weight: "700";
4134        line-height: "1";
4135        letter-spacing: "-0.02em";
4136    }
4137
4138    pub c_euv_result_title {
4139        font-size: var!(font-2xl);
4140        font-weight: "600";
4141        margin: "0px";
4142    }
4143
4144    pub c_euv_result_description {
4145        color: var!(muted-foreground);
4146        margin: "0px";
4147    }
4148
4149    pub c_euv_result_actions {
4150        display: "flex";
4151        gap: var!(space-md);
4152        margin-top: var!(space-lg);
4153    }
4154
4155    pub c_euv_doc_layout {
4156        display: "flex";
4157        gap: var!(space-4xl);
4158        width: "100%";
4159        min-width: "0px";
4160        max-width: "1080px";
4161        margin: "0px auto";
4162    }
4163
4164    pub c_euv_doc_content {
4165        // Two parallel children — the article body and the
4166        // `c_euv_doc_tail` wrapper (pagination + footer). The flex column
4167        // distributes them at the two ends:
4168        //   - when the article is shorter than the column's intrinsic
4169        //     height, `justify-content: space-between` pushes the tail to
4170        //     the bottom edge;
4171        //   - when the article is longer, the tail sits right after the
4172        //     article in normal flow (because content height exceeds
4173        //     min-height, there's no remaining space to distribute).
4174        // `min-height: 100vh` stretches the column to at least one full
4175        // viewport tall — without this, a short article would leave the
4176        // tail directly under the body instead of at the bottom of the
4177        // viewport.
4178        flex: "1";
4179        min-width: "0px";
4180        max-width: var!(content-max-width);
4181        display: "flex";
4182        flex-direction: "column";
4183        justify-content: "space-between";
4184        min-height: "100vh";
4185    }
4186
4187    pub c_euv_doc_tail {
4188        // Plain block wrapper that groups pagination + footer into one
4189        // flex child. With `display: contents` the wrapper would be
4190        // skipped and the two siblings would behave as direct children
4191        // of `c_euv_doc_content` — breaking the two-parallel-containers
4192        // contract that `justify-content: space-between` relies on.
4193        display: "block";
4194    }
4195
4196    pub c_euv_doc_toc {
4197        width: "200px";
4198        flex-shrink: "0";
4199        // Pin the TOC column to the viewport while the main content scrolls.
4200        // The sticky scroll container is `c_app_main` (the overflow:auto
4201        // wrapper), so `top: 0` keeps the TOC aligned with the top of the
4202        // scrollable area for the whole article. The column is left at its
4203        // natural flex stretch height (= the article's content height) so
4204        // the sticky range covers the whole main column — without the stretch
4205        // the column would shrink to its content height and the sticky would
4206        // disengage as soon as the TOC's bottom exits the viewport.
4207        position: "sticky";
4208        top: "0px";
4209        padding-top: var!(padding-main-top);
4210        @media ((max-width: 1100px)) {
4211            display: "none";
4212        }
4213    }
4214}