@lepid-labs/styles 1.0.0 → 1.0.2

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 (50) hide show
  1. package/css.d.ts +8 -0
  2. package/luminous-precision/base.css +6 -2
  3. package/luminous-precision/components/badge.css +25 -0
  4. package/luminous-precision/components/button-group.css +130 -0
  5. package/luminous-precision/components/button-hold.css +112 -0
  6. package/luminous-precision/components/icon-button.css +71 -0
  7. package/luminous-precision/components/layout.css +348 -0
  8. package/luminous-precision/components/page.css +85 -0
  9. package/luminous-precision/components/pre.css +75 -0
  10. package/luminous-precision/components/shell.css +165 -0
  11. package/luminous-precision/components/status-card.css +159 -0
  12. package/luminous-precision/components/stepper.css +108 -0
  13. package/luminous-precision/components/table.css +20 -0
  14. package/luminous-precision/components/tabs.css +42 -0
  15. package/luminous-precision/design.md +64 -4
  16. package/luminous-precision/index.css +8 -0
  17. package/luminous-precision/tokens.css +6 -0
  18. package/neon-butterfly/base.css +6 -2
  19. package/neon-butterfly/components/badge.css +25 -0
  20. package/neon-butterfly/components/button-group.css +128 -0
  21. package/neon-butterfly/components/button-hold.css +112 -0
  22. package/neon-butterfly/components/icon-button.css +66 -0
  23. package/neon-butterfly/components/layout.css +348 -0
  24. package/neon-butterfly/components/page.css +85 -0
  25. package/neon-butterfly/components/pre.css +75 -0
  26. package/neon-butterfly/components/shell.css +196 -0
  27. package/neon-butterfly/components/status-card.css +156 -0
  28. package/neon-butterfly/components/stepper.css +107 -0
  29. package/neon-butterfly/components/table.css +20 -0
  30. package/neon-butterfly/components/tabs.css +42 -0
  31. package/neon-butterfly/design.md +60 -4
  32. package/neon-butterfly/index.css +8 -0
  33. package/neon-butterfly/tokens.css +6 -0
  34. package/package.json +58 -15
  35. package/summer-cloud/base.css +6 -2
  36. package/summer-cloud/components/badge.css +26 -0
  37. package/summer-cloud/components/button-group.css +131 -0
  38. package/summer-cloud/components/button-hold.css +132 -0
  39. package/summer-cloud/components/icon-button.css +76 -0
  40. package/summer-cloud/components/layout.css +348 -0
  41. package/summer-cloud/components/page.css +85 -0
  42. package/summer-cloud/components/pre.css +74 -0
  43. package/summer-cloud/components/shell.css +197 -0
  44. package/summer-cloud/components/status-card.css +158 -0
  45. package/summer-cloud/components/stepper.css +101 -0
  46. package/summer-cloud/components/table.css +20 -0
  47. package/summer-cloud/components/tabs.css +42 -0
  48. package/summer-cloud/design.md +64 -2
  49. package/summer-cloud/index.css +8 -0
  50. package/summer-cloud/tokens.css +6 -0
