@motir/design-system 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/theme/AppearancePickers.js +10 -4
- package/dist/components/theme/AppearancePickers.js.map +1 -1
- package/dist/components/theme/StyleVignette.d.ts +41 -7
- package/dist/components/theme/StyleVignette.js +1 -0
- package/dist/components/theme/StyleVignette.js.map +1 -1
- package/dist/specimen/TokensSpecimen.js +1 -0
- package/dist/specimen/TokensSpecimen.js.map +1 -1
- package/package.json +1 -1
- package/theme.css +910 -587
package/theme.css
CHANGED
|
@@ -554,74 +554,88 @@
|
|
|
554
554
|
overrides `--el-*`, never `--color-*`, so reading `--el-*` here is what keeps
|
|
555
555
|
the glass orthogonal to the palette. The gradient is what the frosted panels
|
|
556
556
|
blur — without it, the blur is invisible. */
|
|
557
|
-
[data-style='glassmorphism']
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
557
|
+
@scope ([data-style='glassmorphism']) to ([data-style]) {
|
|
558
|
+
body {
|
|
559
|
+
background-image:
|
|
560
|
+
radial-gradient(
|
|
561
|
+
85% 80% at 6% -12%,
|
|
562
|
+
color-mix(in srgb, var(--el-accent) var(--glass-wash), transparent),
|
|
563
|
+
transparent 62%
|
|
564
|
+
),
|
|
565
|
+
radial-gradient(
|
|
566
|
+
80% 75% at 110% 4%,
|
|
567
|
+
color-mix(in srgb, var(--el-highlight) var(--glass-wash), transparent),
|
|
568
|
+
transparent 60%
|
|
569
|
+
),
|
|
570
|
+
radial-gradient(
|
|
571
|
+
95% 90% at 50% 120%,
|
|
572
|
+
color-mix(in srgb, var(--el-link) var(--glass-wash), transparent),
|
|
573
|
+
transparent 62%
|
|
574
|
+
),
|
|
575
|
+
radial-gradient(
|
|
576
|
+
60% 60% at 85% 95%,
|
|
577
|
+
color-mix(in srgb, var(--el-accent) var(--glass-wash), transparent),
|
|
578
|
+
transparent 60%
|
|
579
|
+
);
|
|
580
|
+
background-attachment: fixed;
|
|
581
|
+
}
|
|
580
582
|
}
|
|
581
583
|
|
|
582
584
|
/* Frosted container surfaces — cards & popovers float as translucent sheets. */
|
|
583
|
-
[data-style='glassmorphism'] [data-
|
|
584
|
-
[data-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
585
|
+
@scope ([data-style='glassmorphism']) to ([data-style]) {
|
|
586
|
+
[data-surface='card'],
|
|
587
|
+
[data-surface='popover'] {
|
|
588
|
+
/* The translucent fill lets the vibrant canvas through; the linear sheen is
|
|
589
|
+
the light raking across the glass (top-left → fading), the inset RIM is the
|
|
590
|
+
lit glass edge, and the soft drop makes the sheet FLOAT. White light is
|
|
591
|
+
palette-agnostic; the colour still comes only from the palette-derived
|
|
592
|
+
fill/border, so the axes stay disjoint. */
|
|
593
|
+
background-color: color-mix(in srgb, var(--el-page-bg) var(--glass-surface-alpha), transparent);
|
|
594
|
+
background-image: linear-gradient(150deg, var(--glass-sheen), transparent 55%);
|
|
595
|
+
border-color: color-mix(in srgb, var(--el-border) var(--glass-border-alpha), transparent);
|
|
596
|
+
box-shadow:
|
|
597
|
+
inset 0 1px 0 0 var(--glass-rim),
|
|
598
|
+
inset 0 0 0 1px rgba(255, 255, 255, 0.06),
|
|
599
|
+
0 8px 32px -8px rgba(15, 15, 15, 0.18);
|
|
600
|
+
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
|
|
601
|
+
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
|
|
602
|
+
}
|
|
599
603
|
}
|
|
600
604
|
|
|
601
605
|
/* Modal panel — a touch more opaque + a stronger blur (body-text AA + lift). */
|
|
602
|
-
[data-style='glassmorphism'] [data-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
606
|
+
@scope ([data-style='glassmorphism']) to ([data-style]) {
|
|
607
|
+
[data-surface='modal'] {
|
|
608
|
+
background-color: color-mix(in srgb, var(--el-page-bg) var(--glass-modal-alpha), transparent);
|
|
609
|
+
background-image: linear-gradient(150deg, var(--glass-sheen), transparent 55%);
|
|
610
|
+
border-color: color-mix(in srgb, var(--el-border) var(--glass-border-alpha), transparent);
|
|
611
|
+
box-shadow:
|
|
612
|
+
inset 0 1px 0 0 var(--glass-rim),
|
|
613
|
+
0 28px 70px -16px rgba(15, 15, 15, 0.34);
|
|
614
|
+
-webkit-backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
|
|
615
|
+
backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
|
|
616
|
+
}
|
|
611
617
|
}
|
|
612
618
|
|
|
613
619
|
/* The sidebar rail — frosted chrome over the canvas. */
|
|
614
|
-
[data-style='glassmorphism'] [data-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
620
|
+
@scope ([data-style='glassmorphism']) to ([data-style]) {
|
|
621
|
+
[data-surface='sidebar'] {
|
|
622
|
+
background-color: color-mix(
|
|
623
|
+
in srgb,
|
|
624
|
+
var(--el-sidebar-bg) var(--glass-chrome-alpha),
|
|
625
|
+
transparent
|
|
626
|
+
);
|
|
627
|
+
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
|
|
628
|
+
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
|
|
629
|
+
}
|
|
618
630
|
}
|
|
619
631
|
|
|
620
632
|
/* Form controls — a translucent fill so inputs read as glass too. */
|
|
621
|
-
[data-style='glassmorphism'] [data-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
633
|
+
@scope ([data-style='glassmorphism']) to ([data-style]) {
|
|
634
|
+
[data-surface='input'] {
|
|
635
|
+
background-color: color-mix(in srgb, var(--el-page-bg) var(--glass-input-alpha), transparent);
|
|
636
|
+
-webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
|
|
637
|
+
backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
|
|
638
|
+
}
|
|
625
639
|
}
|
|
626
640
|
|
|
627
641
|
/* The MODAL / command-palette BACKDROP — the most important glass surface, since
|
|
@@ -629,10 +643,12 @@
|
|
|
629
643
|
light, palette-derived veil + a page BLUR, so the whole page behind frosts and
|
|
630
644
|
the (also-frosted) modal panel refracts it — the proper glass-modal look.
|
|
631
645
|
Overrides the primitives' `bg-black/40` utility. Palette-derived (no hue). */
|
|
632
|
-
[data-style='glassmorphism'] [data-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
646
|
+
@scope ([data-style='glassmorphism']) to ([data-style]) {
|
|
647
|
+
[data-surface='overlay'] {
|
|
648
|
+
background-color: color-mix(in srgb, var(--el-page-bg) 24%, transparent);
|
|
649
|
+
-webkit-backdrop-filter: blur(8px) saturate(var(--glass-saturate));
|
|
650
|
+
backdrop-filter: blur(8px) saturate(var(--glass-saturate));
|
|
651
|
+
}
|
|
636
652
|
}
|
|
637
653
|
|
|
638
654
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
@@ -711,8 +727,10 @@
|
|
|
711
727
|
descendant rule, not a bare token block, so the disjoint-axis test (which
|
|
712
728
|
inspects token blocks) does not treat it as one — and it sets no colour
|
|
713
729
|
anyway, so the two axes stay disjoint regardless. */
|
|
714
|
-
[data-style='neo-brutalism']
|
|
715
|
-
border
|
|
730
|
+
@scope ([data-style='neo-brutalism']) to ([data-style]) {
|
|
731
|
+
.border {
|
|
732
|
+
border-width: 2px;
|
|
733
|
+
}
|
|
716
734
|
}
|
|
717
735
|
|
|
718
736
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
@@ -795,12 +813,14 @@
|
|
|
795
813
|
so it adapts to the active palette and sits BEHIND content (text never
|
|
796
814
|
renders on it), keeping AA intact. Dark-first — on the dark theme this reads
|
|
797
815
|
as a Tron grid over the near-black canvas. */
|
|
798
|
-
[data-style='cybercore-y2k']
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
816
|
+
@scope ([data-style='cybercore-y2k']) to ([data-style]) {
|
|
817
|
+
body {
|
|
818
|
+
background-image:
|
|
819
|
+
linear-gradient(color-mix(in srgb, currentColor 6%, transparent) 1px, transparent 1px),
|
|
820
|
+
linear-gradient(90deg, color-mix(in srgb, currentColor 6%, transparent) 1px, transparent 1px);
|
|
821
|
+
background-size: 32px 32px;
|
|
822
|
+
background-position: center top;
|
|
823
|
+
}
|
|
804
824
|
}
|
|
805
825
|
|
|
806
826
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
@@ -897,31 +917,33 @@
|
|
|
897
917
|
`--el-*`, never `--color-*`, which is what keeps the aurora orthogonal to the
|
|
898
918
|
palette. background-size > 100% gives the gradient room to drift; the whole
|
|
899
919
|
field eases back and forth over `--aurora-drift-duration`. */
|
|
900
|
-
[data-style='aurora']
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
920
|
+
@scope ([data-style='aurora']) to ([data-style]) {
|
|
921
|
+
body {
|
|
922
|
+
background-image:
|
|
923
|
+
radial-gradient(
|
|
924
|
+
58% 75% at 12% 0%,
|
|
925
|
+
color-mix(in srgb, var(--el-accent) var(--aurora-wash), transparent),
|
|
926
|
+
transparent 60%
|
|
927
|
+
),
|
|
928
|
+
radial-gradient(
|
|
929
|
+
54% 70% at 92% 8%,
|
|
930
|
+
color-mix(in srgb, var(--el-highlight) var(--aurora-wash), transparent),
|
|
931
|
+
transparent 58%
|
|
932
|
+
),
|
|
933
|
+
radial-gradient(
|
|
934
|
+
68% 82% at 62% 104%,
|
|
935
|
+
color-mix(in srgb, var(--el-link) var(--aurora-wash), transparent),
|
|
936
|
+
transparent 62%
|
|
937
|
+
),
|
|
938
|
+
radial-gradient(
|
|
939
|
+
48% 64% at 34% 58%,
|
|
940
|
+
color-mix(in srgb, var(--el-info) var(--aurora-wash-soft), transparent),
|
|
941
|
+
transparent 55%
|
|
942
|
+
);
|
|
943
|
+
background-size: 180% 180%;
|
|
944
|
+
background-attachment: fixed;
|
|
945
|
+
animation: aurora-drift var(--aurora-drift-duration) ease-in-out infinite alternate;
|
|
946
|
+
}
|
|
925
947
|
}
|
|
926
948
|
|
|
927
949
|
@keyframes aurora-drift {
|
|
@@ -944,8 +966,10 @@
|
|
|
944
966
|
/* Respect a reduced-motion preference — the aurora settles to a still gradient
|
|
945
967
|
(the identity holds; only the drift stops). */
|
|
946
968
|
@media (prefers-reduced-motion: reduce) {
|
|
947
|
-
[data-style='aurora']
|
|
948
|
-
|
|
969
|
+
@scope ([data-style='aurora']) to ([data-style]) {
|
|
970
|
+
body {
|
|
971
|
+
animation: none;
|
|
972
|
+
}
|
|
949
973
|
}
|
|
950
974
|
}
|
|
951
975
|
|
|
@@ -955,43 +979,49 @@
|
|
|
955
979
|
rather than lifted by a hard shadow. The sheen sits on background-image over
|
|
956
980
|
the opaque background-color, so it never pulls the surface far enough from its
|
|
957
981
|
base tone to threaten contrast. */
|
|
958
|
-
[data-style='aurora'] [data-
|
|
959
|
-
[data-
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
982
|
+
@scope ([data-style='aurora']) to ([data-style]) {
|
|
983
|
+
[data-surface='card'],
|
|
984
|
+
[data-surface='popover'] {
|
|
985
|
+
background-color: var(--el-surface);
|
|
986
|
+
background-image: linear-gradient(
|
|
987
|
+
180deg,
|
|
988
|
+
color-mix(in srgb, var(--el-highlight) var(--aurora-sheen), transparent),
|
|
989
|
+
transparent 42%
|
|
990
|
+
);
|
|
991
|
+
box-shadow:
|
|
992
|
+
var(--shadow-card),
|
|
993
|
+
0 0 26px -8px color-mix(in srgb, var(--el-accent) var(--aurora-glow), transparent),
|
|
994
|
+
0 0 40px -14px color-mix(in srgb, var(--el-link) var(--aurora-glow), transparent);
|
|
995
|
+
}
|
|
970
996
|
}
|
|
971
997
|
|
|
972
998
|
/* Modal panel — opaque, with a deeper glow so the dialog separates cleanly from
|
|
973
999
|
the drifting canvas behind it (and body text stays on the solid surface). */
|
|
974
|
-
[data-style='aurora'] [data-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
1000
|
+
@scope ([data-style='aurora']) to ([data-style]) {
|
|
1001
|
+
[data-surface='modal'] {
|
|
1002
|
+
background-color: var(--el-surface);
|
|
1003
|
+
background-image: linear-gradient(
|
|
1004
|
+
180deg,
|
|
1005
|
+
color-mix(in srgb, var(--el-highlight) var(--aurora-sheen), transparent),
|
|
1006
|
+
transparent 38%
|
|
1007
|
+
);
|
|
1008
|
+
box-shadow:
|
|
1009
|
+
var(--shadow-modal),
|
|
1010
|
+
0 0 60px -16px color-mix(in srgb, var(--el-accent) var(--aurora-glow-strong), transparent);
|
|
1011
|
+
}
|
|
984
1012
|
}
|
|
985
1013
|
|
|
986
1014
|
/* The sidebar rail — opaque chrome carrying the faint aurora sheen so it reads as
|
|
987
1015
|
part of the lit surface family, not a flat slab. */
|
|
988
|
-
[data-style='aurora'] [data-
|
|
989
|
-
|
|
990
|
-
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
|
|
1016
|
+
@scope ([data-style='aurora']) to ([data-style]) {
|
|
1017
|
+
[data-surface='sidebar'] {
|
|
1018
|
+
background-color: var(--el-sidebar-bg);
|
|
1019
|
+
background-image: linear-gradient(
|
|
1020
|
+
180deg,
|
|
1021
|
+
color-mix(in srgb, var(--el-accent) var(--aurora-sheen), transparent),
|
|
1022
|
+
transparent 30%
|
|
1023
|
+
);
|
|
1024
|
+
}
|
|
995
1025
|
}
|
|
996
1026
|
|
|
997
1027
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
@@ -1086,24 +1116,26 @@
|
|
|
1086
1116
|
rule test passes: a palette swap re-tints the atmosphere, a style swap leaves
|
|
1087
1117
|
hues alone. This is what makes the table/list/board pages (no card surfaces of
|
|
1088
1118
|
their own) read as immersive too. */
|
|
1089
|
-
[data-style='3d-immersive']
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1119
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1120
|
+
body {
|
|
1121
|
+
background-image:
|
|
1122
|
+
radial-gradient(
|
|
1123
|
+
130% 85% at 50% -15%,
|
|
1124
|
+
color-mix(in srgb, var(--el-accent) 9%, transparent),
|
|
1125
|
+
transparent 60%
|
|
1126
|
+
),
|
|
1127
|
+
radial-gradient(
|
|
1128
|
+
95% 75% at 108% 112%,
|
|
1129
|
+
color-mix(in srgb, var(--el-link) 8%, transparent),
|
|
1130
|
+
transparent 55%
|
|
1131
|
+
),
|
|
1132
|
+
radial-gradient(
|
|
1133
|
+
150% 130% at 50% 42%,
|
|
1134
|
+
transparent 52%,
|
|
1135
|
+
color-mix(in srgb, var(--el-text) 8%, transparent)
|
|
1136
|
+
);
|
|
1137
|
+
background-attachment: fixed;
|
|
1138
|
+
}
|
|
1107
1139
|
}
|
|
1108
1140
|
|
|
1109
1141
|
/* EVERY PANEL FLOATS — systematic depth across the WHOLE app, not just the
|
|
@@ -1118,11 +1150,15 @@
|
|
|
1118
1150
|
Per-surface exceptions (the board column's clip-safe shadow, modals) override
|
|
1119
1151
|
below by source order. Modals carry their own deeper shadow via the modal
|
|
1120
1152
|
radius (next rule). */
|
|
1121
|
-
[data-style='3d-immersive']
|
|
1122
|
-
|
|
1153
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1154
|
+
.rounded-\(--radius-card\) {
|
|
1155
|
+
box-shadow: var(--shadow-card);
|
|
1156
|
+
}
|
|
1123
1157
|
}
|
|
1124
|
-
[data-style='3d-immersive']
|
|
1125
|
-
|
|
1158
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1159
|
+
.rounded-\(--radius-modal\) {
|
|
1160
|
+
box-shadow: var(--shadow-modal);
|
|
1161
|
+
}
|
|
1126
1162
|
}
|
|
1127
1163
|
|
|
1128
1164
|
/* 3D / Immersive — the POINTER-PARALLAX TILT (the standard "3D card" effect,
|
|
@@ -1147,10 +1183,12 @@
|
|
|
1147
1183
|
never establishes a transform stacking context that could reposition a
|
|
1148
1184
|
non-portaled fixed/absolute descendant. On leave the engine drops the
|
|
1149
1185
|
attribute and the transform eases back to none over 400ms. */
|
|
1150
|
-
[data-style='3d-immersive'] [data-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1186
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1187
|
+
[data-tilt] {
|
|
1188
|
+
transition:
|
|
1189
|
+
transform 400ms cubic-bezier(0.22, 1, 0.36, 1),
|
|
1190
|
+
box-shadow 260ms ease-out;
|
|
1191
|
+
}
|
|
1154
1192
|
}
|
|
1155
1193
|
/* While the pointer is over the tile the engine sets data-tilt-active='1':
|
|
1156
1194
|
tip it toward the cursor (the per-tile --tilt-rx/ry the engine writes),
|
|
@@ -1159,14 +1197,16 @@
|
|
|
1159
1197
|
establish a 3D context (`preserve-3d`) so the card's slots can sit on
|
|
1160
1198
|
separate translateZ planes and PARALLAX (a flat-plane tilt without this is
|
|
1161
1199
|
the "halfway / flat-3D mix" tell). `position: relative` anchors the glare. */
|
|
1162
|
-
[data-style='3d-immersive'] [data-
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1167
|
-
|
|
1168
|
-
|
|
1169
|
-
|
|
1200
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1201
|
+
[data-tilt][data-tilt-active='1'] {
|
|
1202
|
+
transform: perspective(var(--tilt-perspective, 900px)) rotateX(var(--tilt-rx, 0deg))
|
|
1203
|
+
rotateY(var(--tilt-ry, 0deg));
|
|
1204
|
+
transform-style: preserve-3d;
|
|
1205
|
+
transition:
|
|
1206
|
+
transform 80ms linear,
|
|
1207
|
+
box-shadow 260ms ease-out;
|
|
1208
|
+
box-shadow: var(--shadow-elevated);
|
|
1209
|
+
}
|
|
1170
1210
|
}
|
|
1171
1211
|
|
|
1172
1212
|
/* DEPTH PLANES — the card's slots lift onto different translateZ planes so
|
|
@@ -1175,13 +1215,17 @@
|
|
|
1175
1215
|
content never renders skewed). Only while actively tilting, so a resting
|
|
1176
1216
|
card is perfectly flat. This is the standard layered-parallax technique
|
|
1177
1217
|
(vanilla-tilt / Atropos): perspective + preserve-3d + per-layer translateZ. */
|
|
1178
|
-
[data-style='3d-immersive']
|
|
1179
|
-
|
|
1180
|
-
|
|
1218
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1219
|
+
[data-tilt][data-tilt-active='1'] [data-tilt-layer='front'] {
|
|
1220
|
+
transform: translateZ(42px);
|
|
1221
|
+
transition: transform 80ms linear;
|
|
1222
|
+
}
|
|
1181
1223
|
}
|
|
1182
|
-
[data-style='3d-immersive']
|
|
1183
|
-
|
|
1184
|
-
|
|
1224
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1225
|
+
[data-tilt][data-tilt-active='1'] [data-tilt-layer='back'] {
|
|
1226
|
+
transform: translateZ(14px);
|
|
1227
|
+
transition: transform 80ms linear;
|
|
1228
|
+
}
|
|
1185
1229
|
}
|
|
1186
1230
|
|
|
1187
1231
|
/* GLARE — a cursor-tracked specular sweep across the face (the light catching
|
|
@@ -1189,33 +1233,39 @@
|
|
|
1189
1233
|
hue → passes the material-rule test; a palette swap re-tints the sheen). It
|
|
1190
1234
|
rides a high translateZ so it reads as light on the front glass, fades in
|
|
1191
1235
|
only while active, and never eats pointer events. */
|
|
1192
|
-
[data-style='3d-immersive'] [data-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
|
|
1199
|
-
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1236
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1237
|
+
[data-tilt]::after {
|
|
1238
|
+
content: '';
|
|
1239
|
+
position: absolute;
|
|
1240
|
+
inset: 0;
|
|
1241
|
+
border-radius: inherit;
|
|
1242
|
+
background: radial-gradient(
|
|
1243
|
+
circle at var(--tilt-glare-x, 50%) var(--tilt-glare-y, 50%),
|
|
1244
|
+
color-mix(in srgb, var(--el-page-bg) 65%, transparent),
|
|
1245
|
+
transparent 55%
|
|
1246
|
+
);
|
|
1247
|
+
opacity: 0;
|
|
1248
|
+
transition: opacity 200ms ease-out;
|
|
1249
|
+
pointer-events: none;
|
|
1250
|
+
}
|
|
1205
1251
|
}
|
|
1206
|
-
[data-style='3d-immersive'] [data-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1252
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1253
|
+
[data-tilt][data-tilt-active='1']::after {
|
|
1254
|
+
opacity: 0.45;
|
|
1255
|
+
/* Just above the card FACE but BELOW the popped header/footer planes, so it
|
|
1256
|
+
lights the surface without washing the floating title. */
|
|
1257
|
+
transform: translateZ(2px);
|
|
1258
|
+
}
|
|
1211
1259
|
}
|
|
1212
1260
|
}
|
|
1213
1261
|
|
|
1214
1262
|
/* `position: relative` anchors the glare ::after to each tile. Static (outside
|
|
1215
1263
|
the motion gate) so the anchor is stable; the glare itself only shows while
|
|
1216
1264
|
tilting (above). */
|
|
1217
|
-
[data-style='3d-immersive'] [data-
|
|
1218
|
-
|
|
1265
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1266
|
+
[data-tilt] {
|
|
1267
|
+
position: relative;
|
|
1268
|
+
}
|
|
1219
1269
|
}
|
|
1220
1270
|
|
|
1221
1271
|
/* ── 3D / Immersive — BOARD COLUMNS ─────────────────────────────────────────
|
|
@@ -1226,33 +1276,37 @@
|
|
|
1226
1276
|
clip/occlusion-safe float shadow (small horizontal bleed, modest drop), and
|
|
1227
1277
|
the scroll row widens its gap + adds bottom room so the shadow shows. Result:
|
|
1228
1278
|
each column floats as its own distinct card. */
|
|
1229
|
-
[data-style='3d-immersive'] [data-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1279
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1280
|
+
[data-board-col-panel] {
|
|
1281
|
+
box-shadow:
|
|
1282
|
+
inset 0 1px 0 0 rgba(255, 255, 255, 0.55),
|
|
1283
|
+
0 1px 3px rgba(15, 15, 15, 0.08),
|
|
1284
|
+
0 8px 18px -8px rgba(15, 15, 15, 0.22);
|
|
1285
|
+
/* The column is `h-[calc(100dvh - 10.5rem - var(--shell-bottom-clearance))]` —
|
|
1286
|
+
sized to fill the board area. In the `overflow-x-auto` row that
|
|
1287
|
+
exactly-filling height means the column's rounded BOTTOM corner + its drop
|
|
1288
|
+
shadow sit at the overflow-clip boundary and get sheared flat (the reported
|
|
1289
|
+
"sharp bottom corner"). Trim the height by a further 2.5rem so the rounded
|
|
1290
|
+
corner + shadow clear the clip and the column reads as a fully-rounded
|
|
1291
|
+
floating card. Also clip the column's OWN children to its radius so a flush
|
|
1292
|
+
inner surface can't square a corner — the board cards pop on hover but the
|
|
1293
|
+
DragOverlay clone is portaled, so nothing 3D is lost.
|
|
1294
|
+
|
|
1295
|
+
⚠️ This tracks BoardColumn's height and must keep spending the same
|
|
1296
|
+
`--shell-bottom-clearance` the shell sets (MOTIR-2763), not a flat number:
|
|
1297
|
+
a stylesheet cannot read the `showPlanWithAi` prop, so the custom property
|
|
1298
|
+
is the only way this stays conditional on the orb actually mounting. The
|
|
1299
|
+
13rem below is 10.5rem of chrome + this style's own 2.5rem trim. */
|
|
1300
|
+
height: calc(100dvh - 13rem - var(--shell-bottom-clearance, 1.5rem));
|
|
1301
|
+
overflow: hidden;
|
|
1302
|
+
}
|
|
1251
1303
|
}
|
|
1252
|
-
[data-style='3d-immersive'] [data-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1304
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1305
|
+
[data-board-scroll] {
|
|
1306
|
+
gap: 1.5rem;
|
|
1307
|
+
padding-bottom: 2.25rem;
|
|
1308
|
+
padding-top: 0.25rem;
|
|
1309
|
+
}
|
|
1256
1310
|
}
|
|
1257
1311
|
|
|
1258
1312
|
/* ── 3D / Immersive — CONTROL DEPTH: every control sits on a named plane ────
|
|
@@ -1317,7 +1371,7 @@
|
|
|
1317
1371
|
The `.justify-center` limb is the square icon-button shape: a centred control
|
|
1318
1372
|
on the control radius is a key (the 3-dots trigger, the fullscreen toggle,
|
|
1319
1373
|
every close ×). A row is never centred — it is `w-full` and `text-left`. */
|
|
1320
|
-
[data-style='3d-immersive']
|
|
1374
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1321
1375
|
:where(
|
|
1322
1376
|
.rounded-\(--radius-btn\),
|
|
1323
1377
|
button.rounded-\(--radius-input\),
|
|
@@ -1333,27 +1387,34 @@
|
|
|
1333
1387
|
[data-depth='flat']
|
|
1334
1388
|
)
|
|
1335
1389
|
) {
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1390
|
+
box-shadow:
|
|
1391
|
+
0 3px 0 0 var(--el-border-strong),
|
|
1392
|
+
0 5px 10px -3px rgba(15, 15, 15, 0.18);
|
|
1393
|
+
transition:
|
|
1394
|
+
transform 90ms ease-out,
|
|
1395
|
+
box-shadow 90ms ease-out,
|
|
1396
|
+
background-color var(--transition-duration);
|
|
1397
|
+
}
|
|
1343
1398
|
}
|
|
1344
|
-
[data-style='3d-immersive'] [data-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1399
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1400
|
+
[data-variant='primary'] {
|
|
1401
|
+
box-shadow:
|
|
1402
|
+
0 4px 0 0 var(--el-accent-pressed),
|
|
1403
|
+
0 7px 12px -3px rgba(15, 15, 15, 0.32);
|
|
1404
|
+
}
|
|
1348
1405
|
}
|
|
1349
|
-
[data-style='3d-immersive'] [data-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1406
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1407
|
+
[data-variant='danger'] {
|
|
1408
|
+
box-shadow:
|
|
1409
|
+
0 4px 0 0 color-mix(in srgb, var(--el-danger), black 32%),
|
|
1410
|
+
0 7px 12px -3px rgba(15, 15, 15, 0.32);
|
|
1411
|
+
}
|
|
1353
1412
|
}
|
|
1354
1413
|
/* Ghost — the deliberately-flat quiet button; no thickness. */
|
|
1355
|
-
[data-style='3d-immersive'] [data-
|
|
1356
|
-
|
|
1414
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1415
|
+
[data-variant='ghost'] {
|
|
1416
|
+
box-shadow: none;
|
|
1417
|
+
}
|
|
1357
1418
|
}
|
|
1358
1419
|
|
|
1359
1420
|
/* THE FLAT SET — rows, chips and switches, which §4 keeps on their parent's
|
|
@@ -1361,7 +1422,7 @@
|
|
|
1361
1422
|
(0,1,0) wherever the two overlap (a centred control inside an open menu, a
|
|
1362
1423
|
`data-depth='flat'` icon button). A menu row raised inside an already-floating
|
|
1363
1424
|
popover reads as debris, not depth — the overlay is the thing that floats. */
|
|
1364
|
-
[data-style='3d-immersive']
|
|
1425
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1365
1426
|
:is(
|
|
1366
1427
|
[role='menuitem'],
|
|
1367
1428
|
[role='option'],
|
|
@@ -1370,50 +1431,57 @@
|
|
|
1370
1431
|
[role='switch'],
|
|
1371
1432
|
[data-depth='flat']
|
|
1372
1433
|
),
|
|
1373
|
-
[data-
|
|
1374
|
-
:is(
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
box-shadow: none;
|
|
1434
|
+
:is([data-surface='popover'], [data-menu-surface]) :is(button, a).rounded-\(--radius-control\),
|
|
1435
|
+
:is(button, a).w-full.rounded-\(--radius-control\) {
|
|
1436
|
+
box-shadow: none;
|
|
1437
|
+
}
|
|
1378
1438
|
}
|
|
1379
1439
|
|
|
1380
1440
|
/* THE PRESS — the raised set drops by its thickness and the base edge
|
|
1381
1441
|
compresses, like a real key. Overrides the base `active:scale`. */
|
|
1382
|
-
[data-style='3d-immersive']
|
|
1442
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1383
1443
|
:where(
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1444
|
+
.rounded-\(--radius-btn\),
|
|
1445
|
+
button.rounded-\(--radius-input\),
|
|
1446
|
+
:is(button, a).rounded-\(--radius-control\).justify-center,
|
|
1447
|
+
[data-depth='key']
|
|
1448
|
+
):active:not(:disabled) {
|
|
1449
|
+
transform: translateY(3px);
|
|
1450
|
+
box-shadow:
|
|
1451
|
+
0 1px 0 0 var(--el-border-strong),
|
|
1452
|
+
0 2px 4px rgba(15, 15, 15, 0.14);
|
|
1453
|
+
}
|
|
1393
1454
|
}
|
|
1394
|
-
[data-style='3d-immersive'] [data-
|
|
1395
|
-
|
|
1396
|
-
|
|
1397
|
-
|
|
1455
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1456
|
+
[data-variant='primary']:active:not(:disabled) {
|
|
1457
|
+
box-shadow:
|
|
1458
|
+
0 1px 0 0 var(--el-accent-pressed),
|
|
1459
|
+
0 2px 5px rgba(15, 15, 15, 0.22);
|
|
1460
|
+
}
|
|
1398
1461
|
}
|
|
1399
|
-
[data-style='3d-immersive'] [data-
|
|
1400
|
-
|
|
1401
|
-
|
|
1402
|
-
|
|
1462
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1463
|
+
[data-variant='danger']:active:not(:disabled) {
|
|
1464
|
+
box-shadow:
|
|
1465
|
+
0 1px 0 0 color-mix(in srgb, var(--el-danger), black 32%),
|
|
1466
|
+
0 2px 5px rgba(15, 15, 15, 0.22);
|
|
1467
|
+
}
|
|
1403
1468
|
}
|
|
1404
|
-
[data-style='3d-immersive'] [data-
|
|
1405
|
-
|
|
1469
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1470
|
+
[data-variant='ghost']:active:not(:disabled) {
|
|
1471
|
+
box-shadow: none;
|
|
1472
|
+
}
|
|
1406
1473
|
}
|
|
1407
1474
|
|
|
1408
1475
|
/* THE QUIET PRESS — a control with no resting thickness still has to answer the
|
|
1409
1476
|
pointer, or the style reads as flat wherever it is not a key: menu rows, list
|
|
1410
1477
|
rows, nav links, inline affordances, the ghost button. One pixel of travel is
|
|
1411
1478
|
the whole treatment; it is what separates "quiet" from "inert". */
|
|
1412
|
-
[data-style='3d-immersive']
|
|
1479
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1413
1480
|
:where(:is(button, a).rounded-\(--radius-control\), [data-variant='ghost']):active:not(
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
|
|
1481
|
+
:disabled
|
|
1482
|
+
) {
|
|
1483
|
+
transform: translateY(1px);
|
|
1484
|
+
}
|
|
1417
1485
|
}
|
|
1418
1486
|
|
|
1419
1487
|
/* THE RECESSED SET — text fields are pressed INTO the surface, not raised off
|
|
@@ -1424,16 +1492,17 @@
|
|
|
1424
1492
|
not a copy of it. `[data-surface='input']` is the Input primitive's shell;
|
|
1425
1493
|
the bare element selectors catch the hand-rolled fields. Checkbox and radio
|
|
1426
1494
|
are excluded: they are chips, not wells. */
|
|
1427
|
-
[data-style='3d-immersive']
|
|
1495
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1428
1496
|
:where(
|
|
1429
1497
|
[data-surface='input'],
|
|
1430
1498
|
input:not([type='checkbox'], [type='radio'], [type='range'], [type='color']),
|
|
1431
1499
|
textarea,
|
|
1432
1500
|
select
|
|
1433
1501
|
) {
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1502
|
+
box-shadow:
|
|
1503
|
+
inset 0 2px 6px -2px rgba(15, 15, 15, 0.26),
|
|
1504
|
+
inset 0 1px 2px 0 rgba(15, 15, 15, 0.05);
|
|
1505
|
+
}
|
|
1437
1506
|
}
|
|
1438
1507
|
|
|
1439
1508
|
/* Hero controls paint their own shadow in an INLINE style, which beats every
|
|
@@ -1452,18 +1521,20 @@
|
|
|
1452
1521
|
override every shape role. A descendant rule is neither, which is where the
|
|
1453
1522
|
immersive background (which reads `--el-*` for the same reason) already
|
|
1454
1523
|
lives. Custom properties inherit, so every control below `body` sees these. */
|
|
1455
|
-
[data-style='3d-immersive']
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1524
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1525
|
+
body {
|
|
1526
|
+
--plan-hero-shadow:
|
|
1527
|
+
0 4px 0 0 var(--el-accent-pressed),
|
|
1528
|
+
inset 0 1px 0 color-mix(in srgb, var(--el-accent-text) 38%, transparent),
|
|
1529
|
+
inset 0 0 0 1px color-mix(in srgb, var(--el-accent-text) 18%, transparent),
|
|
1530
|
+
0 9px 18px -5px color-mix(in srgb, var(--el-accent) 75%, transparent),
|
|
1531
|
+
0 0 22px -3px color-mix(in srgb, var(--el-highlight) 50%, transparent);
|
|
1532
|
+
--plan-orb-shadow:
|
|
1533
|
+
0 5px 0 0 var(--el-accent-pressed),
|
|
1534
|
+
inset 0 1px 0 color-mix(in srgb, var(--el-accent-text) 40%, transparent),
|
|
1535
|
+
0 12px 24px -6px color-mix(in srgb, var(--el-accent) 80%, transparent),
|
|
1536
|
+
0 0 28px -2px color-mix(in srgb, var(--el-highlight) 55%, transparent);
|
|
1537
|
+
}
|
|
1467
1538
|
}
|
|
1468
1539
|
|
|
1469
1540
|
/* ── 3D / Immersive — DROPDOWNS / POPOVERS / MENUS unfold in 3D ──────────────
|
|
@@ -1489,22 +1560,28 @@
|
|
|
1489
1560
|
rule above would otherwise flatten any `shadow-(--shadow-elevated)` surface to
|
|
1490
1561
|
--shadow-card). Global + static so menus, tooltips, drag-overlays all keep the
|
|
1491
1562
|
right depth. */
|
|
1492
|
-
[data-style='3d-immersive']
|
|
1493
|
-
|
|
1563
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1564
|
+
.shadow-\(--shadow-elevated\) {
|
|
1565
|
+
box-shadow: var(--shadow-elevated);
|
|
1566
|
+
}
|
|
1494
1567
|
}
|
|
1495
1568
|
@media (prefers-reduced-motion: no-preference) {
|
|
1496
1569
|
/* The 3D UNFOLD is scoped to actual MENU surfaces (the Popover primitive +
|
|
1497
1570
|
the `data-menu-surface` hook on Combobox / MultiSelect / BoardSwitcher
|
|
1498
1571
|
menus) — NOT every elevated surface, so a drag-overlay or toast doesn't
|
|
1499
1572
|
unexpectedly fold open. */
|
|
1500
|
-
[data-style='3d-immersive'] [data-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1573
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1574
|
+
[data-surface='popover'],
|
|
1575
|
+
[data-menu-surface] {
|
|
1576
|
+
transform-origin: top center;
|
|
1577
|
+
animation: immersive-menu-open 200ms cubic-bezier(0.22, 1, 0.36, 1);
|
|
1578
|
+
}
|
|
1504
1579
|
}
|
|
1505
1580
|
/* A Radix popover that flips ABOVE its trigger folds from the bottom edge. */
|
|
1506
|
-
[data-style='3d-immersive'] [data-
|
|
1507
|
-
|
|
1581
|
+
@scope ([data-style='3d-immersive']) to ([data-style]) {
|
|
1582
|
+
[data-surface='popover'][data-side='top'] {
|
|
1583
|
+
transform-origin: bottom center;
|
|
1584
|
+
}
|
|
1508
1585
|
}
|
|
1509
1586
|
}
|
|
1510
1587
|
|
|
@@ -1591,52 +1668,62 @@
|
|
|
1591
1668
|
dividers `.border-b` / `.border-t` (table rows, section rules) — the latter
|
|
1592
1669
|
scoped INSIDE `[data-surface]` panels to bound the count to real surfaces (and
|
|
1593
1670
|
their rows are virtualised, so only ~viewport-many overlays ever render). */
|
|
1594
|
-
[data-style='hand-drawn-indie']
|
|
1595
|
-
border
|
|
1671
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1672
|
+
.border {
|
|
1673
|
+
border-width: 2px;
|
|
1674
|
+
}
|
|
1596
1675
|
}
|
|
1597
|
-
[data-style='hand-drawn-indie']
|
|
1598
|
-
|
|
1676
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1677
|
+
.border:not(.fixed):not(.absolute):not(.sticky) {
|
|
1678
|
+
position: relative;
|
|
1679
|
+
}
|
|
1599
1680
|
}
|
|
1600
|
-
[data-style='hand-drawn-indie']
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1681
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1682
|
+
.border::after {
|
|
1683
|
+
content: '';
|
|
1684
|
+
position: absolute;
|
|
1685
|
+
inset: -1px;
|
|
1686
|
+
pointer-events: none;
|
|
1687
|
+
border: 2px solid var(--el-border-strong);
|
|
1688
|
+
border-radius: inherit;
|
|
1689
|
+
filter: url(#hd-rough);
|
|
1690
|
+
}
|
|
1608
1691
|
}
|
|
1609
1692
|
|
|
1610
1693
|
/* Internal grid dividers — make the inner rules as rough as the frame. Scoped
|
|
1611
1694
|
inside framed surfaces; `:not(.border)` so a full-box element isn't handled
|
|
1612
1695
|
twice; `:not(:last-child)` mirrors the common `last:border-b-0` strip so the
|
|
1613
1696
|
final row gets no phantom line. */
|
|
1614
|
-
[data-style='hand-drawn-indie']
|
|
1615
|
-
[data-surface]
|
|
1616
|
-
|
|
1617
|
-
|
|
1697
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1698
|
+
[data-surface] :is(.border-b, .border-t):not(.border):not(.fixed):not(.absolute):not(.sticky) {
|
|
1699
|
+
position: relative;
|
|
1700
|
+
}
|
|
1618
1701
|
}
|
|
1619
|
-
[data-style='hand-drawn-indie'] [data-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1702
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1703
|
+
[data-surface] .border-b:not(.border)::after {
|
|
1704
|
+
content: '';
|
|
1705
|
+
position: absolute;
|
|
1706
|
+
left: 0;
|
|
1707
|
+
right: 0;
|
|
1708
|
+
bottom: -1px;
|
|
1709
|
+
height: 0;
|
|
1710
|
+
pointer-events: none;
|
|
1711
|
+
border-bottom: 2px solid var(--el-border-strong);
|
|
1712
|
+
filter: url(#hd-rough);
|
|
1713
|
+
}
|
|
1629
1714
|
}
|
|
1630
|
-
[data-style='hand-drawn-indie'] [data-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1715
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1716
|
+
[data-surface] .border-t:not(.border)::after {
|
|
1717
|
+
content: '';
|
|
1718
|
+
position: absolute;
|
|
1719
|
+
left: 0;
|
|
1720
|
+
right: 0;
|
|
1721
|
+
top: -1px;
|
|
1722
|
+
height: 0;
|
|
1723
|
+
pointer-events: none;
|
|
1724
|
+
border-top: 2px solid var(--el-border-strong);
|
|
1725
|
+
filter: url(#hd-rough);
|
|
1726
|
+
}
|
|
1640
1727
|
}
|
|
1641
1728
|
/* Suppress the overlay only where the REAL divider is removed: the last row of a
|
|
1642
1729
|
fully-rendered list strips its border via `last:border-b-0`. (We can't use
|
|
@@ -1644,8 +1731,10 @@
|
|
|
1644
1731
|
own `role="rowgroup"`, so it is itself a `:last-child` and would be wrongly
|
|
1645
1732
|
skipped, which left the work-item table header's divider straight.) Same
|
|
1646
1733
|
specificity as the draw rule, placed after, so it wins on the real last row. */
|
|
1647
|
-
[data-style='hand-drawn-indie'] [data-
|
|
1648
|
-
|
|
1734
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1735
|
+
[data-surface] .last\:border-b-0:last-child::after {
|
|
1736
|
+
content: none;
|
|
1737
|
+
}
|
|
1649
1738
|
}
|
|
1650
1739
|
|
|
1651
1740
|
/* The APP SHELL FRAME — the sidebar rail's right edge + the top bar's bottom edge
|
|
@@ -1659,31 +1748,36 @@
|
|
|
1659
1748
|
ONLY to a STATIC host (the rail) — never the STICKY header, which is already a
|
|
1660
1749
|
containing block (overriding it would break the sticky), mirroring the `.border`
|
|
1661
1750
|
rule's guard. */
|
|
1662
|
-
[data-style='hand-drawn-indie']
|
|
1751
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1663
1752
|
:is([data-surface='sidebar'], [data-surface='header']):not(.fixed):not(.absolute):not(.sticky) {
|
|
1664
|
-
|
|
1753
|
+
position: relative;
|
|
1754
|
+
}
|
|
1665
1755
|
}
|
|
1666
|
-
[data-style='hand-drawn-indie'] [data-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1756
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1757
|
+
[data-surface='sidebar']::after {
|
|
1758
|
+
content: '';
|
|
1759
|
+
position: absolute;
|
|
1760
|
+
top: 0;
|
|
1761
|
+
bottom: 0;
|
|
1762
|
+
right: -1px;
|
|
1763
|
+
width: 0;
|
|
1764
|
+
pointer-events: none;
|
|
1765
|
+
border-right: 2px solid var(--el-border-strong);
|
|
1766
|
+
filter: url(#hd-rough);
|
|
1767
|
+
}
|
|
1676
1768
|
}
|
|
1677
|
-
[data-style='hand-drawn-indie'] [data-
|
|
1678
|
-
|
|
1679
|
-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
|
|
1683
|
-
|
|
1684
|
-
|
|
1685
|
-
|
|
1686
|
-
|
|
1769
|
+
@scope ([data-style='hand-drawn-indie']) to ([data-style]) {
|
|
1770
|
+
[data-surface='header']::after {
|
|
1771
|
+
content: '';
|
|
1772
|
+
position: absolute;
|
|
1773
|
+
left: 0;
|
|
1774
|
+
right: 0;
|
|
1775
|
+
bottom: -1px;
|
|
1776
|
+
height: 0;
|
|
1777
|
+
pointer-events: none;
|
|
1778
|
+
border-bottom: 2px solid var(--el-border-strong);
|
|
1779
|
+
filter: url(#hd-rough);
|
|
1780
|
+
}
|
|
1687
1781
|
}
|
|
1688
1782
|
|
|
1689
1783
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
@@ -1795,8 +1889,10 @@
|
|
|
1795
1889
|
panels look MOULDED OUT OF the same material rather than placed on top. Both
|
|
1796
1890
|
the canvas and the surfaces below share `var(--el-surface)`, which is the whole
|
|
1797
1891
|
neumorphic illusion. Palette-derived (no hue of its own). */
|
|
1798
|
-
[data-style='neumorphism']
|
|
1799
|
-
|
|
1892
|
+
@scope ([data-style='neumorphism']) to ([data-style]) {
|
|
1893
|
+
body {
|
|
1894
|
+
background-color: var(--el-surface);
|
|
1895
|
+
}
|
|
1800
1896
|
}
|
|
1801
1897
|
|
|
1802
1898
|
/* Raised container surfaces — cards & popovers swell OUT of the field on a paired
|
|
@@ -1806,45 +1902,53 @@
|
|
|
1806
1902
|
from hue. The faint hairline is kept as the accessibility fallback so structure
|
|
1807
1903
|
doesn't depend on the shadow alone. Opaque `--el-surface` keeps text on the
|
|
1808
1904
|
palette's AA-tuned surface. */
|
|
1809
|
-
[data-style='neumorphism'] [data-
|
|
1810
|
-
[data-
|
|
1811
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
1815
|
-
|
|
1905
|
+
@scope ([data-style='neumorphism']) to ([data-style]) {
|
|
1906
|
+
[data-surface='card'],
|
|
1907
|
+
[data-surface='popover'] {
|
|
1908
|
+
background-color: var(--el-surface);
|
|
1909
|
+
border-color: color-mix(in srgb, var(--el-border) 45%, transparent);
|
|
1910
|
+
box-shadow:
|
|
1911
|
+
var(--neu-distance) var(--neu-distance) var(--neu-blur) var(--neu-shadow),
|
|
1912
|
+
calc(-1 * var(--neu-distance)) calc(-1 * var(--neu-distance)) var(--neu-blur) var(--neu-light);
|
|
1913
|
+
}
|
|
1816
1914
|
}
|
|
1817
1915
|
|
|
1818
1916
|
/* Modal panel — the same raised mould, a touch deeper so the dialog separates
|
|
1819
1917
|
from the field behind it (body text stays on the opaque surface). */
|
|
1820
|
-
[data-style='neumorphism'] [data-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
var(--neu-
|
|
1826
|
-
|
|
1827
|
-
var(--neu-
|
|
1918
|
+
@scope ([data-style='neumorphism']) to ([data-style]) {
|
|
1919
|
+
[data-surface='modal'] {
|
|
1920
|
+
background-color: var(--el-surface);
|
|
1921
|
+
border-color: color-mix(in srgb, var(--el-border) 45%, transparent);
|
|
1922
|
+
box-shadow:
|
|
1923
|
+
calc(var(--neu-distance) + 2px) calc(var(--neu-distance) + 2px) calc(var(--neu-blur) + 8px)
|
|
1924
|
+
var(--neu-shadow),
|
|
1925
|
+
calc(-1 * var(--neu-distance)) calc(-1 * var(--neu-distance)) calc(var(--neu-blur) + 4px)
|
|
1926
|
+
var(--neu-light);
|
|
1927
|
+
}
|
|
1828
1928
|
}
|
|
1829
1929
|
|
|
1830
1930
|
/* The sidebar rail — moulded from the same field as the chrome, gently raised so
|
|
1831
1931
|
it reads as part of the one continuous surface. */
|
|
1832
|
-
[data-style='neumorphism'] [data-
|
|
1833
|
-
|
|
1834
|
-
|
|
1835
|
-
|
|
1836
|
-
|
|
1932
|
+
@scope ([data-style='neumorphism']) to ([data-style]) {
|
|
1933
|
+
[data-surface='sidebar'] {
|
|
1934
|
+
background-color: var(--el-surface);
|
|
1935
|
+
box-shadow:
|
|
1936
|
+
var(--neu-distance) 0 var(--neu-blur) var(--neu-shadow),
|
|
1937
|
+
calc(-1 * var(--neu-distance)) 0 var(--neu-blur) var(--neu-light);
|
|
1938
|
+
}
|
|
1837
1939
|
}
|
|
1838
1940
|
|
|
1839
1941
|
/* Form controls — the inverse mould: a CONCAVE INSET well pressed INTO the field
|
|
1840
1942
|
(the soft-UI input look), the paired shadow flipped to `inset`. */
|
|
1841
|
-
[data-style='neumorphism'] [data-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
var(--neu-
|
|
1943
|
+
@scope ([data-style='neumorphism']) to ([data-style]) {
|
|
1944
|
+
[data-surface='input'] {
|
|
1945
|
+
background-color: var(--el-surface);
|
|
1946
|
+
border-color: color-mix(in srgb, var(--el-border) 45%, transparent);
|
|
1947
|
+
box-shadow:
|
|
1948
|
+
inset var(--neu-distance-sm) var(--neu-distance-sm) var(--neu-blur-sm) var(--neu-shadow),
|
|
1949
|
+
inset calc(-1 * var(--neu-distance-sm)) calc(-1 * var(--neu-distance-sm)) var(--neu-blur-sm)
|
|
1950
|
+
var(--neu-light);
|
|
1951
|
+
}
|
|
1848
1952
|
}
|
|
1849
1953
|
|
|
1850
1954
|
/* Accessibility fallback — when a user asks for more contrast (or forced colours),
|
|
@@ -1852,23 +1956,27 @@
|
|
|
1852
1956
|
moulded surface and flatten the paired shadow to a single readable lift.
|
|
1853
1957
|
Palette-derived (var(--el-border)); no hue. */
|
|
1854
1958
|
@media (prefers-contrast: more) {
|
|
1855
|
-
[data-style='neumorphism'] [data-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1959
|
+
@scope ([data-style='neumorphism']) to ([data-style]) {
|
|
1960
|
+
[data-surface='card'],
|
|
1961
|
+
[data-surface='popover'],
|
|
1962
|
+
[data-surface='modal'],
|
|
1963
|
+
[data-surface='input'],
|
|
1964
|
+
[data-surface='sidebar'] {
|
|
1965
|
+
border-color: var(--el-border-strong);
|
|
1966
|
+
box-shadow: var(--shadow-card);
|
|
1967
|
+
}
|
|
1862
1968
|
}
|
|
1863
1969
|
}
|
|
1864
1970
|
@media (forced-colors: active) {
|
|
1865
|
-
[data-style='neumorphism'] [data-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1971
|
+
@scope ([data-style='neumorphism']) to ([data-style]) {
|
|
1972
|
+
[data-surface='card'],
|
|
1973
|
+
[data-surface='popover'],
|
|
1974
|
+
[data-surface='modal'],
|
|
1975
|
+
[data-surface='input'],
|
|
1976
|
+
[data-surface='sidebar'] {
|
|
1977
|
+
border-color: var(--el-border-strong);
|
|
1978
|
+
box-shadow: none;
|
|
1979
|
+
}
|
|
1872
1980
|
}
|
|
1873
1981
|
}
|
|
1874
1982
|
|
|
@@ -1972,27 +2080,29 @@
|
|
|
1972
2080
|
axis overrides `--el-*`, never `--color-*`, which keeps the horizon orthogonal
|
|
1973
2081
|
to the palette. Painted as the body's own background (always behind content),
|
|
1974
2082
|
the proven 3D/Immersive atmosphere approach. */
|
|
1975
|
-
[data-style='retrofuturism']
|
|
1976
|
-
|
|
1977
|
-
|
|
1978
|
-
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1984
|
-
|
|
1985
|
-
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
|
|
1990
|
-
|
|
1991
|
-
|
|
1992
|
-
|
|
1993
|
-
|
|
1994
|
-
|
|
1995
|
-
|
|
2083
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2084
|
+
body {
|
|
2085
|
+
background-image:
|
|
2086
|
+
linear-gradient(
|
|
2087
|
+
180deg,
|
|
2088
|
+
transparent 54%,
|
|
2089
|
+
color-mix(in srgb, var(--el-highlight) var(--retro-horizon), transparent) 60.5%,
|
|
2090
|
+
color-mix(in srgb, var(--el-accent) var(--retro-horizon), transparent) 62.5%,
|
|
2091
|
+
transparent 69%
|
|
2092
|
+
),
|
|
2093
|
+
linear-gradient(
|
|
2094
|
+
180deg,
|
|
2095
|
+
color-mix(in srgb, var(--el-link) var(--retro-sky), transparent),
|
|
2096
|
+
transparent 46%
|
|
2097
|
+
),
|
|
2098
|
+
linear-gradient(
|
|
2099
|
+
0deg,
|
|
2100
|
+
color-mix(in srgb, var(--el-accent) var(--retro-ground), transparent),
|
|
2101
|
+
transparent 42%
|
|
2102
|
+
);
|
|
2103
|
+
background-size: 100% 100%;
|
|
2104
|
+
background-attachment: fixed;
|
|
2105
|
+
}
|
|
1996
2106
|
}
|
|
1997
2107
|
|
|
1998
2108
|
/* The Outrun GRID FLOOR — a receding neon grid below the horizon. A separate
|
|
@@ -2003,31 +2113,33 @@
|
|
|
2003
2113
|
their own); the mask uses the achromatic `black` keyword (no hex). The grid is
|
|
2004
2114
|
STATIC depth — like 3D/Immersive's atmosphere it carries the identity, so it is
|
|
2005
2115
|
not motion-gated (there is no animation to suppress). */
|
|
2006
|
-
[data-style='retrofuturism']
|
|
2007
|
-
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2018
|
-
|
|
2019
|
-
|
|
2020
|
-
|
|
2021
|
-
|
|
2022
|
-
|
|
2023
|
-
|
|
2024
|
-
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
|
|
2029
|
-
|
|
2030
|
-
|
|
2116
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2117
|
+
body::after {
|
|
2118
|
+
content: '';
|
|
2119
|
+
position: fixed;
|
|
2120
|
+
left: -30%;
|
|
2121
|
+
right: -30%;
|
|
2122
|
+
bottom: 0;
|
|
2123
|
+
height: 42vh;
|
|
2124
|
+
background-image:
|
|
2125
|
+
repeating-linear-gradient(
|
|
2126
|
+
0deg,
|
|
2127
|
+
color-mix(in srgb, var(--el-highlight) var(--retro-grid), transparent) 0 2px,
|
|
2128
|
+
transparent 2px var(--retro-grid-size)
|
|
2129
|
+
),
|
|
2130
|
+
repeating-linear-gradient(
|
|
2131
|
+
90deg,
|
|
2132
|
+
color-mix(in srgb, var(--el-accent) var(--retro-grid), transparent) 0 2px,
|
|
2133
|
+
transparent 2px var(--retro-grid-size)
|
|
2134
|
+
);
|
|
2135
|
+
background-size: var(--retro-grid-size) var(--retro-grid-size);
|
|
2136
|
+
transform: perspective(300px) rotateX(75deg);
|
|
2137
|
+
transform-origin: bottom center;
|
|
2138
|
+
-webkit-mask-image: linear-gradient(to top, black 2%, transparent 80%);
|
|
2139
|
+
mask-image: linear-gradient(to top, black 2%, transparent 80%);
|
|
2140
|
+
pointer-events: none;
|
|
2141
|
+
z-index: -1;
|
|
2142
|
+
}
|
|
2031
2143
|
}
|
|
2032
2144
|
|
|
2033
2145
|
/* Chrome container surfaces — OPAQUE (text AA is preserved against the base
|
|
@@ -2039,73 +2151,79 @@
|
|
|
2039
2151
|
so they never pull a surface far from its base tone; the inset top/bottom lines
|
|
2040
2152
|
are the lit chrome rim. Applied to EVERY panel via the global card-radius
|
|
2041
2153
|
utility (the 3D/Immersive coverage approach), not just the <Card> primitive. */
|
|
2042
|
-
[data-style='retrofuturism'] [data-
|
|
2043
|
-
[data-
|
|
2044
|
-
[data-
|
|
2045
|
-
|
|
2046
|
-
|
|
2047
|
-
|
|
2048
|
-
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2154
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2155
|
+
[data-surface='card'],
|
|
2156
|
+
[data-surface='popover'],
|
|
2157
|
+
.rounded-\(--radius-card\) {
|
|
2158
|
+
background-color: var(--el-surface);
|
|
2159
|
+
background-image:
|
|
2160
|
+
linear-gradient(
|
|
2161
|
+
158deg,
|
|
2162
|
+
transparent 36%,
|
|
2163
|
+
color-mix(in srgb, white var(--retro-spec), transparent) 49%,
|
|
2164
|
+
transparent 62%
|
|
2165
|
+
),
|
|
2166
|
+
linear-gradient(
|
|
2167
|
+
180deg,
|
|
2168
|
+
color-mix(in srgb, white var(--retro-bevel-light), transparent) 0%,
|
|
2169
|
+
transparent 16%,
|
|
2170
|
+
transparent 78%,
|
|
2171
|
+
color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
|
|
2172
|
+
);
|
|
2173
|
+
box-shadow:
|
|
2174
|
+
var(--shadow-card),
|
|
2175
|
+
inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
|
|
2176
|
+
inset 0 -1px 0 color-mix(in srgb, black 24%, transparent),
|
|
2177
|
+
0 0 28px -8px color-mix(in srgb, var(--el-accent) var(--retro-glow), transparent);
|
|
2178
|
+
}
|
|
2065
2179
|
}
|
|
2066
2180
|
|
|
2067
2181
|
/* Modal panel — the same chrome, with a deeper palette glow so the dialog
|
|
2068
2182
|
separates cleanly from the grid behind it (and body text stays on the solid
|
|
2069
2183
|
surface). Overrides the card-radius rule above for the modal radius. */
|
|
2070
|
-
[data-style='retrofuturism'] [data-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
|
|
2074
|
-
|
|
2075
|
-
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
|
|
2089
|
-
|
|
2184
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2185
|
+
[data-surface='modal'] {
|
|
2186
|
+
background-color: var(--el-surface);
|
|
2187
|
+
background-image:
|
|
2188
|
+
linear-gradient(
|
|
2189
|
+
158deg,
|
|
2190
|
+
transparent 34%,
|
|
2191
|
+
color-mix(in srgb, white var(--retro-spec), transparent) 49%,
|
|
2192
|
+
transparent 64%
|
|
2193
|
+
),
|
|
2194
|
+
linear-gradient(
|
|
2195
|
+
180deg,
|
|
2196
|
+
color-mix(in srgb, white var(--retro-bevel-light), transparent) 0%,
|
|
2197
|
+
transparent 14%,
|
|
2198
|
+
transparent 80%,
|
|
2199
|
+
color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
|
|
2200
|
+
);
|
|
2201
|
+
box-shadow:
|
|
2202
|
+
var(--shadow-modal),
|
|
2203
|
+
inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
|
|
2204
|
+
0 0 56px -14px color-mix(in srgb, var(--el-highlight) var(--retro-glow-strong), transparent);
|
|
2205
|
+
}
|
|
2090
2206
|
}
|
|
2091
2207
|
|
|
2092
2208
|
/* The sidebar rail — opaque chrome with a quieter specular + bevel so it reads as
|
|
2093
2209
|
part of the polished-metal family, not a flat slab. */
|
|
2094
|
-
[data-style='retrofuturism'] [data-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
|
|
2101
|
-
|
|
2102
|
-
|
|
2103
|
-
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2210
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2211
|
+
[data-surface='sidebar'] {
|
|
2212
|
+
background-color: var(--el-sidebar-bg);
|
|
2213
|
+
background-image:
|
|
2214
|
+
linear-gradient(
|
|
2215
|
+
158deg,
|
|
2216
|
+
transparent 40%,
|
|
2217
|
+
color-mix(in srgb, white var(--retro-sheen), transparent) 50%,
|
|
2218
|
+
transparent 60%
|
|
2219
|
+
),
|
|
2220
|
+
linear-gradient(
|
|
2221
|
+
180deg,
|
|
2222
|
+
color-mix(in srgb, white var(--retro-sheen), transparent),
|
|
2223
|
+
transparent 24%,
|
|
2224
|
+
color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
|
|
2225
|
+
);
|
|
2226
|
+
}
|
|
2109
2227
|
}
|
|
2110
2228
|
|
|
2111
2229
|
/* Text inputs (a TYPING field) — a RECESSED chrome well: the bevel inverts (a
|
|
@@ -2113,14 +2231,16 @@
|
|
|
2113
2231
|
metal. Clickable controls (dropdown / select / picker triggers + buttons) get
|
|
2114
2232
|
the RAISED chrome below instead — matching the CTA — so a typing field stays
|
|
2115
2233
|
recessed while everything you click reads as a raised chrome control. */
|
|
2116
|
-
[data-style='retrofuturism'] [data-
|
|
2117
|
-
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2234
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2235
|
+
[data-surface='input'] {
|
|
2236
|
+
background-color: var(--el-page-bg);
|
|
2237
|
+
background-image: linear-gradient(
|
|
2238
|
+
180deg,
|
|
2239
|
+
color-mix(in srgb, black var(--retro-sheen), transparent) 0%,
|
|
2240
|
+
transparent 34%
|
|
2241
|
+
);
|
|
2242
|
+
box-shadow: inset 0 1px 3px color-mix(in srgb, black var(--retro-glow), transparent);
|
|
2243
|
+
}
|
|
2124
2244
|
}
|
|
2125
2245
|
|
|
2126
2246
|
/* ── EVERY clickable control reads as RETRO CHROME (7.3.40) ──────────────────
|
|
@@ -2151,46 +2271,50 @@
|
|
|
2151
2271
|
/* FILLED CTAs — accent (primary) keeps its hue under a diagonal specular glint +
|
|
2152
2272
|
a vertical metallic sweep + a palette glow. Keyed on the fill class so it
|
|
2153
2273
|
covers the `Button` primitive AND `buttonVariants()` anchors alike. */
|
|
2154
|
-
[data-style='retrofuturism']
|
|
2155
|
-
|
|
2156
|
-
|
|
2157
|
-
|
|
2158
|
-
|
|
2159
|
-
|
|
2160
|
-
|
|
2161
|
-
|
|
2162
|
-
|
|
2163
|
-
|
|
2164
|
-
|
|
2165
|
-
|
|
2166
|
-
|
|
2167
|
-
|
|
2168
|
-
|
|
2169
|
-
|
|
2170
|
-
|
|
2171
|
-
|
|
2274
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2275
|
+
.rounded-\(--radius-btn\).bg-\(--el-accent\) {
|
|
2276
|
+
background-image:
|
|
2277
|
+
linear-gradient(
|
|
2278
|
+
158deg,
|
|
2279
|
+
transparent 38%,
|
|
2280
|
+
color-mix(in srgb, white var(--retro-spec), transparent) 50%,
|
|
2281
|
+
transparent 62%
|
|
2282
|
+
),
|
|
2283
|
+
linear-gradient(
|
|
2284
|
+
180deg,
|
|
2285
|
+
color-mix(in srgb, white var(--retro-spec), var(--el-accent)) 0%,
|
|
2286
|
+
var(--el-accent) 46%,
|
|
2287
|
+
color-mix(in srgb, black var(--retro-bevel-shade), var(--el-accent)) 100%
|
|
2288
|
+
);
|
|
2289
|
+
box-shadow:
|
|
2290
|
+
var(--shadow-subtle),
|
|
2291
|
+
inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
|
|
2292
|
+
0 0 22px -6px color-mix(in srgb, var(--el-accent) var(--retro-glow-strong), transparent);
|
|
2293
|
+
}
|
|
2172
2294
|
}
|
|
2173
2295
|
|
|
2174
2296
|
/* Danger CTAs — the same machined sweep, in the danger hue (so a destructive
|
|
2175
2297
|
button reads as red chrome, not a flat red, matching the accent CTA). */
|
|
2176
|
-
[data-style='retrofuturism']
|
|
2177
|
-
|
|
2178
|
-
|
|
2179
|
-
|
|
2180
|
-
|
|
2181
|
-
|
|
2182
|
-
|
|
2183
|
-
|
|
2184
|
-
|
|
2185
|
-
|
|
2186
|
-
|
|
2187
|
-
|
|
2188
|
-
|
|
2189
|
-
|
|
2190
|
-
|
|
2191
|
-
|
|
2192
|
-
|
|
2193
|
-
|
|
2298
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2299
|
+
.rounded-\(--radius-btn\).bg-\(--el-danger\) {
|
|
2300
|
+
background-image:
|
|
2301
|
+
linear-gradient(
|
|
2302
|
+
158deg,
|
|
2303
|
+
transparent 38%,
|
|
2304
|
+
color-mix(in srgb, white var(--retro-spec), transparent) 50%,
|
|
2305
|
+
transparent 62%
|
|
2306
|
+
),
|
|
2307
|
+
linear-gradient(
|
|
2308
|
+
180deg,
|
|
2309
|
+
color-mix(in srgb, white var(--retro-spec), var(--el-danger)) 0%,
|
|
2310
|
+
var(--el-danger) 46%,
|
|
2311
|
+
color-mix(in srgb, black var(--retro-bevel-shade), var(--el-danger)) 100%
|
|
2312
|
+
);
|
|
2313
|
+
box-shadow:
|
|
2314
|
+
var(--shadow-subtle),
|
|
2315
|
+
inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
|
|
2316
|
+
0 0 22px -6px color-mix(in srgb, var(--el-danger) var(--retro-glow-strong), transparent);
|
|
2317
|
+
}
|
|
2194
2318
|
}
|
|
2195
2319
|
|
|
2196
2320
|
/* NEUTRAL STEEL chrome — every OTHER clickable control: bordered buttons + links
|
|
@@ -2199,67 +2323,74 @@
|
|
|
2199
2323
|
`:not([role='group'])` excludes the segmented TRACK (its own rule below); the
|
|
2200
2324
|
FILLED CTAs are excluded automatically (they carry a fill class, not `.border`).
|
|
2201
2325
|
The gunmetal base is set here because secondary controls ship `bg-transparent`. */
|
|
2202
|
-
[data-style='retrofuturism']
|
|
2203
|
-
|
|
2204
|
-
|
|
2205
|
-
|
|
2206
|
-
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2211
|
-
|
|
2212
|
-
|
|
2213
|
-
|
|
2214
|
-
|
|
2215
|
-
|
|
2216
|
-
|
|
2217
|
-
|
|
2218
|
-
|
|
2219
|
-
|
|
2220
|
-
|
|
2221
|
-
|
|
2222
|
-
|
|
2223
|
-
|
|
2326
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2327
|
+
.rounded-\(--radius-btn\).border:not([role='group']),
|
|
2328
|
+
button.rounded-\(--radius-input\) {
|
|
2329
|
+
background-color: color-mix(in srgb, black 24%, var(--el-surface));
|
|
2330
|
+
background-image:
|
|
2331
|
+
linear-gradient(
|
|
2332
|
+
158deg,
|
|
2333
|
+
transparent 36%,
|
|
2334
|
+
color-mix(in srgb, white var(--retro-spec), transparent) 50%,
|
|
2335
|
+
transparent 64%
|
|
2336
|
+
),
|
|
2337
|
+
linear-gradient(
|
|
2338
|
+
180deg,
|
|
2339
|
+
color-mix(in srgb, white var(--retro-bevel-light), transparent) 0%,
|
|
2340
|
+
transparent 42%,
|
|
2341
|
+
transparent 60%,
|
|
2342
|
+
color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
|
|
2343
|
+
);
|
|
2344
|
+
box-shadow:
|
|
2345
|
+
var(--shadow-subtle),
|
|
2346
|
+
inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
|
|
2347
|
+
inset 0 -1px 0 color-mix(in srgb, black 24%, transparent),
|
|
2348
|
+
0 0 18px -8px color-mix(in srgb, var(--el-accent) var(--retro-glow), transparent);
|
|
2349
|
+
}
|
|
2224
2350
|
}
|
|
2225
2351
|
|
|
2226
2352
|
/* SEGMENTED control (the board "Group by" switch + every other `Segmented` use):
|
|
2227
2353
|
the classic metal segmented control — a RECESSED gunmetal TRACK (the
|
|
2228
2354
|
`[role='group']` wrapper) with the ACTIVE segment (`aria-pressed='true'`) raised
|
|
2229
2355
|
out of it as a chrome chip. Inactive segments stay transparent on the track. */
|
|
2230
|
-
[data-style='retrofuturism'] [
|
|
2231
|
-
|
|
2232
|
-
|
|
2356
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2357
|
+
[role='group'].rounded-\(--radius-btn\) {
|
|
2358
|
+
background-color: color-mix(in srgb, black 15%, var(--el-surface));
|
|
2359
|
+
box-shadow: inset 0 1px 3px color-mix(in srgb, black var(--retro-glow), transparent);
|
|
2360
|
+
}
|
|
2233
2361
|
}
|
|
2234
|
-
[data-style='retrofuturism']
|
|
2235
|
-
|
|
2236
|
-
|
|
2237
|
-
|
|
2238
|
-
|
|
2239
|
-
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2362
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2363
|
+
[role='group'] [aria-pressed='true'] {
|
|
2364
|
+
background-color: color-mix(in srgb, black 24%, var(--el-surface));
|
|
2365
|
+
background-image:
|
|
2366
|
+
linear-gradient(
|
|
2367
|
+
158deg,
|
|
2368
|
+
transparent 36%,
|
|
2369
|
+
color-mix(in srgb, white var(--retro-spec), transparent) 50%,
|
|
2370
|
+
transparent 64%
|
|
2371
|
+
),
|
|
2372
|
+
linear-gradient(
|
|
2373
|
+
180deg,
|
|
2374
|
+
color-mix(in srgb, white var(--retro-bevel-light), transparent) 0%,
|
|
2375
|
+
transparent 42%,
|
|
2376
|
+
transparent 60%,
|
|
2377
|
+
color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
|
|
2378
|
+
);
|
|
2379
|
+
box-shadow:
|
|
2380
|
+
var(--shadow-subtle),
|
|
2381
|
+
inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
|
|
2382
|
+
inset 0 -1px 0 color-mix(in srgb, black 24%, transparent);
|
|
2383
|
+
}
|
|
2254
2384
|
}
|
|
2255
2385
|
|
|
2256
2386
|
/* Hover — brighten the steel a touch (the controls' own `hover:bg-*` utilities
|
|
2257
2387
|
are out-specified by the rules above, so restore a clear hover signal). */
|
|
2258
|
-
[data-style='retrofuturism']
|
|
2388
|
+
@scope ([data-style='retrofuturism']) to ([data-style]) {
|
|
2259
2389
|
.rounded-\(--radius-btn\).border:not([role='group']):hover:not(:disabled),
|
|
2260
|
-
|
|
2261
|
-
[
|
|
2262
|
-
|
|
2390
|
+
button.rounded-\(--radius-input\):hover:not(:disabled),
|
|
2391
|
+
[role='group'] [aria-pressed='false']:hover:not(:disabled) {
|
|
2392
|
+
background-color: color-mix(in srgb, black 14%, var(--el-surface));
|
|
2393
|
+
}
|
|
2263
2394
|
}
|
|
2264
2395
|
|
|
2265
2396
|
/* ─────────────────────────────────────────────────────────────────────────
|
|
@@ -2510,16 +2641,48 @@
|
|
|
2510
2641
|
asset carries the correction and the measurement. */
|
|
2511
2642
|
/* pink — BUILT, waiting on checks (MOTIR-3003). The one saturated Tier-0 hue
|
|
2512
2643
|
no other STATUS spends; sharing a hue across FAMILIES is this file's own
|
|
2513
|
-
convention (--el-type-epic is also --color-accent).
|
|
2514
|
-
nearest neighbour in this palette.
|
|
2644
|
+
convention (--el-type-epic is also --color-accent).
|
|
2515
2645
|
⚠️ FIVE palettes re-map --color-accent onto something a status already uses,
|
|
2516
2646
|
so each carries its own override below — the same per-palette follow-up
|
|
2517
2647
|
--el-status-planning needed in citrine and candy (MOTIR-2425). Measured by
|
|
2518
2648
|
tests/theme/statusHueSeparation.test.ts, which now folds a color-mix rather
|
|
2519
|
-
than throwing on one.
|
|
2520
|
-
|
|
2649
|
+
than throwing on one.
|
|
2650
|
+
⚠️ STEPPED TOWARD THE INK (MOTIR-3954). The bare --color-accent was 2.66:1 on
|
|
2651
|
+
--el-card and 2.44:1 on --el-surface in the BASE palette's LIGHT theme —
|
|
2652
|
+
under 1.4.11's 3:1 for a graphical object, and the one palette x theme in
|
|
2653
|
+
which this token missed the bar. A saturated pink at Radix-9 lightness has
|
|
2654
|
+
nowhere to go on white, so the recipe takes one step of the palette's own
|
|
2655
|
+
emphasis ink instead of a new hue: #cd58a2, 3.81 / 3.50 / 3.81 on
|
|
2656
|
+
card / surface / page-bg. --color-charcoal flips with the theme (#37352f
|
|
2657
|
+
light, #e5e5e5 dark), so the same expression DARKENS on white and LIGHTENS
|
|
2658
|
+
on near-black — dark goes 7.22 -> 8.42:1. Both inputs stay palette-tuned, so
|
|
2659
|
+
the four palettes that ride this base value (cobalt, evergreen, spectrum,
|
|
2660
|
+
garnet) re-skin it as before and each GAINS contrast; ΔE2000 to the nearest
|
|
2661
|
+
sibling stays >= 13.7 in all ten palettes x both themes (27.1 / 26.8 here).
|
|
2662
|
+
Why the base and not a [data-palette='motir'] block: <html> carries no
|
|
2663
|
+
data-appearance-scope, so a root palette block would be a second cascade
|
|
2664
|
+
nobody renders — the base layer IS how the browser reaches these values. */
|
|
2665
|
+
--el-status-implemented: color-mix(in srgb, var(--color-accent) 75%, var(--color-charcoal));
|
|
2521
2666
|
--el-status-in-review: var(--color-primary); /* brand — differentiate from in-progress */
|
|
2522
|
-
|
|
2667
|
+
/* green — RESOLVED (MOTIR-3991). The bare --color-success (#1aae39) was
|
|
2668
|
+
2.93:1 on --el-card and 2.69:1 on --el-surface in the BASE palette's LIGHT
|
|
2669
|
+
theme — under 1.4.11's 3:1 for a graphical object, and the one palette x
|
|
2670
|
+
theme in which this token missed the bar. --color-success is NOT free to
|
|
2671
|
+
move: the same Tier-0 hue paints --el-success-surface's companion ink, the
|
|
2672
|
+
success toast/notice family and the chart-success step, each held to its
|
|
2673
|
+
own AA bar that pulls opposite to a dot's 3:1 — so the ramp takes one step
|
|
2674
|
+
of the palette's own emphasis ink instead of re-tuning the source. 85% of
|
|
2675
|
+
--color-success toward --color-charcoal gives #1e9c38, 3.58 / 3.29 / 3.58
|
|
2676
|
+
on card / surface / page-bg. --color-charcoal flips with the theme
|
|
2677
|
+
(#37352f light, #e5e5e5 dark), so the same expression DARKENS on white and
|
|
2678
|
+
LIGHTENS on near-black — dark goes 7.29 / 6.62 / 7.29:1. Both inputs stay
|
|
2679
|
+
palette-tuned, so the nine palettes that ride this base value re-skin it as
|
|
2680
|
+
before and each keeps its own --color-success; ΔE2000 to the nearest
|
|
2681
|
+
sibling stays >= 11.3 in all ten palettes x both themes. Why the base and
|
|
2682
|
+
not a [data-palette='motir'] block: same as --el-status-implemented above —
|
|
2683
|
+
<html> carries no data-appearance-scope, so the base layer IS how the
|
|
2684
|
+
browser reaches these values. */
|
|
2685
|
+
--el-status-done: color-mix(in srgb, var(--color-success) 85%, var(--color-charcoal));
|
|
2523
2686
|
--el-status-blocked: var(--color-warning); /* amber — can't proceed (gap fixed) */
|
|
2524
2687
|
--el-status-cancelled: var(--color-steel); /* terminal grey — not red (cancel ≠ error) */
|
|
2525
2688
|
|
|
@@ -3043,6 +3206,125 @@
|
|
|
3043
3206
|
/* `motir` needs no block — it is the Tier-3 base above. Each later palette
|
|
3044
3207
|
ADDS its [data-palette='<id>'] override here (light + dark companion). */
|
|
3045
3208
|
|
|
3209
|
+
/* ── The `motir` BASE palette, re-asserted for a SCOPED subtree (MOTIR-3933) ──
|
|
3210
|
+
`motir` is the Tier-0 default, so it historically had NO block: the base
|
|
3211
|
+
values simply were the palette. That is correct for `<html>` and wrong for a
|
|
3212
|
+
NESTED scope, which inherits its ancestor's palette and has nothing to
|
|
3213
|
+
override it with — a `motir` preview under a `graphite` document rendered as
|
|
3214
|
+
graphite. Every other palette re-asserts, so the base must too.
|
|
3215
|
+
|
|
3216
|
+
⚠️ SCOPED BY `[data-appearance-scope]`, DELIBERATELY. `<html>` never carries
|
|
3217
|
+
that attribute, so this block matches only a nested preview and the ROOT
|
|
3218
|
+
cascade is byte-identical to before. It also keeps the block from reading as
|
|
3219
|
+
a palette OVERRIDE: several `tests/theme/*` guards DERIVE "which palettes
|
|
3220
|
+
override this token" from the stylesheet, and a bare `[data-palette='motir']`
|
|
3221
|
+
block silently enrolled the BASE palette in bars written for overrides. It is
|
|
3222
|
+
not an override — it is a scope reset — and the selector now says so.
|
|
3223
|
+
|
|
3224
|
+
These values are COPIES, and the duplication is guarded rather than trusted:
|
|
3225
|
+
`tests/theme/scopedPreviewIsolation.test.ts` asserts each declaration here
|
|
3226
|
+
equals the value the base layer declares for that token, so a change to
|
|
3227
|
+
`@theme` that is not mirrored here fails rather than drifts. The token SET is
|
|
3228
|
+
the union of what any `[data-palette]` block overrides — a new palette that
|
|
3229
|
+
overrides a token absent here fails the same test.
|
|
3230
|
+
⚠️ The path above was `test/paletteScopeIsolation.test.tsx` until MOTIR-3954,
|
|
3231
|
+
which is a file that has never existed, and the VALUE assertion it promised
|
|
3232
|
+
had never been written either — only the token-SET one had. Both are true
|
|
3233
|
+
now. A citation to a guard is worth exactly as much as the guard. */
|
|
3234
|
+
[data-appearance-scope][data-palette='motir'] {
|
|
3235
|
+
--color-accent: #ff64c8;
|
|
3236
|
+
--color-accent-green: #1aae39;
|
|
3237
|
+
--color-accent-orange: #dd5b00;
|
|
3238
|
+
--color-accent-teal: #2a9d99;
|
|
3239
|
+
--color-background: #ffffff;
|
|
3240
|
+
--color-border: #e5e3df;
|
|
3241
|
+
--color-canvas: #ecebe7;
|
|
3242
|
+
--color-charcoal: #37352f;
|
|
3243
|
+
--color-destructive: #e03131;
|
|
3244
|
+
--color-destructive-foreground: #ffffff;
|
|
3245
|
+
--color-foreground: #1a1a1a;
|
|
3246
|
+
--color-hairline: #e5e3df;
|
|
3247
|
+
--color-hairline-soft: #ede9e4;
|
|
3248
|
+
--color-hairline-strong: #c8c4be;
|
|
3249
|
+
--color-info: #0075de;
|
|
3250
|
+
--color-ink: #1a1a1a;
|
|
3251
|
+
--color-link: #0070d2;
|
|
3252
|
+
--color-link-pressed: #005bab;
|
|
3253
|
+
--color-muted: #f3f4f6;
|
|
3254
|
+
--color-muted-foreground: #787671;
|
|
3255
|
+
--color-primary: #5645d4;
|
|
3256
|
+
--color-primary-fill: #5645d4;
|
|
3257
|
+
--color-primary-foreground: #ffffff;
|
|
3258
|
+
--color-primary-pressed: #4534b3;
|
|
3259
|
+
--color-slate: #5d5b54;
|
|
3260
|
+
--color-steel: #787671;
|
|
3261
|
+
--color-stone: #a4a097;
|
|
3262
|
+
--color-success: #1aae39;
|
|
3263
|
+
--color-surface: #f6f5f4;
|
|
3264
|
+
--color-surface-soft: #fafaf9;
|
|
3265
|
+
--color-tint-lavender: #e6e0f5;
|
|
3266
|
+
--color-tint-mint: #d9f3e1;
|
|
3267
|
+
--color-tint-peach: #ffe8d4;
|
|
3268
|
+
--color-tint-rose: #fde0ec;
|
|
3269
|
+
--color-tint-sky: #dcecfa;
|
|
3270
|
+
--color-tint-yellow: #fef7d6;
|
|
3271
|
+
--color-warning: #dd5b00;
|
|
3272
|
+
--el-priority-high: var(--color-warning);
|
|
3273
|
+
--el-sidebar-item-bg-hover: #eeede9;
|
|
3274
|
+
--el-status-blocked: var(--color-warning);
|
|
3275
|
+
--el-status-cancelled: var(--color-steel);
|
|
3276
|
+
--el-status-implemented: color-mix(in srgb, var(--color-accent) 75%, var(--color-charcoal));
|
|
3277
|
+
--el-status-in-review: var(--color-primary);
|
|
3278
|
+
--el-status-planning: var(--color-accent-teal);
|
|
3279
|
+
}
|
|
3280
|
+
|
|
3281
|
+
/* The base palette's DARK arm — only the tokens the global dark block
|
|
3282
|
+
overrides; the rest keep the light block's values above. Two selectors for
|
|
3283
|
+
the same reason every other palette now has two: the compound one for
|
|
3284
|
+
`<html>`, the descendant one for a nested scope. */
|
|
3285
|
+
[data-theme='dark'] [data-appearance-scope][data-palette='motir']:not([data-theme]),
|
|
3286
|
+
[data-appearance-scope][data-palette='motir'][data-theme='dark'] {
|
|
3287
|
+
--color-background: #0f0f0f;
|
|
3288
|
+
--color-border: #2a2a2a;
|
|
3289
|
+
--color-canvas: #0e0e0e;
|
|
3290
|
+
--color-charcoal: #e5e5e5;
|
|
3291
|
+
--color-foreground: #f3f4f6;
|
|
3292
|
+
--color-hairline: #2a2a2a;
|
|
3293
|
+
--color-hairline-soft: #1f1f1f;
|
|
3294
|
+
--color-hairline-strong: #3a3a3a;
|
|
3295
|
+
--color-ink: #f3f4f6;
|
|
3296
|
+
--color-link: #58a6ff;
|
|
3297
|
+
--color-link-pressed: #79b8ff;
|
|
3298
|
+
--color-muted: #1a1a1a;
|
|
3299
|
+
--color-muted-foreground: #a4a097;
|
|
3300
|
+
--color-primary: #7b6ce5;
|
|
3301
|
+
--color-primary-fill: #6c5cdd;
|
|
3302
|
+
--color-primary-foreground: #ffffff;
|
|
3303
|
+
--color-primary-pressed: #5645d4;
|
|
3304
|
+
--color-slate: #a4a097;
|
|
3305
|
+
--color-steel: #787671;
|
|
3306
|
+
--color-stone: #5d5b54;
|
|
3307
|
+
--color-surface: #1a1a1a;
|
|
3308
|
+
--color-surface-soft: #161616;
|
|
3309
|
+
--color-tint-lavender: #2a253a;
|
|
3310
|
+
--color-tint-mint: #1a2f25;
|
|
3311
|
+
--color-tint-peach: #3a2a1a;
|
|
3312
|
+
--color-tint-rose: #3a1f2a;
|
|
3313
|
+
--color-tint-sky: #1a2a3a;
|
|
3314
|
+
--color-tint-yellow: #3a341a;
|
|
3315
|
+
--el-sidebar-item-bg-hover: #222222;
|
|
3316
|
+
}
|
|
3317
|
+
|
|
3318
|
+
/* The `motir` BASE type pairing, re-asserted (MOTIR-3933) — same reason as
|
|
3319
|
+
the base palette above. The type axis carries no descendant rules, so these
|
|
3320
|
+
three role tokens are the whole of it. */
|
|
3321
|
+
[data-appearance-scope][data-type='motir'] {
|
|
3322
|
+
--font-mono: var(--font-mono-source, ui-monospace), 'SF Mono', Menlo, monospace;
|
|
3323
|
+
--font-sans:
|
|
3324
|
+
var(--font-sans-source, -apple-system), BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
3325
|
+
--font-serif: var(--font-serif-source, Georgia), serif;
|
|
3326
|
+
}
|
|
3327
|
+
|
|
3046
3328
|
/* ── Palette: Cobalt (data-palette="cobalt") — Subtask 7.3.49 ───────────────
|
|
3047
3329
|
A cool, calm, trustworthy INSTITUTIONAL-BLUE re-skin: slate-cool surfaces, a
|
|
3048
3330
|
confident cobalt primary/accent, a cool cyan highlight, cooled pastel tints.
|
|
@@ -3146,6 +3428,7 @@
|
|
|
3146
3428
|
/* Cobalt — dark companion. A cool navy canvas (not the base near-black);
|
|
3147
3429
|
brightened cobalt/link hues so they read AS text on the dark surface, and a
|
|
3148
3430
|
darker accent fill so white labels still clear AA. */
|
|
3431
|
+
[data-theme='dark'] [data-palette='cobalt']:not([data-theme]),
|
|
3149
3432
|
[data-palette='cobalt'][data-theme='dark'] {
|
|
3150
3433
|
--color-background: #0b111d; /* deep cool navy canvas */
|
|
3151
3434
|
--color-foreground: #e7edf6;
|
|
@@ -3344,6 +3627,7 @@
|
|
|
3344
3627
|
inverts to near-WHITE ink (Vercel's dark white-button), the accent blue
|
|
3345
3628
|
brightens so it reads AS text on the dark canvas, and semantic/type hues
|
|
3346
3629
|
brighten to clear AA on near-black. */
|
|
3630
|
+
[data-theme='dark'] [data-palette='graphite']:not([data-theme]),
|
|
3347
3631
|
[data-palette='graphite'][data-theme='dark'] {
|
|
3348
3632
|
--color-background: #0c0d0f; /* stark cool near-black canvas */
|
|
3349
3633
|
--color-foreground: #edeef0;
|
|
@@ -3519,6 +3803,7 @@
|
|
|
3519
3803
|
/* Evergreen — dark companion. Bright emerald on a deep-forest canvas
|
|
3520
3804
|
(Supabase-style: the bright accent FILL carries DARK label text). Mirrors the
|
|
3521
3805
|
Tier-1 dark flip for the cooled neutrals. */
|
|
3806
|
+
[data-theme='dark'] [data-palette='evergreen']:not([data-theme]),
|
|
3522
3807
|
[data-palette='evergreen'][data-theme='dark'] {
|
|
3523
3808
|
--color-primary: #3ddc97;
|
|
3524
3809
|
--color-primary-foreground: #06140d; /* dark ink on the bright emerald fill */
|
|
@@ -3611,6 +3896,15 @@
|
|
|
3611
3896
|
/* Sans headlines — re-point the editorial serif role at the sans stack. */
|
|
3612
3897
|
--font-serif:
|
|
3613
3898
|
var(--font-sans-source, -apple-system), BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
3899
|
+
/* Re-asserted at the BASE value, not omitted (MOTIR-3933). An omitted role
|
|
3900
|
+
inherits the ANCESTOR's, which is invisible on `<html>` and wrong in a
|
|
3901
|
+
nested scope: this pairing under a mono ancestor rendered mono. Unlike the
|
|
3902
|
+
colour axis there is no `[data-appearance-scope]` layer to fall back
|
|
3903
|
+
through — `--font-*` are role tokens, not `--el-*` — so every
|
|
3904
|
+
`[data-type]` block must be TOTAL over the three roles. */
|
|
3905
|
+
--font-sans:
|
|
3906
|
+
var(--font-sans-source, -apple-system), BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
3907
|
+
--font-mono: var(--font-mono-source, ui-monospace), 'SF Mono', Menlo, monospace;
|
|
3614
3908
|
}
|
|
3615
3909
|
|
|
3616
3910
|
[data-type='motir-mono'] {
|
|
@@ -3621,6 +3915,13 @@
|
|
|
3621
3915
|
already is mono. ONLY --font-* tokens (the disjointness guard). */
|
|
3622
3916
|
--font-serif: var(--font-mono-source, ui-monospace), 'SF Mono', Menlo, monospace;
|
|
3623
3917
|
--font-sans: var(--font-mono-source, ui-monospace), 'SF Mono', Menlo, monospace;
|
|
3918
|
+
/* Re-asserted at the BASE value, not omitted (MOTIR-3933). An omitted role
|
|
3919
|
+
inherits the ANCESTOR's, which is invisible on `<html>` and wrong in a
|
|
3920
|
+
nested scope: this pairing under a mono ancestor rendered mono. Unlike the
|
|
3921
|
+
colour axis there is no `[data-appearance-scope]` layer to fall back
|
|
3922
|
+
through — `--font-*` are role tokens, not `--el-*` — so every
|
|
3923
|
+
`[data-type]` block must be TOTAL over the three roles. */
|
|
3924
|
+
--font-mono: var(--font-mono-source, ui-monospace), 'SF Mono', Menlo, monospace;
|
|
3624
3925
|
}
|
|
3625
3926
|
|
|
3626
3927
|
/* ── Palette: Spectrum (data-palette="spectrum") — Subtask 7.3.52 ───────────
|
|
@@ -3725,6 +4026,7 @@
|
|
|
3725
4026
|
/* Spectrum — dark companion. A deep cool-violet canvas (not the base
|
|
3726
4027
|
near-black); brightened violet/pink/link hues so they read AS text on the
|
|
3727
4028
|
dark surface, and a darker accent fill so white labels still clear AA. */
|
|
4029
|
+
[data-theme='dark'] [data-palette='spectrum']:not([data-theme]),
|
|
3728
4030
|
[data-palette='spectrum'][data-theme='dark'] {
|
|
3729
4031
|
--color-background: #14111f; /* deep cool-violet canvas */
|
|
3730
4032
|
--color-foreground: #ece9f6;
|
|
@@ -3893,6 +4195,7 @@
|
|
|
3893
4195
|
canvas (#0B0E11) + "Shark" cards (#1E2329); the gold brightens to #FCD535 and
|
|
3894
4196
|
the CTA fill carries dark labels; semantics are Binance's real buy-green
|
|
3895
4197
|
#0ECB81 / sell-red #F6465D. */
|
|
4198
|
+
[data-theme='dark'] [data-palette='amber']:not([data-theme]),
|
|
3896
4199
|
[data-palette='amber'][data-theme='dark'] {
|
|
3897
4200
|
--color-background: #0b0e11; /* Binance deepest trading-floor black */
|
|
3898
4201
|
--color-foreground: #eaecef;
|
|
@@ -4048,6 +4351,7 @@
|
|
|
4048
4351
|
/* Sienna — dark companion. Mistral is light-dominant (few dark tokens: Mistral
|
|
4049
4352
|
Black #1f1f1f); a warm near-black canvas built from it, the flame brightened
|
|
4050
4353
|
to read as text, the fill a bright flame with dark-ink labels. */
|
|
4354
|
+
[data-theme='dark'] [data-palette='sienna']:not([data-theme]),
|
|
4051
4355
|
[data-palette='sienna'][data-theme='dark'] {
|
|
4052
4356
|
--color-background: #15120d; /* warm near-black canvas (from Mistral Black) */
|
|
4053
4357
|
--color-foreground: #f5efe2;
|
|
@@ -4191,6 +4495,7 @@
|
|
|
4191
4495
|
/* Garnet — dark companion. Pinterest's Cod-Gray near-black canvas; the red
|
|
4192
4496
|
brightens to read as text, the CTA fill stays the deep Pushpin red carrying
|
|
4193
4497
|
WHITE labels, semantics brighten to clear AA. */
|
|
4498
|
+
[data-theme='dark'] [data-palette='garnet']:not([data-theme]),
|
|
4194
4499
|
[data-palette='garnet'][data-theme='dark'] {
|
|
4195
4500
|
--color-background: #0e0e0e; /* Cod-Gray near-black canvas */
|
|
4196
4501
|
--color-foreground: #efefef;
|
|
@@ -4364,6 +4669,7 @@
|
|
|
4364
4669
|
#090909 / gray-900 #1a1b1e); the Sunglow yellow brightens to read as text and
|
|
4365
4670
|
the fill keeps dark Stratos labels; blue/green/red brighten one ramp step to
|
|
4366
4671
|
clear AA on the dark canvas. All values are documented Mirotone steps. */
|
|
4672
|
+
[data-theme='dark'] [data-palette='citrine']:not([data-theme]),
|
|
4367
4673
|
[data-palette='citrine'][data-theme='dark'] {
|
|
4368
4674
|
--color-background: #090909; /* Miro black */
|
|
4369
4675
|
--color-foreground: #f6f7f9; /* gray-50 */
|
|
@@ -4527,6 +4833,7 @@
|
|
|
4527
4833
|
1/2/3); the bubblegum pink brightens to read as text, the fill is a bright
|
|
4528
4834
|
candy pink with dark labels, and the rainbow tints become deep candy washes.
|
|
4529
4835
|
All values are documented Radix dark steps. */
|
|
4836
|
+
[data-theme='dark'] [data-palette='candy']:not([data-theme]),
|
|
4530
4837
|
[data-palette='candy'][data-theme='dark'] {
|
|
4531
4838
|
--color-background: #191117; /* Radix Pink dark-1 — pink-tinted black */
|
|
4532
4839
|
--color-foreground: #eeeef0; /* Mauve dark-12 */
|
|
@@ -4600,6 +4907,13 @@
|
|
|
4600
4907
|
disjointness guard): no colour (--el / --color) or shape token. */
|
|
4601
4908
|
--font-serif: var(--font-grotesk-source), ui-sans-serif, system-ui, sans-serif;
|
|
4602
4909
|
--font-sans: var(--font-grotesk-source), ui-sans-serif, system-ui, sans-serif;
|
|
4910
|
+
/* Re-asserted at the BASE value, not omitted (MOTIR-3933). An omitted role
|
|
4911
|
+
inherits the ANCESTOR's, which is invisible on `<html>` and wrong in a
|
|
4912
|
+
nested scope: this pairing under a mono ancestor rendered mono. Unlike the
|
|
4913
|
+
colour axis there is no `[data-appearance-scope]` layer to fall back
|
|
4914
|
+
through — `--font-*` are role tokens, not `--el-*` — so every
|
|
4915
|
+
`[data-type]` block must be TOTAL over the three roles. */
|
|
4916
|
+
--font-mono: var(--font-mono-source, ui-monospace), 'SF Mono', Menlo, monospace;
|
|
4603
4917
|
}
|
|
4604
4918
|
|
|
4605
4919
|
[data-type='editorial'] {
|
|
@@ -4611,6 +4925,15 @@
|
|
|
4611
4925
|
size tweak. ONLY --font-* role tokens here (the disjointness guard): no
|
|
4612
4926
|
colour (--el/--color) or shape (--radius/--spacing/--shadow) token. */
|
|
4613
4927
|
--font-serif: var(--font-editorial-source), 'Fraunces', Georgia, serif;
|
|
4928
|
+
/* Re-asserted at the BASE value, not omitted (MOTIR-3933). An omitted role
|
|
4929
|
+
inherits the ANCESTOR's, which is invisible on `<html>` and wrong in a
|
|
4930
|
+
nested scope: this pairing under a mono ancestor rendered mono. Unlike the
|
|
4931
|
+
colour axis there is no `[data-appearance-scope]` layer to fall back
|
|
4932
|
+
through — `--font-*` are role tokens, not `--el-*` — so every
|
|
4933
|
+
`[data-type]` block must be TOTAL over the three roles. */
|
|
4934
|
+
--font-sans:
|
|
4935
|
+
var(--font-sans-source, -apple-system), BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
4936
|
+
--font-mono: var(--font-mono-source, ui-monospace), 'SF Mono', Menlo, monospace;
|
|
4614
4937
|
}
|
|
4615
4938
|
|
|
4616
4939
|
[data-type='mono-technical'] {
|