@signal9/era-ui 31.0.0 → 32.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.
Files changed (59) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/ai/artifact/artifact.svelte +1 -1
  3. package/dist/ai/web-preview/web-preview.svelte +1 -1
  4. package/dist/ai/workflow/node.svelte +1 -1
  5. package/dist/docs/css-utilities.js +2 -2
  6. package/dist/era-ui.css +1 -1
  7. package/dist/generated-docs/llms-full.txt +61 -22
  8. package/dist/generated-docs/llms.txt +4 -1
  9. package/dist/generated-docs/manifest.json +41 -8
  10. package/dist/generated-docs/utilities.json +36 -6
  11. package/dist/generated-docs/utilities.md +57 -21
  12. package/dist/os/notification-center.svelte +1 -1
  13. package/dist/os/taskbar.svelte +1 -1
  14. package/dist/os/toast.svelte +1 -1
  15. package/dist/styles/index.css +42 -21
  16. package/dist/styles/motion.css +1 -1
  17. package/dist/styles/prose.css +1 -1
  18. package/dist/styles/surfaces/bevel.css +16 -19
  19. package/dist/styles/surfaces/contract.css +50 -0
  20. package/dist/styles/surfaces/flat.css +27 -0
  21. package/dist/styles/surfaces/glass.css +11 -8
  22. package/dist/ui/alert-dialog/alert-dialog-content.svelte +1 -1
  23. package/dist/ui/button/button.svelte +1 -0
  24. package/dist/ui/button/variants.d.ts +3 -3
  25. package/dist/ui/button/variants.js +3 -3
  26. package/dist/ui/card/card.svelte +4 -4
  27. package/dist/ui/card/card.svelte.d.ts +3 -3
  28. package/dist/ui/combobox/combobox-content.svelte +1 -1
  29. package/dist/ui/command/command-root.svelte +3 -3
  30. package/dist/ui/command-bar/command-bar.svelte +3 -3
  31. package/dist/ui/context-menu/context-menu-content.svelte +1 -4
  32. package/dist/ui/context-menu/context-menu-sub-content.svelte +1 -4
  33. package/dist/ui/date-picker/date-picker-content.svelte +1 -1
  34. package/dist/ui/date-range-picker/date-range-picker-content.svelte +1 -1
  35. package/dist/ui/dialog/dialog-content.svelte +1 -1
  36. package/dist/ui/dropdown-menu/dropdown-menu-content.svelte +1 -1
  37. package/dist/ui/dropdown-menu/dropdown-menu-sub-content.svelte +1 -4
  38. package/dist/ui/link-preview/link-preview-content.svelte +1 -1
  39. package/dist/ui/menubar/menubar-content.svelte +1 -1
  40. package/dist/ui/menubar/menubar-sub-content.svelte +1 -4
  41. package/dist/ui/meter/meter.svelte +1 -2
  42. package/dist/ui/nav/nav-item.svelte +1 -0
  43. package/dist/ui/pane/pane-root.svelte +1 -1
  44. package/dist/ui/popover/popover-content.svelte +1 -1
  45. package/dist/ui/provider/surfaces.d.ts +1 -1
  46. package/dist/ui/provider/surfaces.js +1 -1
  47. package/dist/ui/select/select-content.svelte +1 -1
  48. package/dist/ui/sheet/sheet-content.svelte +1 -1
  49. package/dist/ui/sheet/sheet-content.svelte.d.ts +1 -1
  50. package/dist/ui/switch/switch.svelte +1 -1
  51. package/dist/ui/toggle-group/toggle-group-item.svelte +1 -1
  52. package/dist/ui/toggle-group/toggle-group-item.svelte.d.ts +3 -3
  53. package/dist/ui/tooltip/tooltip-content.svelte +1 -1
  54. package/dist/ui/video-player/video-player.svelte +2 -2
  55. package/dist/utils/tw-merge-config.d.ts +3 -1
  56. package/dist/utils/tw-merge-config.js +2 -2
  57. package/package.json +2 -1
  58. package/skill/SKILL.md +9 -4
  59. package/dist/styles/surfaces/base.css +0 -257
@@ -63,7 +63,10 @@ Classes, not components — they need no import beyond the stylesheet. Reach for
63
63
  - `era-ink-center` — on a native single-line <input> (or the text layer that must mirror one) inside a fixed-height field — never alongside era-text-trim.
64
64
  - `era-token-ink` — the ink centring for a token pill — a badge, a KV value, any short caps-or-digits label in a fixed-height box, CENTRED horizontally and with no icon sibling. For a left-aligned sentence-case label use era-label-ink; when an icon really must sit beside the text, see the note there.
65
65
  - `era-label-ink` — the ink centring for a fixed-height control holding ONE line of sentence-case text and no icon — a menu item, a nav trigger, a button label. Never alongside `truncate` (the trimmed box becomes the clip).
66
- - `glass-blur` — the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface="glass" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface.
66
+ - `surface-backdrop` — the surface-aware backdrop treatment without choosing a fill or relief. Prefer material-popover/material-panel when the element is a complete surface.
67
+ - `material-popover` — a floating transient surface: menus, popovers, tooltips, pickers, toasts. Binds its raised fill, floating relief, and backdrop treatment atomically.
68
+ - `material-panel` — a floating persistent surface: dialogs, sheets, panes, inspectors. Binds its resting fill, floating relief, and backdrop treatment atomically.
69
+ - `pressable` — the physical press contract on a control whose direct content plane is marked data-era-press-content. The surface owns relief/travel; the component may scale travel with --era-press-scale.
67
70
  - `tier-icon · tier-pill · tier-chip · tier-control · tier-bar` — BOUNDED GEOMETRY — height and radius are one decision.