@@ -0,0 +1,112 @@
1
+ /* neon-butterfly — hold-to-confirm button: lime ring (the activity signal), glow on commit
2
+ *
3
+ * Contract: .ld-btn--hold composes with .ld-btn and any variant. The consumer
4
+ * writes one number, --ld-hold in [0, 1]; the ring fill is pure CSS.
5
+ * data-ld-hold="holding" | "fired" carries the behavioural state.
6
+ */
7
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn--hold {
8
+ --ld-hold: 0;
9
+ --ld-hold-color: var(--ld-on-surface); /* neutral on its own */
10
+ position: relative;
11
+ gap: var(--ld-space-3);
12
+ padding: var(--ld-space-2) var(--ld-space-3) var(--ld-space-2) var(--ld-space-2);
13
+ text-align: left;
14
+ user-select: none;
15
+ -webkit-user-select: none;
16
+ touch-action: none; /* a touch hold must not turn into a scroll */
17
+ }
18
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn--hold.ld-btn--primary {
19
+ --ld-hold-color: var(--ld-primary);
20
+ }
21
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn--hold.ld-btn--accent {
22
+ --ld-hold-color: var(--ld-accent);
23
+ }
24
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn--hold.ld-btn--danger {
25
+ --ld-hold-color: var(--ld-accent);
26
+ }
27
+
28
+ /* ring: the icon well, wrapped by a conic fill masked to a 3px stroke */
29
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn__ring {
30
+ position: relative;
31
+ display: inline-grid;
32
+ place-items: center;
33
+ flex: none;
34
+ width: 2.25rem;
35
+ height: 2.25rem;
36
+ border-radius: 50%;
37
+ background: var(--ld-surface-sunken);
38
+ color: var(--ld-hold-color);
39
+ }
40
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn__ring::before {
41
+ content: "";
42
+ position: absolute;
43
+ inset: 0;
44
+ border-radius: 50%;
45
+ background: conic-gradient(var(--ld-hold-color) calc(var(--ld-hold) * 360deg), var(--ld-border-lit) 0);
46
+ -webkit-mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
47
+ mask: radial-gradient(farthest-side, transparent calc(100% - 3px), #000 calc(100% - 2.5px));
48
+ }
49
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn__ring > svg {
50
+ width: 1rem;
51
+ height: 1rem;
52
+ }
53
+
54
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn__body {
55
+ display: flex;
56
+ flex-direction: column;
57
+ align-items: flex-start;
58
+ gap: 0.125rem;
59
+ line-height: 1.2;
60
+ }
61
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn__label {
62
+ font-weight: var(--ld-font-weight-bold);
63
+ }
64
+ /* the hint and meter restate the ring, so state is never color-only */
65
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn__hint {
66
+ font-size: 11px;
67
+ font-weight: var(--ld-font-weight);
68
+ letter-spacing: normal;
69
+ text-transform: none;
70
+ color: var(--ld-faint);
71
+ }
72
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn__meter {
73
+ margin-left: auto;
74
+ min-width: 3.5ch;
75
+ text-align: right;
76
+ font-family: var(--ld-font-mono);
77
+ font-variant-numeric: tabular-nums;
78
+ font-size: 12px;
79
+ color: var(--ld-faint);
80
+ }
81
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn--hold[data-ld-hold="holding"] .ld-btn__meter {
82
+ color: var(--ld-hold-color);
83
+ }
84
+
85
+ /* fired: the post-commit flash */
86
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn--hold[data-ld-hold="fired"] {
87
+ border-color: var(--ld-hold-color);
88
+ animation: ld-nb-hold-fired 0.6s ease-out;
89
+ }
90
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn--hold[data-ld-hold="fired"] .ld-btn__ring {
91
+ box-shadow: 0 0 16px color-mix(in srgb, var(--ld-hold-color) 55%, transparent);
92
+ }
93
+ @keyframes ld-nb-hold-fired {
94
+ from {
95
+ box-shadow: 0 0 28px color-mix(in srgb, var(--ld-hold-color) 70%, transparent);
96
+ }
97
+ to {
98
+ box-shadow: 0 0 12px color-mix(in srgb, var(--ld-hold-color) 35%, transparent);
99
+ }
100
+ }
101
+
102
+ /* reduced motion: the ring still fills (it is the state, not decoration);
103
+ * only the flash and glow go */
104
+ @media (prefers-reduced-motion: reduce) {
105
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn--hold[data-ld-hold="fired"] {
106
+ animation: none;
107
+ box-shadow: none;
108
+ }
109
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-btn--hold[data-ld-hold="fired"] .ld-btn__ring {
110
+ box-shadow: none;
111
+ }
112
+ }
@@ -0,0 +1,66 @@
1
+ /* neon-butterfly — icon button: chromeless square, faint glyph that lights lilac (backplane's .icon-btn).
2
+ * Icon-only control (<button> or <a>): give it an accessible name (aria-label).
3
+ * Active/current: .ld-icon-btn--active, [aria-pressed="true"], [aria-current="page"]. */
4
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn {
5
+ display: inline-flex;
6
+ align-items: center;
7
+ justify-content: center;
8
+ flex: none;
9
+ width: 2rem;
10
+ height: 2rem;
11
+ padding: 0;
12
+ background: none;
13
+ border: none;
14
+ border-radius: var(--ld-radius);
15
+ color: var(--ld-faint);
16
+ font: inherit;
17
+ line-height: 1;
18
+ text-decoration: none;
19
+ cursor: pointer;
20
+ transition: color var(--ld-transition), box-shadow var(--ld-transition);
21
+ }
22
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn > svg {
23
+ width: 1.25em;
24
+ height: 1.25em;
25
+ flex: none;
26
+ }
27
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn:hover,
28
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn:focus-visible {
29
+ color: var(--ld-primary);
30
+ outline: none;
31
+ }
32
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn:focus-visible {
33
+ box-shadow: 0 0 0 1px var(--ld-primary-border), 0 0 8px var(--ld-primary-glow);
34
+ }
35
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn--active,
36
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn[aria-pressed="true"],
37
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn[aria-current="page"] {
38
+ color: var(--ld-primary);
39
+ text-shadow: 0 0 8px var(--ld-primary-glow);
40
+ }
41
+
42
+ /* danger: destructive action (delete, remove) — faint at rest, red on hover */
43
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn--danger:hover,
44
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn--danger:focus-visible {
45
+ color: var(--ld-danger);
46
+ }
47
+
48
+ /* disabled: dimmed and inert — hover never lights it; [aria-disabled] covers <a> */
49
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn:disabled,
50
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn[aria-disabled="true"] {
51
+ opacity: 0.4;
52
+ color: var(--ld-faint);
53
+ background: none;
54
+ box-shadow: none;
55
+ transform: none;
56
+ cursor: not-allowed;
57
+ }
58
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn[aria-disabled="true"] {
59
+ pointer-events: none;
60
+ }
61
+
62
+ @media (prefers-reduced-motion: reduce) {
63
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-icon-btn {
64
+ transition: none;
65
+ }
66
+ }
@@ -0,0 +1,348 @@
1
+ /* neon-butterfly — layout: the app shell's grid, sticky parts, rail, drawer and tab
2
+ * bar. Structure only, identical in every theme (the chrome lives in
3
+ * shell.css; the page layouts that go inside main live in page.css).
4
+ *
5
+ * .ld-shell is a grid of named areas; any of __header, __nav, __footer may be
6
+ * left out and its track collapses to nothing, so there are no "has header"
7
+ * modifiers. The shell paints the theme's page background (base.css lists it
8
+ * beside .ld-bg). Nav state is two presence attributes on the root:
9
+ * data-ld-nav-collapsed (wide: icon rail) and data-ld-nav-open (narrow:
10
+ * drawer shown). The header always spans the full width above the nav, so
11
+ * its toggle and brand never move as the nav collapses or hides. Below 48rem
12
+ * the nav leaves the grid and becomes a drawer — or, with .ld-shell--tabbar,
13
+ * a bottom tab bar. 48rem is SHELL_NARROW_QUERY
14
+ * in the React package; keep the two in step.
15
+ */
16
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell {
17
+ --ld-shell-header-h: 3.5rem;
18
+ --ld-shell-nav-w: 15rem;
19
+ --ld-shell-rail-w: 4.25rem;
20
+ --ld-shell-top: 0px; /* sticky offset below the header, when there is one */
21
+ display: grid;
22
+ grid-template-columns: auto minmax(0, 1fr);
23
+ grid-template-rows: auto 1fr auto;
24
+ grid-template-areas:
25
+ "header header"
26
+ "nav main"
27
+ "nav footer";
28
+ min-block-size: 100dvh;
29
+ }
30
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell:has(> .ld-shell__header) {
31
+ --ld-shell-top: var(--ld-shell-header-h);
32
+ }
33
+
34
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__skip {
35
+ position: absolute;
36
+ inset-inline-start: var(--ld-space-2);
37
+ inset-block-start: -10rem;
38
+ z-index: 50;
39
+ }
40
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__skip:focus {
41
+ inset-block-start: var(--ld-space-2);
42
+ }
43
+
44
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__header {
45
+ grid-area: header;
46
+ position: sticky;
47
+ inset-block-start: 0;
48
+ z-index: 20;
49
+ display: flex;
50
+ align-items: center;
51
+ gap: var(--ld-space-3);
52
+ block-size: var(--ld-shell-header-h);
53
+ padding-inline: var(--ld-space-3);
54
+ min-inline-size: 0;
55
+ }
56
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__toggle {
57
+ flex: none;
58
+ display: inline-grid;
59
+ place-items: center;
60
+ inline-size: 2.25rem;
61
+ block-size: 2.25rem;
62
+ padding: 0;
63
+ cursor: pointer;
64
+ }
65
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__toggle svg {
66
+ inline-size: 1.25rem;
67
+ block-size: 1.25rem;
68
+ }
69
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell:not(:has(> .ld-shell__nav)) .ld-shell__toggle {
70
+ display: none;
71
+ }
72
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__brand {
73
+ flex: none;
74
+ display: inline-flex;
75
+ align-items: center;
76
+ gap: var(--ld-space-2);
77
+ text-decoration: none;
78
+ white-space: nowrap;
79
+ }
80
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__brand svg,
81
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__brand img {
82
+ inline-size: 1.75rem;
83
+ block-size: 1.75rem;
84
+ }
85
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-topnav {
86
+ display: flex;
87
+ align-items: center;
88
+ gap: var(--ld-space-1);
89
+ min-inline-size: 0;
90
+ overflow-x: auto;
91
+ scrollbar-width: none;
92
+ }
93
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-topnav__item {
94
+ flex: none;
95
+ white-space: nowrap;
96
+ text-decoration: none;
97
+ }
98
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__actions {
99
+ flex: none;
100
+ display: flex;
101
+ align-items: center;
102
+ gap: var(--ld-space-2);
103
+ margin-inline-start: auto;
104
+ }
105
+
106
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__nav {
107
+ grid-area: nav;
108
+ position: sticky;
109
+ inset-block-start: var(--ld-shell-top);
110
+ align-self: start;
111
+ z-index: 10;
112
+ inline-size: var(--ld-shell-nav-w);
113
+ block-size: calc(100dvh - var(--ld-shell-top));
114
+ overflow: hidden auto;
115
+ overscroll-behavior: contain;
116
+ transition: inline-size var(--ld-transition);
117
+ }
118
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__scrim {
119
+ display: none;
120
+ }
121
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__main {
122
+ grid-area: main;
123
+ display: flex;
124
+ flex-direction: column;
125
+ min-inline-size: 0;
126
+ padding: var(--ld-space-4) var(--ld-space-5);
127
+ }
128
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__main:focus {
129
+ outline: none; /* focus target of the skip link, not an interactive control */
130
+ }
131
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__footer {
132
+ grid-area: footer;
133
+ display: flex;
134
+ flex-wrap: wrap;
135
+ align-items: center;
136
+ justify-content: space-between;
137
+ gap: var(--ld-space-2) var(--ld-space-4);
138
+ padding: var(--ld-space-3) var(--ld-space-5);
139
+ }
140
+
141
+ /* Side nav: sections of icon + label items, an optional footer pinned low. */
142
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav {
143
+ display: flex;
144
+ flex-direction: column;
145
+ gap: var(--ld-space-3);
146
+ min-block-size: 100%;
147
+ padding: var(--ld-space-3) var(--ld-space-2);
148
+ }
149
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav__section {
150
+ display: flex;
151
+ flex-direction: column;
152
+ gap: 2px;
153
+ }
154
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav__heading {
155
+ margin: 0;
156
+ padding: var(--ld-space-1) var(--ld-space-3);
157
+ white-space: nowrap;
158
+ overflow: hidden;
159
+ }
160
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav__item {
161
+ display: flex;
162
+ align-items: center;
163
+ gap: var(--ld-space-3);
164
+ min-block-size: 2.5rem;
165
+ padding: var(--ld-space-2) var(--ld-space-3);
166
+ text-decoration: none;
167
+ white-space: nowrap;
168
+ }
169
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav__icon {
170
+ flex: none;
171
+ display: inline-grid;
172
+ place-items: center;
173
+ inline-size: 1.25rem;
174
+ block-size: 1.25rem;
175
+ }
176
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav__icon svg {
177
+ inline-size: 100%;
178
+ block-size: 100%;
179
+ }
180
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav__label {
181
+ flex: 1;
182
+ min-inline-size: 0;
183
+ overflow: hidden;
184
+ text-overflow: ellipsis;
185
+ }
186
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav__badge {
187
+ flex: none;
188
+ margin-inline-start: auto;
189
+ }
190
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav__footer {
191
+ display: flex;
192
+ flex-direction: column;
193
+ gap: 2px;
194
+ margin-block-start: auto;
195
+ }
196
+ /* A brand inside the nav (for shells without a header). */
197
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav > .ld-shell__brand {
198
+ padding: var(--ld-space-1) var(--ld-space-3) var(--ld-space-2);
199
+ }
200
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-sidenav__footer > .ld-shell__toggle {
201
+ margin-inline-start: var(--ld-space-2);
202
+ }
203
+
204
+ /* Wide: the collapsed nav is an icon rail. Labels, headings and badges stay
205
+ * in the accessibility tree, only visually clipped; headings become rules. */
206
+ @media (width > 48rem) {
207
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-collapsed] .ld-shell__nav {
208
+ inline-size: var(--ld-shell-rail-w);
209
+ }
210
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-collapsed] .ld-sidenav__item {
211
+ justify-content: center;
212
+ padding-inline: 0;
213
+ }
214
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-collapsed] :is(.ld-sidenav__label, .ld-sidenav__badge),
215
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-collapsed] .ld-sidenav__heading {
216
+ position: absolute;
217
+ inline-size: 1px;
218
+ block-size: 1px;
219
+ padding: 0;
220
+ overflow: hidden;
221
+ clip-path: inset(50%);
222
+ }
223
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-collapsed] .ld-sidenav > .ld-shell__brand {
224
+ justify-content: center;
225
+ padding-inline: 0;
226
+ }
227
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-collapsed] .ld-sidenav > .ld-shell__brand > :not(svg, img) {
228
+ display: none;
229
+ }
230
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-collapsed] .ld-sidenav__footer > .ld-shell__toggle {
231
+ margin-inline: auto;
232
+ }
233
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-collapsed] .ld-sidenav__section + .ld-sidenav__section {
234
+ border-block-start: 1px solid var(--ld-border);
235
+ padding-block-start: var(--ld-space-3);
236
+ }
237
+ }
238
+
239
+ /* Narrow: the nav leaves the grid. Default is an off-canvas drawer under the
240
+ * header (visibility keeps a closed drawer out of the tab order). */
241
+ @media (width <= 48rem) {
242
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell {
243
+ grid-template-columns: minmax(0, 1fr);
244
+ grid-template-areas:
245
+ "header"
246
+ "main"
247
+ "footer";
248
+ }
249
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__header {
250
+ padding-inline: var(--ld-space-2);
251
+ gap: var(--ld-space-2);
252
+ }
253
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__main {
254
+ padding: var(--ld-space-3);
255
+ }
256
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__footer {
257
+ padding: var(--ld-space-3);
258
+ }
259
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__nav {
260
+ position: fixed;
261
+ inset-block: var(--ld-shell-top) 0;
262
+ inset-inline-start: 0;
263
+ align-self: stretch; /* fixed boxes honour align-self; "start" would shrink-wrap the drawer */
264
+ z-index: 40;
265
+ inline-size: min(var(--ld-shell-nav-w) + 3rem, 85vw);
266
+ block-size: auto;
267
+ transform: translateX(-100%);
268
+ visibility: hidden;
269
+ transition: transform var(--ld-transition), visibility 0s linear var(--ld-transition);
270
+ }
271
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-open] .ld-shell__nav {
272
+ transform: none;
273
+ visibility: visible;
274
+ transition: transform var(--ld-transition);
275
+ }
276
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-open] .ld-shell__scrim {
277
+ display: block;
278
+ position: fixed;
279
+ inset: var(--ld-shell-top) 0 0;
280
+ z-index: 30;
281
+ }
282
+
283
+ /* Tab bar: the nav docks at the bottom; sections flatten into one row. */
284
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-shell__toggle {
285
+ display: none;
286
+ }
287
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-shell__nav {
288
+ inset-block: auto 0;
289
+ inset-inline: 0;
290
+ inline-size: auto;
291
+ transform: none;
292
+ visibility: visible;
293
+ overflow: visible;
294
+ padding-block-end: env(safe-area-inset-bottom, 0px);
295
+ transition: none;
296
+ }
297
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-shell__scrim {
298
+ display: none;
299
+ }
300
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-sidenav {
301
+ flex-direction: row;
302
+ gap: 0;
303
+ min-block-size: 0;
304
+ padding: var(--ld-space-1);
305
+ }
306
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar :is(.ld-sidenav__section, .ld-sidenav__footer) {
307
+ display: contents;
308
+ }
309
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-sidenav > .ld-shell__brand {
310
+ display: none;
311
+ }
312
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-sidenav__heading {
313
+ display: none;
314
+ }
315
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-sidenav__item {
316
+ position: relative;
317
+ flex: 1 1 0;
318
+ flex-direction: column;
319
+ justify-content: center;
320
+ gap: 2px;
321
+ min-inline-size: 0;
322
+ padding: var(--ld-space-1);
323
+ font-size: 0.6875rem;
324
+ }
325
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-sidenav__label {
326
+ flex: none;
327
+ max-inline-size: 100%;
328
+ }
329
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-sidenav__badge {
330
+ position: absolute;
331
+ inset-block-start: 0;
332
+ inset-inline-start: calc(50% + 0.5rem);
333
+ margin: 0;
334
+ }
335
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar .ld-shell__footer {
336
+ padding-block-end: calc(4.5rem + env(safe-area-inset-bottom, 0px));
337
+ }
338
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell--tabbar:not(:has(> .ld-shell__footer)) .ld-shell__main {
339
+ padding-block-end: calc(4.5rem + env(safe-area-inset-bottom, 0px));
340
+ }
341
+ }
342
+
343
+ @media (prefers-reduced-motion: reduce) {
344
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell__nav,
345
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-shell[data-ld-nav-open] .ld-shell__nav {
346
+ transition: none;
347
+ }
348
+ }
@@ -0,0 +1,85 @@
1
+ /* neon-butterfly — page layouts: what goes inside .ld-shell__main (or any
2
+ * container). Structure only, identical in every theme; shell.css dresses the
3
+ * page header's type. */
4
+ /* A page column: width-capped, centered, with a header row. */
5
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page {
6
+ display: grid;
7
+ align-content: start;
8
+ gap: var(--ld-space-4);
9
+ inline-size: 100%;
10
+ max-inline-size: var(--ld-page-max, 72rem);
11
+ margin-inline: auto;
12
+ }
13
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page--narrow { --ld-page-max: 48rem; }
14
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page--wide { --ld-page-max: 96rem; }
15
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page--full { --ld-page-max: none; }
16
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page__header {
17
+ display: flex;
18
+ flex-wrap: wrap;
19
+ align-items: flex-end;
20
+ justify-content: space-between;
21
+ gap: var(--ld-space-3);
22
+ }
23
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page__heading {
24
+ display: grid;
25
+ gap: var(--ld-space-1);
26
+ min-inline-size: 0;
27
+ }
28
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page__title,
29
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page__subtitle,
30
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page__eyebrow {
31
+ margin: 0;
32
+ }
33
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-page__actions {
34
+ display: flex;
35
+ flex-wrap: wrap;
36
+ gap: var(--ld-space-2);
37
+ }
38
+
39
+ /* Dashboard grid: as many columns of at least --ld-grid-min as fit. */
40
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-grid {
41
+ display: grid;
42
+ grid-template-columns: repeat(auto-fill, minmax(min(var(--ld-grid-min, 18rem), 100%), 1fr));
43
+ gap: var(--ld-space-3);
44
+ align-items: start;
45
+ }
46
+
47
+ /* List + detail, and content + aside: two panes that stack by themselves once
48
+ * the wide pane would drop below 60% of the row — no breakpoint, so they work
49
+ * at any shell width. */
50
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-split,
51
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-aside-layout {
52
+ display: flex;
53
+ flex-wrap: wrap;
54
+ align-items: flex-start;
55
+ gap: var(--ld-space-4);
56
+ }
57
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-split__list {
58
+ flex: 1 1 var(--ld-split-list, 20rem);
59
+ display: grid;
60
+ gap: var(--ld-space-2);
61
+ min-inline-size: 0;
62
+ }
63
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-split__detail,
64
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-aside-layout__main {
65
+ flex: 999 1 0;
66
+ min-inline-size: 60%;
67
+ }
68
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-aside-layout__aside {
69
+ flex: 1 1 var(--ld-aside-w, 16rem);
70
+ position: sticky;
71
+ inset-block-start: calc(var(--ld-shell-top, 0px) + var(--ld-space-3));
72
+ min-inline-size: 0;
73
+ }
74
+
75
+ /* Centered: one narrow column in the middle of the remaining height — sign
76
+ * in, empty states, a single form. Fills .ld-shell__main (a flex column). */
77
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-center {
78
+ flex: 1;
79
+ display: grid;
80
+ place-items: center;
81
+ min-block-size: 100%;
82
+ }
83
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-center > * {
84
+ inline-size: min(100%, var(--ld-center-max, 26rem));
85
+ }
@@ -11,3 +11,78 @@
11
11
  font-size: var(--ld-text-sm);
