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