68
71
  - `h-line` — the height of one line of the element's own text — a skeleton standing in for a line, a spacer that must match a line box.
69
72
  - `era-track-well` — instead of `shadow-well` on a track whose value is painted by a child that covers the box — a progress/meter/slider track, a custom gauge. For a well holding ordinary content, `shadow-well` is still right.
@@ -223,7 +226,10 @@ source uses it where a name exists.
223
226
  | `era-ink-center` | on a native single-line <input> (or the text layer that must mirror one) inside a fixed-height field — never alongside era-text-trim. |
224
227
  | `era-token-ink` | the ink centring for a token pill — a badge, a KV value, any short caps-or-digits label in a fixed-height box, CENTRED horizontally and with no icon sibling. For a left-aligned sentence-case label use era-label-ink; when an icon really must sit beside the text, see the note there. |
225
228
  | `era-label-ink` | the ink centring for a fixed-height control holding ONE line of sentence-case text and no icon — a menu item, a nav trigger, a button label. Never alongside `truncate` (the trimmed box becomes the clip). |
226
- | `glass-blur` | the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface="glass" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface. |
229
+ | `surface-backdrop` | the surface-aware backdrop treatment without choosing a fill or relief. Prefer material-popover/material-panel when the element is a complete surface. |
230
+ | `material-popover` | a floating transient surface: menus, popovers, tooltips, pickers, toasts. Binds its raised fill, floating relief, and backdrop treatment atomically. |
231
+ | `material-panel` | a floating persistent surface: dialogs, sheets, panes, inspectors. Binds its resting fill, floating relief, and backdrop treatment atomically. |
232
+ | `pressable` | the physical press contract on a control whose direct content plane is marked data-era-press-content. The surface owns relief/travel; the component may scale travel with --era-press-scale. |
227
233
  | `tier-icon` `tier-pill` `tier-chip` `tier-control` `tier-bar` | — |
228
234
  | `h-line` | the height of one line of the element's own text — a skeleton standing in for a line, a spacer that must match a line box. |
229
235
  | `era-track-well` | instead of `shadow-well` on a track whose value is painted by a child that covers the box — a progress/meter/slider track, a custom gauge. For a well holding ordinary content, `shadow-well` is still right. |
@@ -605,31 +611,64 @@ Declared in `index.css`.
605
611
  }
606
612
  ```
607
613
 
608
- ## glass-blur
614
+ ## surface-backdrop
609
615
 
610
- **Use it for:** the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface="glass" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface.
616
+ **Use it for:** the surface-aware backdrop treatment without choosing a fill or relief. Prefer material-popover/material-panel when the element is a complete surface.
611
617
 
612
- Tailwind v4 cannot resolve var() inside backdrop-blur-[], so the filter
613
- is a registered utility, gated to glass subtrees.
618
+ Declared in `index.css`.
619
+
620
+ ```css
621
+ @utility surface-backdrop {
622
+ backdrop-filter: var(--era-backdrop-filter);
623
+ -webkit-backdrop-filter: var(--era-backdrop-filter);
624
+ }
625
+ ```
626
+
627
+ ## material-popover
628
+
629
+ **Use it for:** a floating transient surface: menus, popovers, tooltips, pickers, toasts. Binds its raised fill, floating relief, and backdrop treatment atomically.
630
+
631
+ Declared in `index.css`.
632
+
633
+ ```css
634
+ @utility material-popover {
635
+ background-color: var(--era-surface-bg-elevated);
636
+ box-shadow: var(--era-shadow-lg);
637
+ backdrop-filter: var(--era-backdrop-filter);
638
+ -webkit-backdrop-filter: var(--era-backdrop-filter);
639
+ }
640
+ ```
641
+
642
+ ## material-panel
643
+
644
+ **Use it for:** a floating persistent surface: dialogs, sheets, panes, inspectors. Binds its resting fill, floating relief, and backdrop treatment atomically.
645
+
646
+ Declared in `index.css`.
647
+
648
+ ```css
649
+ @utility material-panel {
650
+ background-color: var(--era-surface-bg);
651
+ box-shadow: var(--era-shadow-lg);
652
+ backdrop-filter: var(--era-backdrop-filter);
653
+ -webkit-backdrop-filter: var(--era-backdrop-filter);
654
+ }
655
+ ```
614
656
 
615
- It lives HERE rather than in surfaces/glass.css, where a surface's own
616
- chrome would naturally sit, because glass.css is imported into a cascade
617
- layer and `@utility` cannot be nested inside one. Surface-scoped RULES stay
618
- in their surface file; surface-scoped UTILITIES have to come out.
657
+ ## pressable
658
+
659
+ **Use it for:** the physical press contract on a control whose direct content plane is marked data-era-press-content. The surface owns relief/travel; the component may scale travel with --era-press-scale.
619
660
 
620
661
  Declared in `index.css`.
621
662
 
622
663
  ```css
