@gradeui/ui 3.2.0 → 4.0.0

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.
@@ -684,6 +684,7 @@
684
684
  --surface-alpha-translucent: 0.82;
685
685
  --surface-alpha-glass: 0.58;
686
686
  --surface-alpha-glass-strong: 0.42;
687
+ --surface-alpha-frosted: 0.92; /* near-opaque, just a whisper of the page behind */
687
688
 
688
689
  /* -- Atomic blurs -- */
689
690
  --surface-blur-subtle: 6px;
@@ -699,6 +700,7 @@
699
700
  --surface-translucent: oklch(var(--card) / var(--surface-alpha-translucent));
700
701
  --surface-glass: oklch(var(--card) / var(--surface-alpha-glass));
701
702
  --surface-glass-strong: oklch(var(--card) / var(--surface-alpha-glass-strong));
703
+ --surface-frosted: oklch(var(--card) / var(--surface-alpha-frosted));
702
704
 
703
705
  /* ============================================
704
706
  AURA SYSTEM
@@ -773,6 +775,8 @@
773
775
  ---------------------------------------- */
774
776
  --background: 0.985 0.0018 85; /* neutral 50 */
775
777
  --foreground: 0.170 0.0048 85; /* neutral 950 */
778
+ --bg-base: 0.985 0.0018 85; /* stable mirror for scope-inverse */
779
+ --fg-base: 0.170 0.0048 85;
776
780
  --card: 1 0 0; /* pure white */
777
781
  --card-foreground: 0.170 0.0048 85;
778
782
  --popover: 1 0 0;
@@ -1008,6 +1012,8 @@
1008
1012
  ---------------------------------------- */
1009
1013
  --background: 0.170 0.0048 85;
1010
1014
  --foreground: 0.985 0.0018 85;
1015
+ --bg-base: 0.170 0.0048 85;
1016
+ --fg-base: 0.985 0.0018 85;
1011
1017
  --card: 0.245 0.0096 85; /* neutral 900 */
1012
1018
  --card-foreground: 0.985 0.0018 85;
1013
1019
  --popover: 0.245 0.0096 85;
@@ -1087,6 +1093,7 @@
1087
1093
  --surface-alpha-translucent: 0.74;
1088
1094
  --surface-alpha-glass: 0.48;
1089
1095
  --surface-alpha-glass-strong: 0.32;
1096
+ --surface-alpha-frosted: 0.88;
1090
1097
  --surface-edge-alpha: 0.06;
1091
1098
 
1092
1099
  /* Code surface tokens — dark mode mirror. Background sits a touch
@@ -1123,6 +1130,8 @@
1123
1130
  :root[data-grade-theme="energy"] {
1124
1131
  --background: 0.985 0.0012 175; /* neutral 50 */
1125
1132
  --foreground: 0.170 0.0032 175; /* neutral 950 */
1133
+ --bg-base: 0.985 0.0012 175;
1134
+ --fg-base: 0.170 0.0032 175;
1126
1135
  --card: 1 0 0;
1127
1136
  --card-foreground: 0.170 0.0032 175;
1128
1137
  --popover: 1 0 0;
@@ -1147,6 +1156,8 @@
1147
1156
  .dark[data-grade-theme="energy"] {
1148
1157
  --background: 0.170 0.0032 175;
1149
1158
  --foreground: 0.985 0.0012 175;
1159
+ --bg-base: 0.170 0.0032 175;
1160
+ --fg-base: 0.985 0.0012 175;
1150
1161
  --card: 0.245 0.0064 175;
1151
1162
  --card-foreground: 0.985 0.0012 175;
1152
1163
  --popover: 0.245 0.0064 175;
@@ -1523,6 +1534,17 @@
1523
1534
  box-shadow: var(--surface-edge);
1524
1535
  }
1525
1536
 
1537
+ /* Frosted — near-opaque (≈0.92) but keeps the strong blur, so it reads almost
1538
+ solid with just a halo of the page behind. The most solid of the blurred
1539
+ surfaces; above this, reach for `solid`. */
1540
+ .gds-surface-frosted {
1541
+ background-color: var(--surface-frosted);
1542
+ backdrop-filter: blur(var(--surface-blur-strong));
1543
+ -webkit-backdrop-filter: blur(var(--surface-blur-strong));
1544
+ border: 1px solid oklch(var(--border) / 0.4);
1545
+ box-shadow: var(--surface-edge);
1546
+ }
1547
+
1526
1548
  /* ============================================
1527
1549
  AURA — RING (pulsing outer halo)
1528
1550
  ============================================
@@ -1725,22 +1747,15 @@
1725
1747
  }
1726
1748
 
1727
1749
  /* ============================================
1728
- MAP MARKER LIFT every pin gets a border
1750
+ MAP MARKER — intentionally unstyled
1729
1751
  ============================================
1730
- Map tiles are external imagery and don't follow the theme, so marker
1731
- content (Badge price pins, numbered markers, avatars) can melt into
1732
- them illegible dark-on-dark pins were the symptom. Guarantee the
1733
- lift at the DS level: every DIRECT child of a MapMarker's content
1734
- wrapper gets a 1px border + ambient shadow from the mode-aware
1735
- `--gds-map-marker-*` pair (light hairline on dark tiles, dark line
1736
- on light). Being unlayered, this wins over a Badge's own
1737
- border-transparent utility — deliberate: the border is the floor,
1738
- not a suggestion. Backgrounds/text are NOT touched; content keeps
1739
- its own surface tokens. */
1740
- [data-gds-part="map-marker-content"] > * {
1741
- border: 1px solid var(--gds-map-marker-border);
1742
- box-shadow: var(--gds-map-marker-shadow);
1743
- }
1752
+ Marker content (Badge price pins, numbered markers, avatars, custom pin
1753
+ types) is the CONSUMER's design. The DS used to force a 1px border + ambient
1754
+ shadow on every direct child of a marker as a legibility "floor", but that's
1755
+ too opinionated for a primitive it imposed a look on content you supply.
1756
+ Removed. The mode-aware `--gds-map-marker-border` / `--gds-map-marker-shadow`
1757
+ tokens remain defined, and `.gds-map-label` (below) still gives text a halo,
1758
+ so legibility on busy tiles is OPT-IN, not mandatory. */
1744
1759
 
