@motir/design-system 0.1.2 → 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/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'] body {
558
- background-image:
559
- radial-gradient(
560
- 85% 80% at 6% -12%,
561
- color-mix(in srgb, var(--el-accent) var(--glass-wash), transparent),
562
- transparent 62%
563
- ),
564
- radial-gradient(
565
- 80% 75% at 110% 4%,
566
- color-mix(in srgb, var(--el-highlight) var(--glass-wash), transparent),
567
- transparent 60%
568
- ),
569
- radial-gradient(
570
- 95% 90% at 50% 120%,
571
- color-mix(in srgb, var(--el-link) var(--glass-wash), transparent),
572
- transparent 62%
573
- ),
574
- radial-gradient(
575
- 60% 60% at 85% 95%,
576
- color-mix(in srgb, var(--el-accent) var(--glass-wash), transparent),
577
- transparent 60%
578
- );
579
- background-attachment: fixed;
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-surface='card'],
584
- [data-style='glassmorphism'] [data-surface='popover'] {
585
- /* The translucent fill lets the vibrant canvas through; the linear sheen is
586
- the light raking across the glass (top-left fading), the inset RIM is the
587
- lit glass edge, and the soft drop makes the sheet FLOAT. White light is
588
- palette-agnostic; the colour still comes only from the palette-derived
589
- fill/border, so the axes stay disjoint. */
590
- background-color: color-mix(in srgb, var(--el-page-bg) var(--glass-surface-alpha), transparent);
591
- background-image: linear-gradient(150deg, var(--glass-sheen), transparent 55%);
592
- border-color: color-mix(in srgb, var(--el-border) var(--glass-border-alpha), transparent);
593
- box-shadow:
594
- inset 0 1px 0 0 var(--glass-rim),
595
- inset 0 0 0 1px rgba(255, 255, 255, 0.06),
596
- 0 8px 32px -8px rgba(15, 15, 15, 0.18);
597
- -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
598
- backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
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-surface='modal'] {
603
- background-color: color-mix(in srgb, var(--el-page-bg) var(--glass-modal-alpha), transparent);
604
- background-image: linear-gradient(150deg, var(--glass-sheen), transparent 55%);
605
- border-color: color-mix(in srgb, var(--el-border) var(--glass-border-alpha), transparent);
606
- box-shadow:
607
- inset 0 1px 0 0 var(--glass-rim),
608
- 0 28px 70px -16px rgba(15, 15, 15, 0.34);
609
- -webkit-backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
610
- backdrop-filter: blur(var(--glass-blur-strong)) saturate(var(--glass-saturate));
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-surface='sidebar'] {
615
- background-color: color-mix(in srgb, var(--el-sidebar-bg) var(--glass-chrome-alpha), transparent);
616
- -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
617
- backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
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-surface='input'] {
622
- background-color: color-mix(in srgb, var(--el-page-bg) var(--glass-input-alpha), transparent);
623
- -webkit-backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
624
- backdrop-filter: blur(var(--glass-blur)) saturate(var(--glass-saturate));
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-surface='overlay'] {
633
- background-color: color-mix(in srgb, var(--el-page-bg) 24%, transparent);
634
- -webkit-backdrop-filter: blur(8px) saturate(var(--glass-saturate));
635
- backdrop-filter: blur(8px) saturate(var(--glass-saturate));
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'] .border {
715
- border-width: 2px;
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'] body {
799
- background-image:
800
- linear-gradient(color-mix(in srgb, currentColor 6%, transparent) 1px, transparent 1px),
801
- linear-gradient(90deg, color-mix(in srgb, currentColor 6%, transparent) 1px, transparent 1px);
802
- background-size: 32px 32px;
803
- background-position: center top;
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'] body {
901
- background-image:
902
- radial-gradient(
903
- 58% 75% at 12% 0%,
904
- color-mix(in srgb, var(--el-accent) var(--aurora-wash), transparent),
905
- transparent 60%
906
- ),
907
- radial-gradient(
908
- 54% 70% at 92% 8%,
909
- color-mix(in srgb, var(--el-highlight) var(--aurora-wash), transparent),
910
- transparent 58%
911
- ),
912
- radial-gradient(
913
- 68% 82% at 62% 104%,
914
- color-mix(in srgb, var(--el-link) var(--aurora-wash), transparent),
915
- transparent 62%
916
- ),
917
- radial-gradient(
918
- 48% 64% at 34% 58%,
919
- color-mix(in srgb, var(--el-info) var(--aurora-wash-soft), transparent),
920
- transparent 55%
921
- );
922
- background-size: 180% 180%;
923
- background-attachment: fixed;
924
- animation: aurora-drift var(--aurora-drift-duration) ease-in-out infinite alternate;
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'] body {
948
- animation: none;
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-surface='card'],
959
- [data-style='aurora'] [data-surface='popover'] {
960
- background-color: var(--el-surface);
961
- background-image: linear-gradient(
962
- 180deg,
963
- color-mix(in srgb, var(--el-highlight) var(--aurora-sheen), transparent),
964
- transparent 42%
965
- );
966
- box-shadow:
967
- var(--shadow-card),
968
- 0 0 26px -8px color-mix(in srgb, var(--el-accent) var(--aurora-glow), transparent),
969
- 0 0 40px -14px color-mix(in srgb, var(--el-link) var(--aurora-glow), transparent);
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-surface='modal'] {
975
- background-color: var(--el-surface);
976
- background-image: linear-gradient(
977
- 180deg,
978
- color-mix(in srgb, var(--el-highlight) var(--aurora-sheen), transparent),
979
- transparent 38%
980
- );
981
- box-shadow:
982
- var(--shadow-modal),
983
- 0 0 60px -16px color-mix(in srgb, var(--el-accent) var(--aurora-glow-strong), transparent);
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-surface='sidebar'] {
989
- background-color: var(--el-sidebar-bg);
990
- background-image: linear-gradient(
991
- 180deg,
992
- color-mix(in srgb, var(--el-accent) var(--aurora-sheen), transparent),
993
- transparent 30%
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'] body {
1090
- background-image:
1091
- radial-gradient(
1092
- 130% 85% at 50% -15%,
1093
- color-mix(in srgb, var(--el-accent) 9%, transparent),
1094
- transparent 60%
1095
- ),
1096
- radial-gradient(
1097
- 95% 75% at 108% 112%,
1098
- color-mix(in srgb, var(--el-link) 8%, transparent),
1099
- transparent 55%
1100
- ),
1101
- radial-gradient(
1102
- 150% 130% at 50% 42%,
1103
- transparent 52%,
1104
- color-mix(in srgb, var(--el-text) 8%, transparent)
1105
- );
1106
- background-attachment: fixed;
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'] .rounded-\(--radius-card\) {
1122
- box-shadow: var(--shadow-card);
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'] .rounded-\(--radius-modal\) {
1125
- box-shadow: var(--shadow-modal);
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-tilt] {
1151
- transition:
1152
- transform 400ms cubic-bezier(0.22, 1, 0.36, 1),
1153
- box-shadow 260ms ease-out;
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-tilt][data-tilt-active='1'] {
1163
- transform: perspective(var(--tilt-perspective, 900px)) rotateX(var(--tilt-rx, 0deg))
1164
- rotateY(var(--tilt-ry, 0deg));
1165
- transform-style: preserve-3d;
1166
- transition:
1167
- transform 80ms linear,
1168
- box-shadow 260ms ease-out;
1169
- box-shadow: var(--shadow-elevated);
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'] [data-tilt][data-tilt-active='1'] [data-tilt-layer='front'] {
1179
- transform: translateZ(42px);
1180
- transition: transform 80ms linear;
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'] [data-tilt][data-tilt-active='1'] [data-tilt-layer='back'] {
1183
- transform: translateZ(14px);
1184
- transition: transform 80ms linear;
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-tilt]::after {
1193
- content: '';
1194
- position: absolute;
1195
- inset: 0;
1196
- border-radius: inherit;
1197
- background: radial-gradient(
1198
- circle at var(--tilt-glare-x, 50%) var(--tilt-glare-y, 50%),
1199
- color-mix(in srgb, var(--el-page-bg) 65%, transparent),
1200
- transparent 55%
1201
- );
1202
- opacity: 0;
1203
- transition: opacity 200ms ease-out;
1204
- pointer-events: none;
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-tilt][data-tilt-active='1']::after {
1207
- opacity: 0.45;
1208
- /* Just above the card FACE but BELOW the popped header/footer planes, so it
1209
- lights the surface without washing the floating title. */
1210
- transform: translateZ(2px);
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-tilt] {
1218
- position: relative;
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-board-col-panel] {
1230
- box-shadow:
1231
- inset 0 1px 0 0 rgba(255, 255, 255, 0.55),
1232
- 0 1px 3px rgba(15, 15, 15, 0.08),
1233
- 0 8px 18px -8px rgba(15, 15, 15, 0.22);
1234
- /* The column is `h-[calc(100dvh - 10.5rem - var(--shell-bottom-clearance))]` —
1235
- sized to fill the board area. In the `overflow-x-auto` row that
1236
- exactly-filling height means the column's rounded BOTTOM corner + its drop
1237
- shadow sit at the overflow-clip boundary and get sheared flat (the reported
1238
- "sharp bottom corner"). Trim the height by a further 2.5rem so the rounded
1239
- corner + shadow clear the clip and the column reads as a fully-rounded
1240
- floating card. Also clip the column's OWN children to its radius so a flush
1241
- inner surface can't square a corner the board cards pop on hover but the
1242
- DragOverlay clone is portaled, so nothing 3D is lost.
1243
-
1244
- ⚠️ This tracks BoardColumn's height and must keep spending the same
1245
- `--shell-bottom-clearance` the shell sets (MOTIR-2763), not a flat number:
1246
- a stylesheet cannot read the `showPlanWithAi` prop, so the custom property
1247
- is the only way this stays conditional on the orb actually mounting. The
1248
- 13rem below is 10.5rem of chrome + this style's own 2.5rem trim. */
1249
- height: calc(100dvh - 13rem - var(--shell-bottom-clearance, 1.5rem));
1250
- overflow: hidden;
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-board-scroll] {
1253
- gap: 1.5rem;
1254
- padding-bottom: 2.25rem;
1255
- padding-top: 0.25rem;
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
- box-shadow:
1337
- 0 3px 0 0 var(--el-border-strong),
1338
- 0 5px 10px -3px rgba(15, 15, 15, 0.18);
1339
- transition:
1340
- transform 90ms ease-out,
1341
- box-shadow 90ms ease-out,
1342
- background-color var(--transition-duration);
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-variant='primary'] {
1345
- box-shadow:
1346
- 0 4px 0 0 var(--el-accent-pressed),
1347
- 0 7px 12px -3px rgba(15, 15, 15, 0.32);
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-variant='danger'] {
1350
- box-shadow:
1351
- 0 4px 0 0 color-mix(in srgb, var(--el-danger), black 32%),
1352
- 0 7px 12px -3px rgba(15, 15, 15, 0.32);
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-variant='ghost'] {
1356
- box-shadow: none;
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-style='3d-immersive']
1374
- :is([data-surface='popover'], [data-menu-surface])
1375
- :is(button, a).rounded-\(--radius-control\),
1376
- [data-style='3d-immersive'] :is(button, a).w-full.rounded-\(--radius-control\) {
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
- .rounded-\(--radius-btn\),
1385
- button.rounded-\(--radius-input\),
1386
- :is(button, a).rounded-\(--radius-control\).justify-center,
1387
- [data-depth='key']
1388
- ):active:not(:disabled) {
1389
- transform: translateY(3px);
1390
- box-shadow:
1391
- 0 1px 0 0 var(--el-border-strong),
1392
- 0 2px 4px rgba(15, 15, 15, 0.14);
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-variant='primary']:active:not(:disabled) {
1395
- box-shadow:
1396
- 0 1px 0 0 var(--el-accent-pressed),
1397
- 0 2px 5px rgba(15, 15, 15, 0.22);
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-variant='danger']:active:not(:disabled) {
1400
- box-shadow:
1401
- 0 1px 0 0 color-mix(in srgb, var(--el-danger), black 32%),
1402
- 0 2px 5px rgba(15, 15, 15, 0.22);
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-variant='ghost']:active:not(:disabled) {
1405
- box-shadow: none;
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
- :disabled
1415
- ) {
1416
- transform: translateY(1px);
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
- box-shadow:
1435
- inset 0 2px 6px -2px rgba(15, 15, 15, 0.26),
1436
- inset 0 1px 2px 0 rgba(15, 15, 15, 0.05);
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'] body {
1456
- --plan-hero-shadow:
1457
- 0 4px 0 0 var(--el-accent-pressed),
1458
- inset 0 1px 0 color-mix(in srgb, var(--el-accent-text) 38%, transparent),
1459
- inset 0 0 0 1px color-mix(in srgb, var(--el-accent-text) 18%, transparent),
1460
- 0 9px 18px -5px color-mix(in srgb, var(--el-accent) 75%, transparent),
1461
- 0 0 22px -3px color-mix(in srgb, var(--el-highlight) 50%, transparent);
1462
- --plan-orb-shadow:
1463
- 0 5px 0 0 var(--el-accent-pressed),
1464
- inset 0 1px 0 color-mix(in srgb, var(--el-accent-text) 40%, transparent),
1465
- 0 12px 24px -6px color-mix(in srgb, var(--el-accent) 80%, transparent),
1466
- 0 0 28px -2px color-mix(in srgb, var(--el-highlight) 55%, transparent);
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'] .shadow-\(--shadow-elevated\) {
1493
- box-shadow: var(--shadow-elevated);
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-surface='popover'],
1501
- [data-style='3d-immersive'] [data-menu-surface] {
1502
- transform-origin: top center;
1503
- animation: immersive-menu-open 200ms cubic-bezier(0.22, 1, 0.36, 1);
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-surface='popover'][data-side='top'] {
1507
- transform-origin: bottom center;
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'] .border {
1595
- border-width: 2px;
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'] .border:not(.fixed):not(.absolute):not(.sticky) {
1598
- position: relative;
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'] .border::after {
1601
- content: '';
1602
- position: absolute;
1603
- inset: -1px;
1604
- pointer-events: none;
1605
- border: 2px solid var(--el-border-strong);
1606
- border-radius: inherit;
1607
- filter: url(#hd-rough);
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
- :is(.border-b, .border-t):not(.border):not(.fixed):not(.absolute):not(.sticky) {
1617
- position: relative;
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-surface] .border-b:not(.border)::after {
1620
- content: '';
1621
- position: absolute;
1622
- left: 0;
1623
- right: 0;
1624
- bottom: -1px;
1625
- height: 0;
1626
- pointer-events: none;
1627
- border-bottom: 2px solid var(--el-border-strong);
1628
- filter: url(#hd-rough);
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-surface] .border-t:not(.border)::after {
1631
- content: '';
1632
- position: absolute;
1633
- left: 0;
1634
- right: 0;
1635
- top: -1px;
1636
- height: 0;
1637
- pointer-events: none;
1638
- border-top: 2px solid var(--el-border-strong);
1639
- filter: url(#hd-rough);
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-surface] .last\:border-b-0:last-child::after {
1648
- content: none;
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
- position: relative;
1753
+ position: relative;
1754
+ }
1665
1755
  }
1666
- [data-style='hand-drawn-indie'] [data-surface='sidebar']::after {
1667
- content: '';
1668
- position: absolute;
1669
- top: 0;
1670
- bottom: 0;
1671
- right: -1px;
1672
- width: 0;
1673
- pointer-events: none;
1674
- border-right: 2px solid var(--el-border-strong);
1675
- filter: url(#hd-rough);
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-surface='header']::after {
1678
- content: '';
1679
- position: absolute;
1680
- left: 0;
1681
- right: 0;
1682
- bottom: -1px;
1683
- height: 0;
1684
- pointer-events: none;
1685
- border-bottom: 2px solid var(--el-border-strong);
1686
- filter: url(#hd-rough);
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'] body {
1799
- background-color: var(--el-surface);
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-surface='card'],
1810
- [data-style='neumorphism'] [data-surface='popover'] {
1811
- background-color: var(--el-surface);
1812
- border-color: color-mix(in srgb, var(--el-border) 45%, transparent);
1813
- box-shadow:
1814
- var(--neu-distance) var(--neu-distance) var(--neu-blur) var(--neu-shadow),
1815
- calc(-1 * var(--neu-distance)) calc(-1 * var(--neu-distance)) var(--neu-blur) var(--neu-light);
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-surface='modal'] {
1821
- background-color: var(--el-surface);
1822
- border-color: color-mix(in srgb, var(--el-border) 45%, transparent);
1823
- box-shadow:
1824
- calc(var(--neu-distance) + 2px) calc(var(--neu-distance) + 2px) calc(var(--neu-blur) + 8px)
1825
- var(--neu-shadow),
1826
- calc(-1 * var(--neu-distance)) calc(-1 * var(--neu-distance)) calc(var(--neu-blur) + 4px)
1827
- var(--neu-light);
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-surface='sidebar'] {
1833
- background-color: var(--el-surface);
1834
- box-shadow:
1835
- var(--neu-distance) 0 var(--neu-blur) var(--neu-shadow),
1836
- calc(-1 * var(--neu-distance)) 0 var(--neu-blur) var(--neu-light);
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-surface='input'] {
1842
- background-color: var(--el-surface);
1843
- border-color: color-mix(in srgb, var(--el-border) 45%, transparent);
1844
- box-shadow:
1845
- inset var(--neu-distance-sm) var(--neu-distance-sm) var(--neu-blur-sm) var(--neu-shadow),
1846
- inset calc(-1 * var(--neu-distance-sm)) calc(-1 * var(--neu-distance-sm)) var(--neu-blur-sm)
1847
- var(--neu-light);
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-surface='card'],
1856
- [data-style='neumorphism'] [data-surface='popover'],
1857
- [data-style='neumorphism'] [data-surface='modal'],
1858
- [data-style='neumorphism'] [data-surface='input'],
1859
- [data-style='neumorphism'] [data-surface='sidebar'] {
1860
- border-color: var(--el-border-strong);
1861
- box-shadow: var(--shadow-card);
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-surface='card'],
1866
- [data-style='neumorphism'] [data-surface='popover'],
1867
- [data-style='neumorphism'] [data-surface='modal'],
1868
- [data-style='neumorphism'] [data-surface='input'],
1869
- [data-style='neumorphism'] [data-surface='sidebar'] {
1870
- border-color: var(--el-border-strong);
1871
- box-shadow: none;
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'] body {
1976
- background-image:
1977
- linear-gradient(
1978
- 180deg,
1979
- transparent 54%,
1980
- color-mix(in srgb, var(--el-highlight) var(--retro-horizon), transparent) 60.5%,
1981
- color-mix(in srgb, var(--el-accent) var(--retro-horizon), transparent) 62.5%,
1982
- transparent 69%
1983
- ),
1984
- linear-gradient(
1985
- 180deg,
1986
- color-mix(in srgb, var(--el-link) var(--retro-sky), transparent),
1987
- transparent 46%
1988
- ),
1989
- linear-gradient(
1990
- 0deg,
1991
- color-mix(in srgb, var(--el-accent) var(--retro-ground), transparent),
1992
- transparent 42%
1993
- );
1994
- background-size: 100% 100%;
1995
- background-attachment: fixed;
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'] body::after {
2007
- content: '';
2008
- position: fixed;
2009
- left: -30%;
2010
- right: -30%;
2011
- bottom: 0;
2012
- height: 42vh;
2013
- background-image:
2014
- repeating-linear-gradient(
2015
- 0deg,
2016
- color-mix(in srgb, var(--el-highlight) var(--retro-grid), transparent) 0 2px,
2017
- transparent 2px var(--retro-grid-size)
2018
- ),
2019
- repeating-linear-gradient(
2020
- 90deg,
2021
- color-mix(in srgb, var(--el-accent) var(--retro-grid), transparent) 0 2px,
2022
- transparent 2px var(--retro-grid-size)
2023
- );
2024
- background-size: var(--retro-grid-size) var(--retro-grid-size);
2025
- transform: perspective(300px) rotateX(75deg);
2026
- transform-origin: bottom center;
2027
- -webkit-mask-image: linear-gradient(to top, black 2%, transparent 80%);
2028
- mask-image: linear-gradient(to top, black 2%, transparent 80%);
2029
- pointer-events: none;
2030
- z-index: -1;
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-surface='card'],
2043
- [data-style='retrofuturism'] [data-surface='popover'],
2044
- [data-style='retrofuturism'] .rounded-\(--radius-card\) {
2045
- background-color: var(--el-surface);
2046
- background-image:
2047
- linear-gradient(
2048
- 158deg,
2049
- transparent 36%,
2050
- color-mix(in srgb, white var(--retro-spec), transparent) 49%,
2051
- transparent 62%
2052
- ),
2053
- linear-gradient(
2054
- 180deg,
2055
- color-mix(in srgb, white var(--retro-bevel-light), transparent) 0%,
2056
- transparent 16%,
2057
- transparent 78%,
2058
- color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
2059
- );
2060
- box-shadow:
2061
- var(--shadow-card),
2062
- inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
2063
- inset 0 -1px 0 color-mix(in srgb, black 24%, transparent),
2064
- 0 0 28px -8px color-mix(in srgb, var(--el-accent) var(--retro-glow), transparent);
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-surface='modal'] {
2071
- background-color: var(--el-surface);
2072
- background-image:
2073
- linear-gradient(
2074
- 158deg,
2075
- transparent 34%,
2076
- color-mix(in srgb, white var(--retro-spec), transparent) 49%,
2077
- transparent 64%
2078
- ),
2079
- linear-gradient(
2080
- 180deg,
2081
- color-mix(in srgb, white var(--retro-bevel-light), transparent) 0%,
2082
- transparent 14%,
2083
- transparent 80%,
2084
- color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
2085
- );
2086
- box-shadow:
2087
- var(--shadow-modal),
2088
- inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
2089
- 0 0 56px -14px color-mix(in srgb, var(--el-highlight) var(--retro-glow-strong), transparent);
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-surface='sidebar'] {
2095
- background-color: var(--el-sidebar-bg);
2096
- background-image:
2097
- linear-gradient(
2098
- 158deg,
2099
- transparent 40%,
2100
- color-mix(in srgb, white var(--retro-sheen), transparent) 50%,
2101
- transparent 60%
2102
- ),
2103
- linear-gradient(
2104
- 180deg,
2105
- color-mix(in srgb, white var(--retro-sheen), transparent),
2106
- transparent 24%,
2107
- color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
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-surface='input'] {
2117
- background-color: var(--el-page-bg);
2118
- background-image: linear-gradient(
2119
- 180deg,
2120
- color-mix(in srgb, black var(--retro-sheen), transparent) 0%,
2121
- transparent 34%
2122
- );
2123
- box-shadow: inset 0 1px 3px color-mix(in srgb, black var(--retro-glow), transparent);
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'] .rounded-\(--radius-btn\).bg-\(--el-accent\) {
2155
- background-image:
2156
- linear-gradient(
2157
- 158deg,
2158
- transparent 38%,
2159
- color-mix(in srgb, white var(--retro-spec), transparent) 50%,
2160
- transparent 62%
2161
- ),
2162
- linear-gradient(
2163
- 180deg,
2164
- color-mix(in srgb, white var(--retro-spec), var(--el-accent)) 0%,
2165
- var(--el-accent) 46%,
2166
- color-mix(in srgb, black var(--retro-bevel-shade), var(--el-accent)) 100%
2167
- );
2168
- box-shadow:
2169
- var(--shadow-subtle),
2170
- inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
2171
- 0 0 22px -6px color-mix(in srgb, var(--el-accent) var(--retro-glow-strong), transparent);
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'] .rounded-\(--radius-btn\).bg-\(--el-danger\) {
2177
- background-image:
2178
- linear-gradient(
2179
- 158deg,
2180
- transparent 38%,
2181
- color-mix(in srgb, white var(--retro-spec), transparent) 50%,
2182
- transparent 62%
2183
- ),
2184
- linear-gradient(
2185
- 180deg,
2186
- color-mix(in srgb, white var(--retro-spec), var(--el-danger)) 0%,
2187
- var(--el-danger) 46%,
2188
- color-mix(in srgb, black var(--retro-bevel-shade), var(--el-danger)) 100%
2189
- );
2190
- box-shadow:
2191
- var(--shadow-subtle),
2192
- inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
2193
- 0 0 22px -6px color-mix(in srgb, var(--el-danger) var(--retro-glow-strong), transparent);
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'] .rounded-\(--radius-btn\).border:not([role='group']),
2203
- [data-style='retrofuturism'] button.rounded-\(--radius-input\) {
2204
- background-color: color-mix(in srgb, black 24%, var(--el-surface));
2205
- background-image:
2206
- linear-gradient(
2207
- 158deg,
2208
- transparent 36%,
2209
- color-mix(in srgb, white var(--retro-spec), transparent) 50%,
2210
- transparent 64%
2211
- ),
2212
- linear-gradient(
2213
- 180deg,
2214
- color-mix(in srgb, white var(--retro-bevel-light), transparent) 0%,
2215
- transparent 42%,
2216
- transparent 60%,
2217
- color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
2218
- );
2219
- box-shadow:
2220
- var(--shadow-subtle),
2221
- inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
2222
- inset 0 -1px 0 color-mix(in srgb, black 24%, transparent),
2223
- 0 0 18px -8px color-mix(in srgb, var(--el-accent) var(--retro-glow), transparent);
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'] [role='group'].rounded-\(--radius-btn\) {
2231
- background-color: color-mix(in srgb, black 15%, var(--el-surface));
2232
- box-shadow: inset 0 1px 3px color-mix(in srgb, black var(--retro-glow), transparent);
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'] [role='group'] [aria-pressed='true'] {
2235
- background-color: color-mix(in srgb, black 24%, var(--el-surface));
2236
- background-image:
2237
- linear-gradient(
2238
- 158deg,
2239
- transparent 36%,
2240
- color-mix(in srgb, white var(--retro-spec), transparent) 50%,
2241
- transparent 64%
2242
- ),
2243
- linear-gradient(
2244
- 180deg,
2245
- color-mix(in srgb, white var(--retro-bevel-light), transparent) 0%,
2246
- transparent 42%,
2247
- transparent 60%,
2248
- color-mix(in srgb, black var(--retro-bevel-shade), transparent) 100%
2249
- );
2250
- box-shadow:
2251
- var(--shadow-subtle),
2252
- inset 0 1px 0 color-mix(in srgb, white 60%, transparent),
2253
- inset 0 -1px 0 color-mix(in srgb, black 24%, transparent);
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
- [data-style='retrofuturism'] button.rounded-\(--radius-input\):hover:not(:disabled),
2261
- [data-style='retrofuturism'] [role='group'] [aria-pressed='false']:hover:not(:disabled) {
2262
- background-color: color-mix(in srgb, black 14%, var(--el-surface));
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
  /* ─────────────────────────────────────────────────────────────────────────
@@ -2533,7 +2664,25 @@
2533
2664
  nobody renders — the base layer IS how the browser reaches these values. */
2534
2665
  --el-status-implemented: color-mix(in srgb, var(--color-accent) 75%, var(--color-charcoal));
2535
2666
  --el-status-in-review: var(--color-primary); /* brand — differentiate from in-progress */
2536
- --el-status-done: var(--color-success); /* green resolved */
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));
2537
2686
  --el-status-blocked: var(--color-warning); /* amber — can't proceed (gap fixed) */
2538
2687
  --el-status-cancelled: var(--color-steel); /* terminal grey — not red (cancel ≠ error) */
2539
2688