623
- @utility` cannot be nested inside one. Surface-scoped RULES stay
624
- * in their surface file; surface-scoped UTILITIES have to come out.
625
- *
626
- * @use the backdrop blur for a floating panel (popover, dialog, taskbar) — it
627
- * applies only inside a data-surface="glass" subtree and is inert elsewhere,
628
- * so it is safe to leave on a panel that renders under every surface. */
629
- @utility glass-blur {
630
- [data-surface='glass'] & {
631
- backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));
632
- -webkit-backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));
664
+ @utility pressable {
665
+ &:active {
666
+ box-shadow: var(--era-shadow-pressed);
667
+ }
668
+
669
+ &:active > [data-era-press-content] {
670
+ translate: var(--era-press-effective-x, var(--era-press-sink-x))
671
+ var(--era-press-effective-y, var(--era-press-sink-y));
633
672
  }
634
673
  }
635
674
  ```
@@ -1163,8 +1202,8 @@ Declared in `index.css`.
1163
1202
  ## bg-well · text-well · border-well · bg-elevated · text-elevated · border-elevated · bg-highlight · text-highlight · … (12 in all)
1164
1203
 
1165
1204
  Surface fills — bg-well is the surface's own resting fill (pairs with
1166
- shadow-well for recessed chrome), bg-elevated the raised tier (pairs with
1167
- shadow-lg + glass-blur for floating chrome), bg-highlight the transient
1205
+ shadow-well for recessed chrome), bg-elevated the raised tier,
1206
+ bg-highlight the transient
1168
1207
  hover/focus/keyboard wash (pairs with shadow-highlight; latched states
1169
1208
  stay on opaque bg-hover), bg-overlay the modal scrim.
1170
1209
 
@@ -101,7 +101,10 @@ Classes, not components — they need no import beyond the stylesheet. Reach for
101
101
  - `era-ink-center` — on a native single-line <input> (or the text layer that must mirror one) inside a fixed-height field — never alongside era-text-trim.
102
102
  - `era-token-ink` — the ink centring for a token pill — a badge, a KV value, any short caps-or-digits label in a fixed-height box, CENTRED horizontally and with no icon sibling. For a left-aligned sentence-case label use era-label-ink; when an icon really must sit beside the text, see the note there.
103
103
  - `era-label-ink` — the ink centring for a fixed-height control holding ONE line of sentence-case text and no icon — a menu item, a nav trigger, a button label. Never alongside `truncate` (the trimmed box becomes the clip).
104
- - `glass-blur` — the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface="glass" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface.
104
+ - `surface-backdrop` — the surface-aware backdrop treatment without choosing a fill or relief. Prefer material-popover/material-panel when the element is a complete surface.
105
+ - `material-popover` — a floating transient surface: menus, popovers, tooltips, pickers, toasts. Binds its raised fill, floating relief, and backdrop treatment atomically.
106
+ - `material-panel` — a floating persistent surface: dialogs, sheets, panes, inspectors. Binds its resting fill, floating relief, and backdrop treatment atomically.
107
+ - `pressable` — the physical press contract on a control whose direct content plane is marked data-era-press-content. The surface owns relief/travel; the component may scale travel with --era-press-scale.
105
108
  - `tier-icon · tier-pill · tier-chip · tier-control · tier-bar` — BOUNDED GEOMETRY — height and radius are one decision.
106
109
  - `h-line` — the height of one line of the element's own text — a skeleton standing in for a line, a spacer that must match a line box.
107
110
  - `era-track-well` — instead of `shadow-well` on a track whose value is painted by a child that covers the box — a progress/meter/slider track, a custom gauge. For a well holding ordinary content, `shadow-well` is still right.
@@ -52,7 +52,7 @@
52
52
  "slug": "utilities",
53
53
  "title": "Utilities",
54
54
  "summary": "The CSS classes era ships alongside the components — links, ink-centred text, shimmer, hidden scrollbars.",
55
- "tokenEstimate": 13623,
55
+ "tokenEstimate": 13846,
56
56
  "sections": [
57
57
  "Overview",
58
58
  "era-interactive",
@@ -64,7 +64,10 @@
64
64
  "era-ink-center",
65
65
  "era-token-ink",
66
66
  "era-label-ink",
67
- "glass-blur",
67
+ "surface-backdrop",
68
+ "material-popover",
69
+ "material-panel",
70
+ "pressable",
68
71
  "tier-icon · tier-pill · tier-chip · tier-control · tier-bar",
69
72
  "h-line",
70
73
  "era-track-well",
@@ -1120,14 +1123,44 @@
1120
1123
  "css": "@utility era-label-ink {\n\tdisplay: block;\n\talign-content: center;\n\tline-height: 1;\n\ttext-box: trim-both ex alphabetic;\n}"
1121
1124
  },