1745
1760
  /* Floating map label halo — put this class on a text element inside a
1746
1761
  MapMarker to give it a mode-aware outline (white on light tiles,
@@ -2072,6 +2087,569 @@ html[data-gds-streaming] body * {
2072
2087
  }
2073
2088
  }
2074
2089
 
2090
+ @layer utilities {
2091
+ /* Colour SCOPES (STUDIO-COLOR.md) — a local colour mode, the same idea as
2092
+ light/dark but scoped to a wrapper and focused on surfaces.
2093
+ Apply `scope-inverse` (etc.) to any element and it becomes a mini themed
2094
+ region: it re-points the SURFACE family of tokens — page background, card,
2095
+ popover, muted, border, and every foreground — at the named pair, so the
2096
+ whole subtree re-tones (a dark band with light text, cards that sit on the
2097
+ band instead of glaring white). Descendants keep using the ordinary tokens
2098
+ (bg-background / text-foreground / bg-card); only what they resolve to
2099
+ changes. It deliberately leaves the ACTION colours (--primary / --accent /
2100
+ --secondary / --destructive) untouched, so a CTA stays branded and vivid
2101
+ on top of the band.
2102
+ `inverse` reads --fg-base / --bg-base (stable literal mirrors of the page
2103
+ ink/paper that the generator emits) so the fg/bg swap can't form a custom-
2104
+ property cycle; the other scopes read the theme's own tokens directly. */
2105
+ .scope-default,
2106
+ .scope-inverse,
2107
+ .scope-brand,
2108
+ .scope-accent,
2109
+ .scope-muted,
2110
+ .scope-card {
2111
+ background-color: oklch(var(--background));
2112
+ color: oklch(var(--foreground));
2113
+ }
2114
+ /* default = identity: paints the page tokens as-is, no overrides. */
2115
+ .scope-inverse {
2116
+ --background: var(--fg-base);
2117
+ --foreground: var(--bg-base);
2118
+ --card: var(--fg-base);
2119
+ --card-foreground: var(--bg-base);
2120
+ --popover: var(--fg-base);
2121
+ --popover-foreground: var(--bg-base);
2122
+ --muted: var(--fg-base);
2123
+ --muted-foreground: var(--bg-base);
2124
+ --border: var(--bg-base);
2125
+ --input: var(--bg-base);
2126
+ }
2127
+ .scope-brand {
2128
+ --background: var(--primary);
2129
+ --foreground: var(--primary-foreground);
2130
+ --card: var(--primary);
2131
+ --card-foreground: var(--primary-foreground);
2132
+ --popover: var(--primary);
2133
+ --popover-foreground: var(--primary-foreground);
2134
+ --muted: var(--primary);
2135
+ --muted-foreground: var(--primary-foreground);
2136
+ --border: var(--primary-foreground);
2137
+ --input: var(--primary-foreground);
2138
+ }
2139
+ .scope-accent {
2140
+ --background: var(--accent);
2141
+ --foreground: var(--accent-foreground);
2142
+ --card: var(--accent);
2143
+ --card-foreground: var(--accent-foreground);
2144
+ --popover: var(--accent);
2145
+ --popover-foreground: var(--accent-foreground);
2146
+ --muted: var(--accent);
2147
+ --muted-foreground: var(--accent-foreground);
2148
+ --border: var(--accent-foreground);
2149
+ --input: var(--accent-foreground);
2150
+ }
2151
+ .scope-muted {
2152
+ --background: var(--muted);
2153
+ --card: var(--muted);
2154
+ --popover: var(--muted);
2155
+ /* foreground + muted-foreground stay the page's: already tuned to read on
2156
+ a muted surface. */
2157
+ }
2158
+ .scope-card {
2159
+ --background: var(--card);
2160
+ --foreground: var(--card-foreground);
2161
+ --popover: var(--card);
2162
+ --popover-foreground: var(--card-foreground);
2163
+ --muted-foreground: var(--card-foreground);
2164
+ }
2165
+ }
2166
+
2167
+ /* ============================================
2168
+ EXPRESSIVE colour layer — see STUDIO-EXPRESSIVE.md
2169
+ A highlight layer for painting whole SECTIONS, deliberately louder than the
2170
+ neutral product chrome (marketing bands, feature cards, promo strips).
2171
+ Orthogonal to the surface scopes above: it does NOT touch --primary/--accent,
2172
+ so it stacks on top of any theme. Two attributes resolve a section's colour:
2173
+ data-expressive="accent1..5" picks one of 5 accent slots
2174
+ data-expressive-tier="…" picks one of 4 tiers (default: light)
2175
+ …landing an accessible pair on --gds-expressive-bg / --gds-expressive-fg,
2176
+ which the `.expressive` helper paints. Values mirror the Figma "Expressive"
2177
+ collection (accent1..5 = rose, orange, amber, yellow, olive). The accents are
2178
+ fixed ramps today; the generator will later write them from one hue per slot
2179
+ — the token shape stays identical. Tiers use ramp steps 100/300/700/900. */
2180
+ :root {
2181
+ --gds-expressive-accent1-100: #ffe9e6; --gds-expressive-accent1-300: #ffaaa2; --gds-expressive-accent1-700: #8b181d; --gds-expressive-accent1-900: #3f0b0b;
2182
+ --gds-expressive-accent2-100: #ffeae0; --gds-expressive-accent2-300: #ffae89; --gds-expressive-accent2-700: #822c00; --gds-expressive-accent2-900: #3c1100;
2183
+ --gds-expressive-accent3-100: #ffecd8; --gds-expressive-accent3-300: #f6b575; --gds-expressive-accent3-700: #743b00; --gds-expressive-accent3-900: #331900;
2184
+ --gds-expressive-accent4-100: #fdefd2; --gds-expressive-accent4-300: #e5bf6d; --gds-expressive-accent4-700: #634600; --gds-expressive-accent4-900: #2d1d00;
2185
+ --gds-expressive-accent5-100: #f4f2d4; --gds-expressive-accent5-300: #cfc871; --gds-expressive-accent5-700: #544e00; --gds-expressive-accent5-900: #252100;
2186
+ }
2187
+
2188
+ /* accent slot → generic step vars */
2189
+ [data-expressive="accent1"] { --exp-100: var(--gds-expressive-accent1-100); --exp-300: var(--gds-expressive-accent1-300); --exp-700: var(--gds-expressive-accent1-700); --exp-900: var(--gds-expressive-accent1-900); }
2190
+ [data-expressive="accent2"] { --exp-100: var(--gds-expressive-accent2-100); --exp-300: var(--gds-expressive-accent2-300); --exp-700: var(--gds-expressive-accent2-700); --exp-900: var(--gds-expressive-accent2-900); }
2191
+ [data-expressive="accent3"] { --exp-100: var(--gds-expressive-accent3-100); --exp-300: var(--gds-expressive-accent3-300); --exp-700: var(--gds-expressive-accent3-700); --exp-900: var(--gds-expressive-accent3-900); }
2192
+ [data-expressive="accent4"] { --exp-100: var(--gds-expressive-accent4-100); --exp-300: var(--gds-expressive-accent4-300); --exp-700: var(--gds-expressive-accent4-700); --exp-900: var(--gds-expressive-accent4-900); }
2193
+ [data-expressive="accent5"] { --exp-100: var(--gds-expressive-accent5-100); --exp-300: var(--gds-expressive-accent5-300); --exp-700: var(--gds-expressive-accent5-700); --exp-900: var(--gds-expressive-accent5-900); }
2194
+
2195
+ /* tier → which steps become bg / fg (default = light) */
2196
+ [data-expressive] { --gds-expressive-bg: var(--exp-300); --gds-expressive-fg: var(--exp-900); }
2197
+ [data-expressive][data-expressive-tier="superlight"] { --gds-expressive-bg: var(--exp-100); --gds-expressive-fg: var(--exp-900); }
2198
+ [data-expressive][data-expressive-tier="light"] { --gds-expressive-bg: var(--exp-300); --gds-expressive-fg: var(--exp-900); }
2199
+ [data-expressive][data-expressive-tier="dark"] { --gds-expressive-bg: var(--exp-700); --gds-expressive-fg: var(--exp-100); }
2200
+ [data-expressive][data-expressive-tier="superdark"] { --gds-expressive-bg: var(--exp-900); --gds-expressive-fg: var(--exp-100); }
2201
+
2202
+ /* the surface helper a section wears: paints the resolved expressive pair */
2203
+ .expressive { background-color: var(--gds-expressive-bg); color: var(--gds-expressive-fg); }
2204
+
2205
+ /* ============================================
2206
+ REVEAL — scroll-in motion for sections (and any element). Token-driven:
2207
+ reuses the DS transition durations + eases (above), adds a reveal distance.
2208
+ An element with `data-reveal` starts hidden/offset; an IntersectionObserver
2209
+ in the consumer adds `.in-view` to animate it in. Entirely disabled under
2210
+ prefers-reduced-motion (the hidden state lives inside the media query, so
2211
+ content is always visible if motion is off or JS never runs). */
2212
+ :root {
2213
+ --gds-reveal-distance: 1.25rem;
2214
+ --gds-reveal-duration: var(--gds-transition-slower); /* 500ms */
2215
+ --gds-reveal-ease: var(--gds-ease-out);
2216
+ }
2217
+
2218
+ @media (prefers-reduced-motion: no-preference) {
2219
+ [data-reveal] {
2220
+ opacity: 0;
2221
+ transform: translateY(var(--gds-reveal-distance));
2222
+ transition:
2223
+ opacity var(--gds-reveal-duration) var(--gds-reveal-ease),
2224
+ transform var(--gds-reveal-duration) var(--gds-reveal-ease);
2225
+ will-change: opacity, transform;
2226
+ }
2227
+ [data-reveal="fade"] { transform: none; }
2228
+ [data-reveal="fade-down"] { transform: translateY(calc(-1 * var(--gds-reveal-distance))); }
2229
+ [data-reveal="fade-left"] { transform: translateX(var(--gds-reveal-distance)); }
2230
+ [data-reveal="fade-right"] { transform: translateX(calc(-1 * var(--gds-reveal-distance))); }
2231
+ [data-reveal].in-view {
2232
+ opacity: 1;
2233
+ transform: none;
2234
+ }
2235
+ }
2236
+
2237
+ /* ============================================
2238
+ TYPE SCALE — scoped, switchable, fluid (mobile → desktop)
2239
+ ============================================
2240
+ Two scales, one fluid ramp. Pick a mobile + a desktop scale and the whole
2241
+ --text-* ramp (Tailwind 2xs…7xl + semantic display/h1…body) interpolates
2242
+ between them by viewport, CLAMPED to the mobile floor and desktop ceiling
2243
+ (the clamp lives on --ts-fluid: 0→1, so values never exceed either end):
2244
+ data-type-scale-mobile="minor-third" data-type-scale-desktop="perfect-fifth"
2245
+ Shorthand (flat): data-type-scale="major-third" (sets both). Assign to :root,
2246
+ a page, or any element — composes via the cascade like the colour scopes.
2247
+
2248
+ ASYMMETRIC by design: steps go UP at the chosen ratio but DOWN capped at
2249
+ major-third, so a dramatic display scale keeps sm/xs/2xs readable instead of
2250
+ shrinking body/caption text into the floor. Generated from @gradeui/core. */
2251
+
2252
+ [data-type-scale-mobile="minor-second"] {
2253
+ --tsm-2xs: 0.823rem;
2254
+ --tsm-xs: 0.878rem;
2255
+ --tsm-sm: 0.937rem;
2256
+ --tsm-base: 1rem;
2257
+ --tsm-lg: 1.067rem;
2258
+ --tsm-xl: 1.138rem;
2259
+ --tsm-2xl: 1.215rem;
2260
+ --tsm-3xl: 1.296rem;
2261
+ --tsm-4xl: 1.383rem;
2262
+ --tsm-5xl: 1.476rem;
2263
+ --tsm-6xl: 1.575rem;
2264
+ --tsm-7xl: 1.68rem;
2265
+ }
2266
+ [data-type-scale-desktop="minor-second"] {
2267
+ --tsd-2xs: 0.823rem;
2268
+ --tsd-xs: 0.878rem;
2269
+ --tsd-sm: 0.937rem;
2270
+ --tsd-base: 1rem;
2271
+ --tsd-lg: 1.067rem;
2272
+ --tsd-xl: 1.138rem;
2273
+ --tsd-2xl: 1.215rem;
2274
+ --tsd-3xl: 1.296rem;
2275
+ --tsd-4xl: 1.383rem;
2276
+ --tsd-5xl: 1.476rem;
2277
+ --tsd-6xl: 1.575rem;
2278
+ --tsd-7xl: 1.68rem;
2279
+ }
2280
+ [data-type-scale="minor-second"] {
2281
+ --tsm-2xs: 0.823rem; --tsd-2xs: 0.823rem;
2282
+ --tsm-xs: 0.878rem; --tsd-xs: 0.878rem;
2283
+ --tsm-sm: 0.937rem; --tsd-sm: 0.937rem;
2284
+ --tsm-base: 1rem; --tsd-base: 1rem;
2285
+ --tsm-lg: 1.067rem; --tsd-lg: 1.067rem;
2286
+ --tsm-xl: 1.138rem; --tsd-xl: 1.138rem;
2287
+ --tsm-2xl: 1.215rem; --tsd-2xl: 1.215rem;
2288
+ --tsm-3xl: 1.296rem; --tsd-3xl: 1.296rem;
2289
+ --tsm-4xl: 1.383rem; --tsd-4xl: 1.383rem;
2290
+ --tsm-5xl: 1.476rem; --tsd-5xl: 1.476rem;
2291
+ --tsm-6xl: 1.575rem; --tsd-6xl: 1.575rem;
2292
+ --tsm-7xl: 1.68rem; --tsd-7xl: 1.68rem;
2293
+ }
2294
+
2295
+ [data-type-scale-mobile="major-second"] {
2296
+ --tsm-2xs: 0.702rem;
2297
+ --tsm-xs: 0.79rem;
2298
+ --tsm-sm: 0.889rem;
2299
+ --tsm-base: 1rem;
2300
+ --tsm-lg: 1.125rem;
2301
+ --tsm-xl: 1.266rem;
2302
+ --tsm-2xl: 1.424rem;
2303
+ --tsm-3xl: 1.602rem;
2304
+ --tsm-4xl: 1.802rem;
2305
+ --tsm-5xl: 2.027rem;
2306
+ --tsm-6xl: 2.281rem;
2307
+ --tsm-7xl: 2.566rem;
2308
+ }
2309
+ [data-type-scale-desktop="major-second"] {
2310
+ --tsd-2xs: 0.702rem;
2311
+ --tsd-xs: 0.79rem;
2312
+ --tsd-sm: 0.889rem;
2313
+ --tsd-base: 1rem;
2314
+ --tsd-lg: 1.125rem;
2315
+ --tsd-xl: 1.266rem;
2316
+ --tsd-2xl: 1.424rem;
2317
+ --tsd-3xl: 1.602rem;
2318
+ --tsd-4xl: 1.802rem;
2319
+ --tsd-5xl: 2.027rem;
2320
+ --tsd-6xl: 2.281rem;
2321
+ --tsd-7xl: 2.566rem;
2322
+ }
2323
+ [data-type-scale="major-second"] {
2324
+ --tsm-2xs: 0.702rem; --tsd-2xs: 0.702rem;
2325
+ --tsm-xs: 0.79rem; --tsd-xs: 0.79rem;
2326
+ --tsm-sm: 0.889rem; --tsd-sm: 0.889rem;
2327
+ --tsm-base: 1rem; --tsd-base: 1rem;
2328
+ --tsm-lg: 1.125rem; --tsd-lg: 1.125rem;
2329
+ --tsm-xl: 1.266rem; --tsd-xl: 1.266rem;
2330
+ --tsm-2xl: 1.424rem; --tsd-2xl: 1.424rem;
2331
+ --tsm-3xl: 1.602rem; --tsd-3xl: 1.602rem;
2332
+ --tsm-4xl: 1.802rem; --tsd-4xl: 1.802rem;
2333
+ --tsm-5xl: 2.027rem; --tsd-5xl: 2.027rem;
2334
+ --tsm-6xl: 2.281rem; --tsd-6xl: 2.281rem;
2335
+ --tsm-7xl: 2.566rem; --tsd-7xl: 2.566rem;
2336
+ }
2337
+
2338
+ [data-type-scale-mobile="minor-third"] {
2339
+ --tsm-2xs: 0.625rem;
2340
+ --tsm-xs: 0.694rem;
2341
+ --tsm-sm: 0.833rem;
2342
+ --tsm-base: 1rem;
2343
+ --tsm-lg: 1.2rem;
2344
+ --tsm-xl: 1.44rem;
2345
+ --tsm-2xl: 1.728rem;
2346
+ --tsm-3xl: 2.074rem;
2347
+ --tsm-4xl: 2.488rem;
2348
+ --tsm-5xl: 2.986rem;
2349
+ --tsm-6xl: 3.583rem;
2350
+ --tsm-7xl: 4.3rem;
2351
+ }
2352
+ [data-type-scale-desktop="minor-third"] {
2353
+ --tsd-2xs: 0.625rem;
2354
+ --tsd-xs: 0.694rem;
2355
+ --tsd-sm: 0.833rem;
2356
+ --tsd-base: 1rem;
2357
+ --tsd-lg: 1.2rem;
2358
+ --tsd-xl: 1.44rem;
2359
+ --tsd-2xl: 1.728rem;
2360
+ --tsd-3xl: 2.074rem;
2361
+ --tsd-4xl: 2.488rem;
2362
+ --tsd-5xl: 2.986rem;
2363
+ --tsd-6xl: 3.583rem;
2364
+ --tsd-7xl: 4.3rem;
2365
+ }
2366
+ [data-type-scale="minor-third"] {
2367
+ --tsm-2xs: 0.625rem; --tsd-2xs: 0.625rem;
2368
+ --tsm-xs: 0.694rem; --tsd-xs: 0.694rem;
2369
+ --tsm-sm: 0.833rem; --tsd-sm: 0.833rem;
2370
+ --tsm-base: 1rem; --tsd-base: 1rem;
2371
+ --tsm-lg: 1.2rem; --tsd-lg: 1.2rem;
2372
+ --tsm-xl: 1.44rem; --tsd-xl: 1.44rem;
2373
+ --tsm-2xl: 1.728rem; --tsd-2xl: 1.728rem;
2374
+ --tsm-3xl: 2.074rem; --tsd-3xl: 2.074rem;
2375
+ --tsm-4xl: 2.488rem; --tsd-4xl: 2.488rem;
2376
+ --tsm-5xl: 2.986rem; --tsd-5xl: 2.986rem;
2377
+ --tsm-6xl: 3.583rem; --tsd-6xl: 3.583rem;
2378
+ --tsm-7xl: 4.3rem; --tsd-7xl: 4.3rem;
2379
+ }
2380
+
2381
+ [data-type-scale-mobile="major-third"] {
2382
+ --tsm-2xs: 0.625rem;
2383
+ --tsm-xs: 0.64rem;
2384
+ --tsm-sm: 0.8rem;
2385
+ --tsm-base: 1rem;
2386
+ --tsm-lg: 1.25rem;
2387
+ --tsm-xl: 1.563rem;
2388
+ --tsm-2xl: 1.953rem;
2389
+ --tsm-3xl: 2.441rem;
2390
+ --tsm-4xl: 3.052rem;
2391
+ --tsm-5xl: 3.815rem;
2392
+ --tsm-6xl: 4.768rem;
2393
+ --tsm-7xl: 5.96rem;
2394
+ }
2395
+ [data-type-scale-desktop="major-third"] {
2396
+ --tsd-2xs: 0.625rem;
2397
+ --tsd-xs: 0.64rem;
2398
+ --tsd-sm: 0.8rem;
2399
+ --tsd-base: 1rem;
2400
+ --tsd-lg: 1.25rem;
2401
+ --tsd-xl: 1.563rem;
2402
+ --tsd-2xl: 1.953rem;
2403
+ --tsd-3xl: 2.441rem;
2404
+ --tsd-4xl: 3.052rem;
2405
+ --tsd-5xl: 3.815rem;
2406
+ --tsd-6xl: 4.768rem;
2407
+ --tsd-7xl: 5.96rem;
2408
+ }
2409
+ [data-type-scale="major-third"] {
2410
+ --tsm-2xs: 0.625rem; --tsd-2xs: 0.625rem;
2411
+ --tsm-xs: 0.64rem; --tsd-xs: 0.64rem;
2412
+ --tsm-sm: 0.8rem; --tsd-sm: 0.8rem;
2413
+ --tsm-base: 1rem; --tsd-base: 1rem;
2414
+ --tsm-lg: 1.25rem; --tsd-lg: 1.25rem;
2415
+ --tsm-xl: 1.563rem; --tsd-xl: 1.563rem;
2416
+ --tsm-2xl: 1.953rem; --tsd-2xl: 1.953rem;
2417
+ --tsm-3xl: 2.441rem; --tsd-3xl: 2.441rem;
2418
+ --tsm-4xl: 3.052rem; --tsd-4xl: 3.052rem;
2419
+ --tsm-5xl: 3.815rem; --tsd-5xl: 3.815rem;
2420
+ --tsm-6xl: 4.768rem; --tsd-6xl: 4.768rem;
2421
+ --tsm-7xl: 5.96rem; --tsd-7xl: 5.96rem;
2422
+ }
2423
+
2424
+ [data-type-scale-mobile="perfect-fourth"] {
2425
+ --tsm-2xs: 0.625rem;
2426
+ --tsm-xs: 0.64rem;
2427
+ --tsm-sm: 0.8rem;
2428
+ --tsm-base: 1rem;
2429
+ --tsm-lg: 1.333rem;
2430
+ --tsm-xl: 1.777rem;
2431
+ --tsm-2xl: 2.369rem;
2432
+ --tsm-3xl: 3.157rem;
2433
+ --tsm-4xl: 4.209rem;
2434
+ --tsm-5xl: 5.61rem;
2435
+ --tsm-6xl: 7.478rem;
2436
+ --tsm-7xl: 9.969rem;
2437
+ }
2438
+ [data-type-scale-desktop="perfect-fourth"] {
2439
+ --tsd-2xs: 0.625rem;
2440
+ --tsd-xs: 0.64rem;
2441
+ --tsd-sm: 0.8rem;
2442
+ --tsd-base: 1rem;
2443
+ --tsd-lg: 1.333rem;
2444
+ --tsd-xl: 1.777rem;
2445
+ --tsd-2xl: 2.369rem;
2446
+ --tsd-3xl: 3.157rem;
2447
+ --tsd-4xl: 4.209rem;
2448
+ --tsd-5xl: 5.61rem;
2449
+ --tsd-6xl: 7.478rem;
2450
+ --tsd-7xl: 9.969rem;
2451
+ }
2452
+ [data-type-scale="perfect-fourth"] {
2453
+ --tsm-2xs: 0.625rem; --tsd-2xs: 0.625rem;
2454
+ --tsm-xs: 0.64rem; --tsd-xs: 0.64rem;
2455
+ --tsm-sm: 0.8rem; --tsd-sm: 0.8rem;
2456
+ --tsm-base: 1rem; --tsd-base: 1rem;
2457
+ --tsm-lg: 1.333rem; --tsd-lg: 1.333rem;
2458
+ --tsm-xl: 1.777rem; --tsd-xl: 1.777rem;
2459
+ --tsm-2xl: 2.369rem; --tsd-2xl: 2.369rem;
2460
+ --tsm-3xl: 3.157rem; --tsd-3xl: 3.157rem;
2461
+ --tsm-4xl: 4.209rem; --tsd-4xl: 4.209rem;
2462
+ --tsm-5xl: 5.61rem; --tsd-5xl: 5.61rem;
2463
+ --tsm-6xl: 7.478rem; --tsd-6xl: 7.478rem;
2464
+ --tsm-7xl: 9.969rem; --tsd-7xl: 9.969rem;
2465
+ }
2466
+
2467
+ [data-type-scale-mobile="augmented-fourth"] {
2468
+ --tsm-2xs: 0.625rem;
2469
+ --tsm-xs: 0.64rem;
2470
+ --tsm-sm: 0.8rem;
2471
+ --tsm-base: 1rem;
2472
+ --tsm-lg: 1.414rem;
2473
+ --tsm-xl: 1.999rem;
2474
+ --tsm-2xl: 2.827rem;
2475
+ --tsm-3xl: 3.998rem;
2476
+ --tsm-4xl: 5.653rem;
2477
+ --tsm-5xl: 7.993rem;
2478
+ --tsm-6xl: 11.302rem;
2479
+ --tsm-7xl: 15.981rem;
2480
+ }
2481
+ [data-type-scale-desktop="augmented-fourth"] {
2482
+ --tsd-2xs: 0.625rem;
2483
+ --tsd-xs: 0.64rem;
2484
+ --tsd-sm: 0.8rem;
2485
+ --tsd-base: 1rem;
2486
+ --tsd-lg: 1.414rem;
2487
+ --tsd-xl: 1.999rem;
2488
+ --tsd-2xl: 2.827rem;
2489
+ --tsd-3xl: 3.998rem;
2490
+ --tsd-4xl: 5.653rem;
2491
+ --tsd-5xl: 7.993rem;
2492
+ --tsd-6xl: 11.302rem;
2493
+ --tsd-7xl: 15.981rem;
2494
+ }
2495
+ [data-type-scale="augmented-fourth"] {
2496
+ --tsm-2xs: 0.625rem; --tsd-2xs: 0.625rem;
2497
+ --tsm-xs: 0.64rem; --tsd-xs: 0.64rem;
2498
+ --tsm-sm: 0.8rem; --tsd-sm: 0.8rem;
2499
+ --tsm-base: 1rem; --tsd-base: 1rem;
2500
+ --tsm-lg: 1.414rem; --tsd-lg: 1.414rem;
2501
+ --tsm-xl: 1.999rem; --tsd-xl: 1.999rem;
2502
+ --tsm-2xl: 2.827rem; --tsd-2xl: 2.827rem;
2503
+ --tsm-3xl: 3.998rem; --tsd-3xl: 3.998rem;
2504
+ --tsm-4xl: 5.653rem; --tsd-4xl: 5.653rem;
2505
+ --tsm-5xl: 7.993rem; --tsd-5xl: 7.993rem;
2506
+ --tsm-6xl: 11.302rem; --tsd-6xl: 11.302rem;
2507
+ --tsm-7xl: 15.981rem; --tsd-7xl: 15.981rem;
2508
+ }
2509
+
2510
+ [data-type-scale-mobile="perfect-fifth"] {
2511
+ --tsm-2xs: 0.625rem;
2512
+ --tsm-xs: 0.64rem;
2513
+ --tsm-sm: 0.8rem;
2514
+ --tsm-base: 1rem;
2515
+ --tsm-lg: 1.5rem;
2516
+ --tsm-xl: 2.25rem;
2517
+ --tsm-2xl: 3.375rem;
2518
+ --tsm-3xl: 5.063rem;
2519
+ --tsm-4xl: 7.594rem;
2520
+ --tsm-5xl: 11.391rem;
2521
+ --tsm-6xl: 17.086rem;
2522
+ --tsm-7xl: 25.629rem;
2523
+ }
2524
+ [data-type-scale-desktop="perfect-fifth"] {
2525
+ --tsd-2xs: 0.625rem;
2526
+ --tsd-xs: 0.64rem;
2527
+ --tsd-sm: 0.8rem;
2528
+ --tsd-base: 1rem;
2529
+ --tsd-lg: 1.5rem;
2530
+ --tsd-xl: 2.25rem;
2531
+ --tsd-2xl: 3.375rem;
2532
+ --tsd-3xl: 5.063rem;
2533
+ --tsd-4xl: 7.594rem;
2534
+ --tsd-5xl: 11.391rem;
2535
+ --tsd-6xl: 17.086rem;
2536
+ --tsd-7xl: 25.629rem;
2537
+ }
2538
+ [data-type-scale="perfect-fifth"] {
2539
+ --tsm-2xs: 0.625rem; --tsd-2xs: 0.625rem;
2540
+ --tsm-xs: 0.64rem; --tsd-xs: 0.64rem;
2541
+ --tsm-sm: 0.8rem; --tsd-sm: 0.8rem;
2542
+ --tsm-base: 1rem; --tsd-base: 1rem;
2543
+ --tsm-lg: 1.5rem; --tsd-lg: 1.5rem;
2544
+ --tsm-xl: 2.25rem; --tsd-xl: 2.25rem;
2545
+ --tsm-2xl: 3.375rem; --tsd-2xl: 3.375rem;
2546
+ --tsm-3xl: 5.063rem; --tsd-3xl: 5.063rem;
2547
+ --tsm-4xl: 7.594rem; --tsd-4xl: 7.594rem;
2548
+ --tsm-5xl: 11.391rem; --tsd-5xl: 11.391rem;
2549
+ --tsm-6xl: 17.086rem; --tsd-6xl: 17.086rem;
2550
+ --tsm-7xl: 25.629rem; --tsd-7xl: 25.629rem;
2551
+ }
2552
+
2553
+ [data-type-scale-mobile="golden-ratio"] {
2554
+ --tsm-2xs: 0.625rem;
2555
+ --tsm-xs: 0.64rem;
2556
+ --tsm-sm: 0.8rem;
2557
+ --tsm-base: 1rem;
2558
+ --tsm-lg: 1.618rem;
2559
+ --tsm-xl: 2.618rem;
2560
+ --tsm-2xl: 4.236rem;
2561
+ --tsm-3xl: 6.854rem;
2562
+ --tsm-4xl: 11.089rem;
2563
+ --tsm-5xl: 17.942rem;
2564
+ --tsm-6xl: 29.03rem;
2565
+ --tsm-7xl: 46.971rem;
2566
+ }
2567
+ [data-type-scale-desktop="golden-ratio"] {
2568
+ --tsd-2xs: 0.625rem;
2569
+ --tsd-xs: 0.64rem;
2570
+ --tsd-sm: 0.8rem;
2571
+ --tsd-base: 1rem;
2572
+ --tsd-lg: 1.618rem;
2573
+ --tsd-xl: 2.618rem;
2574
+ --tsd-2xl: 4.236rem;
2575
+ --tsd-3xl: 6.854rem;
2576
+ --tsd-4xl: 11.089rem;
2577
+ --tsd-5xl: 17.942rem;
2578
+ --tsd-6xl: 29.03rem;
2579
+ --tsd-7xl: 46.971rem;
2580
+ }
2581
+ [data-type-scale="golden-ratio"] {
2582
+ --tsm-2xs: 0.625rem; --tsd-2xs: 0.625rem;
2583
+ --tsm-xs: 0.64rem; --tsd-xs: 0.64rem;
2584
+ --tsm-sm: 0.8rem; --tsd-sm: 0.8rem;
2585
+ --tsm-base: 1rem; --tsd-base: 1rem;
2586
+ --tsm-lg: 1.618rem; --tsd-lg: 1.618rem;
2587
+ --tsm-xl: 2.618rem; --tsd-xl: 2.618rem;
2588
+ --tsm-2xl: 4.236rem; --tsd-2xl: 4.236rem;
2589
+ --tsm-3xl: 6.854rem; --tsd-3xl: 6.854rem;
2590
+ --tsm-4xl: 11.089rem; --tsd-4xl: 11.089rem;
2591
+ --tsm-5xl: 17.942rem; --tsd-5xl: 17.942rem;
2592
+ --tsm-6xl: 29.03rem; --tsd-6xl: 29.03rem;
2593
+ --tsm-7xl: 46.971rem; --tsd-7xl: 46.971rem;
2594
+ }
2595
+
2596
+ [data-type-scale], [data-type-scale-mobile], [data-type-scale-desktop] {
2597
+ --ts-fluid: clamp(0, calc((100vw - 20rem) / 60rem), 1);
2598
+ --text-2xs: calc(var(--tsm-2xs, var(--tsd-2xs)) + (var(--tsd-2xs, var(--tsm-2xs)) - var(--tsm-2xs, var(--tsd-2xs))) * var(--ts-fluid));
2599
+ --text-xs: calc(var(--tsm-xs, var(--tsd-xs)) + (var(--tsd-xs, var(--tsm-xs)) - var(--tsm-xs, var(--tsd-xs))) * var(--ts-fluid));
2600
+ --text-sm: calc(var(--tsm-sm, var(--tsd-sm)) + (var(--tsd-sm, var(--tsm-sm)) - var(--tsm-sm, var(--tsd-sm))) * var(--ts-fluid));
2601
+ --text-base: calc(var(--tsm-base, var(--tsd-base)) + (var(--tsd-base, var(--tsm-base)) - var(--tsm-base, var(--tsd-base))) * var(--ts-fluid));
2602
+ --text-lg: calc(var(--tsm-lg, var(--tsd-lg)) + (var(--tsd-lg, var(--tsm-lg)) - var(--tsm-lg, var(--tsd-lg))) * var(--ts-fluid));
2603
+ --text-xl: calc(var(--tsm-xl, var(--tsd-xl)) + (var(--tsd-xl, var(--tsm-xl)) - var(--tsm-xl, var(--tsd-xl))) * var(--ts-fluid));
2604
+ --text-2xl: calc(var(--tsm-2xl, var(--tsd-2xl)) + (var(--tsd-2xl, var(--tsm-2xl)) - var(--tsm-2xl, var(--tsd-2xl))) * var(--ts-fluid));
2605
+ --text-3xl: calc(var(--tsm-3xl, var(--tsd-3xl)) + (var(--tsd-3xl, var(--tsm-3xl)) - var(--tsm-3xl, var(--tsd-3xl))) * var(--ts-fluid));
2606
+ --text-4xl: calc(var(--tsm-4xl, var(--tsd-4xl)) + (var(--tsd-4xl, var(--tsm-4xl)) - var(--tsm-4xl, var(--tsd-4xl))) * var(--ts-fluid));
2607
+ --text-5xl: calc(var(--tsm-5xl, var(--tsd-5xl)) + (var(--tsd-5xl, var(--tsm-5xl)) - var(--tsm-5xl, var(--tsd-5xl))) * var(--ts-fluid));
2608
+ --text-6xl: calc(var(--tsm-6xl, var(--tsd-6xl)) + (var(--tsd-6xl, var(--tsm-6xl)) - var(--tsm-6xl, var(--tsd-6xl))) * var(--ts-fluid));
2609
+ --text-7xl: calc(var(--tsm-7xl, var(--tsd-7xl)) + (var(--tsd-7xl, var(--tsm-7xl)) - var(--tsm-7xl, var(--tsd-7xl))) * var(--ts-fluid));
2610
+ --text-display: var(--text-6xl);
2611
+ --text-h1: var(--text-4xl);
2612
+ --text-h2: var(--text-3xl);
2613
+ --text-h3: var(--text-2xl);
2614
+ --text-h4: var(--text-xl);
2615
+ --text-h5: var(--text-lg);
2616
+ --text-body-lg: var(--text-lg);
2617
+ --text-h6: var(--text-base);
2618
+ --text-body: var(--text-base);
2619
+ --text-body-sm: var(--text-sm);
2620
+ }
2621
+
2622
+ /* ============================================
2623
+ SIZE SCALE — scoped, switchable, fluid (mobile → desktop)
2624
+ ============================================
2625
+ Same engine as the type scale, for SPACING. Re-points Tailwind's --spacing
2626
+ base, so EVERY spacing utility (gap-*, p-*, m-*, size-*) re-pitches at once —
2627
+ one knob for a page or section's whole density. Pick a mobile density + a
2628
+ desktop density; --spacing interpolates between them by viewport, clamped.
2629
+ Shorthand data-size-scale="comfortable" sets both (flat). Levels are density
2630
+ presets (the --spacing base unit), not modular ratios — spacing is a linear
2631
+ grid. Composes via the cascade like the type scale; drop data-size-scale=
2632
+ "compact" on an embedded table/UI mockup to tighten just that region. */
2633
+ [data-size-scale-mobile="compact"] { --ssm: 0.2rem; }
2634
+ [data-size-scale-mobile="cozy"] { --ssm: 0.225rem; }
2635
+ [data-size-scale-mobile="comfortable"] { --ssm: 0.25rem; }
2636
+ [data-size-scale-mobile="spacious"] { --ssm: 0.3rem; }
2637
+ [data-size-scale-mobile="expansive"] { --ssm: 0.35rem; }
2638
+ [data-size-scale-desktop="compact"] { --ssd: 0.2rem; }
2639
+ [data-size-scale-desktop="cozy"] { --ssd: 0.225rem; }
2640
+ [data-size-scale-desktop="comfortable"] { --ssd: 0.25rem; }
2641
+ [data-size-scale-desktop="spacious"] { --ssd: 0.3rem; }
2642
+ [data-size-scale-desktop="expansive"] { --ssd: 0.35rem; }
2643
+ [data-size-scale="compact"] { --ssm: 0.2rem; --ssd: 0.2rem; }
2644
+ [data-size-scale="cozy"] { --ssm: 0.225rem; --ssd: 0.225rem; }
2645
+ [data-size-scale="comfortable"] { --ssm: 0.25rem; --ssd: 0.25rem; }
2646
+ [data-size-scale="spacious"] { --ssm: 0.3rem; --ssd: 0.3rem; }
2647
+ [data-size-scale="expansive"] { --ssm: 0.35rem; --ssd: 0.35rem; }
2648
+ [data-size-scale], [data-size-scale-mobile], [data-size-scale-desktop] {
2649
+ --ss-fluid: clamp(0, calc((100vw - 20rem) / 60rem), 1);
2650
+ --spacing: calc(var(--ssm, var(--ssd)) + (var(--ssd, var(--ssm)) - var(--ssm, var(--ssd))) * var(--ss-fluid));
2651
+ }
2652
+
2075
2653
  /* Keyframes */
2076
2654
  @keyframes fadeIn {
2077
2655
  from { opacity: 0; }