kuinetic 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +3 -3
- package/dist/esm/{chunk-WPU33HDL.mjs → chunk-5DON3UFQ.mjs} +1195 -214
- package/dist/esm/{chunk-LWS4OSLX.mjs → chunk-JT4PZL3A.mjs} +50 -7
- package/dist/esm/{chunk-5EVG7CIY.mjs → chunk-QUVFODSQ.mjs} +27 -13
- package/dist/esm/core/index.mjs +2 -2
- package/dist/esm/effects/index.mjs +2 -2
- package/dist/esm/index.mjs +3 -3
- package/dist/kuinetic.all.js +1269 -233
- package/dist/kuinetic.css +1392 -52
- package/dist/kuinetic.js +1268 -232
- package/dist/types/core/instances.d.ts +34 -3
- package/dist/types/core/path-morph.d.ts +19 -0
- package/dist/types/core/style-plan.d.ts +6 -1
- package/dist/types/core/types.d.ts +93 -1
- package/dist/types/effects/catalog/index.d.ts +0 -6
- package/dist/types/effects/catalog/media-shared.d.ts +124 -0
- package/dist/types/effects/catalog/media.d.ts +4 -0
- package/dist/types/effects/catalog/numbers-shared.d.ts +5 -1
- package/dist/types/effects/catalog/shared.d.ts +0 -1
- package/dist/types/effects/catalog/subtree-capture.d.ts +23 -0
- package/dist/types/effects/catalog/text-shared.d.ts +5 -2
- package/dist/types/effects/gestures/index.d.ts +0 -1
- package/dist/types/effects/layout/index.d.ts +0 -2
- package/dist/types/effects/scroll-mechanics/index.d.ts +0 -4
- package/dist/types/effects/scroll-mechanics/scroll-spy.d.ts +26 -0
- package/dist/types/effects/scroll-mechanics/tracker.d.ts +61 -3
- package/dist/types/effects/step-marking.d.ts +99 -0
- package/dist/types/effects/three-d/index.d.ts +0 -7
- package/package.json +9 -2
package/dist/kuinetic.all.js
CHANGED
|
@@ -61,7 +61,7 @@ var kuinetic = (() => {
|
|
|
61
61
|
|
|
62
62
|
// src/core/element-config.ts
|
|
63
63
|
var ACTIVATIONS = /* @__PURE__ */ new Set(["load", "enter", "hover", "focus", "click", "manual"]);
|
|
64
|
-
var TIMELINES = /* @__PURE__ */ new Set(["time", "view", "scroll", "pointer"]);
|
|
64
|
+
var TIMELINES = /* @__PURE__ */ new Set(["time", "view", "scroll", "pointer", "pin"]);
|
|
65
65
|
function readAttributes(el) {
|
|
66
66
|
return {
|
|
67
67
|
source: el.getAttribute(ATTR.source) ?? "",
|
|
@@ -243,7 +243,7 @@ var kuinetic = (() => {
|
|
|
243
243
|
var HEX_COLOR = /^#[0-9a-f]{3,8}$/i;
|
|
244
244
|
var COLOR_FUNCTIONS = /^(?:rgba?|hsla?|okl(?:ch|ab)|l(?:ch|ab)|color)\([^()]*\)$/i;
|
|
245
245
|
var COLOR_KEYWORD = /^[a-z]+$/i;
|
|
246
|
-
var EASING_KEYWORD = /^(?:linear|ease|step-start|step-end|spring|[a-z]+-(?:in|out|in-out))$/i;
|
|
246
|
+
var EASING_KEYWORD = /^(?:linear|ease|step-start|step-end|spring|bounce|[a-z]+-(?:in|out|in-out))$/i;
|
|
247
247
|
var EASING_FUNCTION = /^(?:cubic-bezier|steps|linear)\([^()]*\)$/i;
|
|
248
248
|
var CALC_TYPES = /* @__PURE__ */ new Set(["length", "percentage", "number"]);
|
|
249
249
|
var CALC_CHARACTER = /^[\d.\s+\-*/%a-z,]$/i;
|
|
@@ -530,7 +530,7 @@ var kuinetic = (() => {
|
|
|
530
530
|
plan.vars,
|
|
531
531
|
resolveParams(entry.spec.params, primitive.parameters, (m) => warnings.push(m))
|
|
532
532
|
);
|
|
533
|
-
if (primitive.renderer === "css-keyframes") pushTrack(tracks, entry);
|
|
533
|
+
if (primitive.renderer === "css-keyframes") pushTrack(tracks, entry, timeline);
|
|
534
534
|
else plan.jsEffects.push(entry);
|
|
535
535
|
}
|
|
536
536
|
Object.assign(plan.declarations, declarationsFor(tracks));
|
|
@@ -546,12 +546,13 @@ var kuinetic = (() => {
|
|
|
546
546
|
function iterationCountProperty(presetName) {
|
|
547
547
|
return `--kui-fx-${presetName}-iterations`;
|
|
548
548
|
}
|
|
549
|
-
function pushTrack(tracks, entry) {
|
|
549
|
+
function pushTrack(tracks, entry, timeline) {
|
|
550
550
|
const { spec, resolved } = entry;
|
|
551
551
|
const id = resolved.primitive.id;
|
|
552
552
|
tracks.names.push(resolved.preset.keyframes ?? `kui-${resolved.preset.name}`);
|
|
553
|
-
|
|
554
|
-
tracks.
|
|
553
|
+
const duration = spec.duration ?? `var(${timingProperty(id, "duration")}, 600ms)`;
|
|
554
|
+
tracks.durations.push(duration);
|
|
555
|
+
tracks.delays.push(staggerDelay(spec.delay, id, timeline, duration));
|
|
555
556
|
tracks.easings.push(easingValue(spec.easing, id));
|
|
556
557
|
tracks.iterationCounts.push(`var(${iterationCountProperty(resolved.preset.name)}, 1)`);
|
|
557
558
|
}
|
|
@@ -575,9 +576,12 @@ var kuinetic = (() => {
|
|
|
575
576
|
`"${name}" does not support timeline "${timeline}" (supports: ${supported.join(", ")})`
|
|
576
577
|
);
|
|
577
578
|
}
|
|
578
|
-
function staggerDelay(delay, primitiveId) {
|
|
579
|
+
function staggerDelay(delay, primitiveId, timeline, duration) {
|
|
579
580
|
const base = delay ?? `var(${timingProperty(primitiveId, "delay")}, 0ms)`;
|
|
580
|
-
|
|
581
|
+
const staggered = `${base} + var(--kui-i, 0) * var(--kui-stagger, 0ms)`;
|
|
582
|
+
if (timeline !== "pin") return `calc(${staggered})`;
|
|
583
|
+
const span = `${duration} + (var(--kui-stagger-count, 1) - 1) * var(--kui-stagger, 0ms)`;
|
|
584
|
+
return `calc(${staggered} - var(--kui-progress, 0) * (${span}))`;
|
|
581
585
|
}
|
|
582
586
|
function easingValue(easing, primitiveId) {
|
|
583
587
|
if (!easing) return `var(${timingProperty(primitiveId, "ease")}, ease-out)`;
|
|
@@ -860,7 +864,8 @@ var kuinetic = (() => {
|
|
|
860
864
|
"back-in-out",
|
|
861
865
|
"quart-out",
|
|
862
866
|
"circ-out",
|
|
863
|
-
"spring"
|
|
867
|
+
"spring",
|
|
868
|
+
"bounce"
|
|
864
869
|
]);
|
|
865
870
|
function splitTopLevel(input, delimiter, warnings = []) {
|
|
866
871
|
const parts = [];
|
|
@@ -1095,7 +1100,22 @@ var kuinetic = (() => {
|
|
|
1095
1100
|
viewportLeft: 0
|
|
1096
1101
|
}),
|
|
1097
1102
|
onScroll: (handler) => listen(win, "scroll", handler),
|
|
1098
|
-
|
|
1103
|
+
/*
|
|
1104
|
+
* The document's own height counts as a resize, not just the window's.
|
|
1105
|
+
*
|
|
1106
|
+
* `elementScrollRoot` has observed its element's size since it was written, for the reason
|
|
1107
|
+
* stated three doc comments down: "images loading, fonts swapping, a container changing size,
|
|
1108
|
+
* or content being inserted". Every one of those applies at least as strongly to the page
|
|
1109
|
+
* itself, and the page root was the one that only listened for `window.resize` — so on any
|
|
1110
|
+
* document with lazy-loaded media below the fold, every cached content offset silently drifted
|
|
1111
|
+
* by however much the page grew after it was measured, with no epoch bump to correct it.
|
|
1112
|
+
*
|
|
1113
|
+
* Measured on `demo/scroll.html` (32,000px of lazy screenshots): the horizontal track's stage
|
|
1114
|
+
* moved ~840px between page load and reaching it, which is a third of that effect's whole
|
|
1115
|
+
* scroll range. Nothing was wrong with the maths; the number it was doing the maths on was
|
|
1116
|
+
* taken before forty images existed.
|
|
1117
|
+
*/
|
|
1118
|
+
onResize: (handler) => observeSize(win.document.documentElement, win, handler)
|
|
1099
1119
|
};
|
|
1100
1120
|
}
|
|
1101
1121
|
function elementScrollRoot(el, win) {
|
|
@@ -1322,7 +1342,7 @@ var kuinetic = (() => {
|
|
|
1322
1342
|
flushComputedAnimationName(el);
|
|
1323
1343
|
ledger.set("animation-name", name);
|
|
1324
1344
|
}
|
|
1325
|
-
function createCssInstance(el, ledger, animationNames) {
|
|
1345
|
+
function createCssInstance(el, ledger, animationNames, scrubbed = false) {
|
|
1326
1346
|
const ownedNames = new Set(animationNames);
|
|
1327
1347
|
let settle2;
|
|
1328
1348
|
let finished = new Promise((resolve) => {
|
|
@@ -1341,6 +1361,10 @@ var kuinetic = (() => {
|
|
|
1341
1361
|
finished = new Promise((resolve) => {
|
|
1342
1362
|
settle2 = resolve;
|
|
1343
1363
|
});
|
|
1364
|
+
if (scrubbed) {
|
|
1365
|
+
settle2?.();
|
|
1366
|
+
return;
|
|
1367
|
+
}
|
|
1344
1368
|
let animations = ownedAnimationsOf(el, ownedNames);
|
|
1345
1369
|
if (!activatedBefore) {
|
|
1346
1370
|
restartCssAnimation(el, ledger);
|
|
@@ -1373,6 +1397,9 @@ var kuinetic = (() => {
|
|
|
1373
1397
|
}
|
|
1374
1398
|
};
|
|
1375
1399
|
}
|
|
1400
|
+
function continuousSetup(cleanup) {
|
|
1401
|
+
return { cleanup, continuous: true };
|
|
1402
|
+
}
|
|
1376
1403
|
function cleanupOf(result) {
|
|
1377
1404
|
if (result === void 0) return void 0;
|
|
1378
1405
|
return typeof result === "function" ? result : result.cleanup;
|
|
@@ -1389,7 +1416,7 @@ var kuinetic = (() => {
|
|
|
1389
1416
|
return createJsInstance({
|
|
1390
1417
|
activate() {
|
|
1391
1418
|
running = setup();
|
|
1392
|
-
if (typeof running === "function") return;
|
|
1419
|
+
if (typeof running === "function" || "continuous" in running) return;
|
|
1393
1420
|
const work = running.finished;
|
|
1394
1421
|
finished = new Promise((resolve) => {
|
|
1395
1422
|
settle2 = resolve;
|
|
@@ -1398,11 +1425,14 @@ var kuinetic = (() => {
|
|
|
1398
1425
|
},
|
|
1399
1426
|
cancel: teardown,
|
|
1400
1427
|
finish() {
|
|
1401
|
-
if (typeof running === "object") running.finish?.();
|
|
1428
|
+
if (typeof running === "object" && "finish" in running) running.finish?.();
|
|
1402
1429
|
settle2?.();
|
|
1403
1430
|
},
|
|
1404
1431
|
destroy: teardown,
|
|
1405
|
-
finished: () => finished
|
|
1432
|
+
finished: () => finished,
|
|
1433
|
+
// Only an explicit marker counts. A bare `Cleanup` deliberately does not — see
|
|
1434
|
+
// `ContinuousSetup` above for why the two cannot be told apart by shape.
|
|
1435
|
+
continuous: () => typeof running === "object" && "continuous" in running
|
|
1406
1436
|
});
|
|
1407
1437
|
}
|
|
1408
1438
|
function deferPrepare(setup) {
|
|
@@ -1426,6 +1456,9 @@ var kuinetic = (() => {
|
|
|
1426
1456
|
get finished() {
|
|
1427
1457
|
return hooks.finished?.() ?? Promise.resolve();
|
|
1428
1458
|
},
|
|
1459
|
+
get continuous() {
|
|
1460
|
+
return hooks.continuous?.() ?? false;
|
|
1461
|
+
},
|
|
1429
1462
|
destroy() {
|
|
1430
1463
|
active = false;
|
|
1431
1464
|
hooks.destroy();
|
|
@@ -1437,6 +1470,7 @@ var kuinetic = (() => {
|
|
|
1437
1470
|
function createStyleLedger(el) {
|
|
1438
1471
|
const style = el.style;
|
|
1439
1472
|
const previous = /* @__PURE__ */ new Map();
|
|
1473
|
+
const authoredStyleAttribute = el.hasAttribute("style");
|
|
1440
1474
|
function remember(property) {
|
|
1441
1475
|
if (previous.has(property)) return;
|
|
1442
1476
|
const existing = style.getPropertyValue(property);
|
|
@@ -1454,6 +1488,8 @@ var kuinetic = (() => {
|
|
|
1454
1488
|
else style.setProperty(property, value);
|
|
1455
1489
|
}
|
|
1456
1490
|
previous.clear();
|
|
1491
|
+
if (!authoredStyleAttribute && style.length === 0 && !el.getAttribute("style"))
|
|
1492
|
+
el.removeAttribute("style");
|
|
1457
1493
|
},
|
|
1458
1494
|
owned: () => [...previous.keys()]
|
|
1459
1495
|
};
|
|
@@ -1487,6 +1523,8 @@ var kuinetic = (() => {
|
|
|
1487
1523
|
index++;
|
|
1488
1524
|
}
|
|
1489
1525
|
}
|
|
1526
|
+
;
|
|
1527
|
+
group.style.setProperty("--kui-stagger-count", String(Math.max(index, 1)));
|
|
1490
1528
|
}
|
|
1491
1529
|
function applyStagger(root) {
|
|
1492
1530
|
const selector = `[${ATTR.stagger}]`;
|
|
@@ -1498,12 +1536,14 @@ var kuinetic = (() => {
|
|
|
1498
1536
|
function planStyles(input) {
|
|
1499
1537
|
const { plan, config, capabilities, respectReducedMotion } = input;
|
|
1500
1538
|
const reduce = respectReducedMotion && capabilities.reducedMotion;
|
|
1501
|
-
const
|
|
1539
|
+
const scrubbed = config.timeline === "pin" && plan.supportedTimelines.includes("pin");
|
|
1540
|
+
const useNativeTimeline = !scrubbed && supportsTimeline(config.timeline, capabilities) && plan.supportedTimelines.includes(config.timeline);
|
|
1502
1541
|
const properties = { ...plan.vars, ...plan.declarations };
|
|
1503
1542
|
Object.assign(properties, timelineProperties(config, capabilities, useNativeTimeline));
|
|
1504
1543
|
const hasCssAnimation = Object.keys(plan.declarations).length > 0;
|
|
1505
1544
|
const gate = resolveGate({
|
|
1506
1545
|
useNativeTimeline,
|
|
1546
|
+
scrubbed: scrubbed && hasCssAnimation,
|
|
1507
1547
|
reduce,
|
|
1508
1548
|
activation: config.activation,
|
|
1509
1549
|
// JS effects are gated too. They emit no `animation` declaration, so only the play-state
|
|
@@ -1518,7 +1558,7 @@ var kuinetic = (() => {
|
|
|
1518
1558
|
// already applied under reduced motion.
|
|
1519
1559
|
unsupportedTransform: needsIndividualTransforms(plan.channels, capabilities)
|
|
1520
1560
|
});
|
|
1521
|
-
if (gate === "deferred") properties["animation-play-state"] = "paused";
|
|
1561
|
+
if (gate === "deferred" || gate === "scrubbed") properties["animation-play-state"] = "paused";
|
|
1522
1562
|
return {
|
|
1523
1563
|
properties,
|
|
1524
1564
|
attributes: {
|
|
@@ -1542,6 +1582,7 @@ var kuinetic = (() => {
|
|
|
1542
1582
|
}
|
|
1543
1583
|
function resolveGate(input) {
|
|
1544
1584
|
if (input.useNativeTimeline) return "native-timeline";
|
|
1585
|
+
if (input.scrubbed) return "scrubbed";
|
|
1545
1586
|
if (!input.hasWork) return "immediate";
|
|
1546
1587
|
if (input.reduce || input.activation === "load" || input.unsupportedTransform) return "immediate";
|
|
1547
1588
|
return "deferred";
|
|
@@ -1722,7 +1763,9 @@ var kuinetic = (() => {
|
|
|
1722
1763
|
this.liveElements.add(el);
|
|
1723
1764
|
if (Object.keys(stylePlan.properties).some((property) => property.startsWith("animation-"))) {
|
|
1724
1765
|
const animationNames = (plan.declarations["animation-name"] ?? "").split(",").map((name) => name.trim()).filter(Boolean);
|
|
1725
|
-
state.instances.push(
|
|
1766
|
+
state.instances.push(
|
|
1767
|
+
createCssInstance(el, ledger, animationNames, stylePlan.gate === "scrubbed")
|
|
1768
|
+
);
|
|
1726
1769
|
}
|
|
1727
1770
|
state.instances.push(
|
|
1728
1771
|
...this.jsEffectPreparer.prepare({ el, plan, signal: controller.signal, ledger })
|
|
@@ -1783,7 +1826,9 @@ var kuinetic = (() => {
|
|
|
1783
1826
|
state.attributes.set(ATTR.state, "failed");
|
|
1784
1827
|
return;
|
|
1785
1828
|
}
|
|
1786
|
-
|
|
1829
|
+
const timed = started.filter((instance) => !instance.continuous);
|
|
1830
|
+
if (timed.length === 0 && started.length > 0) return;
|
|
1831
|
+
void Promise.all(timed.map((instance) => instance.finished)).then(() => {
|
|
1787
1832
|
if (this.states.get(el) !== state || state.status !== "running") return;
|
|
1788
1833
|
state.status = "finished";
|
|
1789
1834
|
state.attributes.set(ATTR.state, "finished");
|
|
@@ -1972,7 +2017,18 @@ var kuinetic = (() => {
|
|
|
1972
2017
|
background: "background",
|
|
1973
2018
|
color: "color",
|
|
1974
2019
|
stroke: "stroke",
|
|
1975
|
-
text: "text"
|
|
2020
|
+
text: "text",
|
|
2021
|
+
/**
|
|
2022
|
+
* Skew is the one transform CSS never gave an independent property to — there is no `skew:`
|
|
2023
|
+
* beside `translate:`/`rotate:`/`scale:`, so it can only be written through the `transform`
|
|
2024
|
+
* shorthand. That makes it its own channel: anything writing `transform` clobbers the whole
|
|
2025
|
+
* shorthand, so every primitive that does is on this channel, whatever the transform is for.
|
|
2026
|
+
* `scroll-skew` is one member; `flip-face` (`effects/three-d`) and `flip-3d`
|
|
2027
|
+
* (`effects/catalog/core`, the `flip-in-*`/`flip-out-*` family) are the other two — both need
|
|
2028
|
+
* the `perspective()` transform *function* for an element to have depth on itself, which
|
|
2029
|
+
* likewise only exists inside `transform`.
|
|
2030
|
+
*/
|
|
2031
|
+
skew: "skew"
|
|
1976
2032
|
};
|
|
1977
2033
|
function inertInstance(destroy = () => {
|
|
1978
2034
|
}) {
|
|
@@ -2026,6 +2082,13 @@ var kuinetic = (() => {
|
|
|
2026
2082
|
ease: { type: "easing", default: "ease-in-out", cssProperty: "--kui-ease" },
|
|
2027
2083
|
distance: { type: "length", default: "14px", cssProperty: "--kui-distance" }
|
|
2028
2084
|
};
|
|
2085
|
+
var orbit = {
|
|
2086
|
+
duration: { type: "time", default: "3.5s", cssProperty: "--kui-duration" },
|
|
2087
|
+
// `linear` by default, unlike every other ambient primitive: a continuous rotation that eases
|
|
2088
|
+
// visibly stutters once per revolution, because the ease restarts at each iteration boundary.
|
|
2089
|
+
ease: { type: "easing", default: "linear", cssProperty: "--kui-ease" },
|
|
2090
|
+
angle: { type: "angle", default: "360deg", cssProperty: "--kui-to-angle" }
|
|
2091
|
+
};
|
|
2029
2092
|
var pulse = {
|
|
2030
2093
|
duration: { type: "time", default: "2.2s", cssProperty: "--kui-duration" },
|
|
2031
2094
|
ease: { type: "easing", default: "ease-in-out", cssProperty: "--kui-ease" },
|
|
@@ -2044,6 +2107,12 @@ var kuinetic = (() => {
|
|
|
2044
2107
|
reducedMotion: "disable",
|
|
2045
2108
|
perfClass: "continuous"
|
|
2046
2109
|
}),
|
|
2110
|
+
cssPrimitive("ambient-orbit", [CHANNEL.rotate], {
|
|
2111
|
+
parameters: orbit,
|
|
2112
|
+
defaultActivation: "load",
|
|
2113
|
+
reducedMotion: "disable",
|
|
2114
|
+
perfClass: "continuous"
|
|
2115
|
+
}),
|
|
2047
2116
|
cssPrimitive("ambient-pulse", [CHANNEL.scale, CHANNEL.opacity], {
|
|
2048
2117
|
parameters: pulse,
|
|
2049
2118
|
defaultActivation: "load",
|
|
@@ -2115,6 +2184,7 @@ var kuinetic = (() => {
|
|
|
2115
2184
|
keyframes: "kui-floating-shapes",
|
|
2116
2185
|
params: { duration: "6s", distance: "10px" }
|
|
2117
2186
|
},
|
|
2187
|
+
{ name: "orbit", primitive: "ambient-orbit", keyframes: "kui-orbit" },
|
|
2118
2188
|
{ name: "glow-pulse", primitive: "ambient-pulse", keyframes: "kui-glow-pulse" }
|
|
2119
2189
|
];
|
|
2120
2190
|
function registerAmbient(registry) {
|
|
@@ -2431,6 +2501,9 @@ var kuinetic = (() => {
|
|
|
2431
2501
|
var liftParams = {
|
|
2432
2502
|
distance: { type: "length", default: "6px", cssProperty: "--kui-lift-distance" }
|
|
2433
2503
|
};
|
|
2504
|
+
var popParams = {
|
|
2505
|
+
scale: { type: "number", default: "1.06", cssProperty: "--kui-pop-scale", finite: true, minimum: 0 }
|
|
2506
|
+
};
|
|
2434
2507
|
function hoverPrimitive(id, channels, extraParams = {}) {
|
|
2435
2508
|
return {
|
|
2436
2509
|
id,
|
|
@@ -2452,6 +2525,7 @@ var kuinetic = (() => {
|
|
|
2452
2525
|
}
|
|
2453
2526
|
var HOVER_PRIMITIVES = [
|
|
2454
2527
|
hoverPrimitive("lift", ["translate"], liftParams),
|
|
2528
|
+
hoverPrimitive("pop", ["scale"], popParams),
|
|
2455
2529
|
hoverPrimitive("lift-shadow", ["translate", "shadow"], liftParams),
|
|
2456
2530
|
hoverPrimitive("shine-sweep", ["sweep"]),
|
|
2457
2531
|
hoverPrimitive("split-flap", ["rotate"]),
|
|
@@ -2762,12 +2836,173 @@ var kuinetic = (() => {
|
|
|
2762
2836
|
return registry.registerPrimitives(INTERACTION_PRIMITIVES).registerPresets(INTERACTION_PRESETS);
|
|
2763
2837
|
}
|
|
2764
2838
|
|
|
2839
|
+
// src/effects/catalog/media-shared.ts
|
|
2840
|
+
var AXIS_DEGREES = { vertical: 0, horizontal: 90 };
|
|
2841
|
+
var UNIT_DEGREES = { deg: 1, grad: 0.9, rad: 180 / Math.PI, turn: 360 };
|
|
2842
|
+
var BAND_OVERLAP_PX = 1;
|
|
2843
|
+
var STAGE_CLASS = "kui-slat-stage";
|
|
2844
|
+
var SLAT_CLASS = "kui-slat-item";
|
|
2845
|
+
var GOLDEN_RATIO_CONJUGATE = 0.6180339887498949;
|
|
2846
|
+
function slatOrder(index, count, from) {
|
|
2847
|
+
if (count <= 1) return 0;
|
|
2848
|
+
switch (from) {
|
|
2849
|
+
case "start":
|
|
2850
|
+
return index;
|
|
2851
|
+
case "end":
|
|
2852
|
+
return count - 1 - index;
|
|
2853
|
+
case "edges":
|
|
2854
|
+
return Math.min(index, count - 1 - index);
|
|
2855
|
+
case "random-ish":
|
|
2856
|
+
return Math.floor(index * GOLDEN_RATIO_CONJUGATE % 1 * count);
|
|
2857
|
+
case "alternate":
|
|
2858
|
+
default:
|
|
2859
|
+
return zigzagRank(index, count);
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2862
|
+
function zigzagRank(index, count) {
|
|
2863
|
+
const fromStart = index;
|
|
2864
|
+
const fromEnd = count - 1 - index;
|
|
2865
|
+
const pair = Math.min(fromStart, fromEnd);
|
|
2866
|
+
return fromStart <= fromEnd ? pair * 2 : pair * 2 + 1;
|
|
2867
|
+
}
|
|
2868
|
+
function slatAngleDegrees(authored, axis) {
|
|
2869
|
+
const trimmed = authored.trim();
|
|
2870
|
+
if (!trimmed) return AXIS_DEGREES[axis];
|
|
2871
|
+
const match = /^(-?(?:\d+(?:\.\d+)?|\.\d+))(deg|rad|grad|turn)?$/.exec(trimmed);
|
|
2872
|
+
if (!match) return AXIS_DEGREES[axis];
|
|
2873
|
+
const value = Number(match[1]);
|
|
2874
|
+
if (!Number.isFinite(value)) return AXIS_DEGREES[axis];
|
|
2875
|
+
const unit = match[2] ?? "deg";
|
|
2876
|
+
const degrees = value * UNIT_DEGREES[unit];
|
|
2877
|
+
return (degrees % 180 + 180) % 180;
|
|
2878
|
+
}
|
|
2879
|
+
function slatTravelVector(angleDegrees) {
|
|
2880
|
+
const theta = angleDegrees * Math.PI / 180;
|
|
2881
|
+
return { x: -Math.sin(theta), y: Math.cos(theta) };
|
|
2882
|
+
}
|
|
2883
|
+
function slatBandClip(index, count, angleDegrees, box) {
|
|
2884
|
+
const { width, height } = box;
|
|
2885
|
+
const theta = angleDegrees * Math.PI / 180;
|
|
2886
|
+
const nx = Math.cos(theta);
|
|
2887
|
+
const ny = Math.sin(theta);
|
|
2888
|
+
const { x: dx, y: dy } = slatTravelVector(angleDegrees);
|
|
2889
|
+
const span = Math.abs(nx) * width + Math.abs(ny) * height;
|
|
2890
|
+
const centreX = width / 2;
|
|
2891
|
+
const centreY = height / 2;
|
|
2892
|
+
const step = span / count;
|
|
2893
|
+
const near = index * step - span / 2 - BAND_OVERLAP_PX;
|
|
2894
|
+
const far = (index + 1) * step - span / 2 + BAND_OVERLAP_PX;
|
|
2895
|
+
const reach = width + height;
|
|
2896
|
+
const corner = (along, across) => `${(centreX + along * nx + across * dx).toFixed(2)}px ${(centreY + along * ny + across * dy).toFixed(2)}px`;
|
|
2897
|
+
return `polygon(${corner(near, reach)}, ${corner(near, -reach)}, ${corner(far, -reach)}, ${corner(far, reach)})`;
|
|
2898
|
+
}
|
|
2899
|
+
function axisLabel(angleDegrees) {
|
|
2900
|
+
if (angleDegrees === 0) return "vertical";
|
|
2901
|
+
if (angleDegrees === 90) return "horizontal";
|
|
2902
|
+
return "diagonal";
|
|
2903
|
+
}
|
|
2904
|
+
function syncStageToImage(stage, img, bands) {
|
|
2905
|
+
const { slats, angleDegrees } = bands;
|
|
2906
|
+
const width = img.offsetWidth;
|
|
2907
|
+
const height = img.offsetHeight;
|
|
2908
|
+
stage.style.top = `${img.offsetTop}px`;
|
|
2909
|
+
stage.style.left = `${img.offsetLeft}px`;
|
|
2910
|
+
stage.style.width = `${width}px`;
|
|
2911
|
+
stage.style.height = `${height}px`;
|
|
2912
|
+
slats.forEach((slat, index) => {
|
|
2913
|
+
slat.style.clipPath = slatBandClip(index, slats.length, angleDegrees, { width, height });
|
|
2914
|
+
});
|
|
2915
|
+
}
|
|
2916
|
+
function watchImageBox(stage, img, win, bands) {
|
|
2917
|
+
const handler = () => syncStageToImage(stage, img, bands);
|
|
2918
|
+
win.addEventListener("resize", handler, { passive: true });
|
|
2919
|
+
const stopWindow = () => win.removeEventListener("resize", handler);
|
|
2920
|
+
const ResizeObserverCtor = win.ResizeObserver;
|
|
2921
|
+
if (!ResizeObserverCtor) return stopWindow;
|
|
2922
|
+
const observer = new ResizeObserverCtor(handler);
|
|
2923
|
+
observer.observe(img);
|
|
2924
|
+
return () => {
|
|
2925
|
+
stopWindow();
|
|
2926
|
+
observer.disconnect();
|
|
2927
|
+
};
|
|
2928
|
+
}
|
|
2929
|
+
function imagePaintStyle(img, win) {
|
|
2930
|
+
const computed = win.getComputedStyle(img);
|
|
2931
|
+
const position = computed.objectPosition || "50% 50%";
|
|
2932
|
+
const fit = computed.objectFit;
|
|
2933
|
+
if (fit === "cover") return { size: "cover", position };
|
|
2934
|
+
if (fit === "contain" || fit === "scale-down") return { size: "contain", position };
|
|
2935
|
+
if (fit === "none") return { size: "auto", position };
|
|
2936
|
+
return { size: "100% 100%", position };
|
|
2937
|
+
}
|
|
2938
|
+
function installSlatStage(el, doc, win, options) {
|
|
2939
|
+
const img = el.querySelector("img");
|
|
2940
|
+
if (!img) return null;
|
|
2941
|
+
const url = img.currentSrc || img.getAttribute("src") || "";
|
|
2942
|
+
if (!url) return null;
|
|
2943
|
+
const { count, angleDegrees, from, fold } = options;
|
|
2944
|
+
const travel = slatTravelVector(angleDegrees);
|
|
2945
|
+
const stage = doc.createElement("div");
|
|
2946
|
+
stage.className = STAGE_CLASS;
|
|
2947
|
+
stage.setAttribute("aria-hidden", "true");
|
|
2948
|
+
stage.dataset.kuiSlatAxis = axisLabel(angleDegrees);
|
|
2949
|
+
stage.dataset.kuiSlatAngle = String(angleDegrees);
|
|
2950
|
+
stage.dataset.kuiSlatFold = String(fold);
|
|
2951
|
+
stage.style.setProperty("--kui-slat-count", String(count));
|
|
2952
|
+
stage.style.setProperty("--kui-slat-dx", travel.x.toFixed(4));
|
|
2953
|
+
stage.style.setProperty("--kui-slat-dy", travel.y.toFixed(4));
|
|
2954
|
+
const paint = imagePaintStyle(img, win);
|
|
2955
|
+
const slats = [];
|
|
2956
|
+
for (let index = 0; index < count; index++) {
|
|
2957
|
+
const slat = doc.createElement("div");
|
|
2958
|
+
slat.className = SLAT_CLASS;
|
|
2959
|
+
slat.style.setProperty("--kui-slat-index", String(index));
|
|
2960
|
+
slat.style.setProperty("--kui-i", String(slatOrder(index, count, from)));
|
|
2961
|
+
slat.style.backgroundImage = `url("${url}")`;
|
|
2962
|
+
slat.style.backgroundSize = paint.size;
|
|
2963
|
+
slat.style.backgroundPosition = paint.position;
|
|
2964
|
+
stage.append(slat);
|
|
2965
|
+
slats.push(slat);
|
|
2966
|
+
}
|
|
2967
|
+
el.append(stage);
|
|
2968
|
+
const bands = { slats, angleDegrees };
|
|
2969
|
+
syncStageToImage(stage, img, bands);
|
|
2970
|
+
const stopWatching = watchImageBox(stage, img, win, bands);
|
|
2971
|
+
const imageStyles = createStyleLedger(img);
|
|
2972
|
+
imageStyles.set("visibility", "hidden");
|
|
2973
|
+
return {
|
|
2974
|
+
stage,
|
|
2975
|
+
slats,
|
|
2976
|
+
restore: () => {
|
|
2977
|
+
stopWatching();
|
|
2978
|
+
imageStyles.restore();
|
|
2979
|
+
stage.remove();
|
|
2980
|
+
}
|
|
2981
|
+
};
|
|
2982
|
+
}
|
|
2983
|
+
function applySlatTimingVars(stage, params) {
|
|
2984
|
+
const { durationMs, delayMs, easing } = params.timing;
|
|
2985
|
+
const duration = durationMs === void 0 ? params.text("duration", "500ms") : `${durationMs}ms`;
|
|
2986
|
+
const delay = delayMs === void 0 ? params.text("delay", "0ms") : `${delayMs}ms`;
|
|
2987
|
+
stage.style.setProperty("--kui-duration", duration);
|
|
2988
|
+
stage.style.setProperty("--kui-delay", delay);
|
|
2989
|
+
stage.style.setProperty("--kui-ease", easing ?? params.text("ease", "ease-out"));
|
|
2990
|
+
stage.style.setProperty("--kui-stagger", params.text("stagger", "60ms"));
|
|
2991
|
+
}
|
|
2992
|
+
function slatAssembleFinishMs(params, count) {
|
|
2993
|
+
if (count === 0) return 0;
|
|
2994
|
+
const durationMs = params.timing.durationMs ?? params.ms("duration", 500);
|
|
2995
|
+
const delayMs = params.timing.delayMs ?? params.ms("delay", 0);
|
|
2996
|
+
const staggerMs = params.ms("stagger", 60);
|
|
2997
|
+
return delayMs + (count - 1) * staggerMs + durationMs;
|
|
2998
|
+
}
|
|
2999
|
+
|
|
2765
3000
|
// src/effects/catalog/media.ts
|
|
2766
3001
|
var geometry = {
|
|
2767
3002
|
distance: { type: "length", default: "24px", cssProperty: "--kui-distance" },
|
|
2768
3003
|
scale: { type: "number", default: "1.12", cssProperty: "--kui-to-scale" }
|
|
2769
3004
|
};
|
|
2770
|
-
var
|
|
3005
|
+
var MEDIA_CSS_PRIMITIVES = [
|
|
2771
3006
|
cssPrimitive("media-wipe", [CHANNEL.clip]),
|
|
2772
3007
|
cssPrimitive("media-mask", ["mask"], { perfClass: "paint" }),
|
|
2773
3008
|
// Not `reducedMotion: 'disable'` — that policy means "no finite duration would make sense,
|
|
@@ -2788,33 +3023,66 @@ var kuinetic = (() => {
|
|
|
2788
3023
|
defaultActivation: "hover",
|
|
2789
3024
|
perfClass: "paint"
|
|
2790
3025
|
}),
|
|
3026
|
+
// `geometry.distance` only, not `...geometry`: `kui-blur-up` (media.css) reads `--kui-distance`
|
|
3027
|
+
// and `--kui-blur` but never `--kui-to-scale` — this primitive doesn't even declare
|
|
3028
|
+
// `CHANNEL.scale`. Spreading the whole shared object used to expose `scale:` as an
|
|
3029
|
+
// apparently-valid, silently-inert parameter, the same shape `flip-3d`'s dead `perspective`
|
|
3030
|
+
// parameter was (`entrance.css`'s comment on `kui-flip-in-x`).
|
|
2791
3031
|
cssPrimitive("media-blur-up", [CHANNEL.translate, CHANNEL.filter], {
|
|
2792
|
-
parameters: {
|
|
3032
|
+
parameters: {
|
|
3033
|
+
distance: geometry.distance,
|
|
3034
|
+
blur: { type: "length", default: "16px", cssProperty: "--kui-blur" }
|
|
3035
|
+
},
|
|
2793
3036
|
perfClass: "paint"
|
|
2794
3037
|
}),
|
|
3038
|
+
// No `defaultActivation` — same convention `core.ts`'s `parallax`/`parallax-scale`/
|
|
3039
|
+
// `parallax-rotate`/`scroll-fade`/`desaturate`/`skew`/`progress`/`progress-stroke` already use
|
|
3040
|
+
// for every other `timelines: ['view', 'scroll', ...]` primitive. `resolveActivation`
|
|
3041
|
+
// (`animator.ts`) only consults `defaultActivation` when the author named no activation, and
|
|
3042
|
+
// falls through to `element-config.ts`'s hardcoded `'enter'` when a primitive declares none.
|
|
3043
|
+
// Setting it to `'manual'` here (matching `activations: ['manual']`) looked like the obviously
|
|
3044
|
+
// correct pairing, but it is what actually broke the effect: `effectiveActivation`
|
|
3045
|
+
// (`style-plan.ts`) only converts a stuck `'manual'` into `'enter'` when `config.timeline !==
|
|
3046
|
+
// 'time'` — i.e. only once the author has actually written `timeline:view`/`timeline:scroll`.
|
|
3047
|
+
// Authored bare (no `timeline:`, the sweep's own probe and the likely first thing anyone
|
|
3048
|
+
// tries), `config.timeline` stays the default `'time'`, that conversion never fires, and the
|
|
3049
|
+
// element sits at `data-kui-state="ready"` forever — which is also the state
|
|
3050
|
+
// `entrance.css`'s `[data-kui-state='ready'] { --kui-distance: 0px !important; }` targets, so
|
|
3051
|
+
// every sample read the same permanently-zeroed `--kui-distance`: not a paused animation, a
|
|
3052
|
+
// zeroed one. `timeline:view`/`timeline:scroll` usage is unaffected either way, since a native
|
|
3053
|
+
// timeline resolves to the `'native-timeline'` gate before activation is even consulted.
|
|
3054
|
+
// `geometry.distance` only: `kui-image-parallax-frame` never reads `--kui-to-scale` and this
|
|
3055
|
+
// primitive doesn't declare `CHANNEL.scale` — same dead-parameter shape as `media-blur-up` above.
|
|
2795
3056
|
cssPrimitive("media-parallax-frame", [CHANNEL.translate], {
|
|
2796
|
-
parameters: geometry,
|
|
3057
|
+
parameters: { distance: geometry.distance },
|
|
2797
3058
|
timelines: ["view", "scroll"],
|
|
2798
3059
|
activations: ["manual"],
|
|
2799
|
-
defaultActivation: "manual",
|
|
2800
3060
|
reducedMotion: "disable"
|
|
2801
3061
|
}),
|
|
3062
|
+
// Its own `scale` parameter, not `geometry`: `kui-lightbox-open` opens from a fixed 0.92, never
|
|
3063
|
+
// reading `--kui-to-scale` (or any `distance`, since this primitive doesn't animate position at
|
|
3064
|
+
// all) — the whole shared object was dead weight here. Unlike `media-blur-up`/
|
|
3065
|
+
// `media-parallax-frame`, this primitive *does* declare `CHANNEL.scale`, so the fix is to wire
|
|
3066
|
+
// the keyframe up to a real parameter rather than remove the promise: `--kui-from-scale`, the
|
|
3067
|
+
// same name and "starts at this scale, animates to 1" meaning `scale`/`scale-move`
|
|
3068
|
+
// (`catalog/core.ts`) already use, so `lightbox-open scale:0.8` now does what it looks like it
|
|
3069
|
+
// should. See `kui-lightbox-open` in `media.css`.
|
|
2802
3070
|
cssPrimitive("media-lightbox", [CHANNEL.opacity, CHANNEL.scale], {
|
|
2803
|
-
parameters:
|
|
3071
|
+
parameters: { scale: { type: "number", default: "0.92", cssProperty: "--kui-from-scale" } }
|
|
2804
3072
|
})
|
|
2805
3073
|
];
|
|
2806
|
-
var
|
|
2807
|
-
{ name: "wipe-up", primitive: "media-wipe", keyframes: "kui-wipe-up" },
|
|
2808
|
-
{ name: "wipe-down", primitive: "media-wipe", keyframes: "kui-wipe-down" },
|
|
2809
|
-
{ name: "wipe-left", primitive: "media-wipe", keyframes: "kui-wipe-left" },
|
|
2810
|
-
{ name: "wipe-right", primitive: "media-wipe", keyframes: "kui-wipe-right" },
|
|
2811
|
-
{ name: "wipe-circle", primitive: "media-wipe", keyframes: "kui-wipe-circle" },
|
|
2812
|
-
{ name: "wipe-diagonal", primitive: "media-wipe", keyframes: "kui-wipe-diagonal" },
|
|
2813
|
-
{ name: "mask-reveal", primitive: "media-mask", keyframes: "kui-mask-reveal" },
|
|
2814
|
-
{ name: "curtain-reveal", primitive: "media-wipe", keyframes: "kui-curtain-reveal" },
|
|
3074
|
+
var MEDIA_CSS_PRESETS = [
|
|
3075
|
+
{ name: "wipe-up", primitive: "media-wipe", keyframes: "kui-wipe-up", cloak: true },
|
|
3076
|
+
{ name: "wipe-down", primitive: "media-wipe", keyframes: "kui-wipe-down", cloak: true },
|
|
3077
|
+
{ name: "wipe-left", primitive: "media-wipe", keyframes: "kui-wipe-left", cloak: true },
|
|
3078
|
+
{ name: "wipe-right", primitive: "media-wipe", keyframes: "kui-wipe-right", cloak: true },
|
|
3079
|
+
{ name: "wipe-circle", primitive: "media-wipe", keyframes: "kui-wipe-circle", cloak: true },
|
|
3080
|
+
{ name: "wipe-diagonal", primitive: "media-wipe", keyframes: "kui-wipe-diagonal", cloak: true },
|
|
3081
|
+
{ name: "mask-reveal", primitive: "media-mask", keyframes: "kui-mask-reveal", cloak: true },
|
|
3082
|
+
{ name: "curtain-reveal", primitive: "media-wipe", keyframes: "kui-curtain-reveal", cloak: true },
|
|
2815
3083
|
{ name: "ken-burns", primitive: "media-ken-burns", keyframes: "kui-ken-burns" },
|
|
2816
3084
|
{ name: "ken-burns-out", primitive: "media-ken-burns", keyframes: "kui-ken-burns-out" },
|
|
2817
|
-
{ name: "blur-up", primitive: "media-blur-up", keyframes: "kui-blur-up" },
|
|
3085
|
+
{ name: "blur-up", primitive: "media-blur-up", keyframes: "kui-blur-up", cloak: true },
|
|
2818
3086
|
{ name: "duotone-hover", primitive: "media-filter", keyframes: "kui-duotone-hover" },
|
|
2819
3087
|
{ name: "grayscale-hover", primitive: "media-filter", keyframes: "kui-grayscale-hover" },
|
|
2820
3088
|
{ name: "saturate-hover", primitive: "media-filter", keyframes: "kui-saturate-hover" },
|
|
@@ -2826,14 +3094,131 @@ var kuinetic = (() => {
|
|
|
2826
3094
|
{ name: "before-after-wipe", primitive: "media-wipe", keyframes: "kui-before-after-wipe" },
|
|
2827
3095
|
{ name: "lightbox-open", primitive: "media-lightbox", keyframes: "kui-lightbox-open" }
|
|
2828
3096
|
];
|
|
3097
|
+
var slatParams = {
|
|
3098
|
+
slats: {
|
|
3099
|
+
type: "number",
|
|
3100
|
+
default: "8",
|
|
3101
|
+
cssProperty: "--kui-slats",
|
|
3102
|
+
minimum: 2,
|
|
3103
|
+
maximum: 24,
|
|
3104
|
+
integer: true
|
|
3105
|
+
},
|
|
3106
|
+
axis: {
|
|
3107
|
+
type: "keyword",
|
|
3108
|
+
default: "vertical",
|
|
3109
|
+
cssProperty: "--kui-axis",
|
|
3110
|
+
values: ["vertical", "horizontal"]
|
|
3111
|
+
},
|
|
3112
|
+
/*
|
|
3113
|
+
* The general form of `axis:`, in degrees: `0deg` is `axis:vertical`, `90deg` is
|
|
3114
|
+
* `axis:horizontal`, and anything between cuts the picture into diagonal bands. An authored
|
|
3115
|
+
* angle wins; leaving it off reads `axis:`, so every existing attribute keeps its meaning.
|
|
3116
|
+
*
|
|
3117
|
+
* `text`, not `angle`, for one reason: `readParams` pre-fills every declared parameter with its
|
|
3118
|
+
* schema default, so a typed default is indistinguishable from an authored value and there would
|
|
3119
|
+
* be no way to tell `angle:0deg` from "no angle, use the axis". An empty default is only possible
|
|
3120
|
+
* on a type that is never written to a stylesheet, which is exactly what `text` is for — and this
|
|
3121
|
+
* value never reaches CSS anyway. `slatAngleDegrees` does the parsing and the range clamp.
|
|
3122
|
+
*/
|
|
3123
|
+
angle: { type: "text", default: "", cssProperty: "--kui-slat-angle" },
|
|
3124
|
+
from: {
|
|
3125
|
+
type: "keyword",
|
|
3126
|
+
default: "alternate",
|
|
3127
|
+
cssProperty: "--kui-from",
|
|
3128
|
+
values: ["alternate", "start", "end", "edges", "random-ish"]
|
|
3129
|
+
},
|
|
3130
|
+
fold: { type: "keyword", default: "false", cssProperty: "--kui-fold", values: ["true", "false"] },
|
|
3131
|
+
duration: { type: "time", default: "500ms", cssProperty: "--kui-duration" },
|
|
3132
|
+
delay: { type: "time", default: "0ms", cssProperty: "--kui-delay" },
|
|
3133
|
+
ease: { type: "easing", default: "ease-out", cssProperty: "--kui-ease" },
|
|
3134
|
+
stagger: { type: "time", default: "60ms", cssProperty: "--kui-stagger" }
|
|
3135
|
+
};
|
|
3136
|
+
function prepareSlatAssemble(el, params, ctx) {
|
|
3137
|
+
const doc = el.ownerDocument;
|
|
3138
|
+
const count = Math.min(24, Math.max(2, Math.round(params.num("slats", 8))));
|
|
3139
|
+
const axis = params.text("axis", "vertical");
|
|
3140
|
+
const angleDegrees = slatAngleDegrees(params.text("angle", ""), axis);
|
|
3141
|
+
const from = params.text("from", "alternate");
|
|
3142
|
+
const fold = params.is("fold");
|
|
3143
|
+
const node = el;
|
|
3144
|
+
if (ctx.win.getComputedStyle(node).position === "static") ctx.style.set("position", "relative");
|
|
3145
|
+
const built = installSlatStage(el, doc, ctx.win, { count, angleDegrees, from, fold });
|
|
3146
|
+
if (!built) return () => {
|
|
3147
|
+
};
|
|
3148
|
+
const { stage } = built;
|
|
3149
|
+
applySlatTimingVars(stage, params);
|
|
3150
|
+
stage.classList.add("kui-slat-animating");
|
|
3151
|
+
let settle2;
|
|
3152
|
+
const finished = new Promise((resolve) => {
|
|
3153
|
+
settle2 = resolve;
|
|
3154
|
+
});
|
|
3155
|
+
let landed = false;
|
|
3156
|
+
const land = () => {
|
|
3157
|
+
if (landed) return;
|
|
3158
|
+
landed = true;
|
|
3159
|
+
stage.classList.remove("kui-slat-animating");
|
|
3160
|
+
built.restore();
|
|
3161
|
+
settle2();
|
|
3162
|
+
};
|
|
3163
|
+
const timer = ctx.win.setTimeout(land, slatAssembleFinishMs(params, count));
|
|
3164
|
+
return {
|
|
3165
|
+
cleanup: () => {
|
|
3166
|
+
ctx.win.clearTimeout(timer);
|
|
3167
|
+
if (landed) return;
|
|
3168
|
+
landed = true;
|
|
3169
|
+
built.restore();
|
|
3170
|
+
},
|
|
3171
|
+
finished,
|
|
3172
|
+
finish: () => {
|
|
3173
|
+
ctx.win.clearTimeout(timer);
|
|
3174
|
+
land();
|
|
3175
|
+
}
|
|
3176
|
+
};
|
|
3177
|
+
}
|
|
3178
|
+
var MEDIA_JS_PRIMITIVES = [
|
|
3179
|
+
{
|
|
3180
|
+
id: "slat-assemble",
|
|
3181
|
+
renderer: "javascript",
|
|
3182
|
+
channels: [CHANNEL.opacity, CHANNEL.translate, CHANNEL.rotate],
|
|
3183
|
+
parameters: slatParams,
|
|
3184
|
+
supportedTimelines: ["time"],
|
|
3185
|
+
supportedActivations: ["load", "enter", "hover", "focus", "click", "manual"],
|
|
3186
|
+
defaultActivation: "enter",
|
|
3187
|
+
perfClass: "dom-transform",
|
|
3188
|
+
// Same reasoning as every JS-rendered primitive in `text.ts`: nothing here declares a CSS
|
|
3189
|
+
// `animation-duration` the reduced-motion policy layer could shorten, and `disable` is what
|
|
3190
|
+
// stops `installSlatStage`'s DOM surgery from ever running at all under reduced motion — the
|
|
3191
|
+
// animator never calls `activate()`, so the wrapped `<img>` is simply left exactly as authored.
|
|
3192
|
+
reducedMotion: "disable",
|
|
3193
|
+
// Land()ing hands the picture back to the real `<img>` and tears down every slat — see
|
|
3194
|
+
// `prepareSlatAssemble`'s `land()`. Declared, not assumed: see `restoresOnFinish`'s own comment
|
|
3195
|
+
// in `core/types.ts` for why the catalog's default is the opposite of this.
|
|
3196
|
+
restoresOnFinish: true,
|
|
3197
|
+
prepare: deferPrepare(prepareSlatAssemble)
|
|
3198
|
+
}
|
|
3199
|
+
];
|
|
3200
|
+
var MEDIA_JS_PRESETS = [
|
|
3201
|
+
{ name: "slat-assemble", primitive: "slat-assemble", cloak: true }
|
|
3202
|
+
];
|
|
3203
|
+
var MEDIA_PRIMITIVES = [...MEDIA_CSS_PRIMITIVES, ...MEDIA_JS_PRIMITIVES];
|
|
3204
|
+
var MEDIA_PRESETS = [...MEDIA_CSS_PRESETS, ...MEDIA_JS_PRESETS];
|
|
2829
3205
|
function registerMedia(registry) {
|
|
2830
3206
|
return registry.registerPrimitives(MEDIA_PRIMITIVES).registerPresets(MEDIA_PRESETS);
|
|
2831
3207
|
}
|
|
2832
3208
|
|
|
3209
|
+
// src/effects/catalog/subtree-capture.ts
|
|
3210
|
+
function captureChildren(el) {
|
|
3211
|
+
const authored = Array.from(el.childNodes);
|
|
3212
|
+
return () => {
|
|
3213
|
+
el.replaceChildren(...authored);
|
|
3214
|
+
};
|
|
3215
|
+
}
|
|
3216
|
+
|
|
2833
3217
|
// src/effects/catalog/numbers-shared.ts
|
|
2834
3218
|
var SR_ONLY_CLASS = "kui-sr-only";
|
|
2835
3219
|
var DECORATIVE_CLASS = "kui-count-decorative";
|
|
2836
3220
|
function installCountLayers(el, doc) {
|
|
3221
|
+
const restoreChildren = captureChildren(el);
|
|
2837
3222
|
const decorative = doc.createElement("span");
|
|
2838
3223
|
decorative.setAttribute("aria-hidden", "true");
|
|
2839
3224
|
decorative.className = DECORATIVE_CLASS;
|
|
@@ -2845,9 +3230,7 @@ var kuinetic = (() => {
|
|
|
2845
3230
|
return {
|
|
2846
3231
|
decorative,
|
|
2847
3232
|
srOnly,
|
|
2848
|
-
restore:
|
|
2849
|
-
el.textContent = srOnly.textContent;
|
|
2850
|
-
}
|
|
3233
|
+
restore: restoreChildren
|
|
2851
3234
|
};
|
|
2852
3235
|
}
|
|
2853
3236
|
function easeOutCubic(t) {
|
|
@@ -3157,7 +3540,12 @@ var kuinetic = (() => {
|
|
|
3157
3540
|
];
|
|
3158
3541
|
var METER_PRIMITIVES = [
|
|
3159
3542
|
cssPrimitive("stroke-sweep", [CHANNEL.stroke]),
|
|
3160
|
-
|
|
3543
|
+
// `from` gives `progress-bar` a real knob on its start scale — it had none before. `--kui-bar-from`
|
|
3544
|
+
// is also what the `[data-kui-fx~='progress-bar'][data-kui-state='ready']` gate in numbers.css
|
|
3545
|
+
// neutralizes; see that rule's comment for the on:enter fix this parameter doubles as.
|
|
3546
|
+
cssPrimitive("meter-bar", [CHANNEL.scale], {
|
|
3547
|
+
parameters: { from: { type: "number", default: "0", cssProperty: "--kui-bar-from" } }
|
|
3548
|
+
}),
|
|
3161
3549
|
cssPrimitive("meter-segments", [CHANNEL.opacity]),
|
|
3162
3550
|
cssPrimitive("meter-stars", [CHANNEL.clip])
|
|
3163
3551
|
];
|
|
@@ -3166,7 +3554,13 @@ var kuinetic = (() => {
|
|
|
3166
3554
|
{ name: "gauge-sweep", primitive: "stroke-sweep", keyframes: "kui-gauge-sweep" },
|
|
3167
3555
|
{ name: "donut-sweep", primitive: "stroke-sweep", keyframes: "kui-donut-sweep" },
|
|
3168
3556
|
{ name: "sparkline-draw", primitive: "stroke-sweep", keyframes: "kui-sparkline-draw" },
|
|
3169
|
-
|
|
3557
|
+
// `cloak: true`: `kui-progress-bar`'s `from { scale: 0 1 }` (numbers.css) is a zero-width box
|
|
3558
|
+
// while paused, not just an invisible one — so while it waits it occupies no space in layout at
|
|
3559
|
+
// all. Not, despite the tidier story, because an observer refuses to fire on it: Chromium was
|
|
3560
|
+
// measured resolving a zero-area target's `intersectionRatio` to `1`. See numbers.css's
|
|
3561
|
+
// `[data-kui-fx~='progress-bar'][data-kui-state='ready']` rule for the geometry half of the fix;
|
|
3562
|
+
// `cloak` keeps the pre-JS and post-JS "waiting" look the same (invisible) either side of it.
|
|
3563
|
+
{ name: "progress-bar", primitive: "meter-bar", keyframes: "kui-progress-bar", cloak: true },
|
|
3170
3564
|
{ name: "progress-segments", primitive: "meter-segments", keyframes: "kui-progress-segments" },
|
|
3171
3565
|
{ name: "star-rating-fill", primitive: "meter-stars", keyframes: "kui-star-rating-fill" }
|
|
3172
3566
|
];
|
|
@@ -3181,6 +3575,7 @@ var kuinetic = (() => {
|
|
|
3181
3575
|
var DECORATIVE_CLASS2 = "kui-split-decorative";
|
|
3182
3576
|
function installSplitLayers(el, doc) {
|
|
3183
3577
|
const originalText = el.textContent.trim();
|
|
3578
|
+
const restoreChildren = captureChildren(el);
|
|
3184
3579
|
const decorative = doc.createElement("span");
|
|
3185
3580
|
decorative.setAttribute("aria-hidden", "true");
|
|
3186
3581
|
decorative.className = DECORATIVE_CLASS2;
|
|
@@ -3192,9 +3587,7 @@ var kuinetic = (() => {
|
|
|
3192
3587
|
return {
|
|
3193
3588
|
decorative,
|
|
3194
3589
|
originalText,
|
|
3195
|
-
restore:
|
|
3196
|
-
el.textContent = originalText;
|
|
3197
|
-
}
|
|
3590
|
+
restore: restoreChildren
|
|
3198
3591
|
};
|
|
3199
3592
|
}
|
|
3200
3593
|
function segmentGraphemes(text) {
|
|
@@ -3362,14 +3755,43 @@ var kuinetic = (() => {
|
|
|
3362
3755
|
distance: { type: "length", default: "32px", cssProperty: "--kui-distance" }
|
|
3363
3756
|
};
|
|
3364
3757
|
var TEXT_CSS_PRIMITIVES = [
|
|
3365
|
-
|
|
3758
|
+
// `color`, alongside `background`: both presets' unconditional rule sets `-webkit-text-fill-color:
|
|
3759
|
+
// transparent` so the `background-image` gradient shows through the glyphs (the standard
|
|
3760
|
+
// gradient-text technique). That is a real claim on the glyph fill, the same physical property
|
|
3761
|
+
// `text-outline-fill` animates on its own `color` channel below — without this, the two looked
|
|
3762
|
+
// disjoint to the compiler (`background` vs `stroke`+`color`) and composing them would let
|
|
3763
|
+
// whichever applied last silently win the glyph fill instead of being flagged as a conflict.
|
|
3764
|
+
cssPrimitive("text-shimmer", [CHANNEL.background, CHANNEL.color], { reducedMotion: "disable" }),
|
|
3765
|
+
// `gradient-sweep` is the only one of the three `text-sweep`-family presets whose keyframe
|
|
3766
|
+
// touches `-webkit-text-fill-color` (see text.css) — `highlight-sweep` and `underline-draw` only
|
|
3767
|
+
// paint a `background-image`. Claiming `color` for all three made the compiler reject compositions
|
|
3768
|
+
// like `underline-draw, text-outline-fill` as a glyph-fill conflict even though they touch disjoint
|
|
3769
|
+
// properties. Split so only the preset that actually claims the fill declares the channel.
|
|
3770
|
+
cssPrimitive("text-gradient-sweep", [CHANNEL.background, CHANNEL.color], { parameters: textSweepParams }),
|
|
3366
3771
|
cssPrimitive("text-sweep", [CHANNEL.background], { parameters: textSweepParams }),
|
|
3367
3772
|
cssPrimitive("text-outline-fill", [CHANNEL.stroke, CHANNEL.color]),
|
|
3368
3773
|
cssPrimitive("var-weight", ["font"], { parameters: fontWeightParams }),
|
|
3369
3774
|
cssPrimitive("var-width", ["font"], { parameters: fontWidthParams }),
|
|
3370
3775
|
cssPrimitive("var-slant", ["font"], { parameters: fontSlantParams }),
|
|
3776
|
+
/*
|
|
3777
|
+
* `defaultActivation: 'load'` for the same reason every ambient primitive declares it, and it
|
|
3778
|
+
* was missing here: a marquee is continuous motion, so `reducedMotion: 'disable'` is only half
|
|
3779
|
+
* the rule `ambient.ts` spells out — the other half is starting on `load` rather than waiting on
|
|
3780
|
+
* a scroll-triggered `enter`.
|
|
3781
|
+
*
|
|
3782
|
+
* Without it, a bare `data-kui="marquee 42s"` resolved to `enter`, which `style-plan.ts`'s
|
|
3783
|
+
* `resolveGate` sends down the `deferred` path and stamps `animation-play-state: paused`. It
|
|
3784
|
+
* compiled correctly, reported `data-kui-state="ready"`, and never ran — measured on a marquee
|
|
3785
|
+
* fully in view, so this was not an observer that had simply not fired yet. Every page carrying
|
|
3786
|
+
* one had to know to write `on:load`, which is exactly the kind of thing an author cannot be
|
|
3787
|
+
* expected to guess.
|
|
3788
|
+
*
|
|
3789
|
+
* `marquee-scroll-linked` is unaffected: its position comes from `animation-timeline: scroll()`,
|
|
3790
|
+
* not from an activation.
|
|
3791
|
+
*/
|
|
3371
3792
|
cssPrimitive("text-marquee", [CHANNEL.translate], {
|
|
3372
3793
|
timelines: ["time", "scroll"],
|
|
3794
|
+
defaultActivation: "load",
|
|
3373
3795
|
reducedMotion: "disable"
|
|
3374
3796
|
}),
|
|
3375
3797
|
cssPrimitive("redaction-reveal", [CHANNEL.clip]),
|
|
@@ -3377,7 +3799,7 @@ var kuinetic = (() => {
|
|
|
3377
3799
|
];
|
|
3378
3800
|
var TEXT_CSS_PRESETS = [
|
|
3379
3801
|
{ name: "gradient-shimmer", primitive: "text-shimmer", keyframes: "kui-gradient-shimmer" },
|
|
3380
|
-
{ name: "gradient-sweep", primitive: "text-sweep", keyframes: "kui-gradient-sweep" },
|
|
3802
|
+
{ name: "gradient-sweep", primitive: "text-gradient-sweep", keyframes: "kui-gradient-sweep" },
|
|
3381
3803
|
{
|
|
3382
3804
|
name: "highlight-sweep",
|
|
3383
3805
|
primitive: "text-sweep",
|
|
@@ -3540,9 +3962,10 @@ var kuinetic = (() => {
|
|
|
3540
3962
|
layers.decorative.textContent = scrambledFrame(graphemes, resolved, charset, Math.random);
|
|
3541
3963
|
};
|
|
3542
3964
|
render();
|
|
3965
|
+
const totalTicks = Math.max(1, graphemes.length * revealEvery);
|
|
3543
3966
|
const run = createStepRunner(ctx.win, {
|
|
3544
3967
|
delayMs: params.timing.delayMs ?? 0,
|
|
3545
|
-
stepMs: stepMsFor(params,
|
|
3968
|
+
stepMs: stepMsFor(params, totalTicks, Math.max(1, 700 / totalTicks)),
|
|
3546
3969
|
tick: () => {
|
|
3547
3970
|
ticks++;
|
|
3548
3971
|
if (ticks % revealEvery === 0) resolved++;
|
|
@@ -3567,7 +3990,7 @@ var kuinetic = (() => {
|
|
|
3567
3990
|
const words = params.text("words", "").split("|").map((word) => word.trim()).filter(Boolean);
|
|
3568
3991
|
if (words.length === 0) return () => {
|
|
3569
3992
|
};
|
|
3570
|
-
const
|
|
3993
|
+
const restoreChildren = captureChildren(el);
|
|
3571
3994
|
const swapMs = 150;
|
|
3572
3995
|
let index = 0;
|
|
3573
3996
|
el.textContent = words[0];
|
|
@@ -3588,7 +4011,7 @@ var kuinetic = (() => {
|
|
|
3588
4011
|
cleanup: () => {
|
|
3589
4012
|
run.stop();
|
|
3590
4013
|
el.classList.remove("kui-word-cycler-swap");
|
|
3591
|
-
|
|
4014
|
+
restoreChildren();
|
|
3592
4015
|
},
|
|
3593
4016
|
finished: run.finished,
|
|
3594
4017
|
finish: () => run.stop()
|
|
@@ -3624,9 +4047,9 @@ var kuinetic = (() => {
|
|
|
3624
4047
|
{ name: "split-chars", primitive: "split-text", params: { unit: "chars", direction: "fade" } },
|
|
3625
4048
|
{ name: "split-words", primitive: "split-text", params: { unit: "words", direction: "fade" } },
|
|
3626
4049
|
{ name: "split-lines", primitive: "split-text", params: { unit: "lines", direction: "fade" } },
|
|
3627
|
-
{ name: "text-reveal-up", primitive: "split-text", params: { unit: "words", direction: "up" } },
|
|
3628
|
-
{ name: "text-reveal-down", primitive: "split-text", params: { unit: "words", direction: "down" } },
|
|
3629
|
-
{ name: "text-reveal-mask", primitive: "split-text", params: { unit: "lines", direction: "mask" } },
|
|
4050
|
+
{ name: "text-reveal-up", primitive: "split-text", params: { unit: "words", direction: "up" }, cloak: true },
|
|
4051
|
+
{ name: "text-reveal-down", primitive: "split-text", params: { unit: "words", direction: "down" }, cloak: true },
|
|
4052
|
+
{ name: "text-reveal-mask", primitive: "split-text", params: { unit: "lines", direction: "mask" }, cloak: true },
|
|
3630
4053
|
{ name: "text-wave", primitive: "split-text-motion", params: { motion: "wave" } },
|
|
3631
4054
|
{ name: "text-jitter", primitive: "split-text-motion", params: { motion: "jitter" } },
|
|
3632
4055
|
{ name: "typewriter", primitive: "typewriter", params: { loop: "false" } },
|
|
@@ -3658,66 +4081,130 @@ var kuinetic = (() => {
|
|
|
3658
4081
|
distance: { type: "length", default: "24px", cssProperty: "--kui-distance" },
|
|
3659
4082
|
opacity: { type: "number", default: "0", cssProperty: "--kui-from-opacity" }
|
|
3660
4083
|
};
|
|
4084
|
+
var ENTRANCE_TIMELINES = ["time", "view", "scroll", "pin"];
|
|
3661
4085
|
var PRIMITIVES = [
|
|
3662
4086
|
// --- entrance / exit -------------------------------------------------------------------
|
|
3663
|
-
cssPrimitive("reveal", [CHANNEL.opacity, CHANNEL.translate], { parameters: distance2 }),
|
|
4087
|
+
cssPrimitive("reveal", [CHANNEL.opacity, CHANNEL.translate], { timelines: ENTRANCE_TIMELINES, parameters: distance2 }),
|
|
3664
4088
|
cssPrimitive("scale", [CHANNEL.scale], {
|
|
4089
|
+
timelines: ENTRANCE_TIMELINES,
|
|
3665
4090
|
parameters: { scale: { type: "number", default: "0.92", cssProperty: "--kui-from-scale" } }
|
|
3666
4091
|
}),
|
|
3667
4092
|
// Separate from `scale` because it claims translate as well and so composes differently.
|
|
4093
|
+
// `distance.distance` only, not `...distance`: `kui-zoom-in-up`/`-down` (entrance.css) read
|
|
4094
|
+
// `--kui-distance` and `--kui-from-scale` but never `--kui-from-opacity` — this primitive
|
|
4095
|
+
// doesn't declare `CHANNEL.opacity`. Spreading the whole shared `distance` object used to expose
|
|
4096
|
+
// `opacity:` as an apparently-valid, silently-inert parameter (same dead-parameter shape as
|
|
4097
|
+
// `flip-3d`'s old `perspective`, fixed above).
|
|
3668
4098
|
cssPrimitive("scale-move", [CHANNEL.scale, CHANNEL.translate], {
|
|
4099
|
+
timelines: ENTRANCE_TIMELINES,
|
|
3669
4100
|
parameters: {
|
|
3670
|
-
|
|
4101
|
+
distance: distance2.distance,
|
|
3671
4102
|
scale: { type: "number", default: "0.92", cssProperty: "--kui-from-scale" }
|
|
3672
4103
|
}
|
|
3673
4104
|
}),
|
|
3674
4105
|
cssPrimitive("rotate", [CHANNEL.rotate], {
|
|
4106
|
+
timelines: ENTRANCE_TIMELINES,
|
|
3675
4107
|
parameters: { angle: { type: "angle", default: "-8deg", cssProperty: "--kui-from-angle" } }
|
|
3676
4108
|
}),
|
|
4109
|
+
// `distance.distance` only, not `...distance`: `kui-roll-in`/`-out` (entrance.css) write
|
|
4110
|
+
// `rotate`/`translate`, never `opacity` — this primitive doesn't declare `CHANNEL.opacity`. Same
|
|
4111
|
+
// dead-parameter shape as `scale-move` above.
|
|
3677
4112
|
cssPrimitive("roll", [CHANNEL.rotate, CHANNEL.translate], {
|
|
4113
|
+
timelines: ENTRANCE_TIMELINES,
|
|
3678
4114
|
parameters: {
|
|
3679
|
-
|
|
4115
|
+
distance: distance2.distance,
|
|
3680
4116
|
angle: { type: "angle", default: "-120deg", cssProperty: "--kui-from-angle" }
|
|
3681
4117
|
}
|
|
3682
4118
|
}),
|
|
3683
|
-
|
|
4119
|
+
// `skew`, not `rotate`: entrance.css's keyframes write `transform: perspective(...)
|
|
4120
|
+
// rotateX/Y(...)`, not the individual `rotate:` property — the `perspective` parameter below
|
|
4121
|
+
// used to compile cleanly and do nothing, because nothing read it. See entrance.css's own
|
|
4122
|
+
// comment on `kui-flip-in-x` for the fix; `CHANNEL.skew` is this catalog's name for "claims the
|
|
4123
|
+
// whole `transform` shorthand" (`core/types.ts`), shared with `scroll-skew` and `flip-face`.
|
|
4124
|
+
cssPrimitive("flip-3d", [CHANNEL.skew], {
|
|
4125
|
+
timelines: ENTRANCE_TIMELINES,
|
|
3684
4126
|
parameters: {
|
|
3685
4127
|
angle: { type: "angle", default: "90deg", cssProperty: "--kui-from-angle" },
|
|
3686
4128
|
perspective: { type: "length", default: "1200px", cssProperty: "--kui-perspective" }
|
|
3687
4129
|
}
|
|
3688
4130
|
}),
|
|
3689
4131
|
cssPrimitive("blur", [CHANNEL.filter], {
|
|
4132
|
+
timelines: ENTRANCE_TIMELINES,
|
|
3690
4133
|
parameters: { blur: { type: "length", default: "12px", cssProperty: "--kui-blur" } }
|
|
3691
4134
|
}),
|
|
3692
4135
|
// Purpose-built combination: one keyframe, so opacity is written once instead of twice.
|
|
3693
4136
|
cssPrimitive("reveal-blur", [CHANNEL.opacity, CHANNEL.translate, CHANNEL.filter], {
|
|
4137
|
+
timelines: ENTRANCE_TIMELINES,
|
|
3694
4138
|
parameters: { ...distance2, blur: { type: "length", default: "12px", cssProperty: "--kui-blur" } }
|
|
3695
4139
|
}),
|
|
3696
4140
|
// --- scroll-linked ---------------------------------------------------------------------
|
|
3697
4141
|
// These are progress-linked, not time-triggered: they reverse as the user scrolls back.
|
|
3698
4142
|
// That is by design and is why `timeline:` is a different axis from `on:`.
|
|
4143
|
+
// `distance.distance` only, not the whole `distance` object: `kui-parallax-y`/`-x` (scroll.css)
|
|
4144
|
+
// write only `translate` — this primitive doesn't declare `CHANNEL.opacity`. Same dead-parameter
|
|
4145
|
+
// shape as `scale-move`/`roll` above; `parallax-y`/`parallax-x`/`depth-layer` never read
|
|
4146
|
+
// `--kui-from-opacity`.
|
|
3699
4147
|
cssPrimitive("parallax", [CHANNEL.translate], {
|
|
3700
|
-
parameters: distance2,
|
|
3701
|
-
timelines: ["view", "scroll"],
|
|
4148
|
+
parameters: { distance: distance2.distance },
|
|
4149
|
+
timelines: ["view", "scroll", "pin"],
|
|
3702
4150
|
activations: ["manual"],
|
|
3703
4151
|
reducedMotion: "disable",
|
|
3704
4152
|
perfClass: "compositor"
|
|
3705
4153
|
}),
|
|
4154
|
+
// `from` exists because the resting end was hardcoded (scale 1 / rotate 0deg), which fixed
|
|
4155
|
+
// these to "grow slightly" and "tilt slightly" — a scroll-driven element that should sweep in
|
|
4156
|
+
// from a quarter-size or from half a turn away had no way to say so. Same `--kui-from-*`
|
|
4157
|
+
// properties the entrance primitives already use, so the two stay spellable the same way.
|
|
3706
4158
|
cssPrimitive("parallax-scale", [CHANNEL.scale], {
|
|
3707
|
-
parameters: {
|
|
3708
|
-
|
|
4159
|
+
parameters: {
|
|
4160
|
+
scale: { type: "number", default: "1.2", cssProperty: "--kui-to-scale" },
|
|
4161
|
+
from: { type: "number", default: "1", cssProperty: "--kui-from-scale" }
|
|
4162
|
+
},
|
|
4163
|
+
timelines: ["view", "scroll", "pin"],
|
|
3709
4164
|
activations: ["manual"],
|
|
3710
4165
|
reducedMotion: "disable"
|
|
3711
4166
|
}),
|
|
3712
4167
|
cssPrimitive("parallax-rotate", [CHANNEL.rotate], {
|
|
3713
|
-
parameters: {
|
|
3714
|
-
|
|
4168
|
+
parameters: {
|
|
4169
|
+
angle: { type: "angle", default: "12deg", cssProperty: "--kui-to-angle" },
|
|
4170
|
+
from: { type: "angle", default: "0deg", cssProperty: "--kui-from-angle" }
|
|
4171
|
+
},
|
|
4172
|
+
timelines: ["view", "scroll", "pin"],
|
|
3715
4173
|
activations: ["manual"],
|
|
3716
4174
|
reducedMotion: "disable"
|
|
3717
4175
|
}),
|
|
3718
4176
|
cssPrimitive("scroll-fade", [CHANNEL.opacity], {
|
|
3719
4177
|
parameters: { opacity: { type: "number", default: "0", cssProperty: "--kui-from-opacity" } },
|
|
3720
|
-
timelines: ["view", "scroll"],
|
|
4178
|
+
timelines: ["view", "scroll", "pin"],
|
|
4179
|
+
activations: ["manual"],
|
|
4180
|
+
reducedMotion: "disable"
|
|
4181
|
+
}),
|
|
4182
|
+
// `filter`, not `opacity` — it collides with `blur`, and declaring the real channel is what
|
|
4183
|
+
// makes `channels.ts` say so instead of letting the two silently overwrite each other's
|
|
4184
|
+
// `filter` declaration.
|
|
4185
|
+
cssPrimitive("desaturate", [CHANNEL.filter], {
|
|
4186
|
+
parameters: {
|
|
4187
|
+
from: { type: "percentage", default: "100%", cssProperty: "--kui-from-grayscale" },
|
|
4188
|
+
to: { type: "percentage", default: "0%", cssProperty: "--kui-to-grayscale" }
|
|
4189
|
+
},
|
|
4190
|
+
timelines: ["view", "scroll", "pin"],
|
|
4191
|
+
activations: ["manual"],
|
|
4192
|
+
reducedMotion: "disable",
|
|
4193
|
+
perfClass: "paint"
|
|
4194
|
+
}),
|
|
4195
|
+
/*
|
|
4196
|
+
* `transform`, not one of the independent transform properties, because CSS never shipped a
|
|
4197
|
+
* standalone `skew:`. That is also why `skew` is its own channel rather than folded in with
|
|
4198
|
+
* `rotate`: writing `transform` replaces the entire shorthand, so a skew composed with anything
|
|
4199
|
+
* else that wrote `transform` would silently win. Nothing else in the catalog does — every other
|
|
4200
|
+
* transform in the library goes through `translate`/`rotate`/`scale` — so the shorthand is free.
|
|
4201
|
+
*/
|
|
4202
|
+
cssPrimitive("skew", [CHANNEL.skew], {
|
|
4203
|
+
parameters: {
|
|
4204
|
+
from: { type: "angle", default: "8deg", cssProperty: "--kui-from-skew" },
|
|
4205
|
+
to: { type: "angle", default: "0deg", cssProperty: "--kui-to-skew" }
|
|
4206
|
+
},
|
|
4207
|
+
timelines: ["view", "scroll", "pin"],
|
|
3721
4208
|
activations: ["manual"],
|
|
3722
4209
|
reducedMotion: "disable"
|
|
3723
4210
|
}),
|
|
@@ -3737,13 +4224,14 @@ var kuinetic = (() => {
|
|
|
3737
4224
|
})
|
|
3738
4225
|
];
|
|
3739
4226
|
var p = (name, primitive, keyframes, params) => ({ name, primitive, keyframes, ...params ? { params } : {} });
|
|
4227
|
+
var pIn = (name, primitive, keyframes, params) => ({ ...p(name, primitive, keyframes, params), cloak: true });
|
|
3740
4228
|
var FADE = [
|
|
3741
|
-
|
|
4229
|
+
pIn("fade-in", "reveal", "kui-in"),
|
|
3742
4230
|
p("fade-out", "reveal", "kui-out"),
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
|
|
3746
|
-
|
|
4231
|
+
pIn("fade-up", "reveal", "kui-in-up"),
|
|
4232
|
+
pIn("fade-down", "reveal", "kui-in-down"),
|
|
4233
|
+
pIn("fade-left", "reveal", "kui-in-left"),
|
|
4234
|
+
pIn("fade-right", "reveal", "kui-in-right"),
|
|
3747
4235
|
p("fade-out-up", "reveal", "kui-out-up"),
|
|
3748
4236
|
p("fade-out-down", "reveal", "kui-out-down"),
|
|
3749
4237
|
p("fade-out-left", "reveal", "kui-out-left"),
|
|
@@ -3751,56 +4239,56 @@ var kuinetic = (() => {
|
|
|
3751
4239
|
];
|
|
3752
4240
|
var SLIDE_PARAMS = { distance: "100px", opacity: "1" };
|
|
3753
4241
|
var SLIDE = [
|
|
3754
|
-
|
|
3755
|
-
|
|
3756
|
-
|
|
3757
|
-
|
|
4242
|
+
pIn("slide-up", "reveal", "kui-in-up", SLIDE_PARAMS),
|
|
4243
|
+
pIn("slide-down", "reveal", "kui-in-down", SLIDE_PARAMS),
|
|
4244
|
+
pIn("slide-left", "reveal", "kui-in-left", SLIDE_PARAMS),
|
|
4245
|
+
pIn("slide-right", "reveal", "kui-in-right", SLIDE_PARAMS),
|
|
3758
4246
|
p("slide-out-up", "reveal", "kui-out-up", SLIDE_PARAMS),
|
|
3759
4247
|
p("slide-out-down", "reveal", "kui-out-down", SLIDE_PARAMS),
|
|
3760
4248
|
p("slide-out-left", "reveal", "kui-out-left", SLIDE_PARAMS),
|
|
3761
4249
|
p("slide-out-right", "reveal", "kui-out-right", SLIDE_PARAMS)
|
|
3762
4250
|
];
|
|
3763
4251
|
var LOGICAL = [
|
|
3764
|
-
|
|
3765
|
-
|
|
3766
|
-
|
|
3767
|
-
|
|
4252
|
+
pIn("slide-inline-start", "reveal", "kui-in-inline-start", SLIDE_PARAMS),
|
|
4253
|
+
pIn("slide-inline-end", "reveal", "kui-in-inline-end", SLIDE_PARAMS),
|
|
4254
|
+
pIn("slide-block-start", "reveal", "kui-in-up", SLIDE_PARAMS),
|
|
4255
|
+
pIn("slide-block-end", "reveal", "kui-in-down", SLIDE_PARAMS)
|
|
3768
4256
|
];
|
|
3769
4257
|
var ZOOM = [
|
|
3770
|
-
|
|
4258
|
+
pIn("zoom-in", "scale", "kui-zoom-in"),
|
|
3771
4259
|
p("zoom-out", "scale", "kui-zoom-out"),
|
|
3772
|
-
|
|
4260
|
+
pIn("pop-in", "scale", "kui-zoom-in", { scale: "0.6", ease: "back-out" }),
|
|
3773
4261
|
p("pop-out", "scale", "kui-zoom-out", { scale: "0.6", ease: "back-in" }),
|
|
3774
|
-
|
|
3775
|
-
|
|
4262
|
+
pIn("zoom-in-up", "scale-move", "kui-zoom-in-up"),
|
|
4263
|
+
pIn("zoom-in-down", "scale-move", "kui-zoom-in-down")
|
|
3776
4264
|
];
|
|
3777
4265
|
var FLIP = [
|
|
3778
|
-
|
|
3779
|
-
|
|
4266
|
+
pIn("flip-in-x", "flip-3d", "kui-flip-in-x"),
|
|
4267
|
+
pIn("flip-in-y", "flip-3d", "kui-flip-in-y"),
|
|
3780
4268
|
p("flip-out-x", "flip-3d", "kui-flip-out-x"),
|
|
3781
4269
|
p("flip-out-y", "flip-3d", "kui-flip-out-y")
|
|
3782
4270
|
];
|
|
3783
4271
|
var ROTATE = [
|
|
3784
|
-
|
|
4272
|
+
pIn("rotate-in", "rotate", "kui-rotate-in"),
|
|
3785
4273
|
p("rotate-out", "rotate", "kui-rotate-out"),
|
|
3786
|
-
|
|
3787
|
-
|
|
3788
|
-
|
|
4274
|
+
pIn("rotate-in-left", "rotate", "kui-rotate-in", { angle: "-45deg" }),
|
|
4275
|
+
pIn("rotate-in-right", "rotate", "kui-rotate-in", { angle: "45deg" }),
|
|
4276
|
+
pIn("roll-in", "roll", "kui-roll-in"),
|
|
3789
4277
|
p("roll-out", "roll", "kui-roll-out"),
|
|
3790
|
-
|
|
4278
|
+
pIn("swing-in", "rotate", "kui-swing-in", { angle: "-15deg", ease: "back-out" })
|
|
3791
4279
|
];
|
|
3792
4280
|
var BLUR = [
|
|
3793
|
-
|
|
4281
|
+
pIn("blur-in", "blur", "kui-blur-in"),
|
|
3794
4282
|
p("blur-out", "blur", "kui-blur-out"),
|
|
3795
|
-
|
|
3796
|
-
|
|
4283
|
+
pIn("fade-blur-up", "reveal-blur", "kui-fade-blur-up"),
|
|
4284
|
+
pIn("fade-blur-in", "reveal-blur", "kui-fade-blur-in")
|
|
3797
4285
|
];
|
|
3798
4286
|
var CHARACTER = [
|
|
3799
|
-
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
|
|
3803
|
-
|
|
4287
|
+
pIn("bounce-in", "scale", "kui-zoom-in", { scale: "0.3", ease: "bounce" }),
|
|
4288
|
+
pIn("bounce-in-up", "reveal", "kui-in-up", { distance: "60px", ease: "back-out" }),
|
|
4289
|
+
pIn("bounce-in-down", "reveal", "kui-in-down", { distance: "60px", ease: "back-out" }),
|
|
4290
|
+
pIn("back-in-up", "reveal", "kui-in-up", { distance: "120px", ease: "expo-out" }),
|
|
4291
|
+
pIn("back-in-down", "reveal", "kui-in-down", { distance: "120px", ease: "expo-out" })
|
|
3804
4292
|
];
|
|
3805
4293
|
var SCROLL = [
|
|
3806
4294
|
p("parallax-y", "parallax", "kui-parallax-y"),
|
|
@@ -3809,11 +4297,14 @@ var kuinetic = (() => {
|
|
|
3809
4297
|
p("parallax-rotate", "parallax-rotate", "kui-parallax-rotate"),
|
|
3810
4298
|
p("depth-layer", "parallax", "kui-parallax-y", { distance: "200px" }),
|
|
3811
4299
|
p("scroll-fade", "scroll-fade", "kui-scroll-fade"),
|
|
4300
|
+
p("scroll-desaturate", "desaturate", "kui-desaturate"),
|
|
4301
|
+
p("scroll-skew", "skew", "kui-scroll-skew"),
|
|
3812
4302
|
p("scroll-progress-bar", "progress", "kui-progress-x"),
|
|
4303
|
+
p("scroll-progress-bar-y", "progress", "kui-progress-y"),
|
|
3813
4304
|
p("scroll-progress-ring", "progress-stroke", "kui-progress-ring"),
|
|
3814
4305
|
// `reveal-repeat` was removed: it was byte-identical to `reveal-once`, and the activation
|
|
3815
4306
|
// binder unobserves after first entry, so a repeating reveal is not implementable yet.
|
|
3816
|
-
|
|
4307
|
+
pIn("reveal-once", "reveal", "kui-in-up")
|
|
3817
4308
|
];
|
|
3818
4309
|
var PRESETS = [
|
|
3819
4310
|
...FADE,
|
|
@@ -3836,6 +4327,59 @@ var kuinetic = (() => {
|
|
|
3836
4327
|
return registry;
|
|
3837
4328
|
}
|
|
3838
4329
|
|
|
4330
|
+
// src/effects/step-marking.ts
|
|
4331
|
+
var STEP_STATE_ATTR = "data-kui-step-state";
|
|
4332
|
+
function selectorBreadth(selector, doc) {
|
|
4333
|
+
try {
|
|
4334
|
+
if (doc.documentElement.matches(selector)) return "document-wide";
|
|
4335
|
+
if (doc.body?.matches(selector)) return "document-wide";
|
|
4336
|
+
return "ok";
|
|
4337
|
+
} catch {
|
|
4338
|
+
return "invalid";
|
|
4339
|
+
}
|
|
4340
|
+
}
|
|
4341
|
+
function resolveTarget(selector, ctx, effect) {
|
|
4342
|
+
if (!selector) return selector;
|
|
4343
|
+
const breadth = selectorBreadth(selector, ctx.doc);
|
|
4344
|
+
if (breadth === "invalid") {
|
|
4345
|
+
ctx.warn(`${effect} target "${selector}" is not a valid selector and will be ignored`);
|
|
4346
|
+
return "";
|
|
4347
|
+
}
|
|
4348
|
+
if (breadth === "document-wide") {
|
|
4349
|
+
ctx.warn(`${effect} target "${selector}" matches the whole document and will be ignored`);
|
|
4350
|
+
return "";
|
|
4351
|
+
}
|
|
4352
|
+
return selector;
|
|
4353
|
+
}
|
|
4354
|
+
function createStepMarker(resolve) {
|
|
4355
|
+
const ledgers = /* @__PURE__ */ new Map();
|
|
4356
|
+
return {
|
|
4357
|
+
mark(index) {
|
|
4358
|
+
const seen = /* @__PURE__ */ new Map();
|
|
4359
|
+
for (const node of resolve()) {
|
|
4360
|
+
const parent = node.parentElement;
|
|
4361
|
+
const position = seen.get(parent) ?? 0;
|
|
4362
|
+
seen.set(parent, position + 1);
|
|
4363
|
+
let ledger = ledgers.get(node);
|
|
4364
|
+
if (!ledger) {
|
|
4365
|
+
ledger = createAttributeLedger(node);
|
|
4366
|
+
ledgers.set(node, ledger);
|
|
4367
|
+
}
|
|
4368
|
+
ledger.set(STEP_STATE_ATTR, stepStateFor(position, index));
|
|
4369
|
+
}
|
|
4370
|
+
},
|
|
4371
|
+
restore() {
|
|
4372
|
+
for (const ledger of ledgers.values()) ledger.restore();
|
|
4373
|
+
ledgers.clear();
|
|
4374
|
+
}
|
|
4375
|
+
};
|
|
4376
|
+
}
|
|
4377
|
+
function stepStateFor(position, index) {
|
|
4378
|
+
if (position < index) return "before";
|
|
4379
|
+
if (position === index) return "active";
|
|
4380
|
+
return "after";
|
|
4381
|
+
}
|
|
4382
|
+
|
|
3839
4383
|
// src/effects/forms/primitives.ts
|
|
3840
4384
|
var timing = {
|
|
3841
4385
|
duration: { type: "time", default: "400ms", cssProperty: "--kui-duration" },
|
|
@@ -3954,10 +4498,18 @@ var kuinetic = (() => {
|
|
|
3954
4498
|
function nextStep(step, total) {
|
|
3955
4499
|
return total > 0 ? (step + 1) % total : 0;
|
|
3956
4500
|
}
|
|
3957
|
-
function prepareStepProgress(el, params) {
|
|
4501
|
+
function prepareStepProgress(el, params, ctx) {
|
|
3958
4502
|
const total = Math.max(1, Math.round(params.num("steps", 4)));
|
|
4503
|
+
const selector = resolveTarget(params.text("target"), ctx, "step-progress");
|
|
4504
|
+
const marker = createStepMarker(
|
|
4505
|
+
() => selector ? ctx.doc.querySelectorAll(selector) : el.children
|
|
4506
|
+
);
|
|
4507
|
+
const self = createAttributeLedger(el);
|
|
3959
4508
|
let step = 0;
|
|
3960
|
-
const render = () =>
|
|
4509
|
+
const render = () => {
|
|
4510
|
+
self.set("data-kui-step", String(step));
|
|
4511
|
+
marker.mark(step);
|
|
4512
|
+
};
|
|
3961
4513
|
const advance = () => {
|
|
3962
4514
|
step = nextStep(step, total);
|
|
3963
4515
|
render();
|
|
@@ -3966,13 +4518,17 @@ var kuinetic = (() => {
|
|
|
3966
4518
|
render();
|
|
3967
4519
|
return () => {
|
|
3968
4520
|
el.removeEventListener("click", advance);
|
|
3969
|
-
|
|
4521
|
+
self.restore();
|
|
4522
|
+
marker.restore();
|
|
3970
4523
|
};
|
|
3971
4524
|
}
|
|
3972
4525
|
var STEP_PROGRESS_PRIMITIVE = jsInputPrimitive(
|
|
3973
4526
|
"step-progress",
|
|
3974
4527
|
["state"],
|
|
3975
|
-
{
|
|
4528
|
+
{
|
|
4529
|
+
steps: { type: "number", default: "4", cssProperty: "--kui-steps", minimum: 1, maximum: 20, integer: true },
|
|
4530
|
+
target: { type: "text", default: "", cssProperty: "--kui-target" }
|
|
4531
|
+
},
|
|
3976
4532
|
deferPrepare(prepareStepProgress)
|
|
3977
4533
|
);
|
|
3978
4534
|
function nextSubmitStage(stage) {
|
|
@@ -4229,6 +4785,7 @@ var kuinetic = (() => {
|
|
|
4229
4785
|
const resistance = params.num("resistance", 0.55);
|
|
4230
4786
|
const momentum = params.num("momentum", 0.2);
|
|
4231
4787
|
const offset = { x: 0, y: 0 };
|
|
4788
|
+
const pickup = { x: 0, y: 0 };
|
|
4232
4789
|
const deps = springDeps(ctx);
|
|
4233
4790
|
const runners = {
|
|
4234
4791
|
x: createSpringRunner(config, (value) => write({ ...offset, x: value }), deps),
|
|
@@ -4245,10 +4802,15 @@ var kuinetic = (() => {
|
|
|
4245
4802
|
onStart() {
|
|
4246
4803
|
runners.x.stop();
|
|
4247
4804
|
runners.y.stop();
|
|
4805
|
+
pickup.x = offset.x;
|
|
4806
|
+
pickup.y = offset.y;
|
|
4248
4807
|
el.setAttribute("data-kui-dragging", "true");
|
|
4249
4808
|
},
|
|
4250
4809
|
onMove(vector) {
|
|
4251
|
-
write({
|
|
4810
|
+
write({
|
|
4811
|
+
x: resist(pickup.x + vector.dx, bounds, resistance),
|
|
4812
|
+
y: resist(pickup.y + vector.dy, bounds, resistance)
|
|
4813
|
+
});
|
|
4252
4814
|
},
|
|
4253
4815
|
onEnd(vector) {
|
|
4254
4816
|
el.setAttribute("data-kui-dragging", "false");
|
|
@@ -4276,8 +4838,9 @@ var kuinetic = (() => {
|
|
|
4276
4838
|
runners.y.to(0);
|
|
4277
4839
|
return;
|
|
4278
4840
|
}
|
|
4279
|
-
|
|
4280
|
-
runners.
|
|
4841
|
+
const carry = mode.inertia ? mode.momentum : 0;
|
|
4842
|
+
runners.x.to(offset.x + vector.vx * carry);
|
|
4843
|
+
runners.y.to(offset.y + vector.vy * carry);
|
|
4281
4844
|
}
|
|
4282
4845
|
function prepareSwipeable(el, params) {
|
|
4283
4846
|
const stop = recognise(
|
|
@@ -4561,9 +5124,12 @@ var kuinetic = (() => {
|
|
|
4561
5124
|
ctx.style.claim("height");
|
|
4562
5125
|
const duration = effectDurationMs(params, 400);
|
|
4563
5126
|
let animation = null;
|
|
5127
|
+
let previous = node.getBoundingClientRect().height;
|
|
4564
5128
|
const observer = watchAttribute(node, params.text("attribute"), () => {
|
|
4565
5129
|
animation?.cancel();
|
|
4566
|
-
|
|
5130
|
+
const endpoints = heightEndpoints(node, previous);
|
|
5131
|
+
previous = endpoints.to;
|
|
5132
|
+
animation = animateHeight(node, endpoints, duration, params.text("ease"));
|
|
4567
5133
|
});
|
|
4568
5134
|
ctx.invalidate();
|
|
4569
5135
|
return () => {
|
|
@@ -4571,13 +5137,19 @@ var kuinetic = (() => {
|
|
|
4571
5137
|
animation?.cancel();
|
|
4572
5138
|
};
|
|
4573
5139
|
}
|
|
4574
|
-
function
|
|
4575
|
-
const from = `${node.getBoundingClientRect().height}px`;
|
|
5140
|
+
function heightEndpoints(node, previous) {
|
|
4576
5141
|
node.style.removeProperty("height");
|
|
4577
|
-
const to =
|
|
5142
|
+
const to = node.getBoundingClientRect().height;
|
|
5143
|
+
return { from: previous, to };
|
|
5144
|
+
}
|
|
5145
|
+
function animateHeight(node, endpoints, duration, easing) {
|
|
4578
5146
|
const animate = node.animate;
|
|
4579
5147
|
if (typeof animate !== "function") return null;
|
|
4580
|
-
return animate.call(
|
|
5148
|
+
return animate.call(
|
|
5149
|
+
node,
|
|
5150
|
+
[{ height: `${endpoints.from}px` }, { height: `${endpoints.to}px` }],
|
|
5151
|
+
{ duration, easing, fill: "none" }
|
|
5152
|
+
);
|
|
4581
5153
|
}
|
|
4582
5154
|
function prepareIndicator(el, params, ctx) {
|
|
4583
5155
|
const node = el;
|
|
@@ -4707,27 +5279,42 @@ var kuinetic = (() => {
|
|
|
4707
5279
|
}
|
|
4708
5280
|
function prepareHeaderShrink(el, params, ctx) {
|
|
4709
5281
|
const offset = params.num("offset", 120);
|
|
4710
|
-
|
|
5282
|
+
const state = createAttributeLedger(el);
|
|
5283
|
+
const unsubscribe = subscribeScrollTop(el, ctx, (top) => {
|
|
4711
5284
|
const progress = offset > 0 ? Math.min(1, Math.max(0, top / offset)) : 1;
|
|
4712
5285
|
ctx.style.set("--kui-shrink", progress.toFixed(4));
|
|
4713
|
-
|
|
5286
|
+
state.set("data-kui-shrunk", String(progress >= 1));
|
|
4714
5287
|
});
|
|
5288
|
+
return () => {
|
|
5289
|
+
unsubscribe();
|
|
5290
|
+
state.restore();
|
|
5291
|
+
};
|
|
4715
5292
|
}
|
|
4716
5293
|
function prepareHeaderHide(el, params, ctx) {
|
|
4717
5294
|
const minDelta = params.num("offset", 8);
|
|
4718
5295
|
let last = 0;
|
|
4719
|
-
|
|
5296
|
+
const state = createAttributeLedger(el);
|
|
5297
|
+
const unsubscribe = subscribeScrollTop(el, ctx, (top) => {
|
|
4720
5298
|
const delta = top - last;
|
|
4721
5299
|
if (Math.abs(delta) < minDelta) return;
|
|
4722
|
-
|
|
5300
|
+
state.set("data-kui-hidden", String(delta > 0 && top > minDelta));
|
|
4723
5301
|
last = top;
|
|
4724
5302
|
});
|
|
5303
|
+
return () => {
|
|
5304
|
+
unsubscribe();
|
|
5305
|
+
state.restore();
|
|
5306
|
+
};
|
|
4725
5307
|
}
|
|
4726
5308
|
function prepareBackToTop(el, params, ctx) {
|
|
4727
5309
|
const offset = params.num("offset", 400);
|
|
4728
|
-
|
|
4729
|
-
|
|
5310
|
+
const state = createAttributeLedger(el);
|
|
5311
|
+
const unsubscribe = subscribeScrollTop(el, ctx, (top) => {
|
|
5312
|
+
state.set("data-kui-visible", String(top > offset));
|
|
4730
5313
|
});
|
|
5314
|
+
return () => {
|
|
5315
|
+
unsubscribe();
|
|
5316
|
+
state.restore();
|
|
5317
|
+
};
|
|
4731
5318
|
}
|
|
4732
5319
|
var NAV_JS_PRIMITIVES = [
|
|
4733
5320
|
navPrimitive(
|
|
@@ -4765,13 +5352,38 @@ var kuinetic = (() => {
|
|
|
4765
5352
|
const rect = el.getBoundingClientRect();
|
|
4766
5353
|
return { top: rect.top, height: rect.height };
|
|
4767
5354
|
};
|
|
5355
|
+
var domPosition = (el) => {
|
|
5356
|
+
const view = el.ownerDocument?.defaultView;
|
|
5357
|
+
return view ? view.getComputedStyle(el).position : "static";
|
|
5358
|
+
};
|
|
5359
|
+
var domOffsetTop = (el) => {
|
|
5360
|
+
const view = el.ownerDocument?.defaultView;
|
|
5361
|
+
if (!view) return 0;
|
|
5362
|
+
const parsed = Number.parseFloat(view.getComputedStyle(el).top);
|
|
5363
|
+
return Number.isFinite(parsed) ? parsed : 0;
|
|
5364
|
+
};
|
|
5365
|
+
function geometrySource(el, positionOf) {
|
|
5366
|
+
let outermostSticky = null;
|
|
5367
|
+
for (let node = el; node; node = node.parentElement) {
|
|
5368
|
+
if (positionOf(node) === "sticky") outermostSticky = node;
|
|
5369
|
+
}
|
|
5370
|
+
return outermostSticky?.parentElement ?? el;
|
|
5371
|
+
}
|
|
5372
|
+
function sourceTop(el, box, measure, positionOf) {
|
|
5373
|
+
const source = geometrySource(el, positionOf);
|
|
5374
|
+
return source === el ? box.top : measure(source).top;
|
|
5375
|
+
}
|
|
4768
5376
|
function trackProgress(el, ctx, options, onProgress) {
|
|
4769
5377
|
const measure = options.measure ?? domGeometry;
|
|
5378
|
+
const positionOf = options.positionOf ?? domPosition;
|
|
5379
|
+
const offsetOf = options.offsetOf ?? domOffsetTop;
|
|
4770
5380
|
let scrollTop = 0;
|
|
4771
5381
|
let scrollportTop = 0;
|
|
4772
5382
|
const geometry2 = createMeasureCache(() => {
|
|
4773
5383
|
const box = measure(el);
|
|
4774
|
-
|
|
5384
|
+
const top = options.contentAnchor ? measure(options.contentAnchor).top - box.height : sourceTop(el, box, measure, positionOf);
|
|
5385
|
+
const stickyOffset = options.stickyEl ? offsetOf(options.stickyEl) : 0;
|
|
5386
|
+
return { contentTop: top - stickyOffset - scrollportTop + scrollTop, height: box.height };
|
|
4775
5387
|
});
|
|
4776
5388
|
return ctx.scheduler.subscribe(ctx.rootFor(el), (frame) => {
|
|
4777
5389
|
scrollTop = frame.metrics.scrollTop;
|
|
@@ -4797,11 +5409,167 @@ var kuinetic = (() => {
|
|
|
4797
5409
|
return clamp01(-top / span);
|
|
4798
5410
|
}
|
|
4799
5411
|
|
|
5412
|
+
// src/effects/scroll-mechanics/scroll-spy.ts
|
|
5413
|
+
function prepareScrollSpy(el, params, ctx) {
|
|
5414
|
+
const sectionsAuthored = params.text("sections");
|
|
5415
|
+
if (sectionsAuthored) {
|
|
5416
|
+
const sectionsSelector = resolveTarget(sectionsAuthored, ctx, "scroll-spy sections");
|
|
5417
|
+
return prepareScrollSpyContainer(el, params, ctx, sectionsSelector);
|
|
5418
|
+
}
|
|
5419
|
+
return prepareScrollSpySingle(el, params, ctx);
|
|
5420
|
+
}
|
|
5421
|
+
function prepareScrollSpySingle(el, params, ctx) {
|
|
5422
|
+
if (params.text("offset-top", "0px") !== "0px") {
|
|
5423
|
+
ctx.warn('scroll-spy "offset-top" has no effect without sections: and is ignored here');
|
|
5424
|
+
}
|
|
5425
|
+
const selector = resolveTarget(params.text("target"), ctx, "scroll-spy");
|
|
5426
|
+
const links = /* @__PURE__ */ new Map();
|
|
5427
|
+
const self = createAttributeLedger(el);
|
|
5428
|
+
let last;
|
|
5429
|
+
const untrack = trackProgress(el, ctx, { distance: params.text("distance") }, (progress) => {
|
|
5430
|
+
const active = progress > 0 && progress < 1;
|
|
5431
|
+
if (active === last) return;
|
|
5432
|
+
last = active;
|
|
5433
|
+
self.set("data-kui-active", String(active));
|
|
5434
|
+
if (selector) markLinks(ctx.doc, selector, active, links);
|
|
5435
|
+
});
|
|
5436
|
+
return continuousSetup(() => {
|
|
5437
|
+
untrack();
|
|
5438
|
+
self.restore();
|
|
5439
|
+
for (const ledger of links.values()) ledger.restore();
|
|
5440
|
+
});
|
|
5441
|
+
}
|
|
5442
|
+
function markLinks(doc, selector, active, links) {
|
|
5443
|
+
for (const link of doc.querySelectorAll(selector)) {
|
|
5444
|
+
let ledger = links.get(link);
|
|
5445
|
+
if (!ledger) {
|
|
5446
|
+
ledger = createAttributeLedger(link);
|
|
5447
|
+
links.set(link, ledger);
|
|
5448
|
+
}
|
|
5449
|
+
ledger.set("data-kui-active", String(active));
|
|
5450
|
+
}
|
|
5451
|
+
}
|
|
5452
|
+
function hrefHash(link) {
|
|
5453
|
+
const href = link.getAttribute("href") ?? "";
|
|
5454
|
+
const at = href.indexOf("#");
|
|
5455
|
+
return at === -1 ? "" : href.slice(at);
|
|
5456
|
+
}
|
|
5457
|
+
function pairSectionsWithLinks(sections, links, ctx, sectionsSelector) {
|
|
5458
|
+
const linksByHash = /* @__PURE__ */ new Map();
|
|
5459
|
+
for (const link of links) {
|
|
5460
|
+
const hash = hrefHash(link);
|
|
5461
|
+
if (hash) linksByHash.set(hash, link);
|
|
5462
|
+
}
|
|
5463
|
+
const claimed = /* @__PURE__ */ new Set();
|
|
5464
|
+
const pairs = sections.map((section) => {
|
|
5465
|
+
if (!section.id) {
|
|
5466
|
+
ctx.warn(
|
|
5467
|
+
`scroll-spy: a section matched by sections:"${sectionsSelector}" has no id and cannot be paired with a link`
|
|
5468
|
+
);
|
|
5469
|
+
return { section, link: null };
|
|
5470
|
+
}
|
|
5471
|
+
const hash = `#${section.id}`;
|
|
5472
|
+
const link = linksByHash.get(hash) ?? null;
|
|
5473
|
+
if (link) claimed.add(hash);
|
|
5474
|
+
return { section, link };
|
|
5475
|
+
});
|
|
5476
|
+
for (const [hash, link] of linksByHash) {
|
|
5477
|
+
if (!claimed.has(hash)) {
|
|
5478
|
+
ctx.warn(`scroll-spy: link "${link.getAttribute("href")}" matches no section id in sections:"${sectionsSelector}"`);
|
|
5479
|
+
}
|
|
5480
|
+
}
|
|
5481
|
+
return pairs;
|
|
5482
|
+
}
|
|
5483
|
+
function offsetTopPixels(authored, frame) {
|
|
5484
|
+
return toPixels(
|
|
5485
|
+
authored,
|
|
5486
|
+
{
|
|
5487
|
+
viewportWidth: frame.metrics.viewportWidth,
|
|
5488
|
+
viewportHeight: frame.metrics.viewportHeight,
|
|
5489
|
+
percentBasis: 0,
|
|
5490
|
+
fontSize: 16,
|
|
5491
|
+
rootFontSize: 16
|
|
5492
|
+
},
|
|
5493
|
+
0
|
|
5494
|
+
);
|
|
5495
|
+
}
|
|
5496
|
+
function highestReachedIndex(tops, scrollTop, line) {
|
|
5497
|
+
let index = -1;
|
|
5498
|
+
for (let i = 0; i < tops.length; i++) {
|
|
5499
|
+
if (tops[i] - scrollTop - line <= 0) index = i;
|
|
5500
|
+
}
|
|
5501
|
+
return index;
|
|
5502
|
+
}
|
|
5503
|
+
function prepareScrollSpyContainer(el, params, ctx, sectionsSelector) {
|
|
5504
|
+
if (params.text("distance", "100vh") !== "100vh") {
|
|
5505
|
+
ctx.warn('scroll-spy "distance" has no effect with sections: \u2014 each section measures its own height');
|
|
5506
|
+
}
|
|
5507
|
+
const linksSelector = resolveTarget(params.text("target"), ctx, "scroll-spy target");
|
|
5508
|
+
const sections = sectionsSelector ? [...el.querySelectorAll(sectionsSelector)] : [];
|
|
5509
|
+
if (sectionsSelector && sections.length === 0) {
|
|
5510
|
+
ctx.warn(`scroll-spy sections:"${sectionsSelector}" matched nothing inside this element`);
|
|
5511
|
+
}
|
|
5512
|
+
const links = linksSelector ? [...el.querySelectorAll(linksSelector)] : [];
|
|
5513
|
+
const pairs = pairSectionsWithLinks(sections, links, ctx, sectionsSelector);
|
|
5514
|
+
const sectionLedgers = pairs.map((pair) => createAttributeLedger(pair.section));
|
|
5515
|
+
const linkLedgers = /* @__PURE__ */ new Map();
|
|
5516
|
+
for (const { link } of pairs) {
|
|
5517
|
+
if (link && !linkLedgers.has(link)) linkLedgers.set(link, createAttributeLedger(link));
|
|
5518
|
+
}
|
|
5519
|
+
const offsetAuthored = params.text("offset-top", "0px");
|
|
5520
|
+
let scrollTop = 0;
|
|
5521
|
+
let scrollportTop = 0;
|
|
5522
|
+
const contentTops = createMeasureCache(
|
|
5523
|
+
() => pairs.map(({ section }) => domGeometry(section).top - scrollportTop + scrollTop)
|
|
5524
|
+
);
|
|
5525
|
+
let active = -1;
|
|
5526
|
+
function setActive(index, value) {
|
|
5527
|
+
const pair = pairs[index];
|
|
5528
|
+
sectionLedgers[index].set("data-kui-active", String(value));
|
|
5529
|
+
if (pair.link) linkLedgers.get(pair.link).set("data-kui-active", String(value));
|
|
5530
|
+
}
|
|
5531
|
+
const untrack = ctx.scheduler.subscribe(ctx.rootFor(el), (frame) => {
|
|
5532
|
+
scrollTop = frame.metrics.scrollTop;
|
|
5533
|
+
scrollportTop = frame.metrics.viewportTop;
|
|
5534
|
+
const tops = contentTops.read(frame.epoch);
|
|
5535
|
+
const line = offsetTopPixels(offsetAuthored, frame);
|
|
5536
|
+
const next = highestReachedIndex(tops, scrollTop, line);
|
|
5537
|
+
if (next === active) return;
|
|
5538
|
+
if (active !== -1) setActive(active, false);
|
|
5539
|
+
if (next !== -1) setActive(next, true);
|
|
5540
|
+
active = next;
|
|
5541
|
+
});
|
|
5542
|
+
return continuousSetup(() => {
|
|
5543
|
+
untrack();
|
|
5544
|
+
for (const ledger of sectionLedgers) ledger.restore();
|
|
5545
|
+
for (const ledger of linkLedgers.values()) ledger.restore();
|
|
5546
|
+
});
|
|
5547
|
+
}
|
|
5548
|
+
|
|
4800
5549
|
// src/effects/scroll-mechanics/primitives.ts
|
|
4801
5550
|
var PROGRESS_VAR = "--kui-progress";
|
|
4802
5551
|
var distanceParam = {
|
|
4803
5552
|
distance: { type: "length", default: "100vh", cssProperty: "--kui-distance" }
|
|
4804
5553
|
};
|
|
5554
|
+
var stickyParams = {
|
|
5555
|
+
"offset-top": {
|
|
5556
|
+
type: "length",
|
|
5557
|
+
default: "var(--kui-pin-offset, 0px)",
|
|
5558
|
+
cssProperty: "--kui-offset-top"
|
|
5559
|
+
},
|
|
5560
|
+
spacer: {
|
|
5561
|
+
type: "keyword",
|
|
5562
|
+
default: "false",
|
|
5563
|
+
cssProperty: "--kui-spacer",
|
|
5564
|
+
values: ["true", "false"]
|
|
5565
|
+
}
|
|
5566
|
+
};
|
|
5567
|
+
function installSticky(node, params, ctx) {
|
|
5568
|
+
ctx.style.set("position", "sticky");
|
|
5569
|
+
ctx.style.set("top", params.text("offset-top", "var(--kui-pin-offset, 0px)"));
|
|
5570
|
+
const inserted = params.is("spacer") ? insertSpacer(node, params.text("distance"), ctx) : null;
|
|
5571
|
+
return { spacer: inserted?.spacer ?? null, dispose: () => inserted?.remove() };
|
|
5572
|
+
}
|
|
4805
5573
|
function scrollPrimitive(spec) {
|
|
4806
5574
|
const { id, channels, parameters, prepare, perfClass = "compositor" } = spec;
|
|
4807
5575
|
return {
|
|
@@ -4809,7 +5577,12 @@ var kuinetic = (() => {
|
|
|
4809
5577
|
renderer: "javascript",
|
|
4810
5578
|
channels,
|
|
4811
5579
|
parameters,
|
|
4812
|
-
|
|
5580
|
+
// `'pin'` is accepted but ignored: these primitives read scroll position themselves and are
|
|
5581
|
+
// never driven by an `animation-timeline`. It is listed so that composing the driver with the
|
|
5582
|
+
// effects it drives — `data-kui="pin-section distance:200vh, parallax-rotate ... "` plus
|
|
5583
|
+
// `timeline:pin` — survives `compile.ts`'s `intersect`. Without it the intersection empties,
|
|
5584
|
+
// `style-plan.ts` refuses the timeline, and the scrub silently degrades to a one-shot.
|
|
5585
|
+
supportedTimelines: ["time", "view", "scroll", "pin"],
|
|
4813
5586
|
supportedActivations: ["manual", "load", "enter"],
|
|
4814
5587
|
defaultActivation: "load",
|
|
4815
5588
|
perfClass,
|
|
@@ -4822,19 +5595,17 @@ var kuinetic = (() => {
|
|
|
4822
5595
|
}
|
|
4823
5596
|
function preparePin(el, params, ctx) {
|
|
4824
5597
|
const node = el;
|
|
4825
|
-
|
|
4826
|
-
ctx.style.set("top", params.text("offset", "0px"));
|
|
4827
|
-
const removeSpacer = params.is("spacer") ? insertSpacer(node, params.text("distance"), ctx) : null;
|
|
5598
|
+
const { dispose: unstick } = installSticky(node, params, ctx);
|
|
4828
5599
|
const tracked = node.parentElement ?? el;
|
|
4829
|
-
const untrack = trackProgress(tracked, ctx, { distance: params.text("distance") }, (progress) => {
|
|
5600
|
+
const untrack = trackProgress(tracked, ctx, { distance: params.text("distance"), stickyEl: node }, (progress) => {
|
|
4830
5601
|
writeProgress(ctx, progress);
|
|
4831
5602
|
el.setAttribute("data-kui-pinned", progress > 0 && progress < 1 ? "true" : "false");
|
|
4832
5603
|
});
|
|
4833
|
-
return () => {
|
|
5604
|
+
return continuousSetup(() => {
|
|
4834
5605
|
untrack();
|
|
4835
|
-
|
|
5606
|
+
unstick();
|
|
4836
5607
|
el.removeAttribute("data-kui-pinned");
|
|
4837
|
-
};
|
|
5608
|
+
});
|
|
4838
5609
|
}
|
|
4839
5610
|
function insertSpacer(node, distance3, ctx) {
|
|
4840
5611
|
const spacer = ctx.doc.createElement("div");
|
|
@@ -4844,34 +5615,81 @@ var kuinetic = (() => {
|
|
|
4844
5615
|
spacer.style.pointerEvents = "none";
|
|
4845
5616
|
node.after(spacer);
|
|
4846
5617
|
ctx.invalidate();
|
|
4847
|
-
return
|
|
4848
|
-
spacer
|
|
4849
|
-
|
|
5618
|
+
return {
|
|
5619
|
+
spacer,
|
|
5620
|
+
remove: () => {
|
|
5621
|
+
spacer.remove();
|
|
5622
|
+
ctx.invalidate();
|
|
5623
|
+
}
|
|
4850
5624
|
};
|
|
4851
5625
|
}
|
|
4852
5626
|
function prepareProgress(el, params, ctx) {
|
|
4853
5627
|
const steps = Math.max(0, Math.round(params.num("steps", 0)));
|
|
5628
|
+
const selector = resolveTarget(params.text("target"), ctx, "scrollytelling-step");
|
|
5629
|
+
const marker = createStepMarker(() => ctx.doc.querySelectorAll(selector));
|
|
5630
|
+
const self = createAttributeLedger(el);
|
|
5631
|
+
let lastIndex;
|
|
4854
5632
|
const untrack = trackProgress(el, ctx, { distance: params.text("distance") }, (progress) => {
|
|
4855
5633
|
writeProgress(ctx, progress);
|
|
4856
|
-
if (steps
|
|
4857
|
-
|
|
4858
|
-
|
|
4859
|
-
|
|
5634
|
+
if (steps === 0) return;
|
|
5635
|
+
const index = Math.min(steps - 1, Math.floor(progress * steps));
|
|
5636
|
+
if (index === lastIndex) return;
|
|
5637
|
+
lastIndex = index;
|
|
5638
|
+
self.set("data-kui-step", String(index));
|
|
5639
|
+
ctx.style.set("--kui-step", String(index));
|
|
5640
|
+
if (selector) marker.mark(index);
|
|
4860
5641
|
});
|
|
4861
|
-
return () => {
|
|
5642
|
+
return continuousSetup(() => {
|
|
4862
5643
|
untrack();
|
|
4863
|
-
|
|
4864
|
-
|
|
5644
|
+
self.restore();
|
|
5645
|
+
marker.restore();
|
|
5646
|
+
});
|
|
4865
5647
|
}
|
|
4866
5648
|
function prepareHorizontal(el, params, ctx) {
|
|
4867
|
-
const
|
|
5649
|
+
const selector = resolveTarget(params.text("target"), ctx, "horizontal-scroll");
|
|
5650
|
+
if (!selector) return prepareBareTrack(el, params, ctx);
|
|
5651
|
+
const track = el.querySelector(selector);
|
|
5652
|
+
if (!track) {
|
|
5653
|
+
ctx.warn(`horizontal-scroll target "${selector}" matched nothing inside this element`);
|
|
5654
|
+
return () => {
|
|
5655
|
+
};
|
|
5656
|
+
}
|
|
5657
|
+
return prepareManagedTrack(el, track, params, ctx);
|
|
5658
|
+
}
|
|
5659
|
+
function prepareBareTrack(node, params, ctx) {
|
|
4868
5660
|
const authored = params.text("travel", "auto");
|
|
4869
5661
|
const travel = createMeasureCache(() => trackTravel(node, authored, node.ownerDocument));
|
|
4870
|
-
|
|
4871
|
-
ctx.
|
|
5662
|
+
return continuousSetup(
|
|
5663
|
+
trackProgress(node, ctx, { distance: params.text("distance") }, (progress, frame) => {
|
|
5664
|
+
ctx.style.set("translate", `${-progress * travel.read(frame.epoch)}px 0`);
|
|
5665
|
+
writeProgress(ctx, progress);
|
|
5666
|
+
})
|
|
5667
|
+
);
|
|
5668
|
+
}
|
|
5669
|
+
function prepareManagedTrack(host, track, params, ctx) {
|
|
5670
|
+
const offsetTop = params.text("offset-top", "var(--kui-pin-offset, 0px)");
|
|
5671
|
+
ctx.style.set("position", "sticky");
|
|
5672
|
+
ctx.style.set("top", offsetTop);
|
|
5673
|
+
ctx.style.set("height", `calc(100vh - ${offsetTop})`);
|
|
5674
|
+
ctx.style.set("overflow", "hidden");
|
|
5675
|
+
ctx.style.set("display", "grid");
|
|
5676
|
+
ctx.style.set("align-content", "center");
|
|
5677
|
+
const { remove: removeSpacer } = insertSpacer(host, params.text("distance"), ctx);
|
|
5678
|
+
const rail = createStyleLedger(track);
|
|
5679
|
+
rail.set("display", "flex");
|
|
5680
|
+
rail.set("width", "max-content");
|
|
5681
|
+
const authored = params.text("travel", "auto");
|
|
5682
|
+
const travel = createMeasureCache(() => trackTravel(track, authored, track.ownerDocument));
|
|
5683
|
+
const tracked = host.parentElement ?? host;
|
|
5684
|
+
const untrack = trackProgress(tracked, ctx, { distance: params.text("distance"), stickyEl: host }, (progress, frame) => {
|
|
5685
|
+
rail.set("translate", `${-progress * travel.read(frame.epoch)}px 0`);
|
|
4872
5686
|
writeProgress(ctx, progress);
|
|
4873
5687
|
});
|
|
4874
|
-
return
|
|
5688
|
+
return continuousSetup(() => {
|
|
5689
|
+
untrack();
|
|
5690
|
+
rail.restore();
|
|
5691
|
+
removeSpacer();
|
|
5692
|
+
});
|
|
4875
5693
|
}
|
|
4876
5694
|
function trackTravel(node, authored, doc) {
|
|
4877
5695
|
if (authored && authored !== "auto") return toPixels(authored, ABSOLUTE_BASIS, 0);
|
|
@@ -4881,11 +5699,41 @@ var kuinetic = (() => {
|
|
|
4881
5699
|
return Math.max(0, node.scrollWidth - viewportWidth);
|
|
4882
5700
|
}
|
|
4883
5701
|
function prepareMediaScrub(el, params, ctx) {
|
|
5702
|
+
const managed = params.is("spacer") ? installSticky(el, params, ctx) : null;
|
|
5703
|
+
const contentAnchor = managed?.spacer ?? void 0;
|
|
5704
|
+
const stickyEl = managed ? el : void 0;
|
|
5705
|
+
const selector = resolveTarget(params.text("target"), ctx, "media-scrub");
|
|
5706
|
+
const scrub = selector ? prepareTargetScrub(el, params, ctx, { selector, contentAnchor, stickyEl }) : prepareSrcScrub(el, params, ctx, { contentAnchor, stickyEl });
|
|
5707
|
+
return continuousSetup(() => {
|
|
5708
|
+
scrub();
|
|
5709
|
+
managed?.dispose();
|
|
5710
|
+
});
|
|
5711
|
+
}
|
|
5712
|
+
function prepareTargetScrub(el, params, ctx, authored) {
|
|
5713
|
+
const { selector, contentAnchor, stickyEl } = authored;
|
|
5714
|
+
const marker = createStepMarker(() => ctx.doc.querySelectorAll(selector));
|
|
5715
|
+
const frames = Math.max(1, ctx.doc.querySelectorAll(selector).length);
|
|
5716
|
+
let lastIndex;
|
|
5717
|
+
const untrack = trackProgress(el, ctx, { distance: params.text("distance"), contentAnchor, stickyEl }, (progress) => {
|
|
5718
|
+
writeProgress(ctx, progress);
|
|
5719
|
+
const index = Math.min(frames - 1, Math.floor(progress * frames));
|
|
5720
|
+
if (index === lastIndex) return;
|
|
5721
|
+
lastIndex = index;
|
|
5722
|
+
marker.mark(index);
|
|
5723
|
+
});
|
|
5724
|
+
marker.mark(0);
|
|
5725
|
+
return () => {
|
|
5726
|
+
untrack();
|
|
5727
|
+
marker.restore();
|
|
5728
|
+
};
|
|
5729
|
+
}
|
|
5730
|
+
function prepareSrcScrub(el, params, ctx, anchors) {
|
|
5731
|
+
const { contentAnchor, stickyEl } = anchors;
|
|
4884
5732
|
const frames = Math.max(1, Math.round(params.num("frames", 1)));
|
|
4885
5733
|
const pattern = mediaSrcPattern(params.text("src"), ctx);
|
|
4886
5734
|
const media = el;
|
|
4887
5735
|
let lastIndex = -1;
|
|
4888
|
-
const untrack = trackProgress(el, ctx, { distance: params.text("distance") }, (progress) => {
|
|
5736
|
+
const untrack = trackProgress(el, ctx, { distance: params.text("distance"), contentAnchor, stickyEl }, (progress) => {
|
|
4889
5737
|
writeProgress(ctx, progress);
|
|
4890
5738
|
const index = Math.min(frames - 1, Math.floor(progress * frames));
|
|
4891
5739
|
if (index === lastIndex) return;
|
|
@@ -4909,80 +5757,37 @@ var kuinetic = (() => {
|
|
|
4909
5757
|
if (media.tagName !== "IMG") return;
|
|
4910
5758
|
if (pattern) media.src = pattern.replace("{i}", String(index).padStart(String(frames).length, "0"));
|
|
4911
5759
|
}
|
|
4912
|
-
function
|
|
4913
|
-
|
|
4914
|
-
const links = /* @__PURE__ */ new Map();
|
|
4915
|
-
const self = createAttributeLedger(el);
|
|
4916
|
-
let last;
|
|
4917
|
-
const untrack = trackProgress(el, ctx, { distance: params.text("distance") }, (progress) => {
|
|
4918
|
-
const active = progress > 0 && progress < 1;
|
|
4919
|
-
if (active === last) return;
|
|
4920
|
-
last = active;
|
|
4921
|
-
self.set("data-kui-active", String(active));
|
|
4922
|
-
if (selector) markLinks(ctx.doc, selector, active, links);
|
|
4923
|
-
});
|
|
5760
|
+
function prepareSmoothScroll(el, params, ctx) {
|
|
5761
|
+
ctx.style.set("scroll-behavior", params.text("behavior", "smooth"));
|
|
4924
5762
|
return () => {
|
|
4925
|
-
untrack();
|
|
4926
|
-
self.restore();
|
|
4927
|
-
for (const ledger of links.values()) ledger.restore();
|
|
4928
5763
|
};
|
|
4929
5764
|
}
|
|
4930
|
-
function spyTarget(selector, ctx) {
|
|
4931
|
-
if (!selector) return selector;
|
|
4932
|
-
const breadth = selectorBreadth(selector, ctx.doc);
|
|
4933
|
-
if (breadth === "invalid") {
|
|
4934
|
-
ctx.warn(`scroll-spy target "${selector}" is not a valid selector and will be ignored`);
|
|
4935
|
-
return "";
|
|
4936
|
-
}
|
|
4937
|
-
if (breadth === "document-wide") {
|
|
4938
|
-
ctx.warn(`scroll-spy target "${selector}" matches the whole document and will be ignored`);
|
|
4939
|
-
return "";
|
|
4940
|
-
}
|
|
4941
|
-
return selector;
|
|
4942
|
-
}
|
|
4943
|
-
function selectorBreadth(selector, doc) {
|
|
4944
|
-
try {
|
|
4945
|
-
if (doc.documentElement.matches(selector)) return "document-wide";
|
|
4946
|
-
if (doc.body?.matches(selector)) return "document-wide";
|
|
4947
|
-
return "ok";
|
|
4948
|
-
} catch {
|
|
4949
|
-
return "invalid";
|
|
4950
|
-
}
|
|
4951
|
-
}
|
|
4952
|
-
function markLinks(doc, selector, active, links) {
|
|
4953
|
-
for (const link of doc.querySelectorAll(selector)) {
|
|
4954
|
-
let ledger = links.get(link);
|
|
4955
|
-
if (!ledger) {
|
|
4956
|
-
ledger = createAttributeLedger(link);
|
|
4957
|
-
links.set(link, ledger);
|
|
4958
|
-
}
|
|
4959
|
-
ledger.set("data-kui-active", String(active));
|
|
4960
|
-
}
|
|
4961
|
-
}
|
|
4962
5765
|
function prepareSnap(el, params, ctx) {
|
|
4963
|
-
|
|
4964
|
-
|
|
4965
|
-
|
|
4966
|
-
);
|
|
4967
|
-
|
|
5766
|
+
const axis = params.is("axis", "x") ? "x" : "y";
|
|
5767
|
+
ctx.style.set("scroll-snap-type", `${axis} ${params.text("strictness", "mandatory")}`);
|
|
5768
|
+
const selector = resolveTarget(params.text("target"), ctx, "scroll-snap");
|
|
5769
|
+
const items = selector ? [...el.querySelectorAll(selector)] : [...el.children];
|
|
5770
|
+
if (selector && items.length === 0) {
|
|
5771
|
+
ctx.warn(`scroll-snap target "${selector}" matched nothing inside this element`);
|
|
5772
|
+
}
|
|
5773
|
+
if (selector) installSnapContainer(axis, ctx);
|
|
5774
|
+
const childLedgers = items.map((child) => createStyleLedger(child));
|
|
4968
5775
|
for (const ledger of childLedgers) ledger.set("scroll-snap-align", params.text("align", "start"));
|
|
4969
5776
|
return () => {
|
|
4970
5777
|
for (const ledger of childLedgers) ledger.restore();
|
|
4971
5778
|
};
|
|
4972
5779
|
}
|
|
5780
|
+
function installSnapContainer(axis, ctx) {
|
|
5781
|
+
ctx.style.set(axis === "x" ? "overflow-x" : "overflow-y", "auto");
|
|
5782
|
+
if (axis === "x") ctx.style.set("display", "flex");
|
|
5783
|
+
}
|
|
4973
5784
|
var SCROLL_PRIMITIVES = [
|
|
4974
5785
|
scrollPrimitive({
|
|
4975
5786
|
id: "pin",
|
|
4976
5787
|
channels: ["layout", "progress"],
|
|
4977
5788
|
parameters: {
|
|
4978
5789
|
...distanceParam,
|
|
4979
|
-
|
|
4980
|
-
spacer: {
|
|
4981
|
-
type: "keyword",
|
|
4982
|
-
default: "false",
|
|
4983
|
-
cssProperty: "--kui-spacer",
|
|
4984
|
-
values: ["true", "false"]
|
|
4985
|
-
}
|
|
5790
|
+
...stickyParams
|
|
4986
5791
|
},
|
|
4987
5792
|
prepare: deferPrepare(preparePin),
|
|
4988
5793
|
perfClass: "layout"
|
|
@@ -4992,7 +5797,10 @@ var kuinetic = (() => {
|
|
|
4992
5797
|
channels: ["progress"],
|
|
4993
5798
|
parameters: {
|
|
4994
5799
|
...distanceParam,
|
|
4995
|
-
steps: { type: "number", default: "0", cssProperty: "--kui-steps" }
|
|
5800
|
+
steps: { type: "number", default: "0", cssProperty: "--kui-steps" },
|
|
5801
|
+
// Same name, same shape and the same validation as scroll-spy's: one `target:` convention
|
|
5802
|
+
// across the library rather than a second word for "the elements this effect marks".
|
|
5803
|
+
target: { type: "text", default: "", cssProperty: "--kui-target" }
|
|
4996
5804
|
},
|
|
4997
5805
|
prepare: deferPrepare(prepareProgress)
|
|
4998
5806
|
}),
|
|
@@ -5001,7 +5809,16 @@ var kuinetic = (() => {
|
|
|
5001
5809
|
channels: ["translate", "progress"],
|
|
5002
5810
|
parameters: {
|
|
5003
5811
|
...distanceParam,
|
|
5004
|
-
travel: { type: "text", default: "auto", cssProperty: "--kui-travel" }
|
|
5812
|
+
travel: { type: "text", default: "auto", cssProperty: "--kui-travel" },
|
|
5813
|
+
// Same name, same shape and the same validation as scroll-spy's and media-scrub's: one
|
|
5814
|
+
// `target:` convention across the library. Naming the row that moves is also what opts this
|
|
5815
|
+
// primitive into owning the stage, the sticky window and the row's layout itself.
|
|
5816
|
+
target: { type: "text", default: "", cssProperty: "--kui-target" },
|
|
5817
|
+
"offset-top": {
|
|
5818
|
+
type: "length",
|
|
5819
|
+
default: "var(--kui-pin-offset, 0px)",
|
|
5820
|
+
cssProperty: "--kui-offset-top"
|
|
5821
|
+
}
|
|
5005
5822
|
},
|
|
5006
5823
|
prepare: deferPrepare(prepareHorizontal)
|
|
5007
5824
|
}),
|
|
@@ -5010,8 +5827,13 @@ var kuinetic = (() => {
|
|
|
5010
5827
|
channels: ["media", "progress"],
|
|
5011
5828
|
parameters: {
|
|
5012
5829
|
...distanceParam,
|
|
5830
|
+
// A scrub is a hold, so it needs the same two knobs a pin does. Declaring them here is what
|
|
5831
|
+
// lets `sequence-scrub` become one attribute with no wrapper at all.
|
|
5832
|
+
...stickyParams,
|
|
5013
5833
|
frames: { type: "number", default: "1", cssProperty: "--kui-frames" },
|
|
5014
|
-
src: { type: "text", default: "", cssProperty: "--kui-src" }
|
|
5834
|
+
src: { type: "text", default: "", cssProperty: "--kui-src" },
|
|
5835
|
+
// The preferred form. `frames:`/`src:` remain for sequences too long to author as tags.
|
|
5836
|
+
target: { type: "text", default: "", cssProperty: "--kui-target" }
|
|
5015
5837
|
},
|
|
5016
5838
|
prepare: deferPrepare(prepareMediaScrub),
|
|
5017
5839
|
perfClass: "paint"
|
|
@@ -5020,11 +5842,30 @@ var kuinetic = (() => {
|
|
|
5020
5842
|
id: "scroll-spy",
|
|
5021
5843
|
channels: ["state"],
|
|
5022
5844
|
parameters: {
|
|
5845
|
+
// `distance`: the per-section form only. `offset-top`: the container form only. Each is a
|
|
5846
|
+
// no-op — warned, not silent — in the other; see `prepareScrollSpySingle` and
|
|
5847
|
+
// `prepareScrollSpyContainer`.
|
|
5023
5848
|
...distanceParam,
|
|
5024
|
-
|
|
5849
|
+
// Same name and meaning in both forms: the link(s) this instance marks. Per-section, the
|
|
5850
|
+
// one link this section names; with `sections:`, every link `target:` matches, each paired
|
|
5851
|
+
// to its own section by `href`. See `prepareScrollSpyContainer`.
|
|
5852
|
+
target: { type: "text", default: "", cssProperty: "--kui-target" },
|
|
5853
|
+
// Presence, not value, selects the container form: authoring this at all switches
|
|
5854
|
+
// `prepareScrollSpy` from one-section-per-instance to one-instance-on-the-shared-ancestor.
|
|
5855
|
+
sections: { type: "text", default: "", cssProperty: "--kui-sections" },
|
|
5856
|
+
"offset-top": { type: "length", default: "0px", cssProperty: "--kui-offset-top" }
|
|
5025
5857
|
},
|
|
5026
5858
|
prepare: deferPrepare(prepareScrollSpy)
|
|
5027
5859
|
}),
|
|
5860
|
+
scrollPrimitive({
|
|
5861
|
+
id: "smooth-scroll",
|
|
5862
|
+
channels: ["layout"],
|
|
5863
|
+
parameters: {
|
|
5864
|
+
behavior: { type: "keyword", default: "smooth", cssProperty: "--kui-scroll-behavior", values: ["smooth", "auto"] }
|
|
5865
|
+
},
|
|
5866
|
+
prepare: deferPrepare(prepareSmoothScroll),
|
|
5867
|
+
perfClass: "layout"
|
|
5868
|
+
}),
|
|
5028
5869
|
scrollPrimitive({
|
|
5029
5870
|
id: "scroll-snap",
|
|
5030
5871
|
channels: ["layout"],
|
|
@@ -5041,7 +5882,11 @@ var kuinetic = (() => {
|
|
|
5041
5882
|
default: "start",
|
|
5042
5883
|
cssProperty: "--kui-snap-align",
|
|
5043
5884
|
values: ["start", "center", "end"]
|
|
5044
|
-
}
|
|
5885
|
+
},
|
|
5886
|
+
// Names the snap items. Also what opts this primitive into owning the scroll container
|
|
5887
|
+
// itself — see `installSnapContainer`. Without it, the direct children are the items and
|
|
5888
|
+
// the page keeps its own `overflow`, exactly as before.
|
|
5889
|
+
target: { type: "text", default: "", cssProperty: "--kui-target" }
|
|
5045
5890
|
},
|
|
5046
5891
|
prepare: deferPrepare(prepareSnap),
|
|
5047
5892
|
perfClass: "layout"
|
|
@@ -5064,11 +5909,28 @@ var kuinetic = (() => {
|
|
|
5064
5909
|
// --- travel ------------------------------------------------------------------------------
|
|
5065
5910
|
{ name: "horizontal-scroll", primitive: "horizontal-track" },
|
|
5066
5911
|
// --- media -------------------------------------------------------------------------------
|
|
5067
|
-
|
|
5912
|
+
/*
|
|
5913
|
+
* `spacer:true` is what deletes the `.scrub-stage` wrapper a page used to hand-write.
|
|
5914
|
+
*
|
|
5915
|
+
* It could not be switched on until the tracker stopped measuring against the parent. A scrub
|
|
5916
|
+
* makes itself sticky, and `geometrySource` escapes a sticky subtree by taking its parent — so
|
|
5917
|
+
* with the wrapper gone the scrub was measured against whatever section contained it. Measured
|
|
5918
|
+
* on `demo/scroll.html`: the parent started 926px above the scrub against a 1817px distance, so
|
|
5919
|
+
* progress reached 51% before the element had even stuck and half the sequence played off
|
|
5920
|
+
* screen. The wrapper was not ceremony; it was the tight box that made the parent honest.
|
|
5921
|
+
*
|
|
5922
|
+
* `trackProgress`'s `contentAnchor` is the fix. Progress is read from the spacer, which the
|
|
5923
|
+
* library inserts, is exactly `distance` tall, is never sticky, and moves with the content — so
|
|
5924
|
+
* there is no wrapper to write and nothing to disagree with.
|
|
5925
|
+
*
|
|
5926
|
+
* `video-scrub` stays off: a video positioned by the page is not asking the library for a box.
|
|
5927
|
+
*/
|
|
5928
|
+
{ name: "sequence-scrub", primitive: "media-scrub", params: { spacer: "true" } },
|
|
5068
5929
|
{ name: "video-scrub", primitive: "media-scrub" },
|
|
5069
5930
|
// --- navigation --------------------------------------------------------------------------
|
|
5070
5931
|
{ name: "scroll-spy", primitive: "scroll-spy" },
|
|
5071
5932
|
// --- native CSS passthroughs ---------------------------------------------------------------
|
|
5933
|
+
{ name: "smooth-scroll-to", primitive: "smooth-scroll" },
|
|
5072
5934
|
{ name: "scroll-snap-x", primitive: "scroll-snap", params: { axis: "x" } },
|
|
5073
5935
|
{ name: "scroll-snap-y", primitive: "scroll-snap", params: { axis: "y" } }
|
|
5074
5936
|
];
|
|
@@ -5083,11 +5945,16 @@ var kuinetic = (() => {
|
|
|
5083
5945
|
var UNSUPPORTED = /[AaSsQqTt]/;
|
|
5084
5946
|
function parsePath(d) {
|
|
5085
5947
|
if (UNSUPPORTED.test(d)) {
|
|
5086
|
-
return {
|
|
5948
|
+
return {
|
|
5949
|
+
segments: [],
|
|
5950
|
+
subpaths: [],
|
|
5951
|
+
reason: "arc and shorthand commands (A S Q T) are not supported"
|
|
5952
|
+
};
|
|
5087
5953
|
}
|
|
5088
5954
|
const tokens = [...d.matchAll(COMMAND)].map((m) => m[1] ?? m[2]);
|
|
5089
5955
|
const state = {
|
|
5090
|
-
|
|
5956
|
+
subpaths: [],
|
|
5957
|
+
open: void 0,
|
|
5091
5958
|
current: { x: 0, y: 0 },
|
|
5092
5959
|
start: { x: 0, y: 0 },
|
|
5093
5960
|
command: ""
|
|
@@ -5101,18 +5968,33 @@ var kuinetic = (() => {
|
|
|
5101
5968
|
index++;
|
|
5102
5969
|
continue;
|
|
5103
5970
|
}
|
|
5104
|
-
if (!state.command)
|
|
5971
|
+
if (!state.command) {
|
|
5972
|
+
return { segments: [], subpaths: [], reason: "path must start with a command letter" };
|
|
5973
|
+
}
|
|
5105
5974
|
index = consume(tokens, index, state);
|
|
5106
5975
|
}
|
|
5107
|
-
if (state.
|
|
5108
|
-
|
|
5976
|
+
if (state.subpaths.length === 0) {
|
|
5977
|
+
return { segments: [], subpaths: [], reason: "no drawable segments" };
|
|
5978
|
+
}
|
|
5979
|
+
return { segments: state.subpaths.flatMap((sub) => sub.segments), subpaths: state.subpaths };
|
|
5980
|
+
}
|
|
5981
|
+
function pushSegment(state, segment) {
|
|
5982
|
+
if (!state.open) {
|
|
5983
|
+
state.open = { segments: [], closed: false };
|
|
5984
|
+
state.subpaths.push(state.open);
|
|
5985
|
+
}
|
|
5986
|
+
state.open.segments.push(segment);
|
|
5109
5987
|
}
|
|
5110
5988
|
var ARITY = { m: 2, l: 2, h: 1, v: 1, c: 6, z: 0 };
|
|
5111
5989
|
function closeSubpath(state) {
|
|
5112
|
-
const { current, start } = state;
|
|
5113
|
-
if (
|
|
5114
|
-
|
|
5990
|
+
const { current, start, open } = state;
|
|
5991
|
+
if (!open) return;
|
|
5992
|
+
if (Math.abs(current.x - start.x) >= 1e-6 || Math.abs(current.y - start.y) >= 1e-6) {
|
|
5993
|
+
open.segments.push(lineToCubic(current, start));
|
|
5994
|
+
}
|
|
5995
|
+
open.closed = true;
|
|
5115
5996
|
state.current = { ...start };
|
|
5997
|
+
state.open = void 0;
|
|
5116
5998
|
}
|
|
5117
5999
|
function consume(tokens, index, state) {
|
|
5118
6000
|
const key = state.command.toLowerCase();
|
|
@@ -5124,10 +6006,11 @@ var kuinetic = (() => {
|
|
|
5124
6006
|
if (key === "m") {
|
|
5125
6007
|
state.current = next;
|
|
5126
6008
|
state.start = next;
|
|
6009
|
+
state.open = void 0;
|
|
5127
6010
|
state.command = relative ? "l" : "L";
|
|
5128
6011
|
return index + arity;
|
|
5129
6012
|
}
|
|
5130
|
-
state
|
|
6013
|
+
pushSegment(state, straightOrCubic({ key, args, from: state.current, relative }, next));
|
|
5131
6014
|
state.current = next;
|
|
5132
6015
|
return index + arity;
|
|
5133
6016
|
}
|
|
@@ -5190,34 +6073,78 @@ var kuinetic = (() => {
|
|
|
5190
6073
|
function chordLength(segment) {
|
|
5191
6074
|
return Math.hypot(segment.to.x - segment.from.x, segment.to.y - segment.from.y);
|
|
5192
6075
|
}
|
|
5193
|
-
function
|
|
5194
|
-
|
|
5195
|
-
|
|
5196
|
-
|
|
5197
|
-
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
);
|
|
6076
|
+
function round(value) {
|
|
6077
|
+
return Math.round(value * 100) / 100;
|
|
6078
|
+
}
|
|
6079
|
+
function subpathsToPathData(subpaths) {
|
|
6080
|
+
const parts = [];
|
|
6081
|
+
for (const sub of subpaths) {
|
|
6082
|
+
const head = sub.segments[0];
|
|
6083
|
+
parts.push(`M${round(head.from.x)},${round(head.from.y)}`);
|
|
6084
|
+
for (const s of sub.segments) {
|
|
6085
|
+
parts.push(
|
|
6086
|
+
`C${round(s.c1.x)},${round(s.c1.y)} ${round(s.c2.x)},${round(s.c2.y)} ${round(s.to.x)},${round(s.to.y)}`
|
|
6087
|
+
);
|
|
6088
|
+
}
|
|
6089
|
+
if (sub.closed) parts.push("Z");
|
|
5201
6090
|
}
|
|
5202
6091
|
return parts.join(" ");
|
|
5203
6092
|
}
|
|
5204
|
-
function
|
|
5205
|
-
|
|
6093
|
+
function centroidOf(subpath) {
|
|
6094
|
+
let x = 0;
|
|
6095
|
+
let y = 0;
|
|
6096
|
+
for (const s of subpath.segments) {
|
|
6097
|
+
x += s.from.x;
|
|
6098
|
+
y += s.from.y;
|
|
6099
|
+
}
|
|
6100
|
+
return { x: x / subpath.segments.length, y: y / subpath.segments.length };
|
|
6101
|
+
}
|
|
6102
|
+
function collapsedLike(partner) {
|
|
6103
|
+
const at = centroidOf(partner);
|
|
6104
|
+
return {
|
|
6105
|
+
segments: partner.segments.map(() => ({
|
|
6106
|
+
from: { ...at },
|
|
6107
|
+
c1: { ...at },
|
|
6108
|
+
c2: { ...at },
|
|
6109
|
+
to: { ...at }
|
|
6110
|
+
})),
|
|
6111
|
+
closed: partner.closed
|
|
6112
|
+
};
|
|
6113
|
+
}
|
|
6114
|
+
function normaliseSubpaths(a, b) {
|
|
6115
|
+
const count = Math.max(a.length, b.length);
|
|
6116
|
+
const from = [];
|
|
6117
|
+
const to = [];
|
|
6118
|
+
for (let i = 0; i < count; i++) {
|
|
6119
|
+
const left = a[i] ?? collapsedLike(b[i]);
|
|
6120
|
+
const right = b[i] ?? collapsedLike(a[i]);
|
|
6121
|
+
const target = Math.max(left.segments.length, right.segments.length);
|
|
6122
|
+
const closed = left.closed && right.closed;
|
|
6123
|
+
from.push({ segments: normaliseCount(left.segments, target), closed });
|
|
6124
|
+
to.push({ segments: normaliseCount(right.segments, target), closed });
|
|
6125
|
+
}
|
|
6126
|
+
return { from, to };
|
|
5206
6127
|
}
|
|
5207
6128
|
function createMorph(fromPath, toPath) {
|
|
5208
6129
|
const a = parsePath(fromPath);
|
|
5209
6130
|
const b = parsePath(toPath);
|
|
5210
6131
|
if (a.reason) return { reason: `start path: ${a.reason}` };
|
|
5211
6132
|
if (b.reason) return { reason: `end path: ${b.reason}` };
|
|
5212
|
-
const
|
|
5213
|
-
const
|
|
5214
|
-
const to = normaliseCount(b.segments, count);
|
|
6133
|
+
const { from, to } = normaliseSubpaths(a.subpaths, b.subpaths);
|
|
6134
|
+
const count = from.reduce((total, sub) => total + sub.segments.length, 0);
|
|
5215
6135
|
return {
|
|
5216
6136
|
morph: {
|
|
5217
6137
|
segmentCount: count,
|
|
5218
6138
|
at(t) {
|
|
5219
6139
|
const clamped = Math.min(1, Math.max(0, t));
|
|
5220
|
-
return
|
|
6140
|
+
return subpathsToPathData(
|
|
6141
|
+
from.map((sub, i) => ({
|
|
6142
|
+
segments: sub.segments.map(
|
|
6143
|
+
(segment, j) => lerpCubic(segment, to[i].segments[j], clamped)
|
|
6144
|
+
),
|
|
6145
|
+
closed: sub.closed
|
|
6146
|
+
}))
|
|
6147
|
+
);
|
|
5221
6148
|
}
|
|
5222
6149
|
}
|
|
5223
6150
|
};
|
|
@@ -5274,6 +6201,35 @@ var kuinetic = (() => {
|
|
|
5274
6201
|
path.setAttribute("d", startPath);
|
|
5275
6202
|
};
|
|
5276
6203
|
}
|
|
6204
|
+
var PATH_DRAW_PRIMITIVE = cssPrimitive("path-draw", [CHANNEL.stroke], {
|
|
6205
|
+
parameters: {
|
|
6206
|
+
length: { type: "number", default: "100", cssProperty: "--kui-path-length", finite: true }
|
|
6207
|
+
}
|
|
6208
|
+
});
|
|
6209
|
+
var SHAPE_FILL_PRIMITIVE = cssPrimitive("shape-fill", [CHANNEL.clip]);
|
|
6210
|
+
var BAR_GROW_PRIMITIVE = cssPrimitive("bar-grow", [CHANNEL.scale], {
|
|
6211
|
+
parameters: { from: { type: "number", default: "0", cssProperty: "--kui-bar-from" } }
|
|
6212
|
+
});
|
|
6213
|
+
var LOGO_BUILD_PRIMITIVE = cssPrimitive("logo-assemble", [
|
|
6214
|
+
CHANNEL.opacity,
|
|
6215
|
+
CHANNEL.scale,
|
|
6216
|
+
CHANNEL.rotate
|
|
6217
|
+
]);
|
|
6218
|
+
var ICON_TOGGLE_PRIMITIVE = {
|
|
6219
|
+
id: "icon-toggle",
|
|
6220
|
+
renderer: "javascript",
|
|
6221
|
+
channels: [CHANNEL.translate, CHANNEL.rotate, CHANNEL.scale, CHANNEL.opacity, CHANNEL.clip],
|
|
6222
|
+
parameters: {
|
|
6223
|
+
duration: { type: "time", default: "260ms", cssProperty: "--kui-duration" },
|
|
6224
|
+
ease: { type: "easing", default: "ease-out", cssProperty: "--kui-ease" }
|
|
6225
|
+
},
|
|
6226
|
+
supportedTimelines: ["time"],
|
|
6227
|
+
supportedActivations: ["load"],
|
|
6228
|
+
defaultActivation: "load",
|
|
6229
|
+
perfClass: "compositor",
|
|
6230
|
+
reducedMotion: "disable",
|
|
6231
|
+
prepare: () => inertInstance()
|
|
6232
|
+
};
|
|
5277
6233
|
var SVG_PRIMITIVES = [
|
|
5278
6234
|
{
|
|
5279
6235
|
id: "path-morph",
|
|
@@ -5293,19 +6249,77 @@ var kuinetic = (() => {
|
|
|
5293
6249
|
perfClass: "paint",
|
|
5294
6250
|
reducedMotion: "disable",
|
|
5295
6251
|
prepare: deferPrepare(prepareMorph)
|
|
5296
|
-
}
|
|
6252
|
+
},
|
|
6253
|
+
PATH_DRAW_PRIMITIVE,
|
|
6254
|
+
SHAPE_FILL_PRIMITIVE,
|
|
6255
|
+
BAR_GROW_PRIMITIVE,
|
|
6256
|
+
LOGO_BUILD_PRIMITIVE,
|
|
6257
|
+
ICON_TOGGLE_PRIMITIVE
|
|
5297
6258
|
];
|
|
5298
6259
|
var SVG_PRESETS = [
|
|
5299
6260
|
{ name: "icon-morph", primitive: "path-morph" },
|
|
5300
|
-
{ name: "blob-morph", primitive: "path-morph", params: { duration: "800ms" } }
|
|
6261
|
+
{ name: "blob-morph", primitive: "path-morph", params: { duration: "800ms" } },
|
|
6262
|
+
// Stroke draws. One keyframe block each rather than one shared block, matching the
|
|
6263
|
+
// progress-ring/gauge-sweep/donut-sweep/sparkline-draw group in numbers.ts: identical bodies
|
|
6264
|
+
// today, but each name is free to diverge and a consumer can restyle one without the others.
|
|
6265
|
+
{ name: "draw-stroke", primitive: "path-draw", keyframes: "kui-draw-stroke", params: { duration: "800ms", ease: "ease-in-out" } },
|
|
6266
|
+
{ name: "draw-signature", primitive: "path-draw", keyframes: "kui-draw-signature", params: { duration: "1600ms", ease: "ease-in-out" } },
|
|
6267
|
+
{ name: "draw-underline", primitive: "path-draw", keyframes: "kui-draw-underline", params: { duration: "420ms" } },
|
|
6268
|
+
{ name: "checkmark-draw", primitive: "path-draw", keyframes: "kui-checkmark-draw", params: { duration: "320ms" } },
|
|
6269
|
+
{ name: "cross-draw", primitive: "path-draw", keyframes: "kui-cross-draw", params: { duration: "260ms" } },
|
|
6270
|
+
{ name: "chart-line-draw", primitive: "path-draw", keyframes: "kui-chart-line-draw", params: { duration: "1200ms", ease: "ease-in-out" } },
|
|
6271
|
+
{ name: "gradient-stroke", primitive: "path-draw", keyframes: "kui-gradient-stroke", params: { duration: "2400ms", ease: "ease-in-out" } },
|
|
6272
|
+
// Fills.
|
|
6273
|
+
{ name: "heart-fill", primitive: "shape-fill", keyframes: "kui-heart-fill", params: { duration: "420ms" } },
|
|
6274
|
+
{ name: "bookmark-fill", primitive: "shape-fill", keyframes: "kui-bookmark-fill", params: { duration: "360ms" } },
|
|
6275
|
+
{ name: "chart-area-fill", primitive: "shape-fill", keyframes: "kui-chart-area-fill", params: { duration: "900ms" } },
|
|
6276
|
+
// `cloak: true`: `kui-chart-bar-grow`'s `from { scale: 1 0 }` (svg.css) is a zero-height box
|
|
6277
|
+
// while paused, not just an invisible one — so it occupies no space in layout for the whole
|
|
6278
|
+
// wait. Same defect `fold-panel` has, and the same fix shape: see svg.css's
|
|
6279
|
+
// `[data-kui-fx~='chart-bar-grow'][data-kui-state='ready']` rule.
|
|
6280
|
+
{
|
|
6281
|
+
name: "chart-bar-grow",
|
|
6282
|
+
primitive: "bar-grow",
|
|
6283
|
+
keyframes: "kui-chart-bar-grow",
|
|
6284
|
+
params: { duration: "700ms", ease: "back-out" },
|
|
6285
|
+
cloak: true
|
|
6286
|
+
},
|
|
6287
|
+
{ name: "logo-build", primitive: "logo-assemble", keyframes: "kui-logo-build", params: { duration: "520ms", ease: "back-out" } },
|
|
6288
|
+
// Icon toggles — no `keyframes`, because their motion is a CSS transition in svg.css keyed off
|
|
6289
|
+
// aria state, not a compiled animation. Same shape as forms.ts's native-state presets.
|
|
6290
|
+
{ name: "hamburger-to-x", primitive: "icon-toggle" },
|
|
6291
|
+
{ name: "play-to-pause", primitive: "icon-toggle" },
|
|
6292
|
+
{ name: "plus-to-minus", primitive: "icon-toggle" }
|
|
5301
6293
|
];
|
|
5302
6294
|
function registerSvg(registry) {
|
|
5303
6295
|
return registry.registerPrimitives(SVG_PRIMITIVES).registerPresets(SVG_PRESETS);
|
|
5304
6296
|
}
|
|
5305
6297
|
|
|
5306
6298
|
// src/effects/three-d/index.ts
|
|
6299
|
+
var CARD_TOGGLE_PRIMITIVE = {
|
|
6300
|
+
id: "card-toggle",
|
|
6301
|
+
renderer: "javascript",
|
|
6302
|
+
channels: [CHANNEL.rotate],
|
|
6303
|
+
parameters: {
|
|
6304
|
+
duration: { type: "time", default: "700ms", cssProperty: "--kui-duration" },
|
|
6305
|
+
ease: { type: "easing", default: "ease-in-out", cssProperty: "--kui-ease" },
|
|
6306
|
+
perspective: { type: "length", default: "1600px", cssProperty: "--kui-perspective" }
|
|
6307
|
+
},
|
|
6308
|
+
supportedTimelines: ["time"],
|
|
6309
|
+
supportedActivations: ["load"],
|
|
6310
|
+
defaultActivation: "load",
|
|
6311
|
+
perfClass: "compositor",
|
|
6312
|
+
reducedMotion: "disable",
|
|
6313
|
+
prepare: () => inertInstance()
|
|
6314
|
+
};
|
|
5307
6315
|
var THREE_D_PRIMITIVES = [
|
|
5308
|
-
|
|
6316
|
+
// `skew`, not `rotate`: the keyframes in three-d.css write `transform: perspective(...)
|
|
6317
|
+
// rotateX/Y(...)`, not the individual `rotate:` property — `perspective` only creates depth for
|
|
6318
|
+
// an element's *children*, so giving one of these effects its own depth means reaching for the
|
|
6319
|
+
// `perspective()` transform *function*, which only exists inside the `transform` shorthand.
|
|
6320
|
+
// `CHANNEL.skew` is this catalog's name for "claims the whole `transform` shorthand"; see the
|
|
6321
|
+
// comment on it in `core/types.ts`.
|
|
6322
|
+
cssPrimitive("flip-face", [CHANNEL.skew], {
|
|
5309
6323
|
parameters: {
|
|
5310
6324
|
angle: { type: "angle", default: "180deg", cssProperty: "--kui-from-angle" },
|
|
5311
6325
|
perspective: { type: "length", default: "1200px", cssProperty: "--kui-perspective" }
|
|
@@ -5315,12 +6329,19 @@ var kuinetic = (() => {
|
|
|
5315
6329
|
parameters: { distance: { type: "length", default: "40px", cssProperty: "--kui-distance" } }
|
|
5316
6330
|
}),
|
|
5317
6331
|
cssPrimitive("wipe", [CHANNEL.clip]),
|
|
5318
|
-
|
|
6332
|
+
// `from` gives `loading-bar` a real knob on its start scale — it had none before, unlike
|
|
6333
|
+
// `flip-face`'s `angle:` two rows up. `--kui-bar-from` is also what the fold-panel-style
|
|
6334
|
+
// `[data-kui-fx~='loading-bar'][data-kui-state='ready']` gate neutralizes in three-d.css; see
|
|
6335
|
+
// that rule's comment for the on:enter fix this parameter doubles as.
|
|
6336
|
+
cssPrimitive("bar", [CHANNEL.scale], {
|
|
6337
|
+
parameters: { from: { type: "number", default: "0", cssProperty: "--kui-bar-from" } }
|
|
6338
|
+
}),
|
|
6339
|
+
CARD_TOGGLE_PRIMITIVE
|
|
5319
6340
|
];
|
|
5320
6341
|
var THREE_D_PRESETS = [
|
|
5321
6342
|
// --- 3D & perspective ---
|
|
5322
|
-
{ name: "card-flip-y", primitive: "flip-face", keyframes: "kui-card-flip-y" },
|
|
5323
|
-
{ name: "card-flip-x", primitive: "flip-face", keyframes: "kui-card-flip-x" },
|
|
6343
|
+
{ name: "card-flip-y", primitive: "flip-face", keyframes: "kui-card-flip-y", cloak: true },
|
|
6344
|
+
{ name: "card-flip-x", primitive: "flip-face", keyframes: "kui-card-flip-x", cloak: true },
|
|
5324
6345
|
{ name: "cube-rotate", primitive: "flip-face", keyframes: "kui-cube-rotate", params: { angle: "90deg" } },
|
|
5325
6346
|
{
|
|
5326
6347
|
name: "book-page-turn",
|
|
@@ -5328,17 +6349,32 @@ var kuinetic = (() => {
|
|
|
5328
6349
|
keyframes: "kui-book-page-turn",
|
|
5329
6350
|
params: { angle: "-160deg", duration: "900ms" }
|
|
5330
6351
|
},
|
|
6352
|
+
// `cloak: true`, unlike its `flip-face` siblings above: those are `to`-only keyframes, so their
|
|
6353
|
+
// paused/waiting box is the ordinary, untransformed rest state. `fold-panel` is `from`-only —
|
|
6354
|
+
// its `rotateX(-90deg)` (three-d.css) *is* the paused box, edge-on and zero-height, so it holds
|
|
6355
|
+
// no space in layout for the whole wait; see the
|
|
6356
|
+
// `[data-kui-fx~='fold-panel'][data-kui-state='ready']` rule in three-d.css for the other half
|
|
6357
|
+
// of that fix. `cloak` only ever hid the pre-JS flash, not this, but adding it here keeps the
|
|
6358
|
+
// pre-JS and post-JS "ready" appearances the same (invisible) instead of trading one flash for
|
|
6359
|
+
// the other.
|
|
5331
6360
|
{
|
|
5332
6361
|
name: "fold-panel",
|
|
5333
6362
|
primitive: "flip-face",
|
|
5334
6363
|
keyframes: "kui-fold-panel",
|
|
5335
|
-
params: { angle: "-90deg" }
|
|
6364
|
+
params: { angle: "-90deg" },
|
|
6365
|
+
cloak: true
|
|
5336
6366
|
},
|
|
5337
6367
|
// --- page transitions ---
|
|
5338
6368
|
{ name: "page-fade", primitive: "page-reveal", keyframes: "kui-page-fade" },
|
|
5339
6369
|
{ name: "page-slide", primitive: "page-reveal", keyframes: "kui-page-slide" },
|
|
5340
6370
|
{ name: "curtain-wipe", primitive: "wipe", keyframes: "kui-curtain-wipe", params: { duration: "800ms" } },
|
|
5341
|
-
|
|
6371
|
+
// `cloak: true` for the same reason as `fold-panel`: `kui-loading-bar`'s `from { scale: 0 1 }`
|
|
6372
|
+
// (three-d.css) is a zero-width box, not just an invisible one — see that file's
|
|
6373
|
+
// `[data-kui-fx~='loading-bar'][data-kui-state='ready']` rule.
|
|
6374
|
+
{ name: "loading-bar", primitive: "bar", keyframes: "kui-loading-bar", cloak: true },
|
|
6375
|
+
// No `keyframes`: its motion is a CSS transition in three-d.css keyed off the control's
|
|
6376
|
+
// aria-pressed, not a compiled animation. Same shape as the icon toggles in svg.ts.
|
|
6377
|
+
{ name: "flip-card", primitive: "card-toggle" }
|
|
5342
6378
|
];
|
|
5343
6379
|
function registerThreeD(registry) {
|
|
5344
6380
|
return registry.registerPrimitives(THREE_D_PRIMITIVES).registerPresets(THREE_D_PRESETS);
|
|
@@ -5371,7 +6407,7 @@ var kuinetic = (() => {
|
|
|
5371
6407
|
if (!document.getElementById('kuinetic-styles')) {
|
|
5372
6408
|
var style = document.createElement('style')
|
|
5373
6409
|
style.id = 'kuinetic-styles'
|
|
5374
|
-
style.textContent = "/* src/css/base.css */\n@layer kui.tokens, kui.presets, kui.effects, kui.policy;\n@layer kui.tokens {\n :root {\n --kui-ease-expo-in: cubic-bezier(0.7, 0, 0.84, 0);\n --kui-ease-expo-out: cubic-bezier(0.16, 1, 0.3, 1);\n --kui-ease-expo-in-out: cubic-bezier(0.87, 0, 0.13, 1);\n --kui-ease-back-in: cubic-bezier(0.36, 0, 0.66, -0.56);\n --kui-ease-back-out: cubic-bezier(0.34, 1.56, 0.64, 1);\n --kui-ease-back-in-out: cubic-bezier(0.68, -0.6, 0.32, 1.6);\n --kui-ease-quart-out: cubic-bezier(0.25, 1, 0.5, 1);\n --kui-ease-circ-out: cubic-bezier(0, 0.55, 0.45, 1);\n --kui-ease-spring: linear(0, 0.4 12%, 0.9 25%, 1.06 38%, 1.01 62%, 1);\n }\n [data-kui-fx] {\n --kui-dir: 1;\n }\n :dir(rtl) [data-kui-fx] {\n --kui-dir: -1;\n }\n}\n@layer kui.policy {\n html[data-kui-cloak] [data-kui][data-kui-reveal]:not([data-kui-state]) {\n opacity: 0 !important;\n }\n @media (prefers-reduced-motion: reduce) {\n [data-kui-rm],\n [data-kui-rm]::before,\n [data-kui-rm]::after,\n [data-kui-rm] .kui-odometer-strip,\n [data-kui-rm][data-kui-fx~=label-float] ~ label,\n [data-kui-rm][data-kui-fx~=input-underline-grow] ~ .kui-underline,\n [data-kui-rm][data-kui-fx~=toggle-morph] ~ .kui-track,\n [data-kui-rm][data-kui-fx~=toggle-morph] ~ .kui-track .kui-thumb,\n [data-kui-rm][data-kui-fx~=checkbox-draw] ~ svg path,\n [data-kui-rm][data-kui-fx~=radio-fill] ~ .kui-dot,\n [data-kui-rm][data-kui-fx~=strength-meter] ~ .kui-meter > * {\n transition-duration: 1ms !important;\n transition-delay: 0ms !important;\n }\n [data-kui-rm=shorten],\n [data-kui-rm=shorten]::before,\n [data-kui-rm=shorten]::after {\n animation-duration: 1ms !important;\n animation-delay: 0ms !important;\n }\n [data-kui-rm=crossfade] {\n animation-name: kui-in !important;\n animation-duration: 200ms !important;\n }\n [data-kui-rm=disable] {\n animation: none !important;\n opacity: 1 !important;\n translate: none !important;\n scale: none !important;\n rotate: none !important;\n filter: none !important;\n }\n }\n @media print {\n [data-kui-fx],\n [data-kui-reveal] {\n animation: none !important;\n opacity: 1 !important;\n translate: none !important;\n scale: none !important;\n rotate: none !important;\n filter: none !important;\n }\n }\n}\n\n/* src/css/presets.generated.css */\n@layer kui.presets {\n [data-kui-fx~=back-in-down] {\n --kui-distance: 120px;\n --kui-reveal-ease: expo-out;\n }\n [data-kui-fx~=back-in-up] {\n --kui-distance: 120px;\n --kui-reveal-ease: expo-out;\n }\n [data-kui-fx~=blob-morph] {\n --kui-path-morph-duration: 800ms;\n }\n [data-kui-fx~=bob] {\n --kui-ambient-float-duration: 2s;\n --kui-distance: 8px;\n }\n [data-kui-fx~=book-page-turn] {\n --kui-from-angle: -160deg;\n --kui-flip-face-duration: 900ms;\n }\n [data-kui-fx~=bounce-in] {\n --kui-from-scale: 0.3;\n --kui-scale-ease: back-out;\n }\n [data-kui-fx~=bounce-in-down] {\n --kui-distance: 60px;\n --kui-reveal-ease: back-out;\n }\n [data-kui-fx~=bounce-in-up] {\n --kui-distance: 60px;\n --kui-reveal-ease: back-out;\n }\n [data-kui-fx~=confetti-burst] {\n --kui-feedback-burst-duration: 900ms;\n --kui-pop-scale: 1.15;\n }\n [data-kui-fx~=count-bump] {\n --kui-feedback-pop-duration: 280ms;\n --kui-pop-scale: 1.3;\n }\n [data-kui-fx~=count-compact] {\n --kui-from: 0;\n --kui-to: 128400;\n --kui-format: compact;\n }\n [data-kui-fx~=count-currency] {\n --kui-from: 0;\n --kui-to: 4820;\n --kui-format: currency;\n --kui-decimals: 0;\n }\n [data-kui-fx~=count-down] {\n --kui-from: 100;\n --kui-to: 0;\n }\n [data-kui-fx~=count-percent] {\n --kui-from: 0;\n --kui-to: 0.82;\n --kui-format: percent;\n --kui-decimals: 0;\n }\n [data-kui-fx~=count-up] {\n --kui-from: 0;\n --kui-to: 100;\n }\n [data-kui-fx~=cube-rotate] {\n --kui-from-angle: 90deg;\n }\n [data-kui-fx~=cursor-follow] {\n --kui-stiffness: 300;\n --kui-damping: 30;\n }\n [data-kui-fx~=cursor-invert] {\n --kui-stiffness: 260;\n --kui-damping: 26;\n }\n [data-kui-fx~=cursor-label] {\n --kui-stiffness: 260;\n --kui-damping: 26;\n }\n [data-kui-fx~=cursor-lag] {\n --kui-stiffness: 80;\n --kui-damping: 14;\n }\n [data-kui-fx~=curtain-wipe] {\n --kui-wipe-duration: 800ms;\n }\n [data-kui-fx~=decode] {\n --kui-charset: binary;\n }\n [data-kui-fx~=depth-layer] {\n --kui-distance: 200px;\n }\n [data-kui-fx~=dot-grid-drift] {\n --kui-ambient-gradient-duration: 16s;\n --kui-ambient-gradient-ease: linear;\n }\n [data-kui-fx~=drag-inertia] {\n --kui-inertia: true;\n }\n [data-kui-fx~=drag-x] {\n --kui-axis: x;\n }\n [data-kui-fx~=drag-y] {\n --kui-axis: y;\n }\n [data-kui-fx~=elastic-pull] {\n --kui-return: true;\n --kui-bounds: 80;\n }\n [data-kui-fx~=expand-to-modal] {\n --kui-flip-scale: true;\n --kui-flip-container-duration: 500ms;\n }\n [data-kui-fx~=floating-shapes] {\n --kui-ambient-float-duration: 6s;\n --kui-distance: 10px;\n }\n [data-kui-fx~=fold-panel] {\n --kui-from-angle: -90deg;\n }\n [data-kui-fx~=glitch] {\n --kui-charset: symbols;\n }\n [data-kui-fx~=gradient-rotate-border] {\n --kui-ambient-gradient-duration: 6s;\n --kui-ambient-gradient-ease: linear;\n }\n [data-kui-fx~=grid-to-list] {\n --kui-flip-scale: true;\n }\n [data-kui-fx~=heart-burst] {\n --kui-feedback-burst-duration: 700ms;\n --kui-pop-scale: 1.4;\n }\n [data-kui-fx~=highlight-sweep] {\n --kui-sweep-color: gold;\n }\n [data-kui-fx~=line-grid-drift] {\n --kui-ambient-gradient-duration: 16s;\n --kui-ambient-gradient-ease: linear;\n }\n [data-kui-fx~=magnetic-snap] {\n --kui-strength: 0.6;\n --kui-radius: 160;\n }\n [data-kui-fx~=mega-menu-drop] {\n --kui-panel-reveal-duration: 550ms;\n }\n [data-kui-fx~=noise-overlay] {\n --kui-ambient-gradient-duration: 650ms;\n --kui-ambient-gradient-ease: steps(6);\n }\n [data-kui-fx~=odometer-roll] {\n --kui-from: 0;\n --kui-to: 4820;\n }\n [data-kui-fx~=pin-section] {\n --kui-distance: 100vh;\n --kui-spacer: true;\n }\n [data-kui-fx~=pin-spacer] {\n --kui-spacer: true;\n }\n [data-kui-fx~=pin-until] {\n --kui-spacer: false;\n }\n [data-kui-fx~=pop-in] {\n --kui-from-scale: 0.6;\n --kui-scale-ease: back-out;\n }\n [data-kui-fx~=pop-out] {\n --kui-from-scale: 0.6;\n --kui-scale-ease: back-in;\n }\n [data-kui-fx~=pull-to-refresh] {\n --kui-feedback-pull-duration: 900ms;\n --kui-feedback-pull-ease: ease-out;\n }\n [data-kui-fx~=rotate-in-left] {\n --kui-from-angle: -45deg;\n }\n [data-kui-fx~=rotate-in-right] {\n --kui-from-angle: 45deg;\n }\n [data-kui-fx~=rubber-band] {\n --kui-return: true;\n --kui-bounds: 120;\n }\n [data-kui-fx~=scanline] {\n --kui-ambient-gradient-duration: 3.5s;\n --kui-ambient-gradient-ease: linear;\n }\n [data-kui-fx~=scramble] {\n --kui-charset: upper;\n }\n [data-kui-fx~=scroll-snap-x] {\n --kui-axis: x;\n }\n [data-kui-fx~=scroll-snap-y] {\n --kui-axis: y;\n }\n [data-kui-fx~=scrollytelling-step] {\n --kui-steps: 4;\n }\n [data-kui-fx~=slide-block-end] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-block-start] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-down] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-inline-end] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-inline-start] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-left] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-out-down] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-out-left] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-out-right] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-out-up] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-right] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=slide-up] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n }\n [data-kui-fx~=snap-back] {\n --kui-return: true;\n --kui-stiffness: 260;\n }\n [data-kui-fx~=split-chars] {\n --kui-unit: chars;\n --kui-direction: fade;\n }\n [data-kui-fx~=split-lines] {\n --kui-unit: lines;\n --kui-direction: fade;\n }\n [data-kui-fx~=split-words] {\n --kui-unit: words;\n --kui-direction: fade;\n }\n [data-kui-fx~=spotlight-follow] {\n --kui-ambient-gradient-duration: 9s;\n }\n [data-kui-fx~=stacking-cards] {\n --kui-spacer: false;\n }\n [data-kui-fx~=starfield] {\n --kui-ambient-gradient-duration: 40s;\n --kui-ambient-gradient-ease: linear;\n }\n [data-kui-fx~=swing-in] {\n --kui-from-angle: -15deg;\n --kui-rotate-ease: back-out;\n }\n [data-kui-fx~=swipe-x] {\n --kui-axis: x;\n }\n [data-kui-fx~=tab-indicator-slide] {\n --kui-flip-indicator-duration: 300ms;\n }\n [data-kui-fx~=text-jitter] {\n --kui-motion: jitter;\n }\n [data-kui-fx~=text-reveal-down] {\n --kui-unit: words;\n --kui-direction: down;\n }\n [data-kui-fx~=text-reveal-mask] {\n --kui-unit: lines;\n --kui-direction: mask;\n }\n [data-kui-fx~=text-reveal-up] {\n --kui-unit: words;\n --kui-direction: up;\n }\n [data-kui-fx~=text-wave] {\n --kui-motion: wave;\n }\n [data-kui-fx~=throwable] {\n --kui-inertia: true;\n --kui-damping: 18;\n }\n [data-kui-fx~=toast-slide-out] {\n --kui-feedback-toast-ease: ease-in;\n }\n [data-kui-fx~=typewriter] {\n --kui-loop: false;\n }\n [data-kui-fx~=typewriter-loop] {\n --kui-loop: true;\n }\n [data-kui-fx~=wave-blob] {\n --kui-ambient-gradient-duration: 12s;\n }\n [data-kui-fx~=wobble] {\n --kui-feedback-wobble-duration: 600ms;\n --kui-feedback-wobble-ease: ease-in-out;\n }\n}\n\n/* src/css/entrance.css */\n@layer kui.effects {\n @keyframes kui-in {\n from {\n opacity: var(--kui-from-opacity, 0);\n }\n }\n @keyframes kui-out {\n to {\n opacity: 0;\n }\n }\n @keyframes kui-in-up {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-in-down {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: 0 calc(var(--kui-distance, 24px) * -1);\n }\n }\n @keyframes kui-in-left {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: var(--kui-distance, 24px) 0;\n }\n }\n @keyframes kui-in-right {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: calc(var(--kui-distance, 24px) * -1) 0;\n }\n }\n @keyframes kui-out-up {\n to {\n opacity: 0;\n translate: 0 calc(var(--kui-distance, 24px) * -1);\n }\n }\n @keyframes kui-out-down {\n to {\n opacity: 0;\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-out-left {\n to {\n opacity: 0;\n translate: calc(var(--kui-distance, 24px) * -1) 0;\n }\n }\n @keyframes kui-out-right {\n to {\n opacity: 0;\n translate: var(--kui-distance, 24px) 0;\n }\n }\n @keyframes kui-in-inline-start {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: calc(var(--kui-distance, 24px) * var(--kui-dir, 1) * -1) 0;\n }\n }\n @keyframes kui-in-inline-end {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: calc(var(--kui-distance, 24px) * var(--kui-dir, 1)) 0;\n }\n }\n @keyframes kui-zoom-in {\n from {\n scale: var(--kui-from-scale, 0.92);\n }\n }\n @keyframes kui-zoom-out {\n to {\n scale: var(--kui-from-scale, 0.92);\n }\n }\n @keyframes kui-zoom-in-up {\n from {\n scale: var(--kui-from-scale, 0.92);\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-zoom-in-down {\n from {\n scale: var(--kui-from-scale, 0.92);\n translate: 0 calc(var(--kui-distance, 24px) * -1);\n }\n }\n @keyframes kui-flip-in-x {\n from {\n rotate: x var(--kui-from-angle, 90deg);\n }\n }\n @keyframes kui-flip-in-y {\n from {\n rotate: y var(--kui-from-angle, 90deg);\n }\n }\n @keyframes kui-flip-out-x {\n to {\n rotate: x var(--kui-from-angle, 90deg);\n }\n }\n @keyframes kui-flip-out-y {\n to {\n rotate: y var(--kui-from-angle, 90deg);\n }\n }\n @keyframes kui-rotate-in {\n from {\n rotate: var(--kui-from-angle, -8deg);\n }\n }\n @keyframes kui-rotate-out {\n to {\n rotate: var(--kui-from-angle, -8deg);\n }\n }\n @keyframes kui-swing-in {\n from {\n rotate: var(--kui-from-angle, -15deg);\n }\n }\n @keyframes kui-roll-in {\n from {\n rotate: var(--kui-from-angle, -120deg);\n translate: calc(var(--kui-distance, 24px) * -1) 0;\n }\n }\n @keyframes kui-roll-out {\n to {\n rotate: var(--kui-from-angle, -120deg);\n translate: var(--kui-distance, 24px) 0;\n }\n }\n @keyframes kui-blur-in {\n from {\n filter: blur(var(--kui-blur, 12px));\n }\n }\n @keyframes kui-blur-out {\n to {\n filter: blur(var(--kui-blur, 12px));\n }\n }\n @keyframes kui-fade-blur-up {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: 0 var(--kui-distance, 24px);\n filter: blur(var(--kui-blur, 12px));\n }\n }\n @keyframes kui-fade-blur-in {\n from {\n opacity: var(--kui-from-opacity, 0);\n filter: blur(var(--kui-blur, 12px));\n }\n }\n [data-kui-fx*=flip-] {\n transform-style: preserve-3d;\n }\n}\n\n/* src/css/scroll.css */\n@layer kui.effects {\n @keyframes kui-parallax-y {\n from {\n translate: 0 calc(var(--kui-distance, 100px) * -1);\n }\n to {\n translate: 0 var(--kui-distance, 100px);\n }\n }\n @keyframes kui-parallax-x {\n from {\n translate: calc(var(--kui-distance, 100px) * -1) 0;\n }\n to {\n translate: var(--kui-distance, 100px) 0;\n }\n }\n @keyframes kui-parallax-scale {\n from {\n scale: 1;\n }\n to {\n scale: var(--kui-to-scale, 1.2);\n }\n }\n @keyframes kui-parallax-rotate {\n from {\n rotate: 0deg;\n }\n to {\n rotate: var(--kui-to-angle, 12deg);\n }\n }\n @keyframes kui-scroll-fade {\n from {\n opacity: var(--kui-from-opacity, 0);\n }\n to {\n opacity: 1;\n }\n }\n @keyframes kui-progress-x {\n from {\n scale: 0 1;\n }\n to {\n scale: 1 1;\n }\n }\n @keyframes kui-progress-ring {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n [data-kui-fx~=scroll-progress-bar] {\n transform-origin: left center;\n }\n [data-kui-fx~=scroll-progress-ring] {\n stroke-dasharray: var(--kui-path-length, 100);\n }\n @supports (animation-timeline: view()) {\n [data-kui-timeline] {\n animation-range: var(--kui-range, entry 0% cover 60%);\n }\n }\n}\n\n/* src/css/three-d.css */\n@layer kui.effects {\n @keyframes kui-card-flip-y {\n to {\n rotate: y var(--kui-from-angle, 180deg);\n }\n }\n @keyframes kui-card-flip-x {\n to {\n rotate: x var(--kui-from-angle, 180deg);\n }\n }\n @keyframes kui-cube-rotate {\n to {\n rotate: y var(--kui-from-angle, 90deg);\n }\n }\n @keyframes kui-book-page-turn {\n to {\n rotate: y var(--kui-from-angle, -160deg);\n }\n }\n @keyframes kui-fold-panel {\n from {\n rotate: x var(--kui-from-angle, -90deg);\n }\n }\n [data-kui-fx~=card-flip-x],\n [data-kui-fx~=card-flip-y],\n [data-kui-fx~=cube-rotate],\n [data-kui-fx~=book-page-turn],\n [data-kui-fx~=fold-panel] {\n transform-style: preserve-3d;\n perspective: var(--kui-perspective, 1200px);\n }\n [data-kui-fx~=book-page-turn] {\n transform-origin: left center;\n }\n [data-kui-fx~=fold-panel] {\n transform-origin: top center;\n }\n @keyframes kui-page-fade {\n from {\n opacity: 0;\n }\n }\n @keyframes kui-page-slide {\n from {\n opacity: 0;\n translate: 0 var(--kui-distance, 40px);\n }\n }\n @keyframes kui-curtain-wipe {\n from {\n clip-path: inset(0 0 100% 0);\n }\n }\n @keyframes kui-loading-bar {\n from {\n scale: 0 1;\n }\n }\n [data-kui-fx~=loading-bar] {\n transform-origin: left center;\n }\n}\n\n/* src/css/media.css */\n@layer kui.effects {\n @keyframes kui-wipe-up {\n from {\n clip-path: inset(100% 0 0);\n }\n }\n @keyframes kui-wipe-down {\n from {\n clip-path: inset(0 0 100%);\n }\n }\n @keyframes kui-wipe-left {\n from {\n clip-path: inset(0 100% 0 0);\n }\n }\n @keyframes kui-wipe-right {\n from {\n clip-path: inset(0 0 0 100%);\n }\n }\n @keyframes kui-wipe-circle {\n from {\n clip-path: circle(0 at 50% 50%);\n }\n }\n @keyframes kui-wipe-diagonal {\n from {\n clip-path: polygon(0 0, 0 0, 0 0);\n }\n to {\n clip-path: polygon(0 0, 200% 0, 0 200%);\n }\n }\n @keyframes kui-curtain-reveal {\n from {\n clip-path: inset(0 50%);\n }\n }\n @keyframes kui-before-after-wipe {\n from {\n clip-path: inset(0 100% 0 0);\n }\n }\n @keyframes kui-mask-reveal {\n from {\n mask-position: 100% 0;\n }\n to {\n mask-position: 0 0;\n }\n }\n [data-kui-fx~=mask-reveal] {\n mask-image:\n linear-gradient(\n 90deg,\n #000 0 45%,\n transparent 55% 100%);\n mask-size: 220% 100%;\n }\n @keyframes kui-ken-burns {\n from {\n scale: 1;\n translate: 0 0;\n }\n to {\n scale: var(--kui-to-scale, 1.12);\n translate: var(--kui-distance, 24px) calc(var(--kui-distance, 24px) * -0.5);\n }\n }\n @keyframes kui-ken-burns-out {\n from {\n scale: var(--kui-to-scale, 1.12);\n translate: calc(var(--kui-distance, 24px) * -1) 0;\n }\n to {\n scale: 1;\n translate: 0 0;\n }\n }\n @keyframes kui-blur-up {\n from {\n translate: 0 var(--kui-distance, 24px);\n filter: blur(var(--kui-blur, 16px));\n }\n to {\n translate: 0 0;\n filter: blur(0);\n }\n }\n @keyframes kui-duotone-hover {\n from {\n filter: grayscale(1) sepia(0.7) hue-rotate(330deg) saturate(2);\n }\n to {\n filter: none;\n }\n }\n @keyframes kui-grayscale-hover {\n from {\n filter: grayscale(1);\n }\n to {\n filter: grayscale(0);\n }\n }\n @keyframes kui-saturate-hover {\n from {\n filter: saturate(0.45);\n }\n to {\n filter: saturate(1.35);\n }\n }\n @keyframes kui-image-parallax-frame {\n from {\n translate: 0 calc(var(--kui-distance, 24px) * -1);\n }\n to {\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-lightbox-open {\n from {\n opacity: 0;\n scale: 0.92;\n }\n to {\n opacity: 1;\n scale: 1;\n }\n }\n @media (pointer: coarse) {\n [data-kui-fx~=duotone-hover]:active,\n [data-kui-fx~=grayscale-hover]:active,\n [data-kui-fx~=saturate-hover]:active {\n filter: none;\n }\n }\n}\n\n/* src/css/text.css */\n@layer kui.effects {\n .kui-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n }\n .kui-split-decorative {\n display: inline;\n }\n .kui-split-item {\n display: inline-block;\n animation-duration: var(--kui-duration, 500ms);\n animation-delay: calc(var(--kui-delay, 0ms) + var(--kui-i, 0) * var(--kui-stagger, 30ms));\n animation-timing-function: var(--kui-ease, ease-out);\n animation-fill-mode: both;\n }\n .kui-split-line {\n display: block;\n }\n [data-kui-split-fx=fade] .kui-split-item {\n animation-name: kui-split-reveal-fade;\n }\n [data-kui-split-fx=up] .kui-split-item {\n animation-name: kui-split-reveal-up;\n }\n [data-kui-split-fx=down] .kui-split-item {\n animation-name: kui-split-reveal-down;\n }\n [data-kui-split-fx=mask] .kui-split-item {\n animation-name: kui-split-reveal-mask;\n }\n @keyframes kui-split-reveal-fade {\n from {\n opacity: 0;\n }\n }\n @keyframes kui-split-reveal-up {\n from {\n opacity: 0;\n translate: 0 0.6em;\n }\n }\n @keyframes kui-split-reveal-down {\n from {\n opacity: 0;\n translate: 0 -0.6em;\n }\n }\n @keyframes kui-split-reveal-mask {\n from {\n opacity: 0;\n clip-path: inset(0 0 100% 0);\n }\n }\n [data-kui-split-fx=wave] .kui-split-item {\n animation-name: kui-split-wave;\n animation-duration: 1400ms;\n animation-iteration-count: infinite;\n animation-timing-function: ease-in-out;\n }\n [data-kui-split-fx=jitter] .kui-split-item {\n animation-name: kui-split-jitter;\n animation-duration: 220ms;\n animation-iteration-count: infinite;\n animation-timing-function: ease-in-out;\n animation-direction: alternate;\n }\n @keyframes kui-split-wave {\n 0%, 100% {\n translate: 0 0;\n }\n 50% {\n translate: 0 -0.35em;\n }\n }\n @keyframes kui-split-jitter {\n from {\n translate: 0 0;\n rotate: 0deg;\n }\n to {\n translate: 0 0.08em;\n rotate: 3deg;\n }\n }\n .kui-typewriter::after {\n content: \"\";\n display: inline-block;\n width: 0.08em;\n margin-inline-start: 0.05em;\n height: 1em;\n vertical-align: -0.15em;\n background: currentColor;\n animation: kui-caret-blink 1s steps(1) infinite;\n }\n @keyframes kui-caret-blink {\n 50% {\n opacity: 0;\n }\n }\n .kui-scramble {\n font-variant-numeric: tabular-nums;\n }\n [data-kui-fx~=word-cycler] {\n display: inline-block;\n transition: opacity 150ms ease-out;\n }\n [data-kui-fx~=word-cycler].kui-word-cycler-swap {\n opacity: 0;\n }\n [data-kui-fx~=gradient-shimmer] {\n background-image:\n linear-gradient(\n 100deg,\n currentColor 40%,\n color-mix(in srgb, currentColor 35%, transparent) 50%,\n currentColor 60%);\n background-size: 220% 100%;\n -webkit-background-clip: text;\n background-clip: text;\n -webkit-text-fill-color: transparent;\n --kui-fx-gradient-shimmer-iterations: infinite;\n }\n @keyframes kui-gradient-shimmer {\n from {\n background-position: 200% 0;\n }\n to {\n background-position: -200% 0;\n }\n }\n [data-kui-fx~=gradient-sweep] {\n background-image:\n linear-gradient(\n 100deg,\n transparent 30%,\n color-mix(in srgb, var(--kui-sweep-color, currentColor) 70%, transparent) 50%,\n transparent 70%);\n background-size: 260% 100%;\n -webkit-background-clip: text;\n background-clip: text;\n -webkit-text-fill-color: transparent;\n }\n @keyframes kui-gradient-sweep {\n from {\n background-position: 220% 0;\n }\n to {\n background-position: -60% 0;\n }\n }\n [data-kui-fx~=highlight-sweep] {\n background-image: linear-gradient(90deg, color-mix(in srgb, var(--kui-sweep-color, currentColor) 55%, transparent) 0 100%);\n background-repeat: no-repeat;\n background-size: 0% 100%;\n padding: 0 0.05em;\n }\n @keyframes kui-highlight-sweep {\n to {\n background-size: 100% 100%;\n }\n }\n [data-kui-fx~=underline-draw] {\n background-image: linear-gradient(var(--kui-sweep-color, currentColor), var(--kui-sweep-color, currentColor));\n background-repeat: no-repeat;\n background-position: 0 100%;\n background-size: 0% 2px;\n padding-bottom: 0.15em;\n }\n @keyframes kui-underline-draw {\n to {\n background-size: 100% 2px;\n }\n }\n [data-kui-fx~=text-outline-fill] {\n -webkit-text-stroke: 1px currentColor;\n color: transparent;\n }\n @keyframes kui-text-outline-fill {\n to {\n color: currentColor;\n }\n }\n @keyframes kui-var-weight {\n from {\n font-weight: var(--kui-from-weight, 100);\n }\n to {\n font-weight: var(--kui-to-weight, 800);\n }\n }\n @keyframes kui-var-width {\n from {\n font-stretch: var(--kui-from-width, 75%);\n }\n to {\n font-stretch: var(--kui-to-width, 125%);\n }\n }\n @keyframes kui-var-slant {\n from {\n font-style: oblique var(--kui-from-slant, 0deg);\n }\n to {\n font-style: oblique var(--kui-to-slant, 10deg);\n }\n }\n [data-kui-fx~=marquee],\n [data-kui-fx~=marquee-scroll-linked] {\n display: flex;\n width: max-content;\n will-change: translate;\n }\n [data-kui-fx~=marquee] {\n --kui-fx-marquee-iterations: infinite;\n }\n @keyframes kui-marquee {\n to {\n translate: -50% 0;\n }\n }\n @property --kui-redaction-x { syntax: \"<percentage>\"; inherits: true; initial-value: 0%; }\n [data-kui-fx~=redaction-reveal] {\n position: relative;\n display: inline-block;\n }\n [data-kui-fx~=redaction-reveal]::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background: var(--kui-bar-color, #111);\n clip-path: inset(0 0 0 var(--kui-redaction-x));\n }\n @keyframes kui-redaction-reveal {\n to {\n --kui-redaction-x: 100%;\n }\n }\n [data-kui-fx~=text-3d-extrude] {\n display: inline-block;\n text-shadow:\n 1px 1px 0 color-mix(in srgb, currentColor 70%, transparent),\n 2px 2px 0 color-mix(in srgb, currentColor 60%, transparent),\n 3px 3px 0 color-mix(in srgb, currentColor 50%, transparent),\n 4px 4px 0 color-mix(in srgb, currentColor 40%, transparent),\n 5px 5px 0 color-mix(in srgb, currentColor 30%, transparent),\n 6px 6px 8px rgb(0 0 0 / 0.35);\n }\n @keyframes kui-text-3d-extrude {\n from {\n rotate: var(--kui-from-angle, -20deg);\n translate: 0 var(--kui-distance, 32px);\n }\n to {\n rotate: 0deg;\n translate: 0 0;\n }\n }\n}\n\n/* src/css/navigation.css */\n@layer kui.effects {\n @keyframes kui-nav-reveal {\n from {\n opacity: 0;\n translate: 0 var(--kui-distance, 16px);\n }\n }\n @keyframes kui-menu-fullscreen {\n from {\n opacity: 0;\n clip-path: circle(0% at var(--kui-origin, 100% 0%));\n }\n to {\n opacity: 1;\n clip-path: circle(150% at var(--kui-origin, 100% 0%));\n }\n }\n @keyframes kui-panel-reveal {\n from {\n opacity: 0;\n translate: 0 calc(var(--kui-distance, 10px) * -1);\n }\n }\n @keyframes kui-drawer-slide-right {\n from {\n translate: 100% 0;\n }\n }\n [data-kui-fx~=header-shrink] {\n --kui-shrink: 0;\n padding-block: calc(1.4rem - 0.7rem * var(--kui-shrink, 0));\n font-size: calc(1rem - 0.15rem * var(--kui-shrink, 0));\n transition:\n padding-block 200ms ease-out,\n font-size 200ms ease-out,\n box-shadow 200ms ease-out;\n }\n [data-kui-fx~=header-shrink][data-kui-shrunk=true] {\n box-shadow: 0 2px 10px rgb(0 0 0 / 0.12);\n }\n [data-kui-fx~=header-hide-on-scroll] {\n transition: translate 220ms ease-out;\n }\n [data-kui-fx~=header-hide-on-scroll][data-kui-hidden=true] {\n translate: 0 -100%;\n }\n [data-kui-fx~=back-to-top-fade] {\n opacity: 0;\n translate: 0 12px;\n pointer-events: none;\n transition: opacity 200ms ease-out, translate 200ms ease-out;\n }\n [data-kui-fx~=back-to-top-fade][data-kui-visible=true] {\n opacity: 1;\n translate: 0 0;\n pointer-events: auto;\n }\n}\n\n/* src/css/forms.css */\n@layer kui.effects {\n [data-kui-fx~=label-float] ~ label {\n transition: translate 180ms ease-out, scale 180ms ease-out;\n transform-origin: left center;\n }\n [data-kui-fx~=label-float]:focus ~ label,\n [data-kui-fx~=label-float]:not(:placeholder-shown) ~ label {\n translate: 0 -1.35rem;\n scale: 0.82;\n }\n [data-kui-fx~=input-underline-grow] ~ .kui-underline {\n display: block;\n height: 2px;\n background: currentColor;\n scale: 0 1;\n transform-origin: left center;\n transition: scale 220ms ease-out;\n }\n [data-kui-fx~=input-underline-grow]:focus ~ .kui-underline {\n scale: 1 1;\n }\n @keyframes kui-focus-ring-grow {\n from {\n box-shadow: 0 0 0 0 var(--kui-ring-color, rgb(210 105 30 / 0.55));\n }\n to {\n box-shadow: 0 0 0 5px var(--kui-ring-color, rgb(210 105 30 / 0.55));\n }\n }\n @keyframes kui-validate-shake {\n 10%, 90% {\n translate: -1px 0;\n }\n 20%, 80% {\n translate: 2px 0;\n }\n 30%, 50%, 70% {\n translate: -4px 0;\n }\n 40%, 60% {\n translate: 4px 0;\n }\n }\n [data-kui-fx~=validate-check] {\n stroke-dasharray: 24;\n stroke-dashoffset: 24;\n }\n @keyframes kui-validate-check {\n to {\n stroke-dashoffset: 0;\n }\n }\n [data-kui-fx~=strength-meter] ~ .kui-meter > * {\n background: var(--kui-meter-off, currentColor);\n opacity: 0.2;\n transition: opacity 200ms ease-out, background-color 200ms ease-out;\n }\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"1\"] ~ .kui-meter > *:nth-child(-n+1),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"2\"] ~ .kui-meter > *:nth-child(-n+2),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"3\"] ~ .kui-meter > *:nth-child(-n+3),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"4\"] ~ .kui-meter > *:nth-child(-n+4),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"5\"] ~ .kui-meter > *:nth-child(-n+5),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"6\"] ~ .kui-meter > *:nth-child(-n+6),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"7\"] ~ .kui-meter > *:nth-child(-n+7),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"8\"] ~ .kui-meter > *:nth-child(-n+8),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"9\"] ~ .kui-meter > *:nth-child(-n+9),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"10\"] ~ .kui-meter > *:nth-child(-n+10),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"11\"] ~ .kui-meter > *:nth-child(-n+11),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"12\"] ~ .kui-meter > *:nth-child(-n+12),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"13\"] ~ .kui-meter > *:nth-child(-n+13),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"14\"] ~ .kui-meter > *:nth-child(-n+14),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"15\"] ~ .kui-meter > *:nth-child(-n+15),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"16\"] ~ .kui-meter > *:nth-child(-n+16),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"17\"] ~ .kui-meter > *:nth-child(-n+17),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"18\"] ~ .kui-meter > *:nth-child(-n+18),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"19\"] ~ .kui-meter > *:nth-child(-n+19),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"20\"] ~ .kui-meter > *:nth-child(-n+20) {\n opacity: 1;\n background: var(--kui-meter-on, #2e9e5b);\n }\n [data-kui-fx~=toggle-morph] ~ .kui-track {\n display: inline-block;\n width: calc(40px * var(--kui-toggle-scale, 1));\n height: calc(22px * var(--kui-toggle-scale, 1));\n border-radius: 999px;\n background: var(--dim, #9a8d80);\n transition: background-color 200ms ease-out;\n position: relative;\n }\n [data-kui-fx~=toggle-morph] ~ .kui-track .kui-thumb {\n position: absolute;\n top: calc(2px * var(--kui-toggle-scale, 1));\n left: calc(2px * var(--kui-toggle-scale, 1));\n width: calc(18px * var(--kui-toggle-scale, 1));\n height: calc(18px * var(--kui-toggle-scale, 1));\n border-radius: 50%;\n background: var(--kui-thumb-color, #fff);\n translate: 0 0;\n transition: translate 200ms ease-out;\n }\n [data-kui-fx~=toggle-morph]:checked ~ .kui-track {\n background: var(--accent, #d2691e);\n }\n [data-kui-fx~=toggle-morph]:checked ~ .kui-track .kui-thumb {\n translate: calc(18px * var(--kui-toggle-scale, 1)) 0;\n }\n [data-kui-fx~=checkbox-draw] ~ svg path {\n stroke-dasharray: 24;\n stroke-dashoffset: 24;\n transition: stroke-dashoffset 220ms ease-out;\n }\n [data-kui-fx~=checkbox-draw]:checked ~ svg path {\n stroke-dashoffset: 0;\n }\n [data-kui-fx~=radio-fill] ~ .kui-dot {\n display: inline-block;\n width: calc(10px * var(--kui-radio-scale, 1));\n height: calc(10px * var(--kui-radio-scale, 1));\n border-radius: 50%;\n background: var(--accent, #d2691e);\n scale: 0;\n transition: scale 180ms ease-out;\n }\n [data-kui-fx~=radio-fill]:checked ~ .kui-dot {\n scale: 1;\n }\n [data-kui-fx~=range-fill] {\n --kui-fill: 0%;\n accent-color: var(--accent, #d2691e);\n background:\n linear-gradient(\n to right,\n var(--accent, #d2691e) var(--kui-fill, 0%),\n var(--line, #2a2422) var(--kui-fill, 0%));\n height: 4px;\n border-radius: 999px;\n appearance: none;\n outline: none;\n }\n [data-kui-fx~=submit-to-spinner-to-check] .kui-stage-idle,\n [data-kui-fx~=submit-to-spinner-to-check] .kui-stage-loading,\n [data-kui-fx~=submit-to-spinner-to-check] .kui-stage-done {\n display: none;\n }\n [data-kui-fx~=submit-to-spinner-to-check][data-kui-stage=idle] .kui-stage-idle,\n [data-kui-fx~=submit-to-spinner-to-check][data-kui-stage=loading] .kui-stage-loading,\n [data-kui-fx~=submit-to-spinner-to-check][data-kui-stage=done] .kui-stage-done {\n display: inline-flex;\n }\n [data-kui-fx~=submit-to-spinner-to-check] .kui-spinner {\n width: 1em;\n height: 1em;\n border-radius: 50%;\n border: 2px solid currentColor;\n border-top-color: transparent;\n animation: kui-spin 700ms linear infinite;\n }\n @keyframes kui-spin {\n to {\n rotate: 360deg;\n }\n }\n [data-kui-fx~=step-progress] {\n cursor: pointer;\n }\n [data-kui-fx~=step-progress] > * {\n background: var(--dim, #9a8d80);\n opacity: 0.35;\n transition: opacity 200ms ease-out, background-color 200ms ease-out;\n }\n [data-kui-fx~=step-progress][data-kui-step=\"0\"] > *:nth-child(-n+1),\n [data-kui-fx~=step-progress][data-kui-step=\"1\"] > *:nth-child(-n+2),\n [data-kui-fx~=step-progress][data-kui-step=\"2\"] > *:nth-child(-n+3),\n [data-kui-fx~=step-progress][data-kui-step=\"3\"] > *:nth-child(-n+4),\n [data-kui-fx~=step-progress][data-kui-step=\"4\"] > *:nth-child(-n+5),\n [data-kui-fx~=step-progress][data-kui-step=\"5\"] > *:nth-child(-n+6),\n [data-kui-fx~=step-progress][data-kui-step=\"6\"] > *:nth-child(-n+7),\n [data-kui-fx~=step-progress][data-kui-step=\"7\"] > *:nth-child(-n+8),\n [data-kui-fx~=step-progress][data-kui-step=\"8\"] > *:nth-child(-n+9),\n [data-kui-fx~=step-progress][data-kui-step=\"9\"] > *:nth-child(-n+10),\n [data-kui-fx~=step-progress][data-kui-step=\"10\"] > *:nth-child(-n+11),\n [data-kui-fx~=step-progress][data-kui-step=\"11\"] > *:nth-child(-n+12),\n [data-kui-fx~=step-progress][data-kui-step=\"12\"] > *:nth-child(-n+13),\n [data-kui-fx~=step-progress][data-kui-step=\"13\"] > *:nth-child(-n+14),\n [data-kui-fx~=step-progress][data-kui-step=\"14\"] > *:nth-child(-n+15),\n [data-kui-fx~=step-progress][data-kui-step=\"15\"] > *:nth-child(-n+16),\n [data-kui-fx~=step-progress][data-kui-step=\"16\"] > *:nth-child(-n+17),\n [data-kui-fx~=step-progress][data-kui-step=\"17\"] > *:nth-child(-n+18),\n [data-kui-fx~=step-progress][data-kui-step=\"18\"] > *:nth-child(-n+19),\n [data-kui-fx~=step-progress][data-kui-step=\"19\"] > *:nth-child(-n+20) {\n opacity: 1;\n background: var(--accent, #d2691e);\n }\n}\n\n/* src/css/ambient.css */\n@layer kui.effects {\n [data-kui-fx~=gradient-mesh] {\n background-image:\n radial-gradient(\n at 15% 20%,\n color-mix(in srgb, var(--kui-c1, #7c3aed) 55%, transparent),\n transparent 55%),\n radial-gradient(\n at 85% 15%,\n color-mix(in srgb, var(--kui-c2, #06b6d4) 50%, transparent),\n transparent 55%),\n radial-gradient(\n at 50% 85%,\n color-mix(in srgb, var(--kui-c3, #f97316) 45%, transparent),\n transparent 55%);\n background-size: 200% 200%;\n --kui-fx-gradient-mesh-iterations: infinite;\n }\n @keyframes kui-gradient-mesh {\n 0%, 100% {\n background-position:\n 0% 0%,\n 100% 0%,\n 50% 100%;\n }\n 50% {\n background-position:\n 25% 35%,\n 75% 30%,\n 35% 70%;\n }\n }\n [data-kui-fx~=aurora] {\n background-image:\n linear-gradient(\n 120deg,\n color-mix(in srgb, var(--kui-c1, #34d399) 45%, transparent),\n transparent 45%),\n linear-gradient(\n 240deg,\n color-mix(in srgb, var(--kui-c2, #60a5fa) 45%, transparent),\n transparent 45%),\n linear-gradient(\n 0deg,\n color-mix(in srgb, var(--kui-c3, #c084fc) 40%, transparent),\n transparent 50%);\n background-size: 260% 260%;\n --kui-fx-aurora-iterations: infinite;\n }\n @keyframes kui-aurora {\n 0%, 100% {\n background-position:\n 0% 50%,\n 100% 50%,\n 50% 0%;\n }\n 50% {\n background-position:\n 60% 30%,\n 40% 70%,\n 55% 60%;\n }\n }\n [data-kui-fx~=wave-blob] {\n background-image:\n radial-gradient(\n circle,\n color-mix(in srgb, var(--kui-c1, #22d3ee) 50%, transparent),\n transparent 60%);\n background-size: 140% 140%;\n background-repeat: no-repeat;\n --kui-fx-wave-blob-iterations: infinite;\n }\n @keyframes kui-wave-blob {\n 0%, 100% {\n background-position: 20% 30%;\n background-size: 140% 140%;\n }\n 33% {\n background-position: 70% 20%;\n background-size: 160% 160%;\n }\n 66% {\n background-position: 50% 75%;\n background-size: 120% 120%;\n }\n }\n [data-kui-fx~=spotlight-follow] {\n background-image:\n radial-gradient(\n circle,\n color-mix(in srgb, var(--kui-c1, #fde68a) 65%, transparent),\n transparent 65%);\n background-size: 55% 55%;\n background-repeat: no-repeat;\n --kui-fx-spotlight-follow-iterations: infinite;\n }\n @keyframes kui-spotlight-follow {\n 0%, 100% {\n background-position: 10% 15%;\n }\n 25% {\n background-position: 85% 20%;\n }\n 50% {\n background-position: 80% 80%;\n }\n 75% {\n background-position: 15% 75%;\n }\n }\n [data-kui-fx~=gradient-rotate-border] {\n position: relative;\n background-image:\n linear-gradient(\n 90deg,\n var(--kui-c1, #f472b6),\n var(--kui-c2, #60a5fa),\n var(--kui-c3, #34d399),\n var(--kui-c4, #fbbf24),\n var(--kui-c1, #f472b6));\n background-size: 300% 100%;\n padding: 3px;\n mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);\n mask-composite: exclude;\n -webkit-mask-composite: xor;\n --kui-fx-gradient-rotate-border-iterations: infinite;\n }\n @keyframes kui-gradient-rotate-border {\n from {\n background-position: 0% 50%;\n }\n to {\n background-position: 300% 50%;\n }\n }\n [data-kui-fx~=noise-overlay] {\n background-image:\n repeating-radial-gradient(\n circle at 0 0,\n color-mix(in srgb, var(--kui-c1, currentColor) 30%, transparent) 0,\n transparent 1.4px,\n transparent 3px);\n background-size: 5px 5px;\n --kui-fx-noise-overlay-iterations: infinite;\n }\n @keyframes kui-noise-overlay {\n 0% {\n background-position: 0 0;\n }\n 20% {\n background-position: -3px 1px;\n }\n 40% {\n background-position: 2px -2px;\n }\n 60% {\n background-position: -1px 3px;\n }\n 80% {\n background-position: 3px 2px;\n }\n 100% {\n background-position: 0 0;\n }\n }\n [data-kui-fx~=scanline] {\n background-image:\n linear-gradient(\n to bottom,\n transparent,\n color-mix(in srgb, var(--kui-c1, currentColor) 35%, transparent) 50%,\n transparent);\n background-size: 100% 220%;\n background-repeat: no-repeat;\n --kui-fx-scanline-iterations: infinite;\n }\n @keyframes kui-scanline {\n from {\n background-position: 0 -120%;\n }\n to {\n background-position: 0 120%;\n }\n }\n [data-kui-fx~=dot-grid-drift] {\n background-image:\n radial-gradient(\n circle,\n color-mix(in srgb, var(--kui-c1, currentColor) 45%, transparent) 1.5px,\n transparent 1.5px);\n background-size: 22px 22px;\n --kui-fx-dot-grid-drift-iterations: infinite;\n }\n @keyframes kui-dot-grid-drift {\n from {\n background-position: 0 0;\n }\n to {\n background-position: 22px 22px;\n }\n }\n [data-kui-fx~=line-grid-drift] {\n background-image:\n repeating-linear-gradient(\n 0deg,\n color-mix(in srgb, var(--kui-c1, currentColor) 30%, transparent) 0 1px,\n transparent 1px 26px),\n repeating-linear-gradient(\n 90deg,\n color-mix(in srgb, var(--kui-c1, currentColor) 30%, transparent) 0 1px,\n transparent 1px 26px);\n --kui-fx-line-grid-drift-iterations: infinite;\n }\n @keyframes kui-line-grid-drift {\n from {\n background-position: 0 0, 0 0;\n }\n to {\n background-position: 0 26px, 26px 0;\n }\n }\n [data-kui-fx~=starfield] {\n background-image:\n radial-gradient(\n 1px 1px at 10% 20%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 90%, transparent),\n transparent),\n radial-gradient(\n 1px 1px at 70% 60%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 70%, transparent),\n transparent),\n radial-gradient(\n 1.5px 1.5px at 40% 80%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 85%, transparent),\n transparent),\n radial-gradient(\n 1px 1px at 90% 30%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 60%, transparent),\n transparent),\n radial-gradient(\n 1.5px 1.5px at 25% 55%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 80%, transparent),\n transparent);\n background-size: 220px 220px;\n background-repeat: repeat;\n --kui-fx-starfield-iterations: infinite;\n }\n @keyframes kui-starfield {\n from {\n background-position:\n 0 0,\n 0 0,\n 0 0,\n 0 0,\n 0 0;\n }\n to {\n background-position:\n 220px 90px,\n -160px 220px,\n 90px -140px,\n -220px -90px,\n 140px 160px;\n }\n }\n [data-kui-fx~=float] {\n --kui-fx-float-iterations: infinite;\n }\n @keyframes kui-float {\n 0%, 100% {\n translate: 0 0;\n }\n 50% {\n translate: 0 calc(var(--kui-distance, 14px) * -1);\n }\n }\n [data-kui-fx~=bob] {\n --kui-fx-bob-iterations: infinite;\n }\n @keyframes kui-bob {\n 0%, 100% {\n translate: 0 0;\n }\n 50% {\n translate: 0 calc(var(--kui-distance, 8px) * -1);\n }\n }\n [data-kui-fx~=floating-shapes] {\n --kui-fx-floating-shapes-iterations: infinite;\n }\n @keyframes kui-floating-shapes {\n 0%, 100% {\n translate: 0 0;\n }\n 33% {\n translate: calc(var(--kui-distance, 10px) * 0.6) calc(var(--kui-distance, 10px) * -1);\n }\n 66% {\n translate: calc(var(--kui-distance, 10px) * -0.6) calc(var(--kui-distance, 10px) * -0.4);\n }\n }\n [data-kui-fx~=glow-pulse] {\n --kui-fx-glow-pulse-iterations: infinite;\n }\n @keyframes kui-glow-pulse {\n 0%, 100% {\n scale: 1;\n opacity: 0.6;\n }\n 50% {\n scale: var(--kui-pulse-scale, 1.15);\n opacity: 1;\n }\n }\n}\n\n/* src/css/feedback.css */\n@layer kui.effects {\n [data-kui-fx~=skeleton-shimmer] {\n background-color: var(--kui-skeleton-base, #2a2422);\n background-image:\n linear-gradient(\n 100deg,\n transparent 30%,\n color-mix(in srgb, var(--kui-skeleton-highlight, #ffffff) 18%, transparent) 50%,\n transparent 70%);\n background-size: 200% 100%;\n --kui-fx-skeleton-shimmer-iterations: infinite;\n }\n @keyframes kui-skeleton-shimmer {\n from {\n background-position: 150% 0;\n }\n to {\n background-position: -50% 0;\n }\n }\n @keyframes kui-skeleton-to-content {\n from {\n opacity: 0;\n }\n }\n [data-kui-fx~=spinner] {\n display: inline-block;\n width: var(--kui-spinner-size, 28px);\n height: var(--kui-spinner-size, 28px);\n border-radius: 50%;\n border: 3px solid color-mix(in srgb, currentColor 20%, transparent);\n border-top-color: currentColor;\n --kui-fx-spinner-iterations: infinite;\n }\n @keyframes kui-spinner-spin {\n to {\n rotate: 360deg;\n }\n }\n [data-kui-fx~=spinner-ring] {\n display: inline-block;\n width: var(--kui-spinner-size, 28px);\n height: var(--kui-spinner-size, 28px);\n border-radius: 50%;\n border: 3px dashed color-mix(in srgb, currentColor 55%, transparent);\n --kui-fx-spinner-ring-iterations: infinite;\n }\n @keyframes kui-spinner-ring-spin {\n to {\n rotate: 360deg;\n }\n }\n [data-kui-fx~=spinner-dots] {\n display: inline-block;\n width: var(--kui-dot-size, 8px);\n height: var(--kui-dot-size, 8px);\n border-radius: 50%;\n background: currentColor;\n box-shadow: calc(var(--kui-dot-size, 8px) * -2) 0 currentColor, calc(var(--kui-dot-size, 8px) * 2) 0 currentColor;\n --kui-fx-spinner-dots-iterations: infinite;\n }\n @keyframes kui-spinner-dots {\n 0%, 80%, 100% {\n scale: 0.7;\n opacity: 0.5;\n }\n 40% {\n scale: 1.15;\n opacity: 1;\n }\n }\n [data-kui-fx~=progress-indeterminate] {\n transform-origin: 0% 50%;\n background: currentColor;\n border-radius: inherit;\n --kui-fx-progress-indeterminate-iterations: infinite;\n }\n @keyframes kui-progress-indeterminate {\n 0% {\n translate: -100% 0;\n scale: 0.4 1;\n }\n 50% {\n scale: 1 1;\n }\n 100% {\n translate: 100% 0;\n scale: 0.4 1;\n }\n }\n @keyframes kui-toast-slide-in {\n from {\n opacity: 0;\n translate: 0 var(--kui-distance, 24px);\n }\n to {\n opacity: 1;\n translate: 0 0;\n }\n }\n @keyframes kui-toast-slide-out {\n from {\n opacity: 1;\n translate: 0 0;\n }\n to {\n opacity: 0;\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-shake-error {\n 10%, 90% {\n translate: -1px 0;\n }\n 20%, 80% {\n translate: 2px 0;\n }\n 30%, 50%, 70% {\n translate: -4px 0;\n }\n 40%, 60% {\n translate: 4px 0;\n }\n }\n @keyframes kui-wobble {\n 0% {\n translate: 0 0;\n rotate: 0deg;\n }\n 15% {\n translate: -6px 0;\n rotate: -6deg;\n }\n 30% {\n translate: 4px 0;\n rotate: 4deg;\n }\n 45% {\n translate: -3px 0;\n rotate: -3deg;\n }\n 60% {\n translate: 2px 0;\n rotate: 2deg;\n }\n 75% {\n translate: -1px 0;\n rotate: -1deg;\n }\n 100% {\n translate: 0 0;\n rotate: 0deg;\n }\n }\n [data-kui-fx~=ripple] {\n border-radius: 50%;\n background: currentColor;\n transform-origin: center;\n }\n @keyframes kui-ripple {\n from {\n scale: 0.2;\n opacity: 0.6;\n }\n to {\n scale: var(--kui-ripple-scale, 4);\n opacity: 0;\n }\n }\n @keyframes kui-badge-pop {\n 0% {\n scale: 0.4;\n }\n 60% {\n scale: var(--kui-pop-scale, 1.18);\n }\n 100% {\n scale: 1;\n }\n }\n @keyframes kui-count-bump {\n 0%, 100% {\n scale: 1;\n }\n 50% {\n scale: var(--kui-pop-scale, 1.18);\n }\n }\n [data-kui-fx~=heart-burst] {\n color: var(--kui-heart-color, #f43f5e);\n }\n @keyframes kui-heart-burst {\n 0% {\n scale: 1;\n }\n 30% {\n scale: var(--kui-pop-scale, 1.18);\n }\n 55% {\n scale: 0.9;\n }\n 100% {\n scale: 1;\n }\n }\n [data-kui-fx~=confetti-burst] {\n background-image:\n radial-gradient(\n circle at 20% 20%,\n var(--kui-c1, #f43f5e) 0 3px,\n transparent 3px),\n radial-gradient(\n circle at 75% 15%,\n var(--kui-c2, #fbbf24) 0 3px,\n transparent 3px),\n radial-gradient(\n circle at 50% 75%,\n var(--kui-c3, #34d399) 0 3px,\n transparent 3px),\n radial-gradient(\n circle at 85% 65%,\n var(--kui-c4, #60a5fa) 0 3px,\n transparent 3px),\n radial-gradient(\n circle at 15% 65%,\n var(--kui-c5, #c084fc) 0 3px,\n transparent 3px);\n background-repeat: no-repeat;\n }\n @keyframes kui-confetti-burst {\n 0% {\n scale: 0.6;\n opacity: 0;\n }\n 40% {\n scale: var(--kui-pop-scale, 1.18);\n opacity: 1;\n }\n 100% {\n scale: 1;\n opacity: 1;\n }\n }\n @keyframes kui-copy-confirm {\n 0% {\n opacity: 0;\n }\n 15% {\n opacity: 1;\n }\n 85% {\n opacity: 1;\n }\n 100% {\n opacity: 0;\n }\n }\n @keyframes kui-pull-to-refresh {\n 0% {\n translate: 0 0;\n }\n 45% {\n translate: 0 var(--kui-pull-distance, 36px);\n }\n 100% {\n translate: 0 0;\n }\n }\n}\n\n/* src/css/numbers.css */\n@layer kui.effects {\n @keyframes kui-progress-ring {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-gauge-sweep {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-donut-sweep {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-sparkline-draw {\n from {\n stroke-dashoffset: var(--kui-path-length, 1000);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n [data-kui-fx~=progress-ring],\n [data-kui-fx~=gauge-sweep],\n [data-kui-fx~=donut-sweep],\n [data-kui-fx~=sparkline-draw] {\n stroke-dasharray: var(--kui-path-length, 100);\n fill: none;\n }\n @keyframes kui-progress-bar {\n from {\n scale: 0 1;\n }\n to {\n scale: 1 1;\n }\n }\n [data-kui-fx~=progress-bar] {\n transform-origin: left center;\n }\n @keyframes kui-progress-segments {\n from {\n opacity: 0.18;\n }\n to {\n opacity: 1;\n }\n }\n @keyframes kui-star-rating-fill {\n from {\n clip-path: inset(0 100% 0 0);\n }\n to {\n clip-path: inset(0 calc(100% - var(--kui-fill, 100%)) 0 0);\n }\n }\n .kui-count-decorative {\n display: inline-flex;\n align-items: baseline;\n }\n .kui-odometer-col {\n display: inline-block;\n overflow: hidden;\n height: 1em;\n line-height: 1;\n vertical-align: baseline;\n }\n .kui-odometer-strip {\n display: flex;\n flex-direction: column;\n translate: 0 calc(var(--kui-o, 0) * -1em);\n transition: translate 220ms ease-out;\n }\n .kui-odometer-strip > span {\n height: 1em;\n line-height: 1;\n }\n}\n\n/* src/css/interaction.css */\n@layer kui.effects {\n @property --kui-border-angle { syntax: \"<angle>\"; inherits: false; initial-value: 0deg; }\n @property --kui-border-pct { syntax: \"<percentage>\"; inherits: false; initial-value: 0%; }\n [data-kui-fx~=lift] {\n transition: translate var(--kui-lift-duration, 220ms) var(--kui-lift-ease, ease-out);\n }\n [data-kui-fx~=lift]:focus-visible {\n translate: 0 calc(var(--kui-lift-distance, 6px) * -1);\n }\n [data-kui-fx~=lift-shadow] {\n transition: translate var(--kui-lift-shadow-duration, 220ms) var(--kui-lift-shadow-ease, ease-out), box-shadow var(--kui-lift-shadow-duration, 220ms) var(--kui-lift-shadow-ease, ease-out);\n }\n [data-kui-fx~=lift-shadow]:focus-visible {\n translate: 0 calc(var(--kui-lift-distance, 6px) * -1);\n box-shadow: 0 14px 28px -12px rgb(0 0 0 / 0.45);\n }\n [data-kui-fx~=shine-sweep] {\n position: relative;\n overflow: hidden;\n }\n [data-kui-fx~=shine-sweep]::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background:\n linear-gradient(\n 115deg,\n transparent 40%,\n var(--kui-c1, rgb(255 255 255 / 0.35)) 50%,\n transparent 60%);\n background-size: 220% 100%;\n background-position: 120% 0;\n pointer-events: none;\n }\n [data-kui-fx~=shine-sweep]:focus-visible::after {\n animation: kui-shine-sweep var(--kui-shine-sweep-duration, 700ms) var(--kui-shine-sweep-ease, ease-out);\n }\n @keyframes kui-shine-sweep {\n from {\n background-position: 120% 0;\n }\n to {\n background-position: -20% 0;\n }\n }\n [data-kui-fx~=split-flap] {\n display: inline-block;\n perspective: 600px;\n backface-visibility: hidden;\n }\n [data-kui-fx~=split-flap]:focus-visible {\n animation: kui-split-flap var(--kui-split-flap-duration, 600ms) var(--kui-split-flap-ease, ease-in-out);\n }\n @keyframes kui-split-flap {\n from {\n rotate: x 0deg;\n }\n to {\n rotate: x 360deg;\n }\n }\n [data-kui-fx~=border-draw] {\n border: 2px solid transparent;\n border-image-slice: 1;\n border-image-source:\n conic-gradient(\n from -90deg,\n var(--kui-border-draw-color, var(--accent, #d2691e)) 0 var(--kui-border-pct, 0%),\n transparent 0);\n transition: --kui-border-pct var(--kui-border-draw-duration, 500ms) var(--kui-border-draw-ease, ease-out);\n }\n [data-kui-fx~=border-draw]:focus-visible {\n --kui-border-pct: 100%;\n }\n [data-kui-fx~=border-glow] {\n transition: box-shadow var(--kui-border-glow-duration, 260ms) var(--kui-border-glow-ease, ease-out);\n }\n [data-kui-fx~=border-glow]:focus-visible {\n box-shadow: 0 0 0 3px var(--kui-border-glow-color, var(--accent, #d2691e));\n }\n [data-kui-fx~=beam-border],\n [data-kui-fx~=beam-border-auto] {\n position: relative;\n }\n [data-kui-fx~=beam-border]::before,\n [data-kui-fx~=beam-border-auto]::before {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: inherit;\n padding: var(--kui-beam-border-width, 3px);\n background:\n conic-gradient(\n from var(--kui-border-angle, 0deg),\n transparent 0deg,\n transparent 260deg,\n var(--kui-beam-border-c1, #ff5f6d) 282deg,\n var(--kui-beam-border-c2, #ffc371) 306deg,\n var(--kui-beam-border-c3, #4facfe) 330deg,\n var(--kui-beam-border-c4, #a855f7) 354deg,\n transparent 360deg);\n -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask-composite: exclude;\n opacity: 0;\n pointer-events: none;\n transition: opacity var(--kui-beam-border-fade-duration, 200ms) ease-out;\n }\n [data-kui-fx~=beam-border]:focus-visible::before {\n opacity: 1;\n animation: kui-beam-rotate var(--kui-beam-border-duration, 4260ms) linear infinite;\n }\n [data-kui-fx~=beam-border-auto]::before {\n opacity: 1;\n animation: kui-beam-rotate var(--kui-beam-border-duration, 4260ms) linear infinite;\n }\n @keyframes kui-beam-rotate {\n to {\n --kui-border-angle: 360deg;\n }\n }\n @media (prefers-reduced-motion: reduce) {\n [data-kui-fx~=beam-border]:focus-visible::before,\n [data-kui-fx~=beam-border-auto]::before {\n animation: none;\n --kui-border-angle: 45deg;\n }\n }\n [data-kui-fx~=underline-slide] {\n position: relative;\n text-decoration: none;\n }\n [data-kui-fx~=underline-slide]::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: -0.15em;\n height: 0.08em;\n background: currentcolor;\n scale: 0 1;\n transform-origin: left center;\n transition: scale var(--kui-underline-slide-duration, 260ms) var(--kui-underline-slide-ease, ease-out);\n }\n [data-kui-fx~=underline-slide]:focus-visible::after {\n scale: 1 1;\n }\n [data-kui-fx~=underline-center] {\n position: relative;\n text-decoration: none;\n }\n [data-kui-fx~=underline-center]::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: -0.15em;\n height: 0.08em;\n background: currentcolor;\n scale: 0 1;\n transform-origin: center;\n transition: scale var(--kui-underline-center-duration, 260ms) var(--kui-underline-center-ease, ease-out);\n }\n [data-kui-fx~=underline-center]:focus-visible::after {\n scale: 1 1;\n }\n [data-kui-fx~=icon-wiggle]:focus-visible {\n animation: kui-icon-wiggle var(--kui-icon-wiggle-duration, 500ms) var(--kui-icon-wiggle-ease, ease-in-out);\n }\n @keyframes kui-icon-wiggle {\n 0%, 100% {\n rotate: 0deg;\n }\n 20% {\n rotate: -12deg;\n }\n 40% {\n rotate: 10deg;\n }\n 60% {\n rotate: -6deg;\n }\n 80% {\n rotate: 4deg;\n }\n }\n [data-kui-fx~=icon-spin]:focus-visible {\n animation: kui-icon-spin var(--kui-icon-spin-duration, 700ms) linear;\n }\n @keyframes kui-icon-spin {\n from {\n rotate: 0deg;\n }\n to {\n rotate: 360deg;\n }\n }\n [data-kui-fx~=icon-bounce]:focus-visible {\n animation: kui-icon-bounce var(--kui-icon-bounce-duration, 500ms) var(--kui-icon-bounce-ease, ease-out);\n }\n @keyframes kui-icon-bounce {\n 0%, 100% {\n translate: 0 0;\n }\n 30% {\n translate: 0 -7px;\n }\n 55% {\n translate: 0 1px;\n }\n 75% {\n translate: 0 -3px;\n }\n }\n @media (hover: hover) and (pointer: fine) {\n [data-kui-fx~=lift]:hover {\n translate: 0 calc(var(--kui-lift-distance, 6px) * -1);\n }\n [data-kui-fx~=lift-shadow]:hover {\n translate: 0 calc(var(--kui-lift-distance, 6px) * -1);\n box-shadow: 0 14px 28px -12px rgb(0 0 0 / 0.45);\n }\n [data-kui-fx~=shine-sweep]:hover::after {\n animation: kui-shine-sweep var(--kui-shine-sweep-duration, 700ms) var(--kui-shine-sweep-ease, ease-out);\n }\n [data-kui-fx~=split-flap]:hover {\n animation: kui-split-flap var(--kui-split-flap-duration, 600ms) var(--kui-split-flap-ease, ease-in-out);\n }\n [data-kui-fx~=border-draw]:hover {\n --kui-border-pct: 100%;\n }\n [data-kui-fx~=border-glow]:hover {\n box-shadow: 0 0 0 3px var(--kui-border-glow-color, var(--accent, #d2691e));\n }\n [data-kui-fx~=beam-border]:hover::before {\n opacity: 1;\n animation: kui-beam-rotate var(--kui-beam-border-duration, 4260ms) linear infinite;\n }\n [data-kui-fx~=underline-slide]:hover::after {\n scale: 1 1;\n }\n [data-kui-fx~=underline-center]:hover::after {\n scale: 1 1;\n }\n [data-kui-fx~=icon-wiggle]:hover {\n animation: kui-icon-wiggle var(--kui-icon-wiggle-duration, 500ms) var(--kui-icon-wiggle-ease, ease-in-out);\n }\n [data-kui-fx~=icon-spin]:hover {\n animation: kui-icon-spin var(--kui-icon-spin-duration, 700ms) linear;\n }\n [data-kui-fx~=icon-bounce]:hover {\n animation: kui-icon-bounce var(--kui-icon-bounce-duration, 500ms) var(--kui-icon-bounce-ease, ease-out);\n }\n }\n [data-kui-fx~=tilt-3d],\n [data-kui-fx~=tilt-parallax] {\n transform-style: preserve-3d;\n }\n [data-kui-fx~=cursor-spotlight]::before {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n opacity: var(--kui-spotlight-opacity, 0);\n transition: opacity 200ms ease-out;\n background:\n radial-gradient(\n circle 160px at var(--kui-x, 50%) var(--kui-y, 50%),\n color-mix(in srgb, var(--accent, #d2691e) 30%, transparent),\n transparent 70%);\n }\n .kui-cursor-dot {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 9999;\n display: grid;\n place-items: center;\n pointer-events: none;\n opacity: 0;\n transition: opacity 160ms ease-out;\n }\n .kui-cursor-dot-active {\n opacity: 1;\n }\n .kui-cursor-dot-follow,\n .kui-cursor-dot-lag,\n .kui-cursor-dot-invert {\n width: 14px;\n height: 14px;\n margin: -7px 0 0 -7px;\n border-radius: 50%;\n background: var(--accent, #d2691e);\n }\n .kui-cursor-dot-invert {\n background: var(--kui-invert-color, #fff);\n mix-blend-mode: difference;\n }\n .kui-cursor-dot-label {\n margin: -1.4em 0 0 -1.4em;\n padding: 0.4em 0.8em;\n border-radius: 999px;\n background: var(--accent, #d2691e);\n color: var(--kui-label-color, #fff);\n font-size: 0.75rem;\n font-family:\n ui-monospace,\n Menlo,\n monospace;\n white-space: nowrap;\n }\n @media (pointer: coarse) {\n .kui-cursor-dot {\n display: none;\n }\n }\n}\n\n/* src/css/index.css */\n"
|
|
6410
|
+
style.textContent = "/* src/css/base.css */\n@layer kui.tokens, kui.presets, kui.effects, kui.policy, kui.cloak;\n@layer kui.tokens {\n :root {\n --kui-ease-expo-in: cubic-bezier(0.7, 0, 0.84, 0);\n --kui-ease-expo-out: cubic-bezier(0.16, 1, 0.3, 1);\n --kui-ease-expo-in-out: cubic-bezier(0.87, 0, 0.13, 1);\n --kui-ease-back-in: cubic-bezier(0.36, 0, 0.66, -0.56);\n --kui-ease-back-out: cubic-bezier(0.34, 1.56, 0.64, 1);\n --kui-ease-back-in-out: cubic-bezier(0.68, -0.6, 0.32, 1.6);\n --kui-ease-quart-out: cubic-bezier(0.25, 1, 0.5, 1);\n --kui-ease-circ-out: cubic-bezier(0, 0.55, 0.45, 1);\n --kui-ease-spring: linear(0, 0.4 12%, 0.9 25%, 1.06 38%, 1.01 62%, 1);\n --kui-ease-bounce: linear(0, 0.5 10%, 1.2 30%, 0.9 50%, 1.08 68%, 0.97 82%, 1.02 92%, 1);\n }\n [data-kui-fx] {\n --kui-dir: 1;\n --kui-i: 0;\n }\n :dir(rtl) [data-kui-fx] {\n --kui-dir: -1;\n }\n}\n@layer kui.policy {\n html[data-kui-cloak] [data-kui][data-kui-reveal]:not([data-kui-state]) {\n opacity: 0 !important;\n }\n @media (prefers-reduced-motion: reduce) {\n [data-kui-rm],\n [data-kui-rm]::before,\n [data-kui-rm]::after,\n [data-kui-rm] .kui-odometer-strip,\n [data-kui-rm][data-kui-fx~=label-float] ~ label,\n [data-kui-rm][data-kui-fx~=input-underline-grow] ~ .kui-underline,\n [data-kui-rm][data-kui-fx~=toggle-morph] ~ .kui-track,\n [data-kui-rm][data-kui-fx~=toggle-morph] ~ .kui-track .kui-thumb,\n [data-kui-rm][data-kui-fx~=checkbox-draw] ~ svg path,\n [data-kui-rm][data-kui-fx~=radio-fill] ~ .kui-dot,\n [data-kui-rm][data-kui-fx~=strength-meter] ~ .kui-meter > *,\n [data-kui-rm][data-kui-fx~=hamburger-to-x] .kui-bar,\n [data-kui-rm][data-kui-fx~=play-to-pause] .kui-bar,\n [data-kui-rm][data-kui-fx~=plus-to-minus] .kui-bar,\n [data-kui-rm][data-kui-fx~=flip-card] > .kui-face-front,\n [data-kui-rm][data-kui-fx~=flip-card] > .kui-face-back {\n transition-duration: 1ms !important;\n transition-delay: 0ms !important;\n }\n [data-kui-rm=shorten],\n [data-kui-rm=shorten]::before,\n [data-kui-rm=shorten]::after {\n animation-duration: 1ms !important;\n animation-delay: 0ms !important;\n }\n [data-kui-rm=crossfade] {\n animation-name: kui-in !important;\n animation-duration: 200ms !important;\n }\n [data-kui-rm=disable] {\n animation: none !important;\n opacity: 1 !important;\n translate: none !important;\n scale: none !important;\n rotate: none !important;\n filter: none !important;\n }\n }\n @media print {\n [data-kui-fx],\n [data-kui-reveal] {\n animation: none !important;\n opacity: 1 !important;\n translate: none !important;\n scale: none !important;\n rotate: none !important;\n filter: none !important;\n }\n }\n}\n\n/* src/css/presets.generated.css */\n@layer kui.presets {\n [data-kui-fx~=accordion-height] {\n --kui-auto-height-duration: 400ms;\n --kui-auto-height-ease: ease-out;\n }\n [data-kui-fx~=aurora] {\n --kui-ambient-gradient-duration: 10s;\n --kui-ambient-gradient-delay: 0ms;\n --kui-ambient-gradient-ease: ease-in-out;\n }\n [data-kui-fx~=back-in-down] {\n --kui-distance: 120px;\n --kui-reveal-ease: var(--kui-ease-expo-out, ease-out);\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n }\n [data-kui-fx~=back-in-up] {\n --kui-distance: 120px;\n --kui-reveal-ease: var(--kui-ease-expo-out, ease-out);\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n }\n [data-kui-fx~=badge-pop] {\n --kui-feedback-pop-duration: 420ms;\n --kui-feedback-pop-delay: 0ms;\n --kui-feedback-pop-ease: var(--kui-ease-back-out, ease-out);\n }\n [data-kui-fx~=beam-border] {\n --kui-beam-border-duration: 220ms;\n --kui-beam-border-ease: ease-out;\n }\n [data-kui-fx~=beam-border-auto] {\n --kui-beam-border-auto-duration: 220ms;\n --kui-beam-border-auto-ease: ease-out;\n }\n [data-kui-fx~=before-after-wipe] {\n --kui-media-wipe-duration: 600ms;\n --kui-media-wipe-delay: 0ms;\n --kui-media-wipe-ease: ease-out;\n }\n [data-kui-fx~=blob-morph] {\n --kui-path-morph-duration: 800ms;\n }\n [data-kui-fx~=blur-in] {\n --kui-blur-duration: 600ms;\n --kui-blur-delay: 0ms;\n --kui-blur-ease: ease-out;\n }\n [data-kui-fx~=blur-out] {\n --kui-blur-duration: 600ms;\n --kui-blur-delay: 0ms;\n --kui-blur-ease: ease-out;\n }\n [data-kui-fx~=blur-up] {\n --kui-media-blur-up-duration: 600ms;\n --kui-media-blur-up-delay: 0ms;\n --kui-media-blur-up-ease: ease-out;\n }\n [data-kui-fx~=bob] {\n --kui-ambient-float-duration: 2s;\n --kui-distance: 8px;\n --kui-ambient-float-delay: 0ms;\n --kui-ambient-float-ease: ease-in-out;\n }\n [data-kui-fx~=book-page-turn] {\n --kui-from-angle: -160deg;\n --kui-flip-face-duration: 900ms;\n --kui-flip-face-delay: 0ms;\n --kui-flip-face-ease: ease-out;\n }\n [data-kui-fx~=bookmark-fill] {\n --kui-shape-fill-duration: 360ms;\n --kui-shape-fill-delay: 0ms;\n --kui-shape-fill-ease: ease-out;\n }\n [data-kui-fx~=border-draw] {\n --kui-border-draw-duration: 220ms;\n --kui-border-draw-ease: ease-out;\n }\n [data-kui-fx~=border-glow] {\n --kui-border-glow-duration: 220ms;\n --kui-border-glow-ease: ease-out;\n }\n [data-kui-fx~=bounce-in] {\n --kui-from-scale: 0.3;\n --kui-scale-ease: var(--kui-ease-bounce, ease-out);\n --kui-scale-duration: 600ms;\n --kui-scale-delay: 0ms;\n }\n [data-kui-fx~=bounce-in-down] {\n --kui-distance: 60px;\n --kui-reveal-ease: var(--kui-ease-back-out, ease-out);\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n }\n [data-kui-fx~=bounce-in-up] {\n --kui-distance: 60px;\n --kui-reveal-ease: var(--kui-ease-back-out, ease-out);\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n }\n [data-kui-fx~=card-flip-x] {\n --kui-flip-face-duration: 600ms;\n --kui-flip-face-delay: 0ms;\n --kui-flip-face-ease: ease-out;\n }\n [data-kui-fx~=card-flip-y] {\n --kui-flip-face-duration: 600ms;\n --kui-flip-face-delay: 0ms;\n --kui-flip-face-ease: ease-out;\n }\n [data-kui-fx~=chart-area-fill] {\n --kui-shape-fill-duration: 900ms;\n --kui-shape-fill-delay: 0ms;\n --kui-shape-fill-ease: ease-out;\n }\n [data-kui-fx~=chart-bar-grow] {\n --kui-bar-grow-duration: 700ms;\n --kui-bar-grow-ease: var(--kui-ease-back-out, ease-out);\n --kui-bar-grow-delay: 0ms;\n }\n [data-kui-fx~=chart-line-draw] {\n --kui-path-draw-duration: 1200ms;\n --kui-path-draw-ease: ease-in-out;\n --kui-path-draw-delay: 0ms;\n }\n [data-kui-fx~=checkmark-draw] {\n --kui-path-draw-duration: 320ms;\n --kui-path-draw-delay: 0ms;\n --kui-path-draw-ease: ease-out;\n }\n [data-kui-fx~=confetti-burst] {\n --kui-feedback-burst-duration: 900ms;\n --kui-pop-scale: 1.15;\n --kui-feedback-burst-delay: 0ms;\n --kui-feedback-burst-ease: var(--kui-ease-back-out, ease-out);\n }\n [data-kui-fx~=copy-confirm] {\n --kui-feedback-confirm-duration: 1400ms;\n --kui-feedback-confirm-delay: 0ms;\n --kui-feedback-confirm-ease: linear;\n }\n [data-kui-fx~=count-bump] {\n --kui-feedback-pop-duration: 280ms;\n --kui-pop-scale: 1.3;\n --kui-feedback-pop-delay: 0ms;\n --kui-feedback-pop-ease: var(--kui-ease-back-out, ease-out);\n }\n [data-kui-fx~=count-compact] {\n --kui-from: 0;\n --kui-to: 128400;\n --kui-format: compact;\n --kui-count-duration: 1600ms;\n }\n [data-kui-fx~=count-currency] {\n --kui-from: 0;\n --kui-to: 4820;\n --kui-format: currency;\n --kui-decimals: 0;\n --kui-count-duration: 1600ms;\n }\n [data-kui-fx~=count-down] {\n --kui-from: 100;\n --kui-to: 0;\n --kui-count-duration: 1600ms;\n }\n [data-kui-fx~=count-percent] {\n --kui-from: 0;\n --kui-to: 0.82;\n --kui-format: percent;\n --kui-decimals: 0;\n --kui-count-duration: 1600ms;\n }\n [data-kui-fx~=count-up] {\n --kui-from: 0;\n --kui-to: 100;\n --kui-count-duration: 1600ms;\n }\n [data-kui-fx~=cross-draw] {\n --kui-path-draw-duration: 260ms;\n --kui-path-draw-delay: 0ms;\n --kui-path-draw-ease: ease-out;\n }\n [data-kui-fx~=cube-rotate] {\n --kui-from-angle: 90deg;\n --kui-flip-face-duration: 600ms;\n --kui-flip-face-delay: 0ms;\n --kui-flip-face-ease: ease-out;\n }\n [data-kui-fx~=cursor-follow] {\n --kui-stiffness: 300;\n --kui-damping: 30;\n }\n [data-kui-fx~=cursor-invert] {\n --kui-stiffness: 260;\n --kui-damping: 26;\n }\n [data-kui-fx~=cursor-label] {\n --kui-stiffness: 260;\n --kui-damping: 26;\n }\n [data-kui-fx~=cursor-lag] {\n --kui-stiffness: 80;\n --kui-damping: 14;\n }\n [data-kui-fx~=curtain-reveal] {\n --kui-media-wipe-duration: 600ms;\n --kui-media-wipe-delay: 0ms;\n --kui-media-wipe-ease: ease-out;\n }\n [data-kui-fx~=curtain-wipe] {\n --kui-wipe-duration: 800ms;\n --kui-wipe-delay: 0ms;\n --kui-wipe-ease: ease-out;\n }\n [data-kui-fx~=decode] {\n --kui-charset: binary;\n }\n [data-kui-fx~=depth-layer] {\n --kui-distance: 200px;\n --kui-parallax-duration: 600ms;\n --kui-parallax-delay: 0ms;\n --kui-parallax-ease: ease-out;\n }\n [data-kui-fx~=donut-sweep] {\n --kui-stroke-sweep-duration: 600ms;\n --kui-stroke-sweep-delay: 0ms;\n --kui-stroke-sweep-ease: ease-out;\n }\n [data-kui-fx~=dot-grid-drift] {\n --kui-ambient-gradient-duration: 16s;\n --kui-ambient-gradient-ease: linear;\n --kui-ambient-gradient-delay: 0ms;\n }\n [data-kui-fx~=drag-inertia] {\n --kui-inertia: true;\n }\n [data-kui-fx~=drag-x] {\n --kui-axis: x;\n }\n [data-kui-fx~=drag-y] {\n --kui-axis: y;\n }\n [data-kui-fx~=draw-signature] {\n --kui-path-draw-duration: 1600ms;\n --kui-path-draw-ease: ease-in-out;\n --kui-path-draw-delay: 0ms;\n }\n [data-kui-fx~=draw-stroke] {\n --kui-path-draw-duration: 800ms;\n --kui-path-draw-ease: ease-in-out;\n --kui-path-draw-delay: 0ms;\n }\n [data-kui-fx~=draw-underline] {\n --kui-path-draw-duration: 420ms;\n --kui-path-draw-delay: 0ms;\n --kui-path-draw-ease: ease-out;\n }\n [data-kui-fx~=drawer-slide] {\n --kui-drawer-slide-duration: 600ms;\n --kui-drawer-slide-delay: 0ms;\n --kui-drawer-slide-ease: ease-out;\n }\n [data-kui-fx~=dropdown-open] {\n --kui-panel-reveal-duration: 600ms;\n --kui-panel-reveal-delay: 0ms;\n --kui-panel-reveal-ease: ease-out;\n }\n [data-kui-fx~=duotone-hover] {\n --kui-media-filter-duration: 600ms;\n --kui-media-filter-delay: 0ms;\n --kui-media-filter-ease: ease-out;\n }\n [data-kui-fx~=elastic-pull] {\n --kui-return: true;\n --kui-bounds: 80;\n }\n [data-kui-fx~=expand-to-modal] {\n --kui-flip-scale: true;\n --kui-flip-container-duration: 500ms;\n --kui-flip-container-ease: ease-out;\n }\n [data-kui-fx~=fade-blur-in] {\n --kui-reveal-blur-duration: 600ms;\n --kui-reveal-blur-delay: 0ms;\n --kui-reveal-blur-ease: ease-out;\n }\n [data-kui-fx~=fade-blur-up] {\n --kui-reveal-blur-duration: 600ms;\n --kui-reveal-blur-delay: 0ms;\n --kui-reveal-blur-ease: ease-out;\n }\n [data-kui-fx~=fade-down] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=fade-in] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=fade-left] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=fade-out] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=fade-out-down] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=fade-out-left] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=fade-out-right] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=fade-out-up] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=fade-right] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=fade-up] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=flip-card] {\n --kui-card-toggle-duration: 700ms;\n --kui-card-toggle-ease: ease-in-out;\n }\n [data-kui-fx~=flip-filter] {\n --kui-flip-container-duration: 400ms;\n --kui-flip-container-ease: ease-out;\n }\n [data-kui-fx~=flip-in-x] {\n --kui-flip-3d-duration: 600ms;\n --kui-flip-3d-delay: 0ms;\n --kui-flip-3d-ease: ease-out;\n }\n [data-kui-fx~=flip-in-y] {\n --kui-flip-3d-duration: 600ms;\n --kui-flip-3d-delay: 0ms;\n --kui-flip-3d-ease: ease-out;\n }\n [data-kui-fx~=flip-out-x] {\n --kui-flip-3d-duration: 600ms;\n --kui-flip-3d-delay: 0ms;\n --kui-flip-3d-ease: ease-out;\n }\n [data-kui-fx~=flip-out-y] {\n --kui-flip-3d-duration: 600ms;\n --kui-flip-3d-delay: 0ms;\n --kui-flip-3d-ease: ease-out;\n }\n [data-kui-fx~=flip-reorder] {\n --kui-flip-container-duration: 400ms;\n --kui-flip-container-ease: ease-out;\n }\n [data-kui-fx~=flip-shuffle] {\n --kui-flip-container-duration: 400ms;\n --kui-flip-container-ease: ease-out;\n }\n [data-kui-fx~=flip-sort] {\n --kui-flip-container-duration: 400ms;\n --kui-flip-container-ease: ease-out;\n }\n [data-kui-fx~=float] {\n --kui-ambient-float-duration: 4s;\n --kui-ambient-float-delay: 0ms;\n --kui-ambient-float-ease: ease-in-out;\n }\n [data-kui-fx~=floating-shapes] {\n --kui-ambient-float-duration: 6s;\n --kui-distance: 10px;\n --kui-ambient-float-delay: 0ms;\n --kui-ambient-float-ease: ease-in-out;\n }\n [data-kui-fx~=focus-ring-grow] {\n --kui-focus-ring-duration: 600ms;\n --kui-focus-ring-delay: 0ms;\n --kui-focus-ring-ease: ease-out;\n }\n [data-kui-fx~=fold-panel] {\n --kui-from-angle: -90deg;\n --kui-flip-face-duration: 600ms;\n --kui-flip-face-delay: 0ms;\n --kui-flip-face-ease: ease-out;\n }\n [data-kui-fx~=gauge-sweep] {\n --kui-stroke-sweep-duration: 600ms;\n --kui-stroke-sweep-delay: 0ms;\n --kui-stroke-sweep-ease: ease-out;\n }\n [data-kui-fx~=glitch] {\n --kui-charset: symbols;\n }\n [data-kui-fx~=glow-pulse] {\n --kui-ambient-pulse-duration: 2.2s;\n --kui-ambient-pulse-delay: 0ms;\n --kui-ambient-pulse-ease: ease-in-out;\n }\n [data-kui-fx~=gradient-mesh] {\n --kui-ambient-gradient-duration: 10s;\n --kui-ambient-gradient-delay: 0ms;\n --kui-ambient-gradient-ease: ease-in-out;\n }\n [data-kui-fx~=gradient-rotate-border] {\n --kui-ambient-gradient-duration: 6s;\n --kui-ambient-gradient-ease: linear;\n --kui-ambient-gradient-delay: 0ms;\n }\n [data-kui-fx~=gradient-shimmer] {\n --kui-text-shimmer-duration: 600ms;\n --kui-text-shimmer-delay: 0ms;\n --kui-text-shimmer-ease: ease-out;\n }\n [data-kui-fx~=gradient-stroke] {\n --kui-path-draw-duration: 2400ms;\n --kui-path-draw-ease: ease-in-out;\n --kui-path-draw-delay: 0ms;\n }\n [data-kui-fx~=gradient-sweep] {\n --kui-text-gradient-sweep-duration: 600ms;\n --kui-text-gradient-sweep-delay: 0ms;\n --kui-text-gradient-sweep-ease: ease-out;\n }\n [data-kui-fx~=grayscale-hover] {\n --kui-media-filter-duration: 600ms;\n --kui-media-filter-delay: 0ms;\n --kui-media-filter-ease: ease-out;\n }\n [data-kui-fx~=grid-to-list] {\n --kui-flip-scale: true;\n --kui-flip-container-duration: 400ms;\n --kui-flip-container-ease: ease-out;\n }\n [data-kui-fx~=hamburger-to-x] {\n --kui-icon-toggle-duration: 260ms;\n --kui-icon-toggle-ease: ease-out;\n }\n [data-kui-fx~=heart-burst] {\n --kui-feedback-burst-duration: 700ms;\n --kui-pop-scale: 1.4;\n --kui-feedback-burst-delay: 0ms;\n --kui-feedback-burst-ease: var(--kui-ease-back-out, ease-out);\n }\n [data-kui-fx~=heart-fill] {\n --kui-shape-fill-duration: 420ms;\n --kui-shape-fill-delay: 0ms;\n --kui-shape-fill-ease: ease-out;\n }\n [data-kui-fx~=highlight-sweep] {\n --kui-sweep-color: gold;\n --kui-text-sweep-duration: 600ms;\n --kui-text-sweep-delay: 0ms;\n --kui-text-sweep-ease: ease-out;\n }\n [data-kui-fx~=icon-bounce] {\n --kui-icon-bounce-duration: 220ms;\n --kui-icon-bounce-ease: ease-out;\n }\n [data-kui-fx~=icon-morph] {\n --kui-path-morph-duration: 300ms;\n }\n [data-kui-fx~=icon-spin] {\n --kui-icon-spin-duration: 220ms;\n --kui-icon-spin-ease: ease-out;\n }\n [data-kui-fx~=icon-wiggle] {\n --kui-icon-wiggle-duration: 220ms;\n --kui-icon-wiggle-ease: ease-out;\n }\n [data-kui-fx~=image-parallax-frame] {\n --kui-media-parallax-frame-duration: 600ms;\n --kui-media-parallax-frame-delay: 0ms;\n --kui-media-parallax-frame-ease: ease-out;\n }\n [data-kui-fx~=ken-burns] {\n --kui-media-ken-burns-duration: 600ms;\n --kui-media-ken-burns-delay: 0ms;\n --kui-media-ken-burns-ease: ease-out;\n }\n [data-kui-fx~=ken-burns-out] {\n --kui-media-ken-burns-duration: 600ms;\n --kui-media-ken-burns-delay: 0ms;\n --kui-media-ken-burns-ease: ease-out;\n }\n [data-kui-fx~=lift] {\n --kui-lift-duration: 220ms;\n --kui-lift-ease: ease-out;\n }\n [data-kui-fx~=lift-shadow] {\n --kui-lift-shadow-duration: 220ms;\n --kui-lift-shadow-ease: ease-out;\n }\n [data-kui-fx~=lightbox-open] {\n --kui-media-lightbox-duration: 600ms;\n --kui-media-lightbox-delay: 0ms;\n --kui-media-lightbox-ease: ease-out;\n }\n [data-kui-fx~=line-grid-drift] {\n --kui-ambient-gradient-duration: 16s;\n --kui-ambient-gradient-ease: linear;\n --kui-ambient-gradient-delay: 0ms;\n }\n [data-kui-fx~=loading-bar] {\n --kui-bar-duration: 600ms;\n --kui-bar-delay: 0ms;\n --kui-bar-ease: ease-out;\n }\n [data-kui-fx~=logo-build] {\n --kui-logo-assemble-duration: 520ms;\n --kui-logo-assemble-ease: var(--kui-ease-back-out, ease-out);\n --kui-logo-assemble-delay: 0ms;\n }\n [data-kui-fx~=long-press] {\n --kui-pressable-duration: 500ms;\n }\n [data-kui-fx~=magnetic-snap] {\n --kui-strength: 0.6;\n --kui-radius: 160;\n }\n [data-kui-fx~=marquee] {\n --kui-text-marquee-duration: 600ms;\n --kui-text-marquee-delay: 0ms;\n --kui-text-marquee-ease: ease-out;\n }\n [data-kui-fx~=marquee-scroll-linked] {\n --kui-text-marquee-duration: 600ms;\n --kui-text-marquee-delay: 0ms;\n --kui-text-marquee-ease: ease-out;\n }\n [data-kui-fx~=mask-reveal] {\n --kui-media-mask-duration: 600ms;\n --kui-media-mask-delay: 0ms;\n --kui-media-mask-ease: ease-out;\n }\n [data-kui-fx~=masonry-reflow] {\n --kui-flip-container-duration: 400ms;\n --kui-flip-container-ease: ease-out;\n }\n [data-kui-fx~=mega-menu-drop] {\n --kui-panel-reveal-duration: 550ms;\n --kui-panel-reveal-delay: 0ms;\n --kui-panel-reveal-ease: ease-out;\n }\n [data-kui-fx~=menu-fullscreen] {\n --kui-menu-fullscreen-duration: 600ms;\n --kui-menu-fullscreen-delay: 0ms;\n --kui-menu-fullscreen-ease: ease-out;\n }\n [data-kui-fx~=menu-stagger-open] {\n --kui-nav-reveal-duration: 600ms;\n --kui-nav-reveal-delay: 0ms;\n --kui-nav-reveal-ease: ease-out;\n }\n [data-kui-fx~=noise-overlay] {\n --kui-ambient-gradient-duration: 650ms;\n --kui-ambient-gradient-ease: steps(6);\n --kui-ambient-gradient-delay: 0ms;\n }\n [data-kui-fx~=odometer-roll] {\n --kui-from: 0;\n --kui-to: 4820;\n --kui-count-odometer-duration: 1600ms;\n }\n [data-kui-fx~=orbit] {\n --kui-ambient-orbit-duration: 3.5s;\n --kui-ambient-orbit-delay: 0ms;\n --kui-ambient-orbit-ease: linear;\n }\n [data-kui-fx~=page-fade] {\n --kui-page-reveal-duration: 600ms;\n --kui-page-reveal-delay: 0ms;\n --kui-page-reveal-ease: ease-out;\n }\n [data-kui-fx~=page-slide] {\n --kui-page-reveal-duration: 600ms;\n --kui-page-reveal-delay: 0ms;\n --kui-page-reveal-ease: ease-out;\n }\n [data-kui-fx~=parallax-rotate] {\n --kui-parallax-rotate-duration: 600ms;\n --kui-parallax-rotate-delay: 0ms;\n --kui-parallax-rotate-ease: ease-out;\n }\n [data-kui-fx~=parallax-scale] {\n --kui-parallax-scale-duration: 600ms;\n --kui-parallax-scale-delay: 0ms;\n --kui-parallax-scale-ease: ease-out;\n }\n [data-kui-fx~=parallax-x] {\n --kui-parallax-duration: 600ms;\n --kui-parallax-delay: 0ms;\n --kui-parallax-ease: ease-out;\n }\n [data-kui-fx~=parallax-y] {\n --kui-parallax-duration: 600ms;\n --kui-parallax-delay: 0ms;\n --kui-parallax-ease: ease-out;\n }\n [data-kui-fx~=pin-section] {\n --kui-distance: 100vh;\n --kui-spacer: true;\n }\n [data-kui-fx~=pin-spacer] {\n --kui-spacer: true;\n }\n [data-kui-fx~=pin-until] {\n --kui-spacer: false;\n }\n [data-kui-fx~=play-to-pause] {\n --kui-icon-toggle-duration: 260ms;\n --kui-icon-toggle-ease: ease-out;\n }\n [data-kui-fx~=plus-to-minus] {\n --kui-icon-toggle-duration: 260ms;\n --kui-icon-toggle-ease: ease-out;\n }\n [data-kui-fx~=pop] {\n --kui-pop-duration: 220ms;\n --kui-pop-ease: ease-out;\n }\n [data-kui-fx~=pop-in] {\n --kui-from-scale: 0.6;\n --kui-scale-ease: var(--kui-ease-back-out, ease-out);\n --kui-scale-duration: 600ms;\n --kui-scale-delay: 0ms;\n }\n [data-kui-fx~=pop-out] {\n --kui-from-scale: 0.6;\n --kui-scale-ease: var(--kui-ease-back-in, ease-out);\n --kui-scale-duration: 600ms;\n --kui-scale-delay: 0ms;\n }\n [data-kui-fx~=progress-bar] {\n --kui-meter-bar-duration: 600ms;\n --kui-meter-bar-delay: 0ms;\n --kui-meter-bar-ease: ease-out;\n }\n [data-kui-fx~=progress-indeterminate] {\n --kui-feedback-progress-track-duration: 1.4s;\n --kui-feedback-progress-track-delay: 0ms;\n --kui-feedback-progress-track-ease: ease-in-out;\n }\n [data-kui-fx~=progress-ring] {\n --kui-stroke-sweep-duration: 600ms;\n --kui-stroke-sweep-delay: 0ms;\n --kui-stroke-sweep-ease: ease-out;\n }\n [data-kui-fx~=progress-segments] {\n --kui-meter-segments-duration: 600ms;\n --kui-meter-segments-delay: 0ms;\n --kui-meter-segments-ease: ease-out;\n }\n [data-kui-fx~=pull-to-refresh] {\n --kui-feedback-pull-duration: 900ms;\n --kui-feedback-pull-ease: ease-out;\n --kui-feedback-pull-delay: 0ms;\n }\n [data-kui-fx~=range-fill] {\n --kui-range-fill-duration: 400ms;\n --kui-range-fill-delay: 0ms;\n --kui-range-fill-ease: ease-out;\n }\n [data-kui-fx~=redaction-reveal] {\n --kui-redaction-reveal-duration: 600ms;\n --kui-redaction-reveal-delay: 0ms;\n --kui-redaction-reveal-ease: ease-out;\n }\n [data-kui-fx~=reveal-once] {\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=ripple] {\n --kui-feedback-ripple-duration: 600ms;\n --kui-feedback-ripple-delay: 0ms;\n --kui-feedback-ripple-ease: ease-out;\n }\n [data-kui-fx~=roll-in] {\n --kui-roll-duration: 600ms;\n --kui-roll-delay: 0ms;\n --kui-roll-ease: ease-out;\n }\n [data-kui-fx~=roll-out] {\n --kui-roll-duration: 600ms;\n --kui-roll-delay: 0ms;\n --kui-roll-ease: ease-out;\n }\n [data-kui-fx~=rotate-in] {\n --kui-rotate-duration: 600ms;\n --kui-rotate-delay: 0ms;\n --kui-rotate-ease: ease-out;\n }\n [data-kui-fx~=rotate-in-left] {\n --kui-from-angle: -45deg;\n --kui-rotate-duration: 600ms;\n --kui-rotate-delay: 0ms;\n --kui-rotate-ease: ease-out;\n }\n [data-kui-fx~=rotate-in-right] {\n --kui-from-angle: 45deg;\n --kui-rotate-duration: 600ms;\n --kui-rotate-delay: 0ms;\n --kui-rotate-ease: ease-out;\n }\n [data-kui-fx~=rotate-out] {\n --kui-rotate-duration: 600ms;\n --kui-rotate-delay: 0ms;\n --kui-rotate-ease: ease-out;\n }\n [data-kui-fx~=rubber-band] {\n --kui-return: true;\n --kui-bounds: 120;\n }\n [data-kui-fx~=saturate-hover] {\n --kui-media-filter-duration: 600ms;\n --kui-media-filter-delay: 0ms;\n --kui-media-filter-ease: ease-out;\n }\n [data-kui-fx~=scanline] {\n --kui-ambient-gradient-duration: 3.5s;\n --kui-ambient-gradient-ease: linear;\n --kui-ambient-gradient-delay: 0ms;\n }\n [data-kui-fx~=scramble] {\n --kui-charset: upper;\n }\n [data-kui-fx~=scroll-desaturate] {\n --kui-desaturate-duration: 600ms;\n --kui-desaturate-delay: 0ms;\n --kui-desaturate-ease: ease-out;\n }\n [data-kui-fx~=scroll-fade] {\n --kui-scroll-fade-duration: 600ms;\n --kui-scroll-fade-delay: 0ms;\n --kui-scroll-fade-ease: ease-out;\n }\n [data-kui-fx~=scroll-progress-bar] {\n --kui-progress-duration: 600ms;\n --kui-progress-delay: 0ms;\n --kui-progress-ease: ease-out;\n }\n [data-kui-fx~=scroll-progress-bar-y] {\n --kui-progress-duration: 600ms;\n --kui-progress-delay: 0ms;\n --kui-progress-ease: ease-out;\n }\n [data-kui-fx~=scroll-progress-ring] {\n --kui-progress-stroke-duration: 600ms;\n --kui-progress-stroke-delay: 0ms;\n --kui-progress-stroke-ease: ease-out;\n }\n [data-kui-fx~=scroll-skew] {\n --kui-skew-duration: 600ms;\n --kui-skew-delay: 0ms;\n --kui-skew-ease: ease-out;\n }\n [data-kui-fx~=scroll-snap-x] {\n --kui-axis: x;\n }\n [data-kui-fx~=scroll-snap-y] {\n --kui-axis: y;\n }\n [data-kui-fx~=scrollytelling-step] {\n --kui-steps: 4;\n }\n [data-kui-fx~=sequence-scrub] {\n --kui-spacer: true;\n }\n [data-kui-fx~=shake-error] {\n --kui-feedback-shake-duration: 500ms;\n --kui-feedback-shake-delay: 0ms;\n --kui-feedback-shake-ease: linear;\n }\n [data-kui-fx~=shine-sweep] {\n --kui-shine-sweep-duration: 220ms;\n --kui-shine-sweep-ease: ease-out;\n }\n [data-kui-fx~=skeleton-shimmer] {\n --kui-feedback-shimmer-duration: 1.6s;\n --kui-feedback-shimmer-delay: 0ms;\n --kui-feedback-shimmer-ease: linear;\n }\n [data-kui-fx~=skeleton-to-content] {\n --kui-feedback-fade-duration: 600ms;\n --kui-feedback-fade-delay: 0ms;\n --kui-feedback-fade-ease: ease-out;\n }\n [data-kui-fx~=slat-assemble] {\n --kui-slat-assemble-duration: 500ms;\n --kui-slat-assemble-delay: 0ms;\n --kui-slat-assemble-ease: ease-out;\n }\n [data-kui-fx~=slide-block-end] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-block-start] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-down] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-inline-end] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-inline-start] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-left] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-out-down] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-out-left] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-out-right] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-out-up] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-right] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=slide-up] {\n --kui-distance: 100px;\n --kui-from-opacity: 1;\n --kui-reveal-duration: 600ms;\n --kui-reveal-delay: 0ms;\n --kui-reveal-ease: ease-out;\n }\n [data-kui-fx~=snap-back] {\n --kui-return: true;\n --kui-stiffness: 260;\n }\n [data-kui-fx~=sparkline-draw] {\n --kui-stroke-sweep-duration: 600ms;\n --kui-stroke-sweep-delay: 0ms;\n --kui-stroke-sweep-ease: ease-out;\n }\n [data-kui-fx~=spinner] {\n --kui-feedback-spin-duration: 900ms;\n --kui-feedback-spin-delay: 0ms;\n --kui-feedback-spin-ease: linear;\n }\n [data-kui-fx~=spinner-dots] {\n --kui-feedback-dot-pulse-duration: 1.2s;\n --kui-feedback-dot-pulse-delay: 0ms;\n --kui-feedback-dot-pulse-ease: ease-in-out;\n }\n [data-kui-fx~=spinner-ring] {\n --kui-feedback-spin-duration: 900ms;\n --kui-feedback-spin-delay: 0ms;\n --kui-feedback-spin-ease: linear;\n }\n [data-kui-fx~=split-chars] {\n --kui-unit: chars;\n --kui-direction: fade;\n --kui-split-text-duration: 500ms;\n --kui-split-text-delay: 0ms;\n --kui-split-text-ease: ease-out;\n }\n [data-kui-fx~=split-flap] {\n --kui-split-flap-duration: 220ms;\n --kui-split-flap-ease: ease-out;\n }\n [data-kui-fx~=split-lines] {\n --kui-unit: lines;\n --kui-direction: fade;\n --kui-split-text-duration: 500ms;\n --kui-split-text-delay: 0ms;\n --kui-split-text-ease: ease-out;\n }\n [data-kui-fx~=split-words] {\n --kui-unit: words;\n --kui-direction: fade;\n --kui-split-text-duration: 500ms;\n --kui-split-text-delay: 0ms;\n --kui-split-text-ease: ease-out;\n }\n [data-kui-fx~=spotlight-follow] {\n --kui-ambient-gradient-duration: 9s;\n --kui-ambient-gradient-delay: 0ms;\n --kui-ambient-gradient-ease: ease-in-out;\n }\n [data-kui-fx~=stacking-cards] {\n --kui-spacer: false;\n }\n [data-kui-fx~=star-rating-fill] {\n --kui-meter-stars-duration: 600ms;\n --kui-meter-stars-delay: 0ms;\n --kui-meter-stars-ease: ease-out;\n }\n [data-kui-fx~=starfield] {\n --kui-ambient-gradient-duration: 40s;\n --kui-ambient-gradient-ease: linear;\n --kui-ambient-gradient-delay: 0ms;\n }\n [data-kui-fx~=step-progress] {\n --kui-step-progress-duration: 400ms;\n --kui-step-progress-delay: 0ms;\n --kui-step-progress-ease: ease-out;\n }\n [data-kui-fx~=strength-meter] {\n --kui-strength-meter-duration: 400ms;\n --kui-strength-meter-delay: 0ms;\n --kui-strength-meter-ease: ease-out;\n }\n [data-kui-fx~=submit-to-spinner-to-check] {\n --kui-submit-flow-duration: 400ms;\n --kui-submit-flow-delay: 0ms;\n --kui-submit-flow-ease: ease-out;\n }\n [data-kui-fx~=swing-in] {\n --kui-from-angle: -15deg;\n --kui-rotate-ease: var(--kui-ease-back-out, ease-out);\n --kui-rotate-duration: 600ms;\n --kui-rotate-delay: 0ms;\n }\n [data-kui-fx~=swipe-x] {\n --kui-axis: x;\n }\n [data-kui-fx~=tab-indicator-slide] {\n --kui-flip-indicator-duration: 300ms;\n --kui-flip-indicator-ease: ease-out;\n }\n [data-kui-fx~=text-3d-extrude] {\n --kui-text-3d-extrude-duration: 600ms;\n --kui-text-3d-extrude-delay: 0ms;\n --kui-text-3d-extrude-ease: ease-out;\n }\n [data-kui-fx~=text-jitter] {\n --kui-motion: jitter;\n }\n [data-kui-fx~=text-outline-fill] {\n --kui-text-outline-fill-duration: 600ms;\n --kui-text-outline-fill-delay: 0ms;\n --kui-text-outline-fill-ease: ease-out;\n }\n [data-kui-fx~=text-reveal-down] {\n --kui-unit: words;\n --kui-direction: down;\n --kui-split-text-duration: 500ms;\n --kui-split-text-delay: 0ms;\n --kui-split-text-ease: ease-out;\n }\n [data-kui-fx~=text-reveal-mask] {\n --kui-unit: lines;\n --kui-direction: mask;\n --kui-split-text-duration: 500ms;\n --kui-split-text-delay: 0ms;\n --kui-split-text-ease: ease-out;\n }\n [data-kui-fx~=text-reveal-up] {\n --kui-unit: words;\n --kui-direction: up;\n --kui-split-text-duration: 500ms;\n --kui-split-text-delay: 0ms;\n --kui-split-text-ease: ease-out;\n }\n [data-kui-fx~=text-wave] {\n --kui-motion: wave;\n }\n [data-kui-fx~=throwable] {\n --kui-inertia: true;\n --kui-damping: 18;\n }\n [data-kui-fx~=toast-slide-in] {\n --kui-feedback-toast-duration: 420ms;\n --kui-feedback-toast-delay: 0ms;\n --kui-feedback-toast-ease: var(--kui-ease-back-out, ease-out);\n }\n [data-kui-fx~=toast-slide-out] {\n --kui-feedback-toast-ease: ease-in;\n --kui-feedback-toast-duration: 420ms;\n --kui-feedback-toast-delay: 0ms;\n }\n [data-kui-fx~=typewriter] {\n --kui-loop: false;\n }\n [data-kui-fx~=typewriter-loop] {\n --kui-loop: true;\n }\n [data-kui-fx~=underline-center] {\n --kui-underline-center-duration: 220ms;\n --kui-underline-center-ease: ease-out;\n }\n [data-kui-fx~=underline-draw] {\n --kui-text-sweep-duration: 600ms;\n --kui-text-sweep-delay: 0ms;\n --kui-text-sweep-ease: ease-out;\n }\n [data-kui-fx~=underline-slide] {\n --kui-underline-slide-duration: 220ms;\n --kui-underline-slide-ease: ease-out;\n }\n [data-kui-fx~=validate-check] {\n --kui-validate-check-duration: 600ms;\n --kui-validate-check-delay: 0ms;\n --kui-validate-check-ease: ease-out;\n }\n [data-kui-fx~=validate-shake] {\n --kui-validate-shake-duration: 600ms;\n --kui-validate-shake-delay: 0ms;\n --kui-validate-shake-ease: ease-out;\n }\n [data-kui-fx~=var-slant] {\n --kui-var-slant-duration: 600ms;\n --kui-var-slant-delay: 0ms;\n --kui-var-slant-ease: ease-out;\n }\n [data-kui-fx~=var-weight] {\n --kui-var-weight-duration: 600ms;\n --kui-var-weight-delay: 0ms;\n --kui-var-weight-ease: ease-out;\n }\n [data-kui-fx~=var-width] {\n --kui-var-width-duration: 600ms;\n --kui-var-width-delay: 0ms;\n --kui-var-width-ease: ease-out;\n }\n [data-kui-fx~=wave-blob] {\n --kui-ambient-gradient-duration: 12s;\n --kui-ambient-gradient-delay: 0ms;\n --kui-ambient-gradient-ease: ease-in-out;\n }\n [data-kui-fx~=wipe-circle] {\n --kui-media-wipe-duration: 600ms;\n --kui-media-wipe-delay: 0ms;\n --kui-media-wipe-ease: ease-out;\n }\n [data-kui-fx~=wipe-diagonal] {\n --kui-media-wipe-duration: 600ms;\n --kui-media-wipe-delay: 0ms;\n --kui-media-wipe-ease: ease-out;\n }\n [data-kui-fx~=wipe-down] {\n --kui-media-wipe-duration: 600ms;\n --kui-media-wipe-delay: 0ms;\n --kui-media-wipe-ease: ease-out;\n }\n [data-kui-fx~=wipe-left] {\n --kui-media-wipe-duration: 600ms;\n --kui-media-wipe-delay: 0ms;\n --kui-media-wipe-ease: ease-out;\n }\n [data-kui-fx~=wipe-right] {\n --kui-media-wipe-duration: 600ms;\n --kui-media-wipe-delay: 0ms;\n --kui-media-wipe-ease: ease-out;\n }\n [data-kui-fx~=wipe-up] {\n --kui-media-wipe-duration: 600ms;\n --kui-media-wipe-delay: 0ms;\n --kui-media-wipe-ease: ease-out;\n }\n [data-kui-fx~=wobble] {\n --kui-feedback-wobble-duration: 600ms;\n --kui-feedback-wobble-ease: ease-in-out;\n --kui-feedback-wobble-delay: 0ms;\n }\n [data-kui-fx~=zoom-in] {\n --kui-scale-duration: 600ms;\n --kui-scale-delay: 0ms;\n --kui-scale-ease: ease-out;\n }\n [data-kui-fx~=zoom-in-down] {\n --kui-scale-move-duration: 600ms;\n --kui-scale-move-delay: 0ms;\n --kui-scale-move-ease: ease-out;\n }\n [data-kui-fx~=zoom-in-up] {\n --kui-scale-move-duration: 600ms;\n --kui-scale-move-delay: 0ms;\n --kui-scale-move-ease: ease-out;\n }\n [data-kui-fx~=zoom-out] {\n --kui-scale-duration: 600ms;\n --kui-scale-delay: 0ms;\n --kui-scale-ease: ease-out;\n }\n}\n@layer kui.cloak {\n html[data-kui-cloak] [data-kui~=back-in-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=back-in-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=blur-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=blur-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=bounce-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=bounce-in-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=bounce-in-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=card-flip-x]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=card-flip-y]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=chart-bar-grow]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=curtain-reveal]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-blur-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-blur-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-left]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-right]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=flip-in-x]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=flip-in-y]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fold-panel]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=loading-bar]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=mask-reveal]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=pop-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=progress-bar]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=reveal-once]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=roll-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=rotate-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=rotate-in-left]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=rotate-in-right]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slat-assemble]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-block-end]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-block-start]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-inline-end]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-inline-start]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-left]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-right]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=swing-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=text-reveal-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=text-reveal-mask]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=text-reveal-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-circle]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-diagonal]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-left]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-right]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=zoom-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=zoom-in-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=zoom-in-up]:not([data-kui-state]) {\n opacity: 0;\n animation: kui-cloak-release 1ms linear 2s forwards;\n }\n @keyframes kui-cloak-release {\n to {\n opacity: 1;\n }\n }\n @media (prefers-reduced-motion: reduce) {\n html[data-kui-cloak] [data-kui~=back-in-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=back-in-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=blur-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=blur-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=bounce-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=bounce-in-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=bounce-in-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=card-flip-x]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=card-flip-y]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=chart-bar-grow]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=curtain-reveal]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-blur-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-blur-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-left]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-right]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fade-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=flip-in-x]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=flip-in-y]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=fold-panel]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=loading-bar]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=mask-reveal]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=pop-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=progress-bar]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=reveal-once]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=roll-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=rotate-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=rotate-in-left]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=rotate-in-right]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slat-assemble]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-block-end]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-block-start]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-inline-end]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-inline-start]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-left]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-right]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=slide-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=swing-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=text-reveal-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=text-reveal-mask]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=text-reveal-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-circle]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-diagonal]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-left]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-right]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=wipe-up]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=zoom-in]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=zoom-in-down]:not([data-kui-state]),\n html[data-kui-cloak] [data-kui~=zoom-in-up]:not([data-kui-state]) {\n opacity: 1;\n animation: none;\n }\n }\n}\n\n/* src/css/entrance.css */\n@layer kui.effects {\n @keyframes kui-in {\n from {\n opacity: var(--kui-from-opacity, 0);\n }\n }\n @keyframes kui-out {\n to {\n opacity: 0;\n }\n }\n @keyframes kui-in-up {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-in-down {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: 0 calc(var(--kui-distance, 24px) * -1);\n }\n }\n @keyframes kui-in-left {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: var(--kui-distance, 24px) 0;\n }\n }\n @keyframes kui-in-right {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: calc(var(--kui-distance, 24px) * -1) 0;\n }\n }\n @keyframes kui-out-up {\n to {\n opacity: 0;\n translate: 0 calc(var(--kui-distance, 24px) * -1);\n }\n }\n @keyframes kui-out-down {\n to {\n opacity: 0;\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-out-left {\n to {\n opacity: 0;\n translate: calc(var(--kui-distance, 24px) * -1) 0;\n }\n }\n @keyframes kui-out-right {\n to {\n opacity: 0;\n translate: var(--kui-distance, 24px) 0;\n }\n }\n @keyframes kui-in-inline-start {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: calc(var(--kui-distance, 24px) * var(--kui-dir, 1)) 0;\n }\n }\n @keyframes kui-in-inline-end {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: calc(var(--kui-distance, 24px) * var(--kui-dir, 1) * -1) 0;\n }\n }\n [data-kui-state=ready] {\n --kui-distance: 0px !important;\n }\n @keyframes kui-zoom-in {\n from {\n scale: var(--kui-from-scale, 0.92);\n }\n }\n @keyframes kui-zoom-out {\n to {\n scale: var(--kui-from-scale, 0.92);\n }\n }\n @keyframes kui-zoom-in-up {\n from {\n scale: var(--kui-from-scale, 0.92);\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-zoom-in-down {\n from {\n scale: var(--kui-from-scale, 0.92);\n translate: 0 calc(var(--kui-distance, 24px) * -1);\n }\n }\n @keyframes kui-flip-in-x {\n from {\n transform: perspective(var(--kui-perspective, 1200px)) rotateX(var(--kui-from-angle, 90deg));\n }\n }\n @keyframes kui-flip-in-y {\n from {\n transform: perspective(var(--kui-perspective, 1200px)) rotateY(var(--kui-from-angle, 90deg));\n }\n }\n @keyframes kui-flip-out-x {\n to {\n transform: perspective(var(--kui-perspective, 1200px)) rotateX(var(--kui-from-angle, 90deg));\n }\n }\n @keyframes kui-flip-out-y {\n to {\n transform: perspective(var(--kui-perspective, 1200px)) rotateY(var(--kui-from-angle, 90deg));\n }\n }\n @keyframes kui-rotate-in {\n from {\n rotate: var(--kui-from-angle, -8deg);\n }\n }\n @keyframes kui-rotate-out {\n to {\n rotate: var(--kui-from-angle, -8deg);\n }\n }\n @keyframes kui-swing-in {\n from {\n rotate: var(--kui-from-angle, -15deg);\n }\n }\n @keyframes kui-roll-in {\n from {\n rotate: var(--kui-from-angle, -120deg);\n translate: calc(var(--kui-distance, 24px) * -1) 0;\n }\n }\n @keyframes kui-roll-out {\n to {\n rotate: var(--kui-from-angle, -120deg);\n translate: var(--kui-distance, 24px) 0;\n }\n }\n @keyframes kui-blur-in {\n from {\n filter: blur(var(--kui-blur, 12px));\n }\n }\n @keyframes kui-blur-out {\n to {\n filter: blur(var(--kui-blur, 12px));\n }\n }\n @keyframes kui-fade-blur-up {\n from {\n opacity: var(--kui-from-opacity, 0);\n translate: 0 var(--kui-distance, 24px);\n filter: blur(var(--kui-blur, 12px));\n }\n }\n @keyframes kui-fade-blur-in {\n from {\n opacity: var(--kui-from-opacity, 0);\n filter: blur(var(--kui-blur, 12px));\n }\n }\n [data-kui-fx*=flip-] {\n transform-style: preserve-3d;\n }\n [data-kui-fx~=flip-in-x],\n [data-kui-fx~=flip-in-y],\n [data-kui-fx~=flip-out-x],\n [data-kui-fx~=flip-out-y] {\n perspective: var(--kui-perspective, 1200px);\n }\n [data-kui-fx~=flip-in-x][data-kui-state=ready],\n [data-kui-fx~=flip-in-y][data-kui-state=ready] {\n --kui-from-angle: 0deg !important;\n opacity: 0 !important;\n }\n}\n\n/* src/css/scroll.css */\n@layer kui.effects {\n @keyframes kui-parallax-y {\n from {\n translate: 0 calc(var(--kui-distance, 100px) * -1);\n }\n to {\n translate: 0 var(--kui-distance, 100px);\n }\n }\n @keyframes kui-parallax-x {\n from {\n translate: calc(var(--kui-distance, 100px) * -1) 0;\n }\n to {\n translate: var(--kui-distance, 100px) 0;\n }\n }\n @keyframes kui-parallax-scale {\n from {\n scale: var(--kui-from-scale, 1);\n }\n to {\n scale: var(--kui-to-scale, 1.2);\n }\n }\n @keyframes kui-parallax-rotate {\n from {\n rotate: var(--kui-from-angle, 0deg);\n }\n to {\n rotate: var(--kui-to-angle, 12deg);\n }\n }\n @keyframes kui-scroll-fade {\n from {\n opacity: var(--kui-from-opacity, 0);\n }\n to {\n opacity: 1;\n }\n }\n @keyframes kui-desaturate {\n from {\n filter: grayscale(var(--kui-from-grayscale, 100%));\n }\n to {\n filter: grayscale(var(--kui-to-grayscale, 0%));\n }\n }\n @keyframes kui-scroll-skew {\n from {\n transform: skewY(var(--kui-from-skew, 8deg));\n }\n to {\n transform: skewY(var(--kui-to-skew, 0deg));\n }\n }\n @keyframes kui-progress-x {\n from {\n scale: 0 1;\n }\n to {\n scale: 1 1;\n }\n }\n @keyframes kui-progress-y {\n from {\n scale: 1 0;\n }\n to {\n scale: 1 1;\n }\n }\n @keyframes kui-progress-ring {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n [data-kui-fx~=scroll-progress-bar] {\n transform-origin: left center;\n }\n [data-kui-fx~=scroll-progress-ring] {\n stroke-dasharray: var(--kui-path-length, 100);\n }\n [data-kui-fx~=sequence-scrub]:has(> [data-kui-step-state]),\n [data-kui-fx~=video-scrub]:has(> [data-kui-step-state]),\n .kui-frame-stack {\n position: relative;\n }\n [data-kui-fx~=sequence-scrub] > [data-kui-step-state],\n [data-kui-fx~=video-scrub] > [data-kui-step-state],\n .kui-frame-stack > [data-kui-step-state] {\n position: absolute;\n inset: 0;\n width: 100%;\n height: 100%;\n object-fit: cover;\n opacity: 0;\n }\n [data-kui-fx~=sequence-scrub] > [data-kui-step-state=active],\n [data-kui-fx~=video-scrub] > [data-kui-step-state=active],\n .kui-frame-stack > [data-kui-step-state=active] {\n opacity: 1;\n }\n @supports (animation-timeline: view()) {\n [data-kui-timeline] {\n animation-range: var(--kui-range, entry 0% cover 60%);\n }\n }\n}\n\n/* src/css/three-d.css */\n@layer kui.effects {\n @keyframes kui-card-flip-y {\n to {\n transform: perspective(var(--kui-perspective, 1200px)) rotateY(var(--kui-from-angle, 180deg));\n }\n }\n @keyframes kui-card-flip-x {\n to {\n transform: perspective(var(--kui-perspective, 1200px)) rotateX(var(--kui-from-angle, 180deg));\n }\n }\n @keyframes kui-cube-rotate {\n to {\n transform: perspective(var(--kui-perspective, 1200px)) rotateY(var(--kui-from-angle, 90deg));\n }\n }\n @keyframes kui-book-page-turn {\n to {\n transform: perspective(var(--kui-perspective, 1200px)) rotateY(var(--kui-from-angle, -160deg));\n }\n }\n @keyframes kui-fold-panel {\n from {\n transform: perspective(var(--kui-perspective, 1200px)) rotateX(var(--kui-from-angle, -90deg));\n }\n }\n [data-kui-fx~=card-flip-x],\n [data-kui-fx~=card-flip-y],\n [data-kui-fx~=cube-rotate],\n [data-kui-fx~=book-page-turn],\n [data-kui-fx~=fold-panel] {\n transform-style: preserve-3d;\n perspective: var(--kui-perspective, 1200px);\n }\n [data-kui-fx~=card-flip-x]:not(:has(> :nth-child(2))),\n [data-kui-fx~=card-flip-y]:not(:has(> :nth-child(2))) {\n --kui-from-angle: 360deg;\n }\n [data-kui-fx~=card-flip-x]:has(> :nth-child(2)),\n [data-kui-fx~=card-flip-y]:has(> :nth-child(2)) {\n display: grid;\n }\n [data-kui-fx~=card-flip-x]:has(> :nth-child(2)) > :first-child,\n [data-kui-fx~=card-flip-x]:has(> :nth-child(2)) > :nth-child(2),\n [data-kui-fx~=card-flip-y]:has(> :nth-child(2)) > :first-child,\n [data-kui-fx~=card-flip-y]:has(> :nth-child(2)) > :nth-child(2) {\n grid-area: 1 / 1;\n backface-visibility: hidden;\n }\n [data-kui-fx~=card-flip-x]:has(> :nth-child(2)) > :nth-child(2) {\n rotate: x 180deg;\n }\n [data-kui-fx~=card-flip-y]:has(> :nth-child(2)) > :nth-child(2) {\n rotate: y 180deg;\n }\n [data-kui-fx~=book-page-turn] {\n transform-origin: left center;\n }\n [data-kui-fx~=fold-panel] {\n transform-origin: top center;\n }\n [data-kui-fx~=fold-panel][data-kui-state=ready] {\n --kui-from-angle: 0deg !important;\n opacity: 0 !important;\n }\n @keyframes kui-page-fade {\n from {\n opacity: 0;\n }\n }\n @keyframes kui-page-slide {\n from {\n opacity: 0;\n translate: 0 var(--kui-distance, 40px);\n }\n }\n @keyframes kui-curtain-wipe {\n from {\n clip-path: inset(0 0 100% 0);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n @keyframes kui-loading-bar {\n from {\n scale: var(--kui-bar-from, 0) 1;\n }\n }\n [data-kui-fx~=loading-bar] {\n transform-origin: left center;\n }\n [data-kui-fx~=loading-bar][data-kui-state=ready] {\n --kui-bar-from: 1 !important;\n opacity: 0 !important;\n }\n [data-kui-fx~=flip-card] {\n display: grid;\n perspective: var(--kui-perspective, 1600px);\n }\n [data-kui-fx~=flip-card] > .kui-face-front,\n [data-kui-fx~=flip-card] > .kui-face-back {\n grid-area: 1 / 1;\n backface-visibility: hidden;\n transition: rotate var(--kui-card-toggle-duration, 700ms) var(--kui-card-toggle-ease, ease-in-out);\n }\n [data-kui-fx~=flip-card] > .kui-face-front {\n rotate: y 0deg;\n }\n [data-kui-fx~=flip-card] > .kui-face-back {\n rotate: y 180deg;\n }\n [data-kui-fx~=flip-card]:has(> .kui-flip-control[aria-pressed=true]) > .kui-face-front {\n rotate: y -180deg;\n }\n [data-kui-fx~=flip-card]:has(> .kui-flip-control[aria-pressed=true]) > .kui-face-back {\n rotate: y 0deg;\n }\n [data-kui~=flip-card] {\n display: grid;\n perspective: var(--kui-perspective, 1600px);\n }\n [data-kui~=flip-card] > .kui-face-front,\n [data-kui~=flip-card] > .kui-face-back {\n grid-area: 1 / 1;\n backface-visibility: hidden;\n }\n [data-kui~=flip-card] > .kui-face-front {\n rotate: y 0deg;\n }\n [data-kui~=flip-card] > .kui-face-back {\n rotate: y 180deg;\n }\n}\n\n/* src/css/media.css */\n@layer kui.effects {\n @keyframes kui-wipe-up {\n from {\n clip-path: inset(100% 0 0);\n }\n to {\n clip-path: inset(0 0 0);\n }\n }\n @keyframes kui-wipe-down {\n from {\n clip-path: inset(0 0 100%);\n }\n to {\n clip-path: inset(0 0 0);\n }\n }\n @keyframes kui-wipe-left {\n from {\n clip-path: inset(0 100% 0 0);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n @keyframes kui-wipe-right {\n from {\n clip-path: inset(0 0 0 100%);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n @keyframes kui-wipe-circle {\n from {\n clip-path: circle(0 at 50% 50%);\n }\n to {\n clip-path: circle(75% at 50% 50%);\n }\n }\n @keyframes kui-wipe-diagonal {\n from {\n clip-path: polygon(0 0, 0 0, 0 0);\n }\n to {\n clip-path: polygon(0 0, 200% 0, 0 200%);\n }\n }\n @keyframes kui-curtain-reveal {\n from {\n clip-path: inset(0 50%);\n }\n to {\n clip-path: inset(0 0);\n }\n }\n @keyframes kui-before-after-wipe {\n from {\n clip-path: inset(0 100% 0 0);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n @keyframes kui-mask-reveal {\n from {\n mask-position: 100% 0;\n }\n to {\n mask-position: 0 0;\n }\n }\n [data-kui-fx~=mask-reveal] {\n mask-image:\n linear-gradient(\n 90deg,\n #000 0 45%,\n transparent 55% 100%);\n mask-size: 220% 100%;\n }\n @keyframes kui-ken-burns {\n from {\n scale: 1;\n translate: 0 0;\n }\n to {\n scale: var(--kui-to-scale, 1.12);\n translate: var(--kui-distance, 24px) calc(var(--kui-distance, 24px) * -0.5);\n }\n }\n @keyframes kui-ken-burns-out {\n from {\n scale: var(--kui-to-scale, 1.12);\n translate: calc(var(--kui-distance, 24px) * -1) 0;\n }\n to {\n scale: 1;\n translate: 0 0;\n }\n }\n @keyframes kui-blur-up {\n from {\n translate: 0 var(--kui-distance, 24px);\n filter: blur(var(--kui-blur, 16px));\n }\n to {\n translate: 0 0;\n filter: blur(0);\n }\n }\n @keyframes kui-duotone-hover {\n from {\n filter: grayscale(1) sepia(0.7) hue-rotate(330deg) saturate(2);\n }\n to {\n filter: none;\n }\n }\n @keyframes kui-grayscale-hover {\n from {\n filter: grayscale(1);\n }\n to {\n filter: grayscale(0);\n }\n }\n @keyframes kui-saturate-hover {\n from {\n filter: saturate(0.45);\n }\n to {\n filter: saturate(1.35);\n }\n }\n @keyframes kui-image-parallax-frame {\n from {\n translate: 0 calc(var(--kui-distance, 24px) * -1);\n }\n to {\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-lightbox-open {\n from {\n opacity: 0;\n scale: var(--kui-from-scale, 0.92);\n }\n to {\n opacity: 1;\n scale: 1;\n }\n }\n @media (pointer: coarse) {\n [data-kui-fx~=duotone-hover]:active,\n [data-kui-fx~=grayscale-hover]:active,\n [data-kui-fx~=saturate-hover]:active {\n filter: none;\n }\n }\n .kui-slat-stage {\n position: absolute;\n overflow: clip;\n }\n .kui-slat-item {\n position: absolute;\n inset: 0;\n background-repeat: no-repeat;\n background-size: 100% 100%;\n animation-duration: var(--kui-duration, 500ms);\n animation-delay: calc(var(--kui-delay, 0ms) + var(--kui-i, 0) * var(--kui-stagger, 60ms));\n animation-timing-function: var(--kui-ease, ease-out);\n animation-fill-mode: both;\n }\n .kui-slat-stage.kui-slat-animating .kui-slat-item {\n will-change: transform;\n }\n .kui-slat-item:nth-child(odd) {\n --kui-slat-sign: -1;\n }\n .kui-slat-item:nth-child(even) {\n --kui-slat-sign: 1;\n }\n .kui-slat-stage[data-kui-slat-fold=true] {\n perspective: 1200px;\n }\n .kui-slat-stage:not([data-kui-slat-fold=true]) .kui-slat-item {\n animation-name: kui-slat-assemble;\n }\n .kui-slat-stage[data-kui-slat-fold=true] .kui-slat-item {\n animation-name: kui-slat-assemble-fold;\n }\n @keyframes kui-slat-assemble {\n from {\n opacity: 0;\n translate: calc(var(--kui-slat-sign, 1) * var(--kui-slat-dx, 0) * 38%) calc(var(--kui-slat-sign, 1) * var(--kui-slat-dy, 1) * 38%);\n }\n 12% {\n opacity: 1;\n }\n to {\n opacity: 1;\n translate: 0 0;\n }\n }\n @keyframes kui-slat-assemble-fold {\n from {\n opacity: 0;\n translate: calc(var(--kui-slat-sign, 1) * var(--kui-slat-dx, 0) * 38%) calc(var(--kui-slat-sign, 1) * var(--kui-slat-dy, 1) * 38%);\n rotate: var(--kui-slat-dx, 0) var(--kui-slat-dy, 1) 0 calc(var(--kui-slat-sign, 1) * 38deg);\n }\n 12% {\n opacity: 1;\n }\n to {\n opacity: 1;\n translate: 0 0;\n rotate: var(--kui-slat-dx, 0) var(--kui-slat-dy, 1) 0 0deg;\n }\n }\n}\n\n/* src/css/text.css */\n@layer kui.effects {\n .kui-sr-only {\n position: absolute;\n width: 1px;\n height: 1px;\n padding: 0;\n margin: -1px;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n }\n .kui-split-decorative {\n display: inline;\n }\n .kui-split-item {\n display: inline-block;\n animation-duration: var(--kui-duration, 500ms);\n animation-delay: calc(var(--kui-delay, 0ms) + var(--kui-i, 0) * var(--kui-stagger, 30ms));\n animation-timing-function: var(--kui-ease, ease-out);\n animation-fill-mode: both;\n }\n .kui-split-line {\n display: block;\n }\n [data-kui-split-fx=fade] .kui-split-item {\n animation-name: kui-split-reveal-fade;\n }\n [data-kui-split-fx=up] .kui-split-item {\n animation-name: kui-split-reveal-up;\n }\n [data-kui-split-fx=down] .kui-split-item {\n animation-name: kui-split-reveal-down;\n }\n [data-kui-split-fx=mask] .kui-split-item {\n animation-name: kui-split-reveal-mask;\n }\n @keyframes kui-split-reveal-fade {\n from {\n opacity: 0;\n }\n }\n @keyframes kui-split-reveal-up {\n from {\n opacity: 0;\n translate: 0 0.6em;\n }\n }\n @keyframes kui-split-reveal-down {\n from {\n opacity: 0;\n translate: 0 -0.6em;\n }\n }\n @keyframes kui-split-reveal-mask {\n from {\n opacity: 0;\n clip-path: inset(0 0 100% 0);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n [data-kui-split-fx=wave] .kui-split-item {\n animation-name: kui-split-wave;\n animation-duration: 1400ms;\n animation-iteration-count: infinite;\n animation-timing-function: ease-in-out;\n }\n [data-kui-split-fx=jitter] .kui-split-item {\n animation-name: kui-split-jitter;\n animation-duration: 220ms;\n animation-iteration-count: infinite;\n animation-timing-function: ease-in-out;\n animation-direction: alternate;\n }\n @keyframes kui-split-wave {\n 0%, 100% {\n translate: 0 0;\n }\n 50% {\n translate: 0 -0.35em;\n }\n }\n @keyframes kui-split-jitter {\n from {\n translate: 0 0;\n rotate: 0deg;\n }\n to {\n translate: 0 0.08em;\n rotate: 3deg;\n }\n }\n .kui-typewriter::after {\n content: \"\";\n display: inline-block;\n width: 0.08em;\n margin-inline-start: 0.05em;\n height: 1em;\n vertical-align: -0.15em;\n background: currentColor;\n animation: kui-caret-blink 1s steps(1) infinite;\n }\n @keyframes kui-caret-blink {\n 50% {\n opacity: 0;\n }\n }\n .kui-scramble {\n font-variant-numeric: tabular-nums;\n }\n [data-kui-fx~=word-cycler] {\n display: inline-block;\n transition: opacity 150ms ease-out;\n }\n [data-kui-fx~=word-cycler].kui-word-cycler-swap {\n opacity: 0;\n }\n [data-kui-fx~=gradient-shimmer] {\n background-image:\n linear-gradient(\n 100deg,\n currentColor 40%,\n color-mix(in srgb, currentColor 35%, transparent) 50%,\n currentColor 60%);\n background-size: 220% 100%;\n -webkit-background-clip: text;\n background-clip: text;\n -webkit-text-fill-color: transparent;\n --kui-fx-gradient-shimmer-iterations: infinite;\n }\n @keyframes kui-gradient-shimmer {\n from {\n background-position: 200% 0;\n }\n to {\n background-position: -200% 0;\n }\n }\n [data-kui-fx~=gradient-sweep] {\n background-image:\n linear-gradient(\n 100deg,\n transparent 30%,\n color-mix(in srgb, var(--kui-sweep-color, currentColor) 70%, transparent) 50%,\n transparent 70%);\n background-size: 260% 100%;\n -webkit-background-clip: text;\n background-clip: text;\n -webkit-text-fill-color: transparent;\n }\n @keyframes kui-gradient-sweep {\n from {\n background-position: 220% 0;\n }\n to {\n background-position: -60% 0;\n }\n }\n [data-kui-fx~=highlight-sweep] {\n background-image: linear-gradient(90deg, color-mix(in srgb, var(--kui-sweep-color, currentColor) 55%, transparent) 0 100%);\n background-repeat: no-repeat;\n background-size: 0% 100%;\n padding: 0 0.05em;\n }\n @keyframes kui-highlight-sweep {\n to {\n background-size: 100% 100%;\n }\n }\n [data-kui-fx~=underline-draw] {\n background-image: linear-gradient(var(--kui-sweep-color, currentColor), var(--kui-sweep-color, currentColor));\n background-repeat: no-repeat;\n background-position: 0 100%;\n background-size: 0% 2px;\n padding-bottom: 0.15em;\n }\n @keyframes kui-underline-draw {\n to {\n background-size: 100% 2px;\n }\n }\n [data-kui-fx~=text-outline-fill] {\n -webkit-text-stroke: 1px currentColor;\n -webkit-text-fill-color: transparent;\n }\n @keyframes kui-text-outline-fill {\n to {\n -webkit-text-fill-color: currentColor;\n }\n }\n @keyframes kui-var-weight {\n from {\n font-weight: var(--kui-from-weight, 100);\n }\n to {\n font-weight: var(--kui-to-weight, 800);\n }\n }\n @keyframes kui-var-width {\n from {\n font-stretch: var(--kui-from-width, 75%);\n }\n to {\n font-stretch: var(--kui-to-width, 125%);\n }\n }\n @keyframes kui-var-slant {\n from {\n font-style: oblique var(--kui-from-slant, 0deg);\n }\n to {\n font-style: oblique var(--kui-to-slant, 10deg);\n }\n }\n [data-kui-fx~=marquee],\n [data-kui-fx~=marquee-scroll-linked] {\n display: flex;\n width: max-content;\n will-change: translate;\n }\n [data-kui-fx~=marquee] {\n --kui-fx-marquee-iterations: infinite;\n }\n @keyframes kui-marquee {\n to {\n translate: -50% 0;\n }\n }\n @property --kui-redaction-x { syntax: \"<percentage>\"; inherits: true; initial-value: 0%; }\n [data-kui-fx~=redaction-reveal] {\n position: relative;\n display: inline-block;\n }\n [data-kui-fx~=redaction-reveal]::before {\n content: \"\";\n position: absolute;\n inset: 0;\n background: var(--kui-bar-color, #111);\n clip-path: inset(0 0 0 var(--kui-redaction-x));\n }\n @keyframes kui-redaction-reveal {\n to {\n --kui-redaction-x: 100%;\n }\n }\n [data-kui-fx~=text-3d-extrude] {\n display: inline-block;\n text-shadow:\n 1px 1px 0 color-mix(in srgb, currentColor 70%, transparent),\n 2px 2px 0 color-mix(in srgb, currentColor 60%, transparent),\n 3px 3px 0 color-mix(in srgb, currentColor 50%, transparent),\n 4px 4px 0 color-mix(in srgb, currentColor 40%, transparent),\n 5px 5px 0 color-mix(in srgb, currentColor 30%, transparent),\n 6px 6px 8px rgb(0 0 0 / 0.35);\n }\n @keyframes kui-text-3d-extrude {\n from {\n rotate: var(--kui-from-angle, -20deg);\n translate: 0 var(--kui-distance, 32px);\n }\n to {\n rotate: 0deg;\n translate: 0 0;\n }\n }\n}\n\n/* src/css/navigation.css */\n@layer kui.effects {\n @keyframes kui-nav-reveal {\n from {\n opacity: 0;\n translate: 0 var(--kui-distance, 16px);\n }\n }\n @keyframes kui-menu-fullscreen {\n from {\n opacity: 0;\n clip-path: circle(0% at var(--kui-origin, 100% 0%));\n }\n to {\n opacity: 1;\n clip-path: circle(150% at var(--kui-origin, 100% 0%));\n }\n }\n @keyframes kui-panel-reveal {\n from {\n opacity: 0;\n translate: 0 calc(var(--kui-distance, 10px) * -1);\n }\n }\n @keyframes kui-drawer-slide-right {\n from {\n translate: 100% 0;\n }\n }\n [data-kui-fx~=header-shrink] {\n --kui-shrink: 0;\n padding-block: calc(1.4rem - 0.7rem * var(--kui-shrink, 0));\n font-size: calc(1rem - 0.15rem * var(--kui-shrink, 0));\n transition:\n padding-block 200ms ease-out,\n font-size 200ms ease-out,\n box-shadow 200ms ease-out;\n }\n [data-kui-fx~=header-shrink][data-kui-shrunk=true] {\n box-shadow: 0 2px 10px rgb(0 0 0 / 0.12);\n }\n [data-kui-fx~=header-hide-on-scroll] {\n transition: translate 220ms ease-out;\n }\n [data-kui-fx~=header-hide-on-scroll][data-kui-hidden=true] {\n translate: 0 -100%;\n }\n [data-kui-fx~=back-to-top-fade] {\n opacity: 0;\n translate: 0 12px;\n pointer-events: none;\n transition: opacity 200ms ease-out, translate 200ms ease-out;\n }\n [data-kui-fx~=back-to-top-fade][data-kui-visible=true] {\n opacity: 1;\n translate: 0 0;\n pointer-events: auto;\n }\n}\n\n/* src/css/forms.css */\n@layer kui.effects {\n [data-kui-fx~=label-float] ~ label {\n transition: translate 180ms ease-out, scale 180ms ease-out;\n transform-origin: left center;\n }\n [data-kui-fx~=label-float]:focus ~ label,\n [data-kui-fx~=label-float]:not(:placeholder-shown) ~ label {\n translate: 0 -1.35rem;\n scale: 0.82;\n }\n [data-kui-fx~=input-underline-grow] ~ .kui-underline {\n display: block;\n height: 2px;\n background: currentColor;\n scale: 0 1;\n transform-origin: left center;\n transition: scale 220ms ease-out;\n }\n [data-kui-fx~=input-underline-grow]:focus ~ .kui-underline {\n scale: 1 1;\n }\n @keyframes kui-focus-ring-grow {\n from {\n box-shadow: 0 0 0 0 var(--kui-ring-color, rgb(210 105 30 / 0.55));\n }\n to {\n box-shadow: 0 0 0 5px var(--kui-ring-color, rgb(210 105 30 / 0.55));\n }\n }\n @keyframes kui-validate-shake {\n 10%, 90% {\n translate: -1px 0;\n }\n 20%, 80% {\n translate: 2px 0;\n }\n 30%, 50%, 70% {\n translate: -4px 0;\n }\n 40%, 60% {\n translate: 4px 0;\n }\n }\n [data-kui-fx~=validate-check] {\n stroke-dasharray: 24;\n stroke-dashoffset: 24;\n }\n @keyframes kui-validate-check {\n to {\n stroke-dashoffset: 0;\n }\n }\n [data-kui-fx~=strength-meter] ~ .kui-meter > * {\n background: var(--kui-meter-off, currentColor);\n opacity: 0.2;\n transition: opacity 200ms ease-out, background-color 200ms ease-out;\n }\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"1\"] ~ .kui-meter > *:nth-child(-n+1),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"2\"] ~ .kui-meter > *:nth-child(-n+2),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"3\"] ~ .kui-meter > *:nth-child(-n+3),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"4\"] ~ .kui-meter > *:nth-child(-n+4),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"5\"] ~ .kui-meter > *:nth-child(-n+5),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"6\"] ~ .kui-meter > *:nth-child(-n+6),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"7\"] ~ .kui-meter > *:nth-child(-n+7),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"8\"] ~ .kui-meter > *:nth-child(-n+8),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"9\"] ~ .kui-meter > *:nth-child(-n+9),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"10\"] ~ .kui-meter > *:nth-child(-n+10),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"11\"] ~ .kui-meter > *:nth-child(-n+11),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"12\"] ~ .kui-meter > *:nth-child(-n+12),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"13\"] ~ .kui-meter > *:nth-child(-n+13),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"14\"] ~ .kui-meter > *:nth-child(-n+14),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"15\"] ~ .kui-meter > *:nth-child(-n+15),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"16\"] ~ .kui-meter > *:nth-child(-n+16),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"17\"] ~ .kui-meter > *:nth-child(-n+17),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"18\"] ~ .kui-meter > *:nth-child(-n+18),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"19\"] ~ .kui-meter > *:nth-child(-n+19),\n [data-kui-fx~=strength-meter][data-kui-strength-level=\"20\"] ~ .kui-meter > *:nth-child(-n+20) {\n opacity: 1;\n background: var(--kui-meter-on, #2e9e5b);\n }\n [data-kui-fx~=toggle-morph] ~ .kui-track {\n display: inline-block;\n width: calc(40px * var(--kui-toggle-scale, 1));\n height: calc(22px * var(--kui-toggle-scale, 1));\n border-radius: 999px;\n background: var(--muted, #9a8d80);\n transition: background-color 200ms ease-out;\n position: relative;\n }\n [data-kui-fx~=toggle-morph] ~ .kui-track .kui-thumb {\n position: absolute;\n top: calc(2px * var(--kui-toggle-scale, 1));\n left: calc(2px * var(--kui-toggle-scale, 1));\n width: calc(18px * var(--kui-toggle-scale, 1));\n height: calc(18px * var(--kui-toggle-scale, 1));\n border-radius: 50%;\n background: var(--kui-thumb-color, #fff);\n translate: 0 0;\n transition: translate 200ms ease-out;\n }\n [data-kui-fx~=toggle-morph]:checked ~ .kui-track {\n background: var(--accent, #d2691e);\n }\n [data-kui-fx~=toggle-morph]:checked ~ .kui-track .kui-thumb {\n translate: calc(18px * var(--kui-toggle-scale, 1)) 0;\n }\n [data-kui-fx~=checkbox-draw] ~ svg path {\n stroke-dasharray: 24;\n stroke-dashoffset: 24;\n transition: stroke-dashoffset 220ms ease-out;\n }\n [data-kui-fx~=checkbox-draw]:checked ~ svg path {\n stroke-dashoffset: 0;\n }\n [data-kui-fx~=radio-fill] ~ .kui-dot {\n display: inline-block;\n width: calc(10px * var(--kui-radio-scale, 1));\n height: calc(10px * var(--kui-radio-scale, 1));\n border-radius: 50%;\n background: var(--accent, #d2691e);\n scale: 0;\n transition: scale 180ms ease-out;\n }\n [data-kui-fx~=radio-fill]:checked ~ .kui-dot {\n scale: 1;\n }\n [data-kui-fx~=range-fill] {\n --kui-fill: 0%;\n accent-color: var(--accent, #d2691e);\n background:\n linear-gradient(\n to right,\n var(--accent, #d2691e) var(--kui-fill, 0%),\n var(--border, #2a2422) var(--kui-fill, 0%));\n height: 4px;\n border-radius: 999px;\n appearance: none;\n outline: none;\n }\n [data-kui-fx~=submit-to-spinner-to-check] .kui-stage-idle,\n [data-kui-fx~=submit-to-spinner-to-check] .kui-stage-loading,\n [data-kui-fx~=submit-to-spinner-to-check] .kui-stage-done {\n display: none;\n }\n [data-kui-fx~=submit-to-spinner-to-check][data-kui-stage=idle] .kui-stage-idle,\n [data-kui-fx~=submit-to-spinner-to-check][data-kui-stage=loading] .kui-stage-loading,\n [data-kui-fx~=submit-to-spinner-to-check][data-kui-stage=done] .kui-stage-done {\n display: inline-flex;\n }\n [data-kui-fx~=submit-to-spinner-to-check] .kui-spinner {\n width: 1em;\n height: 1em;\n border-radius: 50%;\n border: 2px solid currentColor;\n border-top-color: transparent;\n animation: kui-spin 700ms linear infinite;\n }\n @keyframes kui-spin {\n to {\n rotate: 360deg;\n }\n }\n [data-kui-fx~=step-progress] {\n cursor: pointer;\n }\n [data-kui-fx~=step-progress] > [data-kui-step-state],\n .kui-step-track > [data-kui-step-state] {\n background: var(--muted, #9a8d80);\n opacity: 0.35;\n transition: opacity 200ms ease-out, background-color 200ms ease-out;\n }\n [data-kui-fx~=step-progress] > [data-kui-step-state=before],\n [data-kui-fx~=step-progress] > [data-kui-step-state=active],\n .kui-step-track > [data-kui-step-state=before],\n .kui-step-track > [data-kui-step-state=active] {\n opacity: 1;\n background: var(--accent, #d2691e);\n }\n}\n\n/* src/css/ambient.css */\n@layer kui.effects {\n [data-kui-fx~=gradient-mesh] {\n background-image:\n radial-gradient(\n at 15% 20%,\n color-mix(in srgb, var(--kui-c1, #7c3aed) 55%, transparent),\n transparent 55%),\n radial-gradient(\n at 85% 15%,\n color-mix(in srgb, var(--kui-c2, #06b6d4) 50%, transparent),\n transparent 55%),\n radial-gradient(\n at 50% 85%,\n color-mix(in srgb, var(--kui-c3, #f97316) 45%, transparent),\n transparent 55%);\n background-size: 200% 200%;\n --kui-fx-gradient-mesh-iterations: infinite;\n }\n @keyframes kui-gradient-mesh {\n 0%, 100% {\n background-position:\n 0% 0%,\n 100% 0%,\n 50% 100%;\n }\n 50% {\n background-position:\n 25% 35%,\n 75% 30%,\n 35% 70%;\n }\n }\n [data-kui-fx~=aurora] {\n background-image:\n linear-gradient(\n 120deg,\n color-mix(in srgb, var(--kui-c1, #34d399) 45%, transparent),\n transparent 45%),\n linear-gradient(\n 240deg,\n color-mix(in srgb, var(--kui-c2, #60a5fa) 45%, transparent),\n transparent 45%),\n linear-gradient(\n 0deg,\n color-mix(in srgb, var(--kui-c3, #c084fc) 40%, transparent),\n transparent 50%);\n background-size: 260% 260%;\n --kui-fx-aurora-iterations: infinite;\n }\n @keyframes kui-aurora {\n 0%, 100% {\n background-position:\n 0% 50%,\n 100% 50%,\n 50% 0%;\n }\n 50% {\n background-position:\n 60% 30%,\n 40% 70%,\n 55% 60%;\n }\n }\n [data-kui-fx~=wave-blob] {\n background-image:\n radial-gradient(\n circle,\n color-mix(in srgb, var(--kui-c1, #22d3ee) 50%, transparent),\n transparent 60%);\n background-size: 140% 140%;\n background-repeat: no-repeat;\n --kui-fx-wave-blob-iterations: infinite;\n }\n @keyframes kui-wave-blob {\n 0%, 100% {\n background-position: 20% 30%;\n background-size: 140% 140%;\n }\n 33% {\n background-position: 70% 20%;\n background-size: 160% 160%;\n }\n 66% {\n background-position: 50% 75%;\n background-size: 120% 120%;\n }\n }\n [data-kui-fx~=spotlight-follow] {\n background-image:\n radial-gradient(\n circle,\n color-mix(in srgb, var(--kui-c1, #fde68a) 65%, transparent),\n transparent 65%);\n background-size: 55% 55%;\n background-repeat: no-repeat;\n --kui-fx-spotlight-follow-iterations: infinite;\n }\n @keyframes kui-spotlight-follow {\n 0%, 100% {\n background-position: 10% 15%;\n }\n 25% {\n background-position: 85% 20%;\n }\n 50% {\n background-position: 80% 80%;\n }\n 75% {\n background-position: 15% 75%;\n }\n }\n [data-kui-fx~=gradient-rotate-border] {\n position: relative;\n background-image:\n linear-gradient(\n 90deg,\n var(--kui-c1, #f472b6),\n var(--kui-c2, #60a5fa),\n var(--kui-c3, #34d399),\n var(--kui-c4, #fbbf24),\n var(--kui-c1, #f472b6));\n background-size: 300% 100%;\n padding: 3px;\n mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);\n mask-composite: exclude;\n -webkit-mask-composite: xor;\n --kui-fx-gradient-rotate-border-iterations: infinite;\n }\n @keyframes kui-gradient-rotate-border {\n from {\n background-position: 0% 50%;\n }\n to {\n background-position: 300% 50%;\n }\n }\n [data-kui-fx~=noise-overlay] {\n background-image:\n repeating-radial-gradient(\n circle at 0 0,\n color-mix(in srgb, var(--kui-c1, currentColor) 30%, transparent) 0,\n transparent 1.4px,\n transparent 3px);\n background-size: 5px 5px;\n --kui-fx-noise-overlay-iterations: infinite;\n }\n @keyframes kui-noise-overlay {\n 0% {\n background-position: 0 0;\n }\n 20% {\n background-position: -3px 1px;\n }\n 40% {\n background-position: 2px -2px;\n }\n 60% {\n background-position: -1px 3px;\n }\n 80% {\n background-position: 3px 2px;\n }\n 100% {\n background-position: 0 0;\n }\n }\n [data-kui-fx~=scanline] {\n background-image:\n linear-gradient(\n to bottom,\n transparent,\n color-mix(in srgb, var(--kui-c1, currentColor) 35%, transparent) 50%,\n transparent);\n background-size: 100% 220%;\n background-repeat: no-repeat;\n --kui-fx-scanline-iterations: infinite;\n }\n @keyframes kui-scanline {\n from {\n background-position: 0 -120%;\n }\n to {\n background-position: 0 120%;\n }\n }\n [data-kui-fx~=dot-grid-drift] {\n background-image:\n radial-gradient(\n circle,\n color-mix(in srgb, var(--kui-c1, currentColor) 45%, transparent) 1.5px,\n transparent 1.5px);\n background-size: 22px 22px;\n --kui-fx-dot-grid-drift-iterations: infinite;\n }\n @keyframes kui-dot-grid-drift {\n from {\n background-position: 0 0;\n }\n to {\n background-position: 22px 22px;\n }\n }\n [data-kui-fx~=line-grid-drift] {\n background-image:\n repeating-linear-gradient(\n 0deg,\n color-mix(in srgb, var(--kui-c1, currentColor) 30%, transparent) 0 1px,\n transparent 1px 26px),\n repeating-linear-gradient(\n 90deg,\n color-mix(in srgb, var(--kui-c1, currentColor) 30%, transparent) 0 1px,\n transparent 1px 26px);\n --kui-fx-line-grid-drift-iterations: infinite;\n }\n @keyframes kui-line-grid-drift {\n from {\n background-position: 0 0, 0 0;\n }\n to {\n background-position: 0 26px, 26px 0;\n }\n }\n [data-kui-fx~=starfield] {\n background-image:\n radial-gradient(\n 1px 1px at 10% 20%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 90%, transparent),\n transparent),\n radial-gradient(\n 1px 1px at 70% 60%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 70%, transparent),\n transparent),\n radial-gradient(\n 1.5px 1.5px at 40% 80%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 85%, transparent),\n transparent),\n radial-gradient(\n 1px 1px at 90% 30%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 60%, transparent),\n transparent),\n radial-gradient(\n 1.5px 1.5px at 25% 55%,\n color-mix(in srgb, var(--kui-c1, #ffffff) 80%, transparent),\n transparent);\n background-size: 220px 220px;\n background-repeat: repeat;\n --kui-fx-starfield-iterations: infinite;\n }\n @keyframes kui-starfield {\n from {\n background-position:\n 0 0,\n 0 0,\n 0 0,\n 0 0,\n 0 0;\n }\n to {\n background-position:\n 220px 90px,\n -160px 220px,\n 90px -140px,\n -220px -90px,\n 140px 160px;\n }\n }\n [data-kui-fx~=orbit] {\n --kui-fx-orbit-iterations: infinite;\n }\n @keyframes kui-orbit {\n to {\n rotate: var(--kui-to-angle, 360deg);\n }\n }\n [data-kui-fx~=float] {\n --kui-fx-float-iterations: infinite;\n }\n @keyframes kui-float {\n 0%, 100% {\n translate: 0 0;\n }\n 50% {\n translate: 0 calc(var(--kui-distance, 14px) * -1);\n }\n }\n [data-kui-fx~=bob] {\n --kui-fx-bob-iterations: infinite;\n }\n @keyframes kui-bob {\n 0%, 100% {\n translate: 0 0;\n }\n 50% {\n translate: 0 calc(var(--kui-distance, 8px) * -1);\n }\n }\n [data-kui-fx~=floating-shapes] {\n --kui-fx-floating-shapes-iterations: infinite;\n }\n @keyframes kui-floating-shapes {\n 0%, 100% {\n translate: 0 0;\n }\n 33% {\n translate: calc(var(--kui-distance, 10px) * 0.6) calc(var(--kui-distance, 10px) * -1);\n }\n 66% {\n translate: calc(var(--kui-distance, 10px) * -0.6) calc(var(--kui-distance, 10px) * -0.4);\n }\n }\n [data-kui-fx~=glow-pulse] {\n --kui-fx-glow-pulse-iterations: infinite;\n }\n @keyframes kui-glow-pulse {\n 0%, 100% {\n scale: 1;\n opacity: 0.6;\n }\n 50% {\n scale: var(--kui-pulse-scale, 1.15);\n opacity: 1;\n }\n }\n}\n\n/* src/css/feedback.css */\n@layer kui.effects {\n [data-kui-fx~=skeleton-shimmer] {\n background-color: var(--kui-skeleton-base, #2a2422);\n background-image:\n linear-gradient(\n 100deg,\n transparent 30%,\n color-mix(in srgb, var(--kui-skeleton-highlight, #ffffff) 18%, transparent) 50%,\n transparent 70%);\n background-size: 200% 100%;\n --kui-fx-skeleton-shimmer-iterations: infinite;\n }\n @keyframes kui-skeleton-shimmer {\n from {\n background-position: 150% 0;\n }\n to {\n background-position: -50% 0;\n }\n }\n @keyframes kui-skeleton-to-content {\n from {\n opacity: 0;\n }\n }\n [data-kui-fx~=spinner] {\n display: inline-block;\n width: var(--kui-spinner-size, 28px);\n height: var(--kui-spinner-size, 28px);\n border-radius: 50%;\n border: 3px solid color-mix(in srgb, currentColor 20%, transparent);\n border-top-color: currentColor;\n --kui-fx-spinner-iterations: infinite;\n }\n @keyframes kui-spinner-spin {\n to {\n rotate: 360deg;\n }\n }\n [data-kui-fx~=spinner-ring] {\n display: inline-block;\n width: var(--kui-spinner-size, 28px);\n height: var(--kui-spinner-size, 28px);\n border-radius: 50%;\n border: 3px dashed color-mix(in srgb, currentColor 55%, transparent);\n --kui-fx-spinner-ring-iterations: infinite;\n }\n @keyframes kui-spinner-ring-spin {\n to {\n rotate: 360deg;\n }\n }\n [data-kui-fx~=spinner-dots] {\n display: inline-block;\n width: var(--kui-dot-size, 8px);\n height: var(--kui-dot-size, 8px);\n border-radius: 50%;\n background: currentColor;\n box-shadow: calc(var(--kui-dot-size, 8px) * -2) 0 currentColor, calc(var(--kui-dot-size, 8px) * 2) 0 currentColor;\n --kui-fx-spinner-dots-iterations: infinite;\n }\n @keyframes kui-spinner-dots {\n 0%, 80%, 100% {\n scale: 0.7;\n opacity: 0.5;\n }\n 40% {\n scale: 1.15;\n opacity: 1;\n }\n }\n [data-kui-fx~=progress-indeterminate] {\n transform-origin: 0% 50%;\n background: currentColor;\n border-radius: inherit;\n --kui-fx-progress-indeterminate-iterations: infinite;\n }\n @keyframes kui-progress-indeterminate {\n 0% {\n translate: -100% 0;\n scale: 0.4 1;\n }\n 50% {\n scale: 1 1;\n }\n 100% {\n translate: 100% 0;\n scale: 0.4 1;\n }\n }\n @keyframes kui-toast-slide-in {\n from {\n opacity: 0;\n translate: 0 var(--kui-distance, 24px);\n }\n to {\n opacity: 1;\n translate: 0 0;\n }\n }\n @keyframes kui-toast-slide-out {\n from {\n opacity: 1;\n translate: 0 0;\n }\n to {\n opacity: 0;\n translate: 0 var(--kui-distance, 24px);\n }\n }\n @keyframes kui-shake-error {\n 10%, 90% {\n translate: -1px 0;\n }\n 20%, 80% {\n translate: 2px 0;\n }\n 30%, 50%, 70% {\n translate: -4px 0;\n }\n 40%, 60% {\n translate: 4px 0;\n }\n }\n @keyframes kui-wobble {\n 0% {\n translate: 0 0;\n rotate: 0deg;\n }\n 15% {\n translate: -6px 0;\n rotate: -6deg;\n }\n 30% {\n translate: 4px 0;\n rotate: 4deg;\n }\n 45% {\n translate: -3px 0;\n rotate: -3deg;\n }\n 60% {\n translate: 2px 0;\n rotate: 2deg;\n }\n 75% {\n translate: -1px 0;\n rotate: -1deg;\n }\n 100% {\n translate: 0 0;\n rotate: 0deg;\n }\n }\n [data-kui-fx~=ripple] {\n border-radius: 50%;\n background: currentColor;\n transform-origin: center;\n }\n @keyframes kui-ripple {\n from {\n scale: 0.2;\n opacity: 0.6;\n }\n to {\n scale: var(--kui-ripple-scale, 4);\n opacity: 0;\n }\n }\n @keyframes kui-badge-pop {\n 0% {\n scale: 0.4;\n }\n 60% {\n scale: var(--kui-pop-scale, 1.18);\n }\n 100% {\n scale: 1;\n }\n }\n @keyframes kui-count-bump {\n 0%, 100% {\n scale: 1;\n }\n 50% {\n scale: var(--kui-pop-scale, 1.18);\n }\n }\n [data-kui-fx~=heart-burst] {\n color: var(--kui-heart-color, #f43f5e);\n }\n @keyframes kui-heart-burst {\n 0% {\n scale: 1;\n }\n 30% {\n scale: var(--kui-pop-scale, 1.18);\n }\n 55% {\n scale: 0.9;\n }\n 100% {\n scale: 1;\n }\n }\n [data-kui-fx~=confetti-burst] {\n background-image:\n radial-gradient(\n circle at 20% 20%,\n var(--kui-c1, #f43f5e) 0 3px,\n transparent 3px),\n radial-gradient(\n circle at 75% 15%,\n var(--kui-c2, #fbbf24) 0 3px,\n transparent 3px),\n radial-gradient(\n circle at 50% 75%,\n var(--kui-c3, #34d399) 0 3px,\n transparent 3px),\n radial-gradient(\n circle at 85% 65%,\n var(--kui-c4, #60a5fa) 0 3px,\n transparent 3px),\n radial-gradient(\n circle at 15% 65%,\n var(--kui-c5, #c084fc) 0 3px,\n transparent 3px);\n background-repeat: no-repeat;\n }\n @keyframes kui-confetti-burst {\n 0% {\n scale: 0.6;\n opacity: 0;\n }\n 40% {\n scale: var(--kui-pop-scale, 1.18);\n opacity: 1;\n }\n 100% {\n scale: 1;\n opacity: 1;\n }\n }\n @keyframes kui-copy-confirm {\n 0% {\n opacity: 0;\n }\n 15% {\n opacity: 1;\n }\n 85% {\n opacity: 1;\n }\n 100% {\n opacity: 0;\n }\n }\n @keyframes kui-pull-to-refresh {\n 0% {\n translate: 0 0;\n }\n 45% {\n translate: 0 var(--kui-pull-distance, 36px);\n }\n 100% {\n translate: 0 0;\n }\n }\n}\n\n/* src/css/numbers.css */\n@layer kui.effects {\n @keyframes kui-progress-ring {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-gauge-sweep {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-donut-sweep {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-sparkline-draw {\n from {\n stroke-dashoffset: var(--kui-path-length, 1000);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n [data-kui-fx~=progress-ring],\n [data-kui-fx~=gauge-sweep],\n [data-kui-fx~=donut-sweep],\n [data-kui-fx~=sparkline-draw] {\n stroke-dasharray: var(--kui-path-length, 100);\n fill: none;\n }\n @keyframes kui-progress-bar {\n from {\n scale: var(--kui-bar-from, 0) 1;\n }\n to {\n scale: 1 1;\n }\n }\n [data-kui-fx~=progress-bar] {\n transform-origin: left center;\n }\n [data-kui-fx~=progress-bar][data-kui-state=ready] {\n --kui-bar-from: 1 !important;\n opacity: 0 !important;\n }\n @keyframes kui-progress-segments {\n from {\n opacity: 0.18;\n }\n to {\n opacity: 1;\n }\n }\n @keyframes kui-star-rating-fill {\n from {\n clip-path: inset(0 100% 0 0);\n }\n to {\n clip-path: inset(0 calc(100% - var(--kui-fill, 100%)) 0 0);\n }\n }\n .kui-count-decorative {\n display: inline-flex;\n align-items: baseline;\n }\n .kui-odometer-col {\n display: inline-block;\n overflow: hidden;\n height: 1em;\n line-height: 1;\n vertical-align: baseline;\n }\n .kui-odometer-strip {\n display: flex;\n flex-direction: column;\n translate: 0 calc(var(--kui-o, 0) * -1em);\n transition: translate 220ms ease-out;\n }\n .kui-odometer-strip > span {\n height: 1em;\n line-height: 1;\n }\n}\n\n/* src/css/interaction.css */\n@layer kui.effects {\n @property --kui-border-angle { syntax: \"<angle>\"; inherits: false; initial-value: 0deg; }\n @property --kui-border-pct { syntax: \"<percentage>\"; inherits: false; initial-value: 0%; }\n [data-kui-fx~=lift] {\n transition: translate var(--kui-lift-duration, 220ms) var(--kui-lift-ease, ease-out);\n }\n [data-kui-fx~=lift]:focus-visible {\n translate: 0 calc(var(--kui-lift-distance, 6px) * -1);\n }\n [data-kui-fx~=pop] {\n transition: scale var(--kui-pop-duration, 220ms) var(--kui-pop-ease, ease-out);\n }\n [data-kui-fx~=pop]:focus-visible {\n scale: var(--kui-pop-scale, 1.06);\n }\n [data-kui-fx~=lift-shadow] {\n transition: translate var(--kui-lift-shadow-duration, 220ms) var(--kui-lift-shadow-ease, ease-out), box-shadow var(--kui-lift-shadow-duration, 220ms) var(--kui-lift-shadow-ease, ease-out);\n }\n [data-kui-fx~=lift-shadow]:focus-visible {\n translate: 0 calc(var(--kui-lift-distance, 6px) * -1);\n box-shadow: 0 14px 28px -12px rgb(0 0 0 / 0.45);\n }\n [data-kui-fx~=shine-sweep] {\n position: relative;\n overflow: hidden;\n }\n [data-kui-fx~=shine-sweep]::after {\n content: \"\";\n position: absolute;\n inset: 0;\n background:\n linear-gradient(\n 115deg,\n transparent 40%,\n var(--kui-c1, rgb(255 255 255 / 0.35)) 50%,\n transparent 60%);\n background-size: 220% 100%;\n background-position: 120% 0;\n pointer-events: none;\n }\n [data-kui-fx~=shine-sweep]:focus-visible::after {\n animation: kui-shine-sweep var(--kui-shine-sweep-duration, 700ms) var(--kui-shine-sweep-ease, ease-out);\n }\n @keyframes kui-shine-sweep {\n from {\n background-position: 120% 0;\n }\n to {\n background-position: -20% 0;\n }\n }\n [data-kui-fx~=split-flap] {\n display: inline-block;\n perspective: 600px;\n backface-visibility: hidden;\n }\n [data-kui-fx~=split-flap]:focus-visible {\n animation: kui-split-flap var(--kui-split-flap-duration, 600ms) var(--kui-split-flap-ease, ease-in-out);\n }\n @keyframes kui-split-flap {\n from {\n rotate: x 0deg;\n }\n to {\n rotate: x 360deg;\n }\n }\n [data-kui-fx~=border-draw] {\n border: 2px solid transparent;\n border-image-slice: 1;\n border-image-source:\n conic-gradient(\n from -90deg,\n var(--kui-border-draw-color, var(--accent, #d2691e)) 0 var(--kui-border-pct, 0%),\n transparent 0);\n transition: --kui-border-pct var(--kui-border-draw-duration, 500ms) var(--kui-border-draw-ease, ease-out);\n }\n [data-kui-fx~=border-draw]:focus-visible {\n --kui-border-pct: 100%;\n }\n [data-kui-fx~=border-glow] {\n transition: box-shadow var(--kui-border-glow-duration, 260ms) var(--kui-border-glow-ease, ease-out);\n }\n [data-kui-fx~=border-glow]:focus-visible {\n box-shadow: 0 0 0 3px var(--kui-border-glow-color, var(--accent, #d2691e));\n }\n [data-kui-fx~=beam-border],\n [data-kui-fx~=beam-border-auto] {\n position: relative;\n }\n [data-kui-fx~=beam-border]::before,\n [data-kui-fx~=beam-border-auto]::before {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: inherit;\n padding: var(--kui-beam-border-width, 3px);\n background:\n conic-gradient(\n from var(--kui-border-angle, 0deg),\n transparent 0deg,\n transparent 260deg,\n var(--kui-beam-border-c1, #ff5f6d) 282deg,\n var(--kui-beam-border-c2, #ffc371) 306deg,\n var(--kui-beam-border-c3, #4facfe) 330deg,\n var(--kui-beam-border-c4, #a855f7) 354deg,\n transparent 360deg);\n -webkit-mask: linear-gradient(#fff 0 0) content-box, linear-gradient(#fff 0 0);\n -webkit-mask-composite: xor;\n mask-composite: exclude;\n opacity: 0;\n pointer-events: none;\n transition: opacity var(--kui-beam-border-fade-duration, 200ms) ease-out;\n }\n [data-kui-fx~=beam-border]:focus-visible::before {\n opacity: 1;\n animation: kui-beam-rotate var(--kui-beam-border-duration, 4260ms) linear infinite;\n }\n [data-kui-fx~=beam-border-auto]::before {\n opacity: 1;\n animation: kui-beam-rotate var(--kui-beam-border-duration, 4260ms) linear infinite;\n }\n @keyframes kui-beam-rotate {\n to {\n --kui-border-angle: 360deg;\n }\n }\n @media (prefers-reduced-motion: reduce) {\n [data-kui-fx~=beam-border]:focus-visible::before,\n [data-kui-fx~=beam-border-auto]::before {\n animation: none;\n --kui-border-angle: 45deg;\n }\n }\n [data-kui-fx~=underline-slide] {\n position: relative;\n text-decoration: none;\n }\n [data-kui-fx~=underline-slide]::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: -0.15em;\n height: 0.08em;\n background: currentcolor;\n scale: 0 1;\n transform-origin: left center;\n transition: scale var(--kui-underline-slide-duration, 260ms) var(--kui-underline-slide-ease, ease-out);\n }\n [data-kui-fx~=underline-slide]:focus-visible::after {\n scale: 1 1;\n }\n [data-kui-fx~=underline-center] {\n position: relative;\n text-decoration: none;\n }\n [data-kui-fx~=underline-center]::after {\n content: \"\";\n position: absolute;\n left: 0;\n right: 0;\n bottom: -0.15em;\n height: 0.08em;\n background: currentcolor;\n scale: 0 1;\n transform-origin: center;\n transition: scale var(--kui-underline-center-duration, 260ms) var(--kui-underline-center-ease, ease-out);\n }\n [data-kui-fx~=underline-center]:focus-visible::after {\n scale: 1 1;\n }\n [data-kui-fx~=icon-wiggle]:focus-visible {\n animation: kui-icon-wiggle var(--kui-icon-wiggle-duration, 500ms) var(--kui-icon-wiggle-ease, ease-in-out);\n }\n @keyframes kui-icon-wiggle {\n 0%, 100% {\n rotate: 0deg;\n }\n 20% {\n rotate: -12deg;\n }\n 40% {\n rotate: 10deg;\n }\n 60% {\n rotate: -6deg;\n }\n 80% {\n rotate: 4deg;\n }\n }\n [data-kui-fx~=icon-spin]:focus-visible {\n animation: kui-icon-spin var(--kui-icon-spin-duration, 700ms) linear;\n }\n @keyframes kui-icon-spin {\n from {\n rotate: 0deg;\n }\n to {\n rotate: 360deg;\n }\n }\n [data-kui-fx~=icon-bounce]:focus-visible {\n animation: kui-icon-bounce var(--kui-icon-bounce-duration, 500ms) var(--kui-icon-bounce-ease, ease-out);\n }\n @keyframes kui-icon-bounce {\n 0%, 100% {\n translate: 0 0;\n }\n 30% {\n translate: 0 -7px;\n }\n 55% {\n translate: 0 1px;\n }\n 75% {\n translate: 0 -3px;\n }\n }\n @media (hover: hover) and (pointer: fine) {\n [data-kui-fx~=lift]:hover {\n translate: 0 calc(var(--kui-lift-distance, 6px) * -1);\n }\n [data-kui-fx~=pop]:hover {\n scale: var(--kui-pop-scale, 1.06);\n }\n [data-kui-fx~=lift-shadow]:hover {\n translate: 0 calc(var(--kui-lift-distance, 6px) * -1);\n box-shadow: 0 14px 28px -12px rgb(0 0 0 / 0.45);\n }\n [data-kui-fx~=shine-sweep]:hover::after {\n animation: kui-shine-sweep var(--kui-shine-sweep-duration, 700ms) var(--kui-shine-sweep-ease, ease-out);\n }\n [data-kui-fx~=split-flap]:hover {\n animation: kui-split-flap var(--kui-split-flap-duration, 600ms) var(--kui-split-flap-ease, ease-in-out);\n }\n [data-kui-fx~=border-draw]:hover {\n --kui-border-pct: 100%;\n }\n [data-kui-fx~=border-glow]:hover {\n box-shadow: 0 0 0 3px var(--kui-border-glow-color, var(--accent, #d2691e));\n }\n [data-kui-fx~=beam-border]:hover::before {\n opacity: 1;\n animation: kui-beam-rotate var(--kui-beam-border-duration, 4260ms) linear infinite;\n }\n [data-kui-fx~=underline-slide]:hover::after {\n scale: 1 1;\n }\n [data-kui-fx~=underline-center]:hover::after {\n scale: 1 1;\n }\n [data-kui-fx~=icon-wiggle]:hover {\n animation: kui-icon-wiggle var(--kui-icon-wiggle-duration, 500ms) var(--kui-icon-wiggle-ease, ease-in-out);\n }\n [data-kui-fx~=icon-spin]:hover {\n animation: kui-icon-spin var(--kui-icon-spin-duration, 700ms) linear;\n }\n [data-kui-fx~=icon-bounce]:hover {\n animation: kui-icon-bounce var(--kui-icon-bounce-duration, 500ms) var(--kui-icon-bounce-ease, ease-out);\n }\n }\n [data-kui-fx~=tilt-3d],\n [data-kui-fx~=tilt-parallax] {\n transform-style: preserve-3d;\n }\n [data-kui-fx~=cursor-spotlight]::before {\n content: \"\";\n position: absolute;\n inset: 0;\n border-radius: inherit;\n pointer-events: none;\n opacity: var(--kui-spotlight-opacity, 0);\n transition: opacity 200ms ease-out;\n background:\n radial-gradient(\n circle 160px at var(--kui-x, 50%) var(--kui-y, 50%),\n color-mix(in srgb, var(--accent, #d2691e) 30%, transparent),\n transparent 70%);\n }\n .kui-cursor-dot {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 9999;\n display: grid;\n place-items: center;\n pointer-events: none;\n opacity: 0;\n transition: opacity 160ms ease-out;\n }\n .kui-cursor-dot-active {\n opacity: 1;\n }\n .kui-cursor-dot-follow,\n .kui-cursor-dot-lag,\n .kui-cursor-dot-invert {\n width: 14px;\n height: 14px;\n margin: -7px 0 0 -7px;\n border-radius: 50%;\n background: var(--accent, #d2691e);\n }\n .kui-cursor-dot-invert {\n background: var(--kui-invert-color, #fff);\n mix-blend-mode: difference;\n }\n .kui-cursor-dot-label {\n margin: -1.4em 0 0 -1.4em;\n padding: 0.4em 0.8em;\n border-radius: 999px;\n background: var(--accent, #d2691e);\n color: var(--kui-label-color, #fff);\n font-size: 0.75rem;\n font-family:\n ui-monospace,\n Menlo,\n monospace;\n white-space: nowrap;\n }\n @media (pointer: coarse) {\n .kui-cursor-dot {\n display: none;\n }\n }\n}\n\n/* src/css/layout.css */\n@layer kui.effects {\n [data-kui-fx~=accordion-height] {\n overflow: hidden;\n }\n [data-kui-fx~=accordion-height]:not([data-open]) {\n height: 0;\n }\n}\n\n/* src/css/svg.css */\n@layer kui.effects {\n @keyframes kui-draw-stroke {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-draw-signature {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-draw-underline {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-checkmark-draw {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-cross-draw {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n @keyframes kui-chart-line-draw {\n from {\n stroke-dashoffset: var(--kui-path-length, 100);\n }\n to {\n stroke-dashoffset: 0;\n }\n }\n [data-kui-fx~=draw-stroke],\n [data-kui-fx~=draw-signature],\n [data-kui-fx~=draw-underline],\n [data-kui-fx~=checkmark-draw],\n [data-kui-fx~=cross-draw],\n [data-kui-fx~=chart-line-draw] {\n stroke-dasharray: var(--kui-path-length, 100);\n fill: none;\n }\n @keyframes kui-gradient-stroke {\n from {\n stroke: var(--kui-stroke-from, currentColor);\n }\n 50% {\n stroke: var(--kui-stroke-via, currentColor);\n }\n to {\n stroke: var(--kui-stroke-to, currentColor);\n }\n }\n [data-kui-fx~=gradient-stroke] {\n --kui-fx-gradient-stroke-iterations: infinite;\n }\n @keyframes kui-heart-fill {\n from {\n clip-path: inset(100% 0 0 0);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n @keyframes kui-bookmark-fill {\n from {\n clip-path: inset(100% 0 0 0);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n @keyframes kui-chart-area-fill {\n from {\n clip-path: inset(0 100% 0 0);\n }\n to {\n clip-path: inset(0 0 0 0);\n }\n }\n @keyframes kui-chart-bar-grow {\n from {\n scale: 1 var(--kui-bar-from, 0);\n }\n to {\n scale: 1 1;\n }\n }\n [data-kui-fx~=chart-bar-grow] {\n transform-origin: bottom center;\n }\n [data-kui-fx~=chart-bar-grow][data-kui-state=ready] {\n --kui-bar-from: 1 !important;\n opacity: 0 !important;\n }\n @keyframes kui-logo-build {\n from {\n opacity: 0;\n scale: 0.62;\n rotate: -8deg;\n }\n to {\n opacity: 1;\n scale: 1;\n rotate: 0deg;\n }\n }\n [data-kui-fx~=hamburger-to-x] .kui-bar {\n transition:\n translate var(--kui-icon-toggle-duration, 260ms) var(--kui-icon-toggle-ease, ease-out),\n rotate var(--kui-icon-toggle-duration, 260ms) var(--kui-icon-toggle-ease, ease-out),\n opacity var(--kui-icon-toggle-duration, 260ms) var(--kui-icon-toggle-ease, ease-out);\n }\n [data-kui-fx~=hamburger-to-x][aria-expanded=true] .kui-bar:nth-child(1) {\n translate: 0 var(--kui-bar-gap, 6px);\n rotate: 45deg;\n }\n [data-kui-fx~=hamburger-to-x][aria-expanded=true] .kui-bar:nth-child(2) {\n opacity: 0;\n }\n [data-kui-fx~=hamburger-to-x][aria-expanded=true] .kui-bar:nth-child(3) {\n translate: 0 calc(var(--kui-bar-gap, 6px) * -1);\n rotate: -45deg;\n }\n [data-kui-fx~=play-to-pause] .kui-bar {\n transition: translate var(--kui-icon-toggle-duration, 260ms) var(--kui-icon-toggle-ease, ease-out), clip-path var(--kui-icon-toggle-duration, 260ms) var(--kui-icon-toggle-ease, ease-out);\n }\n [data-kui-fx~=play-to-pause]:not([aria-pressed=true]) .kui-bar:nth-child(1) {\n translate: var(--kui-bar-gap, 4px) 0;\n clip-path: polygon(0 0, 100% 25%, 100% 75%, 0 100%);\n }\n [data-kui-fx~=play-to-pause]:not([aria-pressed=true]) .kui-bar:nth-child(2) {\n translate: calc(var(--kui-bar-gap, 4px) * -1) 0;\n clip-path: polygon(0 25%, 100% 50%, 100% 50%, 0 75%);\n }\n [data-kui-fx~=plus-to-minus] {\n transition: rotate var(--kui-icon-toggle-duration, 260ms) var(--kui-icon-toggle-ease, ease-out);\n }\n [data-kui-fx~=plus-to-minus] .kui-bar {\n transition: scale var(--kui-icon-toggle-duration, 260ms) var(--kui-icon-toggle-ease, ease-out);\n }\n [data-kui-fx~=plus-to-minus] .kui-bar:nth-child(2) {\n rotate: 90deg;\n }\n [data-kui-fx~=plus-to-minus][aria-expanded=true] {\n rotate: 90deg;\n }\n [data-kui-fx~=plus-to-minus][aria-expanded=true] .kui-bar:nth-child(1) {\n scale: 0;\n }\n}\n\n/* src/css/index.css */\n"
|
|
5375
6411
|
document.head.appendChild(style)
|
|
5376
6412
|
}
|
|
5377
6413
|
window.__kuinetic = kuinetic.kuinetic({ observe: true }).start()
|