1122
1125
  {
1123
- "name": "glass-blur",
1126
+ "name": "surface-backdrop",
1124
1127
  "names": [
1125
- "glass-blur"
1128
+ "surface-backdrop"
1126
1129
  ],
1127
1130
  "file": "index.css",
1128
- "useCase": "the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface=\"glass\" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface.",
1129
- "description": "Tailwind v4 cannot resolve var() inside backdrop-blur-[], so the filter\nis a registered utility, gated to glass subtrees.\n\nIt lives HERE rather than in surfaces/glass.css, where a surface's own\nchrome would naturally sit, because glass.css is imported into a cascade\nlayer and `@utility` cannot be nested inside one. Surface-scoped RULES stay\nin their surface file; surface-scoped UTILITIES have to come out.",
1130
- "css": "@utility` cannot be nested inside one. Surface-scoped RULES stay\n * in their surface file; surface-scoped UTILITIES have to come out.\n *\n * @use the backdrop blur for a floating panel (popover, dialog, taskbar) — it\n * applies only inside a data-surface=\"glass\" subtree and is inert elsewhere,\n * so it is safe to leave on a panel that renders under every surface. */\n@utility glass-blur {\n\t[data-surface='glass'] & {\n\t\tbackdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));\n\t\t-webkit-backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));\n\t}\n}"
1131
+ "useCase": "the surface-aware backdrop treatment without choosing a fill or relief. Prefer material-popover/material-panel when the element is a complete surface.",
1132
+ "description": "",
1133
+ "css": "@utility surface-backdrop {\n\tbackdrop-filter: var(--era-backdrop-filter);\n\t-webkit-backdrop-filter: var(--era-backdrop-filter);\n}"
1134
+ },
1135
+ {
1136
+ "name": "material-popover",
1137
+ "names": [
1138
+ "material-popover"
1139
+ ],
1140
+ "file": "index.css",
1141
+ "useCase": "a floating transient surface: menus, popovers, tooltips, pickers, toasts. Binds its raised fill, floating relief, and backdrop treatment atomically.",
1142
+ "description": "",
1143
+ "css": "@utility material-popover {\n\tbackground-color: var(--era-surface-bg-elevated);\n\tbox-shadow: var(--era-shadow-lg);\n\tbackdrop-filter: var(--era-backdrop-filter);\n\t-webkit-backdrop-filter: var(--era-backdrop-filter);\n}"
1144
+ },
1145
+ {
1146
+ "name": "material-panel",
1147
+ "names": [
1148
+ "material-panel"
1149
+ ],
1150
+ "file": "index.css",
1151
+ "useCase": "a floating persistent surface: dialogs, sheets, panes, inspectors. Binds its resting fill, floating relief, and backdrop treatment atomically.",
1152
+ "description": "",
1153
+ "css": "@utility material-panel {\n\tbackground-color: var(--era-surface-bg);\n\tbox-shadow: var(--era-shadow-lg);\n\tbackdrop-filter: var(--era-backdrop-filter);\n\t-webkit-backdrop-filter: var(--era-backdrop-filter);\n}"
1154
+ },
1155
+ {
1156
+ "name": "pressable",
1157
+ "names": [
1158
+ "pressable"
1159
+ ],
1160
+ "file": "index.css",
1161
+ "useCase": "the physical press contract on a control whose direct content plane is marked data-era-press-content. The surface owns relief/travel; the component may scale travel with --era-press-scale.",
1162
+ "description": "",
1163
+ "css": "@utility pressable {\n\t&:active {\n\t\tbox-shadow: var(--era-shadow-pressed);\n\t}\n\n\t&:active > [data-era-press-content] {\n\t\ttranslate: var(--era-press-effective-x, var(--era-press-sink-x))\n\t\t\tvar(--era-press-effective-y, var(--era-press-sink-y));\n\t}\n}"
1131
1164
  },
1132
1165
  {
1133
1166
  "name": "tier-icon",
@@ -1381,7 +1414,7 @@
1381
1414
  "border-overlay"
1382
1415
  ],
1383
1416
  "file": "index.css",
1384
- "description": "Surface fills — bg-well is the surface's own resting fill (pairs with\nshadow-well for recessed chrome), bg-elevated the raised tier (pairs with\nshadow-lg + glass-blur for floating chrome), bg-highlight the transient\nhover/focus/keyboard wash (pairs with shadow-highlight; latched states\nstay on opaque bg-hover), bg-overlay the modal scrim.",
1417
+ "description": "Surface fills — bg-well is the surface's own resting fill (pairs with\nshadow-well for recessed chrome), bg-elevated the raised tier,\nbg-highlight the transient\nhover/focus/keyboard wash (pairs with shadow-highlight; latched states\nstay on opaque bg-hover), bg-overlay the modal scrim.",
1385
1418
  "css": "@theme inline {\n\t--color-well: var(--era-surface-bg);\n\t--color-elevated: var(--era-surface-bg-elevated);\n\t--color-highlight: var(--era-highlight);\n\t--color-overlay: var(--era-overlay-bg);\n}"
1386
1419
  },
1387
1420
  {
@@ -91,14 +91,44 @@
91
91
  "css": "@utility era-label-ink {\n\tdisplay: block;\n\talign-content: center;\n\tline-height: 1;\n\ttext-box: trim-both ex alphabetic;\n}"
92
92
  },
