@deckio/deck-engine 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,91 @@
1
+ ---
2
+ name: deck-sketch
3
+ description: Sketch a slide on Whiteboard, capture the sketch, and use it as inspiration to create a new slide. Use this when the user wants to draw, sketch, or wireframe a slide before building it.
4
+ ---
5
+
6
+ # Sketch a Slide
7
+
8
+ Use Whiteboard to sketch a slide layout, capture the result, and translate it into a real slide component.
9
+
10
+ ## Workflow
11
+
12
+ ### Step 1 — Open Whiteboard
13
+
14
+ ```powershell
15
+ Start-Process "ms-whiteboard-cmd:"
16
+ ```
17
+
18
+ Tell the user:
19
+
20
+ > **Whiteboard is open. Sketch your slide layout. When you're done, use "Fit to screen" (Ctrl+Shift+F) so the entire sketch is visible, then tell me you're ready.**
21
+
22
+ **STOP here.** Do NOT proceed until the user explicitly says the sketch is ready.
23
+
24
+ ### Step 2 — Capture the sketch
25
+
26
+ When the user says the sketch is ready:
27
+
28
+ ```powershell
29
+ Add-Type @"
30
+ using System;
31
+ using System.Runtime.InteropServices;
32
+ using System.Drawing;
33
+ public class WinCapture {
34
+ [DllImport("user32.dll")] public static extern bool SetForegroundWindow(IntPtr h);
35
+ [DllImport("user32.dll")] public static extern bool GetWindowRect(IntPtr h, out RECT r);
36
+ [DllImport("user32.dll")] public static extern bool SetProcessDPIAware();
37
+ [StructLayout(LayoutKind.Sequential)] public struct RECT { public int L, T, R, B; }
38
+ }
39
+ "@
40
+ [WinCapture]::SetProcessDPIAware() | Out-Null
41
+ Add-Type -AssemblyName System.Drawing
42
+ $h = (Get-Process | Where-Object { $_.MainWindowTitle -like '*Whiteboard*' } | Select-Object -First 1).MainWindowHandle
43
+ if (!$h -or $h -eq [IntPtr]::Zero) { Write-Error "Whiteboard window not found"; return }
44
+ [WinCapture]::SetForegroundWindow($h) | Out-Null
45
+ Start-Sleep -Milliseconds 500
46
+ $r = New-Object WinCapture+RECT
47
+ [WinCapture]::GetWindowRect($h, [ref]$r) | Out-Null
48
+ $w = $r.R - $r.L; $ht = $r.B - $r.T
49
+ $bmp = New-Object Drawing.Bitmap $w, $ht
50
+ $g = [Drawing.Graphics]::FromImage($bmp)
51
+ $g.CopyFromScreen($r.L, $r.T, 0, 0, (New-Object Drawing.Size $w, $ht))
52
+ $dir = ".github\eyes"
53
+ if (!(Test-Path $dir)) { New-Item -ItemType Directory -Path $dir -Force | Out-Null }
54
+ $file = Join-Path $dir "sketch-$(Get-Date -Format 'yyyy-MM-ddTHH-mm-ss').png"
55
+ $bmp.Save($file)
56
+ $g.Dispose(); $bmp.Dispose()
57
+ Write-Host "Sketch saved: $file"
58
+ ```
59
+
60
+ ### Step 3 — Analyze the sketch
61
+
62
+ Reference the saved screenshot image. Study it carefully and identify:
63
+
64
+ - **Layout structure** — columns/rows, content zones, header/footer areas.
65
+ - **Text elements** — headings, labels, bullet points, callouts.
66
+ - **Visual elements** — boxes, icons, images, dividers, backgrounds.
67
+ - **Data patterns** — tables, grids, lists, charts, metrics.
68
+
69
+ Describe what you see back to the user and confirm your interpretation.
70
+
71
+ ### Step 4 — Create the slide
72
+
73
+ Use the **deck-add-slide** skill to build the slide, guided by the sketch:
74
+
75
+ 1. Map sketch regions to CSS Grid or Flexbox layout.
76
+ 2. Translate hand-drawn text into real content with proper typography.
77
+ 3. Replace rough shapes with styled `<div>` containers using CSS Modules.
78
+ 4. Follow all deck-add-slide conventions (accent-bar, content-frame, BottomBar, imports from `@deckio/deck-engine`).
79
+ 5. Register the slide in `deck.config.js`.
80
+
81
+ ### Step 5 — Visual verification
82
+
83
+ After creating the slide, use **deck-eyes** to capture a screenshot of the rendered result.
84
+
85
+ Compare the rendered slide against the original sketch. If the user is present, show both and ask if adjustments are needed.
86
+
87
+ ## Notes
88
+
89
+ - Whiteboard sketches are rough — interpret intent, not exact pixels.
90
+ - If text is hard to read, ask the user to clarify.
91
+ - Screenshots are saved under `.github/eyes/` (gitignored) with a `sketch-` prefix.
@@ -0,0 +1,81 @@
1
+ ---
2
+ name: deck-validate-project
3
+ description: Validate and audit a deck project for correctness. Use this when asked to validate, audit, polish, review, check, or verify slides.
4
+ ---
5
+
6
+ # Validate & Audit a Deck Project
7
+
8
+ ## Step 1: Audit deck.config.js
9
+
10
+ Open `deck.config.js` and verify:
11
+
12
+ ### 1a. All imports resolve
13
+
14
+ For each slide import at the top of the file, verify the target file exists in `src/slides/`.
15
+
16
+ ### 1b. slides array matches imports
17
+
18
+ - Every imported slide should appear in the `slides` array.
19
+ - No unused imports (imported but not in the array).
20
+ - No undefined entries in the array (in array but not imported).
21
+
22
+ ---
23
+
24
+ ## Step 2: Verify slide structure
25
+
26
+ For each slide `.jsx` file in `src/slides/`, verify:
27
+
28
+ - [ ] Imports `{ Slide }` and `{ BottomBar }` from `'@deckio/deck-engine'`
29
+ - [ ] Wrapped in `<Slide index={index} className={styles.xxx}>` (accepts `index` as prop)
30
+ - [ ] Contains `<div className="accent-bar" />` as first child
31
+ - [ ] Contains at least one decorative orb
32
+ - [ ] Content is inside `<div className="content-frame content-gutter">`
33
+ - [ ] `<BottomBar />` is the **last child** inside `<Slide>`
34
+ - [ ] `BottomBar text` is consistent across all slides in the project
35
+
36
+ For each `.module.css` file, verify the root class has:
37
+ - [ ] `background: var(--bg-deep)`
38
+ - [ ] `padding: 0 0 44px 0`
39
+ - [ ] Does NOT use `flex: 1` on the body wrapper (defeats vertical centering)
40
+ - [ ] Does NOT redundantly set `flex-direction: column` (inherited from engine `.slide` class)
41
+
42
+ ---
43
+
44
+ ## Step 3: Check companion files
45
+
46
+ - Every `.jsx` slide in `src/slides/` should have a matching `.module.css` file
47
+ - No orphaned `.module.css` files without a matching `.jsx`
48
+
49
+ ---
50
+
51
+ ## Step 4: Verify metadata
52
+
53
+ Check `deck.config.js` exports these fields:
54
+ - [ ] `id` — string, matches the project folder name convention
55
+ - [ ] `title` — display name
56
+ - [ ] `subtitle` — tagline
57
+ - [ ] `icon` — emoji
58
+ - [ ] `accent` — CSS color value
59
+ - [ ] `slides` — non-empty array
60
+
61
+ ---
62
+
63
+ ## Step 5: Report results
64
+
65
+ Summarize findings:
66
+
67
+ - Number of slides validated
68
+ - Any issues found and fixed (missing files, broken imports, structural issues)
69
+ - Overall project health: **pass** or **issues found**
70
+
71
+ ---
72
+
73
+ ## Quick checklist
74
+
75
+ - [ ] All imports in `deck.config.js` resolve to existing files
76
+ - [ ] `slides` array matches imports (no unused, no missing)
77
+ - [ ] Every `.jsx` slide has a companion `.module.css`
78
+ - [ ] All slides have accent-bar, content-frame, BottomBar
79
+ - [ ] BottomBar text is consistent across the project
80
+ - [ ] CSS root classes have required properties (`background`, `padding`) and no `flex: 1` on body wrapper
81
+ - [ ] Project metadata (id, title, subtitle, icon, accent) is present
@@ -0,0 +1,31 @@
1
+ import Slide from '../components/Slide.jsx'
2
+ import BottomBar from '../components/BottomBar.jsx'
3
+
4
+ export default function GenericThankYouSlide({ index = 10, subtitle, tagline, footerText }) {
5
+ return (
6
+ <Slide index={index} className="deck-ty">
7
+ <div className="accent-bar" />
8
+
9
+ <div className="deck-ty-glow deck-ty-glow1" />
10
+ <div className="deck-ty-glow deck-ty-glow2" />
11
+ <div className="deck-ty-glow deck-ty-glow3" />
12
+
13
+ {[1, 2, 3, 4, 5, 6, 7, 8].map(i => (
14
+ <div key={i} className={`deck-ty-streak deck-ty-streak${i}`} />
15
+ ))}
16
+
17
+ <div className="content-frame content-gutter">
18
+ <div className="deck-ty-content">
19
+ <h2 className="deck-ty-title">Thank You</h2>
20
+ <p className="deck-ty-subtitle">
21
+ {subtitle || <>Let&rsquo;s build something great &mdash; together.</>}
22
+ </p>
23
+ <div className="deck-ty-divider" />
24
+ {tagline && <p className="deck-ty-tagline">{tagline}</p>}
25
+ </div>
26
+ </div>
27
+
28
+ <BottomBar text={footerText} />
29
+ </Slide>
30
+ )
31
+ }
@@ -0,0 +1,392 @@
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@300;400;500;600;700;800;900&display=swap');
2
+
3
+ /* ═══════════════════════════════════════════════════════════════════════════
4
+ DECKIO Design Token System
5
+ ═══════════════════════════════════════════════════════════════════════════
6
+
7
+ Token architecture aligned with shadcn/ui naming conventions for
8
+ multi-theme compatibility, extended with presentation-specific tokens.
9
+
10
+ LAYER STRATEGY (Tailwind v4 + shadcn/ui compatibility):
11
+ ────────────────────────────────────────────────────────
12
+ Tailwind v4 wraps its output in @layer directives. In the CSS cascade,
13
+ unlayered styles ALWAYS beat layered styles — regardless of specificity.
14
+ Without layers, our `* { margin: 0 }` would override every Tailwind
15
+ utility (`p-4`, `m-2`, etc.), breaking shadcn/ui components entirely.
16
+
17
+ We declare the canonical layer order up front (global.css is imported
18
+ before theme CSS), then place engine styles in the appropriate layers:
19
+ @layer base — token defaults, reset, html/body
20
+ @layer components — engine component styles (.slide, .deck, etc.)
21
+ Theme CSS `:root` blocks remain unlayered (highest priority).
22
+ Tailwind utilities live in @layer utilities and override components.
23
+
24
+ CATEGORIES:
25
+
26
+ 1. Core Semantic Colors (shadcn-aligned)
27
+ --background / --foreground Page-level background & text
28
+ --card / --card-foreground Card / panel surfaces
29
+ --primary / --primary-foreground Brand / action color
30
+ --secondary / --secondary-foreground Subtle surfaces (panels, kbd)
31
+ --muted / --muted-foreground Muted text & backgrounds
32
+ --accent / --accent-foreground Accent highlights (= primary in dark theme)
33
+ --destructive / --destructive-foreground Errors & warnings
34
+ --border Default border
35
+ --input Form input borders
36
+ --ring Focus ring color
37
+ --radius Default border radius
38
+
39
+ 2. Decorative Palette
40
+ --purple, --purple-deep, --pink, --cyan, --green
41
+ --blue-glow Glow base for interactive elements
42
+
43
+ 3. Derived Overlays & Glows
44
+ Translucent surfaces, glow effects, and shadows. Explicit tokens
45
+ (not computed) so each theme can override independently.
46
+
47
+ 4. Presentation Layout
48
+ --slide-bg, --content-max-width, --content-gutter
49
+
50
+ 5. Typography Scale
51
+ Font family, sizes (2xs → display), weights, letter-spacing, line-height
52
+
53
+ 6. Spacing Scale (4 px base)
54
+ --space-0 through --space-14
55
+
56
+ 7. Border Radius Scale
57
+ --radius-sm through --radius-full
58
+
59
+ 8. Z-Index Scale
60
+ Named layers: content → bar → nav → progress → overlay
61
+
62
+ 9. Transitions
63
+ Duration + easing presets
64
+
65
+ THEMING:
66
+ Override any token in :root for a global theme, or scope overrides to a
67
+ class (e.g. .theme-light, .theme-shadcn) for per-section theming.
68
+ Current values represent the "dark" theme (default).
69
+ ═══════════════════════════════════════════════════════════════════════════ */
70
+
71
+ /* Establish canonical layer order — must come before any @layer blocks.
72
+ Tailwind v4 uses these exact names; declaring them here (global.css is
73
+ imported first) guarantees the ordering is: theme < base < components < utilities. */
74
+ @layer theme, base, components, utilities;
75
+
76
+ /* ── Base layer: token defaults + reset ─────────────────────────────────── */
77
+ @layer base {
78
+
79
+ :root {
80
+ /* ── 1. Core Semantic Colors (shadcn-aligned) ────────────────────────── */
81
+ --background: #080b10;
82
+ --foreground: #e6edf3;
83
+ --card: #0d1117;
84
+ --card-foreground: #e6edf3;
85
+ --primary: #58a6ff;
86
+ --primary-foreground: #ffffff;
87
+ --secondary: #161b22;
88
+ --secondary-foreground: #e6edf3;
89
+ --muted: #161b22;
90
+ --muted-foreground: #8b949e;
91
+ --accent: #58a6ff;
92
+ --accent-foreground: #ffffff;
93
+ --destructive: #f85149;
94
+ --destructive-foreground: #ffffff;
95
+ --border: #30363d;
96
+ --input: #30363d;
97
+ --ring: #58a6ff;
98
+ --radius: 10px;
99
+
100
+ /* ── 2. Decorative Palette ───────────────────────────────────────────── */
101
+ --blue-glow: #1f6feb;
102
+ --purple: #bc8cff;
103
+ --purple-deep: #6e40c9;
104
+ --pink: #f778ba;
105
+ --cyan: #56d4dd;
106
+ --green: #3fb950;
107
+
108
+ /* ── 3. Derived Overlays & Glows ─────────────────────────────────────── */
109
+ --surface-overlay: rgba(22, 27, 34, 0.8);
110
+ --surface-overlay-heavy: rgba(22, 27, 34, 0.95);
111
+ --background-overlay: rgba(13, 17, 23, 0.85);
112
+ --border-subtle: rgba(48, 54, 61, 0.6);
113
+ --glow-primary: rgba(31, 111, 235, 0.2);
114
+ --glow-primary-strong: rgba(31, 111, 235, 0.22);
115
+ --glow-primary-shadow: rgba(31, 111, 235, 0.18);
116
+ --glow-ring: rgba(121, 192, 255, 0.18);
117
+ --glow-accent: rgba(88, 166, 255, 0.10);
118
+ --glow-purple: rgba(188, 140, 255, 0.10);
119
+ --glow-cyan: rgba(86, 212, 221, 0.08);
120
+ --dot-color: rgba(139, 148, 158, 0.25);
121
+ --destructive-subtle: rgba(248, 81, 73, 0.04);
122
+ --shadow-elevated: 0 8px 24px rgba(0, 0, 0, 0.4);
123
+
124
+ /* ── 4. Presentation Layout ──────────────────────────────────────────── */
125
+ --slide-bg: var(--background);
126
+ --content-max-width: 1280px;
127
+ --content-gutter: 72px;
128
+
129
+ /* ── 5. Typography Scale ─────────────────────────────────────────────── */
130
+ --font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
131
+ --font-size-2xs: 10px;
132
+ --font-size-xs: 11px;
133
+ --font-size-sm: 12px;
134
+ --font-size-md: 13px;
135
+ --font-size-base: 16px;
136
+ --font-size-lg: 20px;
137
+ --font-size-xl: 24px;
138
+ --font-size-2xl: 32px;
139
+ --font-size-display: clamp(40px, 6vw, 64px);
140
+
141
+ --font-weight-light: 300;
142
+ --font-weight-regular: 400;
143
+ --font-weight-medium: 500;
144
+ --font-weight-semibold: 600;
145
+ --font-weight-bold: 700;
146
+ --font-weight-extrabold: 800;
147
+
148
+ --letter-spacing-tight: -2px;
149
+ --letter-spacing-normal: 0;
150
+ --letter-spacing-wide: 0.5px;
151
+ --letter-spacing-wider: 2.5px;
152
+ --letter-spacing-widest: 3px;
153
+
154
+ --line-height-tight: 1.2;
155
+ --line-height-normal: 1.5;
156
+ --line-height-relaxed: 1.75;
157
+
158
+ /* ── 6. Spacing Scale (4 px base) ────────────────────────────────────── */
159
+ --space-0: 0px;
160
+ --space-0-5: 2px;
161
+ --space-1: 4px;
162
+ --space-1-5: 6px;
163
+ --space-2: 8px;
164
+ --space-3: 12px;
165
+ --space-4: 16px;
166
+ --space-5: 20px;
167
+ --space-6: 24px;
168
+ --space-8: 32px;
169
+ --space-10: 40px;
170
+ --space-11: 44px;
171
+ --space-12: 48px;
172
+ --space-14: 56px;
173
+
174
+ /* ── 7. Border Radius Scale ──────────────────────────────────────────── */
175
+ --radius-sm: 4px;
176
+ --radius-md: 6px;
177
+ --radius-lg: 10px;
178
+ --radius-xl: 20px;
179
+ --radius-full: 50%;
180
+
181
+ /* ── 8. Z-Index Scale ────────────────────────────────────────────────── */
182
+ --z-content: 2;
183
+ --z-bar: 100;
184
+ --z-nav: 200;
185
+ --z-progress: 300;
186
+ --z-overlay: 9999;
187
+
188
+ /* ── 9. Transitions ──────────────────────────────────────────────────── */
189
+ --transition-fast: 0.15s ease;
190
+ --transition-base: 0.25s ease;
191
+ --transition-slow: 0.4s ease;
192
+ --ease-slide: cubic-bezier(0.4, 0, 0.2, 1);
193
+ --duration-slide: 0.6s;
194
+ --duration-progress: 0.5s;
195
+ }
196
+
197
+ * { margin: 0; padding: 0; box-sizing: border-box; }
198
+
199
+ html, body, #root {
200
+ width: 100%; height: 100%;
201
+ overflow: hidden;
202
+ font-family: var(--font-family);
203
+ background: var(--background);
204
+ color: var(--foreground);
205
+ }
206
+
207
+ } /* end @layer base */
208
+
209
+ /* ── Components layer: engine chrome + slide primitives ─────────────────── */
210
+ @layer components {
211
+
212
+ /* ── Slide Engine ── */
213
+ .deck {
214
+ width: 100%; height: 100%;
215
+ position: relative;
216
+ }
217
+
218
+ .slide {
219
+ position: absolute;
220
+ inset: 0;
221
+ display: flex;
222
+ flex-direction: column;
223
+ justify-content: center;
224
+ align-items: stretch;
225
+ opacity: 0;
226
+ pointer-events: none;
227
+ transition: opacity var(--duration-slide) var(--ease-slide),
228
+ transform var(--duration-slide) var(--ease-slide);
229
+ transform: translateX(60px);
230
+ overflow: hidden;
231
+ }
232
+ .slide > * {
233
+ flex-grow: 0;
234
+ }
235
+ .slide.active {
236
+ opacity: 1;
237
+ pointer-events: auto;
238
+ transform: translateX(0);
239
+ }
240
+ .slide.exit-left {
241
+ opacity: 0;
242
+ transform: translateX(-60px);
243
+ }
244
+
245
+ /* ── Dev-mode overflow warning ── */
246
+ .slide-overflow-warn {
247
+ position: absolute;
248
+ inset: 0;
249
+ border: 3px dashed var(--destructive);
250
+ pointer-events: none;
251
+ z-index: var(--z-overlay);
252
+ display: flex;
253
+ align-items: flex-end;
254
+ justify-content: center;
255
+ padding-bottom: var(--space-14);
256
+ background: var(--destructive-subtle);
257
+ font-size: var(--font-size-md);
258
+ font-weight: var(--font-weight-semibold);
259
+ color: var(--destructive);
260
+ letter-spacing: 0.3px;
261
+ }
262
+
263
+ /* ── Shared Decorations ── */
264
+ .orb {
265
+ position: absolute;
266
+ border-radius: var(--radius-full);
267
+ filter: blur(2px);
268
+ opacity: 0.7;
269
+ }
270
+ .grid-dots {
271
+ position: absolute;
272
+ width: 200px; height: 200px;
273
+ background-image: radial-gradient(circle, var(--dot-color) 1px, transparent 1px);
274
+ background-size: 18px 18px;
275
+ opacity: 0.5;
276
+ }
277
+
278
+ /* Accent bar left */
279
+ .accent-bar {
280
+ position: absolute;
281
+ left: var(--space-12); top: 15%; bottom: 15%;
282
+ width: 4px;
283
+ border-radius: 2px;
284
+ background: linear-gradient(to bottom, var(--purple), var(--accent), var(--cyan));
285
+ }
286
+
287
+ /* ── Shared Layout ── */
288
+ .content-frame {
289
+ width: min(100%, var(--content-max-width));
290
+ margin-left: auto;
291
+ margin-right: auto;
292
+ }
293
+
294
+ .content-gutter {
295
+ padding-left: var(--content-gutter);
296
+ padding-right: var(--content-gutter);
297
+ }
298
+
299
+ /* ══════════════════════════════════════════════════
300
+ Generic Thank-You Slide (deck-ty-* namespace)
301
+ ══════════════════════════════════════════════════ */
302
+ .deck-ty {
303
+ background: var(--background);
304
+ padding: 0 0 var(--space-11) 0;
305
+ }
306
+
307
+ /* Ambient glow orbs */
308
+ .deck-ty-glow {
309
+ position: absolute;
310
+ border-radius: var(--radius-full);
311
+ filter: blur(80px);
312
+ pointer-events: none;
313
+ animation: deck-ty-pulse 6s ease-in-out infinite;
314
+ }
315
+ .deck-ty-glow1 { width: 300px; height: 300px; background: var(--glow-accent); top: -80px; left: -60px; }
316
+ .deck-ty-glow2 { width: 250px; height: 250px; background: var(--glow-purple); bottom: -40px; right: -40px; animation-delay: -2s; }
317
+ .deck-ty-glow3 { width: 200px; height: 200px; background: var(--glow-cyan); top: 50%; left: 60%; transform: translate(-50%,-50%); animation-delay: -4s; }
318
+
319
+ @keyframes deck-ty-pulse {
320
+ 0%, 100% { transform: scale(1); opacity: 0.7; }
321
+ 50% { transform: scale(1.15); opacity: 1; }
322
+ }
323
+
324
+ /* Speed streaks */
325
+ .deck-ty-streak {
326
+ position: absolute;
327
+ height: 1px;
328
+ border-radius: 1px;
329
+ opacity: 0;
330
+ animation: deck-ty-streak-move 4s ease-in-out infinite;
331
+ }
332
+ .deck-ty-streak1 { width: 120px; top: 15%; left: -120px; background: linear-gradient(90deg, transparent, var(--accent)); animation-delay: 0s; }
333
+ .deck-ty-streak2 { width: 80px; top: 30%; left: -80px; background: linear-gradient(90deg, transparent, var(--purple)); animation-delay: 0.6s; }
334
+ .deck-ty-streak3 { width: 100px; top: 45%; left: -100px; background: linear-gradient(90deg, transparent, var(--cyan)); animation-delay: 1.2s; }
335
+ .deck-ty-streak4 { width: 60px; top: 60%; left: -60px; background: linear-gradient(90deg, transparent, var(--green)); animation-delay: 1.8s; }
336
+ .deck-ty-streak5 { width: 90px; top: 75%; left: -90px; background: linear-gradient(90deg, transparent, var(--pink)); animation-delay: 2.4s; }
337
+ .deck-ty-streak6 { width: 70px; top: 20%; right: -70px; background: linear-gradient(270deg, transparent, var(--accent)); animation-delay: 0.3s; }
338
+ .deck-ty-streak7 { width: 110px; top: 50%; right: -110px; background: linear-gradient(270deg, transparent, var(--purple)); animation-delay: 1.5s; }
339
+ .deck-ty-streak8 { width: 85px; top: 80%; right: -85px; background: linear-gradient(270deg, transparent, var(--cyan)); animation-delay: 2.1s; }
340
+
341
+ @keyframes deck-ty-streak-move {
342
+ 0% { transform: translateX(0); opacity: 0; }
343
+ 10% { opacity: 0.6; }
344
+ 50% { opacity: 0.3; }
345
+ 100% { transform: translateX(calc(100vw + 200px)); opacity: 0; }
346
+ }
347
+
348
+ /* Content */
349
+ .deck-ty-content {
350
+ text-align: left;
351
+ position: relative;
352
+ z-index: var(--z-content);
353
+ }
354
+ .deck-ty-title {
355
+ font-size: var(--font-size-display);
356
+ font-weight: var(--font-weight-extrabold);
357
+ letter-spacing: var(--letter-spacing-tight);
358
+ background: linear-gradient(135deg, var(--accent), var(--purple), var(--cyan), var(--accent));
359
+ background-size: 300% 300%;
360
+ -webkit-background-clip: text;
361
+ -webkit-text-fill-color: transparent;
362
+ background-clip: text;
363
+ animation: deck-ty-grad-shift 6s ease infinite;
364
+ margin-bottom: var(--space-4);
365
+ }
366
+ @keyframes deck-ty-grad-shift {
367
+ 0% { background-position: 0% 50%; }
368
+ 50% { background-position: 100% 50%; }
369
+ 100% { background-position: 0% 50%; }
370
+ }
371
+ .deck-ty-subtitle {
372
+ font-size: var(--font-size-lg);
373
+ font-weight: var(--font-weight-regular);
374
+ color: var(--muted-foreground);
375
+ letter-spacing: var(--letter-spacing-wide);
376
+ }
377
+ .deck-ty-divider {
378
+ width: 60px;
379
+ height: 2px;
380
+ background: linear-gradient(90deg, var(--accent), var(--purple));
381
+ margin: var(--space-6) 0;
382
+ border-radius: 1px;
383
+ }
384
+ .deck-ty-tagline {
385
+ font-size: var(--font-size-md);
386
+ text-transform: uppercase;
387
+ letter-spacing: var(--letter-spacing-widest);
388
+ color: var(--muted-foreground);
389
+ opacity: 0.5;
390
+ }
391
+
392
+ } /* end @layer components */