@heyramzi/ui 7.0.0 → 8.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/COMPONENTS.md +28 -17
- package/README.md +6 -2
- package/package.json +25 -15
- package/scripts/sync-shadcn.mjs +17 -13
- package/scripts/sync-transitions.mjs +11 -11
- package/src/agents/agent-avatar.svelte +67 -114
- package/src/agents/agent-cast.svelte +31 -7
- package/src/agents/demo.svelte +55 -8
- package/src/agents/helpers.ts +58 -0
- package/src/agents/page-state.ts +70 -0
- package/src/agents/types.ts +3 -1
- package/src/ai/ai-button/AiButton.svelte +86 -0
- package/src/ai/ai-button/index.ts +4 -0
- package/src/ai/confirmation/Confirmation.svelte +8 -8
- package/src/ai/confirmation/confirmation-context.svelte.ts +2 -2
- package/src/ai/generation-progress/GenerationProgress.svelte +354 -0
- package/src/ai/generation-progress/index.ts +7 -0
- package/src/ai/index.ts +16 -6
- package/src/ai/prompt-input/PromptInput.svelte +19 -1
- package/src/ai/prompt-input/PromptInputSubmit.svelte +9 -3
- package/src/ai/reasoning/Reasoning.svelte +11 -8
- package/src/ambient.d.ts +4 -0
- package/src/animations/README.md +14 -14
- package/src/animations/index.css +3 -14
- package/src/animations/upstream-coverage.test.ts +1 -1
- package/src/components/copy/clipboard.test.ts +206 -0
- package/src/components/copy/clipboard.ts +49 -0
- package/src/components/copy/copied.svelte.ts +39 -0
- package/src/components/copy/copy-button.svelte +175 -0
- package/src/components/copy/copy-button.test.ts +110 -0
- package/src/components/copy/index.ts +3 -0
- package/src/components/data-table/data-table.test.ts +134 -0
- package/src/components/data-table/data-table.ts +77 -0
- package/src/components/data-table/index.ts +20 -0
- package/src/components/data-table/infinite-scroll.svelte +69 -0
- package/src/components/data-table/pagination.svelte +62 -0
- package/src/components/data-table/row-arrow.svelte +28 -0
- package/src/components/data-table/row-context-menu.svelte +106 -0
- package/src/components/data-table/row-context-menu.test.ts +18 -0
- package/src/components/data-table/sortable-head.svelte +56 -0
- package/src/components/data-table/table-skeleton.svelte +83 -0
- package/src/components/hold-to-confirm/hold-to-confirm.svelte +232 -0
- package/src/components/hold-to-confirm/index.ts +1 -0
- package/src/components/icon/icon.svelte +23 -0
- package/src/components/icon/index.ts +1 -0
- package/src/components/language-flag/index.ts +1 -0
- package/src/components/language-flag/language-flag.svelte +60 -0
- package/src/components/list-page/detail-empty.svelte +50 -0
- package/src/components/list-page/detail-header.svelte +107 -0
- package/src/components/list-page/detail-panel.svelte +90 -0
- package/src/components/list-page/detail-row.svelte +36 -0
- package/src/components/list-page/detail-stack.svelte +33 -0
- package/src/components/list-page/empty-state.svelte +91 -0
- package/src/components/list-page/filter-item.svelte +49 -0
- package/src/components/list-page/filter-popover.svelte +88 -0
- package/src/components/list-page/filter-section.ts +12 -0
- package/src/components/list-page/grouped-list.svelte +116 -0
- package/src/components/list-page/index.ts +28 -0
- package/src/components/list-page/list-page-shell.svelte +195 -0
- package/src/components/list-page/list-table.ts +19 -0
- package/src/components/list-page/master-detail.svelte +206 -0
- package/src/components/list-page/master-detail.test.ts +37 -0
- package/src/components/list-page/notice-bar.svelte +68 -0
- package/src/components/list-page/prev-next.svelte +104 -0
- package/src/components/list-page/queue-rail.ts +25 -0
- package/src/components/list-page/rail-body.svelte +29 -0
- package/src/components/list-page/rail-empty.svelte +51 -0
- package/src/components/list-page/rail-head.svelte +49 -0
- package/src/components/list-page/rail-row.svelte +163 -0
- package/src/components/list-page/section-host.ts +24 -0
- package/src/components/list-page/section-label.svelte +39 -0
- package/src/components/list-page/step.test.ts +21 -0
- package/src/components/list-page/step.ts +10 -0
- package/src/components/list-page/toolbar-search.svelte +63 -0
- package/src/components/list-page/toolbar-trigger.ts +23 -0
- package/src/components/list-page/types.ts +1 -0
- package/src/components/locale-switch/index.ts +1 -0
- package/src/components/locale-switch/locale-switch.svelte +59 -0
- package/src/components/mark/index.ts +1 -0
- package/src/components/mark/mark.svelte +70 -0
- package/src/components/open-in/index.ts +6 -0
- package/src/components/open-in/open-in.svelte +106 -0
- package/src/components/picker/index.ts +4 -0
- package/src/components/picker/mark-picker.svelte +84 -0
- package/src/components/picker/picker.svelte +143 -0
- package/src/components/picker/trigger.ts +42 -0
- package/src/components/picker/types.ts +26 -0
- package/src/components/segmented/animated-tabs.svelte +175 -0
- package/src/components/segmented/collapse.test.ts +49 -0
- package/src/components/segmented/collapse.ts +39 -0
- package/src/components/segmented/index.ts +41 -0
- package/src/components/segmented/section-runs.svelte +79 -0
- package/src/components/segmented/segment.svelte +106 -0
- package/src/components/segmented/segmented-filter.svelte +125 -0
- package/src/components/segmented/segmented-nav.svelte +82 -0
- package/src/components/segmented/segmented-overflow.svelte +85 -0
- package/src/components/segmented/segmented-track.svelte +181 -0
- package/src/components/segmented/segmented.test.ts +20 -0
- package/src/components/segmented/segmented.ts +80 -0
- package/src/components/star-rating-input/index.ts +9 -0
- package/src/components/star-rating-input/star-rating-input.svelte +256 -0
- package/src/components/svg/index.ts +1 -0
- package/src/components/svg/svg.svelte +9 -0
- package/src/effects/border-beam/BorderBeam.svelte +1 -1
- package/src/effects/image-comparison/ImageComparison.css +42 -8
- package/src/effects/image-comparison/ImageComparison.svelte +138 -21
- package/src/effects/image-comparison/compare.test.ts +17 -0
- package/src/effects/image-comparison/compare.ts +5 -0
- package/src/effects/interactive-hover-button/InteractiveHoverButton.svelte +338 -0
- package/src/effects/magic-card/MagicCard.css +47 -0
- package/src/effects/magic-card/MagicCard.svelte +57 -0
- package/src/effects/marquee/Marquee.css +27 -1
- package/src/effects/marquee/Marquee.svelte +67 -3
- package/src/effects/reveal/index.ts +2 -1
- package/src/effects/reveal/observe.test.ts +60 -0
- package/src/effects/reveal/observe.ts +33 -1
- package/src/effects/reveal/types.ts +7 -0
- package/src/effects/theme-toggle/ThemeToggle.css +199 -6
- package/src/effects/theme-toggle/ThemeToggle.svelte +51 -26
- package/src/gallery.test.ts +52 -0
- package/src/index.ts +5 -1
- package/src/lib/panel.ts +7 -1
- package/src/lib/theme-transition.ts +37 -11
- package/src/lib/tone.ts +48 -0
- package/src/shadcn/accordion/accordion-trigger.svelte +15 -6
- package/src/shadcn/alert/alert.svelte +3 -1
- package/src/shadcn/badge/badge.svelte +8 -7
- package/src/shadcn/breadcrumb/breadcrumb-ellipsis.svelte +2 -2
- package/src/shadcn/breadcrumb/breadcrumb-separator.svelte +2 -2
- package/src/shadcn/calendar/calendar-month-select.svelte +2 -2
- package/src/shadcn/calendar/calendar-next-button.svelte +2 -2
- package/src/shadcn/calendar/calendar-prev-button.svelte +2 -2
- package/src/shadcn/calendar/calendar-year-select.svelte +2 -2
- package/src/shadcn/calendar/calendar.svelte +6 -0
- package/src/shadcn/code-block/code-block-copy-button.svelte +6 -55
- package/src/shadcn/command/index.ts +3 -0
- package/src/shadcn/field/index.ts +3 -0
- package/src/shadcn/field/simple-field.svelte +71 -0
- package/src/shadcn/field/simple-field.test.ts +47 -0
- package/src/shadcn/message-scroller/message-scroller-button.svelte +2 -2
- package/src/shadcn/radio-group/radio-group-item.svelte +3 -2
- package/src/shadcn/sheet/sheet-content.svelte +1 -0
- package/src/shadcn/sheet/sheet.css +48 -0
- package/src/shadcn/sonner/sonner.svelte +7 -10
- package/src/shadcn/toggle-group/toggle-group.svelte +10 -3
- package/src/shadcn/trace/trace-collapsible-trigger.svelte +2 -2
- package/src/ai/composer/Composer.css +0 -108
- package/src/ai/composer/Composer.svelte +0 -111
- package/src/ai/composer/index.ts +0 -10
- package/src/animations/accordion.css +0 -58
- package/src/animations/icon-swap.css +0 -43
- package/src/animations/notification-badge.css +0 -81
- package/src/animations/panel.css +0 -86
- package/src/animations/reasoning-stream.css +0 -49
- package/src/animations/skeleton-reveal.css +0 -97
- package/src/animations/streaming-text.css +0 -31
- package/src/animations/tabs-sliding.css +0 -83
- package/src/animations/texts-reveal.css +0 -70
- package/src/animations/tooltip.css +0 -72
- package/src/animations/view-transition-reveal.ts +0 -74
- package/src/lib/utils.ts +0 -45
- package/src/showcase/AiSection.svelte +0 -150
- package/src/showcase/AnimationsSection.svelte +0 -1658
- package/src/showcase/EffectsSection.svelte +0 -152
- package/src/showcase/ShadcnSection.svelte +0 -27
- package/src/showcase/ShowcaseImport.svelte +0 -126
- package/src/showcase/ShowcaseList.svelte +0 -132
- package/src/showcase/ShowcaseNav.svelte +0 -247
- package/src/showcase/ShowcaseSection.svelte +0 -112
- package/src/showcase/ShowcaseShell.svelte +0 -55
- package/src/showcase/ShowcaseStage.svelte +0 -342
- package/src/showcase/ShowcaseVariant.svelte +0 -109
- package/src/showcase/assets/image-reveal/art-1.jpg +0 -0
- package/src/showcase/assets/image-reveal/art-2.jpg +0 -0
- package/src/showcase/assets/image-reveal/art-3.jpg +0 -0
- package/src/showcase/check.svg +0 -1
- package/src/showcase/chevron-arms.svg +0 -2
- package/src/showcase/chevron-down.svg +0 -1
- package/src/showcase/copy.svg +0 -2
- package/src/showcase/demos/ai/confirmation.svelte +0 -59
- package/src/showcase/demos/ai/loading-state.svelte +0 -19
- package/src/showcase/demos/ai/prompt-input.svelte +0 -57
- package/src/showcase/demos/ai/reasoning.svelte +0 -19
- package/src/showcase/demos/ai/thinking-dots.svelte +0 -15
- package/src/showcase/demos/ai/voice-waveform.svelte +0 -24
- package/src/showcase/demos/effects/animated-beam.svelte +0 -50
- package/src/showcase/demos/effects/animated-group.svelte +0 -47
- package/src/showcase/demos/effects/border-beam-default.svelte +0 -20
- package/src/showcase/demos/effects/border-beam-line.svelte +0 -20
- package/src/showcase/demos/effects/border-beam-mono.svelte +0 -20
- package/src/showcase/demos/effects/border-beam-sunset.svelte +0 -20
- package/src/showcase/demos/effects/image-comparison.svelte +0 -25
- package/src/showcase/demos/effects/image-reveal.svelte +0 -49
- package/src/showcase/demos/effects/in-view.svelte +0 -41
- package/src/showcase/demos/effects/integrations-hub.svelte +0 -82
- package/src/showcase/demos/effects/magnetic.svelte +0 -31
- package/src/showcase/demos/effects/marquee.svelte +0 -33
- package/src/showcase/demos/effects/progressive-blur.svelte +0 -47
- package/src/showcase/demos/effects/spotlight.svelte +0 -40
- package/src/showcase/demos/effects/text-effect.svelte +0 -55
- package/src/showcase/demos/shadcn/accordion.svelte +0 -45
- package/src/showcase/demos/shadcn/alert-dialog.svelte +0 -23
- package/src/showcase/demos/shadcn/alert.svelte +0 -30
- package/src/showcase/demos/shadcn/attachment.svelte +0 -71
- package/src/showcase/demos/shadcn/avatar.svelte +0 -30
- package/src/showcase/demos/shadcn/badge.svelte +0 -26
- package/src/showcase/demos/shadcn/breadcrumb.svelte +0 -34
- package/src/showcase/demos/shadcn/bubble.svelte +0 -36
- package/src/showcase/demos/shadcn/button.svelte +0 -11
- package/src/showcase/demos/shadcn/calendar.svelte +0 -8
- package/src/showcase/demos/shadcn/card.svelte +0 -39
- package/src/showcase/demos/shadcn/checkbox.svelte +0 -39
- package/src/showcase/demos/shadcn/code-block.svelte +0 -80
- package/src/showcase/demos/shadcn/collapsible.svelte +0 -20
- package/src/showcase/demos/shadcn/command.svelte +0 -48
- package/src/showcase/demos/shadcn/context-menu.svelte +0 -54
- package/src/showcase/demos/shadcn/demo-harness.svelte +0 -12
- package/src/showcase/demos/shadcn/demos.test.ts +0 -20
- package/src/showcase/demos/shadcn/dialog.svelte +0 -38
- package/src/showcase/demos/shadcn/dropdown-menu.svelte +0 -59
- package/src/showcase/demos/shadcn/empty.svelte +0 -29
- package/src/showcase/demos/shadcn/field.svelte +0 -115
- package/src/showcase/demos/shadcn/hover-card.svelte +0 -32
- package/src/showcase/demos/shadcn/index.ts +0 -382
- package/src/showcase/demos/shadcn/input-otp.svelte +0 -19
- package/src/showcase/demos/shadcn/input.svelte +0 -5
- package/src/showcase/demos/shadcn/label.svelte +0 -11
- package/src/showcase/demos/shadcn/marker.svelte +0 -30
- package/src/showcase/demos/shadcn/message-scroller.svelte +0 -44
- package/src/showcase/demos/shadcn/message.svelte +0 -75
- package/src/showcase/demos/shadcn/popover.svelte +0 -36
- package/src/showcase/demos/shadcn/progress.svelte +0 -13
- package/src/showcase/demos/shadcn/radio-group.svelte +0 -19
- package/src/showcase/demos/shadcn/scroll-area.svelte +0 -18
- package/src/showcase/demos/shadcn/select.svelte +0 -29
- package/src/showcase/demos/shadcn/separator.svelte +0 -12
- package/src/showcase/demos/shadcn/sheet.svelte +0 -48
- package/src/showcase/demos/shadcn/skeleton.svelte +0 -11
- package/src/showcase/demos/shadcn/slider.svelte +0 -7
- package/src/showcase/demos/shadcn/sonner.svelte +0 -18
- package/src/showcase/demos/shadcn/spinner.svelte +0 -11
- package/src/showcase/demos/shadcn/switch.svelte +0 -9
- package/src/showcase/demos/shadcn/table.svelte +0 -76
- package/src/showcase/demos/shadcn/tabs.svelte +0 -62
- package/src/showcase/demos/shadcn/textarea.svelte +0 -5
- package/src/showcase/demos/shadcn/toggle-group.svelte +0 -18
- package/src/showcase/demos/shadcn/toggle.svelte +0 -14
- package/src/showcase/demos/shadcn/tooltip.svelte +0 -13
- package/src/showcase/demos/shadcn/trace.svelte +0 -51
- package/src/showcase/heart.svg +0 -1
- package/src/showcase/index.ts +0 -38
- package/src/showcase/kit.test.ts +0 -72
- package/src/showcase/kit.ts +0 -16
- package/src/showcase/plus.svg +0 -1
- package/src/showcase/showcase-shell.css +0 -91
- package/src/showcase/stacked-section.css +0 -15
- package/src/showcase/success-check.svg +0 -1
- package/src/showcase/types.ts +0 -29
- package/src/svg-raw.d.ts +0 -7
|
@@ -1,1658 +0,0 @@
|
|
|
1
|
-
<!-- ========================== -->
|
|
2
|
-
<!-- IMPORTS -->
|
|
3
|
-
<!-- ========================== -->
|
|
4
|
-
<script lang="ts">
|
|
5
|
-
import { untrack } from "svelte";
|
|
6
|
-
import { swapText } from "../animations/text-swap.js";
|
|
7
|
-
import Bell from "@lucide/svelte/icons/bell";
|
|
8
|
-
import Info from "@lucide/svelte/icons/info";
|
|
9
|
-
import Menu from "@lucide/svelte/icons/menu";
|
|
10
|
-
import X from "@lucide/svelte/icons/x";
|
|
11
|
-
import ShowcaseStage from "./ShowcaseStage.svelte";
|
|
12
|
-
import chevronArms from "./chevron-arms.svg?raw";
|
|
13
|
-
import chevronDown from "./chevron-down.svg?raw";
|
|
14
|
-
import heart from "./heart.svg?raw";
|
|
15
|
-
import plus from "./plus.svg?raw";
|
|
16
|
-
import successCheck from "./success-check.svg?raw";
|
|
17
|
-
|
|
18
|
-
// =========================
|
|
19
|
-
// CONST
|
|
20
|
-
// =========================
|
|
21
|
-
const CLEAR_TEXT = "project deadline";
|
|
22
|
-
|
|
23
|
-
// =========================
|
|
24
|
-
// STATE
|
|
25
|
-
// =========================
|
|
26
|
-
let target = null;
|
|
27
|
-
const phrases = [
|
|
28
|
-
"Build the system.",
|
|
29
|
-
"Ship the route.",
|
|
30
|
-
"Verify the output.",
|
|
31
|
-
"Repeat tomorrow.",
|
|
32
|
-
];
|
|
33
|
-
let cursor = 0;
|
|
34
|
-
|
|
35
|
-
let digitGroup = null;
|
|
36
|
-
let digitAnimating = $state(false);
|
|
37
|
-
let digitValue = $state("1234");
|
|
38
|
-
|
|
39
|
-
let resizeSmall = $state(false);
|
|
40
|
-
let badgeOpen = $state(true);
|
|
41
|
-
let badgeCount = $state(3);
|
|
42
|
-
let activePage = $state<"1" | "2">("1");
|
|
43
|
-
|
|
44
|
-
let modalOpen = $state(true);
|
|
45
|
-
let dropdownOpen = $state(true);
|
|
46
|
-
let panelOpen = $state(true);
|
|
47
|
-
let iconState = $state<"a" | "b">("a");
|
|
48
|
-
|
|
49
|
-
let checkEl = null;
|
|
50
|
-
|
|
51
|
-
let avatarRoot = null;
|
|
52
|
-
// Dummy team members so the hover-lift reads as a real avatar stack.
|
|
53
|
-
const avatars = [
|
|
54
|
-
{ initials: "RK", hue: 24 },
|
|
55
|
-
{ initials: "KA", hue: 158 },
|
|
56
|
-
{ initials: "AM", hue: 268 },
|
|
57
|
-
{ initials: "MT", hue: 334 },
|
|
58
|
-
{ initials: "ZL", hue: 200 },
|
|
59
|
-
];
|
|
60
|
-
|
|
61
|
-
let shakeWrap = null;
|
|
62
|
-
let shakeInput = null;
|
|
63
|
-
let shakeRevert;
|
|
64
|
-
|
|
65
|
-
let clearWrap = null;
|
|
66
|
-
let clearInput = null;
|
|
67
|
-
let clearMirror = null;
|
|
68
|
-
let clearPhold = null;
|
|
69
|
-
let clearGlow = null;
|
|
70
|
-
let clearBusy = false;
|
|
71
|
-
|
|
72
|
-
let skelEl = null;
|
|
73
|
-
let skelSkeleton = null;
|
|
74
|
-
|
|
75
|
-
let tabsBar = null;
|
|
76
|
-
let tabsPill = null;
|
|
77
|
-
const tabs = ["Plan", "Debug", "Ask"];
|
|
78
|
-
let activeTab = $state(0);
|
|
79
|
-
|
|
80
|
-
let staggerEl = null;
|
|
81
|
-
|
|
82
|
-
// =========================
|
|
83
|
-
// EFFECTS
|
|
84
|
-
// =========================
|
|
85
|
-
$effect(() => {
|
|
86
|
-
const checkPath = checkEl?.querySelector("path");
|
|
87
|
-
if (!checkPath) return;
|
|
88
|
-
const len = Math.ceil(checkPath.getTotalLength());
|
|
89
|
-
checkPath.style.strokeDasharray = String(len);
|
|
90
|
-
checkPath.style.strokeDashoffset = String(len);
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
$effect(() => {
|
|
94
|
-
untrack(() => positionTabsPill(false));
|
|
95
|
-
const onResize = () => untrack(() => positionTabsPill(false));
|
|
96
|
-
window.addEventListener("resize", onResize);
|
|
97
|
-
return () => window.removeEventListener("resize", onResize);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
// =========================
|
|
101
|
-
// FUNCTIONS
|
|
102
|
-
// =========================
|
|
103
|
-
function cssNum(name: string, fallback: number) {
|
|
104
|
-
const v = parseFloat(getComputedStyle(document.documentElement).getPropertyValue(name));
|
|
105
|
-
return Number.isFinite(v) ? v : fallback;
|
|
106
|
-
}
|
|
107
|
-
function nextPhrase() {
|
|
108
|
-
if (!target) return;
|
|
109
|
-
cursor = (cursor + 1) % phrases.length;
|
|
110
|
-
swapText(target, phrases[cursor]);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function replayDigits() {
|
|
114
|
-
if (!digitGroup) return;
|
|
115
|
-
digitAnimating = false;
|
|
116
|
-
digitValue = String(Math.floor(1000 + Math.random() * 8999));
|
|
117
|
-
// WHY: force reflow so removing+re-adding .is-animating restarts the keyframes
|
|
118
|
-
void digitGroup.offsetWidth;
|
|
119
|
-
digitAnimating = true;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
function bumpBadge() {
|
|
123
|
-
badgeOpen = false;
|
|
124
|
-
setTimeout(() => {
|
|
125
|
-
badgeCount += 1;
|
|
126
|
-
badgeOpen = true;
|
|
127
|
-
}, 220);
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function togglePage() {
|
|
131
|
-
activePage = activePage === "1" ? "2" : "1";
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
function replayCheck() {
|
|
135
|
-
if (!checkEl) return;
|
|
136
|
-
checkEl.setAttribute("data-state", "out");
|
|
137
|
-
// WHY: force reflow so the appear keyframes restart from offset 0
|
|
138
|
-
void checkEl.offsetWidth;
|
|
139
|
-
checkEl.setAttribute("data-state", "in");
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
function liftAvatars(activeIdx: number | null) {
|
|
143
|
-
if (!avatarRoot) return;
|
|
144
|
-
const lift = cssNum("--avatar-lift", -4);
|
|
145
|
-
const falloff = cssNum("--avatar-falloff", 0.45);
|
|
146
|
-
const scale = cssNum("--avatar-scale", 1.05);
|
|
147
|
-
const ease = "cubic-bezier(0.22, 1, 0.36, 1)";
|
|
148
|
-
avatarRoot.querySelectorAll(".t-avatar").forEach((el, i) => {
|
|
149
|
-
el.style.transitionTimingFunction = ease;
|
|
150
|
-
if (activeIdx === null) {
|
|
151
|
-
el.style.setProperty("--shift", "0px");
|
|
152
|
-
el.style.setProperty("--scale-active", "1");
|
|
153
|
-
return;
|
|
154
|
-
}
|
|
155
|
-
const d = Math.abs(i - activeIdx);
|
|
156
|
-
el.style.setProperty("--shift", `${(lift * Math.pow(falloff, d)).toFixed(3)}px`);
|
|
157
|
-
el.style.setProperty("--scale-active", i === activeIdx ? String(scale) : "1");
|
|
158
|
-
});
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function showError() {
|
|
162
|
-
if (!shakeWrap || !shakeInput) return;
|
|
163
|
-
shakeWrap.classList.add("is-error");
|
|
164
|
-
shakeInput.classList.add("is-error");
|
|
165
|
-
// Replay the shake from a clean baseline.
|
|
166
|
-
shakeInput.classList.remove("is-shaking");
|
|
167
|
-
void shakeInput.offsetWidth;
|
|
168
|
-
shakeInput.classList.add("is-shaking");
|
|
169
|
-
const shakeMs = cssNum("--shake-dur-a", 80) * 2 + cssNum("--shake-dur-b", 60) * 2;
|
|
170
|
-
setTimeout(() => shakeInput?.classList.remove("is-shaking"), shakeMs + 20);
|
|
171
|
-
if (shakeRevert) clearTimeout(shakeRevert);
|
|
172
|
-
const hold = cssNum("--revert-hold", 3000);
|
|
173
|
-
shakeRevert = setTimeout(() => {
|
|
174
|
-
shakeWrap?.classList.remove("is-error");
|
|
175
|
-
shakeInput?.classList.remove("is-error");
|
|
176
|
-
}, shakeMs + hold);
|
|
177
|
-
}
|
|
178
|
-
|
|
179
|
-
// Minimal cubic-bezier sampler so the JS easing matches the CSS curves.
|
|
180
|
-
function cubicBezier(str: string) {
|
|
181
|
-
const m = str.match(/cubic-bezier\(([-\d.]+),\s*([-\d.]+),\s*([-\d.]+),\s*([-\d.]+)\)/);
|
|
182
|
-
if (!m) return (t: number) => t;
|
|
183
|
-
const [x1, y1, x2, y2] = m.slice(1).map(Number);
|
|
184
|
-
const cx = 3 * x1;
|
|
185
|
-
const bx = 3 * (x2 - x1) - cx;
|
|
186
|
-
const ax = 1 - cx - bx;
|
|
187
|
-
const cy = 3 * y1;
|
|
188
|
-
const by = 3 * (y2 - y1) - cy;
|
|
189
|
-
const ay = 1 - cy - by;
|
|
190
|
-
return (t: number) => {
|
|
191
|
-
if (t <= 0) return 0;
|
|
192
|
-
if (t >= 1) return 1;
|
|
193
|
-
let s = t;
|
|
194
|
-
for (let i = 0; i < 8; i++) {
|
|
195
|
-
const dx = ((ax * s + bx) * s + cx) * s - t;
|
|
196
|
-
const d = (3 * ax * s + 2 * bx) * s + cx;
|
|
197
|
-
if (Math.abs(dx) < 1e-6 || d === 0) break;
|
|
198
|
-
s -= dx / d;
|
|
199
|
-
}
|
|
200
|
-
return ((ay * s + by) * s + cy) * s;
|
|
201
|
-
};
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
function buildClearGlow(text: string, isDark: boolean) {
|
|
205
|
-
if (!clearInput || !clearWrap) return "";
|
|
206
|
-
const ctx = document.createElement("canvas").getContext("2d");
|
|
207
|
-
if (!ctx) return "";
|
|
208
|
-
ctx.font = getComputedStyle(clearInput).font;
|
|
209
|
-
const rgb = isDark ? "255,255,255" : "0,0,0";
|
|
210
|
-
const w = clearWrap.clientWidth || 280;
|
|
211
|
-
const padLeft = parseFloat(getComputedStyle(clearInput).paddingLeft) || 12;
|
|
212
|
-
const spread = cssNum("--glow-spread", 1.5);
|
|
213
|
-
const layers: string[] = [];
|
|
214
|
-
let x = 0;
|
|
215
|
-
text.split(/(\s+)/).forEach((seg) => {
|
|
216
|
-
const segW = ctx.measureText(seg).width;
|
|
217
|
-
if (seg.trim()) {
|
|
218
|
-
const cx = padLeft + x + segW / 2;
|
|
219
|
-
const hw = Math.max(segW * 0.45, 8) * spread;
|
|
220
|
-
(
|
|
221
|
-
[
|
|
222
|
-
[0, 0.8, 7, 0.22],
|
|
223
|
-
[hw * 0.45, 0.55, 8, 0.18],
|
|
224
|
-
[-hw * 0.4, 0.65, 6, 0.16],
|
|
225
|
-
[hw * 0.15, 0.9, 5, 0.14],
|
|
226
|
-
] as const
|
|
227
|
-
).forEach(([dx, rwm, rh, a]) => {
|
|
228
|
-
const lx = (((cx + dx) / w) * 100).toFixed(2);
|
|
229
|
-
layers.push(
|
|
230
|
-
`radial-gradient(ellipse ${Math.max(hw * rwm, 2).toFixed(1)}px ${rh}px at ${lx}% 100%, rgba(${rgb},${a}), transparent)`,
|
|
231
|
-
);
|
|
232
|
-
});
|
|
233
|
-
}
|
|
234
|
-
x += segW;
|
|
235
|
-
});
|
|
236
|
-
return layers.join(", ");
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
function triggerClear() {
|
|
240
|
-
if (clearBusy || !clearWrap || !clearInput || !clearMirror || !clearPhold || !clearGlow) return;
|
|
241
|
-
// Repeatable demo: an empty field refills instantly instead of clearing.
|
|
242
|
-
if (!clearInput.value) {
|
|
243
|
-
clearInput.value = CLEAR_TEXT;
|
|
244
|
-
clearMirror.textContent = CLEAR_TEXT;
|
|
245
|
-
clearWrap.classList.add("has-value");
|
|
246
|
-
return;
|
|
247
|
-
}
|
|
248
|
-
clearBusy = true;
|
|
249
|
-
const isDark = !document.documentElement.classList.contains("light");
|
|
250
|
-
const total = cssNum("--clear-dur", 1000);
|
|
251
|
-
const outDur = cssNum("--clear-out-dur", 400);
|
|
252
|
-
const inDur = cssNum("--clear-in-dur", 400);
|
|
253
|
-
const outFly = cssNum("--clear-out-fly", 12);
|
|
254
|
-
const inFly = cssNum("--clear-in-fly", 12);
|
|
255
|
-
const blur = cssNum("--clear-blur", 2);
|
|
256
|
-
const delay = cssNum("--glow-delay", 50);
|
|
257
|
-
const peakAt = cssNum("--glow-peak-at", 0.15);
|
|
258
|
-
const gOp = isDark ? 0.85 : cssNum("--glow-opacity", 0.42);
|
|
259
|
-
const cs = getComputedStyle(document.documentElement);
|
|
260
|
-
const easeOut = cubicBezier(cs.getPropertyValue("--clear-out-ease"));
|
|
261
|
-
const easeIn = cubicBezier(cs.getPropertyValue("--clear-in-ease"));
|
|
262
|
-
|
|
263
|
-
const text = clearInput.value;
|
|
264
|
-
clearMirror.textContent = text;
|
|
265
|
-
clearInput.value = "";
|
|
266
|
-
clearWrap.classList.remove("has-value");
|
|
267
|
-
clearWrap.classList.add("is-clearing");
|
|
268
|
-
clearGlow.style.mixBlendMode = isDark ? "screen" : "multiply";
|
|
269
|
-
clearGlow.style.background = buildClearGlow(text, isDark);
|
|
270
|
-
clearGlow.style.opacity = "0";
|
|
271
|
-
clearPhold.style.transform = `translateY(-${inFly}px)`;
|
|
272
|
-
clearPhold.style.opacity = "0.9";
|
|
273
|
-
clearPhold.style.filter = `blur(${blur}px)`;
|
|
274
|
-
|
|
275
|
-
const start = performance.now();
|
|
276
|
-
const tick = (now: number) => {
|
|
277
|
-
if (!clearWrap || !clearMirror || !clearPhold || !clearGlow) return;
|
|
278
|
-
const el = now - start;
|
|
279
|
-
const eo = easeOut(Math.min(1, el / outDur));
|
|
280
|
-
clearMirror.style.transform = `translateY(${(eo * outFly).toFixed(1)}px)`;
|
|
281
|
-
clearMirror.style.opacity = (1 - eo).toFixed(3);
|
|
282
|
-
clearMirror.style.filter = `blur(${(eo * blur).toFixed(1)}px)`;
|
|
283
|
-
|
|
284
|
-
const ei = easeIn(Math.min(1, el / inDur));
|
|
285
|
-
clearPhold.style.transform = `translateY(${(-inFly + ei * inFly).toFixed(1)}px)`;
|
|
286
|
-
clearPhold.style.opacity = (0.9 + ei * 0.1).toFixed(3);
|
|
287
|
-
clearPhold.style.filter = `blur(${(blur - ei * blur).toFixed(1)}px)`;
|
|
288
|
-
|
|
289
|
-
let g = 0;
|
|
290
|
-
if (el > delay) {
|
|
291
|
-
const gp = Math.min(1, (el - delay) / Math.max(1, total - delay));
|
|
292
|
-
g = gp < peakAt ? gp / peakAt : 1 - (gp - peakAt) / (1 - peakAt);
|
|
293
|
-
}
|
|
294
|
-
clearGlow.style.opacity = (g * gOp).toFixed(3);
|
|
295
|
-
|
|
296
|
-
if (el < total) {
|
|
297
|
-
requestAnimationFrame(tick);
|
|
298
|
-
} else {
|
|
299
|
-
clearWrap.classList.remove("is-clearing");
|
|
300
|
-
clearMirror.style.cssText = "";
|
|
301
|
-
clearPhold.style.cssText = "";
|
|
302
|
-
clearMirror.textContent = "";
|
|
303
|
-
clearGlow.style.opacity = "0";
|
|
304
|
-
clearGlow.style.background = "";
|
|
305
|
-
clearBusy = false;
|
|
306
|
-
}
|
|
307
|
-
};
|
|
308
|
-
requestAnimationFrame(tick);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function replaySkeleton() {
|
|
312
|
-
if (!skelEl || !skelSkeleton) return;
|
|
313
|
-
skelEl.classList.add("is-resetting");
|
|
314
|
-
skelEl.classList.remove("is-revealed");
|
|
315
|
-
skelSkeleton.classList.remove("is-pulsing");
|
|
316
|
-
void skelSkeleton.offsetWidth;
|
|
317
|
-
skelEl.classList.remove("is-resetting");
|
|
318
|
-
skelSkeleton.classList.add("is-pulsing");
|
|
319
|
-
const total = cssNum("--pulse-dur", 1000) * cssNum("--pulse-count", 1);
|
|
320
|
-
setTimeout(() => skelEl?.classList.add("is-revealed"), total);
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
function positionTabsPill(animate: boolean) {
|
|
324
|
-
if (!tabsBar || !tabsPill) return;
|
|
325
|
-
const tab = tabsBar.querySelectorAll(".t-tab")[activeTab];
|
|
326
|
-
if (!tab) return;
|
|
327
|
-
if (animate) {
|
|
328
|
-
tabsPill.style.transform = `translateX(${tab.offsetLeft}px)`;
|
|
329
|
-
tabsPill.style.width = `${tab.offsetWidth}px`;
|
|
330
|
-
} else {
|
|
331
|
-
const prev = tabsPill.style.transition;
|
|
332
|
-
tabsPill.style.transition = "none";
|
|
333
|
-
tabsPill.style.transform = `translateX(${tab.offsetLeft}px)`;
|
|
334
|
-
tabsPill.style.width = `${tab.offsetWidth}px`;
|
|
335
|
-
void tabsPill.offsetWidth;
|
|
336
|
-
tabsPill.style.transition = prev;
|
|
337
|
-
}
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
function selectTab(i: number) {
|
|
341
|
-
activeTab = i;
|
|
342
|
-
positionTabsPill(true);
|
|
343
|
-
}
|
|
344
|
-
|
|
345
|
-
function replayStagger() {
|
|
346
|
-
if (!staggerEl) return;
|
|
347
|
-
staggerEl.classList.remove("is-hiding");
|
|
348
|
-
staggerEl.classList.remove("is-shown");
|
|
349
|
-
void staggerEl.offsetHeight;
|
|
350
|
-
staggerEl.classList.add("is-shown");
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
// =========================
|
|
354
|
-
// THE NINE THE SECTION USED TO SKIP
|
|
355
|
-
// =========================
|
|
356
|
-
// Four are pure CSS. The rest carry the small JS each upstream usage note
|
|
357
|
-
// calls for; the markup follows `.upstream/transitions/<slug>.css`.
|
|
358
|
-
let accOpen = $state(true);
|
|
359
|
-
let morphOpen = $state(false);
|
|
360
|
-
let liked = $state(false);
|
|
361
|
-
let bursting = $state(false);
|
|
362
|
-
|
|
363
|
-
let tiltEl = null;
|
|
364
|
-
let tiltCard = null;
|
|
365
|
-
let reelEl = null;
|
|
366
|
-
let streamEl = null;
|
|
367
|
-
let reasonScroll = null;
|
|
368
|
-
let thinkEl = null;
|
|
369
|
-
|
|
370
|
-
const STREAM_TEXT =
|
|
371
|
-
"The parser reads the diff, keeps the hunks it can apply, and hands the rest back with a reason.";
|
|
372
|
-
const THINK_STATES = ["Thinking...", "Reading the repository...", "Drafting the patch..."];
|
|
373
|
-
const REASON_LINES = [
|
|
374
|
-
"Checking the lockfile for a version that moved.",
|
|
375
|
-
"Two primitives changed upstream since the last sync.",
|
|
376
|
-
"One of them is retuned here, so it stays ours.",
|
|
377
|
-
"Writing the other and formatting what landed.",
|
|
378
|
-
];
|
|
379
|
-
|
|
380
|
-
function tiltMove(event: PointerEvent) {
|
|
381
|
-
const rect = tiltEl.getBoundingClientRect();
|
|
382
|
-
const x = (event.clientX - rect.left) / rect.width;
|
|
383
|
-
const y = (event.clientY - rect.top) / rect.height;
|
|
384
|
-
tiltCard.classList.add("is-tilting");
|
|
385
|
-
tiltEl.classList.add("is-hover");
|
|
386
|
-
tiltEl.style.setProperty("--tilt-rx", `${(0.5 - y) * 14}deg`);
|
|
387
|
-
tiltEl.style.setProperty("--tilt-ry", `${(x - 0.5) * 14}deg`);
|
|
388
|
-
tiltEl.style.setProperty("--tilt-gx", `${x * 100}%`);
|
|
389
|
-
tiltEl.style.setProperty("--tilt-gy", `${y * 100}%`);
|
|
390
|
-
}
|
|
391
|
-
|
|
392
|
-
function tiltLeave() {
|
|
393
|
-
tiltCard.classList.remove("is-tilting");
|
|
394
|
-
tiltEl.classList.remove("is-hover");
|
|
395
|
-
tiltEl.style.setProperty("--tilt-rx", "0deg");
|
|
396
|
-
tiltEl.style.setProperty("--tilt-ry", "0deg");
|
|
397
|
-
}
|
|
398
|
-
|
|
399
|
-
// A spray nobody can predict: every dot takes its own angle, distance and
|
|
400
|
-
// clock, which is what keeps two likes from looking like one animation.
|
|
401
|
-
function toggleLike(event: MouseEvent) {
|
|
402
|
-
liked = !liked;
|
|
403
|
-
if (!liked) return;
|
|
404
|
-
const root = event.currentTarget as HTMLElement;
|
|
405
|
-
for (const dot of root.querySelectorAll<HTMLElement>(".t-like-particles i")) {
|
|
406
|
-
const angle = Math.random() * Math.PI * 2;
|
|
407
|
-
const dist = 14 + Math.random() * 14;
|
|
408
|
-
dot.style.setProperty("--px", `${Math.cos(angle) * dist}px`);
|
|
409
|
-
dot.style.setProperty("--py", `${Math.sin(angle) * dist}px`);
|
|
410
|
-
dot.style.setProperty("--pdur", `${480 + Math.random() * 240}ms`);
|
|
411
|
-
dot.style.setProperty("--pdelay", `${Math.random() * 60}ms`);
|
|
412
|
-
dot.style.setProperty("--psize", `${0.7 + Math.random() * 0.8}`);
|
|
413
|
-
}
|
|
414
|
-
bursting = false;
|
|
415
|
-
void root.offsetHeight;
|
|
416
|
-
bursting = true;
|
|
417
|
-
setTimeout(() => (bursting = false), 700);
|
|
418
|
-
}
|
|
419
|
-
|
|
420
|
-
/** One column per digit, each clipping a 0-9 strip it spins past. */
|
|
421
|
-
function spinReel(value = "482") {
|
|
422
|
-
reelEl.replaceChildren();
|
|
423
|
-
value.split("").forEach((digit, index) => {
|
|
424
|
-
const col = document.createElement("div");
|
|
425
|
-
col.className = "t-reel-col";
|
|
426
|
-
const strip = document.createElement("div");
|
|
427
|
-
strip.className = "t-reel-strip";
|
|
428
|
-
for (let n = 0; n < 30; n++) {
|
|
429
|
-
const cell = document.createElement("div");
|
|
430
|
-
cell.className = "t-reel-digit";
|
|
431
|
-
cell.textContent = String(n % 10);
|
|
432
|
-
strip.append(cell);
|
|
433
|
-
}
|
|
434
|
-
col.append(strip);
|
|
435
|
-
reelEl.append(col);
|
|
436
|
-
const cells = 20 + Number(digit);
|
|
437
|
-
strip.style.transform = "translateY(0)";
|
|
438
|
-
strip.style.filter = "blur(0px)";
|
|
439
|
-
void strip.offsetHeight;
|
|
440
|
-
strip.style.transition = `transform var(--reel-dur) var(--reel-ease) ${index * 90}ms, filter var(--reel-dur) linear ${index * 90}ms`;
|
|
441
|
-
strip.style.transform = `translateY(calc(var(--reel-cell) * -${cells}))`;
|
|
442
|
-
});
|
|
443
|
-
}
|
|
444
|
-
|
|
445
|
-
/** Wrap each word once, then let them in one --stream-gap apart. */
|
|
446
|
-
function replayStream() {
|
|
447
|
-
const words = streamEl.querySelectorAll<HTMLElement>(".t-stream-w");
|
|
448
|
-
for (const word of words) {
|
|
449
|
-
word.style.transition = "none";
|
|
450
|
-
word.classList.remove("is-in");
|
|
451
|
-
}
|
|
452
|
-
void streamEl.offsetHeight;
|
|
453
|
-
words.forEach((word, index) => {
|
|
454
|
-
word.style.transition = "";
|
|
455
|
-
setTimeout(() => word.classList.add("is-in"), index * 60);
|
|
456
|
-
});
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
// The two that run on their own: a transcript stepping up while a model
|
|
460
|
-
// thinks, and the line under it swapping state.
|
|
461
|
-
$effect(() => {
|
|
462
|
-
if (!reasonScroll || !thinkEl) return;
|
|
463
|
-
replayStream();
|
|
464
|
-
spinReel();
|
|
465
|
-
|
|
466
|
-
let offset = 0;
|
|
467
|
-
const step = setInterval(() => {
|
|
468
|
-
offset = (offset + 2) % REASON_LINES.length;
|
|
469
|
-
reasonScroll.style.transition = "transform var(--reason-step) var(--reason-ease)";
|
|
470
|
-
reasonScroll.style.transform = `translateY(calc(var(--reason-line) * -${offset}))`;
|
|
471
|
-
}, 840);
|
|
472
|
-
|
|
473
|
-
let state = 0;
|
|
474
|
-
const swap = setInterval(() => {
|
|
475
|
-
state = (state + 1) % THINK_STATES.length;
|
|
476
|
-
thinkEl.classList.add("is-exit");
|
|
477
|
-
setTimeout(() => {
|
|
478
|
-
thinkEl.textContent = THINK_STATES[state];
|
|
479
|
-
thinkEl.dataset.text = THINK_STATES[state];
|
|
480
|
-
thinkEl.classList.remove("is-exit");
|
|
481
|
-
thinkEl.classList.add("is-enter-start");
|
|
482
|
-
void thinkEl.offsetHeight;
|
|
483
|
-
thinkEl.classList.remove("is-enter-start");
|
|
484
|
-
}, 200);
|
|
485
|
-
}, 2000);
|
|
486
|
-
|
|
487
|
-
return () => {
|
|
488
|
-
clearInterval(step);
|
|
489
|
-
clearInterval(swap);
|
|
490
|
-
};
|
|
491
|
-
});
|
|
492
|
-
</script>
|
|
493
|
-
|
|
494
|
-
<!-- ========================== -->
|
|
495
|
-
<!-- MARKUP -->
|
|
496
|
-
<!-- ========================== -->
|
|
497
|
-
<div class="grid">
|
|
498
|
-
<ShowcaseStage
|
|
499
|
-
title="Text states swap"
|
|
500
|
-
note="Text swap with translate and blur"
|
|
501
|
-
importPath={"import { swapText } from '@heyramzi/ui/animations/text-swap';"}
|
|
502
|
-
onaction={nextPhrase}
|
|
503
|
-
>
|
|
504
|
-
<span bind:this={target} class="phrase">{phrases[0]}</span>
|
|
505
|
-
</ShowcaseStage>
|
|
506
|
-
|
|
507
|
-
<ShowcaseStage
|
|
508
|
-
title="Number pop-in"
|
|
509
|
-
note="Digit flip with blur and stagger"
|
|
510
|
-
importPath={"import '@heyramzi/ui/animations/digit-pop-in.css';"}
|
|
511
|
-
onaction={replayDigits}
|
|
512
|
-
>
|
|
513
|
-
<span
|
|
514
|
-
bind:this={digitGroup}
|
|
515
|
-
class="t-digit-group digit-display"
|
|
516
|
-
class:is-animating={digitAnimating}
|
|
517
|
-
>
|
|
518
|
-
{#each digitValue.split("") as ch, i (i + ch)}
|
|
519
|
-
<span class="t-digit" data-stagger={i}>{ch}</span>
|
|
520
|
-
{/each}
|
|
521
|
-
</span>
|
|
522
|
-
</ShowcaseStage>
|
|
523
|
-
|
|
524
|
-
<ShowcaseStage
|
|
525
|
-
title="Card resize"
|
|
526
|
-
note="Smooth width and height transition"
|
|
527
|
-
importPath={"import '@heyramzi/ui/animations/resize.css';"}
|
|
528
|
-
onaction={() => (resizeSmall = !resizeSmall)}
|
|
529
|
-
>
|
|
530
|
-
<div class="t-resize sk-card" class:is-small={resizeSmall}>
|
|
531
|
-
<span class="sk sk-1"></span>
|
|
532
|
-
<span class="sk sk-2"></span>
|
|
533
|
-
<span class="sk sk-3"></span>
|
|
534
|
-
<span class="sk sk-4"></span>
|
|
535
|
-
<span class="sk sk-5"></span>
|
|
536
|
-
<span class="sk sk-6"></span>
|
|
537
|
-
</div>
|
|
538
|
-
</ShowcaseStage>
|
|
539
|
-
|
|
540
|
-
<ShowcaseStage
|
|
541
|
-
title="Notification badge"
|
|
542
|
-
note="Diagonal slide with spring pop-in"
|
|
543
|
-
importPath={"import '@heyramzi/ui/animations/notification-badge.css';"}
|
|
544
|
-
onaction={bumpBadge}
|
|
545
|
-
>
|
|
546
|
-
<button type="button" class="bell-trigger" onclick={bumpBadge} aria-label="Notifications">
|
|
547
|
-
<Bell class="size-5" />
|
|
548
|
-
<span class="t-badge" data-open={badgeOpen ? "true" : "false"}>
|
|
549
|
-
<span class="t-badge-dot">{badgeCount}</span>
|
|
550
|
-
</span>
|
|
551
|
-
</button>
|
|
552
|
-
</ShowcaseStage>
|
|
553
|
-
|
|
554
|
-
<ShowcaseStage
|
|
555
|
-
title="Modal open / close"
|
|
556
|
-
note="Scale and blur transition"
|
|
557
|
-
importPath={"import '@heyramzi/ui/animations/modal.css';"}
|
|
558
|
-
onaction={() => (modalOpen = !modalOpen)}
|
|
559
|
-
>
|
|
560
|
-
<div class="t-modal sk-modal" class:is-open={modalOpen}>
|
|
561
|
-
<div class="sk sk-mtitle"></div>
|
|
562
|
-
<div class="sk sk-mclose"></div>
|
|
563
|
-
<div class="sk sk-line full"></div>
|
|
564
|
-
<div class="sk sk-line full"></div>
|
|
565
|
-
<div class="sk sk-line three-q"></div>
|
|
566
|
-
<div class="sk-pills">
|
|
567
|
-
<div class="sk sk-pill"></div>
|
|
568
|
-
<div class="sk sk-pill"></div>
|
|
569
|
-
</div>
|
|
570
|
-
</div>
|
|
571
|
-
</ShowcaseStage>
|
|
572
|
-
|
|
573
|
-
<ShowcaseStage
|
|
574
|
-
title="Menu dropdown"
|
|
575
|
-
note="Origin-aware open and close"
|
|
576
|
-
importPath={"import '@heyramzi/ui/animations/dropdown.css';"}
|
|
577
|
-
onaction={() => (dropdownOpen = !dropdownOpen)}
|
|
578
|
-
>
|
|
579
|
-
<div class="dropdown-stack">
|
|
580
|
-
<div class="sk-trigger"></div>
|
|
581
|
-
<div class="t-dropdown sk-dropdown" class:is-open={dropdownOpen}>
|
|
582
|
-
<div class="sk sk-row full"></div>
|
|
583
|
-
<div class="sk sk-row three-q"></div>
|
|
584
|
-
<div class="sk sk-row half"></div>
|
|
585
|
-
</div>
|
|
586
|
-
</div>
|
|
587
|
-
</ShowcaseStage>
|
|
588
|
-
|
|
589
|
-
<ShowcaseStage
|
|
590
|
-
title="Panel reveal"
|
|
591
|
-
note="Translate and blur entrance"
|
|
592
|
-
importPath={"import '@heyramzi/ui/animations/panel.css';"}
|
|
593
|
-
onaction={() => (panelOpen = !panelOpen)}
|
|
594
|
-
>
|
|
595
|
-
<div class="panel-clip">
|
|
596
|
-
<div class="t-panel-slide sk-panel" data-open={panelOpen ? "true" : "false"}>
|
|
597
|
-
<div class="sk sk-line full"></div>
|
|
598
|
-
<div class="sk sk-line three-q"></div>
|
|
599
|
-
<div class="sk-tiles">
|
|
600
|
-
<div class="sk sk-tile"></div>
|
|
601
|
-
<div class="sk sk-tile"></div>
|
|
602
|
-
<div class="sk sk-tile"></div>
|
|
603
|
-
<div class="sk sk-tile"></div>
|
|
604
|
-
</div>
|
|
605
|
-
</div>
|
|
606
|
-
</div>
|
|
607
|
-
</ShowcaseStage>
|
|
608
|
-
|
|
609
|
-
<ShowcaseStage
|
|
610
|
-
title="Page side-by-side"
|
|
611
|
-
note="Forward and back page slide"
|
|
612
|
-
importPath={"import '@heyramzi/ui/animations/page-side-by-side.css';"}
|
|
613
|
-
actionLabel={activePage === "1" ? "Next" : "Back"}
|
|
614
|
-
onaction={togglePage}
|
|
615
|
-
>
|
|
616
|
-
<div class="t-page-slide sk-page-stage" data-page={activePage}>
|
|
617
|
-
<section class="t-page sk-page" data-page-id="1">
|
|
618
|
-
<div class="sk sk-row full"></div>
|
|
619
|
-
<div class="sk sk-row three-q"></div>
|
|
620
|
-
<div class="sk sk-row half"></div>
|
|
621
|
-
</section>
|
|
622
|
-
<section class="t-page sk-page sk-page-2" data-page-id="2">
|
|
623
|
-
<div class="sk-amount">$10</div>
|
|
624
|
-
<div class="sk-pill-row">
|
|
625
|
-
<div class="sk sk-mini-pill"></div>
|
|
626
|
-
<div class="sk sk-mini-pill"></div>
|
|
627
|
-
<div class="sk sk-mini-pill"></div>
|
|
628
|
-
</div>
|
|
629
|
-
</section>
|
|
630
|
-
</div>
|
|
631
|
-
</ShowcaseStage>
|
|
632
|
-
|
|
633
|
-
<ShowcaseStage
|
|
634
|
-
title="Icon swap"
|
|
635
|
-
note="Crossfade with blur between icons"
|
|
636
|
-
importPath={"import '@heyramzi/ui/animations/icon-swap.css';"}
|
|
637
|
-
onaction={() => (iconState = iconState === "a" ? "b" : "a")}
|
|
638
|
-
>
|
|
639
|
-
<div class="t-icon-swap icon-stack" data-state={iconState}>
|
|
640
|
-
<div class="t-icon" data-icon="a"><Menu class="size-7" /></div>
|
|
641
|
-
<div class="t-icon" data-icon="b"><X class="size-7" /></div>
|
|
642
|
-
</div>
|
|
643
|
-
</ShowcaseStage>
|
|
644
|
-
|
|
645
|
-
<ShowcaseStage
|
|
646
|
-
title="Success check"
|
|
647
|
-
note="Fade, rotate, bob, and stroke draw"
|
|
648
|
-
importPath={"import '@heyramzi/ui/animations/success-check.css';"}
|
|
649
|
-
onaction={replayCheck}
|
|
650
|
-
>
|
|
651
|
-
<div class="check-badge">
|
|
652
|
-
<span bind:this={checkEl} class="t-success-check" data-state="in" aria-hidden="true">
|
|
653
|
-
{@html successCheck}
|
|
654
|
-
</span>
|
|
655
|
-
</div>
|
|
656
|
-
</ShowcaseStage>
|
|
657
|
-
|
|
658
|
-
<ShowcaseStage
|
|
659
|
-
title="Avatar group hover"
|
|
660
|
-
note="Distance falloff lift with spring return"
|
|
661
|
-
importPath={"import '@heyramzi/ui/animations/avatar-group-hover.css';"}
|
|
662
|
-
>
|
|
663
|
-
<div
|
|
664
|
-
bind:this={avatarRoot}
|
|
665
|
-
class="t-avatar-group avatar-row"
|
|
666
|
-
role="group"
|
|
667
|
-
aria-label="Team"
|
|
668
|
-
onmouseleave={() => liftAvatars(null)}
|
|
669
|
-
>
|
|
670
|
-
{#each avatars as person, i (person.initials)}
|
|
671
|
-
<div
|
|
672
|
-
class="t-avatar avatar-chip"
|
|
673
|
-
style="z-index: {avatars.length -
|
|
674
|
-
i}; background: linear-gradient(145deg, hsl({person.hue} 52% 52%), hsl({person.hue} 56% 38%)); color: #fff;"
|
|
675
|
-
onmouseenter={() => liftAvatars(i)}
|
|
676
|
-
>
|
|
677
|
-
{person.initials}
|
|
678
|
-
</div>
|
|
679
|
-
{/each}
|
|
680
|
-
</div>
|
|
681
|
-
</ShowcaseStage>
|
|
682
|
-
|
|
683
|
-
<ShowcaseStage
|
|
684
|
-
title="Error state shake"
|
|
685
|
-
note="Percussive shake with auto-revert"
|
|
686
|
-
importPath={"import '@heyramzi/ui/animations/input-shake.css';"}
|
|
687
|
-
actionLabel="Submit"
|
|
688
|
-
onaction={showError}
|
|
689
|
-
>
|
|
690
|
-
<div bind:this={shakeWrap} class="t-input-wrap shake-wrap">
|
|
691
|
-
<div bind:this={shakeInput} class="t-input shake-input">name@email</div>
|
|
692
|
-
<p class="t-error-msg shake-msg">Enter a valid email address.</p>
|
|
693
|
-
</div>
|
|
694
|
-
</ShowcaseStage>
|
|
695
|
-
|
|
696
|
-
<ShowcaseStage
|
|
697
|
-
title="Input clear"
|
|
698
|
-
note="Fly-out text with per-word streak"
|
|
699
|
-
importPath={"import '@heyramzi/ui/animations/input-clear-dissolve.css';"}
|
|
700
|
-
actionLabel="Clear"
|
|
701
|
-
onaction={triggerClear}
|
|
702
|
-
>
|
|
703
|
-
<div bind:this={clearWrap} class="t-clear clear-field has-value">
|
|
704
|
-
<input
|
|
705
|
-
bind:this={clearInput}
|
|
706
|
-
class="clear-input"
|
|
707
|
-
type="text"
|
|
708
|
-
value={CLEAR_TEXT}
|
|
709
|
-
readonly
|
|
710
|
-
aria-label="Search"
|
|
711
|
-
/>
|
|
712
|
-
<div bind:this={clearMirror} class="t-clear-mirror clear-text" aria-hidden="true">
|
|
713
|
-
{CLEAR_TEXT}
|
|
714
|
-
</div>
|
|
715
|
-
<div
|
|
716
|
-
bind:this={clearPhold}
|
|
717
|
-
class="t-clear-placeholder clear-text clear-ph"
|
|
718
|
-
aria-hidden="true"
|
|
719
|
-
>
|
|
720
|
-
Search
|
|
721
|
-
</div>
|
|
722
|
-
<div bind:this={clearGlow} class="t-clear-glow" aria-hidden="true"></div>
|
|
723
|
-
<button type="button" class="t-clear-btn clear-x" onclick={triggerClear} aria-label="Clear">
|
|
724
|
-
<X class="size-3.5" />
|
|
725
|
-
</button>
|
|
726
|
-
</div>
|
|
727
|
-
</ShowcaseStage>
|
|
728
|
-
|
|
729
|
-
<ShowcaseStage
|
|
730
|
-
title="Skeleton loader"
|
|
731
|
-
note="Pulse, then cross-blur to content"
|
|
732
|
-
importPath={"import '@heyramzi/ui/animations/skeleton-reveal.css';"}
|
|
733
|
-
actionLabel="Reload"
|
|
734
|
-
onaction={replaySkeleton}
|
|
735
|
-
>
|
|
736
|
-
<div bind:this={skelEl} class="t-skel skel-card is-revealed">
|
|
737
|
-
<div bind:this={skelSkeleton} class="t-skel-skeleton skel-layer">
|
|
738
|
-
<span class="sk skel-avatar"></span>
|
|
739
|
-
<span class="skel-bars">
|
|
740
|
-
<span class="sk skel-l1"></span>
|
|
741
|
-
<span class="sk skel-l2"></span>
|
|
742
|
-
</span>
|
|
743
|
-
</div>
|
|
744
|
-
<div class="t-skel-content skel-layer">
|
|
745
|
-
<div class="skel-avatar-real">R</div>
|
|
746
|
-
<div class="skel-lines">
|
|
747
|
-
<div class="skel-name">Ramzi K.</div>
|
|
748
|
-
<div class="skel-sub">Shipped 14 routes</div>
|
|
749
|
-
</div>
|
|
750
|
-
</div>
|
|
751
|
-
</div>
|
|
752
|
-
</ShowcaseStage>
|
|
753
|
-
|
|
754
|
-
<ShowcaseStage
|
|
755
|
-
title="Shimmer text"
|
|
756
|
-
note="Sweeping highlight on a loop"
|
|
757
|
-
importPath={"import '@heyramzi/ui/animations/shimmer-text.css';"}
|
|
758
|
-
>
|
|
759
|
-
<span class="t-shimmer shimmer-demo" data-text="Generating response">Generating response</span>
|
|
760
|
-
</ShowcaseStage>
|
|
761
|
-
|
|
762
|
-
<ShowcaseStage
|
|
763
|
-
title="Tabs sliding"
|
|
764
|
-
note="Active pill slides between options"
|
|
765
|
-
importPath={"import '@heyramzi/ui/animations/tabs-sliding.css';"}
|
|
766
|
-
>
|
|
767
|
-
<div bind:this={tabsBar} class="t-tabs tabs-demo" role="tablist" aria-label="View">
|
|
768
|
-
<span bind:this={tabsPill} class="t-tabs-pill" aria-hidden="true"></span>
|
|
769
|
-
{#each tabs as label, i (label)}
|
|
770
|
-
<button
|
|
771
|
-
type="button"
|
|
772
|
-
class="t-tab"
|
|
773
|
-
role="tab"
|
|
774
|
-
aria-selected={i === activeTab}
|
|
775
|
-
onclick={() => selectTab(i)}
|
|
776
|
-
>
|
|
777
|
-
{label}
|
|
778
|
-
</button>
|
|
779
|
-
{/each}
|
|
780
|
-
</div>
|
|
781
|
-
</ShowcaseStage>
|
|
782
|
-
|
|
783
|
-
<ShowcaseStage
|
|
784
|
-
title="Tooltip"
|
|
785
|
-
note="Delayed fade-in, instant out"
|
|
786
|
-
importPath={"import '@heyramzi/ui/animations/tooltip.css';"}
|
|
787
|
-
>
|
|
788
|
-
<span class="t-tt-wrap tt-demo">
|
|
789
|
-
<button type="button" class="t-tt-trigger tt-trigger" aria-describedby="tt-anim">
|
|
790
|
-
<Info class="size-5" />
|
|
791
|
-
</button>
|
|
792
|
-
<span class="t-tt tt-bubble" id="tt-anim" role="tooltip">Keyboard shortcuts</span>
|
|
793
|
-
</span>
|
|
794
|
-
</ShowcaseStage>
|
|
795
|
-
|
|
796
|
-
<ShowcaseStage
|
|
797
|
-
title="Texts reveal"
|
|
798
|
-
note="Staggered blurred rise"
|
|
799
|
-
importPath={"import '@heyramzi/ui/animations/texts-reveal.css';"}
|
|
800
|
-
actionLabel="Replay"
|
|
801
|
-
onaction={replayStagger}
|
|
802
|
-
>
|
|
803
|
-
<div bind:this={staggerEl} class="t-stagger stagger-demo is-shown">
|
|
804
|
-
<strong class="t-stagger-line t-stagger-line--1 stagger-head">Ship with rhythm</strong>
|
|
805
|
-
<span class="t-stagger-line t-stagger-line--2 stagger-sub"
|
|
806
|
-
>Headline first, the rest follows.</span
|
|
807
|
-
>
|
|
808
|
-
</div>
|
|
809
|
-
</ShowcaseStage>
|
|
810
|
-
|
|
811
|
-
<ShowcaseStage
|
|
812
|
-
title="Accordion"
|
|
813
|
-
note="Grid-row expand, no measured height"
|
|
814
|
-
importPath={"import '@heyramzi/ui/animations/accordion.css';"}
|
|
815
|
-
>
|
|
816
|
-
<div class="t-acc acc-demo" data-open={accOpen ? "true" : "false"}>
|
|
817
|
-
<button
|
|
818
|
-
type="button"
|
|
819
|
-
class="t-acc-head acc-head"
|
|
820
|
-
aria-expanded={accOpen}
|
|
821
|
-
onclick={() => (accOpen = !accOpen)}
|
|
822
|
-
>
|
|
823
|
-
Shipping details
|
|
824
|
-
<span class="t-acc-chevron">
|
|
825
|
-
{@html chevronDown}
|
|
826
|
-
</span>
|
|
827
|
-
</button>
|
|
828
|
-
<div class="t-acc-panel">
|
|
829
|
-
<div class="t-acc-panel-inner">
|
|
830
|
-
<p class="acc-body">
|
|
831
|
-
Standard delivery takes three to five days. Express arrives the next morning, tracked
|
|
832
|
-
end to end.
|
|
833
|
-
</p>
|
|
834
|
-
</div>
|
|
835
|
-
</div>
|
|
836
|
-
</div>
|
|
837
|
-
</ShowcaseStage>
|
|
838
|
-
|
|
839
|
-
<ShowcaseStage
|
|
840
|
-
title="Card tilt"
|
|
841
|
-
note="Pointer-tracked 3D tilt with a glare"
|
|
842
|
-
importPath={"import '@heyramzi/ui/animations/card-tilt.css';"}
|
|
843
|
-
>
|
|
844
|
-
<div bind:this={tiltEl} class="t-tilt" onpointermove={tiltMove} onpointerleave={tiltLeave}>
|
|
845
|
-
<div bind:this={tiltCard} class="t-tilt-card tilt-card">
|
|
846
|
-
<strong>Pro</strong>
|
|
847
|
-
<span class="tilt-price">39 EUR</span>
|
|
848
|
-
<span class="tilt-note">Move the pointer across the card.</span>
|
|
849
|
-
<div class="t-tilt-glare"></div>
|
|
850
|
-
</div>
|
|
851
|
-
</div>
|
|
852
|
-
</ShowcaseStage>
|
|
853
|
-
|
|
854
|
-
<ShowcaseStage
|
|
855
|
-
title="Learn more hover"
|
|
856
|
-
note="Chevron shifts, its arms open"
|
|
857
|
-
importPath={"import '@heyramzi/ui/animations/learn-more-hover.css';"}
|
|
858
|
-
>
|
|
859
|
-
<button type="button" class="t-learn learn-demo">
|
|
860
|
-
Learn more
|
|
861
|
-
<span class="t-learn-chevron">
|
|
862
|
-
{@html chevronArms}
|
|
863
|
-
</span>
|
|
864
|
-
</button>
|
|
865
|
-
</ShowcaseStage>
|
|
866
|
-
|
|
867
|
-
<ShowcaseStage
|
|
868
|
-
title="Like button"
|
|
869
|
-
note="Heart fills, particles spray"
|
|
870
|
-
importPath={"import '@heyramzi/ui/animations/like-button.css';"}
|
|
871
|
-
>
|
|
872
|
-
<button
|
|
873
|
-
type="button"
|
|
874
|
-
class="t-like like-demo"
|
|
875
|
-
class:is-bursting={bursting}
|
|
876
|
-
data-liked={liked ? "true" : "false"}
|
|
877
|
-
aria-pressed={liked}
|
|
878
|
-
onclick={toggleLike}
|
|
879
|
-
>
|
|
880
|
-
<span class="t-like-icon">
|
|
881
|
-
{@html heart}
|
|
882
|
-
</span>
|
|
883
|
-
<span class="t-like-particles" aria-hidden="true">
|
|
884
|
-
{#each { length: 8 } as _, i (i)}
|
|
885
|
-
<i></i>
|
|
886
|
-
{/each}
|
|
887
|
-
</span>
|
|
888
|
-
Like
|
|
889
|
-
</button>
|
|
890
|
-
</ShowcaseStage>
|
|
891
|
-
|
|
892
|
-
<ShowcaseStage
|
|
893
|
-
title="Plus menu morph"
|
|
894
|
-
note="The button becomes the surface"
|
|
895
|
-
importPath={"import '@heyramzi/ui/animations/plus-menu-morph.css';"}
|
|
896
|
-
>
|
|
897
|
-
<div class="morph-anchor">
|
|
898
|
-
<div class="t-morph morph-demo" data-open={morphOpen ? "true" : "false"}>
|
|
899
|
-
<div class="t-morph-menu morph-menu">
|
|
900
|
-
<span>Duplicate</span>
|
|
901
|
-
<span>Move to...</span>
|
|
902
|
-
<span>Archive</span>
|
|
903
|
-
</div>
|
|
904
|
-
<button
|
|
905
|
-
type="button"
|
|
906
|
-
class="t-morph-plus morph-plus"
|
|
907
|
-
aria-expanded={morphOpen}
|
|
908
|
-
aria-label={morphOpen ? "Close menu" : "Open menu"}
|
|
909
|
-
onclick={() => (morphOpen = !morphOpen)}
|
|
910
|
-
>
|
|
911
|
-
{@html plus}
|
|
912
|
-
</button>
|
|
913
|
-
</div>
|
|
914
|
-
</div>
|
|
915
|
-
</ShowcaseStage>
|
|
916
|
-
|
|
917
|
-
<ShowcaseStage
|
|
918
|
-
title="Spinning counter"
|
|
919
|
-
note="One reel per digit, staggered landing"
|
|
920
|
-
importPath={"import '@heyramzi/ui/animations/spinning-counter.css';"}
|
|
921
|
-
onaction={() => spinReel(String(100 + Math.floor(Math.random() * 900)))}
|
|
922
|
-
>
|
|
923
|
-
<div bind:this={reelEl} class="t-reel reel-demo"></div>
|
|
924
|
-
</ShowcaseStage>
|
|
925
|
-
|
|
926
|
-
<ShowcaseStage
|
|
927
|
-
title="Streaming text"
|
|
928
|
-
note="Word by word, opacity and blur"
|
|
929
|
-
importPath={"import '@heyramzi/ui/animations/streaming-text.css';"}
|
|
930
|
-
onaction={replayStream}
|
|
931
|
-
>
|
|
932
|
-
<p bind:this={streamEl} class="stream-demo">
|
|
933
|
-
{#each STREAM_TEXT.split(" ") as word, i (i)}
|
|
934
|
-
<span class="t-stream-w">{word} </span>
|
|
935
|
-
{/each}
|
|
936
|
-
</p>
|
|
937
|
-
</ShowcaseStage>
|
|
938
|
-
|
|
939
|
-
<ShowcaseStage
|
|
940
|
-
title="Reasoning stream"
|
|
941
|
-
note="A transcript stepping under a mask"
|
|
942
|
-
importPath={"import '@heyramzi/ui/animations/reasoning-stream.css';"}
|
|
943
|
-
>
|
|
944
|
-
<div class="t-reason reason-demo">
|
|
945
|
-
<div class="t-reason-viewport">
|
|
946
|
-
<div bind:this={reasonScroll} class="t-reason-scroll">
|
|
947
|
-
{#each [...REASON_LINES, ...REASON_LINES] as line, i (i)}
|
|
948
|
-
<p class="reason-line">{line}</p>
|
|
949
|
-
{/each}
|
|
950
|
-
</div>
|
|
951
|
-
</div>
|
|
952
|
-
</div>
|
|
953
|
-
</ShowcaseStage>
|
|
954
|
-
|
|
955
|
-
<ShowcaseStage
|
|
956
|
-
title="Thinking states"
|
|
957
|
-
note="Shimmering line, swapped on a hold"
|
|
958
|
-
importPath={"import '@heyramzi/ui/animations/thinking-states.css';"}
|
|
959
|
-
>
|
|
960
|
-
<span class="t-think think-demo" role="status">
|
|
961
|
-
<span class="t-think-sizer" aria-hidden="true">Reading the repository...</span>
|
|
962
|
-
<span bind:this={thinkEl} class="t-think-text" data-text="Thinking...">Thinking...</span>
|
|
963
|
-
</span>
|
|
964
|
-
</ShowcaseStage>
|
|
965
|
-
</div>
|
|
966
|
-
|
|
967
|
-
<!-- ========================== -->
|
|
968
|
-
<!-- STYLE -->
|
|
969
|
-
<!-- ========================== -->
|
|
970
|
-
<style>
|
|
971
|
-
/* One demo per row, the rule ShowcaseSection states for `.sc-stack`. An
|
|
972
|
-
animation is read by watching it run, and a third-width stage clips it. */
|
|
973
|
-
.grid {
|
|
974
|
-
display: grid;
|
|
975
|
-
grid-template-columns: minmax(0, 1fr);
|
|
976
|
-
gap: 1rem;
|
|
977
|
-
|
|
978
|
-
/* transitions.dev demo material mapped onto host tokens. Nothing defined
|
|
979
|
-
the names, so eleven of eighteen drew transparent until 10 Sep 2026.
|
|
980
|
-
Every value reads the app palette. */
|
|
981
|
-
--td-material-bg: var(--color-card, var(--card));
|
|
982
|
-
--td-material-shadow:
|
|
983
|
-
0 0 0 1px color-mix(in oklab, var(--color-border, var(--border)) 80%, transparent),
|
|
984
|
-
0 6px 18px -8px
|
|
985
|
-
color-mix(in oklab, var(--color-foreground, var(--foreground)) 22%, transparent);
|
|
986
|
-
--td-skeleton: color-mix(
|
|
987
|
-
in oklab,
|
|
988
|
-
var(--color-muted-foreground, var(--muted-foreground)) 22%,
|
|
989
|
-
transparent
|
|
990
|
-
);
|
|
991
|
-
--td-stage-bg: var(--color-background, var(--background));
|
|
992
|
-
--td-text: var(--color-foreground, var(--foreground));
|
|
993
|
-
--td-text-subtle: var(--color-muted-foreground, var(--muted-foreground));
|
|
994
|
-
--td-icon-color: var(--color-foreground, var(--foreground));
|
|
995
|
-
--td-icon-color-muted: var(--color-muted-foreground, var(--muted-foreground));
|
|
996
|
-
--td-copy-bg: color-mix(in oklab, var(--color-muted, var(--muted)) 80%, transparent);
|
|
997
|
-
--td-copy-bg-hover: var(--color-muted, var(--muted));
|
|
998
|
-
}
|
|
999
|
-
|
|
1000
|
-
.sk {
|
|
1001
|
-
background: var(--td-skeleton);
|
|
1002
|
-
border-radius: 4px;
|
|
1003
|
-
}
|
|
1004
|
-
|
|
1005
|
-
.phrase {
|
|
1006
|
-
font-size: 1.0625rem;
|
|
1007
|
-
font-weight: 500;
|
|
1008
|
-
color: var(--td-text, var(--foreground));
|
|
1009
|
-
--text-swap-dur: 240ms;
|
|
1010
|
-
}
|
|
1011
|
-
|
|
1012
|
-
.digit-display {
|
|
1013
|
-
font-size: 2.25rem;
|
|
1014
|
-
font-weight: 600;
|
|
1015
|
-
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
1016
|
-
color: var(--td-text, var(--foreground));
|
|
1017
|
-
font-feature-settings: "tnum";
|
|
1018
|
-
letter-spacing: -0.02em;
|
|
1019
|
-
}
|
|
1020
|
-
|
|
1021
|
-
.sk-card {
|
|
1022
|
-
position: relative;
|
|
1023
|
-
width: 12.5rem;
|
|
1024
|
-
height: 8.75rem;
|
|
1025
|
-
background: var(--td-material-bg);
|
|
1026
|
-
box-shadow: var(--td-material-shadow);
|
|
1027
|
-
border-radius: 12px;
|
|
1028
|
-
/* WHY: clip the skeleton lines so they don't spill past the card edge as it shrinks */
|
|
1029
|
-
overflow: hidden;
|
|
1030
|
-
}
|
|
1031
|
-
.sk-card.is-small {
|
|
1032
|
-
width: 9rem;
|
|
1033
|
-
height: 6rem;
|
|
1034
|
-
}
|
|
1035
|
-
.sk-card .sk {
|
|
1036
|
-
position: absolute;
|
|
1037
|
-
left: 14px;
|
|
1038
|
-
right: 14px;
|
|
1039
|
-
}
|
|
1040
|
-
.sk-card .sk-1 {
|
|
1041
|
-
top: 16px;
|
|
1042
|
-
height: 10px;
|
|
1043
|
-
right: auto;
|
|
1044
|
-
width: 56%;
|
|
1045
|
-
}
|
|
1046
|
-
.sk-card .sk-2 {
|
|
1047
|
-
top: 32px;
|
|
1048
|
-
height: 6px;
|
|
1049
|
-
}
|
|
1050
|
-
.sk-card .sk-3 {
|
|
1051
|
-
top: 44px;
|
|
1052
|
-
height: 6px;
|
|
1053
|
-
}
|
|
1054
|
-
.sk-card .sk-4 {
|
|
1055
|
-
top: 56px;
|
|
1056
|
-
height: 6px;
|
|
1057
|
-
right: auto;
|
|
1058
|
-
width: 70%;
|
|
1059
|
-
}
|
|
1060
|
-
.sk-card .sk-5 {
|
|
1061
|
-
top: 84px;
|
|
1062
|
-
height: 6px;
|
|
1063
|
-
}
|
|
1064
|
-
.sk-card .sk-6 {
|
|
1065
|
-
top: 96px;
|
|
1066
|
-
height: 6px;
|
|
1067
|
-
}
|
|
1068
|
-
|
|
1069
|
-
.bell-trigger {
|
|
1070
|
-
position: relative;
|
|
1071
|
-
display: inline-flex;
|
|
1072
|
-
align-items: center;
|
|
1073
|
-
justify-content: center;
|
|
1074
|
-
width: 3rem;
|
|
1075
|
-
height: 3rem;
|
|
1076
|
-
border-radius: 12px;
|
|
1077
|
-
border: 0;
|
|
1078
|
-
background: var(--td-material-bg);
|
|
1079
|
-
box-shadow: var(--td-material-shadow);
|
|
1080
|
-
color: var(--td-icon-color, var(--foreground));
|
|
1081
|
-
cursor: pointer;
|
|
1082
|
-
}
|
|
1083
|
-
.bell-trigger:hover {
|
|
1084
|
-
filter: brightness(1.05);
|
|
1085
|
-
}
|
|
1086
|
-
:global(.bell-trigger .t-badge-dot) {
|
|
1087
|
-
display: inline-flex;
|
|
1088
|
-
align-items: center;
|
|
1089
|
-
justify-content: center;
|
|
1090
|
-
min-width: 1.125rem;
|
|
1091
|
-
height: 1.125rem;
|
|
1092
|
-
padding: 0 0.3125rem;
|
|
1093
|
-
font-size: 0.6875rem;
|
|
1094
|
-
font-weight: 600;
|
|
1095
|
-
color: var(--primary-foreground);
|
|
1096
|
-
background: var(--primary);
|
|
1097
|
-
border-radius: 999px;
|
|
1098
|
-
line-height: 1;
|
|
1099
|
-
}
|
|
1100
|
-
|
|
1101
|
-
.sk-modal {
|
|
1102
|
-
position: relative;
|
|
1103
|
-
width: 16rem;
|
|
1104
|
-
height: 10rem;
|
|
1105
|
-
background: var(--td-material-bg);
|
|
1106
|
-
box-shadow: var(--td-material-shadow);
|
|
1107
|
-
border: 0;
|
|
1108
|
-
border-radius: 12px;
|
|
1109
|
-
padding: 1rem;
|
|
1110
|
-
display: flex;
|
|
1111
|
-
flex-direction: column;
|
|
1112
|
-
gap: 0.4375rem;
|
|
1113
|
-
}
|
|
1114
|
-
.sk-modal .sk-mtitle {
|
|
1115
|
-
width: 60%;
|
|
1116
|
-
height: 12px;
|
|
1117
|
-
}
|
|
1118
|
-
.sk-modal .sk-mclose {
|
|
1119
|
-
position: absolute;
|
|
1120
|
-
top: 0.875rem;
|
|
1121
|
-
right: 0.875rem;
|
|
1122
|
-
width: 14px;
|
|
1123
|
-
height: 14px;
|
|
1124
|
-
border-radius: 50%;
|
|
1125
|
-
}
|
|
1126
|
-
.sk-modal .sk-line {
|
|
1127
|
-
height: 8px;
|
|
1128
|
-
}
|
|
1129
|
-
.sk-modal .sk-line.full {
|
|
1130
|
-
width: 100%;
|
|
1131
|
-
}
|
|
1132
|
-
.sk-modal .sk-line.three-q {
|
|
1133
|
-
width: 75%;
|
|
1134
|
-
}
|
|
1135
|
-
.sk-modal .sk-pills {
|
|
1136
|
-
margin-top: auto;
|
|
1137
|
-
display: flex;
|
|
1138
|
-
gap: 0.5rem;
|
|
1139
|
-
}
|
|
1140
|
-
.sk-modal .sk-pill {
|
|
1141
|
-
width: 4.25rem;
|
|
1142
|
-
height: 1.375rem;
|
|
1143
|
-
border-radius: 999px;
|
|
1144
|
-
}
|
|
1145
|
-
|
|
1146
|
-
.dropdown-stack {
|
|
1147
|
-
position: relative;
|
|
1148
|
-
display: flex;
|
|
1149
|
-
flex-direction: column;
|
|
1150
|
-
align-items: center;
|
|
1151
|
-
gap: 0.5rem;
|
|
1152
|
-
}
|
|
1153
|
-
.sk-trigger {
|
|
1154
|
-
width: 7rem;
|
|
1155
|
-
height: 2rem;
|
|
1156
|
-
background: var(--td-material-bg);
|
|
1157
|
-
box-shadow: var(--td-material-shadow);
|
|
1158
|
-
border-radius: 8px;
|
|
1159
|
-
}
|
|
1160
|
-
.sk-dropdown {
|
|
1161
|
-
width: 11rem;
|
|
1162
|
-
padding: 0.625rem;
|
|
1163
|
-
background: var(--td-material-bg);
|
|
1164
|
-
box-shadow: var(--td-material-shadow);
|
|
1165
|
-
border: 0;
|
|
1166
|
-
border-radius: 10px;
|
|
1167
|
-
display: flex;
|
|
1168
|
-
flex-direction: column;
|
|
1169
|
-
gap: 0.4375rem;
|
|
1170
|
-
}
|
|
1171
|
-
.sk-dropdown .sk-row {
|
|
1172
|
-
height: 9px;
|
|
1173
|
-
}
|
|
1174
|
-
.sk-dropdown .sk-row.full {
|
|
1175
|
-
width: 100%;
|
|
1176
|
-
}
|
|
1177
|
-
.sk-dropdown .sk-row.three-q {
|
|
1178
|
-
width: 75%;
|
|
1179
|
-
}
|
|
1180
|
-
.sk-dropdown .sk-row.half {
|
|
1181
|
-
width: 50%;
|
|
1182
|
-
}
|
|
1183
|
-
|
|
1184
|
-
.panel-clip {
|
|
1185
|
-
width: 100%;
|
|
1186
|
-
max-width: 16rem;
|
|
1187
|
-
height: 9rem;
|
|
1188
|
-
overflow: hidden;
|
|
1189
|
-
border-radius: 12px;
|
|
1190
|
-
background: var(--td-material-bg);
|
|
1191
|
-
box-shadow: var(--td-material-shadow);
|
|
1192
|
-
}
|
|
1193
|
-
.sk-panel {
|
|
1194
|
-
padding: 0.875rem;
|
|
1195
|
-
display: flex;
|
|
1196
|
-
flex-direction: column;
|
|
1197
|
-
gap: 0.625rem;
|
|
1198
|
-
}
|
|
1199
|
-
.sk-panel .sk-line {
|
|
1200
|
-
height: 9px;
|
|
1201
|
-
}
|
|
1202
|
-
.sk-panel .sk-line.full {
|
|
1203
|
-
width: 100%;
|
|
1204
|
-
}
|
|
1205
|
-
.sk-panel .sk-line.three-q {
|
|
1206
|
-
width: 75%;
|
|
1207
|
-
}
|
|
1208
|
-
.sk-panel .sk-tiles {
|
|
1209
|
-
display: grid;
|
|
1210
|
-
grid-template-columns: repeat(2, 1fr);
|
|
1211
|
-
gap: 0.5rem;
|
|
1212
|
-
margin-top: 0.25rem;
|
|
1213
|
-
}
|
|
1214
|
-
.sk-panel .sk-tile {
|
|
1215
|
-
height: 2.25rem;
|
|
1216
|
-
}
|
|
1217
|
-
|
|
1218
|
-
.sk-page-stage {
|
|
1219
|
-
position: relative;
|
|
1220
|
-
width: 16rem;
|
|
1221
|
-
height: 10rem;
|
|
1222
|
-
background: var(--td-material-bg);
|
|
1223
|
-
box-shadow: var(--td-material-shadow);
|
|
1224
|
-
border-radius: 12px;
|
|
1225
|
-
overflow: hidden;
|
|
1226
|
-
}
|
|
1227
|
-
.sk-page {
|
|
1228
|
-
padding: 1rem;
|
|
1229
|
-
display: flex;
|
|
1230
|
-
flex-direction: column;
|
|
1231
|
-
gap: 0.5rem;
|
|
1232
|
-
}
|
|
1233
|
-
.sk-page .sk-row {
|
|
1234
|
-
height: 10px;
|
|
1235
|
-
}
|
|
1236
|
-
.sk-page .sk-row.full {
|
|
1237
|
-
width: 100%;
|
|
1238
|
-
}
|
|
1239
|
-
.sk-page .sk-row.three-q {
|
|
1240
|
-
width: 75%;
|
|
1241
|
-
}
|
|
1242
|
-
.sk-page .sk-row.half {
|
|
1243
|
-
width: 50%;
|
|
1244
|
-
}
|
|
1245
|
-
.sk-page-2 {
|
|
1246
|
-
align-items: center;
|
|
1247
|
-
justify-content: center;
|
|
1248
|
-
gap: 0.625rem;
|
|
1249
|
-
}
|
|
1250
|
-
.sk-amount {
|
|
1251
|
-
font-size: 2rem;
|
|
1252
|
-
font-weight: 600;
|
|
1253
|
-
color: var(--td-text, var(--foreground));
|
|
1254
|
-
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
1255
|
-
}
|
|
1256
|
-
.sk-pill-row {
|
|
1257
|
-
display: flex;
|
|
1258
|
-
gap: 0.375rem;
|
|
1259
|
-
}
|
|
1260
|
-
.sk-mini-pill {
|
|
1261
|
-
width: 2.5rem;
|
|
1262
|
-
height: 1.25rem;
|
|
1263
|
-
border-radius: 999px;
|
|
1264
|
-
}
|
|
1265
|
-
|
|
1266
|
-
.icon-stack {
|
|
1267
|
-
display: inline-grid;
|
|
1268
|
-
place-items: center;
|
|
1269
|
-
width: 3.5rem;
|
|
1270
|
-
height: 3.5rem;
|
|
1271
|
-
border-radius: 12px;
|
|
1272
|
-
background: var(--td-material-bg);
|
|
1273
|
-
box-shadow: var(--td-material-shadow);
|
|
1274
|
-
color: var(--td-icon-color, var(--foreground));
|
|
1275
|
-
--icon-swap-dur: 220ms;
|
|
1276
|
-
}
|
|
1277
|
-
.icon-stack :global(.t-icon) {
|
|
1278
|
-
display: inline-flex;
|
|
1279
|
-
align-items: center;
|
|
1280
|
-
justify-content: center;
|
|
1281
|
-
}
|
|
1282
|
-
|
|
1283
|
-
.check-badge {
|
|
1284
|
-
display: inline-flex;
|
|
1285
|
-
align-items: center;
|
|
1286
|
-
justify-content: center;
|
|
1287
|
-
width: 4rem;
|
|
1288
|
-
height: 4rem;
|
|
1289
|
-
border-radius: 50%;
|
|
1290
|
-
background: oklch(0.66 0.16 155);
|
|
1291
|
-
color: #fff;
|
|
1292
|
-
}
|
|
1293
|
-
.check-badge :global(.t-success-check svg) {
|
|
1294
|
-
width: 2.25rem;
|
|
1295
|
-
height: 2.25rem;
|
|
1296
|
-
}
|
|
1297
|
-
|
|
1298
|
-
.avatar-row {
|
|
1299
|
-
display: inline-flex;
|
|
1300
|
-
}
|
|
1301
|
-
.avatar-chip {
|
|
1302
|
-
display: inline-flex;
|
|
1303
|
-
align-items: center;
|
|
1304
|
-
justify-content: center;
|
|
1305
|
-
width: 2.75rem;
|
|
1306
|
-
height: 2.75rem;
|
|
1307
|
-
margin-left: -0.625rem;
|
|
1308
|
-
border-radius: 50%;
|
|
1309
|
-
background: var(--td-material-bg);
|
|
1310
|
-
box-shadow: var(--td-material-shadow);
|
|
1311
|
-
border: 2px solid var(--td-stage-bg);
|
|
1312
|
-
color: var(--td-text);
|
|
1313
|
-
font-size: 0.875rem;
|
|
1314
|
-
font-weight: 600;
|
|
1315
|
-
cursor: default;
|
|
1316
|
-
}
|
|
1317
|
-
.avatar-chip:first-child {
|
|
1318
|
-
margin-left: 0;
|
|
1319
|
-
}
|
|
1320
|
-
|
|
1321
|
-
.shake-wrap {
|
|
1322
|
-
display: flex;
|
|
1323
|
-
flex-direction: column;
|
|
1324
|
-
gap: 0.5rem;
|
|
1325
|
-
width: 13rem;
|
|
1326
|
-
}
|
|
1327
|
-
.shake-input {
|
|
1328
|
-
display: flex;
|
|
1329
|
-
align-items: center;
|
|
1330
|
-
height: 2.5rem;
|
|
1331
|
-
padding: 0 0.75rem;
|
|
1332
|
-
border: 1.5px solid var(--border);
|
|
1333
|
-
border-radius: 8px;
|
|
1334
|
-
background: var(--td-material-bg);
|
|
1335
|
-
color: var(--td-text-subtle);
|
|
1336
|
-
font-size: 0.875rem;
|
|
1337
|
-
}
|
|
1338
|
-
.shake-input.is-error {
|
|
1339
|
-
border-color: var(--destructive);
|
|
1340
|
-
}
|
|
1341
|
-
.shake-msg {
|
|
1342
|
-
margin: 0;
|
|
1343
|
-
font-size: 0.75rem;
|
|
1344
|
-
color: var(--destructive);
|
|
1345
|
-
}
|
|
1346
|
-
|
|
1347
|
-
.clear-field {
|
|
1348
|
-
width: 14rem;
|
|
1349
|
-
height: 2.75rem;
|
|
1350
|
-
border-radius: 10px;
|
|
1351
|
-
background: var(--td-material-bg);
|
|
1352
|
-
box-shadow: var(--td-material-shadow);
|
|
1353
|
-
}
|
|
1354
|
-
.clear-input {
|
|
1355
|
-
width: 100%;
|
|
1356
|
-
height: 100%;
|
|
1357
|
-
padding: 0 2.25rem 0 0.75rem;
|
|
1358
|
-
border: 0;
|
|
1359
|
-
background: transparent;
|
|
1360
|
-
outline: none;
|
|
1361
|
-
font: inherit;
|
|
1362
|
-
font-size: 0.9375rem;
|
|
1363
|
-
color: var(--td-text);
|
|
1364
|
-
}
|
|
1365
|
-
.clear-text {
|
|
1366
|
-
padding-left: 0.75rem;
|
|
1367
|
-
font-size: 0.9375rem;
|
|
1368
|
-
color: var(--td-text);
|
|
1369
|
-
}
|
|
1370
|
-
.clear-ph {
|
|
1371
|
-
color: var(--td-text-subtle);
|
|
1372
|
-
}
|
|
1373
|
-
.clear-x {
|
|
1374
|
-
position: absolute;
|
|
1375
|
-
top: 50%;
|
|
1376
|
-
right: 0.5rem;
|
|
1377
|
-
transform: translateY(-50%);
|
|
1378
|
-
z-index: 4;
|
|
1379
|
-
display: inline-flex;
|
|
1380
|
-
align-items: center;
|
|
1381
|
-
justify-content: center;
|
|
1382
|
-
width: 1.5rem;
|
|
1383
|
-
height: 1.5rem;
|
|
1384
|
-
border: 0;
|
|
1385
|
-
border-radius: 50%;
|
|
1386
|
-
background: var(--td-copy-bg);
|
|
1387
|
-
color: var(--td-icon-color-muted);
|
|
1388
|
-
cursor: pointer;
|
|
1389
|
-
}
|
|
1390
|
-
.clear-x:hover {
|
|
1391
|
-
background: var(--td-copy-bg-hover);
|
|
1392
|
-
color: var(--td-icon-color);
|
|
1393
|
-
}
|
|
1394
|
-
|
|
1395
|
-
.skel-card {
|
|
1396
|
-
width: 14rem;
|
|
1397
|
-
height: 4.5rem;
|
|
1398
|
-
background: var(--td-material-bg);
|
|
1399
|
-
box-shadow: var(--td-material-shadow);
|
|
1400
|
-
border-radius: 12px;
|
|
1401
|
-
}
|
|
1402
|
-
.skel-layer {
|
|
1403
|
-
display: flex;
|
|
1404
|
-
align-items: center;
|
|
1405
|
-
gap: 0.75rem;
|
|
1406
|
-
padding: 0 1rem;
|
|
1407
|
-
}
|
|
1408
|
-
.skel-avatar {
|
|
1409
|
-
flex: none;
|
|
1410
|
-
width: 2.5rem;
|
|
1411
|
-
height: 2.5rem;
|
|
1412
|
-
border-radius: 50%;
|
|
1413
|
-
}
|
|
1414
|
-
.skel-bars {
|
|
1415
|
-
display: flex;
|
|
1416
|
-
flex-direction: column;
|
|
1417
|
-
gap: 0.5rem;
|
|
1418
|
-
}
|
|
1419
|
-
.skel-l1 {
|
|
1420
|
-
width: 6rem;
|
|
1421
|
-
height: 9px;
|
|
1422
|
-
}
|
|
1423
|
-
.skel-l2 {
|
|
1424
|
-
width: 4rem;
|
|
1425
|
-
height: 9px;
|
|
1426
|
-
}
|
|
1427
|
-
.skel-avatar-real {
|
|
1428
|
-
flex: none;
|
|
1429
|
-
display: inline-flex;
|
|
1430
|
-
align-items: center;
|
|
1431
|
-
justify-content: center;
|
|
1432
|
-
width: 2.5rem;
|
|
1433
|
-
height: 2.5rem;
|
|
1434
|
-
border-radius: 50%;
|
|
1435
|
-
background: var(--primary);
|
|
1436
|
-
color: var(--primary-foreground);
|
|
1437
|
-
font-size: 0.875rem;
|
|
1438
|
-
font-weight: 600;
|
|
1439
|
-
}
|
|
1440
|
-
.skel-lines {
|
|
1441
|
-
display: flex;
|
|
1442
|
-
flex-direction: column;
|
|
1443
|
-
gap: 0.125rem;
|
|
1444
|
-
}
|
|
1445
|
-
.skel-name {
|
|
1446
|
-
font-size: 0.875rem;
|
|
1447
|
-
font-weight: 600;
|
|
1448
|
-
color: var(--td-text);
|
|
1449
|
-
}
|
|
1450
|
-
.skel-sub {
|
|
1451
|
-
font-size: 0.75rem;
|
|
1452
|
-
color: var(--td-text-subtle);
|
|
1453
|
-
}
|
|
1454
|
-
|
|
1455
|
-
.shimmer-demo {
|
|
1456
|
-
font-size: 1.125rem;
|
|
1457
|
-
font-weight: 500;
|
|
1458
|
-
--shimmer-base: var(--td-text-subtle);
|
|
1459
|
-
--shimmer-highlight: var(--td-text);
|
|
1460
|
-
}
|
|
1461
|
-
|
|
1462
|
-
.tabs-demo {
|
|
1463
|
-
font-size: 0.8125rem;
|
|
1464
|
-
font-weight: 500;
|
|
1465
|
-
--tabs-bar-bg: color-mix(in srgb, var(--td-text) 8%, transparent);
|
|
1466
|
-
--tabs-pill-bg: var(--td-material-bg);
|
|
1467
|
-
--tabs-text-muted: var(--td-text-subtle);
|
|
1468
|
-
--tabs-text-active: var(--td-text);
|
|
1469
|
-
}
|
|
1470
|
-
.tabs-demo :global(.t-tabs-pill) {
|
|
1471
|
-
box-shadow: var(--td-material-shadow);
|
|
1472
|
-
}
|
|
1473
|
-
|
|
1474
|
-
.tt-trigger {
|
|
1475
|
-
display: inline-flex;
|
|
1476
|
-
align-items: center;
|
|
1477
|
-
justify-content: center;
|
|
1478
|
-
width: 2.75rem;
|
|
1479
|
-
height: 2.75rem;
|
|
1480
|
-
border: 0;
|
|
1481
|
-
border-radius: 10px;
|
|
1482
|
-
background: var(--td-material-bg);
|
|
1483
|
-
box-shadow: var(--td-material-shadow);
|
|
1484
|
-
color: var(--td-icon-color);
|
|
1485
|
-
cursor: pointer;
|
|
1486
|
-
}
|
|
1487
|
-
.tt-bubble {
|
|
1488
|
-
font-size: 0.8125rem;
|
|
1489
|
-
font-weight: 500;
|
|
1490
|
-
--tt-bg: var(--td-material-bg);
|
|
1491
|
-
--tt-fg: var(--td-text);
|
|
1492
|
-
}
|
|
1493
|
-
|
|
1494
|
-
.stagger-demo {
|
|
1495
|
-
display: flex;
|
|
1496
|
-
flex-direction: column;
|
|
1497
|
-
gap: 0.375rem;
|
|
1498
|
-
max-width: 14rem;
|
|
1499
|
-
text-align: center;
|
|
1500
|
-
}
|
|
1501
|
-
.stagger-head {
|
|
1502
|
-
font-size: 1.25rem;
|
|
1503
|
-
font-weight: 600;
|
|
1504
|
-
color: var(--td-text);
|
|
1505
|
-
letter-spacing: -0.01em;
|
|
1506
|
-
}
|
|
1507
|
-
.stagger-sub {
|
|
1508
|
-
font-size: 0.875rem;
|
|
1509
|
-
color: var(--td-text-subtle);
|
|
1510
|
-
}
|
|
1511
|
-
/* ---- the nine added 14 Sep 2026 ---- */
|
|
1512
|
-
.acc-demo {
|
|
1513
|
-
width: min(24rem, 100%);
|
|
1514
|
-
background: var(--td-material-bg);
|
|
1515
|
-
box-shadow: var(--td-material-shadow);
|
|
1516
|
-
border-radius: 10px;
|
|
1517
|
-
}
|
|
1518
|
-
|
|
1519
|
-
.acc-head {
|
|
1520
|
-
display: flex;
|
|
1521
|
-
align-items: center;
|
|
1522
|
-
justify-content: space-between;
|
|
1523
|
-
gap: 1rem;
|
|
1524
|
-
width: 100%;
|
|
1525
|
-
padding: 0.75rem 0.875rem;
|
|
1526
|
-
font-size: 0.875rem;
|
|
1527
|
-
font-weight: 500;
|
|
1528
|
-
color: var(--td-text);
|
|
1529
|
-
background: none;
|
|
1530
|
-
border: 0;
|
|
1531
|
-
cursor: pointer;
|
|
1532
|
-
}
|
|
1533
|
-
|
|
1534
|
-
.acc-body {
|
|
1535
|
-
margin: 0;
|
|
1536
|
-
padding: 0 0.875rem 0.875rem;
|
|
1537
|
-
font-size: 0.8125rem;
|
|
1538
|
-
line-height: 1.55;
|
|
1539
|
-
color: var(--td-text-subtle);
|
|
1540
|
-
}
|
|
1541
|
-
|
|
1542
|
-
.tilt-card {
|
|
1543
|
-
display: flex;
|
|
1544
|
-
flex-direction: column;
|
|
1545
|
-
gap: 0.25rem;
|
|
1546
|
-
width: 13rem;
|
|
1547
|
-
padding: 1.125rem;
|
|
1548
|
-
background: var(--td-material-bg);
|
|
1549
|
-
box-shadow: var(--td-material-shadow);
|
|
1550
|
-
color: var(--td-text);
|
|
1551
|
-
font-size: 0.8125rem;
|
|
1552
|
-
}
|
|
1553
|
-
|
|
1554
|
-
.tilt-price {
|
|
1555
|
-
font-size: 1.5rem;
|
|
1556
|
-
font-weight: 600;
|
|
1557
|
-
letter-spacing: -0.02em;
|
|
1558
|
-
}
|
|
1559
|
-
|
|
1560
|
-
.tilt-note {
|
|
1561
|
-
color: var(--td-text-subtle);
|
|
1562
|
-
}
|
|
1563
|
-
|
|
1564
|
-
.learn-demo,
|
|
1565
|
-
.like-demo {
|
|
1566
|
-
display: inline-flex;
|
|
1567
|
-
align-items: center;
|
|
1568
|
-
gap: 0.4375rem;
|
|
1569
|
-
padding: 0.5rem 0.875rem;
|
|
1570
|
-
font-size: 0.875rem;
|
|
1571
|
-
font-weight: 500;
|
|
1572
|
-
color: var(--td-text);
|
|
1573
|
-
background: var(--td-copy-bg);
|
|
1574
|
-
border: 0;
|
|
1575
|
-
border-radius: 8px;
|
|
1576
|
-
cursor: pointer;
|
|
1577
|
-
}
|
|
1578
|
-
|
|
1579
|
-
.like-demo {
|
|
1580
|
-
position: relative;
|
|
1581
|
-
}
|
|
1582
|
-
|
|
1583
|
-
/* The anchor is sized to the open footprint, the way the usage note asks:
|
|
1584
|
-
without it the morph grows the stage and every demo under it jumps. */
|
|
1585
|
-
.morph-anchor {
|
|
1586
|
-
position: relative;
|
|
1587
|
-
width: 11rem;
|
|
1588
|
-
height: 7.5rem;
|
|
1589
|
-
}
|
|
1590
|
-
|
|
1591
|
-
.morph-demo {
|
|
1592
|
-
position: absolute;
|
|
1593
|
-
inset-block-start: 0;
|
|
1594
|
-
inset-inline-start: 0;
|
|
1595
|
-
background: var(--td-material-bg);
|
|
1596
|
-
box-shadow: var(--td-material-shadow);
|
|
1597
|
-
}
|
|
1598
|
-
|
|
1599
|
-
.morph-menu {
|
|
1600
|
-
display: flex;
|
|
1601
|
-
flex-direction: column;
|
|
1602
|
-
gap: 0.5rem;
|
|
1603
|
-
padding: 0.75rem 0.875rem;
|
|
1604
|
-
font-size: 0.8125rem;
|
|
1605
|
-
color: var(--td-text);
|
|
1606
|
-
}
|
|
1607
|
-
|
|
1608
|
-
.morph-plus {
|
|
1609
|
-
display: inline-flex;
|
|
1610
|
-
align-items: center;
|
|
1611
|
-
justify-content: center;
|
|
1612
|
-
color: var(--td-text);
|
|
1613
|
-
background: none;
|
|
1614
|
-
border: 0;
|
|
1615
|
-
cursor: pointer;
|
|
1616
|
-
}
|
|
1617
|
-
|
|
1618
|
-
.reel-demo {
|
|
1619
|
-
font-size: 2rem;
|
|
1620
|
-
font-weight: 600;
|
|
1621
|
-
font-family: ui-monospace, SFMono-Regular, monospace;
|
|
1622
|
-
color: var(--td-text);
|
|
1623
|
-
}
|
|
1624
|
-
|
|
1625
|
-
.stream-demo {
|
|
1626
|
-
margin: 0;
|
|
1627
|
-
max-width: 32rem;
|
|
1628
|
-
font-size: 0.9375rem;
|
|
1629
|
-
line-height: 1.6;
|
|
1630
|
-
color: var(--td-text);
|
|
1631
|
-
}
|
|
1632
|
-
|
|
1633
|
-
.reason-demo {
|
|
1634
|
-
width: min(26rem, 100%);
|
|
1635
|
-
height: 7rem;
|
|
1636
|
-
padding: 0.875rem 1rem;
|
|
1637
|
-
background: var(--td-material-bg);
|
|
1638
|
-
box-shadow: var(--td-material-shadow);
|
|
1639
|
-
border-radius: 10px;
|
|
1640
|
-
--reason-line: 1.5rem;
|
|
1641
|
-
}
|
|
1642
|
-
|
|
1643
|
-
.reason-line {
|
|
1644
|
-
margin: 0;
|
|
1645
|
-
height: 1.5rem;
|
|
1646
|
-
font-size: 0.8125rem;
|
|
1647
|
-
line-height: 1.5rem;
|
|
1648
|
-
color: var(--td-text-subtle);
|
|
1649
|
-
white-space: nowrap;
|
|
1650
|
-
overflow: hidden;
|
|
1651
|
-
text-overflow: ellipsis;
|
|
1652
|
-
}
|
|
1653
|
-
|
|
1654
|
-
.think-demo {
|
|
1655
|
-
font-size: 0.9375rem;
|
|
1656
|
-
color: var(--td-text-subtle);
|
|
1657
|
-
}
|
|
1658
|
-
</style>
|