93
93
  {
94
- "name": "glass-blur",
94
+ "name": "surface-backdrop",
95
95
  "names": [
96
- "glass-blur"
96
+ "surface-backdrop"
97
97
  ],
98
98
  "file": "index.css",
99
- "useCase": "the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface=\"glass\" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface.",
100
- "description": "Tailwind v4 cannot resolve var() inside backdrop-blur-[], so the filter\nis a registered utility, gated to glass subtrees.\n\nIt lives HERE rather than in surfaces/glass.css, where a surface's own\nchrome would naturally sit, because glass.css is imported into a cascade\nlayer and `@utility` cannot be nested inside one. Surface-scoped RULES stay\nin their surface file; surface-scoped UTILITIES have to come out.",
101
- "css": "@utility` cannot be nested inside one. Surface-scoped RULES stay\n * in their surface file; surface-scoped UTILITIES have to come out.\n *\n * @use the backdrop blur for a floating panel (popover, dialog, taskbar) — it\n * applies only inside a data-surface=\"glass\" subtree and is inert elsewhere,\n * so it is safe to leave on a panel that renders under every surface. */\n@utility glass-blur {\n\t[data-surface='glass'] & {\n\t\tbackdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));\n\t\t-webkit-backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));\n\t}\n}"
99
+ "useCase": "the surface-aware backdrop treatment without choosing a fill or relief. Prefer material-popover/material-panel when the element is a complete surface.",
100
+ "description": "",
101
+ "css": "@utility surface-backdrop {\n\tbackdrop-filter: var(--era-backdrop-filter);\n\t-webkit-backdrop-filter: var(--era-backdrop-filter);\n}"
102
+ },
103
+ {
104
+ "name": "material-popover",
105
+ "names": [
106
+ "material-popover"
107
+ ],
108
+ "file": "index.css",
109
+ "useCase": "a floating transient surface: menus, popovers, tooltips, pickers, toasts. Binds its raised fill, floating relief, and backdrop treatment atomically.",
110
+ "description": "",
111
+ "css": "@utility material-popover {\n\tbackground-color: var(--era-surface-bg-elevated);\n\tbox-shadow: var(--era-shadow-lg);\n\tbackdrop-filter: var(--era-backdrop-filter);\n\t-webkit-backdrop-filter: var(--era-backdrop-filter);\n}"
112
+ },
113
+ {
114
+ "name": "material-panel",
115
+ "names": [
116
+ "material-panel"
117
+ ],
118
+ "file": "index.css",
119
+ "useCase": "a floating persistent surface: dialogs, sheets, panes, inspectors. Binds its resting fill, floating relief, and backdrop treatment atomically.",
120
+ "description": "",
121
+ "css": "@utility material-panel {\n\tbackground-color: var(--era-surface-bg);\n\tbox-shadow: var(--era-shadow-lg);\n\tbackdrop-filter: var(--era-backdrop-filter);\n\t-webkit-backdrop-filter: var(--era-backdrop-filter);\n}"
122
+ },
123
+ {
124
+ "name": "pressable",
125
+ "names": [
126
+ "pressable"
127
+ ],
128
+ "file": "index.css",
129
+ "useCase": "the physical press contract on a control whose direct content plane is marked data-era-press-content. The surface owns relief/travel; the component may scale travel with --era-press-scale.",
130
+ "description": "",
131
+ "css": "@utility pressable {\n\t&:active {\n\t\tbox-shadow: var(--era-shadow-pressed);\n\t}\n\n\t&:active > [data-era-press-content] {\n\t\ttranslate: var(--era-press-effective-x, var(--era-press-sink-x))\n\t\t\tvar(--era-press-effective-y, var(--era-press-sink-y));\n\t}\n}"
102
132
  },
103
133
  {
104
134
  "name": "tier-icon",
@@ -352,7 +382,7 @@
352
382
  "border-overlay"
353
383
  ],
354
384
  "file": "index.css",
355
- "description": "Surface fills — bg-well is the surface's own resting fill (pairs with\nshadow-well for recessed chrome), bg-elevated the raised tier (pairs with\nshadow-lg + glass-blur for floating chrome), bg-highlight the transient\nhover/focus/keyboard wash (pairs with shadow-highlight; latched states\nstay on opaque bg-hover), bg-overlay the modal scrim.",
385
+ "description": "Surface fills — bg-well is the surface's own resting fill (pairs with\nshadow-well for recessed chrome), bg-elevated the raised tier,\nbg-highlight the transient\nhover/focus/keyboard wash (pairs with shadow-highlight; latched states\nstay on opaque bg-hover), bg-overlay the modal scrim.",
356
386
  "css": "@theme inline {\n\t--color-well: var(--era-surface-bg);\n\t--color-elevated: var(--era-surface-bg-elevated);\n\t--color-highlight: var(--era-highlight);\n\t--color-overlay: var(--era-overlay-bg);\n}"
357
387
  },
358
388
  {
@@ -73,7 +73,10 @@ source uses it where a name exists.
73
73
  | `era-ink-center` | on a native single-line <input> (or the text layer that must mirror one) inside a fixed-height field — never alongside era-text-trim. |
74
74
  | `era-token-ink` | the ink centring for a token pill — a badge, a KV value, any short caps-or-digits label in a fixed-height box, CENTRED horizontally and with no icon sibling. For a left-aligned sentence-case label use era-label-ink; when an icon really must sit beside the text, see the note there. |
75
75
  | `era-label-ink` | the ink centring for a fixed-height control holding ONE line of sentence-case text and no icon — a menu item, a nav trigger, a button label. Never alongside `truncate` (the trimmed box becomes the clip). |
76
- | `glass-blur` | the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface="glass" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface. |
76
+ | `surface-backdrop` | the surface-aware backdrop treatment without choosing a fill or relief. Prefer material-popover/material-panel when the element is a complete surface. |
77
+ | `material-popover` | a floating transient surface: menus, popovers, tooltips, pickers, toasts. Binds its raised fill, floating relief, and backdrop treatment atomically. |
78
+ | `material-panel` | a floating persistent surface: dialogs, sheets, panes, inspectors. Binds its resting fill, floating relief, and backdrop treatment atomically. |
79
+ | `pressable` | the physical press contract on a control whose direct content plane is marked data-era-press-content. The surface owns relief/travel; the component may scale travel with --era-press-scale. |
77
80
  | `tier-icon` `tier-pill` `tier-chip` `tier-control` `tier-bar` | — |
78
81
  | `h-line` | the height of one line of the element's own text — a skeleton standing in for a line, a spacer that must match a line box. |
79
82
  | `era-track-well` | instead of `shadow-well` on a track whose value is painted by a child that covers the box — a progress/meter/slider track, a custom gauge. For a well holding ordinary content, `shadow-well` is still right. |
@@ -455,31 +458,64 @@ Declared in `index.css`.
455
458
  }
