@bysages/core 0.0.0 → 0.1.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.
- package/dist/index.d.mts +10 -7
- package/dist/index.mjs +2689 -398
- package/package.json +6 -2
package/dist/index.mjs
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import tokensStyles from "@bysages/tokens/styles";
|
|
1
2
|
//#region src/theme.ts
|
|
2
3
|
/** Each scene pairs with a default accent — the pigment that carries its
|
|
3
4
|
* context (civic identity is zhusha, never an error color; tech stays
|
|
@@ -6,7 +7,12 @@ const SCENE_DEFAULT_ACCENT = {
|
|
|
6
7
|
civic: "zhusha",
|
|
7
8
|
enterprise: "qinghua",
|
|
8
9
|
studio: "celadon",
|
|
9
|
-
tech: "ink"
|
|
10
|
+
tech: "ink",
|
|
11
|
+
cupertino: "ink",
|
|
12
|
+
expressive: "zhusha",
|
|
13
|
+
fluent: "qinghua",
|
|
14
|
+
material: "celadon",
|
|
15
|
+
sketch: "zhusha"
|
|
10
16
|
};
|
|
11
17
|
/** Each scene also pairs with a contrast tier — civic serves elders, so it
|
|
12
18
|
* speaks at the loud tier by default. "auto" contrast resolves here;
|
|
@@ -15,7 +21,12 @@ const SCENE_DEFAULT_CONTRAST = {
|
|
|
15
21
|
civic: "high",
|
|
16
22
|
enterprise: "normal",
|
|
17
23
|
studio: "normal",
|
|
18
|
-
tech: "normal"
|
|
24
|
+
tech: "normal",
|
|
25
|
+
cupertino: "normal",
|
|
26
|
+
expressive: "normal",
|
|
27
|
+
fluent: "normal",
|
|
28
|
+
material: "normal",
|
|
29
|
+
sketch: "normal"
|
|
19
30
|
};
|
|
20
31
|
const STORAGE_KEY = "bs-theme";
|
|
21
32
|
const DARK_QUERY = "(prefers-color-scheme: dark)";
|
|
@@ -205,19 +216,25 @@ function detachDynamicLight() {
|
|
|
205
216
|
//#endregion
|
|
206
217
|
//#region src/ink-ripple.ts
|
|
207
218
|
/**
|
|
208
|
-
* Ink ripple — the press feedback of the paper-and-ink register
|
|
209
|
-
*
|
|
210
|
-
*
|
|
211
|
-
*
|
|
219
|
+
* Ink ripple — the press feedback of the paper-and-ink register: a wash of
|
|
220
|
+
* the element's own pigment bleeding outward from the press point. The
|
|
221
|
+
* bleed is two-phase, answering the hand rather than the click — it spreads
|
|
222
|
+
* while the pointer holds (`data-ripple="press"`) and dissolves when it
|
|
223
|
+
* lifts (`data-ripple="release"`). A scene retunes the wash through the
|
|
224
|
+
* `--bs-ripple-*` tokens; a register that presses without a wash silences
|
|
225
|
+
* it with a zero opacity.
|
|
212
226
|
*
|
|
213
227
|
* The bleed's CSS lives in the base stylesheet, keyed on
|
|
214
|
-
* `data-motion~="ink-ripple"`; this module watches
|
|
215
|
-
*
|
|
228
|
+
* `data-motion~="ink-ripple"`; this module watches pointers and marks the
|
|
229
|
+
* phase. Reduced motion collapses the bleed to a state change, as
|
|
216
230
|
* everywhere else in the system.
|
|
217
231
|
*
|
|
218
232
|
* @module
|
|
219
233
|
*/
|
|
220
234
|
const RIPPLE_SELECTOR = "[data-motion~='ink-ripple']";
|
|
235
|
+
/** A wash released before this long still plays out to here before it
|
|
236
|
+
* dissolves — a quick tap earns a visible wave, not a flicker. */
|
|
237
|
+
const MIN_PRESS_MS = 225;
|
|
221
238
|
let detachPress;
|
|
222
239
|
/** Watch for presses anywhere inside `root` (default: the document) and
|
|
223
240
|
* bleed ink from the press point of the nearest opt-in element. Safe to
|
|
@@ -225,9 +242,7 @@ let detachPress;
|
|
|
225
242
|
function attachInkRipple(root) {
|
|
226
243
|
detachInkRipple();
|
|
227
244
|
if (typeof document === "undefined") return () => {};
|
|
228
|
-
const
|
|
229
|
-
if (event.target instanceof HTMLElement) delete event.target.dataset.ripple;
|
|
230
|
-
};
|
|
245
|
+
const held = /* @__PURE__ */ new Map();
|
|
231
246
|
const onDown = (event) => {
|
|
232
247
|
if (!(event instanceof PointerEvent)) return;
|
|
233
248
|
if (event.pointerType !== "touch" && event.button !== 0) return;
|
|
@@ -236,18 +251,44 @@ function attachInkRipple(root) {
|
|
|
236
251
|
const host = target.closest(RIPPLE_SELECTOR);
|
|
237
252
|
if (!(host instanceof HTMLElement)) return;
|
|
238
253
|
const rect = host.getBoundingClientRect();
|
|
239
|
-
|
|
240
|
-
|
|
254
|
+
const px = event.clientX - rect.left;
|
|
255
|
+
const py = event.clientY - rect.top;
|
|
256
|
+
host.style.setProperty("--bs-ripple-x", `${px.toFixed(1)}px`);
|
|
257
|
+
host.style.setProperty("--bs-ripple-y", `${py.toFixed(1)}px`);
|
|
258
|
+
host.style.setProperty("--bs-ripple-dx", `${(rect.width / 2 - px).toFixed(1)}px`);
|
|
259
|
+
host.style.setProperty("--bs-ripple-dy", `${(rect.height / 2 - py).toFixed(1)}px`);
|
|
241
260
|
delete host.dataset.ripple;
|
|
242
261
|
host.offsetWidth;
|
|
243
|
-
host.dataset.ripple = "
|
|
262
|
+
host.dataset.ripple = "press";
|
|
263
|
+
held.set(event.pointerId, {
|
|
264
|
+
host,
|
|
265
|
+
at: performance.now()
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
const onUp = (event) => {
|
|
269
|
+
if (!(event instanceof PointerEvent)) return;
|
|
270
|
+
const press = held.get(event.pointerId);
|
|
271
|
+
if (!press) return;
|
|
272
|
+
held.delete(event.pointerId);
|
|
273
|
+
const remain = MIN_PRESS_MS - (performance.now() - press.at);
|
|
274
|
+
if (remain > 0) setTimeout(() => {
|
|
275
|
+
if (press.host.dataset.ripple === "press") press.host.dataset.ripple = "release";
|
|
276
|
+
}, remain);
|
|
277
|
+
else press.host.dataset.ripple = "release";
|
|
278
|
+
};
|
|
279
|
+
const onAnimationEnd = (event) => {
|
|
280
|
+
if (event.target instanceof HTMLElement && event.target.dataset.ripple === "release") delete event.target.dataset.ripple;
|
|
244
281
|
};
|
|
245
282
|
const scope = root ?? document;
|
|
246
283
|
scope.addEventListener("pointerdown", onDown, { passive: true });
|
|
247
|
-
scope.addEventListener("
|
|
284
|
+
scope.addEventListener("pointerup", onUp, { passive: true });
|
|
285
|
+
scope.addEventListener("pointercancel", onUp, { passive: true });
|
|
286
|
+
scope.addEventListener("animationend", onAnimationEnd, true);
|
|
248
287
|
detachPress = () => {
|
|
249
288
|
scope.removeEventListener("pointerdown", onDown);
|
|
250
|
-
scope.removeEventListener("
|
|
289
|
+
scope.removeEventListener("pointerup", onUp);
|
|
290
|
+
scope.removeEventListener("pointercancel", onUp);
|
|
291
|
+
scope.removeEventListener("animationend", onAnimationEnd, true);
|
|
251
292
|
};
|
|
252
293
|
return detachPress;
|
|
253
294
|
}
|
|
@@ -257,10 +298,6 @@ function detachInkRipple() {
|
|
|
257
298
|
detachPress = void 0;
|
|
258
299
|
}
|
|
259
300
|
//#endregion
|
|
260
|
-
//#region ../tokens/dist/js/styles.mjs
|
|
261
|
-
/** Stylesheet for the full token layer, generated from dist/css/index.css. */
|
|
262
|
-
var styles_default = "@layer bs.tokens;\n\n@layer bs.tokens {\n /**\n * Do not edit directly, this file was auto-generated.\n */\n\n :root, :host {\n --bs-color-gray-25: oklch(0.985 0.003 92);\n --bs-color-gray-50: oklch(0.968 0.005 90);\n --bs-color-gray-100: oklch(0.928 0.007 88);\n --bs-color-gray-200: oklch(0.872 0.009 86);\n --bs-color-gray-300: oklch(0.795 0.011 84);\n --bs-color-gray-400: oklch(0.665 0.013 82);\n --bs-color-gray-500: oklch(0.568 0.014 80);\n --bs-color-gray-600: oklch(0.482 0.014 78);\n --bs-color-gray-700: oklch(0.405 0.013 76);\n --bs-color-gray-800: oklch(0.318 0.011 76);\n --bs-color-gray-850: oklch(0.272 0.01 76);\n --bs-color-gray-900: oklch(0.23 0.009 76);\n --bs-color-gray-925: oklch(0.188 0.008 76);\n --bs-color-gray-950: oklch(0.15 0.007 76);\n --bs-color-gray-975: oklch(0.118 0.006 76);\n --bs-color-brand-50: oklch(0.962 0.014 255);\n --bs-color-brand-100: oklch(0.93 0.031 255);\n --bs-color-brand-200: oklch(0.885 0.056 255);\n --bs-color-brand-300: oklch(0.815 0.09 255);\n --bs-color-brand-400: oklch(0.72 0.122 255);\n --bs-color-brand-500: oklch(0.6 0.15 255);\n --bs-color-brand-600: oklch(0.53 0.155 255);\n --bs-color-brand-700: oklch(0.46 0.15 255);\n --bs-color-brand-800: oklch(0.395 0.13 255);\n --bs-color-brand-900: oklch(0.33 0.105 255);\n --bs-color-brand-950: oklch(0.26 0.08 255);\n --bs-color-celadon-50: oklch(0.962 0.014 205);\n --bs-color-celadon-100: oklch(0.928 0.028 205);\n --bs-color-celadon-200: oklch(0.88 0.05 205);\n --bs-color-celadon-300: oklch(0.81 0.072 205);\n --bs-color-celadon-400: oklch(0.715 0.082 205);\n --bs-color-celadon-500: oklch(0.63 0.085 205);\n --bs-color-celadon-600: oklch(0.56 0.085 205);\n --bs-color-celadon-700: oklch(0.485 0.08 205);\n --bs-color-celadon-800: oklch(0.41 0.068 205);\n --bs-color-celadon-900: oklch(0.34 0.054 205);\n --bs-color-celadon-950: oklch(0.265 0.04 205);\n --bs-color-zhusha-50: oklch(0.964 0.016 28);\n --bs-color-zhusha-100: oklch(0.926 0.036 28);\n --bs-color-zhusha-200: oklch(0.874 0.066 28);\n --bs-color-zhusha-300: oklch(0.806 0.098 28);\n --bs-color-zhusha-400: oklch(0.716 0.13 28);\n --bs-color-zhusha-500: oklch(0.625 0.15 28);\n --bs-color-zhusha-600: oklch(0.55 0.16 28);\n --bs-color-zhusha-700: oklch(0.472 0.148 28);\n --bs-color-zhusha-800: oklch(0.398 0.125 28);\n --bs-color-zhusha-900: oklch(0.328 0.098 28);\n --bs-color-zhusha-950: oklch(0.254 0.072 28);\n --bs-color-success-50: oklch(0.962 0.024 155);\n --bs-color-success-100: oklch(0.922 0.048 155);\n --bs-color-success-200: oklch(0.868 0.082 155);\n --bs-color-success-300: oklch(0.794 0.108 155);\n --bs-color-success-400: oklch(0.71 0.122 155);\n --bs-color-success-500: oklch(0.6 0.112 155);\n --bs-color-success-600: oklch(0.52 0.1 155);\n --bs-color-success-700: oklch(0.445 0.088 155);\n --bs-color-success-800: oklch(0.375 0.072 155);\n --bs-color-success-900: oklch(0.31 0.056 155);\n --bs-color-success-950: oklch(0.24 0.04 155);\n --bs-color-warning-50: oklch(0.968 0.028 78);\n --bs-color-warning-100: oklch(0.934 0.056 74);\n --bs-color-warning-200: oklch(0.892 0.086 70);\n --bs-color-warning-300: oklch(0.836 0.112 67);\n --bs-color-warning-400: oklch(0.76 0.126 66);\n --bs-color-warning-500: oklch(0.665 0.125 65);\n --bs-color-warning-600: oklch(0.55 0.122 65);\n --bs-color-warning-700: oklch(0.495 0.11 63);\n --bs-color-warning-800: oklch(0.415 0.092 62);\n --bs-color-warning-900: oklch(0.34 0.074 62);\n --bs-color-warning-950: oklch(0.262 0.054 62);\n --bs-color-danger-50: oklch(0.964 0.018 25);\n --bs-color-danger-100: oklch(0.924 0.04 25);\n --bs-color-danger-200: oklch(0.87 0.07 25);\n --bs-color-danger-300: oklch(0.798 0.106 25);\n --bs-color-danger-400: oklch(0.712 0.138 25);\n --bs-color-danger-500: oklch(0.6 0.15 25);\n --bs-color-danger-600: oklch(0.51 0.15 25);\n --bs-color-danger-700: oklch(0.44 0.135 25);\n --bs-color-danger-800: oklch(0.372 0.112 25);\n --bs-color-danger-900: oklch(0.306 0.088 25);\n --bs-color-danger-950: oklch(0.236 0.064 25);\n --bs-color-info-50: oklch(0.962 0.014 250);\n --bs-color-info-100: oklch(0.924 0.03 250);\n --bs-color-info-200: oklch(0.872 0.054 250);\n --bs-color-info-300: oklch(0.802 0.082 250);\n --bs-color-info-400: oklch(0.718 0.11 250);\n --bs-color-info-500: oklch(0.6 0.125 250);\n --bs-color-info-600: oklch(0.505 0.125 250);\n --bs-color-info-700: oklch(0.432 0.112 250);\n --bs-color-info-800: oklch(0.364 0.092 250);\n --bs-color-info-900: oklch(0.3 0.072 250);\n --bs-color-info-950: oklch(0.232 0.052 250);\n --bs-space-1: 0.25rem;\n --bs-space-2: 0.5rem;\n --bs-space-3: 0.75rem;\n --bs-space-4: 1rem;\n --bs-space-5: 1.25rem;\n --bs-space-6: 1.5rem;\n --bs-space-7: 1.75rem;\n --bs-space-8: 2rem;\n --bs-space-10: 2.5rem;\n --bs-space-12: 3rem;\n --bs-space-16: 4rem;\n --bs-space-20: 5rem;\n --bs-space-24: 6rem;\n --bs-radius-none: 0rem;\n --bs-radius-xs: 0.25rem;\n --bs-radius-sm: 0.375rem;\n --bs-radius-md: 0.5rem;\n --bs-radius-lg: 0.75rem;\n --bs-radius-xl: 1rem;\n --bs-radius-2xl: 1.5rem;\n --bs-radius-full: 9999px;\n }\n\n\n /* Light theme — light as shadow, the paper-and-ink register: hierarchy reads through\n the paper ladder (the ground sits in ambient shade, raised surfaces catch\n the light), hairline borders, and restrained cast shadows in warm ink.\n Controls stay crisp — a paper-white surface, one hairline, and shadow-xs.\n Primary defaults to ink so the interface stays monochrome and solemn; the\n pigment accents (qinghua, celadon, zhusha) live in accent.css. */\n\n :root,\n :host,\n [data-theme=\"light\"],\n :host([data-theme=\"light\"]) {\n color-scheme: light;\n\n /* Surfaces: the ground rests in ambient shade; raised surfaces catch the\n light. Warm paper whites throughout — pure #ffffff never appears, it\n would read clinical against the ink. */\n --bs-color-surface-0: var(--bs-color-gray-50);\n --bs-color-surface-1: var(--bs-color-gray-25);\n --bs-color-surface-2: oklch(0.988 0.004 95);\n --bs-color-surface-3: oklch(0.988 0.004 95);\n --bs-color-surface-4: oklch(0.988 0.004 95);\n --bs-color-surface-5: oklch(0.988 0.004 95);\n --bs-color-surface-inset: var(--bs-color-gray-100);\n /* The inverted surface — ink on paper — hosts floating labels like\n tooltips that must read against the page, never blend into it. */\n --bs-color-surface-inverse: var(--bs-color-gray-800);\n --bs-color-scrim: oklch(0.15 0.007 76 / 0.4);\n\n --bs-color-text-primary: var(--bs-color-gray-900);\n --bs-color-text-secondary: var(--bs-color-gray-600);\n --bs-color-text-tertiary: var(--bs-color-gray-500);\n --bs-color-text-disabled: var(--bs-color-gray-400);\n --bs-color-text-inverse: var(--bs-color-surface-2);\n /* Ink on a solid pigment fill: paper under daylight, kneaded bright\n under lacquer night (see the dark theme). */\n --bs-color-ink-on-fill: var(--bs-color-surface-2);\n --bs-ink-knead: 0%;\n\n --bs-color-border: var(--bs-color-gray-200);\n --bs-color-border-strong: var(--bs-color-gray-300);\n\n /* Focus is a halo of light: a crisp inner line inside a soft, wide glow.\n The inset variant serves parts flush against a container edge (steppers),\n where an outer halo would spill past it. */\n --bs-color-focus: var(--bs-color-primary);\n --bs-focus-ring-color: color-mix(in oklab, var(--bs-color-focus) 16%, transparent);\n --bs-focus-ring-width: 8px;\n --bs-focus-ring:\n 0 0 0 1px var(--bs-color-focus), 0 0 0 var(--bs-focus-ring-width) var(--bs-focus-ring-color);\n --bs-focus-ring-inset:\n inset 0 0 0 1px var(--bs-color-focus), inset 0 0 0 4px var(--bs-focus-ring-color);\n\n /* Primary is ink by default — solemn, unhurried, industry-neutral. The\n hover deepens the ink into the paper; the pigment accents override the\n whole block (see accent.css). */\n --bs-color-primary: var(--bs-color-gray-800);\n --bs-color-primary-hover: var(--bs-color-gray-900);\n --bs-color-primary-active: var(--bs-color-gray-925);\n --bs-color-primary-text: var(--bs-color-surface-2);\n /* The solid-fill body: pigments rest at full strength on paper — night\n kneads them (see the dark theme), daylight does not. */\n --bs-color-primary-fill: var(--bs-color-primary);\n --bs-color-primary-fill-hover: var(--bs-color-primary-hover);\n --bs-color-primary-subtle: var(--bs-color-gray-100);\n --bs-color-primary-subtle-text: var(--bs-color-gray-800);\n --bs-color-primary-border: var(--bs-color-gray-300);\n\n /* Fixed semantic pigments — bamboo, ochre, cinnabar, ultramarine. They do\n not follow the accent theme: an error is always cinnabar-red, a warning\n always ochre, whatever pigment the brand rides. */\n --bs-color-success: var(--bs-color-success-600);\n --bs-color-success-hover: var(--bs-color-success-700);\n --bs-color-success-subtle: var(--bs-color-success-100);\n --bs-color-success-subtle-text: var(--bs-color-success-800);\n\n --bs-color-warning: var(--bs-color-warning-600);\n --bs-color-warning-hover: var(--bs-color-warning-700);\n --bs-color-warning-subtle: var(--bs-color-warning-100);\n --bs-color-warning-subtle-text: var(--bs-color-warning-800);\n\n --bs-color-danger: var(--bs-color-danger-600);\n --bs-color-danger-hover: var(--bs-color-danger-700);\n --bs-color-danger-subtle: var(--bs-color-danger-100);\n --bs-color-danger-subtle-text: var(--bs-color-danger-800);\n\n --bs-color-info: var(--bs-color-info-600);\n --bs-color-info-hover: var(--bs-color-info-700);\n --bs-color-info-subtle: var(--bs-color-info-100);\n --bs-color-info-subtle-text: var(--bs-color-info-800);\n\n /* Lighting — elevation shadows are computed, never copy-pasted. Every\n shadow draws its ink from --bs-shadow-ink, this theme's warm shadow hue,\n shifts with --bs-light-x/-y (where the key light stands), and spreads\n with --bs-light-reach (how high the surface floats). Custom properties\n resolve their own var() references at the declaring element, so these\n composite tokens always carry theme ink; a colored surface that casts in\n its own color composes its shadow inline from these parts mixed with its\n tint — see the dialog trigger. Restraint ladder: controls carry only\n shadow-xs; cards rise on elevation-1/2; menus and popovers separate on\n elevation-3; dialogs own elevation-4/5. */\n --bs-shadow-ink: oklch(0.3 0.02 80);\n --bs-light-x: 0px;\n --bs-light-y: 0px;\n --bs-light-reach: 1;\n /* Weighted hairlines: the 1px edge everything rides, and the 3px\n status edge an alert earns. */\n --bs-hairline: 1px;\n --bs-hairline-strong: 3px;\n --bs-shadow-xs: var(--bs-light-x) calc(1px * var(--bs-light-reach) + var(--bs-light-y))\n calc(2px * var(--bs-light-reach)) 0 color-mix(in oklab, var(--bs-shadow-ink) 5%, transparent);\n --bs-elevation-0: none;\n --bs-elevation-1: var(--bs-light-x) calc(1px * var(--bs-light-reach) + var(--bs-light-y))\n calc(2px * var(--bs-light-reach)) 0 color-mix(in oklab, var(--bs-shadow-ink) 7%, transparent);\n --bs-elevation-2:\n var(--bs-light-x) calc(1px * var(--bs-light-reach) + var(--bs-light-y))\n calc(2px * var(--bs-light-reach)) 0 color-mix(in oklab, var(--bs-shadow-ink) 6%, transparent),\n var(--bs-light-x) calc(3px * var(--bs-light-reach) + var(--bs-light-y))\n calc(8px * var(--bs-light-reach)) calc(-2px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 9%, transparent);\n --bs-elevation-3:\n var(--bs-light-x) calc(2px * var(--bs-light-reach) + var(--bs-light-y))\n calc(4px * var(--bs-light-reach)) calc(-2px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 7%, transparent),\n var(--bs-light-x) calc(5px * var(--bs-light-reach) + var(--bs-light-y))\n calc(12px * var(--bs-light-reach)) calc(-3px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 10%, transparent),\n var(--bs-light-x) calc(12px * var(--bs-light-reach) + var(--bs-light-y))\n calc(24px * var(--bs-light-reach)) calc(-6px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 8%, transparent);\n --bs-elevation-4:\n var(--bs-light-x) calc(4px * var(--bs-light-reach) + var(--bs-light-y))\n calc(8px * var(--bs-light-reach)) calc(-4px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 8%, transparent),\n var(--bs-light-x) calc(10px * var(--bs-light-reach) + var(--bs-light-y))\n calc(28px * var(--bs-light-reach)) calc(-6px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 12%, transparent),\n var(--bs-light-x) calc(28px * var(--bs-light-reach) + var(--bs-light-y))\n calc(56px * var(--bs-light-reach)) calc(-12px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 12%, transparent);\n --bs-elevation-5:\n var(--bs-light-x) calc(6px * var(--bs-light-reach) + var(--bs-light-y))\n calc(12px * var(--bs-light-reach)) calc(-6px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 10%, transparent),\n var(--bs-light-x) calc(16px * var(--bs-light-reach) + var(--bs-light-y))\n calc(40px * var(--bs-light-reach)) calc(-8px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 14%, transparent),\n var(--bs-light-x) calc(40px * var(--bs-light-reach) + var(--bs-light-y))\n calc(80px * var(--bs-light-reach)) calc(-16px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 14%, transparent);\n }\n\n\n /* Dark theme — lacquer night: the room dims into warm lacquer black,\n and text turns to paper. Surfaces still brighten as they rise (e0 darkest\n → e5 lightest) — at night the ladder of light, not the cast shadow, does\n the separating. Primary inverts: paper-white buttons set ink on fire\n gently against the dark. */\n\n [data-theme=\"dark\"],\n :host([data-theme=\"dark\"]) {\n color-scheme: dark;\n\n /* Lacquer surfaces: warm black at every step, never pure #000. */\n --bs-color-surface-0: oklch(0.165 0.008 75);\n --bs-color-surface-1: oklch(0.205 0.009 75);\n --bs-color-surface-2: oklch(0.245 0.01 76);\n --bs-color-surface-3: oklch(0.272 0.01 76);\n --bs-color-surface-4: oklch(0.29 0.01 76);\n --bs-color-surface-5: oklch(0.31 0.01 76);\n --bs-color-surface-inset: oklch(0.135 0.007 75);\n /* The inverted surface — paper on lacquer — hosts floating labels like\n tooltips; at night the inversion reads as a slip of bright paper. */\n --bs-color-surface-inverse: var(--bs-color-gray-100);\n --bs-color-scrim: oklch(0.05 0.01 75 / 0.6);\n\n --bs-color-text-primary: oklch(0.925 0.006 90);\n --bs-color-text-secondary: var(--bs-color-gray-300);\n --bs-color-text-tertiary: var(--bs-color-gray-400);\n --bs-color-text-disabled: var(--bs-color-gray-500);\n --bs-color-text-inverse: var(--bs-color-gray-900);\n /* Ink on a solid pigment fill: pigments knead a fifth of ink into their\n bodies at night (a mid-tone fill carries neither deep nor pale text\n past 4.5:1), so the ink turns bright paper. */\n --bs-color-ink-on-fill: var(--bs-color-gray-25);\n --bs-ink-knead: 20%;\n\n --bs-color-border: oklch(0.31 0.01 78);\n --bs-color-border-strong: oklch(0.4 0.012 78);\n\n /* The halo reads brighter at night, like any light source does. */\n --bs-color-focus: var(--bs-color-primary);\n --bs-focus-ring-color: color-mix(in oklab, var(--bs-color-focus) 22%, transparent);\n --bs-focus-ring-width: 8px;\n --bs-focus-ring:\n 0 0 0 1px var(--bs-color-focus), 0 0 0 var(--bs-focus-ring-width) var(--bs-focus-ring-color);\n --bs-focus-ring-inset:\n inset 0 0 0 1px var(--bs-color-focus), inset 0 0 0 4px var(--bs-focus-ring-color);\n\n /* Primary inverts to paper — ink set down on lacquer. */\n --bs-color-primary: oklch(0.93 0.007 90);\n --bs-color-primary-hover: var(--bs-color-gray-200);\n --bs-color-primary-active: var(--bs-color-gray-300);\n --bs-color-primary-text: var(--bs-color-gray-900);\n --bs-color-primary-fill: var(--bs-color-primary);\n --bs-color-primary-fill-hover: var(--bs-color-primary-hover);\n --bs-color-primary-subtle: color-mix(in oklab, var(--bs-color-primary) 10%, transparent);\n --bs-color-primary-subtle-text: var(--bs-color-gray-200);\n --bs-color-primary-border: var(--bs-color-gray-700);\n\n /* Semantic pigments lift to their lighter steps at night; the fixed hue\n relationships (bamboo / ochre / cinnabar / ultramarine) never change. */\n --bs-color-success: var(--bs-color-success-500);\n --bs-color-success-hover: var(--bs-color-success-400);\n --bs-color-success-subtle: color-mix(in oklab, var(--bs-color-success) 16%, transparent);\n --bs-color-success-subtle-text: var(--bs-color-success-300);\n\n --bs-color-warning: var(--bs-color-warning-500);\n --bs-color-warning-hover: var(--bs-color-warning-400);\n --bs-color-warning-subtle: color-mix(in oklab, var(--bs-color-warning) 16%, transparent);\n --bs-color-warning-subtle-text: var(--bs-color-warning-300);\n\n --bs-color-danger: var(--bs-color-danger-500);\n --bs-color-danger-hover: var(--bs-color-danger-400);\n --bs-color-danger-subtle: color-mix(in oklab, var(--bs-color-danger) 16%, transparent);\n --bs-color-danger-subtle-text: var(--bs-color-danger-300);\n\n --bs-color-info: var(--bs-color-info-500);\n --bs-color-info-hover: var(--bs-color-info-400);\n --bs-color-info-subtle: color-mix(in oklab, var(--bs-color-info) 16%, transparent);\n --bs-color-info-subtle-text: var(--bs-color-info-300);\n\n /* Elevation in the dark: cast shadows need far more opacity to read against\n a dark ground, so every level carries a faint warm hairline of light to\n cut the raised surface out of the one below it. Same lighting parts as\n light — ink from --bs-shadow-ink, shifted by --bs-light-x/-y, spread by\n --bs-light-reach; colored surfaces compose their tint inline. */\n --bs-shadow-ink: oklch(0.04 0.01 75);\n --bs-light-x: 0px;\n --bs-light-y: 0px;\n --bs-light-reach: 1;\n --bs-hairline: 1px;\n --bs-hairline-strong: 3px;\n --bs-shadow-xs: var(--bs-light-x) calc(1px * var(--bs-light-reach) + var(--bs-light-y))\n calc(2px * var(--bs-light-reach)) 0 color-mix(in oklab, var(--bs-shadow-ink) 35%, transparent);\n --bs-elevation-0: none;\n --bs-elevation-1:\n 0 0 0 1px oklch(0.95 0.01 90 / 0.04),\n var(--bs-light-x) calc(1px * var(--bs-light-reach) + var(--bs-light-y))\n calc(2px * var(--bs-light-reach)) 0 color-mix(in oklab, var(--bs-shadow-ink) 32%, transparent);\n --bs-elevation-2:\n 0 0 0 1px oklch(0.95 0.01 90 / 0.05),\n var(--bs-light-x) calc(2px * var(--bs-light-reach) + var(--bs-light-y))\n calc(4px * var(--bs-light-reach)) calc(-1px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 40%, transparent),\n var(--bs-light-x) calc(4px * var(--bs-light-reach) + var(--bs-light-y))\n calc(12px * var(--bs-light-reach)) calc(-2px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 36%, transparent);\n --bs-elevation-3:\n 0 0 0 1px oklch(0.95 0.01 90 / 0.06),\n var(--bs-light-x) calc(4px * var(--bs-light-reach) + var(--bs-light-y))\n calc(8px * var(--bs-light-reach)) calc(-3px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 44%, transparent),\n var(--bs-light-x) calc(10px * var(--bs-light-reach) + var(--bs-light-y))\n calc(24px * var(--bs-light-reach)) calc(-4px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 40%, transparent);\n --bs-elevation-4:\n 0 0 0 1px oklch(0.95 0.01 90 / 0.07),\n var(--bs-light-x) calc(8px * var(--bs-light-reach) + var(--bs-light-y))\n calc(16px * var(--bs-light-reach)) calc(-6px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 48%, transparent),\n var(--bs-light-x) calc(24px * var(--bs-light-reach) + var(--bs-light-y))\n calc(48px * var(--bs-light-reach)) calc(-8px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 44%, transparent);\n --bs-elevation-5:\n 0 0 0 1px oklch(0.95 0.01 90 / 0.08),\n var(--bs-light-x) calc(12px * var(--bs-light-reach) + var(--bs-light-y))\n calc(24px * var(--bs-light-reach)) calc(-8px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 52%, transparent),\n var(--bs-light-x) calc(40px * var(--bs-light-reach) + var(--bs-light-y))\n calc(80px * var(--bs-light-reach)) calc(-12px * var(--bs-light-reach))\n color-mix(in oklab, var(--bs-shadow-ink) 48%, transparent);\n }\n\n\n /* Accent themes — the pigments. Primary is ink by default (theme-light/dark);\n switching [data-accent] lays a different mineral pigment under the same\n interface: qinghua (cobalt, the blue of blue-and-white porcelain), celadon\n (aquatic green-blue), zhusha (cinnabar, the seal-paste red used sparingly\n by civic sites for identity — never for errors; danger stays cinnabar-red\n by way of --bs-color-danger, a separate token). Each accent redefines the\n primary block and the focus hue; the fixed semantic pigments never follow. */\n\n [data-accent=\"qinghua\"] {\n --bs-color-primary: var(--bs-color-brand-600);\n --bs-color-primary-hover: var(--bs-color-brand-700);\n --bs-color-primary-active: var(--bs-color-brand-800);\n --bs-color-primary-text: oklch(0.988 0.004 95);\n --bs-color-primary-subtle: var(--bs-color-brand-100);\n --bs-color-primary-subtle-text: var(--bs-color-brand-800);\n --bs-color-primary-border: var(--bs-color-brand-300);\n --bs-color-focus: var(--bs-color-primary);\n }\n\n [data-theme=\"dark\"] [data-accent=\"qinghua\"],\n [data-theme=\"dark\"][data-accent=\"qinghua\"],\n :host([data-theme=\"dark\"][data-accent=\"qinghua\"]) {\n --bs-color-primary: var(--bs-color-brand-500);\n --bs-color-primary-hover: var(--bs-color-brand-600);\n --bs-color-primary-active: var(--bs-color-brand-700);\n /* A mid-tone pigment body carries neither deep nor pale text past\n 4.5:1, so the solid fill kneads toward black and reads with bright\n paper ink. */\n --bs-color-primary-fill: color-mix(in oklab, var(--bs-color-brand-500) 80%, black);\n --bs-color-primary-fill-hover: color-mix(in oklab, var(--bs-color-brand-500) 70%, black);\n --bs-color-primary-text: var(--bs-color-gray-25);\n --bs-color-primary-subtle: color-mix(in oklab, var(--bs-color-primary) 16%, transparent);\n --bs-color-primary-subtle-text: var(--bs-color-brand-300);\n --bs-color-primary-border: var(--bs-color-brand-700);\n }\n\n [data-accent=\"celadon\"] {\n --bs-color-primary: var(--bs-color-celadon-600);\n --bs-color-primary-hover: var(--bs-color-celadon-700);\n --bs-color-primary-active: var(--bs-color-celadon-800);\n --bs-color-primary-text: oklch(0.988 0.004 95);\n --bs-color-primary-subtle: var(--bs-color-celadon-100);\n --bs-color-primary-subtle-text: var(--bs-color-celadon-800);\n --bs-color-primary-border: var(--bs-color-celadon-300);\n --bs-color-focus: var(--bs-color-primary);\n }\n\n [data-theme=\"dark\"] [data-accent=\"celadon\"],\n [data-theme=\"dark\"][data-accent=\"celadon\"],\n :host([data-theme=\"dark\"][data-accent=\"celadon\"]) {\n --bs-color-primary: var(--bs-color-celadon-500);\n --bs-color-primary-hover: var(--bs-color-celadon-600);\n --bs-color-primary-active: var(--bs-color-celadon-700);\n /* A mid-tone pigment body carries neither deep nor pale text past\n 4.5:1, so the solid fill kneads toward black and reads with bright\n paper ink. */\n --bs-color-primary-fill: color-mix(in oklab, var(--bs-color-celadon-500) 80%, black);\n --bs-color-primary-fill-hover: color-mix(in oklab, var(--bs-color-celadon-500) 70%, black);\n --bs-color-primary-text: var(--bs-color-gray-25);\n --bs-color-primary-subtle: color-mix(in oklab, var(--bs-color-primary) 16%, transparent);\n --bs-color-primary-subtle-text: var(--bs-color-celadon-300);\n --bs-color-primary-border: var(--bs-color-celadon-700);\n }\n\n [data-accent=\"zhusha\"] {\n --bs-color-primary: var(--bs-color-zhusha-600);\n --bs-color-primary-hover: var(--bs-color-zhusha-700);\n --bs-color-primary-active: var(--bs-color-zhusha-800);\n --bs-color-primary-text: oklch(0.988 0.004 95);\n --bs-color-primary-subtle: var(--bs-color-zhusha-100);\n --bs-color-primary-subtle-text: var(--bs-color-zhusha-800);\n --bs-color-primary-border: var(--bs-color-zhusha-300);\n --bs-color-focus: var(--bs-color-primary);\n }\n\n [data-theme=\"dark\"] [data-accent=\"zhusha\"],\n [data-theme=\"dark\"][data-accent=\"zhusha\"],\n :host([data-theme=\"dark\"][data-accent=\"zhusha\"]) {\n --bs-color-primary: var(--bs-color-zhusha-500);\n --bs-color-primary-hover: var(--bs-color-zhusha-600);\n --bs-color-primary-active: var(--bs-color-zhusha-700);\n /* A mid-tone pigment body carries neither deep nor pale text past\n 4.5:1, so the solid fill kneads toward black and reads with bright\n paper ink. */\n --bs-color-primary-fill: color-mix(in oklab, var(--bs-color-zhusha-500) 80%, black);\n --bs-color-primary-fill-hover: color-mix(in oklab, var(--bs-color-zhusha-500) 70%, black);\n --bs-color-primary-text: var(--bs-color-gray-25);\n --bs-color-primary-subtle: color-mix(in oklab, var(--bs-color-primary) 16%, transparent);\n --bs-color-primary-subtle-text: var(--bs-color-zhusha-300);\n --bs-color-primary-border: var(--bs-color-zhusha-700);\n }\n\n\n /* Scene presets — one attribute that retunes the temperament of the whole\n interface for its audience: civic serves elders and civic desks (square\n seal-cut geometry, generous targets, loud contrast, an unhurried pace),\n tech serves modern efficiency products (sharp, dense, quick), enterprise\n is the quiet commercial baseline, studio the literati gathering for\n design and editorial work.\n\n A scene moves only what the paper allows: shape (radius), density, motion\n pace, where the key light stands, and how far it reaches — never\n interaction, never the semantic pigments. Each scene pairs with a default\n accent and (for civic) the high-contrast tier; those pairings are applied\n by the theme engine as plain data attributes, so the accent and contrast\n rules — including their dark variants — carry them unchanged.\n\n Explicit attributes always outrank the scene's bundled defaults: a\n `[data-accent]`, `[data-contrast]`, or `[data-density]` set alongside\n `[data-scene]` wins by cascade order. Note `:root` ties `[data-scene]` in\n specificity (both 0,1,0), so this file must sit after every stylesheet\n that declares these variables on `:root` (themes, primitives via accent's\n placement) and before density.css, whose explicit tiers must win over\n scene defaults. */\n\n [data-scene=\"civic\"] {\n /* 典章 — for elders and civic desks: the square-cut register of official\n documents. Corners go true square (a seal is not round), targets grow\n to the spacious ladder (48px controls), the pace slows so states are\n never missed, and the light stays flat so nothing hides in a shadow. */\n --bs-radius-sm: 0rem;\n --bs-radius-md: 0.125rem;\n --bs-radius-lg: 0.25rem;\n --bs-radius-xl: 0.375rem;\n --bs-radius-2xl: 0.5rem;\n --bs-control-height-sm: 2.25rem;\n --bs-control-height-md: 2.625rem;\n --bs-control-height-lg: 3rem;\n --bs-density-scale: 1.5;\n --bs-motion-scale: 1.25;\n --bs-light-x: 0px;\n --bs-light-y: 0px;\n --bs-light-reach: 0.7;\n }\n\n [data-scene=\"enterprise\"] {\n /* 信笺 — the measured commercial baseline: default geometry at a calmer\n light, so long working sessions read quiet and the hairlines do the\n talking. */\n --bs-density-scale: 1;\n --bs-motion-scale: 1;\n --bs-light-x: 0px;\n --bs-light-y: 0px;\n --bs-light-reach: 0.85;\n }\n\n [data-scene=\"studio\"] {\n /* 雅集 — the literati gathering for design and editorial work: controls\n keep the 6px seal edge, vessels round out generously, whitespace\n breathes, and the light comes from the upper left, casting each\n element's shadow gently toward the lower right. */\n --bs-radius-md: 0.625rem;\n --bs-radius-lg: 0.875rem;\n --bs-radius-xl: 1.25rem;\n --bs-radius-2xl: 1.75rem;\n --bs-control-height-sm: 2rem;\n --bs-control-height-md: 2.25rem;\n --bs-control-height-lg: 2.75rem;\n --bs-density-scale: 1.25;\n --bs-motion-scale: 1;\n --bs-light-x: 0.125rem;\n --bs-light-y: 0.125rem;\n --bs-light-reach: 1.25;\n }\n\n [data-scene=\"tech\"] {\n /* 司南 — the modern precision instrument: near-square corners, dense\n rows, a snappy pace, and a flat restrained light where hairlines carry\n all the hierarchy. */\n --bs-radius-sm: 0.125rem;\n --bs-radius-md: 0.25rem;\n --bs-radius-lg: 0.5rem;\n --bs-radius-xl: 0.75rem;\n --bs-radius-2xl: 1rem;\n --bs-control-height-sm: 1.5rem;\n --bs-control-height-md: 1.75rem;\n --bs-control-height-lg: 2rem;\n --bs-density-scale: 0.75;\n --bs-motion-scale: 0.85;\n --bs-light-x: 0px;\n --bs-light-y: 0px;\n --bs-light-reach: 0.5;\n }\n\n\n /* Density — decoration compresses, information never does: density scales whitespace and decoration\n only. Type sizes and contrast stay fixed so compact can never trade away\n readability. Control heights ride the density directly — a compact\n workbench and an elder-friendly spacious screen are different products,\n not the same one nudged by two pixels. */\n\n /* The default scale sits behind :where() so a scene preset (an attribute,\n same 0,1,0 as :root) can override it by cascade order, while the explicit\n [data-density] tiers below still outrank scenes that come before them. */\n :where(:root),\n :where(:host) {\n --bs-density-scale: 1;\n }\n\n :root,\n :host {\n /* Interior control parts (thumbs, knobs, check boxes, close buttons) are\n decoration riding a control, not the control itself: they scale with\n density and keep no readable floor, so a compact density actually\n makes them smaller. */\n --bs-part-size-sm: calc(1rem * var(--bs-density-scale));\n --bs-part-size-md: calc(1.25rem * var(--bs-density-scale));\n --bs-part-size-lg: calc(1.75rem * var(--bs-density-scale));\n\n /* Density-scaled whitespace. */\n --bs-padding-xs: calc(var(--bs-space-1) * var(--bs-density-scale));\n --bs-padding-sm: calc(var(--bs-space-2) * var(--bs-density-scale));\n --bs-padding-md: calc(var(--bs-space-3) * var(--bs-density-scale));\n --bs-padding-lg: calc(var(--bs-space-4) * var(--bs-density-scale));\n --bs-padding-xl: calc(var(--bs-space-6) * var(--bs-density-scale));\n --bs-gap-xs: calc(var(--bs-space-1) * var(--bs-density-scale));\n --bs-gap-sm: calc(var(--bs-space-2) * var(--bs-density-scale));\n --bs-gap-md: calc(var(--bs-space-3) * var(--bs-density-scale));\n --bs-gap-lg: calc(var(--bs-space-5) * var(--bs-density-scale));\n --bs-gap-xl: calc(var(--bs-space-8) * var(--bs-density-scale));\n }\n\n /* Control heights per tier — the cross-system ladders (28/32/40 sits at\n default; compact matches the Fiori/Ant workbench register; spacious\n reaches the 48px targets elderly-vision research asks for). The base\n tier sits behind :where() like the scale above, so a scene's bundled\n ladder overrides it by cascade order while the explicit [data-density]\n tiers below still outrank both. */\n :where(:root),\n :where(:host) {\n --bs-control-height-sm: 1.75rem;\n --bs-control-height-md: 2rem;\n --bs-control-height-lg: 2.5rem;\n }\n\n [data-density=\"compact\"],\n :host([data-density=\"compact\"]) {\n --bs-density-scale: 0.75;\n --bs-control-height-sm: 1.5rem;\n --bs-control-height-md: 1.75rem;\n --bs-control-height-lg: 2rem;\n }\n\n [data-density=\"comfortable\"],\n :host([data-density=\"comfortable\"]) {\n --bs-density-scale: 1.25;\n --bs-control-height-sm: 2rem;\n --bs-control-height-md: 2.25rem;\n --bs-control-height-lg: 2.75rem;\n }\n\n [data-density=\"spacious\"],\n :host([data-density=\"spacious\"]) {\n --bs-density-scale: 1.5;\n --bs-control-height-sm: 2.25rem;\n --bs-control-height-md: 2.625rem;\n --bs-control-height-lg: 3rem;\n }\n\n\n /* Contrast tier — softness comes from light and shadow, never from low contrast: the aesthetic softens through\n light, never through gray-on-gray. The high tier pulls secondary text and\n borders up to primary strength and widens the focus halo; it exists so\n older and low-vision users get the same design, just louder. Surface\n steps stay untouched — rows signal hover by one step of shade, and\n flattening the ladder would silence every hover in the system. */\n\n [data-contrast=\"high\"],\n :host([data-contrast=\"high\"]) {\n --bs-color-text-secondary: var(--bs-color-text-primary);\n --bs-color-text-tertiary: var(--bs-color-text-secondary);\n --bs-color-border: var(--bs-color-border-strong);\n --bs-focus-ring-color: color-mix(in oklab, var(--bs-color-focus) 30%, transparent);\n }\n\n [data-theme=\"light\"][data-contrast=\"high\"],\n :host([data-theme=\"light\"][data-contrast=\"high\"]) {\n --bs-color-border-strong: var(--bs-color-gray-400);\n }\n\n [data-theme=\"dark\"][data-contrast=\"high\"],\n :host([data-theme=\"dark\"][data-contrast=\"high\"]) {\n --bs-color-border-strong: var(--bs-color-gray-500);\n }\n\n\n /* Typography — two tracks: the voice and the chrome. The voice is the song\n stack (upright, structured strokes — Noto Serif SC falling back through the\n platform faces); headings and editorial narrative ride it, the way Western\n systems let a serif carry voice. The chrome is the modern hei stack — MiSans\n and HarmonyOS Sans lead, falling back into PingFang / YaHei so mixed CJK-Latin lines stay\n on one rhythm. Sizes are fixed rem values outside the density scale; compact\n UI may choose --bs-font-size-sm but never below it. */\n\n :root,\n :host {\n --bs-font-sans:\n MiSans, \"HarmonyOS Sans SC\", \"PingFang SC\", \"Microsoft YaHei\", system-ui, -apple-system,\n \"Segoe UI\", Roboto, \"Noto Sans CJK SC\", sans-serif;\n --bs-font-serif:\n \"Noto Serif SC\", \"Source Han Serif SC\", \"Songti SC\", SimSun, \"Times New Roman\", Georgia, serif;\n --bs-font-mono:\n ui-monospace, \"Cascadia Code\", \"JetBrains Mono\", Consolas, \"PingFang SC\", \"Microsoft YaHei\",\n monospace;\n\n --bs-font-size-xs: 0.75rem;\n --bs-font-size-sm: 0.8125rem;\n --bs-font-size-md: 0.875rem;\n --bs-font-size-base: 0.9375rem;\n --bs-font-size-lg: 1.0625rem;\n --bs-font-size-xl: 1.25rem;\n --bs-font-size-2xl: 1.5rem;\n --bs-font-size-3xl: 1.875rem;\n --bs-font-size-4xl: 2.25rem;\n\n --bs-line-height-tight: 1.25;\n --bs-line-height-snug: 1.375;\n --bs-line-height-normal: 1.5;\n --bs-line-height-relaxed: 1.625;\n\n /* Control labels carry a whisper of tracking — upright and unhurried is a\n property of CJK typesetting, not of any single typeface. */\n --bs-tracking-label: 0.02em;\n\n --bs-font-weight-regular: 400;\n --bs-font-weight-medium: 500;\n --bs-font-weight-semibold: 600;\n --bs-font-weight-bold: 700;\n }\n\n\n /* Motion — the ink-and-light grammar. Three rules and a floor:\n Light needs time — shadows transition about 1.5x slower than the property\n that raised them, so a shadow reads as cast light, not a sticker.\n Ink bleeds — surfaces enter by fading AND dissolving (blur to sharp),\n never popping. Puppets have strings — moving parts overshoot on the spring\n curve, and lists follow one another with a small stagger.\n Tokens drive all transitions; the reduced-motion block retunes them instead\n of removing states, so opacity still communicates elevation changes. */\n\n :root,\n :host {\n /* Durations ride --bs-motion-scale so a scene preset can tune the pace\n (a snappier instrument, an unhurried civic register) without touching\n the reduced-motion floor below, which declares 1ms directly. */\n --bs-duration-instant: calc(80ms * var(--bs-motion-scale, 1));\n --bs-duration-fast: calc(140ms * var(--bs-motion-scale, 1));\n --bs-duration-base: calc(200ms * var(--bs-motion-scale, 1));\n --bs-duration-slow: calc(320ms * var(--bs-motion-scale, 1));\n\n --bs-ease-out: cubic-bezier(0.16, 1, 0.3, 1);\n --bs-ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);\n --bs-ease-in: cubic-bezier(0.7, 0, 0.84, 0);\n --bs-ease-spring: cubic-bezier(0.34, 1.3, 0.5, 1);\n\n /* Stagger step for lists and menus — each follower comes up 24ms after\n the one before it, like puppets lifted in sequence. */\n --bs-stagger-step: 24ms;\n }\n\n /* Surfaces dissolve in like ink settling into paper: a fade, a soft focus\n pulling sharp, and a one-percent settle. Panels and menus apply it on\n their open state; exits stay plain opacity fades — faster, unobtrusive. */\n @keyframes bs-ink-in {\n from {\n opacity: 0;\n filter: blur(3px);\n scale: 1.01;\n }\n to {\n opacity: 1;\n filter: blur(0);\n scale: 1;\n }\n }\n\n /* Followers rise into place on the string — a short lift with the spring\n curve. Combine with per-item `animation-delay: calc(var(--bs-i) * var(--bs-stagger-step))`. */\n @keyframes bs-item-in {\n from {\n opacity: 0;\n translate: 0 4px;\n }\n to {\n opacity: 1;\n translate: 0 0;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n :root,\n :host {\n --bs-duration-instant: 1ms;\n --bs-duration-fast: 1ms;\n --bs-duration-base: 1ms;\n --bs-duration-slow: 1ms;\n --bs-stagger-step: 0ms;\n }\n }\n\n\n /* Overlay stacking — one shared base for every dismissible layer (dialog,\n popover, menu, select, …), ordered by zag's --layer-index offset so any\n nesting combination stacks correctly. Per-component bases are forbidden. */\n :root,\n :host {\n --bs-z-overlay: 1000;\n }\n}\n";
|
|
263
|
-
//#endregion
|
|
264
301
|
//#region src/styles/base.ts
|
|
265
302
|
/** Document-level guard rules. The machines drive visibility with the
|
|
266
303
|
* `hidden` attribute (select/combobox item indicators), which any author
|
|
@@ -269,6 +306,21 @@ const baseCss = `
|
|
|
269
306
|
[hidden] {
|
|
270
307
|
display: none !important;
|
|
271
308
|
}
|
|
309
|
+
|
|
310
|
+
/* The field baseline: containers that hold text or choices fill their
|
|
311
|
+
container — width is the layout's decision, never the component's.
|
|
312
|
+
Zero specificity (:where), so a family's own declaration always wins
|
|
313
|
+
without a fight; intrinsic controls (buttons, chips, markers) are
|
|
314
|
+
simply not on the list. */
|
|
315
|
+
:where([data-scope="select"], [data-scope="combobox"], [data-scope="listbox"],
|
|
316
|
+
[data-scope="cascade-select"], [data-scope="tree-select"],
|
|
317
|
+
[data-scope="number-input"], [data-scope="password-input"],
|
|
318
|
+
[data-scope="date-input"], [data-scope="date-picker"],
|
|
319
|
+
[data-scope="color-picker"], [data-scope="tags-input"],
|
|
320
|
+
[data-scope="fieldset"], [data-scope="file-upload"],
|
|
321
|
+
[data-scope="signature-pad"])[data-part="root"] {
|
|
322
|
+
inline-size: 100%;
|
|
323
|
+
}
|
|
272
324
|
`;
|
|
273
325
|
/** Press feedback that rides the motion attribute, not any one component —
|
|
274
326
|
* anything with `data-motion~="ink-ripple"` bleeds from its press point. */
|
|
@@ -291,38 +343,60 @@ const inkRippleCss = `
|
|
|
291
343
|
border-radius: 100%;
|
|
292
344
|
background: radial-gradient(
|
|
293
345
|
circle closest-side,
|
|
294
|
-
var(--
|
|
295
|
-
transparent 80%
|
|
346
|
+
var(--bs-ripple-pigment) var(--bs-ripple-core, 0%),
|
|
347
|
+
transparent var(--bs-ripple-fade, 80%)
|
|
296
348
|
);
|
|
297
349
|
scale: 0;
|
|
298
350
|
opacity: 0;
|
|
299
351
|
pointer-events: none;
|
|
300
352
|
}
|
|
301
353
|
|
|
302
|
-
[data-motion~="ink-ripple"][data-ripple="
|
|
303
|
-
animation: bs-
|
|
354
|
+
[data-motion~="ink-ripple"][data-ripple="press"]::after {
|
|
355
|
+
animation: bs-ripple-press var(--bs-ripple-duration, calc(650ms * var(--bs-motion-scale, 1)))
|
|
356
|
+
var(--bs-ripple-ease, var(--bs-ease-out)) forwards;
|
|
304
357
|
}
|
|
305
358
|
|
|
306
|
-
/*
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
359
|
+
/* On release the press phase keeps running to full cover — re-declaring
|
|
360
|
+
the same-name animation carries it over instead of restarting — while
|
|
361
|
+
the dissolve fades on top of it. */
|
|
362
|
+
[data-motion~="ink-ripple"][data-ripple="release"]::after {
|
|
363
|
+
animation: bs-ripple-press var(--bs-ripple-duration, calc(650ms * var(--bs-motion-scale, 1)))
|
|
364
|
+
var(--bs-ripple-ease, var(--bs-ease-out)) forwards,
|
|
365
|
+
bs-ripple-fade var(--bs-ripple-release, calc(320ms * var(--bs-motion-scale, 1))) ease-out
|
|
366
|
+
forwards;
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/* Ink wells up from the fingertip: the wash starts small at the press
|
|
370
|
+
point and grows while drifting toward the element's center (--bs-ripple-dx/dy,
|
|
371
|
+
set by the press watcher), staying at full strength while the pointer
|
|
372
|
+
holds — the paper is wet until the hand lifts. Peak opacity rides
|
|
373
|
+
--bs-ripple-opacity so a scene can quiet the wash or silence it
|
|
374
|
+
entirely; --bs-ripple-spread caps how far it reaches. */
|
|
375
|
+
@keyframes bs-ripple-press {
|
|
376
|
+
from {
|
|
377
|
+
translate: -50% -50%;
|
|
378
|
+
scale: 0.2;
|
|
379
|
+
opacity: var(--bs-ripple-opacity, 0.9);
|
|
313
380
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
381
|
+
to {
|
|
382
|
+
translate: calc(-50% + var(--bs-ripple-dx, 0px)) calc(-50% + var(--bs-ripple-dy, 0px));
|
|
383
|
+
scale: var(--bs-ripple-spread, 1);
|
|
384
|
+
opacity: var(--bs-ripple-opacity, 0.9);
|
|
317
385
|
}
|
|
318
|
-
|
|
319
|
-
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
@keyframes bs-ripple-fade {
|
|
389
|
+
from {
|
|
390
|
+
opacity: var(--bs-ripple-opacity, 0.9);
|
|
391
|
+
}
|
|
392
|
+
to {
|
|
320
393
|
opacity: 0;
|
|
321
394
|
}
|
|
322
395
|
}
|
|
323
396
|
|
|
324
397
|
@media (prefers-reduced-motion: reduce) {
|
|
325
|
-
[data-motion~="ink-ripple"][data-ripple="
|
|
398
|
+
[data-motion~="ink-ripple"][data-ripple="press"]::after,
|
|
399
|
+
[data-motion~="ink-ripple"][data-ripple="release"]::after {
|
|
326
400
|
animation-duration: 1ms;
|
|
327
401
|
}
|
|
328
402
|
}
|
|
@@ -352,6 +426,7 @@ const accordionCss = `
|
|
|
352
426
|
/* Triggers are quiet rows on the paper — no chrome of their own; the
|
|
353
427
|
hairline rule carries the structure instead. */
|
|
354
428
|
[data-scope="accordion"][data-part="item-trigger"] {
|
|
429
|
+
box-sizing: border-box;
|
|
355
430
|
display: flex;
|
|
356
431
|
align-items: center;
|
|
357
432
|
justify-content: space-between;
|
|
@@ -474,6 +549,15 @@ const accordionCss = `
|
|
|
474
549
|
}
|
|
475
550
|
`;
|
|
476
551
|
//#endregion
|
|
552
|
+
//#region src/styles/components/affix.ts
|
|
553
|
+
const affixCss = `
|
|
554
|
+
/* The nail draws nothing of its own: it is one sticky instruction on a
|
|
555
|
+
carrier the caller sizes and surfaces. */
|
|
556
|
+
[data-scope="affix"][data-part="root"] {
|
|
557
|
+
position: sticky;
|
|
558
|
+
}
|
|
559
|
+
`;
|
|
560
|
+
//#endregion
|
|
477
561
|
//#region src/styles/components/ai.ts
|
|
478
562
|
const aiCss = `
|
|
479
563
|
/* The conversation column: messages stack with section-band air, the
|
|
@@ -505,7 +589,11 @@ const aiCss = `
|
|
|
505
589
|
border-radius: var(--bs-radius-lg);
|
|
506
590
|
background: var(--bs-color-surface-1);
|
|
507
591
|
inline-size: fit-content;
|
|
508
|
-
|
|
592
|
+
/* A fixed ceiling, not a percentage: the percentage feeds the
|
|
593
|
+
fit-content resolution a reference it cannot satisfy (the parent's
|
|
594
|
+
own width is being fit-content from this very box), and short
|
|
595
|
+
messages then collapse toward min-content — one glyph per line. */
|
|
596
|
+
max-inline-size: 30rem;
|
|
509
597
|
}
|
|
510
598
|
|
|
511
599
|
/* Markdown response: the ink is set with relaxed leading, code rides
|
|
@@ -751,6 +839,78 @@ const aiCss = `
|
|
|
751
839
|
text-decoration-color: var(--bs-color-border-strong);
|
|
752
840
|
}
|
|
753
841
|
|
|
842
|
+
/* Attachments: the files riding the prompt's header — paper chips on
|
|
843
|
+
the recessed vessel, square-cut like every control. Uploading is a
|
|
844
|
+
dashed ghost, error speaks in danger ink; no chip casts a shadow. */
|
|
845
|
+
[data-scope="ai"][data-part="attachments"] {
|
|
846
|
+
display: flex;
|
|
847
|
+
flex-wrap: wrap;
|
|
848
|
+
gap: var(--bs-space-1);
|
|
849
|
+
}
|
|
850
|
+
|
|
851
|
+
[data-scope="ai"][data-part="attachment"] {
|
|
852
|
+
display: inline-flex;
|
|
853
|
+
align-items: center;
|
|
854
|
+
gap: var(--bs-space-1);
|
|
855
|
+
max-inline-size: 100%;
|
|
856
|
+
padding-block: calc(var(--bs-space-1) / 2);
|
|
857
|
+
padding-inline: var(--bs-space-2);
|
|
858
|
+
border: 1px solid var(--bs-color-border);
|
|
859
|
+
border-radius: var(--bs-radius-sm);
|
|
860
|
+
background: var(--bs-color-surface);
|
|
861
|
+
color: var(--bs-color-text-secondary);
|
|
862
|
+
font-size: var(--bs-font-size-sm);
|
|
863
|
+
transition: border-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
[data-scope="ai"][data-part="attachment"]:hover {
|
|
867
|
+
border-color: var(--bs-color-border-strong);
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
[data-scope="ai"][data-part="attachment"] svg {
|
|
871
|
+
inline-size: 0.875rem;
|
|
872
|
+
block-size: 0.875rem;
|
|
873
|
+
flex: none;
|
|
874
|
+
color: var(--bs-color-text-tertiary);
|
|
875
|
+
}
|
|
876
|
+
|
|
877
|
+
[data-scope="ai"][data-part="attachment"][data-status="uploading"] {
|
|
878
|
+
border-style: dashed;
|
|
879
|
+
color: var(--bs-color-text-tertiary);
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
[data-scope="ai"][data-part="attachment"][data-status="error"] {
|
|
883
|
+
border-color: var(--bs-color-danger);
|
|
884
|
+
color: var(--bs-color-danger);
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
[data-scope="ai"][data-part="attachment"] > span {
|
|
888
|
+
overflow: hidden;
|
|
889
|
+
text-overflow: ellipsis;
|
|
890
|
+
white-space: nowrap;
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
[data-scope="ai"][data-part="attachment"] [data-remove] {
|
|
894
|
+
display: inline-flex;
|
|
895
|
+
align-items: center;
|
|
896
|
+
flex: none;
|
|
897
|
+
padding: 0;
|
|
898
|
+
border: none;
|
|
899
|
+
background: none;
|
|
900
|
+
color: inherit;
|
|
901
|
+
cursor: pointer;
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
[data-scope="ai"][data-part="attachment"] [data-remove]:hover {
|
|
905
|
+
color: var(--bs-color-text-primary);
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
[data-scope="ai"][data-part="attachment"] [data-remove]:focus-visible {
|
|
909
|
+
outline: none;
|
|
910
|
+
border-radius: var(--bs-radius-sm);
|
|
911
|
+
box-shadow: var(--bs-focus-ring);
|
|
912
|
+
}
|
|
913
|
+
|
|
754
914
|
/* Actions row: a quiet line of shared ghost buttons. */
|
|
755
915
|
[data-scope="ai"][data-part="actions"] {
|
|
756
916
|
display: flex;
|
|
@@ -761,10 +921,13 @@ const aiCss = `
|
|
|
761
921
|
/* The prompt: one vessel — the shared field bared to the paper and
|
|
762
922
|
self-growing on the machine's autoresize. It starts a single line tall,
|
|
763
923
|
the submit seal riding that line; as the text grows the seal settles
|
|
764
|
-
onto the last line. The
|
|
924
|
+
onto the last line. The rows above and below (attachments, the model
|
|
925
|
+
and its switches) are slots — absent when empty, so the bare vessel
|
|
926
|
+
stays one quiet line. The halo answers the vessel, not the control. */
|
|
765
927
|
[data-scope="ai"][data-part="prompt"] {
|
|
766
928
|
display: flex;
|
|
767
|
-
|
|
929
|
+
flex-direction: column;
|
|
930
|
+
align-items: stretch;
|
|
768
931
|
gap: var(--bs-space-2);
|
|
769
932
|
padding: var(--bs-space-2);
|
|
770
933
|
border: 1px solid var(--bs-color-border);
|
|
@@ -780,6 +943,30 @@ const aiCss = `
|
|
|
780
943
|
box-shadow: var(--bs-focus-ring);
|
|
781
944
|
}
|
|
782
945
|
|
|
946
|
+
/* The writing row: the field between its optional shoulders, the seal
|
|
947
|
+
and the tools riding the text's last line. */
|
|
948
|
+
[data-scope="ai"][data-part="prompt-main"] {
|
|
949
|
+
display: flex;
|
|
950
|
+
align-items: flex-end;
|
|
951
|
+
gap: var(--bs-space-2);
|
|
952
|
+
min-inline-size: 0;
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
[data-scope="ai"][data-part="prompt-header"] {
|
|
956
|
+
display: flex;
|
|
957
|
+
flex-wrap: wrap;
|
|
958
|
+
align-items: center;
|
|
959
|
+
gap: var(--bs-space-1);
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
[data-scope="ai"][data-part="prompt-leading"],
|
|
963
|
+
[data-scope="ai"][data-part="prompt-trailing"] {
|
|
964
|
+
display: flex;
|
|
965
|
+
align-items: flex-end;
|
|
966
|
+
gap: var(--bs-space-1);
|
|
967
|
+
flex: none;
|
|
968
|
+
}
|
|
969
|
+
|
|
783
970
|
[data-scope="ai"][data-part="prompt"] [data-scope="field"][data-part="root"] {
|
|
784
971
|
flex: 1;
|
|
785
972
|
min-inline-size: 0;
|
|
@@ -808,10 +995,31 @@ const aiCss = `
|
|
|
808
995
|
resize: none;
|
|
809
996
|
}
|
|
810
997
|
|
|
998
|
+
/* The tool row beneath the writing: the model and its switches — the
|
|
999
|
+
seal closes the row at its far end. */
|
|
811
1000
|
[data-scope="ai"][data-part="prompt-footer"] {
|
|
1001
|
+
display: flex;
|
|
1002
|
+
flex-wrap: wrap;
|
|
1003
|
+
align-items: center;
|
|
1004
|
+
gap: var(--bs-space-1);
|
|
1005
|
+
flex: none;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
/* The send-side group: it drifts to the row's far end and keeps the
|
|
1009
|
+
model picker and the seal shoulder to shoulder. */
|
|
1010
|
+
[data-scope="ai"][data-part="prompt-end"] {
|
|
812
1011
|
display: flex;
|
|
813
1012
|
align-items: center;
|
|
1013
|
+
gap: var(--bs-space-2);
|
|
814
1014
|
flex: none;
|
|
1015
|
+
margin-inline-start: auto;
|
|
1016
|
+
}
|
|
1017
|
+
|
|
1018
|
+
/* The tool row holds fixed-width chrome: a field family dropped in
|
|
1019
|
+
here keeps its natural width, not the form-field full-bleed
|
|
1020
|
+
baseline. */
|
|
1021
|
+
[data-scope="ai"][data-part="prompt-footer"] [data-part="root"] {
|
|
1022
|
+
inline-size: auto;
|
|
815
1023
|
}
|
|
816
1024
|
|
|
817
1025
|
[data-scope="ai"][data-part="prompt"] [data-scope="field"][data-part="textarea"]:focus,
|
|
@@ -1161,6 +1369,25 @@ const angleSliderCss = labelCss("angle-slider") + `
|
|
|
1161
1369
|
}
|
|
1162
1370
|
`;
|
|
1163
1371
|
//#endregion
|
|
1372
|
+
//#region src/styles/components/aspect-ratio.ts
|
|
1373
|
+
const aspectRatioCss = `
|
|
1374
|
+
/* The frame that keeps its shape: the box holds the ratio the wrapper
|
|
1375
|
+
hands over, whatever width it is dealt. */
|
|
1376
|
+
[data-scope="aspect-ratio"][data-part="root"] {
|
|
1377
|
+
position: relative;
|
|
1378
|
+
inline-size: 100%;
|
|
1379
|
+
aspect-ratio: var(--bs-aspect-ratio, 1 / 1);
|
|
1380
|
+
}
|
|
1381
|
+
|
|
1382
|
+
/* The child owns the frame's face: it fills the box the ratio draws. */
|
|
1383
|
+
[data-scope="aspect-ratio"][data-part="root"] > * {
|
|
1384
|
+
position: absolute;
|
|
1385
|
+
inset: 0;
|
|
1386
|
+
inline-size: 100%;
|
|
1387
|
+
block-size: 100%;
|
|
1388
|
+
}
|
|
1389
|
+
`;
|
|
1390
|
+
//#endregion
|
|
1164
1391
|
//#region src/styles/components/avatar.ts
|
|
1165
1392
|
const avatarCss = `
|
|
1166
1393
|
[data-scope="avatar"][data-part="root"] {
|
|
@@ -1175,7 +1402,7 @@ const avatarCss = `
|
|
|
1175
1402
|
justify-content: center;
|
|
1176
1403
|
inline-size: var(--bs-avatar-size);
|
|
1177
1404
|
block-size: var(--bs-avatar-size);
|
|
1178
|
-
border-radius:
|
|
1405
|
+
border-radius: var(--bs-radius-full);
|
|
1179
1406
|
background: var(--bs-color-surface-inset);
|
|
1180
1407
|
color: var(--bs-color-text-secondary);
|
|
1181
1408
|
font-size: calc(var(--bs-font-size-sm) * 1.125);
|
|
@@ -1225,6 +1452,57 @@ const avatarGroupCss = `
|
|
|
1225
1452
|
}
|
|
1226
1453
|
`;
|
|
1227
1454
|
//#endregion
|
|
1455
|
+
//#region src/styles/components/back-top.ts
|
|
1456
|
+
const backTopCss = `
|
|
1457
|
+
/* A way-home control: a small floating tile at the page's corner. The
|
|
1458
|
+
paper, hairline and halo are the button's; this family owns the
|
|
1459
|
+
mooring and the entrance. It floats, so it casts — one rung of
|
|
1460
|
+
elevation, recomposed from the lighting parts. */
|
|
1461
|
+
[data-scope="back-top"][data-part="root"] {
|
|
1462
|
+
position: fixed;
|
|
1463
|
+
inset-inline-end: var(--bs-space-6);
|
|
1464
|
+
inset-block-end: var(--bs-space-6);
|
|
1465
|
+
z-index: var(--bs-z-overlay);
|
|
1466
|
+
transition:
|
|
1467
|
+
opacity var(--bs-duration-base) var(--bs-ease-out),
|
|
1468
|
+
translate var(--bs-duration-base) var(--bs-ease-spring);
|
|
1469
|
+
}
|
|
1470
|
+
|
|
1471
|
+
/* Hidden sinks below the page and steps out of the reading order —
|
|
1472
|
+
states remain, animation does not. */
|
|
1473
|
+
[data-scope="back-top"][data-part="root"][data-state="hidden"] {
|
|
1474
|
+
opacity: 0;
|
|
1475
|
+
translate: 0 var(--bs-space-2);
|
|
1476
|
+
visibility: hidden;
|
|
1477
|
+
pointer-events: none;
|
|
1478
|
+
}
|
|
1479
|
+
|
|
1480
|
+
/* The floating tile rises a rung; hovering lifts one more on the same
|
|
1481
|
+
slow shadow clock the lighting engine keeps. */
|
|
1482
|
+
[data-scope="back-top"][data-part="root"][data-state="shown"] [data-scope="button"][data-part="root"],
|
|
1483
|
+
[data-scope="back-top"][data-part="root"][data-state="shown"]:hover [data-scope="button"][data-part="root"] {
|
|
1484
|
+
--bs-shadow-color: color-mix(in oklab, var(--bs-shadow-ink) 30%, transparent);
|
|
1485
|
+
box-shadow: var(--bs-elevation-2);
|
|
1486
|
+
transition: box-shadow 220ms var(--bs-ease-out);
|
|
1487
|
+
}
|
|
1488
|
+
|
|
1489
|
+
[data-scope="back-top"][data-part="root"][data-state="shown"]:hover [data-scope="button"][data-part="root"] {
|
|
1490
|
+
box-shadow: var(--bs-elevation-3);
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
[data-scope="back-top"][data-part="root"][data-state="shown"]:active [data-scope="button"][data-part="root"] {
|
|
1494
|
+
box-shadow: none;
|
|
1495
|
+
}
|
|
1496
|
+
|
|
1497
|
+
/* The return trip rides the page's own scroll container, offered only
|
|
1498
|
+
while the reader allows motion. */
|
|
1499
|
+
@media (prefers-reduced-motion: no-preference) {
|
|
1500
|
+
html:has([data-scope="back-top"][data-part="root"][data-state="shown"]) {
|
|
1501
|
+
scroll-behavior: smooth;
|
|
1502
|
+
}
|
|
1503
|
+
}
|
|
1504
|
+
`;
|
|
1505
|
+
//#endregion
|
|
1228
1506
|
//#region src/styles/components/badge.ts
|
|
1229
1507
|
const badgeCss = `
|
|
1230
1508
|
/* A small seal of state: flat pigment fill, tracked caps-height ink. The
|
|
@@ -1480,7 +1758,7 @@ const buttonCss = `
|
|
|
1480
1758
|
the pigment it carries. Each variant declares its fill/ink defaults,
|
|
1481
1759
|
semantic tones re-point the pigment, and hover/focus ride the same
|
|
1482
1760
|
variables. Ink is the solemn default. */
|
|
1483
|
-
[data-scope="button"][data-part="root"] {
|
|
1761
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant]) {
|
|
1484
1762
|
--_pigment: var(--bs-color-primary);
|
|
1485
1763
|
/* The deep register of the pigment for the subtle wash — the 600-step
|
|
1486
1764
|
tone itself fails 4.5:1 on its own wash, so washed fills read from
|
|
@@ -1490,6 +1768,10 @@ const buttonCss = `
|
|
|
1490
1768
|
--_fill-hover: transparent;
|
|
1491
1769
|
--_ink: var(--bs-color-text-secondary);
|
|
1492
1770
|
--_edge: transparent;
|
|
1771
|
+
}
|
|
1772
|
+
|
|
1773
|
+
/* The recipe's own body: the layout and states of the button proper. */
|
|
1774
|
+
[data-scope="button"][data-part="root"] {
|
|
1493
1775
|
display: inline-flex;
|
|
1494
1776
|
align-items: center;
|
|
1495
1777
|
justify-content: center;
|
|
@@ -1501,7 +1783,7 @@ const buttonCss = `
|
|
|
1501
1783
|
systems use 15-16px at this height, 24px at large). */
|
|
1502
1784
|
padding: 0 var(--bs-padding-lg);
|
|
1503
1785
|
border: 1px solid var(--_edge);
|
|
1504
|
-
border-radius: var(--bs-radius-sm);
|
|
1786
|
+
border-radius: var(--bs-radius-control, var(--bs-radius-sm));
|
|
1505
1787
|
background: var(--_fill);
|
|
1506
1788
|
color: var(--_ink);
|
|
1507
1789
|
font: inherit;
|
|
@@ -1553,19 +1835,19 @@ const buttonCss = `
|
|
|
1553
1835
|
block-size: 1rem;
|
|
1554
1836
|
}
|
|
1555
1837
|
|
|
1556
|
-
[data-scope="button"][data-part="root"][data-tone="danger"] {
|
|
1838
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-tone="danger"] {
|
|
1557
1839
|
--_pigment: var(--bs-color-danger);
|
|
1558
1840
|
--_ink-strong: var(--bs-color-danger-subtle-text);
|
|
1559
1841
|
}
|
|
1560
|
-
[data-scope="button"][data-part="root"][data-tone="success"] {
|
|
1842
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-tone="success"] {
|
|
1561
1843
|
--_pigment: var(--bs-color-success);
|
|
1562
1844
|
--_ink-strong: var(--bs-color-success-subtle-text);
|
|
1563
1845
|
}
|
|
1564
|
-
[data-scope="button"][data-part="root"][data-tone="warning"] {
|
|
1846
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-tone="warning"] {
|
|
1565
1847
|
--_pigment: var(--bs-color-warning);
|
|
1566
1848
|
--_ink-strong: var(--bs-color-warning-subtle-text);
|
|
1567
1849
|
}
|
|
1568
|
-
[data-scope="button"][data-part="root"][data-tone="info"] {
|
|
1850
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-tone="info"] {
|
|
1569
1851
|
--_pigment: var(--bs-color-info);
|
|
1570
1852
|
--_ink-strong: var(--bs-color-info-subtle-text);
|
|
1571
1853
|
}
|
|
@@ -1573,7 +1855,7 @@ const buttonCss = `
|
|
|
1573
1855
|
/* Solid: the flat pigment fill, no lit edge at rest. On hover the ink
|
|
1574
1856
|
bleeds — the pigment casts a small shadow of its own color, on a slower
|
|
1575
1857
|
transition than the fill (light needs time). */
|
|
1576
|
-
[data-scope="button"][data-part="root"][data-variant="solid"] {
|
|
1858
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="solid"] {
|
|
1577
1859
|
/* The solid body follows --bs-color-primary-fill: full pigment on
|
|
1578
1860
|
paper, kneaded toward black at night, and the theme keeps the ink
|
|
1579
1861
|
on it legible in both registers. */
|
|
@@ -1581,63 +1863,64 @@ const buttonCss = `
|
|
|
1581
1863
|
--_fill-hover: var(--bs-color-primary-fill-hover);
|
|
1582
1864
|
--_ink: var(--bs-color-primary-text);
|
|
1583
1865
|
/* On a filled body the wash must read against the fill, not sink into
|
|
1584
|
-
it — the ink that blooms on a fill is the fill's own ink
|
|
1585
|
-
|
|
1866
|
+
it — the ink that blooms on a fill is the fill's own ink (opaque; the
|
|
1867
|
+
wash's concentration lives in --bs-ripple-opacity alone). */
|
|
1868
|
+
--bs-ripple-pigment: var(--_ink);
|
|
1586
1869
|
box-shadow: none;
|
|
1587
1870
|
}
|
|
1588
1871
|
|
|
1589
1872
|
/* The fixed pigments knead by the theme's measure — a mid-tone body at
|
|
1590
1873
|
night carries neither deep nor pale text past 4.5:1, so its ink turns
|
|
1591
1874
|
bright paper. */
|
|
1592
|
-
[data-scope="button"][data-part="root"][data-variant="solid"][data-tone="danger"] {
|
|
1875
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="solid"][data-tone="danger"] {
|
|
1593
1876
|
--_fill: color-mix(in oklab, var(--_pigment) calc(100% - var(--bs-ink-knead, 0%)), black);
|
|
1594
1877
|
--_fill-hover: color-mix(in oklab, var(--_pigment) calc(85% - var(--bs-ink-knead, 0%)), black);
|
|
1595
1878
|
--_ink: var(--bs-color-ink-on-fill);
|
|
1596
1879
|
}
|
|
1597
|
-
[data-scope="button"][data-part="root"][data-variant="solid"][data-tone="success"] {
|
|
1880
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="solid"][data-tone="success"] {
|
|
1598
1881
|
--_fill: color-mix(in oklab, var(--_pigment) calc(100% - var(--bs-ink-knead, 0%)), black);
|
|
1599
1882
|
--_fill-hover: color-mix(in oklab, var(--_pigment) calc(85% - var(--bs-ink-knead, 0%)), black);
|
|
1600
1883
|
--_ink: var(--bs-color-ink-on-fill);
|
|
1601
1884
|
}
|
|
1602
|
-
[data-scope="button"][data-part="root"][data-variant="solid"][data-tone="warning"] {
|
|
1885
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="solid"][data-tone="warning"] {
|
|
1603
1886
|
--_fill: color-mix(in oklab, var(--_pigment) calc(100% - var(--bs-ink-knead, 0%)), black);
|
|
1604
1887
|
--_fill-hover: color-mix(in oklab, var(--_pigment) calc(85% - var(--bs-ink-knead, 0%)), black);
|
|
1605
1888
|
--_ink: var(--bs-color-ink-on-fill);
|
|
1606
1889
|
}
|
|
1607
|
-
[data-scope="button"][data-part="root"][data-variant="solid"][data-tone="info"] {
|
|
1890
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="solid"][data-tone="info"] {
|
|
1608
1891
|
--_fill: color-mix(in oklab, var(--_pigment) calc(100% - var(--bs-ink-knead, 0%)), black);
|
|
1609
1892
|
--_fill-hover: color-mix(in oklab, var(--_pigment) calc(85% - var(--bs-ink-knead, 0%)), black);
|
|
1610
1893
|
--_ink: var(--bs-color-ink-on-fill);
|
|
1611
1894
|
}
|
|
1612
1895
|
|
|
1613
|
-
[data-scope="button"][data-part="root"][data-variant="solid"]:hover:not(:disabled) {
|
|
1896
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="solid"]:hover:not(:disabled) {
|
|
1614
1897
|
box-shadow: var(--bs-light-x) calc(1px * var(--bs-light-reach) + var(--bs-light-y))
|
|
1615
1898
|
calc(3px * var(--bs-light-reach)) 0 color-mix(in oklab, var(--_pigment) 28%, transparent);
|
|
1616
1899
|
}
|
|
1617
1900
|
|
|
1618
1901
|
/* Outline: paper on a hairline, the hairline deepening on hover. */
|
|
1619
|
-
[data-scope="button"][data-part="root"][data-variant="outline"] {
|
|
1902
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="outline"] {
|
|
1620
1903
|
--_fill: var(--bs-color-surface-2);
|
|
1621
1904
|
--_ink: var(--bs-color-text-primary);
|
|
1622
1905
|
--_edge: var(--bs-color-border);
|
|
1623
1906
|
}
|
|
1624
1907
|
|
|
1625
1908
|
/* Ghost: bare ink that borrows the subtle surface under the cursor. */
|
|
1626
|
-
[data-scope="button"][data-part="root"][data-variant="ghost"] {
|
|
1909
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="ghost"] {
|
|
1627
1910
|
--_fill-hover: var(--bs-color-surface-0);
|
|
1628
1911
|
box-shadow: none;
|
|
1629
1912
|
}
|
|
1630
1913
|
|
|
1631
1914
|
/* Subtle: a wash of the pigment with its deep register on top. */
|
|
1632
|
-
[data-scope="button"][data-part="root"][data-variant="subtle"] {
|
|
1915
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="subtle"] {
|
|
1633
1916
|
--_fill: color-mix(in oklab, var(--_pigment) 12%, transparent);
|
|
1634
1917
|
--_fill-hover: color-mix(in oklab, var(--_pigment) 20%, transparent);
|
|
1635
1918
|
--_ink: var(--_ink-strong);
|
|
1636
1919
|
box-shadow: none;
|
|
1637
1920
|
}
|
|
1638
1921
|
|
|
1639
|
-
[data-scope="button"][data-part="root"][data-variant="outline"]:hover:not(:disabled),
|
|
1640
|
-
[data-scope="button"][data-part="root"][data-variant="outline"]:focus-visible {
|
|
1922
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="outline"]:hover:not(:disabled),
|
|
1923
|
+
:is([data-scope="button"][data-part="root"], [data-scope][data-part="trigger"][data-variant])[data-variant="outline"]:focus-visible {
|
|
1641
1924
|
--_edge: var(--bs-color-border-strong);
|
|
1642
1925
|
}
|
|
1643
1926
|
|
|
@@ -1664,67 +1947,178 @@ const buttonCss = `
|
|
|
1664
1947
|
box-shadow: none;
|
|
1665
1948
|
}
|
|
1666
1949
|
|
|
1667
|
-
/* As-child hosting: an overlay trigger that hosts a Button overwrites
|
|
1668
|
-
button's anatomy (data-scope reads the overlay family, not
|
|
1669
|
-
so the rules
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1950
|
+
/* As-child hosting: an overlay trigger that hosts a Button overwrites
|
|
1951
|
+
the button's anatomy (data-scope reads the overlay family, not
|
|
1952
|
+
"button"), so the body rules never match. The variant, tone and size
|
|
1953
|
+
seals survive, though — and the variable rules above match them
|
|
1954
|
+
through the bare [data-scope], so this layout block only has to ride
|
|
1955
|
+
the same variables. The bare [data-scope] keeps specificity above any
|
|
1956
|
+
family's base, and the state branches above its open/focus/disabled
|
|
1957
|
+
rules. */
|
|
1958
|
+
[data-scope][data-part="trigger"][data-variant] {
|
|
1674
1959
|
display: inline-flex;
|
|
1675
1960
|
align-items: center;
|
|
1676
1961
|
justify-content: center;
|
|
1677
1962
|
gap: var(--bs-space-2);
|
|
1678
1963
|
flex: none;
|
|
1679
|
-
block-size: var(--bs-control-height-
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
border
|
|
1683
|
-
|
|
1684
|
-
|
|
1964
|
+
block-size: var(--bs-control-height-md);
|
|
1965
|
+
/* One step wider than the shell register, like the body above. */
|
|
1966
|
+
padding: 0 var(--bs-padding-lg);
|
|
1967
|
+
border: 1px solid var(--_edge);
|
|
1968
|
+
border-radius: var(--bs-radius-control, var(--bs-radius-sm));
|
|
1969
|
+
background: var(--_fill);
|
|
1970
|
+
color: var(--_ink);
|
|
1685
1971
|
font: inherit;
|
|
1686
|
-
font-size: var(--bs-font-size-
|
|
1972
|
+
font-size: var(--bs-font-size-md);
|
|
1687
1973
|
font-weight: var(--bs-font-weight-medium);
|
|
1688
1974
|
letter-spacing: var(--bs-tracking-label);
|
|
1689
1975
|
white-space: nowrap;
|
|
1690
1976
|
text-decoration: none;
|
|
1691
1977
|
cursor: pointer;
|
|
1692
1978
|
user-select: none;
|
|
1693
|
-
box-shadow:
|
|
1979
|
+
box-shadow: var(--bs-shadow-xs);
|
|
1694
1980
|
transition:
|
|
1695
1981
|
background-color var(--bs-duration-fast) var(--bs-ease-out),
|
|
1982
|
+
border-color var(--bs-duration-fast) var(--bs-ease-out),
|
|
1696
1983
|
color var(--bs-duration-fast) var(--bs-ease-out),
|
|
1697
1984
|
box-shadow calc(var(--bs-duration-fast) * 1.5) var(--bs-ease-out);
|
|
1698
1985
|
}
|
|
1699
1986
|
|
|
1987
|
+
[data-scope][data-part="trigger"][data-variant][data-size="sm"] {
|
|
1988
|
+
block-size: var(--bs-control-height-sm);
|
|
1989
|
+
padding: 0 var(--bs-padding-md);
|
|
1990
|
+
font-size: var(--bs-font-size-sm);
|
|
1991
|
+
}
|
|
1992
|
+
|
|
1993
|
+
[data-scope][data-part="trigger"][data-variant][data-size="lg"] {
|
|
1994
|
+
block-size: var(--bs-control-height-lg);
|
|
1995
|
+
padding: 0 var(--bs-padding-xl);
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1700
1998
|
/* Icon-only: the silhouette is the seal — width equals height. */
|
|
1701
|
-
[data-scope][data-part="trigger"][data-variant
|
|
1999
|
+
[data-scope][data-part="trigger"][data-variant][data-square="true"] {
|
|
1702
2000
|
inline-size: var(--bs-control-height-sm);
|
|
1703
2001
|
padding-inline: 0;
|
|
1704
2002
|
}
|
|
1705
2003
|
|
|
1706
|
-
[data-scope][data-part="trigger"][data-variant="
|
|
1707
|
-
|
|
2004
|
+
[data-scope][data-part="trigger"][data-variant][data-size="md"][data-square="true"] {
|
|
2005
|
+
inline-size: var(--bs-control-height-md);
|
|
2006
|
+
}
|
|
2007
|
+
|
|
2008
|
+
[data-scope][data-part="trigger"][data-variant][data-size="lg"][data-square="true"] {
|
|
2009
|
+
inline-size: var(--bs-control-height-lg);
|
|
2010
|
+
}
|
|
2011
|
+
|
|
2012
|
+
[data-scope][data-part="trigger"][data-variant]:hover:not(:disabled) {
|
|
2013
|
+
background: var(--_fill-hover);
|
|
1708
2014
|
}
|
|
1709
2015
|
|
|
1710
2016
|
/* Open keeps the focus look: Zag hands focus to the overlay itself, so
|
|
1711
2017
|
:focus-visible alone would drop the halo the moment it opens. */
|
|
1712
|
-
[data-scope][data-part="trigger"][data-variant
|
|
1713
|
-
[data-scope][data-part="trigger"][data-variant
|
|
2018
|
+
[data-scope][data-part="trigger"][data-variant]:focus-visible,
|
|
2019
|
+
[data-scope][data-part="trigger"][data-variant][data-state="open"] {
|
|
1714
2020
|
outline: none;
|
|
2021
|
+
border-color: var(--bs-color-primary);
|
|
1715
2022
|
box-shadow: var(--bs-focus-ring);
|
|
1716
2023
|
}
|
|
1717
2024
|
|
|
1718
|
-
[data-scope][data-part="trigger"][data-variant
|
|
2025
|
+
[data-scope][data-part="trigger"][data-variant]:active:not(:disabled) {
|
|
1719
2026
|
box-shadow: none;
|
|
1720
2027
|
}
|
|
1721
2028
|
|
|
1722
|
-
[data-scope][data-part="trigger"][data-variant
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
2029
|
+
[data-scope][data-part="trigger"][data-variant]:disabled,
|
|
2030
|
+
[data-scope][data-part="trigger"][data-variant][data-disabled] {
|
|
2031
|
+
--_fill: var(--bs-color-surface-inset);
|
|
2032
|
+
--_fill-hover: var(--bs-color-surface-inset);
|
|
2033
|
+
--_ink: var(--bs-color-text-disabled);
|
|
2034
|
+
--_edge: transparent;
|
|
1726
2035
|
cursor: not-allowed;
|
|
2036
|
+
box-shadow: none;
|
|
2037
|
+
}
|
|
2038
|
+
`;
|
|
2039
|
+
//#endregion
|
|
2040
|
+
//#region src/styles/components/button-group.ts
|
|
2041
|
+
const buttonGroupCss = `
|
|
2042
|
+
/* Buttons fused into one control: the group owns only the joinery. Corners
|
|
2043
|
+
trim where the members meet, a shared hairline merges through a 1px
|
|
2044
|
+
overlap, and the hovered or focused member steps above the pile so its
|
|
2045
|
+
deepened edge and halo are not painted over by the neighbor. Selection
|
|
2046
|
+
is not this family's business — each button keeps the variant it was
|
|
2047
|
+
given, solid beside outline beside ghost. */
|
|
2048
|
+
[data-scope="button-group"][data-part="root"] {
|
|
2049
|
+
display: inline-flex;
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
[data-scope="button-group"][data-part="root"][data-orientation="vertical"] {
|
|
2053
|
+
flex-direction: column;
|
|
2054
|
+
/* The column reads as one slab: members fill to the widest. */
|
|
2055
|
+
align-items: stretch;
|
|
2056
|
+
}
|
|
2057
|
+
|
|
2058
|
+
/* One register for the whole group: the group's size retunes every
|
|
2059
|
+
member's height the way a control register should — one knob, not one
|
|
2060
|
+
per button. */
|
|
2061
|
+
[data-scope="button-group"][data-part="root"][data-size="sm"] > [data-scope="button"][data-part="root"] {
|
|
2062
|
+
block-size: var(--bs-control-height-sm);
|
|
2063
|
+
padding: 0 var(--bs-padding-md);
|
|
2064
|
+
font-size: var(--bs-font-size-sm);
|
|
2065
|
+
}
|
|
2066
|
+
|
|
2067
|
+
[data-scope="button-group"][data-part="root"][data-size="lg"] > [data-scope="button"][data-part="root"] {
|
|
2068
|
+
block-size: var(--bs-control-height-lg);
|
|
2069
|
+
padding: 0 var(--bs-padding-xl);
|
|
2070
|
+
}
|
|
2071
|
+
|
|
2072
|
+
/* The seam: each member after the first slides one pixel over its
|
|
2073
|
+
predecessor's trailing hairline, so two borders read as one. */
|
|
2074
|
+
[data-scope="button-group"][data-part="root"] > [data-scope="button"][data-part="root"] + [data-scope="button"][data-part="root"] {
|
|
2075
|
+
margin-inline-start: -1px;
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
[data-scope="button-group"][data-part="root"][data-orientation="vertical"] > [data-scope="button"][data-part="root"] + [data-scope="button"][data-part="root"] {
|
|
2079
|
+
margin-inline-start: 0;
|
|
2080
|
+
margin-block-start: -1px;
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
/* 方寸为章, trimmed where the seals meet: interior corners square off,
|
|
2084
|
+
the first keeps its start side and the last its end side. */
|
|
2085
|
+
[data-scope="button-group"][data-part="root"][data-orientation="horizontal"] > [data-scope="button"][data-part="root"]:not(:first-child) {
|
|
2086
|
+
border-start-start-radius: 0;
|
|
2087
|
+
border-end-start-radius: 0;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
[data-scope="button-group"][data-part="root"][data-orientation="horizontal"] > [data-scope="button"][data-part="root"]:not(:last-child) {
|
|
2091
|
+
border-start-end-radius: 0;
|
|
2092
|
+
border-end-end-radius: 0;
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
[data-scope="button-group"][data-part="root"][data-orientation="vertical"] > [data-scope="button"][data-part="root"]:not(:first-child) {
|
|
2096
|
+
border-start-start-radius: 0;
|
|
2097
|
+
border-start-end-radius: 0;
|
|
2098
|
+
}
|
|
2099
|
+
|
|
2100
|
+
[data-scope="button-group"][data-part="root"][data-orientation="vertical"] > [data-scope="button"][data-part="root"]:not(:last-child) {
|
|
2101
|
+
border-end-start-radius: 0;
|
|
2102
|
+
border-end-end-radius: 0;
|
|
2103
|
+
}
|
|
2104
|
+
|
|
2105
|
+
/* Raised while hovered or focused: the deepened hairline and the focus
|
|
2106
|
+
halo paint above the neighbors instead of vanishing under them. */
|
|
2107
|
+
[data-scope="button-group"][data-part="root"] > [data-scope="button"][data-part="root"]:hover,
|
|
2108
|
+
[data-scope="button-group"][data-part="root"] > [data-scope="button"][data-part="root"]:focus-visible {
|
|
2109
|
+
z-index: 1;
|
|
1727
2110
|
}
|
|
2111
|
+
|
|
2112
|
+
/* The group may set the members' corner register: data-radius retunes
|
|
2113
|
+
--bs-radius-control, which every member's border-radius consumes, so
|
|
2114
|
+
the fused whole — first edge, last edge, and the trimmed seams —
|
|
2115
|
+
keeps one corner story. */
|
|
2116
|
+
[data-scope="button-group"][data-part="root"][data-radius="sm"] { --bs-radius-control: var(--bs-radius-sm); }
|
|
2117
|
+
[data-scope="button-group"][data-part="root"][data-radius="md"] { --bs-radius-control: var(--bs-radius-md); }
|
|
2118
|
+
[data-scope="button-group"][data-part="root"][data-radius="lg"] { --bs-radius-control: var(--bs-radius-lg); }
|
|
2119
|
+
[data-scope="button-group"][data-part="root"][data-radius="xl"] { --bs-radius-control: var(--bs-radius-xl); }
|
|
2120
|
+
[data-scope="button-group"][data-part="root"][data-radius="2xl"] { --bs-radius-control: var(--bs-radius-2xl); }
|
|
2121
|
+
[data-scope="button-group"][data-part="root"][data-radius="full"] { --bs-radius-control: var(--bs-radius-full); }
|
|
1728
2122
|
`;
|
|
1729
2123
|
//#endregion
|
|
1730
2124
|
//#region src/styles/components/calendar.ts
|
|
@@ -1972,7 +2366,7 @@ const carouselCss = `
|
|
|
1972
2366
|
block-size: calc(var(--bs-space-2) + 2px);
|
|
1973
2367
|
padding: 0;
|
|
1974
2368
|
border: none;
|
|
1975
|
-
border-radius:
|
|
2369
|
+
border-radius: var(--bs-radius-full);
|
|
1976
2370
|
background: var(--bs-color-border-strong);
|
|
1977
2371
|
cursor: pointer;
|
|
1978
2372
|
transition: background-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
@@ -2000,19 +2394,173 @@ const carouselCss = `
|
|
|
2000
2394
|
}
|
|
2001
2395
|
`;
|
|
2002
2396
|
//#endregion
|
|
2003
|
-
//#region src/styles/components/
|
|
2004
|
-
const
|
|
2005
|
-
|
|
2006
|
-
|
|
2397
|
+
//#region src/styles/components/cascade-select.ts
|
|
2398
|
+
const cascadeSelectCss = positionerCss("cascade-select") + popupContentCss("cascade-select", "0rem") + `
|
|
2399
|
+
/* The trigger reads as a field — the input recipe — with the joined
|
|
2400
|
+
labels as its ink and a quiet chevron at the inline end. */
|
|
2401
|
+
[data-scope="cascade-select"][data-part="control"] {
|
|
2402
|
+
display: flex;
|
|
2403
|
+
inline-size: 100%;
|
|
2404
|
+
}
|
|
2405
|
+
|
|
2406
|
+
[data-scope="cascade-select"][data-part="trigger"] {
|
|
2407
|
+
box-sizing: border-box;
|
|
2408
|
+
display: flex;
|
|
2409
|
+
flex: 1;
|
|
2007
2410
|
align-items: center;
|
|
2411
|
+
justify-content: space-between;
|
|
2008
2412
|
gap: var(--bs-space-2);
|
|
2413
|
+
inline-size: 100%;
|
|
2414
|
+
block-size: var(--bs-control-height-md);
|
|
2415
|
+
padding-inline: var(--bs-padding-md);
|
|
2416
|
+
border: 1px solid var(--bs-color-border);
|
|
2417
|
+
border-radius: var(--bs-radius-sm);
|
|
2418
|
+
background: var(--bs-color-surface-2);
|
|
2009
2419
|
color: var(--bs-color-text-primary);
|
|
2010
|
-
font
|
|
2420
|
+
font: inherit;
|
|
2421
|
+
font-size: var(--bs-font-size-md);
|
|
2422
|
+
text-align: start;
|
|
2423
|
+
cursor: pointer;
|
|
2424
|
+
transition: border-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
2011
2425
|
}
|
|
2012
2426
|
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2427
|
+
[data-scope="cascade-select"][data-part="trigger"][data-placeholder-shown]
|
|
2428
|
+
[data-part="value-text"] {
|
|
2429
|
+
color: var(--bs-color-text-tertiary);
|
|
2430
|
+
}
|
|
2431
|
+
|
|
2432
|
+
[data-scope="cascade-select"][data-part="trigger"]:hover:not(:focus):not(:disabled) {
|
|
2433
|
+
border-color: var(--bs-color-border-strong);
|
|
2434
|
+
}
|
|
2435
|
+
|
|
2436
|
+
[data-scope="cascade-select"][data-part="trigger"]:focus-visible {
|
|
2437
|
+
outline: none;
|
|
2438
|
+
border-color: var(--bs-color-primary);
|
|
2439
|
+
box-shadow: var(--bs-focus-ring);
|
|
2440
|
+
}
|
|
2441
|
+
|
|
2442
|
+
[data-scope="cascade-select"][data-part="trigger"][data-invalid] {
|
|
2443
|
+
border-color: var(--bs-color-danger);
|
|
2444
|
+
}
|
|
2445
|
+
|
|
2446
|
+
[data-scope="cascade-select"][data-part="trigger"]:disabled {
|
|
2447
|
+
border-color: var(--bs-color-border);
|
|
2448
|
+
background: var(--bs-color-surface-inset);
|
|
2449
|
+
color: var(--bs-color-text-disabled);
|
|
2450
|
+
cursor: not-allowed;
|
|
2451
|
+
}
|
|
2452
|
+
|
|
2453
|
+
[data-scope="cascade-select"][data-part="indicator"] {
|
|
2454
|
+
display: grid;
|
|
2455
|
+
place-items: center;
|
|
2456
|
+
color: var(--bs-color-text-tertiary);
|
|
2457
|
+
}
|
|
2458
|
+
|
|
2459
|
+
[data-scope="cascade-select"][data-part="indicator"] svg {
|
|
2460
|
+
inline-size: var(--bs-space-4);
|
|
2461
|
+
block-size: var(--bs-space-4);
|
|
2462
|
+
transition: transform var(--bs-duration-fast) var(--bs-ease-out);
|
|
2463
|
+
}
|
|
2464
|
+
|
|
2465
|
+
[data-scope="cascade-select"][data-part="trigger"][data-state="open"]
|
|
2466
|
+
[data-part="indicator"]
|
|
2467
|
+
svg {
|
|
2468
|
+
transform: rotate(180deg);
|
|
2469
|
+
}
|
|
2470
|
+
|
|
2471
|
+
/* The vessel is a corridor: one column per walked level, a hairline
|
|
2472
|
+
between neighbours, each column scrolling past its own grove. */
|
|
2473
|
+
[data-scope="cascade-select"][data-part="content"] {
|
|
2474
|
+
display: flex;
|
|
2475
|
+
}
|
|
2476
|
+
|
|
2477
|
+
[data-scope="cascade-select"][data-part="list"] {
|
|
2478
|
+
box-sizing: border-box;
|
|
2479
|
+
flex-shrink: 0;
|
|
2480
|
+
min-inline-size: 11rem;
|
|
2481
|
+
max-block-size: 16rem;
|
|
2482
|
+
margin: 0;
|
|
2483
|
+
padding: var(--bs-space-1);
|
|
2484
|
+
list-style: none;
|
|
2485
|
+
overflow-block: auto;
|
|
2486
|
+
}
|
|
2487
|
+
|
|
2488
|
+
[data-scope="cascade-select"][data-part="list"] + [data-part="list"] {
|
|
2489
|
+
border-inline-start: 1px solid var(--bs-color-border);
|
|
2490
|
+
}
|
|
2491
|
+
|
|
2492
|
+
[data-scope="cascade-select"][data-part="item"] {
|
|
2493
|
+
display: flex;
|
|
2494
|
+
align-items: center;
|
|
2495
|
+
gap: var(--bs-space-2);
|
|
2496
|
+
min-block-size: var(--bs-control-height-sm);
|
|
2497
|
+
padding: 0 var(--bs-space-2);
|
|
2498
|
+
border-radius: var(--bs-radius-sm);
|
|
2499
|
+
color: var(--bs-color-text-primary);
|
|
2500
|
+
font-size: var(--bs-font-size-sm);
|
|
2501
|
+
cursor: pointer;
|
|
2502
|
+
}
|
|
2503
|
+
|
|
2504
|
+
[data-scope="cascade-select"][data-part="item"]:hover:not([data-state="checked"], [data-disabled]),
|
|
2505
|
+
[data-scope="cascade-select"][data-part="item"][data-highlighted]:not([data-state="checked"]) {
|
|
2506
|
+
background: var(--bs-color-surface-0);
|
|
2507
|
+
}
|
|
2508
|
+
|
|
2509
|
+
[data-scope="cascade-select"][data-part="item"]:focus-visible {
|
|
2510
|
+
outline: none;
|
|
2511
|
+
box-shadow: var(--bs-focus-ring-inset);
|
|
2512
|
+
}
|
|
2513
|
+
|
|
2514
|
+
[data-scope="cascade-select"][data-part="item"][data-state="checked"] {
|
|
2515
|
+
background: var(--bs-color-primary);
|
|
2516
|
+
color: var(--bs-color-primary-text);
|
|
2517
|
+
font-weight: var(--bs-font-weight-medium);
|
|
2518
|
+
}
|
|
2519
|
+
|
|
2520
|
+
[data-scope="cascade-select"][data-part="item"][data-disabled] {
|
|
2521
|
+
color: var(--bs-color-text-disabled);
|
|
2522
|
+
cursor: not-allowed;
|
|
2523
|
+
}
|
|
2524
|
+
|
|
2525
|
+
[data-scope="cascade-select"][data-part="item-text"] {
|
|
2526
|
+
flex: 1;
|
|
2527
|
+
overflow: hidden;
|
|
2528
|
+
text-overflow: ellipsis;
|
|
2529
|
+
white-space: nowrap;
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
[data-scope="cascade-select"][data-part="branch-indicator"],
|
|
2533
|
+
[data-scope="cascade-select"][data-part="item-indicator"] {
|
|
2534
|
+
display: grid;
|
|
2535
|
+
place-items: center;
|
|
2536
|
+
color: var(--bs-color-text-tertiary);
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
[data-scope="cascade-select"][data-part="branch-indicator"] svg,
|
|
2540
|
+
[data-scope="cascade-select"][data-part="item-indicator"] svg {
|
|
2541
|
+
inline-size: var(--bs-space-4);
|
|
2542
|
+
block-size: var(--bs-space-4);
|
|
2543
|
+
}
|
|
2544
|
+
|
|
2545
|
+
[data-scope="cascade-select"][data-part="item"][data-state="checked"] [data-part="item-indicator"],
|
|
2546
|
+
[data-scope="cascade-select"][data-part="item"][data-highlighted] [data-part="branch-indicator"] {
|
|
2547
|
+
color: currentColor;
|
|
2548
|
+
}
|
|
2549
|
+
`;
|
|
2550
|
+
//#endregion
|
|
2551
|
+
//#region src/styles/components/checkbox.ts
|
|
2552
|
+
const checkboxCss = labelCss("checkbox") + `
|
|
2553
|
+
[data-scope="checkbox"][data-part="root"] {
|
|
2554
|
+
display: inline-flex;
|
|
2555
|
+
align-items: center;
|
|
2556
|
+
gap: var(--bs-space-2);
|
|
2557
|
+
color: var(--bs-color-text-primary);
|
|
2558
|
+
font-size: var(--bs-font-size-sm);
|
|
2559
|
+
}
|
|
2560
|
+
|
|
2561
|
+
/* A group of checkboxes is one field: the rows stack, and the invalid
|
|
2562
|
+
* pigment bleeds onto every row inside. */
|
|
2563
|
+
[data-scope="checkbox"][data-part="group"] {
|
|
2016
2564
|
display: flex;
|
|
2017
2565
|
flex-direction: column;
|
|
2018
2566
|
gap: var(--bs-space-2);
|
|
@@ -2029,8 +2577,8 @@ const checkboxCss = labelCss("checkbox") + `
|
|
|
2029
2577
|
align-items: center;
|
|
2030
2578
|
justify-content: center;
|
|
2031
2579
|
flex-shrink: 0;
|
|
2032
|
-
inline-size: var(--bs-part-size-
|
|
2033
|
-
block-size: var(--bs-part-size-
|
|
2580
|
+
inline-size: var(--bs-part-size-sm);
|
|
2581
|
+
block-size: var(--bs-part-size-sm);
|
|
2034
2582
|
border: 1px solid var(--bs-color-border);
|
|
2035
2583
|
border-radius: var(--bs-radius-sm);
|
|
2036
2584
|
background: var(--bs-color-surface-2);
|
|
@@ -2090,8 +2638,8 @@ const checkboxCss = labelCss("checkbox") + `
|
|
|
2090
2638
|
}
|
|
2091
2639
|
|
|
2092
2640
|
[data-scope="checkbox"][data-part="indicator"] svg {
|
|
2093
|
-
inline-size: calc(var(--bs-part-size-
|
|
2094
|
-
block-size: calc(var(--bs-part-size-
|
|
2641
|
+
inline-size: calc(var(--bs-part-size-sm) * 0.7);
|
|
2642
|
+
block-size: calc(var(--bs-part-size-sm) * 0.7);
|
|
2095
2643
|
}
|
|
2096
2644
|
|
|
2097
2645
|
[data-scope="checkbox"][data-part="root"]:has([data-disabled]) {
|
|
@@ -2103,6 +2651,24 @@ const checkboxCss = labelCss("checkbox") + `
|
|
|
2103
2651
|
}
|
|
2104
2652
|
`;
|
|
2105
2653
|
//#endregion
|
|
2654
|
+
//#region src/styles/components/checkbox-group.ts
|
|
2655
|
+
const checkboxGroupCss = `
|
|
2656
|
+
/* The group stacks its seals by default; the horizontal layout keeps the
|
|
2657
|
+
natural reading order and wraps when the container narrows. */
|
|
2658
|
+
[data-scope="checkbox-group"][data-part="root"] {
|
|
2659
|
+
display: grid;
|
|
2660
|
+
gap: var(--bs-space-3);
|
|
2661
|
+
max-inline-size: 20rem;
|
|
2662
|
+
}
|
|
2663
|
+
|
|
2664
|
+
[data-scope="checkbox-group"][data-part="root"][data-layout="horizontal"] {
|
|
2665
|
+
display: flex;
|
|
2666
|
+
flex-wrap: wrap;
|
|
2667
|
+
gap: var(--bs-space-2) var(--bs-space-4);
|
|
2668
|
+
max-inline-size: none;
|
|
2669
|
+
}
|
|
2670
|
+
`;
|
|
2671
|
+
//#endregion
|
|
2106
2672
|
//#region src/styles/components/chip.ts
|
|
2107
2673
|
const chipCss = `
|
|
2108
2674
|
/* A counting coin: one small number, round as a seal impression. It sits
|
|
@@ -2313,6 +2879,7 @@ const collapsibleCss = `
|
|
|
2313
2879
|
/* A collapsible stands alone, so its trigger is a full control: paper
|
|
2314
2880
|
surface, one hairline, resting on xs. */
|
|
2315
2881
|
[data-scope="collapsible"][data-part="trigger"] {
|
|
2882
|
+
box-sizing: border-box;
|
|
2316
2883
|
display: flex;
|
|
2317
2884
|
align-items: center;
|
|
2318
2885
|
justify-content: space-between;
|
|
@@ -2452,7 +3019,6 @@ const colorPickerCss = labelCss("color-picker") + positionerCss("color-picker")
|
|
|
2452
3019
|
display: flex;
|
|
2453
3020
|
flex-direction: column;
|
|
2454
3021
|
gap: var(--bs-space-2);
|
|
2455
|
-
max-inline-size: 17rem;
|
|
2456
3022
|
}
|
|
2457
3023
|
|
|
2458
3024
|
[data-scope="color-picker"][data-part="root"][data-disabled] {
|
|
@@ -2521,7 +3087,7 @@ const colorPickerCss = labelCss("color-picker") + positionerCss("color-picker")
|
|
|
2521
3087
|
[data-scope="color-picker"][data-part="swatch"] {
|
|
2522
3088
|
position: absolute;
|
|
2523
3089
|
inset: var(--bs-space-1);
|
|
2524
|
-
border-radius:
|
|
3090
|
+
border-radius: var(--bs-radius-xs);
|
|
2525
3091
|
box-shadow: inset 0 0 0 1px var(--bs-color-border);
|
|
2526
3092
|
}
|
|
2527
3093
|
|
|
@@ -2531,7 +3097,7 @@ const colorPickerCss = labelCss("color-picker") + positionerCss("color-picker")
|
|
|
2531
3097
|
[data-scope="color-picker"][data-part="transparency-grid"] {
|
|
2532
3098
|
position: absolute;
|
|
2533
3099
|
inset: var(--bs-space-1);
|
|
2534
|
-
border-radius:
|
|
3100
|
+
border-radius: var(--bs-radius-xs);
|
|
2535
3101
|
}
|
|
2536
3102
|
|
|
2537
3103
|
/* The geometry vars live on the content: the popup teleports to body, out
|
|
@@ -2566,7 +3132,7 @@ const colorPickerCss = labelCss("color-picker") + positionerCss("color-picker")
|
|
|
2566
3132
|
position: absolute;
|
|
2567
3133
|
inline-size: var(--bs-color-picker-thumb);
|
|
2568
3134
|
block-size: var(--bs-color-picker-thumb);
|
|
2569
|
-
border-radius:
|
|
3135
|
+
border-radius: var(--bs-radius-full);
|
|
2570
3136
|
outline: none;
|
|
2571
3137
|
transform: translate(-50%, -50%);
|
|
2572
3138
|
box-shadow:
|
|
@@ -2598,7 +3164,7 @@ const colorPickerCss = labelCss("color-picker") + positionerCss("color-picker")
|
|
|
2598
3164
|
position: absolute;
|
|
2599
3165
|
inline-size: var(--bs-color-picker-thumb);
|
|
2600
3166
|
block-size: var(--bs-color-picker-thumb);
|
|
2601
|
-
border-radius:
|
|
3167
|
+
border-radius: var(--bs-radius-full);
|
|
2602
3168
|
outline: none;
|
|
2603
3169
|
transform: translate(-50%, -50%);
|
|
2604
3170
|
box-shadow:
|
|
@@ -3060,108 +3626,359 @@ const comboboxCss = labelCss("combobox") + positionerCss("combobox") + popupCont
|
|
|
3060
3626
|
}
|
|
3061
3627
|
`;
|
|
3062
3628
|
//#endregion
|
|
3063
|
-
//#region src/styles/components/
|
|
3064
|
-
const
|
|
3065
|
-
|
|
3629
|
+
//#region src/styles/components/command.ts
|
|
3630
|
+
const commandCss = `
|
|
3631
|
+
/* The palette's footing: full-viewport, the sheet docked a fifth of the
|
|
3632
|
+
way down (structural placement, not a spacing value). */
|
|
3633
|
+
[data-scope="command"][data-part="positioner"] {
|
|
3634
|
+
position: fixed;
|
|
3635
|
+
inset: 0;
|
|
3636
|
+
z-index: calc(var(--bs-z-overlay) + var(--layer-index, 0));
|
|
3066
3637
|
display: flex;
|
|
3067
|
-
|
|
3068
|
-
|
|
3638
|
+
justify-content: center;
|
|
3639
|
+
align-items: flex-start;
|
|
3640
|
+
padding: 20dvh var(--bs-padding-lg) var(--bs-padding-lg);
|
|
3069
3641
|
}
|
|
3070
3642
|
|
|
3071
|
-
|
|
3643
|
+
/* The sheet: a wide vessel at the top of the elevation ladder, entering
|
|
3644
|
+
as ink dissolving into paper. */
|
|
3645
|
+
[data-scope="command"][data-part="content"] {
|
|
3646
|
+
position: relative;
|
|
3647
|
+
box-sizing: border-box;
|
|
3648
|
+
inline-size: min(36rem, 100%);
|
|
3072
3649
|
display: flex;
|
|
3073
|
-
|
|
3074
|
-
|
|
3650
|
+
flex-direction: column;
|
|
3651
|
+
padding: var(--bs-padding-md);
|
|
3652
|
+
border: 1px solid var(--bs-color-border);
|
|
3653
|
+
border-radius: var(--bs-radius-lg);
|
|
3654
|
+
background: var(--bs-color-surface-2);
|
|
3655
|
+
color: var(--bs-color-text-primary);
|
|
3656
|
+
box-shadow: var(--bs-elevation-4);
|
|
3657
|
+
transition:
|
|
3658
|
+
opacity var(--bs-duration-base) var(--bs-ease-out),
|
|
3659
|
+
translate var(--bs-duration-base) var(--bs-ease-spring);
|
|
3075
3660
|
}
|
|
3076
3661
|
|
|
3077
|
-
|
|
3078
|
-
|
|
3079
|
-
|
|
3662
|
+
[data-scope="command"][data-state="open"][data-part="content"] {
|
|
3663
|
+
box-shadow: var(--bs-elevation-5);
|
|
3664
|
+
animation: bs-ink-in var(--bs-duration-slow) var(--bs-ease-out);
|
|
3665
|
+
}
|
|
3666
|
+
|
|
3667
|
+
/* The search field carries the same recipe as every input: border +
|
|
3668
|
+
surface + focus halo, never a shadow lift. */
|
|
3669
|
+
[data-scope="command"][data-part="input"] {
|
|
3080
3670
|
box-sizing: border-box;
|
|
3081
|
-
|
|
3082
|
-
|
|
3083
|
-
align-items: center;
|
|
3084
|
-
min-width: 0;
|
|
3085
|
-
block-size: var(--bs-control-height-md);
|
|
3671
|
+
inline-size: 100%;
|
|
3672
|
+
block-size: var(--bs-control-height-lg);
|
|
3086
3673
|
padding: 0 var(--bs-padding-md);
|
|
3087
|
-
border:
|
|
3088
|
-
border-
|
|
3089
|
-
|
|
3674
|
+
border: none;
|
|
3675
|
+
border-block-end: 1px solid var(--bs-color-border);
|
|
3676
|
+
border-radius: 0;
|
|
3677
|
+
background: transparent;
|
|
3090
3678
|
color: var(--bs-color-text-primary);
|
|
3091
3679
|
font: inherit;
|
|
3092
3680
|
font-size: var(--bs-font-size-md);
|
|
3093
|
-
cursor: text;
|
|
3094
|
-
transition: border-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
3095
3681
|
}
|
|
3096
3682
|
|
|
3097
|
-
[data-scope="
|
|
3098
|
-
|
|
3683
|
+
[data-scope="command"][data-part="input"]::placeholder {
|
|
3684
|
+
color: var(--bs-color-text-tertiary);
|
|
3099
3685
|
}
|
|
3100
3686
|
|
|
3101
|
-
[data-scope="
|
|
3102
|
-
|
|
3103
|
-
|
|
3687
|
+
[data-scope="command"][data-part="input"]:focus,
|
|
3688
|
+
[data-scope="command"][data-part="input"]:focus-visible {
|
|
3689
|
+
outline: none;
|
|
3690
|
+
box-shadow: var(--bs-focus-ring-inset);
|
|
3104
3691
|
}
|
|
3105
3692
|
|
|
3106
|
-
|
|
3107
|
-
|
|
3693
|
+
/* The ledger: the machine's content grafts onto this list, so the
|
|
3694
|
+
vessel stays inside the sheet instead of floating a second popup. */
|
|
3695
|
+
[data-scope="command"][data-part="list"] {
|
|
3696
|
+
display: flex;
|
|
3697
|
+
flex-direction: column;
|
|
3698
|
+
gap: var(--bs-space-1);
|
|
3699
|
+
margin-block-start: var(--bs-space-2);
|
|
3700
|
+
max-block-size: min(50dvh, 24rem);
|
|
3701
|
+
padding: var(--bs-space-1);
|
|
3702
|
+
overflow-y: auto;
|
|
3703
|
+
overscroll-behavior: contain;
|
|
3108
3704
|
}
|
|
3109
3705
|
|
|
3110
|
-
[data-scope="
|
|
3111
|
-
|
|
3706
|
+
[data-scope="command"][data-part="list"][hidden] {
|
|
3707
|
+
display: none;
|
|
3112
3708
|
}
|
|
3113
3709
|
|
|
3114
|
-
[data-scope="
|
|
3115
|
-
|
|
3116
|
-
|
|
3117
|
-
|
|
3118
|
-
cursor: not-allowed;
|
|
3710
|
+
[data-scope="command"][data-part="group"] {
|
|
3711
|
+
display: flex;
|
|
3712
|
+
flex-direction: column;
|
|
3713
|
+
gap: var(--bs-space-1);
|
|
3119
3714
|
}
|
|
3120
3715
|
|
|
3121
|
-
[data-scope="
|
|
3122
|
-
|
|
3716
|
+
[data-scope="command"][data-part="group"] + [data-scope="command"][data-part="group"] {
|
|
3717
|
+
margin-block-start: var(--bs-space-2);
|
|
3123
3718
|
}
|
|
3124
3719
|
|
|
3125
|
-
|
|
3126
|
-
|
|
3127
|
-
|
|
3128
|
-
|
|
3129
|
-
|
|
3130
|
-
|
|
3131
|
-
|
|
3132
|
-
|
|
3133
|
-
|
|
3134
|
-
outline: none;
|
|
3720
|
+
/* Group headings whisper: small, tracked, never competing with rows. */
|
|
3721
|
+
[data-scope="command"][data-part="group-label"] {
|
|
3722
|
+
padding: var(--bs-space-1) var(--bs-space-2);
|
|
3723
|
+
color: var(--bs-color-text-tertiary);
|
|
3724
|
+
font-size: var(--bs-font-size-xs);
|
|
3725
|
+
font-weight: var(--bs-font-weight-medium);
|
|
3726
|
+
letter-spacing: var(--bs-tracking-label);
|
|
3727
|
+
text-transform: uppercase;
|
|
3728
|
+
user-select: none;
|
|
3135
3729
|
}
|
|
3136
3730
|
|
|
3137
|
-
/*
|
|
3138
|
-
[data-scope="
|
|
3139
|
-
|
|
3140
|
-
|
|
3731
|
+
/* Rows are quiet ink: the highlight is light on the row, not a fill. */
|
|
3732
|
+
[data-scope="command"][data-part="item"] {
|
|
3733
|
+
display: flex;
|
|
3734
|
+
align-items: center;
|
|
3735
|
+
justify-content: space-between;
|
|
3736
|
+
gap: var(--bs-space-2);
|
|
3737
|
+
min-block-size: var(--bs-control-height-sm);
|
|
3738
|
+
padding: 0 var(--bs-space-2);
|
|
3739
|
+
border-radius: var(--bs-radius-sm);
|
|
3740
|
+
color: var(--bs-color-text-primary);
|
|
3741
|
+
font-size: var(--bs-font-size-sm);
|
|
3742
|
+
cursor: pointer;
|
|
3743
|
+
user-select: none;
|
|
3744
|
+
transition: background-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
3141
3745
|
}
|
|
3142
3746
|
|
|
3143
|
-
[data-scope="
|
|
3144
|
-
|
|
3747
|
+
[data-scope="command"][data-part="item"][data-highlighted] {
|
|
3748
|
+
background: var(--bs-color-surface-0);
|
|
3145
3749
|
}
|
|
3146
3750
|
|
|
3147
|
-
[data-scope="
|
|
3148
|
-
color: var(--bs-color-
|
|
3751
|
+
[data-scope="command"][data-part="item"][data-disabled] {
|
|
3752
|
+
color: var(--bs-color-text-disabled);
|
|
3753
|
+
cursor: not-allowed;
|
|
3149
3754
|
}
|
|
3150
3755
|
|
|
3151
|
-
|
|
3152
|
-
|
|
3153
|
-
|
|
3154
|
-
|
|
3155
|
-
|
|
3156
|
-
user-select: none;
|
|
3756
|
+
[data-scope="command"][data-part="item-label"] {
|
|
3757
|
+
flex: 1;
|
|
3758
|
+
overflow: hidden;
|
|
3759
|
+
text-overflow: ellipsis;
|
|
3760
|
+
white-space: nowrap;
|
|
3157
3761
|
}
|
|
3158
3762
|
|
|
3159
|
-
/* The
|
|
3160
|
-
|
|
3161
|
-
|
|
3162
|
-
|
|
3163
|
-
|
|
3164
|
-
|
|
3763
|
+
/* The hint is a keycap in miniature — the kbd recipe, riding the row. */
|
|
3764
|
+
[data-scope="command"][data-part="item-hint"] {
|
|
3765
|
+
flex: none;
|
|
3766
|
+
display: inline-flex;
|
|
3767
|
+
align-items: center;
|
|
3768
|
+
min-inline-size: 1.75em;
|
|
3769
|
+
padding: 0.125em 0.375em;
|
|
3770
|
+
border: 1px solid var(--bs-color-border);
|
|
3771
|
+
border-radius: var(--bs-radius-sm);
|
|
3772
|
+
background: var(--bs-color-surface-2);
|
|
3773
|
+
box-shadow: 0 1px 0 var(--bs-color-border);
|
|
3774
|
+
color: var(--bs-color-text-secondary);
|
|
3775
|
+
font-size: max(var(--bs-font-size-xs), 0.8125em);
|
|
3776
|
+
line-height: 1.2;
|
|
3777
|
+
font-variant-numeric: tabular-nums;
|
|
3778
|
+
white-space: nowrap;
|
|
3779
|
+
}
|
|
3780
|
+
|
|
3781
|
+
[data-scope="command"][data-part="item"][data-highlighted] [data-scope="command"][data-part="item-hint"] {
|
|
3782
|
+
background: var(--bs-color-surface-1);
|
|
3783
|
+
}
|
|
3784
|
+
|
|
3785
|
+
[data-scope="command"][data-part="empty"] {
|
|
3786
|
+
padding: var(--bs-space-4);
|
|
3787
|
+
color: var(--bs-color-text-tertiary);
|
|
3788
|
+
font-size: var(--bs-font-size-sm);
|
|
3789
|
+
text-align: center;
|
|
3790
|
+
}
|
|
3791
|
+
`;
|
|
3792
|
+
//#endregion
|
|
3793
|
+
//#region src/styles/components/comment.ts
|
|
3794
|
+
const commentCss = `
|
|
3795
|
+
/* A voice on the record: the portrait hangs left, the body carries the
|
|
3796
|
+
byline, the ink, and the row of answers — each in its own register,
|
|
3797
|
+
so the thread reads at a scan. */
|
|
3798
|
+
[data-scope="comment"][data-part="root"] {
|
|
3799
|
+
display: flex;
|
|
3800
|
+
gap: var(--bs-gap-md);
|
|
3801
|
+
padding-block: var(--bs-padding-sm);
|
|
3802
|
+
}
|
|
3803
|
+
|
|
3804
|
+
[data-scope="comment"][data-part="avatar"] {
|
|
3805
|
+
display: flex;
|
|
3806
|
+
flex: none;
|
|
3807
|
+
}
|
|
3808
|
+
|
|
3809
|
+
[data-scope="comment"][data-part="body"] {
|
|
3810
|
+
display: flex;
|
|
3811
|
+
flex: 1;
|
|
3812
|
+
flex-direction: column;
|
|
3813
|
+
gap: var(--bs-space-1);
|
|
3814
|
+
min-inline-size: 0;
|
|
3815
|
+
}
|
|
3816
|
+
|
|
3817
|
+
[data-scope="comment"][data-part="header"] {
|
|
3818
|
+
display: flex;
|
|
3819
|
+
align-items: baseline;
|
|
3820
|
+
gap: var(--bs-space-2);
|
|
3821
|
+
}
|
|
3822
|
+
|
|
3823
|
+
[data-scope="comment"][data-part="author"] {
|
|
3824
|
+
color: var(--bs-color-text-primary);
|
|
3825
|
+
font-weight: var(--bs-font-weight-medium);
|
|
3826
|
+
}
|
|
3827
|
+
|
|
3828
|
+
[data-scope="comment"][data-part="datetime"] {
|
|
3829
|
+
color: var(--bs-color-text-tertiary);
|
|
3830
|
+
font-size: var(--bs-font-size-xs);
|
|
3831
|
+
}
|
|
3832
|
+
|
|
3833
|
+
[data-scope="comment"][data-part="content"] {
|
|
3834
|
+
color: var(--bs-color-text-primary);
|
|
3835
|
+
line-height: var(--bs-line-height-relaxed);
|
|
3836
|
+
}
|
|
3837
|
+
|
|
3838
|
+
[data-scope="comment"][data-part="actions"] {
|
|
3839
|
+
display: flex;
|
|
3840
|
+
align-items: center;
|
|
3841
|
+
gap: var(--bs-space-4);
|
|
3842
|
+
margin-block-start: var(--bs-space-1);
|
|
3843
|
+
font-size: var(--bs-font-size-sm);
|
|
3844
|
+
}
|
|
3845
|
+
`;
|
|
3846
|
+
//#endregion
|
|
3847
|
+
//#region src/styles/components/container.ts
|
|
3848
|
+
const containerCss = `
|
|
3849
|
+
/* The reading frame. The measures are set in ch — the rendered width of
|
|
3850
|
+
the zero glyph — so the clamp tracks the typeset text itself instead
|
|
3851
|
+
of a fixed visual value: the same measure holds fewer Latin
|
|
3852
|
+
characters than CJK ones, and both keep the line short enough to
|
|
3853
|
+
cross without losing its head. Padding keeps the ink off the page
|
|
3854
|
+
edges when the viewport runs narrower than the measure. */
|
|
3855
|
+
[data-scope="container"][data-part="root"] {
|
|
3856
|
+
inline-size: 100%;
|
|
3857
|
+
margin-inline: auto;
|
|
3858
|
+
}
|
|
3859
|
+
|
|
3860
|
+
[data-scope="container"][data-part="root"][data-size="narrow"] {
|
|
3861
|
+
max-inline-size: 48ch;
|
|
3862
|
+
}
|
|
3863
|
+
[data-scope="container"][data-part="root"][data-size="readable"] {
|
|
3864
|
+
max-inline-size: 72ch;
|
|
3865
|
+
}
|
|
3866
|
+
[data-scope="container"][data-part="root"][data-size="wide"] {
|
|
3867
|
+
max-inline-size: 96ch;
|
|
3868
|
+
}
|
|
3869
|
+
|
|
3870
|
+
/* Full leaves the measure to the page — the clamp simply lifts. */
|
|
3871
|
+
[data-scope="container"][data-part="root"][data-size="full"] {
|
|
3872
|
+
max-inline-size: none;
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3875
|
+
[data-scope="container"][data-part="root"][data-padding] {
|
|
3876
|
+
padding-inline: var(--bs-padding-lg);
|
|
3877
|
+
}
|
|
3878
|
+
`;
|
|
3879
|
+
//#endregion
|
|
3880
|
+
//#region src/styles/components/date-input.ts
|
|
3881
|
+
const dateInputCss = labelCss("date-input") + `
|
|
3882
|
+
[data-scope="date-input"][data-part="root"] {
|
|
3883
|
+
display: flex;
|
|
3884
|
+
flex-direction: column;
|
|
3885
|
+
gap: var(--bs-space-2);
|
|
3886
|
+
}
|
|
3887
|
+
|
|
3888
|
+
[data-scope="date-input"][data-part="control"] {
|
|
3889
|
+
display: flex;
|
|
3890
|
+
align-items: center;
|
|
3891
|
+
gap: var(--bs-space-2);
|
|
3892
|
+
}
|
|
3893
|
+
|
|
3894
|
+
/* The segment group IS the field — the same border + surface + focus halo
|
|
3895
|
+
recipe as every input, no shadow. */
|
|
3896
|
+
[data-scope="date-input"][data-part="segment-group"] {
|
|
3897
|
+
box-sizing: border-box;
|
|
3898
|
+
flex: 1;
|
|
3899
|
+
display: flex;
|
|
3900
|
+
align-items: center;
|
|
3901
|
+
min-width: 0;
|
|
3902
|
+
block-size: var(--bs-control-height-md);
|
|
3903
|
+
padding: 0 var(--bs-padding-md);
|
|
3904
|
+
border: 1px solid var(--bs-color-border);
|
|
3905
|
+
border-radius: var(--bs-radius-sm);
|
|
3906
|
+
background: var(--bs-color-surface-2);
|
|
3907
|
+
color: var(--bs-color-text-primary);
|
|
3908
|
+
font: inherit;
|
|
3909
|
+
font-size: var(--bs-font-size-md);
|
|
3910
|
+
cursor: text;
|
|
3911
|
+
transition: border-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
3912
|
+
}
|
|
3913
|
+
|
|
3914
|
+
[data-scope="date-input"][data-part="segment-group"]:hover:not([data-disabled], [data-readonly]) {
|
|
3915
|
+
border-color: var(--bs-color-border-strong);
|
|
3916
|
+
}
|
|
3917
|
+
|
|
3918
|
+
[data-scope="date-input"][data-part="segment-group"][data-focus] {
|
|
3919
|
+
border-color: var(--bs-color-primary);
|
|
3920
|
+
box-shadow: var(--bs-focus-ring);
|
|
3921
|
+
}
|
|
3922
|
+
|
|
3923
|
+
[data-scope="date-input"][data-part="segment-group"][data-invalid] {
|
|
3924
|
+
border-color: var(--bs-color-danger);
|
|
3925
|
+
}
|
|
3926
|
+
|
|
3927
|
+
[data-scope="date-input"][data-part="segment-group"][data-invalid][data-focus] {
|
|
3928
|
+
box-shadow: var(--bs-focus-ring);
|
|
3929
|
+
}
|
|
3930
|
+
|
|
3931
|
+
[data-scope="date-input"][data-part="segment-group"][data-disabled] {
|
|
3932
|
+
border-color: var(--bs-color-border);
|
|
3933
|
+
background: var(--bs-color-surface-inset);
|
|
3934
|
+
color: var(--bs-color-text-disabled);
|
|
3935
|
+
cursor: not-allowed;
|
|
3936
|
+
}
|
|
3937
|
+
|
|
3938
|
+
[data-scope="date-input"][data-part="segment-group"][data-readonly] {
|
|
3939
|
+
background: var(--bs-color-surface-inset);
|
|
3940
|
+
}
|
|
3941
|
+
|
|
3942
|
+
[data-scope="date-input"][data-part="segment"] {
|
|
3943
|
+
display: inline-flex;
|
|
3944
|
+
align-items: center;
|
|
3945
|
+
justify-content: center;
|
|
3946
|
+
min-width: 2ch;
|
|
3947
|
+
padding: 0 2px;
|
|
3948
|
+
border-radius: var(--bs-radius-xs);
|
|
3949
|
+
font-variant-numeric: tabular-nums;
|
|
3950
|
+
caret-color: transparent;
|
|
3951
|
+
outline: none;
|
|
3952
|
+
}
|
|
3953
|
+
|
|
3954
|
+
/* The focused segment takes the flat primary fill — ink where the eye is. */
|
|
3955
|
+
[data-scope="date-input"][data-part="segment"]:focus {
|
|
3956
|
+
background: var(--bs-color-primary);
|
|
3957
|
+
color: var(--bs-color-primary-text);
|
|
3958
|
+
}
|
|
3959
|
+
|
|
3960
|
+
[data-scope="date-input"][data-part="segment"][data-placeholder-shown] {
|
|
3961
|
+
color: var(--bs-color-text-tertiary);
|
|
3962
|
+
}
|
|
3963
|
+
|
|
3964
|
+
[data-scope="date-input"][data-part="segment"]:focus[data-placeholder-shown] {
|
|
3965
|
+
color: var(--bs-color-primary-text);
|
|
3966
|
+
}
|
|
3967
|
+
|
|
3968
|
+
/* Separators are type, not controls — never take the ink. */
|
|
3969
|
+
[data-scope="date-input"][data-part="segment"][data-type="literal"] {
|
|
3970
|
+
min-width: 0;
|
|
3971
|
+
padding: 0;
|
|
3972
|
+
color: var(--bs-color-text-tertiary);
|
|
3973
|
+
user-select: none;
|
|
3974
|
+
}
|
|
3975
|
+
|
|
3976
|
+
/* The hidden input still hosts form autofill — visually gone, structurally
|
|
3977
|
+
present. */
|
|
3978
|
+
[data-scope="date-input"][data-part="hidden-input"] {
|
|
3979
|
+
position: absolute;
|
|
3980
|
+
inline-size: 1px;
|
|
3981
|
+
block-size: 1px;
|
|
3165
3982
|
opacity: 0;
|
|
3166
3983
|
pointer-events: none;
|
|
3167
3984
|
}
|
|
@@ -3430,6 +4247,10 @@ const datePickerCss = labelCss("date-picker") + positionerCss("date-picker") + p
|
|
|
3430
4247
|
}
|
|
3431
4248
|
|
|
3432
4249
|
[data-scope="date-picker"][data-part="table"] {
|
|
4250
|
+
/* Table layout is the geometry here — the columns must share the
|
|
4251
|
+
panel — so a host's prose reset that blockifies tables (docs sites
|
|
4252
|
+
do this for their markdown tables) must not reach inside. */
|
|
4253
|
+
display: table;
|
|
3433
4254
|
inline-size: 100%;
|
|
3434
4255
|
border-collapse: separate;
|
|
3435
4256
|
border-spacing: 0;
|
|
@@ -3540,6 +4361,52 @@ const datePickerCss = labelCss("date-picker") + positionerCss("date-picker") + p
|
|
|
3540
4361
|
}
|
|
3541
4362
|
`;
|
|
3542
4363
|
//#endregion
|
|
4364
|
+
//#region src/styles/components/descriptions.ts
|
|
4365
|
+
const descriptionsCss = `
|
|
4366
|
+
/* The horizontal ledger: term column, detail column, one hairline
|
|
4367
|
+
between rows — a table that never becomes one. */
|
|
4368
|
+
[data-scope="descriptions"][data-part="root"] {
|
|
4369
|
+
margin: 0;
|
|
4370
|
+
display: flex;
|
|
4371
|
+
flex-direction: column;
|
|
4372
|
+
gap: var(--bs-space-2);
|
|
4373
|
+
font-size: var(--bs-font-size-md);
|
|
4374
|
+
}
|
|
4375
|
+
|
|
4376
|
+
[data-scope="descriptions"][data-part="item"] {
|
|
4377
|
+
display: grid;
|
|
4378
|
+
grid-template-columns: minmax(6em, max-content) 1fr;
|
|
4379
|
+
gap: var(--bs-space-4);
|
|
4380
|
+
padding-block: var(--bs-space-2);
|
|
4381
|
+
border-block-end: 1px solid var(--bs-color-border);
|
|
4382
|
+
}
|
|
4383
|
+
|
|
4384
|
+
[data-scope="descriptions"][data-part="item"]:last-child {
|
|
4385
|
+
border-block-end: none;
|
|
4386
|
+
}
|
|
4387
|
+
|
|
4388
|
+
[data-scope="descriptions"][data-part="term"] {
|
|
4389
|
+
color: var(--bs-color-text-tertiary);
|
|
4390
|
+
font-size: var(--bs-font-size-sm);
|
|
4391
|
+
letter-spacing: var(--bs-tracking-label);
|
|
4392
|
+
}
|
|
4393
|
+
|
|
4394
|
+
[data-scope="descriptions"][data-part="detail"] {
|
|
4395
|
+
margin: 0;
|
|
4396
|
+
color: var(--bs-color-text-primary);
|
|
4397
|
+
}
|
|
4398
|
+
|
|
4399
|
+
/* The vertical ledger: each pair stacked, for narrow measures. */
|
|
4400
|
+
[data-scope="descriptions"][data-part="root"][data-layout="vertical"] [data-part="item"] {
|
|
4401
|
+
grid-template-columns: 1fr;
|
|
4402
|
+
gap: var(--bs-space-1);
|
|
4403
|
+
}
|
|
4404
|
+
|
|
4405
|
+
[data-scope="descriptions"][data-layout="vertical"] [data-part="detail"] {
|
|
4406
|
+
color: var(--bs-color-text-secondary);
|
|
4407
|
+
}
|
|
4408
|
+
`;
|
|
4409
|
+
//#endregion
|
|
3543
4410
|
//#region src/styles/components/dialog.ts
|
|
3544
4411
|
const dialogCss = `
|
|
3545
4412
|
[data-scope="dialog"][data-part="trigger"] {
|
|
@@ -3808,6 +4675,31 @@ const drawerCss = positionerCss("drawer") + `
|
|
|
3808
4675
|
background: var(--bs-color-text-tertiary);
|
|
3809
4676
|
}
|
|
3810
4677
|
|
|
4678
|
+
/* A side sheet's handle turns on its side and rides the leading edge:
|
|
4679
|
+
the hand drags along the same axis it dismisses, so the bar reads as
|
|
4680
|
+
a rail, not a lid. */
|
|
4681
|
+
[data-scope="drawer"][data-part="content"][data-swipe-direction="left"] [data-scope="drawer"][data-part="grabber"],
|
|
4682
|
+
[data-scope="drawer"][data-part="content"][data-swipe-direction="right"] [data-scope="drawer"][data-part="grabber"] {
|
|
4683
|
+
position: absolute;
|
|
4684
|
+
inset-block: 0;
|
|
4685
|
+
inline-size: auto;
|
|
4686
|
+
padding-inline: var(--bs-space-2);
|
|
4687
|
+
}
|
|
4688
|
+
|
|
4689
|
+
[data-scope="drawer"][data-part="content"][data-swipe-direction="left"] [data-scope="drawer"][data-part="grabber"] {
|
|
4690
|
+
inset-inline-start: 0;
|
|
4691
|
+
}
|
|
4692
|
+
|
|
4693
|
+
[data-scope="drawer"][data-part="content"][data-swipe-direction="right"] [data-scope="drawer"][data-part="grabber"] {
|
|
4694
|
+
inset-inline-end: 0;
|
|
4695
|
+
}
|
|
4696
|
+
|
|
4697
|
+
[data-scope="drawer"][data-part="content"][data-swipe-direction="left"] [data-scope="drawer"][data-part="grabber-indicator"],
|
|
4698
|
+
[data-scope="drawer"][data-part="content"][data-swipe-direction="right"] [data-scope="drawer"][data-part="grabber-indicator"] {
|
|
4699
|
+
inline-size: var(--bs-space-1);
|
|
4700
|
+
block-size: var(--bs-space-8);
|
|
4701
|
+
}
|
|
4702
|
+
|
|
3811
4703
|
/* The trigger is a seal-cut control: paper on a hairline, deepening on
|
|
3812
4704
|
hover, the shadow letting go under the press. */
|
|
3813
4705
|
[data-scope="drawer"][data-part="trigger"] {
|
|
@@ -3948,23 +4840,67 @@ const drawerCss = positionerCss("drawer") + `
|
|
|
3948
4840
|
}
|
|
3949
4841
|
`;
|
|
3950
4842
|
//#endregion
|
|
4843
|
+
//#region src/styles/components/dynamic-input.ts
|
|
4844
|
+
const dynamicInputCss = `
|
|
4845
|
+
/* A column of entry rows: the rows keep their rhythm on the density gap,
|
|
4846
|
+
the group itself stays frameless — the inputs carry the recipe. */
|
|
4847
|
+
[data-scope="dynamic-input"][data-part="root"] {
|
|
4848
|
+
display: flex;
|
|
4849
|
+
flex-direction: column;
|
|
4850
|
+
gap: var(--bs-gap-sm);
|
|
4851
|
+
inline-size: 100%;
|
|
4852
|
+
}
|
|
4853
|
+
|
|
4854
|
+
[data-scope="dynamic-input"][data-part="row"] {
|
|
4855
|
+
display: flex;
|
|
4856
|
+
align-items: center;
|
|
4857
|
+
gap: var(--bs-gap-xs);
|
|
4858
|
+
}
|
|
4859
|
+
|
|
4860
|
+
/* The entry stretches to the row; the remove seal keeps its own width. */
|
|
4861
|
+
[data-scope="dynamic-input"][data-part="row"] [data-scope="input"][data-part="root"] {
|
|
4862
|
+
flex: 1;
|
|
4863
|
+
min-inline-size: 0;
|
|
4864
|
+
}
|
|
4865
|
+
|
|
4866
|
+
[data-scope="dynamic-input"][data-part="add"] {
|
|
4867
|
+
display: flex;
|
|
4868
|
+
}
|
|
4869
|
+
`;
|
|
4870
|
+
//#endregion
|
|
3951
4871
|
//#region src/styles/components/editable.ts
|
|
3952
4872
|
const editableCss = labelCss("editable") + `
|
|
3953
4873
|
[data-scope="editable"][data-part="root"] {
|
|
3954
|
-
display:
|
|
3955
|
-
|
|
4874
|
+
display: grid;
|
|
4875
|
+
grid-template-columns: 1fr auto;
|
|
4876
|
+
grid-template-areas:
|
|
4877
|
+
"label label"
|
|
4878
|
+
"area control";
|
|
3956
4879
|
gap: var(--bs-space-2);
|
|
4880
|
+
align-items: center;
|
|
3957
4881
|
inline-size: 100%;
|
|
3958
4882
|
}
|
|
3959
4883
|
|
|
4884
|
+
[data-scope="editable"][data-part="label"] {
|
|
4885
|
+
grid-area: label;
|
|
4886
|
+
}
|
|
4887
|
+
|
|
3960
4888
|
[data-scope="editable"][data-part="root"][data-disabled] {
|
|
3961
4889
|
color: var(--bs-color-text-disabled);
|
|
3962
4890
|
}
|
|
3963
4891
|
|
|
4892
|
+
/* The text and its triggers share one row: the field stretches, the
|
|
4893
|
+
seals sit at its right shoulder. */
|
|
3964
4894
|
[data-scope="editable"][data-part="area"] {
|
|
4895
|
+
grid-area: area;
|
|
3965
4896
|
position: relative;
|
|
3966
4897
|
display: flex;
|
|
3967
4898
|
align-items: center;
|
|
4899
|
+
min-inline-size: 0;
|
|
4900
|
+
}
|
|
4901
|
+
|
|
4902
|
+
[data-scope="editable"][data-part="control"] {
|
|
4903
|
+
grid-area: control;
|
|
3968
4904
|
}
|
|
3969
4905
|
|
|
3970
4906
|
/* Preview and input share one geometry so the swap never shifts the page;
|
|
@@ -4101,12 +5037,37 @@ const editableCss = labelCss("editable") + `
|
|
|
4101
5037
|
}
|
|
4102
5038
|
`;
|
|
4103
5039
|
//#endregion
|
|
5040
|
+
//#region src/styles/components/ellipsis.ts
|
|
5041
|
+
const ellipsisCss = `
|
|
5042
|
+
/* One line, cut: the overflow knife draws the ellipsis at the box edge.
|
|
5043
|
+
The element is a span, stood up as a block — the cut only works on a
|
|
5044
|
+
block-level box. */
|
|
5045
|
+
[data-scope="ellipsis"][data-part="root"] {
|
|
5046
|
+
display: block;
|
|
5047
|
+
overflow: hidden;
|
|
5048
|
+
text-overflow: ellipsis;
|
|
5049
|
+
white-space: nowrap;
|
|
5050
|
+
}
|
|
5051
|
+
|
|
5052
|
+
/* N lines, clamped: the box-line algorithm counts the lines the
|
|
5053
|
+
wrapper hands over in --bs-ellipsis-lines. Word wrapping stays on —
|
|
5054
|
+
a long word must never force the clamp to cut mid-glyph. */
|
|
5055
|
+
[data-scope="ellipsis"][data-part="root"][data-multiline] {
|
|
5056
|
+
display: -webkit-box;
|
|
5057
|
+
overflow-wrap: break-word;
|
|
5058
|
+
white-space: normal;
|
|
5059
|
+
-webkit-box-orient: vertical;
|
|
5060
|
+
-webkit-line-clamp: var(--bs-ellipsis-lines);
|
|
5061
|
+
}
|
|
5062
|
+
`;
|
|
5063
|
+
//#endregion
|
|
4104
5064
|
//#region src/styles/components/empty.ts
|
|
4105
5065
|
const emptyCss = `
|
|
4106
5066
|
/* An empty state: the page holds its breath — a quiet mark, one line of
|
|
4107
5067
|
ink, and room for the next action. Centered, generous with whitespace. */
|
|
4108
5068
|
[data-scope="empty"][data-part="root"] {
|
|
4109
5069
|
/* Full width is the component's own property, not the stage's stretch. */
|
|
5070
|
+
box-sizing: border-box;
|
|
4110
5071
|
inline-size: 100%;
|
|
4111
5072
|
display: flex;
|
|
4112
5073
|
flex-direction: column;
|
|
@@ -4153,17 +5114,10 @@ const emptyCss = `
|
|
|
4153
5114
|
`;
|
|
4154
5115
|
//#endregion
|
|
4155
5116
|
//#region src/styles/components/field.ts
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4159
|
-
|
|
4160
|
-
align-items: start;
|
|
4161
|
-
gap: var(--bs-space-2);
|
|
4162
|
-
inline-size: 100%;
|
|
4163
|
-
}
|
|
4164
|
-
|
|
4165
|
-
/* The control itself: inputs rely on border + surface + focus halo, never
|
|
4166
|
-
a shadow — a field sits on the paper, it does not float above it. */
|
|
5117
|
+
/** The control recipe alone: border + surface + focus halo, the register
|
|
5118
|
+
* every text entry rides. The bare Input and Textarea families re-scope
|
|
5119
|
+
* this to their own anatomy instead of copying it. */
|
|
5120
|
+
const fieldControlCss = `
|
|
4167
5121
|
[data-scope="field"][data-part="input"],
|
|
4168
5122
|
[data-scope="field"][data-part="textarea"],
|
|
4169
5123
|
[data-scope="field"][data-part="select"] {
|
|
@@ -4187,6 +5141,20 @@ const fieldCss = labelCss("field") + `
|
|
|
4187
5141
|
block-size: var(--bs-control-height-md);
|
|
4188
5142
|
}
|
|
4189
5143
|
|
|
5144
|
+
/* Size tiers ride the control-height ladder, as anywhere. */
|
|
5145
|
+
[data-scope="field"][data-part="input"][data-size="sm"],
|
|
5146
|
+
[data-scope="field"][data-part="select"][data-size="sm"] {
|
|
5147
|
+
block-size: var(--bs-control-height-sm);
|
|
5148
|
+
padding-inline: var(--bs-padding-sm);
|
|
5149
|
+
font-size: var(--bs-font-size-sm);
|
|
5150
|
+
}
|
|
5151
|
+
|
|
5152
|
+
[data-scope="field"][data-part="input"][data-size="lg"],
|
|
5153
|
+
[data-scope="field"][data-part="select"][data-size="lg"] {
|
|
5154
|
+
block-size: var(--bs-control-height-lg);
|
|
5155
|
+
padding-inline: var(--bs-padding-lg);
|
|
5156
|
+
}
|
|
5157
|
+
|
|
4190
5158
|
[data-scope="field"][data-part="textarea"] {
|
|
4191
5159
|
min-block-size: calc(var(--bs-control-height-md) * 2 + var(--bs-space-2));
|
|
4192
5160
|
padding-block: var(--bs-space-2);
|
|
@@ -4227,7 +5195,16 @@ const fieldCss = labelCss("field") + `
|
|
|
4227
5195
|
color: var(--bs-color-text-disabled);
|
|
4228
5196
|
cursor: not-allowed;
|
|
4229
5197
|
}
|
|
4230
|
-
|
|
5198
|
+
`;
|
|
5199
|
+
const fieldCss = labelCss("field") + `
|
|
5200
|
+
[data-scope="field"][data-part="root"] {
|
|
5201
|
+
display: flex;
|
|
5202
|
+
flex-direction: column;
|
|
5203
|
+
align-items: start;
|
|
5204
|
+
gap: var(--bs-space-2);
|
|
5205
|
+
inline-size: 100%;
|
|
5206
|
+
}
|
|
5207
|
+
` + fieldControlCss + `
|
|
4231
5208
|
/* The required mark whispers, never shouts: a quiet pigment point after
|
|
4232
5209
|
the label. */
|
|
4233
5210
|
[data-scope="field"][data-part="required-indicator"] {
|
|
@@ -4250,6 +5227,49 @@ const fieldCss = labelCss("field") + `
|
|
|
4250
5227
|
[data-scope="field"][data-part="root"][data-disabled] {
|
|
4251
5228
|
color: var(--bs-color-text-disabled);
|
|
4252
5229
|
}
|
|
5230
|
+
|
|
5231
|
+
/* The floating-label variant, opted in per field with [data-float]. The
|
|
5232
|
+
label starts riding the control at placeholder height and floats to
|
|
5233
|
+
the control's top edge once the reader focuses or types. :has() reads
|
|
5234
|
+
the real input element so the pairing survives whatever part marks the
|
|
5235
|
+
machine writes; the empty-looking space placeholder keeps
|
|
5236
|
+
:placeholder-shown honest for an untouched field. */
|
|
5237
|
+
[data-scope="field"][data-float][data-part="root"] {
|
|
5238
|
+
position: relative;
|
|
5239
|
+
/* Room above the control edge for the label once it is afloat. */
|
|
5240
|
+
margin-block-start: var(--bs-space-4);
|
|
5241
|
+
}
|
|
5242
|
+
|
|
5243
|
+
[data-scope="field"][data-float][data-part="root"] [data-part="label"] {
|
|
5244
|
+
position: absolute;
|
|
5245
|
+
inset-inline-start: var(--bs-padding-md);
|
|
5246
|
+
inset-block-start: calc(var(--bs-control-height-md) / 2);
|
|
5247
|
+
translate: 0 -50%;
|
|
5248
|
+
color: var(--bs-color-text-tertiary);
|
|
5249
|
+
pointer-events: none;
|
|
5250
|
+
/* The control's own paper under the label cuts the hairline it rides,
|
|
5251
|
+
the way a legend cuts a fieldset border. */
|
|
5252
|
+
padding: 0 var(--bs-space-1);
|
|
5253
|
+
background: var(--bs-color-surface-2);
|
|
5254
|
+
transition:
|
|
5255
|
+
inset-block-start var(--bs-duration-fast) var(--bs-ease-out),
|
|
5256
|
+
color var(--bs-duration-fast) var(--bs-ease-out),
|
|
5257
|
+
font-size var(--bs-duration-fast) var(--bs-ease-out);
|
|
5258
|
+
}
|
|
5259
|
+
|
|
5260
|
+
[data-scope="field"][data-float][data-part="root"]:has(input:focus) [data-part="label"],
|
|
5261
|
+
[data-scope="field"][data-float][data-part="root"]:has(input:not(:placeholder-shown)) [data-part="label"],
|
|
5262
|
+
[data-scope="field"][data-float][data-part="root"]:has(textarea:not(:placeholder-shown)) [data-part="label"] {
|
|
5263
|
+
inset-block-start: 0;
|
|
5264
|
+
font-size: var(--bs-font-size-xs);
|
|
5265
|
+
color: var(--bs-color-text-secondary);
|
|
5266
|
+
}
|
|
5267
|
+
|
|
5268
|
+
/* While the reader is in the field, the afloat label carries the same
|
|
5269
|
+
pigment as the haloed hairline. */
|
|
5270
|
+
[data-scope="field"][data-float][data-part="root"]:has(input:focus) [data-part="label"] {
|
|
5271
|
+
color: var(--bs-color-primary);
|
|
5272
|
+
}
|
|
4253
5273
|
`;
|
|
4254
5274
|
//#endregion
|
|
4255
5275
|
//#region src/styles/components/fieldset.ts
|
|
@@ -4312,7 +5332,6 @@ const fileUploadCss = labelCss("file-upload") + `
|
|
|
4312
5332
|
align-items: flex-start;
|
|
4313
5333
|
gap: var(--bs-space-3);
|
|
4314
5334
|
inline-size: 100%;
|
|
4315
|
-
max-inline-size: 24rem;
|
|
4316
5335
|
}
|
|
4317
5336
|
|
|
4318
5337
|
/* The choose-files button rides the control recipe: paper fill, one
|
|
@@ -4555,6 +5574,136 @@ const fileUploadCss = labelCss("file-upload") + `
|
|
|
4555
5574
|
}
|
|
4556
5575
|
`;
|
|
4557
5576
|
//#endregion
|
|
5577
|
+
//#region src/styles/components/float-button.ts
|
|
5578
|
+
const floatButtonCss = `
|
|
5579
|
+
/* A float: the trigger moors at the page corner and the actions fan out
|
|
5580
|
+
from it. It floats, so it casts — and vessels are round: the trigger
|
|
5581
|
+
and every action take the vessel radius, one rung of elevation at
|
|
5582
|
+
rest, lifting another under the pointer on the slow shadow clock. */
|
|
5583
|
+
[data-scope="float-button"][data-part="root"] {
|
|
5584
|
+
position: fixed;
|
|
5585
|
+
display: flex;
|
|
5586
|
+
/* The fan grows away from the mooring: first in the DOM sits nearest
|
|
5587
|
+
the corner, the actions rise (or hang) beyond it. */
|
|
5588
|
+
flex-direction: column-reverse;
|
|
5589
|
+
gap: var(--bs-space-2);
|
|
5590
|
+
z-index: calc(var(--bs-z-overlay) + var(--layer-index, 0));
|
|
5591
|
+
}
|
|
5592
|
+
|
|
5593
|
+
/* Top moorings hang the actions below the trigger instead. */
|
|
5594
|
+
[data-scope="float-button"][data-part="root"][data-placement^="top"] {
|
|
5595
|
+
flex-direction: column;
|
|
5596
|
+
}
|
|
5597
|
+
|
|
5598
|
+
/* The stack hugs its corner: start moorings align inward from the
|
|
5599
|
+
start edge, end moorings from the end edge. */
|
|
5600
|
+
[data-scope="float-button"][data-part="root"][data-placement$="-start"] {
|
|
5601
|
+
align-items: flex-start;
|
|
5602
|
+
}
|
|
5603
|
+
|
|
5604
|
+
[data-scope="float-button"][data-part="root"][data-placement$="-end"] {
|
|
5605
|
+
align-items: flex-end;
|
|
5606
|
+
}
|
|
5607
|
+
|
|
5608
|
+
[data-scope="float-button"][data-part="root"][data-placement="bottom-end"] {
|
|
5609
|
+
inset-block-end: var(--bs-space-6);
|
|
5610
|
+
inset-inline-end: var(--bs-space-6);
|
|
5611
|
+
}
|
|
5612
|
+
|
|
5613
|
+
[data-scope="float-button"][data-part="root"][data-placement="bottom-start"] {
|
|
5614
|
+
inset-block-end: var(--bs-space-6);
|
|
5615
|
+
inset-inline-start: var(--bs-space-6);
|
|
5616
|
+
}
|
|
5617
|
+
|
|
5618
|
+
[data-scope="float-button"][data-part="root"][data-placement="top-end"] {
|
|
5619
|
+
inset-block-start: var(--bs-space-6);
|
|
5620
|
+
inset-inline-end: var(--bs-space-6);
|
|
5621
|
+
}
|
|
5622
|
+
|
|
5623
|
+
[data-scope="float-button"][data-part="root"][data-placement="top-start"] {
|
|
5624
|
+
inset-block-start: var(--bs-space-6);
|
|
5625
|
+
inset-inline-start: var(--bs-space-6);
|
|
5626
|
+
}
|
|
5627
|
+
|
|
5628
|
+
/* The vessel register for both the trigger and the actions — above the
|
|
5629
|
+
recipe's own variant and active rules, so a solid trigger still casts
|
|
5630
|
+
at rest and everything settles back into the page when pressed. */
|
|
5631
|
+
[data-scope="float-button"][data-part="root"] [data-scope="button"][data-part="root"] {
|
|
5632
|
+
border-radius: var(--bs-radius-lg);
|
|
5633
|
+
--bs-shadow-color: color-mix(in oklab, var(--bs-shadow-ink) 30%, transparent);
|
|
5634
|
+
box-shadow: var(--bs-elevation-2);
|
|
5635
|
+
}
|
|
5636
|
+
|
|
5637
|
+
[data-scope="float-button"][data-part="root"] [data-scope="button"][data-part="root"]:hover:not(:disabled) {
|
|
5638
|
+
box-shadow: var(--bs-elevation-3);
|
|
5639
|
+
}
|
|
5640
|
+
|
|
5641
|
+
[data-scope="float-button"][data-part="root"] [data-scope="button"][data-part="root"]:active:not(:disabled) {
|
|
5642
|
+
box-shadow: none;
|
|
5643
|
+
}
|
|
5644
|
+
|
|
5645
|
+
/* Each action rides a row: the round button, and a small annotation
|
|
5646
|
+
surfaced beside it toward the page center while the group is open.
|
|
5647
|
+
The label is prose, not a control — the pointer passes through to
|
|
5648
|
+
the button. */
|
|
5649
|
+
[data-scope="float-button"][data-part="item"] {
|
|
5650
|
+
display: inline-flex;
|
|
5651
|
+
align-items: center;
|
|
5652
|
+
gap: var(--bs-space-2);
|
|
5653
|
+
flex-direction: row-reverse;
|
|
5654
|
+
}
|
|
5655
|
+
|
|
5656
|
+
[data-scope="float-button"][data-part="root"][data-placement$="-start"] [data-scope="float-button"][data-part="item"] {
|
|
5657
|
+
flex-direction: row;
|
|
5658
|
+
}
|
|
5659
|
+
|
|
5660
|
+
[data-scope="float-button"][data-part="item-label"] {
|
|
5661
|
+
padding: var(--bs-space-1) var(--bs-space-2);
|
|
5662
|
+
border: 1px solid var(--bs-color-border);
|
|
5663
|
+
border-radius: var(--bs-radius-sm);
|
|
5664
|
+
background: var(--bs-color-surface-2);
|
|
5665
|
+
color: var(--bs-color-text-secondary);
|
|
5666
|
+
font-size: var(--bs-font-size-xs);
|
|
5667
|
+
letter-spacing: var(--bs-tracking-label);
|
|
5668
|
+
white-space: nowrap;
|
|
5669
|
+
pointer-events: none;
|
|
5670
|
+
}
|
|
5671
|
+
|
|
5672
|
+
/* The fan folds, it never pops: actions fade and drift toward the
|
|
5673
|
+
trigger, and only once the fold has finished do they leave the
|
|
5674
|
+
reading order — visibility rounds the transition off, so a closed
|
|
5675
|
+
group is unfocusable without a bounce. States remain; animation does
|
|
5676
|
+
not. */
|
|
5677
|
+
[data-scope="float-button"][data-part="item"] {
|
|
5678
|
+
transition:
|
|
5679
|
+
opacity var(--bs-duration-base) var(--bs-ease-out),
|
|
5680
|
+
translate var(--bs-duration-base) var(--bs-ease-spring),
|
|
5681
|
+
visibility var(--bs-duration-base);
|
|
5682
|
+
}
|
|
5683
|
+
|
|
5684
|
+
[data-scope="float-button"][data-part="item-label"] {
|
|
5685
|
+
transition: opacity var(--bs-duration-fast) var(--bs-ease-out);
|
|
5686
|
+
}
|
|
5687
|
+
|
|
5688
|
+
[data-scope="float-button"][data-part="root"][data-state="closed"] [data-scope="float-button"][data-part="item"] {
|
|
5689
|
+
opacity: 0;
|
|
5690
|
+
visibility: hidden;
|
|
5691
|
+
pointer-events: none;
|
|
5692
|
+
}
|
|
5693
|
+
|
|
5694
|
+
[data-scope="float-button"][data-part="root"][data-placement^="bottom"][data-state="closed"] [data-scope="float-button"][data-part="item"] {
|
|
5695
|
+
translate: 0 var(--bs-space-2);
|
|
5696
|
+
}
|
|
5697
|
+
|
|
5698
|
+
[data-scope="float-button"][data-part="root"][data-placement^="top"][data-state="closed"] [data-scope="float-button"][data-part="item"] {
|
|
5699
|
+
translate: 0 calc(var(--bs-space-2) * -1);
|
|
5700
|
+
}
|
|
5701
|
+
|
|
5702
|
+
[data-scope="float-button"][data-part="root"][data-state="closed"] [data-scope="float-button"][data-part="item-label"] {
|
|
5703
|
+
opacity: 0;
|
|
5704
|
+
}
|
|
5705
|
+
`;
|
|
5706
|
+
//#endregion
|
|
4558
5707
|
//#region src/styles/components/floating-panel.ts
|
|
4559
5708
|
const floatingPanelCss = positionerCss("floating-panel") + popupContentCss("floating-panel", "20rem") + `
|
|
4560
5709
|
[data-scope="floating-panel"][data-part="positioner"] {
|
|
@@ -4808,6 +5957,43 @@ const floatingPanelCss = positionerCss("floating-panel") + popupContentCss("floa
|
|
|
4808
5957
|
}
|
|
4809
5958
|
`;
|
|
4810
5959
|
//#endregion
|
|
5960
|
+
//#region src/styles/components/form.ts
|
|
5961
|
+
const formCss = `
|
|
5962
|
+
/* The form is a quiet container — fields stack in one column and the
|
|
5963
|
+
spacing belongs to the grid, not to each field's margins. */
|
|
5964
|
+
[data-scope="form"][data-part="root"] {
|
|
5965
|
+
display: grid;
|
|
5966
|
+
gap: var(--bs-space-4);
|
|
5967
|
+
max-inline-size: 34rem;
|
|
5968
|
+
}
|
|
5969
|
+
|
|
5970
|
+
/* The FormField's wrapper keeps the field from stretching its own
|
|
5971
|
+
content wider than the grid column. */
|
|
5972
|
+
[data-form-field] {
|
|
5973
|
+
min-inline-size: 0;
|
|
5974
|
+
}
|
|
5975
|
+
`;
|
|
5976
|
+
//#endregion
|
|
5977
|
+
//#region src/styles/components/grid.ts
|
|
5978
|
+
const gridCss = `
|
|
5979
|
+
/* The alignment lattice. minmax(0, 1fr) — not a bare 1fr: a long word
|
|
5980
|
+
or a wide child would otherwise stretch its track past the lattice
|
|
5981
|
+
and shove every sibling aside. The column count and the gap ride CSS
|
|
5982
|
+
variables the wrapper points at their tokens. */
|
|
5983
|
+
[data-scope="grid"][data-part="root"] {
|
|
5984
|
+
display: grid;
|
|
5985
|
+
grid-template-columns: repeat(var(--bs-grid-columns, 12), minmax(0, 1fr));
|
|
5986
|
+
gap: var(--bs-grid-gap, var(--bs-space-3));
|
|
5987
|
+
}
|
|
5988
|
+
|
|
5989
|
+
/* The auto-fill lattice: as many tracks as the container fits, each at
|
|
5990
|
+
least --bs-grid-min-child-width. The wrapper sets the variable and
|
|
5991
|
+
this attribute together — one never arrives without the other. */
|
|
5992
|
+
[data-scope="grid"][data-part="root"][data-autofill] {
|
|
5993
|
+
grid-template-columns: repeat(auto-fill, minmax(var(--bs-grid-min-child-width), 1fr));
|
|
5994
|
+
}
|
|
5995
|
+
`;
|
|
5996
|
+
//#endregion
|
|
4811
5997
|
//#region src/styles/components/highlight.ts
|
|
4812
5998
|
const highlightCss = `
|
|
4813
5999
|
/* Search hits are strokes of pigment on the page, not neon. The highlight
|
|
@@ -4864,6 +6050,136 @@ const hoverCardCss = popupContentCss("hover-card") + positionerCss("hover-card")
|
|
|
4864
6050
|
}
|
|
4865
6051
|
`;
|
|
4866
6052
|
//#endregion
|
|
6053
|
+
//#region src/styles/components/icon.ts
|
|
6054
|
+
const iconCss = `
|
|
6055
|
+
/* The inkwell: one box at the glyph's optical measure, riding the
|
|
6056
|
+
text's own color — the fill comes from currentColor, so the icon
|
|
6057
|
+
carries no pigment of its own. The size steps follow the surrounding
|
|
6058
|
+
font size, so an icon sits in a line of any size with no breakpoint
|
|
6059
|
+
of its own; inherit is that same one-em default, named. */
|
|
6060
|
+
[data-scope="icon"][data-part="root"] {
|
|
6061
|
+
--_size: 1em;
|
|
6062
|
+
display: inline-flex;
|
|
6063
|
+
align-items: center;
|
|
6064
|
+
justify-content: center;
|
|
6065
|
+
flex: none;
|
|
6066
|
+
inline-size: var(--_size);
|
|
6067
|
+
block-size: var(--_size);
|
|
6068
|
+
font-size: var(--_size);
|
|
6069
|
+
fill: currentColor;
|
|
6070
|
+
}
|
|
6071
|
+
|
|
6072
|
+
[data-scope="icon"][data-part="root"][data-size="sm"] {
|
|
6073
|
+
--_size: 0.75em;
|
|
6074
|
+
}
|
|
6075
|
+
[data-scope="icon"][data-part="root"][data-size="md"] {
|
|
6076
|
+
--_size: 1em;
|
|
6077
|
+
}
|
|
6078
|
+
[data-scope="icon"][data-part="root"][data-size="lg"] {
|
|
6079
|
+
--_size: 1.25em;
|
|
6080
|
+
}
|
|
6081
|
+
|
|
6082
|
+
/* The glyph fills the box it is given — a standard measure is the
|
|
6083
|
+
whole point of the well. */
|
|
6084
|
+
[data-scope="icon"][data-part="root"] > svg {
|
|
6085
|
+
display: block;
|
|
6086
|
+
inline-size: 100%;
|
|
6087
|
+
block-size: 100%;
|
|
6088
|
+
}
|
|
6089
|
+
`;
|
|
6090
|
+
//#endregion
|
|
6091
|
+
//#region src/styles/components/image.ts
|
|
6092
|
+
const imageCss = `
|
|
6093
|
+
/* A framed picture that announces its own arrival: while the source
|
|
6094
|
+
loads, the frame keeps the skeleton's breath; the picture dissolves
|
|
6095
|
+
in when it lands; a broken source leaves the fallback. The frame's
|
|
6096
|
+
size belongs to the consumer, like the skeleton's. */
|
|
6097
|
+
[data-scope="image"][data-part="root"] {
|
|
6098
|
+
--_fit: cover;
|
|
6099
|
+
position: relative;
|
|
6100
|
+
display: block;
|
|
6101
|
+
margin: 0;
|
|
6102
|
+
overflow: hidden;
|
|
6103
|
+
border-radius: var(--bs-radius-sm);
|
|
6104
|
+
background: var(--bs-color-surface-inset);
|
|
6105
|
+
}
|
|
6106
|
+
|
|
6107
|
+
[data-scope="image"][data-part="root"][data-fit="contain"] {
|
|
6108
|
+
--_fit: contain;
|
|
6109
|
+
}
|
|
6110
|
+
|
|
6111
|
+
[data-scope="image"][data-part="root"][data-fit="fill"] {
|
|
6112
|
+
--_fit: fill;
|
|
6113
|
+
}
|
|
6114
|
+
|
|
6115
|
+
[data-scope="image"][data-part="root"][data-fit="none"] {
|
|
6116
|
+
--_fit: none;
|
|
6117
|
+
}
|
|
6118
|
+
|
|
6119
|
+
/* Waiting is the skeleton's breath — same wash, same pace. */
|
|
6120
|
+
[data-scope="image"][data-part="root"][data-state="loading"] {
|
|
6121
|
+
animation: bs-image-breathe 1600ms var(--bs-ease-in-out) infinite;
|
|
6122
|
+
}
|
|
6123
|
+
|
|
6124
|
+
[data-scope="image"][data-part="img"] {
|
|
6125
|
+
display: block;
|
|
6126
|
+
inline-size: 100%;
|
|
6127
|
+
block-size: 100%;
|
|
6128
|
+
object-fit: var(--_fit);
|
|
6129
|
+
/* The picture arrives unseen and dissolves in — ink settling, never
|
|
6130
|
+
a flash of half-drawn pixels. */
|
|
6131
|
+
opacity: 0;
|
|
6132
|
+
transition: opacity var(--bs-duration-slow) var(--bs-ease-out);
|
|
6133
|
+
}
|
|
6134
|
+
|
|
6135
|
+
[data-scope="image"][data-part="root"][data-state="loaded"] [data-scope="image"][data-part="img"] {
|
|
6136
|
+
opacity: 1;
|
|
6137
|
+
}
|
|
6138
|
+
|
|
6139
|
+
/* A broken source leaves nothing but the fallback: the browser's own
|
|
6140
|
+
broken-image mark would argue with the page. */
|
|
6141
|
+
[data-scope="image"][data-part="root"][data-state="error"] [data-scope="image"][data-part="img"] {
|
|
6142
|
+
display: none;
|
|
6143
|
+
}
|
|
6144
|
+
|
|
6145
|
+
[data-scope="image"][data-part="fallback"] {
|
|
6146
|
+
position: absolute;
|
|
6147
|
+
inset: 0;
|
|
6148
|
+
display: grid;
|
|
6149
|
+
place-items: center;
|
|
6150
|
+
background: var(--bs-color-surface-inset);
|
|
6151
|
+
color: var(--bs-color-text-tertiary);
|
|
6152
|
+
}
|
|
6153
|
+
|
|
6154
|
+
[data-scope="image"][data-part="fallback"] svg {
|
|
6155
|
+
inline-size: var(--bs-space-8);
|
|
6156
|
+
block-size: var(--bs-space-8);
|
|
6157
|
+
fill: none;
|
|
6158
|
+
stroke: currentColor;
|
|
6159
|
+
stroke-width: 1.5;
|
|
6160
|
+
stroke-linecap: round;
|
|
6161
|
+
stroke-linejoin: round;
|
|
6162
|
+
}
|
|
6163
|
+
|
|
6164
|
+
@media (prefers-reduced-motion: reduce) {
|
|
6165
|
+
[data-scope="image"][data-part="root"][data-state="loading"] {
|
|
6166
|
+
animation: none;
|
|
6167
|
+
opacity: 0.7;
|
|
6168
|
+
}
|
|
6169
|
+
}
|
|
6170
|
+
|
|
6171
|
+
@keyframes bs-image-breathe {
|
|
6172
|
+
0%,
|
|
6173
|
+
100% {
|
|
6174
|
+
opacity: 1;
|
|
6175
|
+
}
|
|
6176
|
+
|
|
6177
|
+
50% {
|
|
6178
|
+
opacity: 0.55;
|
|
6179
|
+
}
|
|
6180
|
+
}
|
|
6181
|
+
`;
|
|
6182
|
+
//#endregion
|
|
4867
6183
|
//#region src/styles/components/image-cropper.ts
|
|
4868
6184
|
const imageCropperCss = labelCss("image-cropper") + `
|
|
4869
6185
|
[data-scope="image-cropper"][data-part="root"] {
|
|
@@ -5027,37 +6343,229 @@ const imageCropperCss = labelCss("image-cropper") + `
|
|
|
5027
6343
|
}
|
|
5028
6344
|
`;
|
|
5029
6345
|
//#endregion
|
|
5030
|
-
//#region src/styles/components/
|
|
5031
|
-
const
|
|
5032
|
-
|
|
5033
|
-
|
|
5034
|
-
|
|
5035
|
-
|
|
5036
|
-
|
|
5037
|
-
|
|
5038
|
-
|
|
5039
|
-
|
|
5040
|
-
|
|
5041
|
-
|
|
5042
|
-
|
|
6346
|
+
//#region src/styles/components/image-viewer.ts
|
|
6347
|
+
const imageViewerCss = `
|
|
6348
|
+
/* The lightbox rides the dialog machine for scrim, stacking, focus and
|
|
6349
|
+
Escape, but it owns the whole screen: the extra class out-specifies
|
|
6350
|
+
the sheet chrome — no paper vessel, just the picture floating over
|
|
6351
|
+
the dimmed page. The layer math repeats the dialog's on purpose: the
|
|
6352
|
+
viewer must stand correct even where the dialog's own sheet is
|
|
6353
|
+
never styled. */
|
|
6354
|
+
[data-scope="dialog"][data-part="backdrop"].bs-image-viewer-backdrop {
|
|
6355
|
+
position: fixed;
|
|
6356
|
+
inset: 0;
|
|
6357
|
+
/* One below its positioner, from the same shared base. */
|
|
6358
|
+
z-index: calc(var(--bs-z-overlay) + var(--layer-index, 0) - 1);
|
|
6359
|
+
background: var(--bs-color-scrim);
|
|
6360
|
+
transition: opacity var(--bs-duration-slow) var(--bs-ease-out);
|
|
5043
6361
|
}
|
|
5044
6362
|
|
|
5045
|
-
[data-scope="
|
|
5046
|
-
|
|
5047
|
-
|
|
5048
|
-
|
|
5049
|
-
|
|
6363
|
+
[data-scope="dialog"][data-part="positioner"].bs-image-viewer-positioner {
|
|
6364
|
+
position: fixed;
|
|
6365
|
+
inset: 0;
|
|
6366
|
+
z-index: calc(var(--bs-z-overlay) + var(--layer-index, 0));
|
|
6367
|
+
display: grid;
|
|
6368
|
+
/* One row capped at the viewport: an auto row would let the picture's
|
|
6369
|
+
intrinsic height stretch the content past the screen, carrying the
|
|
6370
|
+
toolbar out of reach below the fold. */
|
|
6371
|
+
grid-template-rows: minmax(0, 1fr);
|
|
6372
|
+
padding: 0;
|
|
5050
6373
|
}
|
|
5051
6374
|
|
|
5052
|
-
|
|
5053
|
-
light on the paper. */
|
|
5054
|
-
[data-scope="tree-view"][data-part="branch-control"],
|
|
5055
|
-
[data-scope="tree-view"][data-part="item"] {
|
|
6375
|
+
[data-scope="dialog"][data-part="content"].bs-image-viewer-content {
|
|
5056
6376
|
position: relative;
|
|
5057
6377
|
display: flex;
|
|
5058
|
-
|
|
5059
|
-
gap: var(--bs-space-
|
|
5060
|
-
|
|
6378
|
+
flex-direction: column;
|
|
6379
|
+
gap: var(--bs-space-4);
|
|
6380
|
+
box-sizing: border-box;
|
|
6381
|
+
inline-size: 100%;
|
|
6382
|
+
block-size: 100%;
|
|
6383
|
+
max-block-size: none;
|
|
6384
|
+
overflow: visible;
|
|
6385
|
+
padding: 0;
|
|
6386
|
+
border: none;
|
|
6387
|
+
border-radius: 0;
|
|
6388
|
+
background: transparent;
|
|
6389
|
+
box-shadow: none;
|
|
6390
|
+
}
|
|
6391
|
+
|
|
6392
|
+
[data-scope="dialog"][data-part="content"].bs-image-viewer-content:focus,
|
|
6393
|
+
[data-scope="dialog"][data-part="content"].bs-image-viewer-content:focus-visible {
|
|
6394
|
+
outline: none;
|
|
6395
|
+
}
|
|
6396
|
+
|
|
6397
|
+
/* The panel grammar still holds: the lightbox dissolves in — the room
|
|
6398
|
+
darkening, never a flash. */
|
|
6399
|
+
[data-scope="dialog"][data-part="content"].bs-image-viewer-content[data-state="open"] {
|
|
6400
|
+
animation: bs-ink-in var(--bs-duration-slow) var(--bs-ease-out);
|
|
6401
|
+
}
|
|
6402
|
+
|
|
6403
|
+
/* The picture takes the row the toolbar leaves and keeps its shape
|
|
6404
|
+
inside it — contain centers whatever the frame cannot hold. The
|
|
6405
|
+
minimum height must be let go of explicitly, or the picture's own
|
|
6406
|
+
height would pin the row and push the tools off the screen. The
|
|
6407
|
+
hand's zoom and quarter-turns compose on one transform, which never
|
|
6408
|
+
animates into place on open — zoom is the reader's hand, not the
|
|
6409
|
+
ink's. */
|
|
6410
|
+
[data-scope="image-viewer"][data-part="viewport"] {
|
|
6411
|
+
display: block;
|
|
6412
|
+
flex: 1 1 auto;
|
|
6413
|
+
min-block-size: 0;
|
|
6414
|
+
min-inline-size: 0;
|
|
6415
|
+
inline-size: 100%;
|
|
6416
|
+
object-fit: contain;
|
|
6417
|
+
user-select: none;
|
|
6418
|
+
transition: transform var(--bs-duration-base) var(--bs-ease-out);
|
|
6419
|
+
}
|
|
6420
|
+
|
|
6421
|
+
[data-scope="image-viewer"][data-part="toolbar"] {
|
|
6422
|
+
display: flex;
|
|
6423
|
+
flex: none;
|
|
6424
|
+
justify-content: center;
|
|
6425
|
+
gap: var(--bs-space-2);
|
|
6426
|
+
/* The tools ride a small lacquer tray: a translucent ink that keeps
|
|
6427
|
+
the room dark in either register, held clear of the picture above
|
|
6428
|
+
and of the page's edge below. The group inside carries the joinery;
|
|
6429
|
+
its corners stay at the control register. */
|
|
6430
|
+
inline-size: max-content;
|
|
6431
|
+
margin-inline: auto;
|
|
6432
|
+
margin-block-end: var(--bs-space-6);
|
|
6433
|
+
padding: var(--bs-space-1);
|
|
6434
|
+
border-radius: var(--bs-radius-control, var(--bs-radius-sm));
|
|
6435
|
+
background: color-mix(in oklab, var(--bs-color-gray-900) 72%, transparent);
|
|
6436
|
+
}
|
|
6437
|
+
|
|
6438
|
+
/* Ghost ink over the dark scrim must be the paper-bright ink that never
|
|
6439
|
+
flips with the theme, and the hover wash follows as a pale breath. */
|
|
6440
|
+
[data-scope="image-viewer"][data-part="toolbar"] [data-scope="button"][data-part="root"] {
|
|
6441
|
+
--_ink: var(--bs-color-text-on-scrim);
|
|
6442
|
+
--_fill-hover: color-mix(in oklab, var(--bs-color-surface-2) 16%, transparent);
|
|
6443
|
+
}
|
|
6444
|
+
`;
|
|
6445
|
+
//#endregion
|
|
6446
|
+
//#region src/styles/components/input-group.ts
|
|
6447
|
+
const inputGroupCss = `
|
|
6448
|
+
/* The merged control: one hairline and one halo for the whole family.
|
|
6449
|
+
The input inside surrenders its own frame so attachments read as parts
|
|
6450
|
+
of the same seal, not buttons bolted onto a field. */
|
|
6451
|
+
[data-scope="input-group"][data-part="root"] {
|
|
6452
|
+
display: inline-flex;
|
|
6453
|
+
align-items: stretch;
|
|
6454
|
+
border: 1px solid var(--bs-color-border);
|
|
6455
|
+
border-radius: var(--bs-radius-sm);
|
|
6456
|
+
background: var(--bs-color-surface-2);
|
|
6457
|
+
/* The attachments are square-cut cells; the seal's rounding clips
|
|
6458
|
+
them, so the corners read as one shape instead of a field with
|
|
6459
|
+
blocks bolted on. */
|
|
6460
|
+
overflow: hidden;
|
|
6461
|
+
transition:
|
|
6462
|
+
border-color var(--bs-duration-fast) var(--bs-ease-out),
|
|
6463
|
+
box-shadow var(--bs-duration-fast) var(--bs-ease-out);
|
|
6464
|
+
}
|
|
6465
|
+
|
|
6466
|
+
[data-scope="input-group"][data-part="root"]:hover {
|
|
6467
|
+
border-color: var(--bs-color-border-strong);
|
|
6468
|
+
}
|
|
6469
|
+
|
|
6470
|
+
/* Focus is light arriving at the group: one halo, however many controls
|
|
6471
|
+
sit inside. */
|
|
6472
|
+
[data-scope="input-group"][data-part="root"]:focus-within {
|
|
6473
|
+
border-color: var(--bs-color-primary);
|
|
6474
|
+
box-shadow: var(--bs-focus-ring);
|
|
6475
|
+
}
|
|
6476
|
+
|
|
6477
|
+
/* The entry wears no frame of its own — it stretches to fill what is
|
|
6478
|
+
left of the seal, its own halo silenced in favor of the group's. The
|
|
6479
|
+
compound selectors outrank the field recipe's focus and disabled
|
|
6480
|
+
branches without touching the shared stylesheet. */
|
|
6481
|
+
[data-scope="input-group"][data-part="root"] [data-scope="input"][data-part="root"],
|
|
6482
|
+
[data-scope="input-group"][data-part="root"] [data-scope="textarea"][data-part="root"] {
|
|
6483
|
+
flex: 1;
|
|
6484
|
+
inline-size: auto;
|
|
6485
|
+
min-inline-size: 0;
|
|
6486
|
+
border: none;
|
|
6487
|
+
border-radius: 0;
|
|
6488
|
+
background: transparent;
|
|
6489
|
+
box-shadow: none;
|
|
6490
|
+
}
|
|
6491
|
+
|
|
6492
|
+
[data-scope="input-group"][data-part="root"] [data-scope="input"][data-part="root"]:focus,
|
|
6493
|
+
[data-scope="input-group"][data-part="root"] [data-scope="input"][data-part="root"]:focus-visible,
|
|
6494
|
+
[data-scope="input-group"][data-part="root"] [data-scope="textarea"][data-part="root"]:focus,
|
|
6495
|
+
[data-scope="input-group"][data-part="root"] [data-scope="textarea"][data-part="root"]:focus-visible {
|
|
6496
|
+
border: none;
|
|
6497
|
+
box-shadow: none;
|
|
6498
|
+
}
|
|
6499
|
+
|
|
6500
|
+
/* Disabled keeps the group's paper too — only the ink steps back. */
|
|
6501
|
+
[data-scope="input-group"][data-part="root"] [data-scope="input"][data-part="root"]:disabled,
|
|
6502
|
+
[data-scope="input-group"][data-part="root"] [data-scope="textarea"][data-part="root"]:disabled {
|
|
6503
|
+
background: transparent;
|
|
6504
|
+
}
|
|
6505
|
+
|
|
6506
|
+
/* A button living in an attachment focuses inside the clipped seal, so
|
|
6507
|
+
its halo wears the inset variant — the outward glow would be cut to
|
|
6508
|
+
ugly half-corners by the group's rounding. */
|
|
6509
|
+
[data-scope="input-group"][data-part="root"] [data-scope="button"][data-part="root"]:focus-visible {
|
|
6510
|
+
box-shadow: var(--bs-focus-ring-inset);
|
|
6511
|
+
}
|
|
6512
|
+
|
|
6513
|
+
/* An attachment cell: a recessed face between the reader's fixed words
|
|
6514
|
+
and the ink they type. Hairlines do the separating — leading cells
|
|
6515
|
+
part from the entry on the inline end, trailing on the inline start,
|
|
6516
|
+
so any root/addon order divides correctly. */
|
|
6517
|
+
[data-scope="input-group"][data-part="addon"] {
|
|
6518
|
+
display: inline-flex;
|
|
6519
|
+
flex: none;
|
|
6520
|
+
align-items: center;
|
|
6521
|
+
gap: var(--bs-gap-xs);
|
|
6522
|
+
padding: 0 var(--bs-padding-md);
|
|
6523
|
+
background: var(--bs-color-surface-inset);
|
|
6524
|
+
color: var(--bs-color-text-secondary);
|
|
6525
|
+
font-size: var(--bs-font-size-sm);
|
|
6526
|
+
white-space: nowrap;
|
|
6527
|
+
}
|
|
6528
|
+
|
|
6529
|
+
[data-scope="input-group"][data-part="addon"]:not(:first-child) {
|
|
6530
|
+
border-inline-start: 1px solid var(--bs-color-border);
|
|
6531
|
+
}
|
|
6532
|
+
|
|
6533
|
+
[data-scope="input-group"][data-part="addon"]:not(:last-child) {
|
|
6534
|
+
border-inline-end: 1px solid var(--bs-color-border);
|
|
6535
|
+
}
|
|
6536
|
+
`;
|
|
6537
|
+
//#endregion
|
|
6538
|
+
//#region src/styles/components/tree-view.ts
|
|
6539
|
+
const treeViewCss = labelCss("tree-view") + `
|
|
6540
|
+
[data-scope="tree-view"][data-part="root"] {
|
|
6541
|
+
/* The indent system: depth comes from the machine as --depth per node;
|
|
6542
|
+
every offset below derives from these three knobs. */
|
|
6543
|
+
--bs-tree-indent: 1rem;
|
|
6544
|
+
--bs-tree-icon: 1rem;
|
|
6545
|
+
--bs-tree-row-block: var(--bs-space-2);
|
|
6546
|
+
/* Full width is the component's own property, not the stage's stretch. */
|
|
6547
|
+
inline-size: 100%;
|
|
6548
|
+
display: flex;
|
|
6549
|
+
flex-direction: column;
|
|
6550
|
+
gap: var(--bs-space-2);
|
|
6551
|
+
}
|
|
6552
|
+
|
|
6553
|
+
[data-scope="tree-view"][data-part="tree"] {
|
|
6554
|
+
display: flex;
|
|
6555
|
+
flex-direction: column;
|
|
6556
|
+
color: var(--bs-color-text-primary);
|
|
6557
|
+
font-size: var(--bs-font-size-sm);
|
|
6558
|
+
}
|
|
6559
|
+
|
|
6560
|
+
/* Rows are quiet: no hairlines, no shadows — selection and hover are pure
|
|
6561
|
+
light on the paper. */
|
|
6562
|
+
[data-scope="tree-view"][data-part="branch-control"],
|
|
6563
|
+
[data-scope="tree-view"][data-part="item"] {
|
|
6564
|
+
position: relative;
|
|
6565
|
+
display: flex;
|
|
6566
|
+
align-items: center;
|
|
6567
|
+
gap: var(--bs-space-2);
|
|
6568
|
+
/* No page reset may be assumed: 100% must count the row's own padding. */
|
|
5061
6569
|
box-sizing: border-box;
|
|
5062
6570
|
inline-size: 100%;
|
|
5063
6571
|
padding-block: var(--bs-tree-row-block);
|
|
@@ -5290,6 +6798,154 @@ const kbdCss = `
|
|
|
5290
6798
|
}
|
|
5291
6799
|
`;
|
|
5292
6800
|
//#endregion
|
|
6801
|
+
//#region src/styles/components/layout.ts
|
|
6802
|
+
const layoutCss = `
|
|
6803
|
+
/* The application skeleton: a full-height grid that holds the header on
|
|
6804
|
+
top, the footer at the foot, and the flow between them. When a sider
|
|
6805
|
+
is declared a fixed rail joins the columns; the minmax(0, 1fr) — not
|
|
6806
|
+
a bare 1fr — keeps a wide child from stretching its track and
|
|
6807
|
+
shoving every sibling aside. */
|
|
6808
|
+
[data-scope="layout"][data-part="root"] {
|
|
6809
|
+
display: grid;
|
|
6810
|
+
min-block-size: 100dvh;
|
|
6811
|
+
grid-template-columns: minmax(0, 1fr);
|
|
6812
|
+
grid-template-rows: auto minmax(0, 1fr) auto;
|
|
6813
|
+
grid-template-areas:
|
|
6814
|
+
"header"
|
|
6815
|
+
"content"
|
|
6816
|
+
"footer";
|
|
6817
|
+
}
|
|
6818
|
+
|
|
6819
|
+
/* With a sider the rail owns one whole row span, so the header and the
|
|
6820
|
+
footer reach it only on the flow side. */
|
|
6821
|
+
[data-scope="layout"][data-part="root"][data-sider="start"] {
|
|
6822
|
+
grid-template-columns: auto minmax(0, 1fr);
|
|
6823
|
+
grid-template-areas:
|
|
6824
|
+
"sider header"
|
|
6825
|
+
"sider content"
|
|
6826
|
+
"sider footer";
|
|
6827
|
+
}
|
|
6828
|
+
|
|
6829
|
+
[data-scope="layout"][data-part="root"][data-sider="end"] {
|
|
6830
|
+
grid-template-columns: minmax(0, 1fr) auto;
|
|
6831
|
+
grid-template-areas:
|
|
6832
|
+
"header sider"
|
|
6833
|
+
"content sider"
|
|
6834
|
+
"footer sider";
|
|
6835
|
+
}
|
|
6836
|
+
|
|
6837
|
+
[data-scope="layout"][data-part="header"] {
|
|
6838
|
+
grid-area: header;
|
|
6839
|
+
padding: var(--bs-padding-md) var(--bs-padding-xl);
|
|
6840
|
+
border-block-end: 1px solid var(--bs-color-border);
|
|
6841
|
+
}
|
|
6842
|
+
|
|
6843
|
+
[data-scope="layout"][data-part="footer"] {
|
|
6844
|
+
grid-area: footer;
|
|
6845
|
+
padding: var(--bs-padding-md) var(--bs-padding-xl);
|
|
6846
|
+
border-block-start: 1px solid var(--bs-color-border);
|
|
6847
|
+
}
|
|
6848
|
+
|
|
6849
|
+
/* The rail: a panel on the first surface, separated from the flow by
|
|
6850
|
+
one hairline. The inline size rides the variable the wrapper writes —
|
|
6851
|
+
a layout parameter, not a visual token — so the collapse animates by
|
|
6852
|
+
re-pointing it, and the resizable rail's floor and ceiling clamp it
|
|
6853
|
+
between the caller's bounds. */
|
|
6854
|
+
[data-scope="layout"][data-part="sider"] {
|
|
6855
|
+
position: relative;
|
|
6856
|
+
grid-area: sider;
|
|
6857
|
+
inline-size: clamp(
|
|
6858
|
+
var(--bs-layout-sider-min, 12rem),
|
|
6859
|
+
var(--bs-layout-sider-width, 16rem),
|
|
6860
|
+
var(--bs-layout-sider-max, 24rem)
|
|
6861
|
+
);
|
|
6862
|
+
overflow: hidden;
|
|
6863
|
+
background: var(--bs-color-surface-1);
|
|
6864
|
+
border-inline-end: 1px solid var(--bs-color-border);
|
|
6865
|
+
transition: inline-size var(--bs-duration-slow) var(--bs-ease-out);
|
|
6866
|
+
}
|
|
6867
|
+
|
|
6868
|
+
/* The hand leads: while dragging, the rail follows the pointer without
|
|
6869
|
+
the easing catching up behind it. */
|
|
6870
|
+
[data-scope="layout"][data-part="sider"][data-dragging] {
|
|
6871
|
+
transition: none;
|
|
6872
|
+
}
|
|
6873
|
+
|
|
6874
|
+
/* The resize hairline: a generous hit strip at the flow edge whose ink
|
|
6875
|
+
answers to the hand — quiet until hovered, primary while gripped or
|
|
6876
|
+
keyed. It stays inside the rail, whose overflow clips anything that
|
|
6877
|
+
pokes out — the strip and its ink both live inboard of the border. */
|
|
6878
|
+
[data-scope="layout"][data-part="sider-resize"] {
|
|
6879
|
+
position: absolute;
|
|
6880
|
+
inset-block: 0;
|
|
6881
|
+
inset-inline-end: 0;
|
|
6882
|
+
inline-size: var(--bs-space-2);
|
|
6883
|
+
cursor: ew-resize;
|
|
6884
|
+
touch-action: none;
|
|
6885
|
+
}
|
|
6886
|
+
|
|
6887
|
+
[data-scope="layout"][data-part="sider-resize"]::before {
|
|
6888
|
+
content: "";
|
|
6889
|
+
position: absolute;
|
|
6890
|
+
inset-block: 0;
|
|
6891
|
+
inset-inline-end: calc(var(--bs-space-2) / 2);
|
|
6892
|
+
inline-size: 1px;
|
|
6893
|
+
background: var(--bs-color-border);
|
|
6894
|
+
transition: background-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
6895
|
+
}
|
|
6896
|
+
|
|
6897
|
+
[data-scope="layout"][data-part="sider-resize"]:hover::before,
|
|
6898
|
+
[data-scope="layout"][data-part="sider-resize"]:focus-visible::before,
|
|
6899
|
+
[data-scope="layout"][data-part="sider-resize"][data-dragging]::before {
|
|
6900
|
+
background: var(--bs-color-primary);
|
|
6901
|
+
}
|
|
6902
|
+
|
|
6903
|
+
[data-scope="layout"][data-part="sider-resize"]:focus-visible {
|
|
6904
|
+
outline: none;
|
|
6905
|
+
}
|
|
6906
|
+
|
|
6907
|
+
/* An end-side rail wears its handle on the other edge, and the pull
|
|
6908
|
+
toward the flow points the other way — the wrapper already mirrors
|
|
6909
|
+
the arithmetic. */
|
|
6910
|
+
[data-scope="layout"][data-part="root"][data-sider="end"]
|
|
6911
|
+
[data-scope="layout"][data-part="sider-resize"] {
|
|
6912
|
+
inset-inline-end: auto;
|
|
6913
|
+
inset-inline-start: 0;
|
|
6914
|
+
}
|
|
6915
|
+
|
|
6916
|
+
[data-scope="layout"][data-part="root"][data-sider="end"]
|
|
6917
|
+
[data-scope="layout"][data-part="sider-resize"]::before {
|
|
6918
|
+
inset-inline-end: auto;
|
|
6919
|
+
inset-inline-start: calc(var(--bs-space-2) / 2);
|
|
6920
|
+
}
|
|
6921
|
+
|
|
6922
|
+
/* The hairline always faces the flow, so an end sider wears it on its
|
|
6923
|
+
other edge. */
|
|
6924
|
+
[data-scope="layout"][data-part="root"][data-sider="end"]
|
|
6925
|
+
[data-scope="layout"][data-part="sider"] {
|
|
6926
|
+
border-inline-end: none;
|
|
6927
|
+
border-inline-start: 1px solid var(--bs-color-border);
|
|
6928
|
+
}
|
|
6929
|
+
|
|
6930
|
+
/* A resizable rail retires its own border: the resize hairline that
|
|
6931
|
+
rides the flow edge is the one line — the border would draw a second
|
|
6932
|
+
one beside it. */
|
|
6933
|
+
[data-scope="layout"][data-part="root"][data-sider="start"]
|
|
6934
|
+
[data-scope="layout"][data-part="sider"][data-resizable] {
|
|
6935
|
+
border-inline-end: none;
|
|
6936
|
+
}
|
|
6937
|
+
|
|
6938
|
+
[data-scope="layout"][data-part="root"][data-sider="end"]
|
|
6939
|
+
[data-scope="layout"][data-part="sider"][data-resizable] {
|
|
6940
|
+
border-inline-start: none;
|
|
6941
|
+
}
|
|
6942
|
+
|
|
6943
|
+
[data-scope="layout"][data-part="content"] {
|
|
6944
|
+
grid-area: content;
|
|
6945
|
+
padding: var(--bs-padding-xl);
|
|
6946
|
+
}
|
|
6947
|
+
`;
|
|
6948
|
+
//#endregion
|
|
5293
6949
|
//#region src/styles/components/link.ts
|
|
5294
6950
|
const linkCss = `
|
|
5295
6951
|
/* A link is ink in the accent's voice: quiet at rest, deepening under
|
|
@@ -5326,6 +6982,87 @@ const linkCss = `
|
|
|
5326
6982
|
}
|
|
5327
6983
|
`;
|
|
5328
6984
|
//#endregion
|
|
6985
|
+
//#region src/styles/components/list.ts
|
|
6986
|
+
const listCss = `
|
|
6987
|
+
/* A ledger of rows: Leading carries the mark, Content the title and
|
|
6988
|
+
its quiet echo, Actions the way out. The hairline between rows is
|
|
6989
|
+
the bordered variant's; the hover wash belongs to the interactive
|
|
6990
|
+
registers — a row that reads as clickable must answer the pointer. */
|
|
6991
|
+
[data-scope="list"][data-part="root"] {
|
|
6992
|
+
display: flex;
|
|
6993
|
+
flex-direction: column;
|
|
6994
|
+
margin: 0;
|
|
6995
|
+
padding: 0;
|
|
6996
|
+
list-style: none;
|
|
6997
|
+
}
|
|
6998
|
+
|
|
6999
|
+
[data-scope="list"][data-part="item"] {
|
|
7000
|
+
display: flex;
|
|
7001
|
+
align-items: center;
|
|
7002
|
+
gap: var(--bs-gap-sm);
|
|
7003
|
+
padding: var(--bs-padding-sm) var(--bs-padding-md);
|
|
7004
|
+
transition: background-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
7005
|
+
}
|
|
7006
|
+
|
|
7007
|
+
/* The bordered variant draws one hairline between rows — never before
|
|
7008
|
+
the first, so the ledger starts clean. */
|
|
7009
|
+
[data-scope="list"][data-part="root"][data-bordered]
|
|
7010
|
+
[data-scope="list"][data-part="item"]
|
|
7011
|
+
+ [data-scope="list"][data-part="item"] {
|
|
7012
|
+
border-block-start: 1px solid var(--bs-color-border);
|
|
7013
|
+
}
|
|
7014
|
+
|
|
7015
|
+
/* A row the caller made clickable (role="button") owns the pointer and
|
|
7016
|
+
the hover wash; focus rides the inset halo, since the row is the
|
|
7017
|
+
full bleed of its container. */
|
|
7018
|
+
[data-scope="list"][data-part="item"][role="button"] {
|
|
7019
|
+
cursor: pointer;
|
|
7020
|
+
}
|
|
7021
|
+
|
|
7022
|
+
[data-scope="list"][data-part="root"][data-hoverable] [data-scope="list"][data-part="item"]:hover,
|
|
7023
|
+
[data-scope="list"][data-part="item"][role="button"]:hover {
|
|
7024
|
+
background: var(--bs-color-surface-0);
|
|
7025
|
+
}
|
|
7026
|
+
|
|
7027
|
+
[data-scope="list"][data-part="item"]:focus-visible {
|
|
7028
|
+
outline: none;
|
|
7029
|
+
box-shadow: var(--bs-focus-ring-inset);
|
|
7030
|
+
}
|
|
7031
|
+
|
|
7032
|
+
[data-scope="list"][data-part="leading"] {
|
|
7033
|
+
display: flex;
|
|
7034
|
+
flex: none;
|
|
7035
|
+
align-items: center;
|
|
7036
|
+
}
|
|
7037
|
+
|
|
7038
|
+
[data-scope="list"][data-part="content"] {
|
|
7039
|
+
display: flex;
|
|
7040
|
+
flex: 1;
|
|
7041
|
+
flex-direction: column;
|
|
7042
|
+
gap: var(--bs-space-1);
|
|
7043
|
+
min-inline-size: 0;
|
|
7044
|
+
}
|
|
7045
|
+
|
|
7046
|
+
[data-scope="list"][data-part="title"] {
|
|
7047
|
+
color: var(--bs-color-text-primary);
|
|
7048
|
+
font-weight: var(--bs-font-weight-medium);
|
|
7049
|
+
}
|
|
7050
|
+
|
|
7051
|
+
[data-scope="list"][data-part="description"] {
|
|
7052
|
+
color: var(--bs-color-text-secondary);
|
|
7053
|
+
font-size: var(--bs-font-size-sm);
|
|
7054
|
+
line-height: var(--bs-line-height-relaxed);
|
|
7055
|
+
}
|
|
7056
|
+
|
|
7057
|
+
[data-scope="list"][data-part="actions"] {
|
|
7058
|
+
display: flex;
|
|
7059
|
+
flex: none;
|
|
7060
|
+
align-items: center;
|
|
7061
|
+
gap: var(--bs-space-2);
|
|
7062
|
+
margin-inline-start: auto;
|
|
7063
|
+
}
|
|
7064
|
+
`;
|
|
7065
|
+
//#endregion
|
|
5329
7066
|
//#region src/styles/components/listbox.ts
|
|
5330
7067
|
const listboxCss = labelCss("listbox") + popupContentCss("listbox", "16rem") + `
|
|
5331
7068
|
[data-scope="listbox"][data-part="root"] {
|
|
@@ -5594,6 +7331,116 @@ const marqueeCss = `
|
|
|
5594
7331
|
}
|
|
5595
7332
|
`;
|
|
5596
7333
|
//#endregion
|
|
7334
|
+
//#region src/styles/components/masonry.ts
|
|
7335
|
+
const masonryCss = `
|
|
7336
|
+
/* The wall of uneven heights, cut by the browser's multi-column
|
|
7337
|
+
layout. Filling runs down each column before crossing to the next —
|
|
7338
|
+
the order is column-first; a row-flow wall needs grid masonry, which
|
|
7339
|
+
browsers do not ship yet. */
|
|
7340
|
+
[data-scope="masonry"][data-part="root"] {
|
|
7341
|
+
column-count: var(--bs-masonry-columns, 3);
|
|
7342
|
+
column-gap: var(--bs-masonry-gap, var(--bs-space-3));
|
|
7343
|
+
}
|
|
7344
|
+
|
|
7345
|
+
/* Each stone stays whole — never split across two columns — and the
|
|
7346
|
+
gap below it holds the next stone of the column at the named
|
|
7347
|
+
distance. */
|
|
7348
|
+
[data-scope="masonry"][data-part="root"] > * {
|
|
7349
|
+
break-inside: avoid;
|
|
7350
|
+
margin-block-end: var(--bs-masonry-gap, var(--bs-space-3));
|
|
7351
|
+
}
|
|
7352
|
+
`;
|
|
7353
|
+
//#endregion
|
|
7354
|
+
//#region src/styles/components/mentions.ts
|
|
7355
|
+
const mentionsCss = `
|
|
7356
|
+
/* The field: a textarea in the standard field recipe — border + surface
|
|
7357
|
+
+ focus halo, never a shadow lift. */
|
|
7358
|
+
[data-scope="mentions"][data-part="root"] {
|
|
7359
|
+
display: flex;
|
|
7360
|
+
}
|
|
7361
|
+
|
|
7362
|
+
[data-scope="mentions"][data-part="textarea"] {
|
|
7363
|
+
box-sizing: border-box;
|
|
7364
|
+
flex: 1;
|
|
7365
|
+
min-inline-size: 0;
|
|
7366
|
+
min-block-size: calc(var(--bs-control-height-md) + var(--bs-space-4));
|
|
7367
|
+
padding: var(--bs-space-2) var(--bs-padding-md);
|
|
7368
|
+
border: 1px solid var(--bs-color-border);
|
|
7369
|
+
border-radius: var(--bs-radius-sm);
|
|
7370
|
+
background: var(--bs-color-surface-2);
|
|
7371
|
+
color: var(--bs-color-text-primary);
|
|
7372
|
+
font: inherit;
|
|
7373
|
+
font-size: var(--bs-font-size-md);
|
|
7374
|
+
line-height: var(--bs-line-height-relaxed);
|
|
7375
|
+
resize: vertical;
|
|
7376
|
+
transition: border-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
7377
|
+
}
|
|
7378
|
+
|
|
7379
|
+
[data-scope="mentions"][data-part="textarea"]::placeholder {
|
|
7380
|
+
color: var(--bs-color-text-tertiary);
|
|
7381
|
+
}
|
|
7382
|
+
|
|
7383
|
+
[data-scope="mentions"][data-part="textarea"]:hover:not([disabled], [readonly]) {
|
|
7384
|
+
border-color: var(--bs-color-border-strong);
|
|
7385
|
+
}
|
|
7386
|
+
|
|
7387
|
+
[data-scope="mentions"][data-part="textarea"]:focus,
|
|
7388
|
+
[data-scope="mentions"][data-part="textarea"]:focus-visible {
|
|
7389
|
+
outline: none;
|
|
7390
|
+
border-color: var(--bs-color-primary);
|
|
7391
|
+
box-shadow: var(--bs-focus-ring);
|
|
7392
|
+
}
|
|
7393
|
+
|
|
7394
|
+
[data-scope="mentions"][data-part="textarea"][disabled] {
|
|
7395
|
+
border-color: var(--bs-color-border);
|
|
7396
|
+
background: var(--bs-color-surface-inset);
|
|
7397
|
+
color: var(--bs-color-text-disabled);
|
|
7398
|
+
cursor: not-allowed;
|
|
7399
|
+
}
|
|
7400
|
+
|
|
7401
|
+
/* The candidate vessel: the popup recipe — paper, one hairline,
|
|
7402
|
+
elevation 3 — riding the popover positioner's shared ladder. */
|
|
7403
|
+
[data-scope="mentions"][data-part="popup"] {
|
|
7404
|
+
box-sizing: border-box;
|
|
7405
|
+
min-inline-size: 10rem;
|
|
7406
|
+
max-block-size: 14rem;
|
|
7407
|
+
display: flex;
|
|
7408
|
+
flex-direction: column;
|
|
7409
|
+
padding: var(--bs-space-1);
|
|
7410
|
+
border: 1px solid var(--bs-color-border);
|
|
7411
|
+
border-radius: var(--bs-radius-lg);
|
|
7412
|
+
background: var(--bs-color-surface-2);
|
|
7413
|
+
color: var(--bs-color-text-primary);
|
|
7414
|
+
box-shadow: var(--bs-elevation-3);
|
|
7415
|
+
overflow-y: auto;
|
|
7416
|
+
outline: none;
|
|
7417
|
+
}
|
|
7418
|
+
|
|
7419
|
+
[data-scope="mentions"][data-state="open"][data-part="popup"] {
|
|
7420
|
+
animation: bs-ink-in var(--bs-duration-base) var(--bs-ease-out);
|
|
7421
|
+
}
|
|
7422
|
+
|
|
7423
|
+
/* Options are rows of light like every list: hover is the machine's
|
|
7424
|
+
highlight, the keyboard's row is the active one — and the two are the
|
|
7425
|
+
same stroke, so pointer and arrows never disagree. */
|
|
7426
|
+
[data-scope="mentions"][data-part="option"] {
|
|
7427
|
+
display: flex;
|
|
7428
|
+
align-items: center;
|
|
7429
|
+
gap: var(--bs-space-2);
|
|
7430
|
+
min-block-size: var(--bs-control-height-sm);
|
|
7431
|
+
padding: 0 var(--bs-padding-sm);
|
|
7432
|
+
border-radius: var(--bs-radius-sm);
|
|
7433
|
+
font-size: var(--bs-font-size-sm);
|
|
7434
|
+
cursor: pointer;
|
|
7435
|
+
user-select: none;
|
|
7436
|
+
transition: background-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
7437
|
+
}
|
|
7438
|
+
|
|
7439
|
+
[data-scope="mentions"][data-part="option"][data-active] {
|
|
7440
|
+
background: var(--bs-color-surface-0);
|
|
7441
|
+
}
|
|
7442
|
+
`;
|
|
7443
|
+
//#endregion
|
|
5597
7444
|
//#region src/styles/components/menu.ts
|
|
5598
7445
|
const menuCss = positionerCss("menu") + popupContentCss("menu", "12rem") + `
|
|
5599
7446
|
[data-scope="menu"][data-part="content"] {
|
|
@@ -5795,6 +7642,66 @@ const menuCss = positionerCss("menu") + popupContentCss("menu", "12rem") + `
|
|
|
5795
7642
|
}
|
|
5796
7643
|
`;
|
|
5797
7644
|
//#endregion
|
|
7645
|
+
//#region src/styles/components/menubar.ts
|
|
7646
|
+
const menubarCss = `
|
|
7647
|
+
/* The bar: one hairline of rest under a row of quiet triggers. */
|
|
7648
|
+
[data-scope="menubar"][data-part="root"] {
|
|
7649
|
+
display: flex;
|
|
7650
|
+
align-items: center;
|
|
7651
|
+
gap: var(--bs-space-1);
|
|
7652
|
+
padding: var(--bs-space-1) 0;
|
|
7653
|
+
border-block-end: 1px solid var(--bs-color-border);
|
|
7654
|
+
}
|
|
7655
|
+
|
|
7656
|
+
/* The triggers are ghost buttons — terrain, not controls: no fill, no
|
|
7657
|
+
hairline of their own, the bar's hairline doing the framing. */
|
|
7658
|
+
[data-scope="menubar"][data-part="trigger"] {
|
|
7659
|
+
display: inline-flex;
|
|
7660
|
+
align-items: center;
|
|
7661
|
+
block-size: var(--bs-control-height-sm);
|
|
7662
|
+
padding: 0 var(--bs-padding-sm);
|
|
7663
|
+
border: none;
|
|
7664
|
+
border-radius: var(--bs-radius-sm);
|
|
7665
|
+
background: transparent;
|
|
7666
|
+
color: var(--bs-color-text-secondary);
|
|
7667
|
+
font: inherit;
|
|
7668
|
+
font-size: var(--bs-font-size-sm);
|
|
7669
|
+
letter-spacing: var(--bs-tracking-label);
|
|
7670
|
+
white-space: nowrap;
|
|
7671
|
+
cursor: pointer;
|
|
7672
|
+
user-select: none;
|
|
7673
|
+
transition:
|
|
7674
|
+
background-color var(--bs-duration-fast) var(--bs-ease-out),
|
|
7675
|
+
color var(--bs-duration-fast) var(--bs-ease-out);
|
|
7676
|
+
}
|
|
7677
|
+
|
|
7678
|
+
[data-scope="menubar"][data-part="trigger"]:hover {
|
|
7679
|
+
background: var(--bs-color-surface-0);
|
|
7680
|
+
color: var(--bs-color-text-primary);
|
|
7681
|
+
}
|
|
7682
|
+
|
|
7683
|
+
/* Open keeps the focus look: the machine hands focus into the menu, so
|
|
7684
|
+
:focus-visible alone would drop the halo the moment it opens. */
|
|
7685
|
+
[data-scope="menubar"][data-part="trigger"]:focus-visible,
|
|
7686
|
+
[data-scope="menubar"][data-part="trigger"][data-state="open"] {
|
|
7687
|
+
outline: none;
|
|
7688
|
+
background: var(--bs-color-surface-0);
|
|
7689
|
+
color: var(--bs-color-text-primary);
|
|
7690
|
+
box-shadow: var(--bs-focus-ring);
|
|
7691
|
+
}
|
|
7692
|
+
|
|
7693
|
+
/* The popup keeps the menu parts and the menu stylesheet; only the
|
|
7694
|
+
danger rows ride this scope's knowledge of the bar's callers. */
|
|
7695
|
+
[data-scope="menu"][data-part="item"][data-danger] {
|
|
7696
|
+
color: var(--bs-color-danger);
|
|
7697
|
+
}
|
|
7698
|
+
|
|
7699
|
+
[data-scope="menu"][data-part="item"][data-danger][data-state="checked"] {
|
|
7700
|
+
background: var(--bs-color-danger);
|
|
7701
|
+
color: var(--bs-color-ink-on-fill);
|
|
7702
|
+
}
|
|
7703
|
+
`;
|
|
7704
|
+
//#endregion
|
|
5798
7705
|
//#region src/styles/components/meter.ts
|
|
5799
7706
|
const meterCss = `
|
|
5800
7707
|
/* A measure in the world, not a task in flight: how much of the toner
|
|
@@ -5838,70 +7745,17 @@ const meterCss = `
|
|
|
5838
7745
|
overflow: hidden;
|
|
5839
7746
|
block-size: var(--bs-space-1);
|
|
5840
7747
|
border-radius: var(--bs-radius-sm);
|
|
5841
|
-
background: var(--bs-color-surface-0);
|
|
5842
|
-
}
|
|
5843
|
-
|
|
5844
|
-
[data-scope="meter"][data-part="range"] {
|
|
5845
|
-
/* The fill reads the root's declared share of the scale. */
|
|
5846
|
-
display: block;
|
|
5847
|
-
inline-size: var(--_percent, 0%);
|
|
5848
|
-
block-size: 100%;
|
|
5849
|
-
border-radius: inherit;
|
|
5850
|
-
background: var(--_pigment);
|
|
5851
|
-
transition: inline-size var(--bs-duration-slow) var(--bs-ease-out);
|
|
5852
|
-
}
|
|
5853
|
-
`;
|
|
5854
|
-
//#endregion
|
|
5855
|
-
//#region src/styles/components/typography.ts
|
|
5856
|
-
const typographyCss = `
|
|
5857
|
-
/* The typographic voices, named so prose can ask for one: display and
|
|
5858
|
-
heading ride the song-serif, the rest ride the hei. Nothing here is
|
|
5859
|
-
decorative — hierarchy is size, weight, and space. */
|
|
5860
|
-
[data-scope="typography"][data-part="display"] {
|
|
5861
|
-
margin: 0;
|
|
5862
|
-
color: var(--bs-color-text-primary);
|
|
5863
|
-
font-family: var(--bs-font-serif);
|
|
5864
|
-
font-size: var(--bs-font-size-4xl);
|
|
5865
|
-
font-weight: var(--bs-font-weight-semibold);
|
|
5866
|
-
line-height: var(--bs-line-height-tight);
|
|
5867
|
-
}
|
|
5868
|
-
|
|
5869
|
-
[data-scope="typography"][data-part="heading"] {
|
|
5870
|
-
margin: 0;
|
|
5871
|
-
color: var(--bs-color-text-primary);
|
|
5872
|
-
font-family: var(--bs-font-serif);
|
|
5873
|
-
font-size: var(--bs-font-size-2xl);
|
|
5874
|
-
font-weight: var(--bs-font-weight-semibold);
|
|
5875
|
-
line-height: var(--bs-line-height-snug);
|
|
5876
|
-
}
|
|
5877
|
-
|
|
5878
|
-
[data-scope="typography"][data-part="lead"] {
|
|
5879
|
-
margin: 0;
|
|
5880
|
-
color: var(--bs-color-text-secondary);
|
|
5881
|
-
font-size: var(--bs-font-size-lg);
|
|
5882
|
-
line-height: var(--bs-line-height-relaxed);
|
|
5883
|
-
}
|
|
5884
|
-
|
|
5885
|
-
[data-scope="typography"][data-part="body"] {
|
|
5886
|
-
margin: 0;
|
|
5887
|
-
color: var(--bs-color-text-secondary);
|
|
5888
|
-
font-size: var(--bs-font-size-base);
|
|
5889
|
-
line-height: var(--bs-line-height-relaxed);
|
|
5890
|
-
}
|
|
5891
|
-
|
|
5892
|
-
[data-scope="typography"][data-part="muted"] {
|
|
5893
|
-
margin: 0;
|
|
5894
|
-
color: var(--bs-color-text-tertiary);
|
|
5895
|
-
font-size: var(--bs-font-size-sm);
|
|
5896
|
-
line-height: var(--bs-line-height-relaxed);
|
|
7748
|
+
background: var(--bs-color-surface-0);
|
|
5897
7749
|
}
|
|
5898
7750
|
|
|
5899
|
-
[data-scope="
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
5903
|
-
|
|
5904
|
-
|
|
7751
|
+
[data-scope="meter"][data-part="range"] {
|
|
7752
|
+
/* The fill reads the root's declared share of the scale. */
|
|
7753
|
+
display: block;
|
|
7754
|
+
inline-size: var(--_percent, 0%);
|
|
7755
|
+
block-size: 100%;
|
|
7756
|
+
border-radius: inherit;
|
|
7757
|
+
background: var(--_pigment);
|
|
7758
|
+
transition: inline-size var(--bs-duration-slow) var(--bs-ease-out);
|
|
5905
7759
|
}
|
|
5906
7760
|
`;
|
|
5907
7761
|
//#endregion
|
|
@@ -6580,6 +8434,31 @@ const pinInputCss = labelCss("pin-input") + `
|
|
|
6580
8434
|
}
|
|
6581
8435
|
`;
|
|
6582
8436
|
//#endregion
|
|
8437
|
+
//#region src/styles/components/popconfirm.ts
|
|
8438
|
+
const popconfirmCss = `
|
|
8439
|
+
/* The popconfirm rides the popover vessel for its paper, hairline and
|
|
8440
|
+
elevation; these rules only lay out the question and its answers.
|
|
8441
|
+
The extra class out-specifies any part-level popover padding so the
|
|
8442
|
+
panel reads as one tight question, not a floating card. */
|
|
8443
|
+
.bs-popconfirm {
|
|
8444
|
+
max-inline-size: 18rem;
|
|
8445
|
+
padding: var(--bs-padding-md);
|
|
8446
|
+
}
|
|
8447
|
+
|
|
8448
|
+
.bs-popconfirm [data-part="message"] {
|
|
8449
|
+
margin: 0 0 var(--bs-space-3);
|
|
8450
|
+
color: var(--bs-color-text-primary);
|
|
8451
|
+
font-size: var(--bs-font-size-sm);
|
|
8452
|
+
line-height: var(--bs-line-height-relaxed);
|
|
8453
|
+
}
|
|
8454
|
+
|
|
8455
|
+
.bs-popconfirm [data-part="actions"] {
|
|
8456
|
+
display: flex;
|
|
8457
|
+
justify-content: flex-end;
|
|
8458
|
+
gap: var(--bs-space-2);
|
|
8459
|
+
}
|
|
8460
|
+
`;
|
|
8461
|
+
//#endregion
|
|
6583
8462
|
//#region src/styles/components/popover.ts
|
|
6584
8463
|
const popoverCss = positionerCss("popover") + popupContentCss("popover", "20rem") + `
|
|
6585
8464
|
[data-scope="popover"][data-part="content"] {
|
|
@@ -6735,14 +8614,16 @@ const progressCss = labelCss("progress") + `
|
|
|
6735
8614
|
text-align: end;
|
|
6736
8615
|
}
|
|
6737
8616
|
|
|
6738
|
-
/* The track is a
|
|
6739
|
-
|
|
8617
|
+
/* The track is a groove pressed into the paper — ink will run through it,
|
|
8618
|
+
so it stays quiet until the fill arrives. It sits one mix-step below the
|
|
8619
|
+
ground it is drawn on (the ground itself), or the groove reads as
|
|
8620
|
+
nothing; the pressed depth keeps it visible like M3's tone-based track. */
|
|
6740
8621
|
[data-scope="progress"][data-part="track"] {
|
|
6741
8622
|
grid-column: 1 / -1;
|
|
6742
8623
|
overflow: hidden;
|
|
6743
8624
|
block-size: var(--bs-space-1);
|
|
6744
8625
|
border-radius: var(--bs-radius-sm);
|
|
6745
|
-
background: var(--bs-color-surface-0);
|
|
8626
|
+
background: color-mix(in oklab, var(--bs-color-surface-0) 96%, black);
|
|
6746
8627
|
}
|
|
6747
8628
|
|
|
6748
8629
|
[data-scope="progress"][data-part="track"][data-orientation="vertical"] {
|
|
@@ -6809,7 +8690,7 @@ const progressCss = labelCss("progress") + `
|
|
|
6809
8690
|
}
|
|
6810
8691
|
|
|
6811
8692
|
[data-scope="progress"][data-part="circle-track"] {
|
|
6812
|
-
stroke: var(--bs-color-surface-0);
|
|
8693
|
+
stroke: color-mix(in oklab, var(--bs-color-surface-0) 92%, black);
|
|
6813
8694
|
}
|
|
6814
8695
|
|
|
6815
8696
|
[data-scope="progress"][data-part="circle-range"] {
|
|
@@ -6838,6 +8719,83 @@ const progressCss = labelCss("progress") + `
|
|
|
6838
8719
|
}
|
|
6839
8720
|
`;
|
|
6840
8721
|
//#endregion
|
|
8722
|
+
//#region src/styles/components/progress-group.ts
|
|
8723
|
+
const progressGroupCss = `
|
|
8724
|
+
/* One bar, several verdicts: the track lays the segments shoulder to
|
|
8725
|
+
shoulder, each speaking its own pigment (the badge's --_pigment
|
|
8726
|
+
mode), and the legend reads them back beneath. */
|
|
8727
|
+
[data-scope="progress-group"][data-part="root"] {
|
|
8728
|
+
display: flex;
|
|
8729
|
+
flex-direction: column;
|
|
8730
|
+
gap: var(--bs-space-2);
|
|
8731
|
+
inline-size: 100%;
|
|
8732
|
+
font-size: var(--bs-font-size-sm);
|
|
8733
|
+
}
|
|
8734
|
+
|
|
8735
|
+
[data-scope="progress-group"][data-part="track"] {
|
|
8736
|
+
display: flex;
|
|
8737
|
+
overflow: hidden;
|
|
8738
|
+
block-size: var(--bs-space-2);
|
|
8739
|
+
border-radius: var(--bs-radius-xs);
|
|
8740
|
+
background: var(--bs-color-surface-inset);
|
|
8741
|
+
}
|
|
8742
|
+
|
|
8743
|
+
:is([data-scope="progress-group"][data-part="segment"], [data-scope="progress-group"][data-part="legend-item"]) {
|
|
8744
|
+
--_pigment: var(--bs-color-primary);
|
|
8745
|
+
}
|
|
8746
|
+
|
|
8747
|
+
:is([data-scope="progress-group"][data-part="segment"], [data-scope="progress-group"][data-part="legend-item"])[data-pigment="success"] {
|
|
8748
|
+
--_pigment: var(--bs-color-success);
|
|
8749
|
+
}
|
|
8750
|
+
|
|
8751
|
+
:is([data-scope="progress-group"][data-part="segment"], [data-scope="progress-group"][data-part="legend-item"])[data-pigment="warning"] {
|
|
8752
|
+
--_pigment: var(--bs-color-warning);
|
|
8753
|
+
}
|
|
8754
|
+
|
|
8755
|
+
:is([data-scope="progress-group"][data-part="segment"], [data-scope="progress-group"][data-part="legend-item"])[data-pigment="danger"] {
|
|
8756
|
+
--_pigment: var(--bs-color-danger);
|
|
8757
|
+
}
|
|
8758
|
+
|
|
8759
|
+
:is([data-scope="progress-group"][data-part="segment"], [data-scope="progress-group"][data-part="legend-item"])[data-pigment="info"] {
|
|
8760
|
+
--_pigment: var(--bs-color-info);
|
|
8761
|
+
}
|
|
8762
|
+
|
|
8763
|
+
[data-scope="progress-group"][data-part="segment"] {
|
|
8764
|
+
overflow: hidden;
|
|
8765
|
+
background: var(--_pigment);
|
|
8766
|
+
/* The fill flows at the measure's pace — width trails the data like
|
|
8767
|
+
the single bar's does. The track's rounded mask rounds the ends;
|
|
8768
|
+
the segments themselves stay square so the bar reads as one. */
|
|
8769
|
+
transition: inline-size var(--bs-duration-slow) var(--bs-ease-out);
|
|
8770
|
+
}
|
|
8771
|
+
|
|
8772
|
+
[data-scope="progress-group"][data-part="legend"] {
|
|
8773
|
+
display: flex;
|
|
8774
|
+
flex-wrap: wrap;
|
|
8775
|
+
gap: var(--bs-space-2) var(--bs-gap-md);
|
|
8776
|
+
color: var(--bs-color-text-secondary);
|
|
8777
|
+
}
|
|
8778
|
+
|
|
8779
|
+
[data-scope="progress-group"][data-part="legend-item"] {
|
|
8780
|
+
display: inline-flex;
|
|
8781
|
+
align-items: center;
|
|
8782
|
+
gap: var(--bs-space-2);
|
|
8783
|
+
}
|
|
8784
|
+
|
|
8785
|
+
[data-scope="progress-group"][data-part="swatch"] {
|
|
8786
|
+
flex: none;
|
|
8787
|
+
inline-size: var(--bs-space-2);
|
|
8788
|
+
block-size: var(--bs-space-2);
|
|
8789
|
+
border-radius: var(--bs-radius-xs);
|
|
8790
|
+
background: var(--_pigment);
|
|
8791
|
+
}
|
|
8792
|
+
|
|
8793
|
+
[data-scope="progress-group"][data-part="legend-value"] {
|
|
8794
|
+
color: var(--bs-color-text-primary);
|
|
8795
|
+
font-variant-numeric: tabular-nums;
|
|
8796
|
+
}
|
|
8797
|
+
`;
|
|
8798
|
+
//#endregion
|
|
6841
8799
|
//#region src/styles/components/qr-code.ts
|
|
6842
8800
|
const qrCodeCss = `
|
|
6843
8801
|
[data-scope="qr-code"][data-part="root"] {
|
|
@@ -6959,8 +8917,8 @@ const radioGroupCss = labelCss("radio-group") + `
|
|
|
6959
8917
|
align-items: center;
|
|
6960
8918
|
justify-content: center;
|
|
6961
8919
|
flex-shrink: 0;
|
|
6962
|
-
inline-size: var(--bs-part-size-
|
|
6963
|
-
block-size: var(--bs-part-size-
|
|
8920
|
+
inline-size: var(--bs-part-size-sm);
|
|
8921
|
+
block-size: var(--bs-part-size-sm);
|
|
6964
8922
|
border: 1px solid var(--bs-color-border);
|
|
6965
8923
|
border-radius: var(--bs-radius-full);
|
|
6966
8924
|
background: var(--bs-color-surface-2);
|
|
@@ -6989,8 +8947,8 @@ const radioGroupCss = labelCss("radio-group") + `
|
|
|
6989
8947
|
|
|
6990
8948
|
[data-scope="radio-group"][data-part="item-control"][data-state="checked"]::before {
|
|
6991
8949
|
content: "";
|
|
6992
|
-
inline-size: calc(var(--bs-part-size-
|
|
6993
|
-
block-size: calc(var(--bs-part-size-
|
|
8950
|
+
inline-size: calc(var(--bs-part-size-sm) * 0.5);
|
|
8951
|
+
block-size: calc(var(--bs-part-size-sm) * 0.5);
|
|
6994
8952
|
border-radius: var(--bs-radius-full);
|
|
6995
8953
|
background: var(--bs-color-primary-text);
|
|
6996
8954
|
}
|
|
@@ -7019,8 +8977,8 @@ const radioGroupCss = labelCss("radio-group") + `
|
|
|
7019
8977
|
the spring — position comes from the machine. */
|
|
7020
8978
|
[data-scope="radio-group"][data-part="indicator"] {
|
|
7021
8979
|
position: absolute;
|
|
7022
|
-
inline-size: var(--bs-part-size-
|
|
7023
|
-
block-size: var(--bs-part-size-
|
|
8980
|
+
inline-size: var(--bs-part-size-sm);
|
|
8981
|
+
block-size: var(--bs-part-size-sm);
|
|
7024
8982
|
border-radius: var(--bs-radius-full);
|
|
7025
8983
|
background: var(--bs-color-primary);
|
|
7026
8984
|
transition:
|
|
@@ -7332,6 +9290,7 @@ const selectCss = labelCss("select") + positionerCss("select") + popupContentCss
|
|
|
7332
9290
|
/* The control is the field: the recipe's border, surface and focus halo
|
|
7333
9291
|
ride on it, with the trigger and its passengers sitting inside. */
|
|
7334
9292
|
[data-scope="select"][data-part="control"] {
|
|
9293
|
+
box-sizing: border-box;
|
|
7335
9294
|
display: flex;
|
|
7336
9295
|
align-items: center;
|
|
7337
9296
|
gap: var(--bs-space-1);
|
|
@@ -7714,104 +9673,6 @@ const skeletonCss = `
|
|
|
7714
9673
|
}
|
|
7715
9674
|
`;
|
|
7716
9675
|
//#endregion
|
|
7717
|
-
//#region src/styles/components/spinner.ts
|
|
7718
|
-
const spinnerCss = `
|
|
7719
|
-
/* A wheel of waiting: one arc of ink turning about its center. Quiet by
|
|
7720
|
-
default — it reports progress without claiming attention. */
|
|
7721
|
-
[data-scope="spinner"][data-part="root"] {
|
|
7722
|
-
display: inline-flex;
|
|
7723
|
-
flex: none;
|
|
7724
|
-
color: var(--bs-color-text-tertiary);
|
|
7725
|
-
animation: bs-spinner-turn 0.9s linear infinite;
|
|
7726
|
-
}
|
|
7727
|
-
|
|
7728
|
-
[data-scope="spinner"][data-part="root"][data-size="sm"] {
|
|
7729
|
-
inline-size: var(--bs-part-size-sm);
|
|
7730
|
-
block-size: var(--bs-part-size-sm);
|
|
7731
|
-
}
|
|
7732
|
-
[data-scope="spinner"][data-part="root"][data-size="md"] {
|
|
7733
|
-
inline-size: var(--bs-part-size-md);
|
|
7734
|
-
block-size: var(--bs-part-size-md);
|
|
7735
|
-
}
|
|
7736
|
-
[data-scope="spinner"][data-part="root"][data-size="lg"] {
|
|
7737
|
-
inline-size: var(--bs-part-size-lg);
|
|
7738
|
-
block-size: var(--bs-part-size-lg);
|
|
7739
|
-
}
|
|
7740
|
-
|
|
7741
|
-
[data-scope="spinner"][data-part="root"] svg {
|
|
7742
|
-
inline-size: 100%;
|
|
7743
|
-
block-size: 100%;
|
|
7744
|
-
}
|
|
7745
|
-
|
|
7746
|
-
@keyframes bs-spinner-turn {
|
|
7747
|
-
to {
|
|
7748
|
-
transform: rotate(1turn);
|
|
7749
|
-
}
|
|
7750
|
-
}
|
|
7751
|
-
|
|
7752
|
-
@media (prefers-reduced-motion: reduce) {
|
|
7753
|
-
[data-scope="spinner"][data-part="root"] {
|
|
7754
|
-
animation-duration: 1ms;
|
|
7755
|
-
animation-iteration-count: 1;
|
|
7756
|
-
}
|
|
7757
|
-
}
|
|
7758
|
-
`;
|
|
7759
|
-
//#endregion
|
|
7760
|
-
//#region src/styles/components/stat.ts
|
|
7761
|
-
const statCss = `
|
|
7762
|
-
/* One figure on the page: the label whispers what it is, the value
|
|
7763
|
-
states it plainly in tabular figures, the delta reads the direction
|
|
7764
|
-
in the fixed semantic pigments. */
|
|
7765
|
-
[data-scope="stat"][data-part="root"] {
|
|
7766
|
-
display: flex;
|
|
7767
|
-
flex-direction: column;
|
|
7768
|
-
gap: var(--bs-space-1);
|
|
7769
|
-
}
|
|
7770
|
-
|
|
7771
|
-
[data-scope="stat"][data-part="label"] {
|
|
7772
|
-
margin: 0;
|
|
7773
|
-
color: var(--bs-color-text-secondary);
|
|
7774
|
-
font-size: var(--bs-font-size-sm);
|
|
7775
|
-
font-weight: var(--bs-font-weight-medium);
|
|
7776
|
-
letter-spacing: var(--bs-tracking-label);
|
|
7777
|
-
}
|
|
7778
|
-
|
|
7779
|
-
/* The value carries the ink: large, semibold, tabular so figures
|
|
7780
|
-
align across a row of stats. */
|
|
7781
|
-
[data-scope="stat"][data-part="value"] {
|
|
7782
|
-
color: var(--bs-color-text-primary);
|
|
7783
|
-
font-size: var(--bs-font-size-3xl);
|
|
7784
|
-
font-weight: var(--bs-font-weight-semibold);
|
|
7785
|
-
font-variant-numeric: tabular-nums;
|
|
7786
|
-
line-height: var(--bs-line-height-tight);
|
|
7787
|
-
}
|
|
7788
|
-
|
|
7789
|
-
[data-scope="stat"][data-part="delta"] {
|
|
7790
|
-
display: inline-flex;
|
|
7791
|
-
align-items: center;
|
|
7792
|
-
gap: var(--bs-space-1);
|
|
7793
|
-
color: var(--bs-color-text-tertiary);
|
|
7794
|
-
font-size: var(--bs-font-size-sm);
|
|
7795
|
-
font-weight: var(--bs-font-weight-medium);
|
|
7796
|
-
font-variant-numeric: tabular-nums;
|
|
7797
|
-
}
|
|
7798
|
-
|
|
7799
|
-
[data-scope="stat"][data-part="delta"][data-direction="up"] {
|
|
7800
|
-
color: var(--bs-color-success);
|
|
7801
|
-
}
|
|
7802
|
-
|
|
7803
|
-
[data-scope="stat"][data-part="delta"][data-direction="down"] {
|
|
7804
|
-
color: var(--bs-color-danger);
|
|
7805
|
-
}
|
|
7806
|
-
|
|
7807
|
-
[data-scope="stat"][data-part="description"] {
|
|
7808
|
-
margin: 0;
|
|
7809
|
-
color: var(--bs-color-text-tertiary);
|
|
7810
|
-
font-size: var(--bs-font-size-sm);
|
|
7811
|
-
line-height: var(--bs-line-height-relaxed);
|
|
7812
|
-
}
|
|
7813
|
-
`;
|
|
7814
|
-
//#endregion
|
|
7815
9676
|
//#region src/styles/components/slider.ts
|
|
7816
9677
|
const sliderCss = labelCss("slider") + `
|
|
7817
9678
|
[data-scope="slider"][data-part="root"] {
|
|
@@ -7880,15 +9741,17 @@ const sliderCss = labelCss("slider") + `
|
|
|
7880
9741
|
}
|
|
7881
9742
|
|
|
7882
9743
|
/* The thumb is a paper seal riding the ink: surface fill, primary hairline,
|
|
7883
|
-
focus turns the ring primary — never a background change. Its size
|
|
7884
|
-
|
|
9744
|
+
focus turns the ring primary — never a background change. Its size rides
|
|
9745
|
+
the control height at a fixed share (five eighths), not the density
|
|
9746
|
+
scale — scenes that grow the targets grow the thumb with them, never
|
|
9747
|
+
past the track it sits on. */
|
|
7885
9748
|
[data-scope="slider"][data-part="thumb"] {
|
|
7886
9749
|
box-sizing: border-box;
|
|
7887
9750
|
display: flex;
|
|
7888
9751
|
align-items: center;
|
|
7889
9752
|
justify-content: center;
|
|
7890
|
-
inline-size: var(--bs-
|
|
7891
|
-
block-size: var(--bs-
|
|
9753
|
+
inline-size: calc(var(--bs-control-height-md) * 0.625);
|
|
9754
|
+
block-size: calc(var(--bs-control-height-md) * 0.625);
|
|
7892
9755
|
border: 1px solid var(--bs-color-primary);
|
|
7893
9756
|
border-radius: var(--bs-radius-full);
|
|
7894
9757
|
background: var(--bs-color-surface-2);
|
|
@@ -7970,18 +9833,107 @@ const sliderCss = labelCss("slider") + `
|
|
|
7970
9833
|
translate: -50% 0;
|
|
7971
9834
|
}
|
|
7972
9835
|
|
|
7973
|
-
[data-scope="slider"][data-part="marker"][data-state="at-value"],
|
|
7974
|
-
[data-scope="slider"][data-part="marker"][data-state="under-value"] {
|
|
7975
|
-
color: var(--bs-color-primary);
|
|
9836
|
+
[data-scope="slider"][data-part="marker"][data-state="at-value"],
|
|
9837
|
+
[data-scope="slider"][data-part="marker"][data-state="under-value"] {
|
|
9838
|
+
color: var(--bs-color-primary);
|
|
9839
|
+
}
|
|
9840
|
+
|
|
9841
|
+
[data-scope="slider"][data-part="marker"][data-state="at-value"]::before,
|
|
9842
|
+
[data-scope="slider"][data-part="marker"][data-state="under-value"]::before {
|
|
9843
|
+
background: var(--bs-color-primary);
|
|
9844
|
+
}
|
|
9845
|
+
|
|
9846
|
+
[data-scope="slider"][data-part="marker"][data-disabled] {
|
|
9847
|
+
color: var(--bs-color-text-disabled);
|
|
9848
|
+
}
|
|
9849
|
+
`;
|
|
9850
|
+
//#endregion
|
|
9851
|
+
//#region src/styles/components/spinner.ts
|
|
9852
|
+
const spinnerCss = `
|
|
9853
|
+
/* A wheel of waiting: one arc of ink turning about its center. Quiet by
|
|
9854
|
+
default — it reports progress without claiming attention. */
|
|
9855
|
+
[data-scope="spinner"][data-part="root"] {
|
|
9856
|
+
display: inline-flex;
|
|
9857
|
+
flex: none;
|
|
9858
|
+
color: var(--bs-color-text-tertiary);
|
|
9859
|
+
animation: bs-spinner-turn 0.9s linear infinite;
|
|
9860
|
+
}
|
|
9861
|
+
|
|
9862
|
+
[data-scope="spinner"][data-part="root"][data-size="sm"] {
|
|
9863
|
+
inline-size: var(--bs-part-size-sm);
|
|
9864
|
+
block-size: var(--bs-part-size-sm);
|
|
9865
|
+
}
|
|
9866
|
+
[data-scope="spinner"][data-part="root"][data-size="md"] {
|
|
9867
|
+
inline-size: var(--bs-part-size-md);
|
|
9868
|
+
block-size: var(--bs-part-size-md);
|
|
9869
|
+
}
|
|
9870
|
+
[data-scope="spinner"][data-part="root"][data-size="lg"] {
|
|
9871
|
+
inline-size: var(--bs-part-size-lg);
|
|
9872
|
+
block-size: var(--bs-part-size-lg);
|
|
9873
|
+
}
|
|
9874
|
+
|
|
9875
|
+
[data-scope="spinner"][data-part="root"] svg {
|
|
9876
|
+
inline-size: 100%;
|
|
9877
|
+
block-size: 100%;
|
|
9878
|
+
}
|
|
9879
|
+
|
|
9880
|
+
@keyframes bs-spinner-turn {
|
|
9881
|
+
to {
|
|
9882
|
+
transform: rotate(1turn);
|
|
9883
|
+
}
|
|
9884
|
+
}
|
|
9885
|
+
|
|
9886
|
+
@media (prefers-reduced-motion: reduce) {
|
|
9887
|
+
[data-scope="spinner"][data-part="root"] {
|
|
9888
|
+
animation-duration: 1ms;
|
|
9889
|
+
animation-iteration-count: 1;
|
|
9890
|
+
}
|
|
9891
|
+
}
|
|
9892
|
+
`;
|
|
9893
|
+
//#endregion
|
|
9894
|
+
//#region src/styles/components/split-button.ts
|
|
9895
|
+
const splitButtonCss = `
|
|
9896
|
+
/* The split: a primary action and its dropdown arrow seam-fused into one
|
|
9897
|
+
control — the button group's joinery closed to two members. The main
|
|
9898
|
+
button gives up its end corners; the arrow gives up its start corners
|
|
9899
|
+
and slides one pixel over the trailing hairline, redrawing the seam as
|
|
9900
|
+
a single line of border color (a cut of paper through a solid fill). */
|
|
9901
|
+
[data-scope="split-button"][data-part="root"] {
|
|
9902
|
+
display: inline-flex;
|
|
9903
|
+
}
|
|
9904
|
+
|
|
9905
|
+
[data-scope="split-button"][data-part="root"] > [data-scope="button"][data-part="root"] {
|
|
9906
|
+
border-start-end-radius: 0;
|
|
9907
|
+
border-end-end-radius: 0;
|
|
7976
9908
|
}
|
|
7977
9909
|
|
|
7978
|
-
|
|
7979
|
-
|
|
7980
|
-
|
|
9910
|
+
/* The arrow rides the menu machine's trigger anatomy (as-child hosting
|
|
9911
|
+
reads data-scope="menu"), dressed as a button by the button
|
|
9912
|
+
stylesheet's trigger register — hence the variant seal here, keeping
|
|
9913
|
+
these joins above that register regardless of stylesheet order. */
|
|
9914
|
+
[data-scope="split-button"][data-part="root"] > [data-scope="menu"][data-part="trigger"][data-variant] {
|
|
9915
|
+
border-start-start-radius: 0;
|
|
9916
|
+
border-end-start-radius: 0;
|
|
9917
|
+
margin-inline-start: -1px;
|
|
9918
|
+
border-inline-start: 1px solid var(--bs-color-border);
|
|
7981
9919
|
}
|
|
7982
9920
|
|
|
7983
|
-
|
|
7984
|
-
|
|
9921
|
+
/* Focus fuses like the border: a raised member keeps its halo and its
|
|
9922
|
+
deepened edge clear of the neighbor, and an open menu reads as one
|
|
9923
|
+
control at rest. */
|
|
9924
|
+
[data-scope="split-button"][data-part="root"] > [data-scope="button"][data-part="root"]:hover,
|
|
9925
|
+
[data-scope="split-button"][data-part="root"] > [data-scope="button"][data-part="root"]:focus-visible,
|
|
9926
|
+
[data-scope="split-button"][data-part="root"] > [data-scope="menu"][data-part="trigger"][data-variant]:hover,
|
|
9927
|
+
[data-scope="split-button"][data-part="root"] > [data-scope="menu"][data-part="trigger"][data-variant]:focus-visible,
|
|
9928
|
+
[data-scope="split-button"][data-part="root"] > [data-scope="menu"][data-part="trigger"][data-variant][data-state="open"] {
|
|
9929
|
+
z-index: 1;
|
|
9930
|
+
}
|
|
9931
|
+
|
|
9932
|
+
/* The popup keeps the menu parts and the menu stylesheet; only the
|
|
9933
|
+
danger rows ride this scope's knowledge of the callers — the
|
|
9934
|
+
menubar's register, restated so this family stands alone. */
|
|
9935
|
+
[data-scope="menu"][data-part="item"][data-danger] {
|
|
9936
|
+
color: var(--bs-color-danger);
|
|
7985
9937
|
}
|
|
7986
9938
|
`;
|
|
7987
9939
|
//#endregion
|
|
@@ -8120,6 +10072,77 @@ const splitterCss = `
|
|
|
8120
10072
|
}
|
|
8121
10073
|
`;
|
|
8122
10074
|
//#endregion
|
|
10075
|
+
//#region src/styles/components/stack.ts
|
|
10076
|
+
const stackCss = `
|
|
10077
|
+
/* The spacing primitive: the wrapper points --bs-stack-gap at a step of
|
|
10078
|
+
the space ramp, and the flex gap carries it — the distance is one
|
|
10079
|
+
named token, never an ad-hoc margin between siblings. */
|
|
10080
|
+
[data-scope="stack"][data-part="root"] {
|
|
10081
|
+
display: flex;
|
|
10082
|
+
flex-direction: column;
|
|
10083
|
+
gap: var(--bs-stack-gap, var(--bs-space-3));
|
|
10084
|
+
}
|
|
10085
|
+
|
|
10086
|
+
[data-scope="stack"][data-part="root"][data-direction="row"] {
|
|
10087
|
+
flex-direction: row;
|
|
10088
|
+
}
|
|
10089
|
+
`;
|
|
10090
|
+
//#endregion
|
|
10091
|
+
//#region src/styles/components/stat.ts
|
|
10092
|
+
const statCss = `
|
|
10093
|
+
/* One figure on the page: the label whispers what it is, the value
|
|
10094
|
+
states it plainly in tabular figures, the delta reads the direction
|
|
10095
|
+
in the fixed semantic pigments. */
|
|
10096
|
+
[data-scope="stat"][data-part="root"] {
|
|
10097
|
+
display: flex;
|
|
10098
|
+
flex-direction: column;
|
|
10099
|
+
gap: var(--bs-space-1);
|
|
10100
|
+
}
|
|
10101
|
+
|
|
10102
|
+
[data-scope="stat"][data-part="label"] {
|
|
10103
|
+
margin: 0;
|
|
10104
|
+
color: var(--bs-color-text-secondary);
|
|
10105
|
+
font-size: var(--bs-font-size-sm);
|
|
10106
|
+
font-weight: var(--bs-font-weight-medium);
|
|
10107
|
+
letter-spacing: var(--bs-tracking-label);
|
|
10108
|
+
}
|
|
10109
|
+
|
|
10110
|
+
/* The value carries the ink: large, semibold, tabular so figures
|
|
10111
|
+
align across a row of stats. */
|
|
10112
|
+
[data-scope="stat"][data-part="value"] {
|
|
10113
|
+
color: var(--bs-color-text-primary);
|
|
10114
|
+
font-size: var(--bs-font-size-3xl);
|
|
10115
|
+
font-weight: var(--bs-font-weight-semibold);
|
|
10116
|
+
font-variant-numeric: tabular-nums;
|
|
10117
|
+
line-height: var(--bs-line-height-tight);
|
|
10118
|
+
}
|
|
10119
|
+
|
|
10120
|
+
[data-scope="stat"][data-part="delta"] {
|
|
10121
|
+
display: inline-flex;
|
|
10122
|
+
align-items: center;
|
|
10123
|
+
gap: var(--bs-space-1);
|
|
10124
|
+
color: var(--bs-color-text-tertiary);
|
|
10125
|
+
font-size: var(--bs-font-size-sm);
|
|
10126
|
+
font-weight: var(--bs-font-weight-medium);
|
|
10127
|
+
font-variant-numeric: tabular-nums;
|
|
10128
|
+
}
|
|
10129
|
+
|
|
10130
|
+
[data-scope="stat"][data-part="delta"][data-direction="up"] {
|
|
10131
|
+
color: var(--bs-color-success);
|
|
10132
|
+
}
|
|
10133
|
+
|
|
10134
|
+
[data-scope="stat"][data-part="delta"][data-direction="down"] {
|
|
10135
|
+
color: var(--bs-color-danger);
|
|
10136
|
+
}
|
|
10137
|
+
|
|
10138
|
+
[data-scope="stat"][data-part="description"] {
|
|
10139
|
+
margin: 0;
|
|
10140
|
+
color: var(--bs-color-text-tertiary);
|
|
10141
|
+
font-size: var(--bs-font-size-sm);
|
|
10142
|
+
line-height: var(--bs-line-height-relaxed);
|
|
10143
|
+
}
|
|
10144
|
+
`;
|
|
10145
|
+
//#endregion
|
|
8123
10146
|
//#region src/styles/components/steps.ts
|
|
8124
10147
|
const stepsCss = `
|
|
8125
10148
|
[data-scope="steps"][data-part="root"] {
|
|
@@ -8191,7 +10214,7 @@ const stepsCss = `
|
|
|
8191
10214
|
place-items: center;
|
|
8192
10215
|
inline-size: var(--bs-control-height-sm);
|
|
8193
10216
|
block-size: var(--bs-control-height-sm);
|
|
8194
|
-
border-radius:
|
|
10217
|
+
border-radius: var(--bs-radius-full);
|
|
8195
10218
|
background: var(--bs-color-surface-2);
|
|
8196
10219
|
box-shadow: inset 0 0 0 1px var(--bs-color-border);
|
|
8197
10220
|
color: var(--bs-color-text-secondary);
|
|
@@ -8363,10 +10386,12 @@ const switchCss = labelCss("switch") + `
|
|
|
8363
10386
|
}
|
|
8364
10387
|
|
|
8365
10388
|
/* The track geometry: thumb travel is derived here so the knob lands
|
|
8366
|
-
flush against the far edge instead of drifting off-token.
|
|
10389
|
+
flush against the far edge instead of drifting off-token. The thumb
|
|
10390
|
+
rides the small part size — a switch sits beside controls, not
|
|
10391
|
+
among them, and 24px of track reads quiet at every density. */
|
|
8367
10392
|
[data-scope="switch"][data-part="control"] {
|
|
8368
10393
|
--bs-switch-track: calc(var(--bs-switch-thumb) * 2 + var(--bs-switch-inset) * 2);
|
|
8369
|
-
--bs-switch-thumb: var(--bs-part-size-
|
|
10394
|
+
--bs-switch-thumb: var(--bs-part-size-sm);
|
|
8370
10395
|
--bs-switch-inset: var(--bs-space-1);
|
|
8371
10396
|
display: inline-flex;
|
|
8372
10397
|
align-items: center;
|
|
@@ -9820,6 +11845,171 @@ const tourCss = popupContentCss("tour", "0") + `
|
|
|
9820
11845
|
}
|
|
9821
11846
|
`;
|
|
9822
11847
|
//#endregion
|
|
11848
|
+
//#region src/styles/components/transfer.ts
|
|
11849
|
+
const transferCss = `
|
|
11850
|
+
/* Two ledgers and a crossing: the panels carry the popup chrome's
|
|
11851
|
+
paper-and-hairline at rest weight, the buttons column rides between. */
|
|
11852
|
+
[data-scope="transfer"][data-part="root"] {
|
|
11853
|
+
display: flex;
|
|
11854
|
+
align-items: center;
|
|
11855
|
+
gap: var(--bs-space-3);
|
|
11856
|
+
}
|
|
11857
|
+
|
|
11858
|
+
[data-scope="transfer"][data-part="panel"] {
|
|
11859
|
+
display: flex;
|
|
11860
|
+
flex-direction: column;
|
|
11861
|
+
inline-size: 14rem;
|
|
11862
|
+
border: 1px solid var(--bs-color-border);
|
|
11863
|
+
border-radius: var(--bs-radius-md);
|
|
11864
|
+
background: var(--bs-color-surface-1);
|
|
11865
|
+
}
|
|
11866
|
+
|
|
11867
|
+
[data-scope="transfer"][data-part="head"] {
|
|
11868
|
+
display: flex;
|
|
11869
|
+
align-items: center;
|
|
11870
|
+
justify-content: space-between;
|
|
11871
|
+
gap: var(--bs-space-2);
|
|
11872
|
+
padding: var(--bs-space-2) var(--bs-space-3);
|
|
11873
|
+
border-block-end: 1px solid var(--bs-color-border);
|
|
11874
|
+
}
|
|
11875
|
+
|
|
11876
|
+
[data-scope="transfer"][data-part="title"] {
|
|
11877
|
+
color: var(--bs-color-text-secondary);
|
|
11878
|
+
font-size: var(--bs-font-size-sm);
|
|
11879
|
+
font-weight: var(--bs-font-weight-semibold);
|
|
11880
|
+
letter-spacing: var(--bs-tracking-label);
|
|
11881
|
+
}
|
|
11882
|
+
|
|
11883
|
+
[data-scope="transfer"][data-part="count"] {
|
|
11884
|
+
min-inline-size: var(--bs-control-height-sm);
|
|
11885
|
+
padding-inline: var(--bs-space-1);
|
|
11886
|
+
border-radius: var(--bs-radius-sm);
|
|
11887
|
+
background: var(--bs-color-surface-inset);
|
|
11888
|
+
color: var(--bs-color-text-tertiary);
|
|
11889
|
+
font-size: var(--bs-font-size-xs, 0.75rem);
|
|
11890
|
+
line-height: var(--bs-control-height-sm);
|
|
11891
|
+
text-align: center;
|
|
11892
|
+
font-variant-numeric: tabular-nums;
|
|
11893
|
+
}
|
|
11894
|
+
|
|
11895
|
+
[data-scope="transfer"][data-part="search"] {
|
|
11896
|
+
padding: var(--bs-space-2);
|
|
11897
|
+
border-block-end: 1px solid var(--bs-color-border);
|
|
11898
|
+
}
|
|
11899
|
+
|
|
11900
|
+
[data-scope="transfer"][data-part="list"] {
|
|
11901
|
+
display: flex;
|
|
11902
|
+
flex-direction: column;
|
|
11903
|
+
padding: var(--bs-space-1);
|
|
11904
|
+
max-block-size: 16rem;
|
|
11905
|
+
overflow-block: auto;
|
|
11906
|
+
}
|
|
11907
|
+
|
|
11908
|
+
/* Rows are the checkbox's own seal and label — the panel only gives
|
|
11909
|
+
them a clickable span and a hover wash. */
|
|
11910
|
+
[data-scope="transfer"] [data-scope="checkbox"][data-part="root"] {
|
|
11911
|
+
flex: 1;
|
|
11912
|
+
gap: var(--bs-space-2);
|
|
11913
|
+
padding: var(--bs-space-1) var(--bs-space-2);
|
|
11914
|
+
border-radius: var(--bs-radius-sm);
|
|
11915
|
+
transition: background-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
11916
|
+
}
|
|
11917
|
+
|
|
11918
|
+
[data-scope="transfer"] [data-scope="checkbox"][data-part="root"]:hover {
|
|
11919
|
+
background: var(--bs-color-surface-inset);
|
|
11920
|
+
}
|
|
11921
|
+
|
|
11922
|
+
[data-scope="transfer"] [data-part="label"] {
|
|
11923
|
+
flex: 1;
|
|
11924
|
+
font-size: var(--bs-font-size-sm);
|
|
11925
|
+
color: var(--bs-color-text-primary);
|
|
11926
|
+
cursor: inherit;
|
|
11927
|
+
}
|
|
11928
|
+
|
|
11929
|
+
[data-scope="transfer"][data-part="empty"] {
|
|
11930
|
+
padding: var(--bs-space-4);
|
|
11931
|
+
color: var(--bs-color-text-tertiary);
|
|
11932
|
+
font-size: var(--bs-font-size-sm);
|
|
11933
|
+
text-align: center;
|
|
11934
|
+
}
|
|
11935
|
+
|
|
11936
|
+
[data-scope="transfer"][data-part="operations"] {
|
|
11937
|
+
display: flex;
|
|
11938
|
+
flex-direction: column;
|
|
11939
|
+
gap: var(--bs-space-2);
|
|
11940
|
+
}
|
|
11941
|
+
`;
|
|
11942
|
+
//#endregion
|
|
11943
|
+
//#region src/styles/components/tree-select.ts
|
|
11944
|
+
const treeSelectCss = positionerCss("tree-select") + popupContentCss("tree-select", "0rem") + `
|
|
11945
|
+
/* The control reads as a field — the input recipe, with the chosen
|
|
11946
|
+
label as its ink and a quiet chevron at the inline end. */
|
|
11947
|
+
[data-scope="tree-select"][data-part="control"] {
|
|
11948
|
+
box-sizing: border-box;
|
|
11949
|
+
display: flex;
|
|
11950
|
+
align-items: center;
|
|
11951
|
+
justify-content: space-between;
|
|
11952
|
+
gap: var(--bs-space-2);
|
|
11953
|
+
inline-size: 100%;
|
|
11954
|
+
block-size: var(--bs-control-height-md);
|
|
11955
|
+
padding-inline: var(--bs-padding-md);
|
|
11956
|
+
border: 1px solid var(--bs-color-border);
|
|
11957
|
+
border-radius: var(--bs-radius-sm);
|
|
11958
|
+
background: var(--bs-color-surface-2);
|
|
11959
|
+
color: var(--bs-color-text-primary);
|
|
11960
|
+
font: inherit;
|
|
11961
|
+
font-size: var(--bs-font-size-md);
|
|
11962
|
+
text-align: start;
|
|
11963
|
+
cursor: pointer;
|
|
11964
|
+
transition: border-color var(--bs-duration-fast) var(--bs-ease-out);
|
|
11965
|
+
}
|
|
11966
|
+
|
|
11967
|
+
[data-scope="tree-select"][data-part="control"][data-placeholder] {
|
|
11968
|
+
color: var(--bs-color-text-tertiary);
|
|
11969
|
+
}
|
|
11970
|
+
|
|
11971
|
+
[data-scope="tree-select"][data-part="control"]:hover:not(:focus):not(:disabled) {
|
|
11972
|
+
border-color: var(--bs-color-border-strong);
|
|
11973
|
+
}
|
|
11974
|
+
|
|
11975
|
+
[data-scope="tree-select"][data-part="control"]:focus-visible {
|
|
11976
|
+
outline: none;
|
|
11977
|
+
border-color: var(--bs-color-primary);
|
|
11978
|
+
box-shadow: var(--bs-focus-ring);
|
|
11979
|
+
}
|
|
11980
|
+
|
|
11981
|
+
[data-scope="tree-select"][data-part="control"]:disabled {
|
|
11982
|
+
border-color: var(--bs-color-border);
|
|
11983
|
+
background: var(--bs-color-surface-inset);
|
|
11984
|
+
color: var(--bs-color-text-disabled);
|
|
11985
|
+
cursor: not-allowed;
|
|
11986
|
+
}
|
|
11987
|
+
|
|
11988
|
+
[data-scope="tree-select"][data-part="chevron"] {
|
|
11989
|
+
display: grid;
|
|
11990
|
+
place-items: center;
|
|
11991
|
+
color: var(--bs-color-text-tertiary);
|
|
11992
|
+
}
|
|
11993
|
+
|
|
11994
|
+
[data-scope="tree-select"][data-part="chevron"] svg {
|
|
11995
|
+
inline-size: var(--bs-space-4);
|
|
11996
|
+
block-size: var(--bs-space-4);
|
|
11997
|
+
transition: transform var(--bs-duration-fast) var(--bs-ease-out);
|
|
11998
|
+
}
|
|
11999
|
+
|
|
12000
|
+
[data-scope="tree-select"][data-part="control"][data-open] [data-part="chevron"] svg {
|
|
12001
|
+
transform: rotate(90deg);
|
|
12002
|
+
}
|
|
12003
|
+
|
|
12004
|
+
/* Inside the shared popup vessel, the tree keeps its own height and
|
|
12005
|
+
scrolls past a small grove. */
|
|
12006
|
+
[data-scope="tree-select"][data-part="content"] {
|
|
12007
|
+
max-block-size: 16rem;
|
|
12008
|
+
overflow-block: auto;
|
|
12009
|
+
padding: var(--bs-space-2);
|
|
12010
|
+
}
|
|
12011
|
+
`;
|
|
12012
|
+
//#endregion
|
|
9823
12013
|
//#region src/styles/components/index.ts
|
|
9824
12014
|
/** Component style registry — every component contributes its stylesheet
|
|
9825
12015
|
* here, keyed by the name wrappers pass to `injectComponentStyle`. */
|
|
@@ -9835,9 +12025,11 @@ const componentStyles = {
|
|
|
9835
12025
|
breadcrumb: breadcrumbCss,
|
|
9836
12026
|
button: buttonCss,
|
|
9837
12027
|
calendar: calendarCss + datePickerCss.replaceAll("data-scope=\"date-picker\"", "data-scope=\"calendar\""),
|
|
12028
|
+
"cascade-select": cascadeSelectCss,
|
|
9838
12029
|
card: cardCss,
|
|
9839
12030
|
carousel: carouselCss,
|
|
9840
12031
|
checkbox: checkboxCss,
|
|
12032
|
+
"checkbox-group": checkboxGroupCss,
|
|
9841
12033
|
chip: chipCss,
|
|
9842
12034
|
clipboard: clipboardCss,
|
|
9843
12035
|
collapsible: collapsibleCss,
|
|
@@ -9845,6 +12037,7 @@ const componentStyles = {
|
|
|
9845
12037
|
combobox: comboboxCss,
|
|
9846
12038
|
"date-input": dateInputCss,
|
|
9847
12039
|
"date-picker": datePickerCss,
|
|
12040
|
+
descriptions: descriptionsCss,
|
|
9848
12041
|
dialog: dialogCss,
|
|
9849
12042
|
drawer: drawerCss,
|
|
9850
12043
|
editable: editableCss,
|
|
@@ -9853,9 +12046,11 @@ const componentStyles = {
|
|
|
9853
12046
|
fieldset: fieldsetCss,
|
|
9854
12047
|
"file-upload": fileUploadCss,
|
|
9855
12048
|
"floating-panel": floatingPanelCss,
|
|
12049
|
+
form: formCss,
|
|
9856
12050
|
highlight: highlightCss,
|
|
9857
12051
|
"hover-card": hoverCardCss,
|
|
9858
12052
|
"image-cropper": imageCropperCss,
|
|
12053
|
+
input: fieldControlCss.replaceAll("data-scope=\"field\"", "data-scope=\"input\"").replaceAll("data-part=\"input\"", "data-part=\"root\""),
|
|
9859
12054
|
"json-tree-view": jsonTreeViewCss,
|
|
9860
12055
|
kbd: kbdCss,
|
|
9861
12056
|
link: linkCss,
|
|
@@ -9863,13 +12058,13 @@ const componentStyles = {
|
|
|
9863
12058
|
marquee: marqueeCss,
|
|
9864
12059
|
menu: menuCss,
|
|
9865
12060
|
meter: meterCss,
|
|
9866
|
-
typography: typographyCss,
|
|
9867
12061
|
"navigation-menu": navigationMenuCss,
|
|
9868
12062
|
"number-input": numberInputCss,
|
|
9869
12063
|
"page-header": pageHeaderCss,
|
|
9870
12064
|
pagination: paginationCss,
|
|
9871
12065
|
"password-input": passwordInputCss,
|
|
9872
12066
|
"pin-input": pinInputCss,
|
|
12067
|
+
popconfirm: popconfirmCss,
|
|
9873
12068
|
popover: popoverCss,
|
|
9874
12069
|
progress: progressCss,
|
|
9875
12070
|
"qr-code": qrCodeCss,
|
|
@@ -9890,6 +12085,7 @@ const componentStyles = {
|
|
|
9890
12085
|
switch: switchCss,
|
|
9891
12086
|
tabs: tabsCss,
|
|
9892
12087
|
"tags-input": tagsInputCss,
|
|
12088
|
+
textarea: fieldControlCss.replaceAll("data-scope=\"field\"", "data-scope=\"textarea\"").replaceAll("data-part=\"textarea\"", "data-part=\"root\""),
|
|
9893
12089
|
timeline: timelineCss,
|
|
9894
12090
|
timer: timerCss,
|
|
9895
12091
|
table: tableCss,
|
|
@@ -9897,16 +12093,111 @@ const componentStyles = {
|
|
|
9897
12093
|
toc: tocCss,
|
|
9898
12094
|
toggle: toggleCss,
|
|
9899
12095
|
"toggle-group": toggleGroupCss,
|
|
12096
|
+
transfer: transferCss,
|
|
9900
12097
|
tooltip: tooltipCss,
|
|
9901
12098
|
tour: tourCss,
|
|
9902
|
-
"tree-
|
|
12099
|
+
"tree-select": treeSelectCss,
|
|
12100
|
+
"tree-view": treeViewCss,
|
|
12101
|
+
typography: `
|
|
12102
|
+
/* The typographic voices, named so prose can ask for one: display and
|
|
12103
|
+
heading ride the song-serif, the rest ride the hei. Nothing here is
|
|
12104
|
+
decorative — hierarchy is size, weight, and space. */
|
|
12105
|
+
[data-scope="typography"][data-part="display"] {
|
|
12106
|
+
margin: 0;
|
|
12107
|
+
color: var(--bs-color-text-primary);
|
|
12108
|
+
font-family: var(--bs-font-serif);
|
|
12109
|
+
font-size: var(--bs-font-size-4xl);
|
|
12110
|
+
font-weight: var(--bs-font-weight-semibold);
|
|
12111
|
+
line-height: var(--bs-line-height-tight);
|
|
12112
|
+
}
|
|
12113
|
+
|
|
12114
|
+
[data-scope="typography"][data-part="heading"] {
|
|
12115
|
+
margin: 0;
|
|
12116
|
+
color: var(--bs-color-text-primary);
|
|
12117
|
+
font-family: var(--bs-font-serif);
|
|
12118
|
+
font-size: var(--bs-font-size-2xl);
|
|
12119
|
+
font-weight: var(--bs-font-weight-semibold);
|
|
12120
|
+
line-height: var(--bs-line-height-snug);
|
|
12121
|
+
}
|
|
12122
|
+
|
|
12123
|
+
[data-scope="typography"][data-part="lead"] {
|
|
12124
|
+
margin: 0;
|
|
12125
|
+
color: var(--bs-color-text-secondary);
|
|
12126
|
+
font-size: var(--bs-font-size-lg);
|
|
12127
|
+
line-height: var(--bs-line-height-relaxed);
|
|
12128
|
+
}
|
|
12129
|
+
|
|
12130
|
+
[data-scope="typography"][data-part="body"] {
|
|
12131
|
+
margin: 0;
|
|
12132
|
+
color: var(--bs-color-text-secondary);
|
|
12133
|
+
font-size: var(--bs-font-size-base);
|
|
12134
|
+
line-height: var(--bs-line-height-relaxed);
|
|
12135
|
+
}
|
|
12136
|
+
|
|
12137
|
+
[data-scope="typography"][data-part="muted"] {
|
|
12138
|
+
margin: 0;
|
|
12139
|
+
color: var(--bs-color-text-tertiary);
|
|
12140
|
+
font-size: var(--bs-font-size-sm);
|
|
12141
|
+
line-height: var(--bs-line-height-relaxed);
|
|
12142
|
+
}
|
|
12143
|
+
|
|
12144
|
+
[data-scope="typography"][data-part="label"] {
|
|
12145
|
+
margin: 0;
|
|
12146
|
+
color: var(--bs-color-text-secondary);
|
|
12147
|
+
font-size: var(--bs-font-size-sm);
|
|
12148
|
+
font-weight: var(--bs-font-weight-medium);
|
|
12149
|
+
letter-spacing: var(--bs-tracking-label);
|
|
12150
|
+
}
|
|
12151
|
+
`,
|
|
12152
|
+
container: containerCss,
|
|
12153
|
+
stack: stackCss,
|
|
12154
|
+
grid: gridCss,
|
|
12155
|
+
"aspect-ratio": aspectRatioCss,
|
|
12156
|
+
masonry: masonryCss,
|
|
12157
|
+
icon: iconCss,
|
|
12158
|
+
ellipsis: ellipsisCss,
|
|
12159
|
+
image: imageCss,
|
|
12160
|
+
"image-viewer": imageViewerCss,
|
|
12161
|
+
list: listCss,
|
|
12162
|
+
comment: commentCss,
|
|
12163
|
+
watermark: `
|
|
12164
|
+
/* The paper bears its seal beneath the content: the wrapper holds the
|
|
12165
|
+
flow, the marks repeat their tile across the whole sheet and never
|
|
12166
|
+
take a pointer — the page beneath stays live. */
|
|
12167
|
+
[data-scope="watermark"][data-part="root"] {
|
|
12168
|
+
position: relative;
|
|
12169
|
+
}
|
|
12170
|
+
|
|
12171
|
+
[data-scope="watermark"][data-part="content"] {
|
|
12172
|
+
position: relative;
|
|
12173
|
+
}
|
|
12174
|
+
|
|
12175
|
+
[data-scope="watermark"][data-part="marks"] {
|
|
12176
|
+
position: absolute;
|
|
12177
|
+
inset: 0;
|
|
12178
|
+
pointer-events: none;
|
|
12179
|
+
background-repeat: repeat;
|
|
12180
|
+
}
|
|
12181
|
+
`,
|
|
12182
|
+
"progress-group": progressGroupCss,
|
|
12183
|
+
"back-top": backTopCss,
|
|
12184
|
+
affix: affixCss,
|
|
12185
|
+
command: commandCss,
|
|
12186
|
+
mentions: mentionsCss,
|
|
12187
|
+
menubar: menubarCss,
|
|
12188
|
+
"input-group": inputGroupCss,
|
|
12189
|
+
"dynamic-input": dynamicInputCss,
|
|
12190
|
+
"button-group": buttonGroupCss,
|
|
12191
|
+
"split-button": splitButtonCss,
|
|
12192
|
+
"float-button": floatButtonCss,
|
|
12193
|
+
layout: layoutCss
|
|
9903
12194
|
};
|
|
9904
12195
|
//#endregion
|
|
9905
12196
|
//#region src/styles.ts
|
|
9906
12197
|
/** The complete token layer (`@layer bs.tokens`): themes, density, contrast,
|
|
9907
12198
|
* typography, motion, z-index, plus the document-level base guard and the
|
|
9908
12199
|
* ink-ripple motion grammar. */
|
|
9909
|
-
const tokensCss =
|
|
12200
|
+
const tokensCss = tokensStyles + baseCss + inkRippleCss;
|
|
9910
12201
|
let injected = false;
|
|
9911
12202
|
/** True when an SSR integration already delivered the whole layer (the
|
|
9912
12203
|
* Nuxt module ships it as one build-time stylesheet and plants this
|