@cyber-dash-tech/revela 0.4.0 → 0.4.1

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,271 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
6
+ <title>Starter Design System — Preview</title>
7
+ <link rel="preconnect" href="https://fonts.googleapis.com">
8
+ <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
9
+ <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap" rel="stylesheet">
10
+ <script src="https://cdn.jsdelivr.net/npm/echarts@5/dist/echarts.min.js"></script>
11
+ <style>
12
+ :root {
13
+ --bg-frame: #111315;
14
+ --bg-page: #f6f7f8;
15
+ --bg-page-alt: #eceff2;
16
+ --surface: #ffffff;
17
+ --surface-strong: #dfe5eb;
18
+ --text-primary: #17191c;
19
+ --text-secondary: #4f5965;
20
+ --text-muted: #7a8490;
21
+ --line: rgba(23, 25, 28, 0.12);
22
+ --line-strong: rgba(23, 25, 28, 0.26);
23
+ --accent-primary: #3b82f6;
24
+ --accent-secondary: #64748b;
25
+ --accent-soft: #dbeafe;
26
+ --accent-danger: #dc2626;
27
+ --shadow-soft: rgba(15, 23, 42, 0.16);
28
+ --font-display: 'Inter', ui-sans-serif, sans-serif;
29
+ --font-body: 'Inter', ui-sans-serif, sans-serif;
30
+ --font-size-body: 17px;
31
+ --font-size-meta: 12px;
32
+ }
33
+
34
+ * { box-sizing: border-box; margin: 0; padding: 0; }
35
+ html { scroll-snap-type: y mandatory; overflow-y: scroll; height: 100%; }
36
+ body { background: var(--bg-frame); color: var(--text-primary); font-family: var(--font-body); -webkit-font-smoothing: antialiased; height: 100%; }
37
+ .slide { min-height: 100dvh; scroll-snap-align: start; display: flex; align-items: center; justify-content: center; overflow: hidden; background: var(--bg-frame); }
38
+ .slide-canvas { width: 1920px; height: 1080px; flex-shrink: 0; transform-origin: center center; position: relative; overflow: hidden; padding: 10px; }
39
+ .page { position: relative; width: 100%; height: 100%; background: var(--bg-page); color: var(--text-primary); padding: 56px 64px 64px; box-shadow: 0 24px 80px var(--shadow-soft); display: flex; flex-direction: column; overflow: hidden; }
40
+ .page.alt { background: var(--bg-page-alt); }
41
+ .eyebrow, .caption, .meta-label { font-size: var(--font-size-meta); line-height: 1.4; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-muted); }
42
+ h1, h2, h3, h4 { font-family: var(--font-display); font-weight: 750; letter-spacing: -0.035em; color: var(--text-primary); }
43
+ h1 { font-size: 96px; line-height: 0.94; }
44
+ h2 { font-size: 46px; line-height: 1.04; }
45
+ h3 { font-size: 26px; line-height: 1.14; }
46
+ p, li { font-size: var(--font-size-body); line-height: 1.6; color: var(--text-secondary); }
47
+ .rule { width: 100%; height: 1px; background: var(--line); }
48
+ .rule.strong { background: var(--line-strong); }
49
+ .media-frame { position: relative; overflow: hidden; background: var(--surface-strong); }
50
+ .media-frame img { width: 100%; height: 100%; display: block; object-fit: cover; }
51
+ .media-caption { margin-top: 12px; font-size: var(--font-size-meta); line-height: 1.5; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-muted); }
52
+ .editorial-list { list-style: none; display: flex; flex-direction: column; gap: 14px; }
53
+ .editorial-list li { position: relative; padding-left: 20px; font-size: var(--font-size-body); line-height: 1.58; color: var(--text-secondary); }
54
+ .editorial-list li::before { content: ''; position: absolute; left: 0; top: 8px; width: 6px; height: 6px; background: var(--accent-primary); }
55
+ .reveal { opacity: 0; transform: translateY(18px); transition: opacity 0.55s cubic-bezier(0.22, 1, 0.36, 1), transform 0.55s cubic-bezier(0.22, 1, 0.36, 1); }
56
+ .reveal.visible { opacity: 1; transform: translateY(0); }
57
+
58
+ .narrative-grid { display: grid; grid-template-columns: minmax(0, 1.618fr) minmax(0, 1fr); grid-template-rows: minmax(0, 1fr); height: 100%; overflow: hidden; align-items: stretch; }
59
+ .narrative-grid--reverse { grid-template-columns: minmax(0, 1fr) minmax(0, 1.618fr); }
60
+ .narrative-grid > * { overflow: hidden; min-height: 0; min-width: 0; }
61
+ .highlight-cols-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(0, 1fr)); gap: 32px; overflow: hidden; align-items: stretch; }
62
+ .highlight-cols-grid > * { overflow: hidden; min-height: 0; }
63
+ .halves-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); height: 100%; overflow: hidden; align-items: stretch; }
64
+ .halves-grid > * { overflow: hidden; min-height: 0; min-width: 0; }
65
+ .stacked-grid { display: grid; grid-template-rows: minmax(0, 1fr) minmax(0, 1.618fr); height: 100%; width: 100%; overflow: hidden; }
66
+ .stacked-top, .stacked-bottom { overflow: hidden; min-height: 0; }
67
+
68
+ .text-panel { height: 100%; padding: 56px 48px 34px; display: flex; flex-direction: column; justify-content: space-between; gap: 32px; }
69
+ .text-panel--light { background: var(--bg-page-alt); color: var(--text-primary); }
70
+ .text-panel--dark { background: #1f242b; color: #f8fafc; --text-primary: #f8fafc; --text-secondary: #cbd5e1; --text-muted: #94a3b8; --line: rgba(248,250,252,0.16); }
71
+ .text-panel-body { display: flex; flex-direction: column; gap: 14px; }
72
+ .text-panel-footer { display: flex; justify-content: space-between; align-items: flex-end; gap: 18px; }
73
+ .stat-card { height: 100%; display: flex; min-height: 0; flex-direction: column; justify-content: flex-start; gap: 16px; padding-top: 8px; }
74
+ .stat-card--horizontal { flex-direction: row; align-items: flex-start; gap: 30px; }
75
+ .stat-card-value { font-family: var(--font-display); font-size: 88px; line-height: 0.9; letter-spacing: -0.05em; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--accent-primary); }
76
+ .editorial-image-top { display: flex; flex-direction: column; gap: 16px; height: 100%; }
77
+ .editorial-image-top .editorial-media { height: 240px; border: 1px solid var(--line); }
78
+ .editorial-module-body { display: flex; flex-direction: column; gap: 12px; }
79
+ .editorial-text-top { display: flex; flex-direction: column; gap: 16px; height: 100%; }
80
+ .editorial-text-top .editorial-media { flex: 1; min-height: 180px; border: 1px solid var(--line); }
81
+ .editorial-text-left { display: flex; flex-direction: column; gap: 0; height: 100%; overflow: hidden; border: 1px solid var(--line); }
82
+ .editorial-text-left-header { flex-shrink: 0; padding: 24px 26px 16px; border-bottom: 1px solid var(--line); }
83
+ .editorial-text-left-content { display: flex; flex: 1; min-height: 0; }
84
+ .editorial-text-left-copy { flex: 1.1; min-width: 0; padding: 20px 24px; display: flex; flex-direction: column; justify-content: flex-start; }
85
+ .editorial-text-left-visual { flex: 1; min-width: 0; min-height: 0; align-self: stretch; overflow: hidden; position: relative; background: var(--surface-strong); }
86
+
87
+ .echart-panel { display: flex; flex-direction: column; height: 100%; gap: 0; }
88
+ .echart-panel-header { flex-shrink: 0; padding-bottom: 16px; border-bottom: 1px solid var(--line); margin-bottom: 20px; }
89
+ .chart-subtitle { margin-top: 4px; font-size: 13px; color: var(--text-muted); line-height: 1.4; }
90
+ .echart-container { flex: 1; min-height: 0; }
91
+ .chart-caption { flex-shrink: 0; margin-top: 12px; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase; color: var(--text-muted); }
92
+ .flow-number { position: relative; width: 36px; height: 36px; flex-shrink: 0; border: 1px solid var(--line-strong); background: var(--surface); display: flex; align-items: center; justify-content: center; }
93
+ .flow-number::after { content: attr(data-n); font-size: 12px; font-weight: 800; color: var(--accent-primary); }
94
+ .flow-body h4 { font-size: 20px; font-weight: 700; line-height: 1.14; }
95
+ .flow-body p { margin-top: 8px; font-size: 17px; line-height: 1.6; color: var(--text-secondary); }
96
+ .flow-horizontal { position: relative; display: flex; align-items: flex-start; width: 100%; }
97
+ .flow-horizontal::before { content: ''; position: absolute; top: 17px; left: 0; right: 0; height: 1px; background: var(--line-strong); z-index: 0; }
98
+ .flow-horizontal .flow-item { flex: 1; display: flex; flex-direction: column; gap: 18px; padding-right: 40px; }
99
+ .flow-horizontal .flow-number { position: relative; z-index: 1; }
100
+ .flow-vertical { display: flex; flex-direction: column; width: 100%; }
101
+ .flow-vertical .flow-item { display: flex; gap: 28px; align-items: flex-start; }
102
+ .flow-vertical .flow-marker { display: flex; flex-direction: column; align-items: center; flex-shrink: 0; }
103
+ .flow-vertical .flow-line { width: 1px; flex: 1; min-height: 28px; background: var(--line-strong); margin: 6px 0; }
104
+ .flow-vertical .flow-body { padding-bottom: 32px; }
105
+ .flow-vertical .flow-item.last .flow-body { padding-bottom: 0; }
106
+
107
+ .data-table-wrap { width: 100%; }
108
+ .data-table-label { font-size: 10px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--text-muted); margin-bottom: 8px; }
109
+ .data-table { width: 100%; border-collapse: collapse; font-family: var(--font-body); font-size: 17px; font-variant-numeric: tabular-nums; color: var(--text-primary); }
110
+ .data-table thead tr { border-bottom: 1.5px solid var(--line-strong); }
111
+ .data-table th { padding: 0 12px 10px 0; text-align: left; font-size: 13px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); white-space: nowrap; }
112
+ .data-table th:not(:first-child), .data-table td:not(:first-child) { text-align: right; }
113
+ .data-table tbody tr { border-bottom: 1px solid var(--line); }
114
+ .data-table td { padding: 9px 12px 9px 0; line-height: 1.4; color: var(--text-secondary); }
115
+ .data-table .delta.positive { color: var(--accent-primary); }
116
+ .data-table .delta.negative { color: var(--accent-danger); }
117
+ .table-caption { margin-top: 12px; font-size: 11px; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); }
118
+
119
+ .image-title { position: relative; width: 100%; height: 100%; overflow: hidden; color: #f8fafc; background: #1f242b; }
120
+ .image-title-media { position: absolute; inset: 0; z-index: 0; background: linear-gradient(135deg, #1f2937, #475569); }
121
+ .image-title-overlay { position: absolute; inset: 0; z-index: 1; background: linear-gradient(90deg, rgba(15,23,42,0.78), rgba(15,23,42,0.18)); }
122
+ .image-title-fg { position: relative; z-index: 2; height: 100%; display: flex; flex-direction: column; justify-content: space-between; padding: 72px 84px; }
123
+ .image-title--left .image-title-body { max-width: 760px; }
124
+ .image-title h1 { color: #f8fafc; font-size: 104px; line-height: 0.92; letter-spacing: -0.055em; }
125
+ .image-title-eyebrow { font-size: 12px; font-weight: 800; letter-spacing: 0.18em; text-transform: uppercase; color: rgba(248,250,252,0.62); margin-bottom: 20px; }
126
+ .image-title-subtitle { margin-top: 24px; font-size: 18px; line-height: 1.56; color: rgba(248,250,252,0.78); max-width: 520px; }
127
+ .toc-panel { height: 100%; padding: 54px 52px 42px; display: flex; overflow: hidden; background: var(--bg-page); }
128
+ .toc-panel-inner { display: flex; flex-direction: column; justify-content: space-between; width: 100%; gap: 32px; }
129
+ .toc-header { max-width: 620px; display: flex; flex-direction: column; gap: 18px; }
130
+ .toc-list { display: flex; flex-direction: column; border-top: 1px solid var(--line-strong); }
131
+ .toc-item { display: grid; grid-template-columns: 70px 1fr 60px; gap: 24px; align-items: baseline; padding: 22px 0; border-bottom: 1px solid var(--line); }
132
+ .toc-item span, .toc-item em { font-style: normal; color: var(--text-muted); font-size: 12px; letter-spacing: 0.14em; text-transform: uppercase; }
133
+ .toc-item strong { font-size: 28px; line-height: 1.08; color: var(--text-primary); }
134
+ .quote-block { height: 100%; display: flex; flex-direction: column; justify-content: center; gap: 24px; max-width: 980px; }
135
+ .quote-mark { font-size: 96px; line-height: 0.7; color: var(--accent-primary); }
136
+ .quote-block blockquote { font-family: var(--font-display); font-size: 54px; line-height: 1.06; letter-spacing: -0.04em; color: var(--text-primary); }
137
+ .quote-source { font-size: 13px; text-transform: uppercase; letter-spacing: 0.14em; color: var(--text-muted); }
138
+ .brand-watermark { display: inline-flex; align-items: center; gap: 10px; color: var(--text-muted); font-size: 12px; letter-spacing: 0.12em; text-transform: uppercase; }
139
+ .brand-watermark span { width: 18px; height: 18px; border: 2px solid var(--accent-primary); display: block; }
140
+ .brand-watermark strong { font-weight: 800; color: var(--text-secondary); }
141
+ .page-number { position: absolute; right: 34px; bottom: 26px; z-index: 10; font-size: 12px; letter-spacing: 0.14em; color: var(--text-muted); }
142
+ .page-number--light { color: rgba(248,250,252,0.72); }
143
+ .timeline-journey-horizontal { position: relative; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 28px; }
144
+ .timeline-journey-horizontal::before { content: ''; position: absolute; left: 0; right: 0; top: 18px; height: 1px; background: var(--line-strong); }
145
+ .timeline-node { position: relative; z-index: 1; display: flex; flex-direction: column; gap: 12px; padding-right: 18px; }
146
+ .timeline-node span, .timeline-v-node span { width: 36px; height: 36px; display: flex; align-items: center; justify-content: center; background: var(--surface); border: 1px solid var(--line-strong); color: var(--accent-primary); font-size: 12px; font-weight: 800; }
147
+ .timeline-journey-vertical { display: flex; flex-direction: column; gap: 0; }
148
+ .timeline-v-node { display: grid; grid-template-columns: 42px 1fr; gap: 18px; padding-bottom: 26px; position: relative; }
149
+ .timeline-v-node::before { content: ''; position: absolute; left: 17px; top: 42px; bottom: 4px; width: 1px; background: var(--line-strong); }
150
+ .svg-motif { position: relative; pointer-events: none; color: var(--text-primary); }
151
+ .svg-motif svg { display: block; width: 100%; height: 100%; overflow: visible; }
152
+ .svg-motif--bottom { position: absolute; left: 0; right: 0; bottom: 0; height: 30%; }
153
+ .svg-motif--side { position: absolute; right: 0; top: 0; bottom: 0; width: 34%; }
154
+ .svg-motif--corner { position: absolute; right: 40px; bottom: 36px; width: 360px; height: 220px; }
155
+ .svg-motif--hero { width: 100%; height: 100%; }
156
+ </style>
157
+ </head>
158
+ <body>
159
+ <section class="slide" slide-qa="false" data-index="0">
160
+ <div class="slide-canvas">
161
+ <div class="page" style="padding:0;">
162
+ <div class="image-title image-title--left">
163
+ <div class="image-title-media"></div>
164
+ <div class="image-title-overlay"></div>
165
+ <div class="svg-motif svg-motif--bottom" aria-hidden="true">
166
+ <svg viewBox="0 0 1600 420"><rect x="0" y="354" width="1600" height="26" fill="#dbeafe"/><circle cx="1240" cy="230" r="96" fill="#3b82f6" opacity=".18"/><path d="M118 344 C150 250 265 224 342 290 C400 340 315 378 176 374 Z" fill="#3b82f6"/><path d="M392 368 C430 250 590 228 668 314 C714 364 606 394 462 390 Z" fill="#64748b" opacity=".85"/><path d="M692 360 C730 285 835 282 888 336 C920 370 832 392 716 386 Z" fill="#dbeafe"/><path d="M1160 278 l28 -28 l28 28 l-28 28 Z" fill="none" stroke="#f8fafc" stroke-width="8"/><path d="M1320 198 C1370 160 1412 168 1448 220" fill="none" stroke="#f8fafc" stroke-width="10" stroke-linecap="round"/><circle cx="232" cy="318" r="7" fill="#17191c"/><circle cx="284" cy="318" r="7" fill="#17191c"/><path d="M238 340 C252 354 272 354 286 340" fill="none" stroke="#17191c" stroke-width="7" stroke-linecap="round"/></svg>
167
+ </div>
168
+ <div class="image-title-fg">
169
+ <div class="brand-watermark"><span></span><strong>Starter</strong></div>
170
+ <div class="image-title-body reveal"><p class="image-title-eyebrow">Neutral base design</p><h1>Design System Preview</h1><p class="image-title-subtitle">A structural scaffold for AI-authored Revela themes. Preserve the system; replace the visual identity.</p></div>
171
+ </div>
172
+ <div class="page-number page-number--light">01</div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ </section>
177
+
178
+ <section class="slide" slide-qa="false" data-index="1">
179
+ <div class="slide-canvas">
180
+ <div class="page" style="padding:0;">
181
+ <div class="toc-panel">
182
+ <div class="toc-panel-inner">
183
+ <div class="toc-header reveal"><p class="eyebrow">Contents</p><h2>Core primitives for derived themes</h2><p>Starter preview demonstrates structure, not a fixed aesthetic.</p></div>
184
+ <div class="toc-list reveal">
185
+ <div class="toc-item"><span>01</span><strong>Foundation and visual schema</strong><em>03</em></div>
186
+ <div class="toc-item"><span>02</span><strong>Layouts and content modules</strong><em>04</em></div>
187
+ <div class="toc-item"><span>03</span><strong>Data, flow, and evidence</strong><em>05</em></div>
188
+ <div class="toc-item"><span>04</span><strong>Motifs and closing states</strong><em>06</em></div>
189
+ </div>
190
+ </div>
191
+ <div class="page-number">02</div>
192
+ </div>
193
+ </div>
194
+ </div>
195
+ </section>
196
+
197
+ <section class="slide" slide-qa="false" data-index="2">
198
+ <div class="slide-canvas">
199
+ <div class="page" style="padding:0;">
200
+ <div class="narrative-grid">
201
+ <div class="text-panel text-panel--light reveal">
202
+ <div class="text-panel-body"><p class="eyebrow">Visual schema first</p><h2>Preserve composition before changing style</h2><ul class="editorial-list"><li><strong>Reference type.</strong> Identify whether the source is vector, photo, UI, page, or motif.</li><li><strong>Scale and anchor.</strong> Keep a bottom strip low, a corner motif small, and a hero visual dominant only when requested.</li><li><strong>Implementation path.</strong> Use SVG for flat motifs; use image/surface rules for photo and UI references.</li></ul></div>
203
+ <div class="text-panel-footer"><span class="caption">Authoring constraint</span><span class="caption">03</span></div>
204
+ </div>
205
+ <div class="text-panel text-panel--dark reveal">
206
+ <div class="text-panel-body"><p class="eyebrow">CSS scope</p><h3>Stable containers, replaceable skins</h3><p>Derived designs should modify tokens, type, component surfaces, and motif components before rewriting layout CSS.</p></div>
207
+ <div class="stat-card"><div class="stat-card-value">6</div><p>Baseline layouts remain available as neutral structure.</p></div>
208
+ </div>
209
+ </div>
210
+ </div>
211
+ </div>
212
+ </section>
213
+
214
+ <section class="slide" slide-qa="false" data-index="3">
215
+ <div class="slide-canvas">
216
+ <div class="page">
217
+ <div style="display:flex;flex-direction:column;gap:10px;margin-bottom:28px;max-width:620px;" class="reveal"><p class="eyebrow">Component coverage</p><h2>Reusable modules with neutral skins</h2></div>
218
+ <div class="highlight-cols-grid" style="flex:1;min-height:0;">
219
+ <div class="editorial-image-top reveal"><div class="media-frame editorial-media"><div class="svg-motif svg-motif--hero"><svg viewBox="0 0 600 320"><rect width="600" height="320" fill="#dfe5eb"/><circle cx="140" cy="150" r="72" fill="#3b82f6" opacity=".76"/><rect x="250" y="86" width="210" height="132" rx="24" fill="#fff"/><path d="M286 132 H426 M286 166 H390" stroke="#64748b" stroke-width="12" stroke-linecap="round"/></svg></div></div><div class="editorial-module-body"><p class="eyebrow">Media module</p><h3>Image or motif above copy</h3><p>Use for examples, evidence, screenshots, and vector moments.</p></div></div>
220
+ <div class="editorial-text-top reveal"><div class="editorial-module-body"><p class="eyebrow">Text module</p><h3>Copy-led primitive</h3><p>Neutral spacing and type hierarchy provide a stable baseline for derived themes.</p></div><div class="media-frame editorial-media"></div></div>
221
+ <div class="stat-card reveal"><p class="eyebrow">Metric</p><div class="stat-card-value">16</div><h3>Components</h3><p>Starter includes broad enough coverage for most generated decks, including SVG motifs.</p></div>
222
+ </div>
223
+ <div class="page-number">04</div>
224
+ </div>
225
+ </div>
226
+ </section>
227
+
228
+ <section class="slide" slide-qa="false" data-index="4">
229
+ <div class="slide-canvas">
230
+ <div class="page" style="padding:0;">
231
+ <div class="stacked-grid">
232
+ <div class="stacked-top text-panel reveal" style="padding:48px 56px 30px;"><div class="text-panel-body"><p class="eyebrow">Data and process</p><h2>Evidence components stay structural</h2><p>Charts, tables, and flows inherit the active theme while keeping predictable geometry.</p></div></div>
233
+ <div class="stacked-bottom" style="display:grid;grid-template-columns:1.2fr .8fr;gap:40px;padding:0 56px 56px;">
234
+ <div class="echart-panel reveal"><div class="echart-panel-header"><p class="eyebrow">Example chart</p><h3>Signal distribution</h3><p class="chart-subtitle">Neutral chart defaults with restrained labels.</p></div><div class="echart-container" id="starter-chart"></div><p class="chart-caption">Source: demo data</p></div>
235
+ <div class="data-table-wrap reveal"><div class="data-table-label">Component matrix</div><table class="data-table"><thead><tr><th>Primitive</th><th>Count</th><th>Role</th></tr></thead><tbody><tr><td>Layouts</td><td>6</td><td>Structure</td></tr><tr><td>Components</td><td>16</td><td>Coverage</td></tr><tr><td>SVG motif</td><td>1</td><td>Vector</td></tr></tbody></table><p class="table-caption">Starter remains visually neutral.</p></div>
236
+ </div>
237
+ </div>
238
+ <div class="page-number">05</div>
239
+ </div>
240
+ </div>
241
+ </section>
242
+
243
+ <section class="slide" slide-qa="false" data-index="5">
244
+ <div class="slide-canvas">
245
+ <div class="page">
246
+ <div class="svg-motif svg-motif--corner" aria-hidden="true"><svg viewBox="0 0 600 360"><rect x="80" y="190" width="360" height="34" fill="#dbeafe"/><circle cx="190" cy="150" r="82" fill="#3b82f6" opacity=".82"/><path d="M286 230 C330 120 474 122 516 226 C458 274 348 276 286 230 Z" fill="#64748b" opacity=".68"/><path d="M112 70 l22 -22 l22 22 l-22 22 Z" fill="none" stroke="#17191c" stroke-width="8"/><path d="M470 72 C508 38 548 46 566 88" fill="none" stroke="#17191c" stroke-width="9" stroke-linecap="round"/></svg></div>
247
+ <div style="height:100%;display:flex;flex-direction:column;justify-content:space-between;max-width:1040px;" class="reveal">
248
+ <div class="brand-watermark"><span></span><strong>Starter</strong></div>
249
+ <div class="quote-block"><p class="quote-mark">“</p><blockquote>A starter design should be boring enough to replace, but complete enough to trust.</blockquote><p class="quote-source">Neutral base principle</p></div>
250
+ <p class="caption">Activate derived designs after preview inspection.</p>
251
+ </div>
252
+ <div class="page-number">06</div>
253
+ </div>
254
+ </div>
255
+ </section>
256
+
257
+ <script>
258
+ class SlidePresentation {
259
+ constructor() { this.slides = document.querySelectorAll('.slide'); this.currentSlide = 0; this.setupScaling(); this.setupIntersectionObserver(); this.setupKeyboardNav(); this.setupTouchNav(); this.setupMouseWheel(); this.setupChart(); }
260
+ setupScaling() { const canvases = document.querySelectorAll('.slide-canvas'); const update = () => { const scale = Math.min(window.innerWidth / 1920, window.innerHeight / 1080); canvases.forEach((canvas) => { canvas.style.transform = `scale(${scale})`; }); }; window.addEventListener('resize', update); update(); }
261
+ setupIntersectionObserver() { const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (entry.isIntersecting) entry.target.querySelectorAll('.reveal').forEach((el) => el.classList.add('visible')); }); }, { threshold: 0.2 }); this.slides.forEach((slide) => observer.observe(slide)); }
262
+ setupKeyboardNav() { document.addEventListener('keydown', (event) => { if (['ArrowDown', 'ArrowRight', ' ', 'PageDown'].includes(event.key)) { event.preventDefault(); this.goTo(this.currentSlide + 1); } else if (['ArrowUp', 'ArrowLeft', 'PageUp'].includes(event.key)) { event.preventDefault(); this.goTo(this.currentSlide - 1); } }); }
263
+ setupTouchNav() { let startY = 0; document.addEventListener('touchstart', (event) => { startY = event.touches[0].clientY; }, { passive: true }); document.addEventListener('touchend', (event) => { const deltaY = startY - event.changedTouches[0].clientY; if (Math.abs(deltaY) > 40) this.goTo(this.currentSlide + (deltaY > 0 ? 1 : -1)); }, { passive: true }); }
264
+ setupMouseWheel() { let last = 0; document.addEventListener('wheel', (event) => { const now = Date.now(); if (now - last < 800) return; last = now; this.goTo(this.currentSlide + (event.deltaY > 0 ? 1 : -1)); }, { passive: true }); }
265
+ setupChart() { const el = document.getElementById('starter-chart'); if (!el || !window.echarts) return; const chart = echarts.init(el); chart.setOption({ grid: { left: 30, right: 16, top: 20, bottom: 32 }, xAxis: { type: 'category', data: ['A', 'B', 'C', 'D'], axisLine: { lineStyle: { color: 'rgba(23,25,28,.26)' } }, axisTick: { show: false } }, yAxis: { type: 'value', splitLine: { lineStyle: { color: 'rgba(23,25,28,.12)' } } }, series: [{ type: 'bar', data: [42, 68, 51, 76], itemStyle: { color: '#3b82f6' }, barWidth: 34 }] }); window.addEventListener('resize', () => chart.resize()); }
266
+ goTo(index) { const clamped = Math.max(0, Math.min(this.slides.length - 1, index)); this.slides[clamped].scrollIntoView({ behavior: 'smooth' }); this.currentSlide = clamped; }
267
+ }
268
+ new SlidePresentation();
269
+ </script>
270
+ </body>
271
+ </html>