456
459
  ```
457
460
 
458
- ## glass-blur
461
+ ## surface-backdrop
459
462
 
460
- **Use it for:** the backdrop blur for a floating panel (popover, dialog, taskbar) — it applies only inside a data-surface="glass" subtree and is inert elsewhere, so it is safe to leave on a panel that renders under every surface.
463
+ **Use it for:** the surface-aware backdrop treatment without choosing a fill or relief. Prefer material-popover/material-panel when the element is a complete surface.
461
464
 
462
- Tailwind v4 cannot resolve var() inside backdrop-blur-[], so the filter
463
- is a registered utility, gated to glass subtrees.
465
+ Declared in `index.css`.
466
+
467
+ ```css
468
+ @utility surface-backdrop {
469
+ backdrop-filter: var(--era-backdrop-filter);
470
+ -webkit-backdrop-filter: var(--era-backdrop-filter);
471
+ }
472
+ ```
473
+
474
+ ## material-popover
475
+
476
+ **Use it for:** a floating transient surface: menus, popovers, tooltips, pickers, toasts. Binds its raised fill, floating relief, and backdrop treatment atomically.
477
+
478
+ Declared in `index.css`.
479
+
480
+ ```css
481
+ @utility material-popover {
482
+ background-color: var(--era-surface-bg-elevated);
483
+ box-shadow: var(--era-shadow-lg);
484
+ backdrop-filter: var(--era-backdrop-filter);
485
+ -webkit-backdrop-filter: var(--era-backdrop-filter);
486
+ }
487
+ ```
488
+
489
+ ## material-panel
490
+
491
+ **Use it for:** a floating persistent surface: dialogs, sheets, panes, inspectors. Binds its resting fill, floating relief, and backdrop treatment atomically.
492
+
493
+ Declared in `index.css`.
494
+
495
+ ```css
496
+ @utility material-panel {
497
+ background-color: var(--era-surface-bg);
498
+ box-shadow: var(--era-shadow-lg);
499
+ backdrop-filter: var(--era-backdrop-filter);
500
+ -webkit-backdrop-filter: var(--era-backdrop-filter);
501
+ }
502
+ ```
464
503
 
465
- It lives HERE rather than in surfaces/glass.css, where a surface's own
466
- chrome would naturally sit, because glass.css is imported into a cascade
467
- layer and `@utility` cannot be nested inside one. Surface-scoped RULES stay
468
- in their surface file; surface-scoped UTILITIES have to come out.
504
+ ## pressable
505
+
506
+ **Use it for:** the physical press contract on a control whose direct content plane is marked data-era-press-content. The surface owns relief/travel; the component may scale travel with --era-press-scale.
469
507
 
470
508
  Declared in `index.css`.
471
509
 
472
510
  ```css
473
- @utility` cannot be nested inside one. Surface-scoped RULES stay
474
- * in their surface file; surface-scoped UTILITIES have to come out.
475
- *
476
- * @use the backdrop blur for a floating panel (popover, dialog, taskbar) — it
477
- * applies only inside a data-surface="glass" subtree and is inert elsewhere,
478
- * so it is safe to leave on a panel that renders under every surface. */
479
- @utility glass-blur {
480
- [data-surface='glass'] & {
481
- backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));
482
- -webkit-backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));
511
+ @utility pressable {
512
+ &:active {
513
+ box-shadow: var(--era-shadow-pressed);
514
+ }
515
+
516
+ &:active > [data-era-press-content] {
517
+ translate: var(--era-press-effective-x, var(--era-press-sink-x))
518
+ var(--era-press-effective-y, var(--era-press-sink-y));
483
519
  }
484
520
  }
485
521
  ```
@@ -1013,8 +1049,8 @@ Declared in `index.css`.
1013
1049
  ## bg-well · text-well · border-well · bg-elevated · text-elevated · border-elevated · bg-highlight · text-highlight · … (12 in all)
1014
1050
 
1015
1051
  Surface fills — bg-well is the surface's own resting fill (pairs with
1016
- shadow-well for recessed chrome), bg-elevated the raised tier (pairs with
1017
- shadow-lg + glass-blur for floating chrome), bg-highlight the transient
1052
+ shadow-well for recessed chrome), bg-elevated the raised tier,
1053
+ bg-highlight the transient
1018
1054
  hover/focus/keyboard wash (pairs with shadow-highlight; latched states
1019
1055
  stay on opaque bg-hover), bg-overlay the modal scrim.
1020
1056
 
@@ -51,7 +51,7 @@
51
51
  transition:eraFly={{ x: 320, duration: 200 }}
52
52
  style:top="{pm.insets.top}px"
53
53
  style:bottom="{pm.insets.bottom}px"
54
- class="absolute right-0 flex w-80 flex-col bg-well shadow-lg glass-blur"
54
+ class="absolute right-0 flex w-80 flex-col material-panel"
55
55
  >
56
56
  <header
57
57
  class="flex shrink-0 items-center gap-gutter border-b border-divider-faded px-card py-inset-chip"
@@ -210,7 +210,7 @@
210
210
  // shadow-lg only when FLOATING. Flush, the bar's edge is its own
211
211
  // border-b/border-t against the content it docks beside, and the ring would
212
212
  // double it on exactly that side — the one edge a flush bar exposes.