12
12
  overflow-x: auto;
13
13
  }
14
+
15
+ /* Log / terminal variant (.ld-pre--log): bounded, scrolls both ways, wraps
16
+ * long lines, and carries faint 4px scanlines. Height comes from
17
+ * --ld-log-max-height (the React LogBlock's maxHeight sets it inline). */
18
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre--log {
19
+ max-height: var(--ld-log-max-height, 420px);
20
+ overflow: auto;
21
+ line-height: 1.45;
22
+ white-space: pre-wrap;
23
+ overflow-wrap: anywhere;
24
+ background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0.02) 1px, transparent 1px);
25
+ background-size: 100% 4px;
26
+ }
27
+
28
+ /* Copy control (.ld-pre-wrap + .ld-pre-copy): an .ld-icon-btn pinned to the
29
+ * block's top-right corner. Hidden until the wrap is hovered or holds focus
30
+ * (so it stays keyboard-reachable), always shown where there's no hover
31
+ * (touch). The host script sets data-ld-copy="copied" | "failed" on the
32
+ * button for ~1.5s: copied swaps the copy glyph for the check. Status text for
33
+ * screen readers goes in the visually hidden aria-live .ld-pre-copy-status. */
34
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-wrap {
35
+ position: relative;
36
+ }
37
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-wrap > .ld-pre {
38
+ padding-right: calc(2rem + var(--ld-space-3));
39
+ }
40
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-copy {
41
+ position: absolute;
42
+ top: var(--ld-space-1);
43
+ right: var(--ld-space-1);
44
+ background: var(--ld-surface-sunken);
45
+ opacity: 0;
46
+ transition: opacity var(--ld-transition), color var(--ld-transition), box-shadow var(--ld-transition);
47
+ }
48
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-wrap:hover .ld-pre-copy,
49
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-wrap:focus-within .ld-pre-copy,
50
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-wrap .ld-pre-copy[data-ld-copy] {
51
+ opacity: 1;
52
+ }
53
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-wrap .ld-pre-copy[data-ld-copy="copied"] {
54
+ color: var(--ld-success);
55
+ }
56
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-wrap .ld-pre-copy[data-ld-copy="failed"] {
57
+ color: var(--ld-danger);
58
+ }
59
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-copy__check,
60
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-copy[data-ld-copy="copied"] .ld-pre-copy__icon {
61
+ display: none;
62
+ }
63
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-copy[data-ld-copy="copied"] .ld-pre-copy__check {
64
+ display: block;
65
+ }
66
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-copy-status {
67
+ position: absolute;
68
+ width: 1px;
69
+ height: 1px;
70
+ margin: -1px;
71
+ padding: 0;
72
+ overflow: hidden;
73
+ clip-path: inset(50%);
74
+ white-space: nowrap;
75
+ border: 0;
76
+ }
77
+
78
+ @media (hover: none) {
79
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-copy {
80
+ opacity: 1;
81
+ }
82
+ }
83
+
84
+ @media (prefers-reduced-motion: reduce) {
85
+ :where([data-ld-style="neon-butterfly"], [data-ld-style="neon-butterfly"] *).ld-pre-copy {
86
+ transition: none;
87
+ }
88
+ }