213
- 'absolute flex h-bar items-center gap-gutter bg-elevated px-gutter glass-blur',
213
+ 'absolute flex h-bar items-center gap-gutter bg-elevated px-gutter surface-backdrop',
214
214
  floating && 'shadow-lg',
215
215
  floating
216
216
  ? cn('inset-x-gutter rounded-bar', position === 'top' ? 'top-gutter' : 'bottom-gutter')
@@ -16,7 +16,7 @@
16
16
  </script>
17
17
 
18
18
  <div
19
- class="pointer-events-auto relative flex w-80 gap-inset-chip overflow-hidden rounded-bar bg-elevated p-card shadow-lg glass-blur"
19
+ class="pointer-events-auto relative flex w-80 gap-inset-chip overflow-hidden rounded-bar material-popover p-card"
20
20
  >
21
21
  <span class={cn('absolute inset-y-menu left-menu w-1 rounded-full', accent[n.tone])}></span>
22
22
  {#if n.icon}
@@ -36,10 +36,9 @@
36
36
  * surfaces so a [data-surface] block can override --era-ease as a delta.
37
37
  * UNLAYERED: carries the prefers-reduced-motion !important — see above. */
38
38
  @import './motion.css';
39
- /* Surfaces: base contract first, then each surface's deltas. Order matters —
40
- * the base block and a surface's block target the same element, and the
41
- * surface's declarations must win. Same layer, so source order still decides. */
42
- @import './surfaces/base.css' layer(era.tokens);
39
+ /* Material contract first, then complete surface implementations. */
40
+ @import './surfaces/contract.css' layer(era.tokens);
41
+ @import './surfaces/flat.css' layer(era.tokens);
43
42
  @import './surfaces/glass.css' layer(era.tokens);
44
43
  @import './surfaces/bevel.css' layer(era.tokens);
45
44
  /* UNLAYERED: carries the font-axis !important — see above. */
@@ -443,21 +442,43 @@
443
442
  text-box: trim-both ex alphabetic;
444
443
  }
445
444
 
446
- /* Tailwind v4 cannot resolve var() inside backdrop-blur-[], so the filter
447
- * is a registered utility, gated to glass subtrees.
448
- *
449
- * It lives HERE rather than in surfaces/glass.css, where a surface's own
450
- * chrome would naturally sit, because glass.css is imported into a cascade
451
- * layer and `@utility` cannot be nested inside one. Surface-scoped RULES stay
452
- * in their surface file; surface-scoped UTILITIES have to come out.
453
- *
454
- * @use the backdrop blur for a floating panel (popover, dialog, taskbar) it
455
- * applies only inside a data-surface="glass" subtree and is inert elsewhere,
456
- * so it is safe to leave on a panel that renders under every surface. */
457
- @utility glass-blur {
458
- [data-surface='glass'] & {
459
- backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));
460
- -webkit-backdrop-filter: blur(var(--era-blur)) saturate(var(--era-saturate));
445
+ /* MATERIAL ROLES components choose meaning; surfaces choose appearance. */
446
+ /* @use the surface-aware backdrop treatment without choosing a fill or relief.
447
+ * Prefer material-popover/material-panel when the element is a complete surface. */
448
+ @utility surface-backdrop {
449
+ backdrop-filter: var(--era-backdrop-filter);
450
+ -webkit-backdrop-filter: var(--era-backdrop-filter);
451
+ }
452
+
453
+ /* @use a floating transient surface: menus, popovers, tooltips, pickers, toasts.
454
+ * Binds its raised fill, floating relief, and backdrop treatment atomically. */
455
+ @utility material-popover {
456
+ background-color: var(--era-surface-bg-elevated);
457
+ box-shadow: var(--era-shadow-lg);
458
+ backdrop-filter: var(--era-backdrop-filter);
459
+ -webkit-backdrop-filter: var(--era-backdrop-filter);
460
+ }
461
+
462
+ /* @use a floating persistent surface: dialogs, sheets, panes, inspectors.
463
+ * Binds its resting fill, floating relief, and backdrop treatment atomically. */
464
+ @utility material-panel {
465
+ background-color: var(--era-surface-bg);
466
+ box-shadow: var(--era-shadow-lg);
467
+ backdrop-filter: var(--era-backdrop-filter);
468
+ -webkit-backdrop-filter: var(--era-backdrop-filter);
469
+ }
470
+
471
+ /* @use the physical press contract on a control whose direct content plane is
472
+ * marked data-era-press-content. The surface owns relief/travel; compact
473
+ * components select the compact travel primitives as their effective values. */
474
+ @utility pressable {
475
+ &:active {
476
+ box-shadow: var(--era-shadow-pressed);
477
+ }
478
+
479
+ &:active > [data-era-press-content] {
480
+ translate: var(--era-press-effective-x, var(--era-press-sink-x))
481
+ var(--era-press-effective-y, var(--era-press-sink-y));
461
482
  }
462
483
  }
463
484
 
@@ -758,8 +779,8 @@
758
779
  --shadow-pressed: var(--era-shadow-pressed);
759
780
  --shadow-highlight: var(--era-highlight-shadow);
760
781
  /* Surface fills — bg-well is the surface's own resting fill (pairs with
761
- * shadow-well for recessed chrome), bg-elevated the raised tier (pairs with
762
- * shadow-lg + glass-blur for floating chrome), bg-highlight the transient
782
+ * shadow-well for recessed chrome), bg-elevated the raised tier,
783
+ * bg-highlight the transient
763
784
  * hover/focus/keyboard wash (pairs with shadow-highlight; latched states
764
785
  * stay on opaque bg-hover), bg-overlay the modal scrim. */
765
786
  --color-well: var(--era-surface-bg);
@@ -22,7 +22,7 @@
22
22
  *
23
23
  * Surfaces may override --era-ease (or a component-scoped ease token) as a
24
24
  * delta — motion.css is imported BEFORE surfaces/, so a [data-surface] block
25
- * wins. See surfaces/base.css for the surface-animation recipe.
25
+ * wins. Surface implementations may override only the easing primitive.
26
26
  */
27
27
 
28
28
  /* Named easing curves — design constants, referenced by the levels below. */
@@ -372,7 +372,7 @@
372
372
  /* NO ::selection rule here, deliberately.
373
373
  *
374
374
  * era owns text selection as a surface token contract — --era-selection-bg /
375
- * -fg / -shadow (surfaces/base.css), which is how flat gets inverse video,
375
+ * -fg / -shadow (surfaces/contract.css), which is how flat gets inverse video,
376
376
  * glass a glowing wash, and bevel an opaque accent bar. This file used to
377
377
  * override it with `background: var(--color-4)` and no `color`, which threw
378
378
  * all of that away AND left body text on a mid-scale grey: the band barely
@@ -23,6 +23,10 @@
23
23
  * shading reads as lighting, not tilt. Do not remove it.
24
24
  */
25
25
  [data-surface='bevel'] {
26
+ --era-border-color: transparent;
27
+ --era-divider-color: var(--color-border);
28
+ --era-surface-bg: var(--color-2);
29
+ --era-field-bg: var(--color-hover);
26
30
  /* Horizontal cast ratio — the light-direction knob (see header). Below 1
27
31
  * rotates the light toward the top; the vertical cast stays a full pixel. */
28
32
  --era-bevel-side: 0.6;
@@ -46,7 +50,7 @@
46
50
  ),
47
51
  var(--era-bevel-rim);
48
52
  /* ELEVATION IS A CHISEL, NOT A TONE — bevel's whole premise, and the reason
49
- * it opts out of the raised tier's tone step. base now mixes the elevated
53
+ * it opts out of the flat implementation's raised-tier tone step. Flat mixes the elevated
50
54
  * fill 6% toward --color-bright so flat can separate a floating panel
51
55
  * without drawing an edge; bevel already separates one with the slab below,
52
56
  * and a panel that was ALSO a lighter grey would read as two mechanisms
@@ -93,19 +97,28 @@
93
97
  ),
94
98
  var(--era-bevel-rim);
95
99
  --era-shadow-pressed: var(--era-shadow-well);
100
+ --era-highlight: light-dark(
101
+ color-mix(in oklch, var(--color-bright) 9%, transparent),
102
+ color-mix(in oklch, var(--color-bright) 8%, transparent)
103
+ );
104
+ --era-fill: var(--era-highlight);
96
105
  /* The BOX never moves on press, so releasing doesn't pop the button up.
97
106
  * Instead the CONTENT sinks straight DOWN 1px while
98
107
  * the frame holds still, so the icon/label depresses like a Win95 keycap
99
108
  * travelling into its socket. An earlier version also nudged it 1px RIGHT (into
100
109
  * the sunken bottom-right corner) but the sideways drift read as the glyph
101
110
  * sliding off rather than pressing in — vertical-only is the truer key press.
102
- * The smallest icon buttons override this to half see below the block. */
111
+ * Compact controls select the half-step travel from the same contract. */
103
112
  --era-press-sink-x: 0px;
104
113
  --era-press-sink-y: 1px;
114
+ --era-press-sink-compact-x: 0px;
115
+ --era-press-sink-compact-y: 0.5px;
105
116
  /* Floating panels wear a 2-layer chisel frame; row highlights inset past
106
117
  * it with a concentric radius (square under data-corners="square", as
107
118
  * the era had it — Win95 drew its selection bar inside the border). */
108
119
  --era-panel-inset: 2px;
120
+ --era-overlay-bg: color-mix(in oklch, var(--color-1) 60%, transparent);
121
+ --era-backdrop-filter: none;
109
122
  /* Text selection is the period highlight bar: hard, fully opaque, in the
110
123
  * ACCENT — Win95 painted selections with the system highlight color, not
111
124
  * inverse video. Under the neutral theme primary is the fg step, so it
@@ -113,21 +126,5 @@
113
126
  * colored selection. Crisp by definition: no glow, no shadow. */
114
127
  --era-selection-bg: var(--color-primary);
115
128
  --era-selection-fg: var(--color-primary-fg);
116
- }
117
-
118
- /*
119
- * SMALL-BUTTON SINK — the depression, scaled to the keycap.
120
- *
121
- * The 1px content sink is tuned for a default (h-control) button, where it is ~4% of
122
- * the box. On the h-icon tier — size="xs" and size="icon", the 14px squares a
123
- * pane's close X is built from — that same 1px is ~7% of the box and the glyph,
124
- * which fills the button, visibly drops too far on press. Half the sink
125
- * (proportional: 14/24 ≈ 0.58, rounded to 0.5) puts the small keycap's travel
126
- * back in step with the large one. Overriding the token (not the transform)
127
- * means the existing `[&:active>*]` rule keeps applying it; the content wrapper
128
- * inherits the value.
129
- */
130
- [data-surface='bevel'] button[data-size='xs'],
131
- [data-surface='bevel'] button[data-size='icon'] {
132
- --era-press-sink-y: 0.5px;
129
+ --era-selection-shadow: none;
133
130
  }