@cyber-dash-tech/revela 0.18.15 → 0.18.16

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.
@@ -821,6 +821,7 @@ Horizontal milestone journey with a central axis line. Nodes sit on the axis; a
821
821
 
822
822
  Rules:
823
823
  - Position nodes with `left: X%` inline style. For N nodes, space them at `(100 / (N + 1)) * k %` or manually distribute to show real time gaps.
824
+ - Treat `left: X%` as the milestone centreline. The label, tip dot, stem, and axis dot must remain centered on that same x-position; do not left-align the label block away from the marker.
824
825
  - Each node may set `--tjh-item-color` inline. Prefer existing neutral theme tokens such as `--accent-primary`, `--accent-secondary`, `--accent-danger`, or a derived local accent.
825
826
  - Up node DOM order is `label -> tip-dot -> stem -> axis-dot`; down node DOM order is `axis-dot -> stem -> tip-dot -> label`.
826
827
  - Keep `.tjh-text` short, usually 1-2 lines. The column width limits wrapping naturally.
@@ -872,12 +873,11 @@ Vertical milestone journey with a central axis line. Nodes sit on the axis; a ho
872
873
  height: 100%;
873
874
  }
874
875
  .tjv-axis { position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: var(--line-strong); transform: translateX(-50%); }
875
- .tjv-item { position: absolute; display: flex; align-items: center; height: 78px; transform: translateY(-50%); }
876
- .tjv-item--left { right: 50%; flex-direction: row-reverse; }
877
- .tjv-item--right { left: 50%; flex-direction: row; }
876
+ .tjv-item { position: absolute; display: flex; align-items: center; min-width: 220px; height: 78px; transform: translateY(-50%); }
877
+ .tjv-item--left { right: calc(50% - var(--tjv-node) / 2); flex-direction: row-reverse; }
878
+ .tjv-item--right { left: calc(50% - var(--tjv-node) / 2); flex-direction: row; }
878
879
  .tjv-axis-dot { width: var(--tjv-node); height: var(--tjv-node); border-radius: 999px; background: var(--tjv-item-color, var(--accent-primary)); flex-shrink: 0; position: relative; z-index: 1; }
879
- .tjv-item--left .tjv-axis-dot { margin-right: calc(-1 * var(--tjv-node) / 2); }
880
- .tjv-item--right .tjv-axis-dot { margin-left: calc(-1 * var(--tjv-node) / 2); }
880
+ .tjv-item--left .tjv-axis-dot, .tjv-item--right .tjv-axis-dot { margin: 0; }
881
881
  .tjv-tip-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--tjv-item-color, var(--accent-primary)); flex-shrink: 0; }
882
882
  .tjv-stem { width: var(--tjv-stem-w); height: 1px; background-image: repeating-linear-gradient(to right, var(--line-strong) 0 4px, transparent 4px 8px); flex-shrink: 0; }
883
883
  .tjv-label { display: flex; flex-direction: column; gap: 4px; }
@@ -891,6 +891,9 @@ Vertical milestone journey with a central axis line. Nodes sit on the axis; a ho
891
891
  Rules:
892
892
  - DOM order is identical for left and right nodes: `axis-dot -> stem -> tip-dot -> label`. Direction is controlled by CSS (`row-reverse` for left, `row` for right).
893
893
  - Position each node with `top: Y%` inline style. For N nodes, distribute evenly with `(100 / (N + 1)) * k %` or manually to reflect time proportions.
894
+ - Treat `top: Y%` as the milestone row centre. The axis dot, stem, tip dot, and label row must stay vertically centered on that same y-position.
895
+ - Anchor left/right rows at `calc(50% - var(--tjv-node) / 2)` rather than using negative margins on `.tjv-axis-dot`; this keeps the marker centered on the axis without creating export/QA overflow.
896
+ - Give `.tjv-item` an explicit `min-width` large enough to include label + tip + stem + axis-dot, rather than relying on intrinsic content width.
894
897
  - Each node may set `--tjv-item-color` inline. Prefer current theme tokens rather than hard-coded project colors.
895
898
  - Alternate left and right nodes for rhythm. Avoid consecutive same-side nodes unless the story needs clustering.
896
899
  - The parent container must have a defined height. Use `height: 100%` inside a layout slot, or set an explicit height when standalone.
@@ -40,7 +40,7 @@
40
40
  .page.alt { background: var(--bg-page-alt); }
41
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
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; }
43
+ h1 { font-size: 92px; line-height: 1.08; }
44
44
  h2 { font-size: 46px; line-height: 1.04; }
45
45
  h3 { font-size: 26px; line-height: 1.14; }
46
46
  p, li { font-size: var(--font-size-body); line-height: 1.6; color: var(--text-secondary); }
@@ -52,6 +52,11 @@
52
52
  .editorial-list { list-style: none; display: flex; flex-direction: column; gap: 14px; }
53
53
  .editorial-list li { position: relative; padding-left: 20px; font-size: var(--font-size-body); line-height: 1.58; color: var(--text-secondary); }
54
54
  .editorial-list li::before { content: ''; position: absolute; left: 0; top: 8px; width: 6px; height: 6px; background: var(--accent-primary); }
55
+ .editorial-list li.editorial-list__red { color: var(--accent-danger); }
56
+ .editorial-list li.editorial-list__red::before { background: var(--accent-danger); }
57
+ .editorial-list li.editorial-list__wide { width: 1200px; min-height: 36px; line-height: 36px; }
58
+ .editorial-list li.editorial-list__green { color: #16a34a; }
59
+ .editorial-list li.editorial-list__green::before { background: #16a34a; }
55
60
  .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
61
  .reveal.visible { opacity: 1; transform: translateY(0); }
57
62
 
@@ -62,7 +67,7 @@
62
67
  .highlight-cols-grid > * { overflow: hidden; min-height: 0; }
63
68
  .halves-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); height: 100%; overflow: hidden; align-items: stretch; }
64
69
  .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; }
70
+ .stacked-grid { display: grid; grid-template-rows: minmax(0, .52fr) minmax(0, 1.72fr); height: 100%; width: 100%; overflow: hidden; }
66
71
  .stacked-top, .stacked-bottom { overflow: hidden; min-height: 0; }
67
72
 
68
73
  .text-panel { height: 100%; padding: 56px 48px 34px; display: flex; flex-direction: column; justify-content: space-between; gap: 32px; }
@@ -72,7 +77,7 @@
72
77
  .text-panel-footer { display: flex; justify-content: space-between; align-items: flex-end; gap: 18px; }
73
78
  .stat-card { height: 100%; display: flex; min-height: 0; flex-direction: column; justify-content: flex-start; gap: 16px; padding-top: 8px; }
74
79
  .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); }
80
+ .stat-card-value { font-family: var(--font-display); font-size: 76px; line-height: 1.08; letter-spacing: -0.04em; font-weight: 800; font-variant-numeric: tabular-nums; color: var(--accent-primary); }
76
81
  .editorial-image-top { display: flex; flex-direction: column; gap: 16px; height: 100%; }
77
82
  .editorial-image-top .editorial-media { height: 240px; border: 1px solid var(--line); }
78
83
  .editorial-module-body { display: flex; flex-direction: column; gap: 12px; }
@@ -120,8 +125,8 @@
120
125
  .image-title-media { position: absolute; inset: 0; z-index: 0; background: linear-gradient(135deg, #1f2937, #475569); }
121
126
  .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
127
  .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; }
128
+ .image-title--left .image-title-body { max-width: 820px; }
129
+ .image-title h1 { color: #f8fafc; font-size: 82px; line-height: 1.18; letter-spacing: -0.03em; padding: 4px 0 10px; }
125
130
  .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
131
  .image-title-subtitle { margin-top: 24px; font-size: 18px; line-height: 1.56; color: rgba(248,250,252,0.78); max-width: 520px; }
127
132
  .toc-panel { height: 100%; padding: 86px 118px 58px; display: flex; overflow: hidden; background: var(--bg-page); }
@@ -131,9 +136,9 @@
131
136
  .toc-note { margin-top: 230px; margin-bottom: 0; max-width: 300px; font-size: 14px; line-height: 1.7; letter-spacing: 0.02em; color: var(--text-muted); }
132
137
  .toc-footer { margin-top: auto; font-size: 11px; line-height: 1.4; letter-spacing: 0.08em; text-transform: uppercase; font-weight: 750; color: var(--text-primary); }
133
138
  .toc-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; justify-content: center; gap: 42px; height: 100%; }
134
- .toc-item { display: grid; grid-template-columns: 80px 1fr; gap: 44px; align-items: center; }
139
+ .toc-item { display: grid; grid-template-columns: 80px 1fr; gap: 44px; align-items: center; min-height: 54px; overflow: visible; }
135
140
  .toc-item span { font-style: normal; font-family: var(--font-display); font-size: 42px; line-height: 1; letter-spacing: 0.03em; color: var(--text-primary); font-variant-numeric: tabular-nums; }
136
- .toc-item strong { font-size: 17px; line-height: 1.35; letter-spacing: 0.12em; text-transform: uppercase; font-weight: 500; color: var(--text-primary); }
141
+ .toc-item strong { font-size: 16px; line-height: 1.55; letter-spacing: 0.10em; text-transform: uppercase; font-weight: 500; color: var(--text-primary); }
137
142
  .quote-block { height: 100%; display: flex; flex-direction: column; justify-content: center; gap: 24px; max-width: 980px; }
138
143
  .quote-mark { font-size: 96px; line-height: 0.7; color: var(--accent-primary); }
139
144
  .quote-block blockquote { font-family: var(--font-display); font-size: 54px; line-height: 1.06; letter-spacing: -0.04em; color: var(--text-primary); }
@@ -143,9 +148,9 @@
143
148
  .brand-watermark strong { font-weight: 800; color: var(--text-secondary); }
144
149
  .page-number { position: absolute; right: 34px; bottom: 26px; z-index: 10; font-size: 12px; letter-spacing: 0.14em; color: var(--text-muted); }
145
150
  .page-number--light { color: rgba(248,250,252,0.72); }
146
- .timeline-journey-horizontal { --tjh-node: 12px; --tjh-stem-h: 62px; --tjh-col: 180px; position: relative; width: 100%; height: 245px; }
151
+ .timeline-journey-horizontal { --tjh-node: 12px; --tjh-stem-h: 34px; --tjh-col: 210px; position: relative; width: 100%; height: 245px; overflow: visible; }
147
152
  .tjh-axis { position: absolute; top: 50%; left: 0; right: 0; height: 1px; background: var(--line-strong); transform: translateY(-50%); }
148
- .tjh-item { position: absolute; display: flex; flex-direction: column; align-items: center; width: var(--tjh-col); transform: translateX(-50%); }
153
+ .tjh-item { position: absolute; display: flex; flex-direction: column; align-items: center; width: var(--tjh-col); transform: translateX(-50%); overflow: visible; }
149
154
  .tjh-item--up { bottom: 50%; }
150
155
  .tjh-item--down { top: 50%; }
151
156
  .tjh-axis-dot, .tjh-tip-dot { width: var(--tjh-node); height: var(--tjh-node); border-radius: 999px; background: var(--tjh-item-color, var(--accent-primary)); flex-shrink: 0; }
@@ -156,34 +161,42 @@
156
161
  .tjh-item--up .tjh-label { margin-bottom: 8px; }
157
162
  .tjh-item--down .tjh-label { margin-top: 8px; }
158
163
  .tjh-date { font-size: 11px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--tjh-item-color, var(--accent-primary)); line-height: 1.3; white-space: nowrap; }
159
- .tjh-title { font-size: 17px; font-weight: 700; line-height: 1.15; color: var(--text-primary); }
160
- .tjh-text { font-size: 13px; line-height: 1.4; color: var(--text-secondary); }
161
- .timeline-journey-vertical { --tjv-node: 12px; --tjv-stem-w: 46px; position: relative; width: 100%; height: 100%; min-height: 260px; }
164
+ .tjh-title { font-size: 15px; font-weight: 700; line-height: 1.28; color: var(--text-primary); }
165
+ .tjh-text { font-size: 12px; line-height: 1.35; color: var(--text-secondary); }
166
+ .timeline-journey-vertical { --tjv-node: 12px; --tjv-stem-w: 28px; position: relative; width: 100%; height: 100%; min-height: 260px; overflow: visible; }
162
167
  .tjv-axis { position: absolute; left: 50%; top: 0; bottom: 0; width: 1px; background: var(--line-strong); transform: translateX(-50%); }
163
- .tjv-item { position: absolute; display: flex; align-items: center; height: 72px; transform: translateY(-50%); }
164
- .tjv-item--left { right: 50%; flex-direction: row-reverse; }
165
- .tjv-item--right { left: 50%; flex-direction: row; }
168
+ .tjv-item { position: absolute; display: flex; align-items: center; min-width: 220px; min-height: 92px; transform: translateY(-50%); overflow: visible; }
169
+ .tjv-item--left { right: calc(50% - var(--tjv-node) / 2); flex-direction: row-reverse; }
170
+ .tjv-item--right { left: calc(50% - var(--tjv-node) / 2); flex-direction: row; }
166
171
  .tjv-axis-dot { width: var(--tjv-node); height: var(--tjv-node); border-radius: 999px; background: var(--tjv-item-color, var(--accent-primary)); flex-shrink: 0; position: relative; z-index: 1; }
167
- .tjv-item--left .tjv-axis-dot { margin-right: calc(-1 * var(--tjv-node) / 2); }
168
- .tjv-item--right .tjv-axis-dot { margin-left: calc(-1 * var(--tjv-node) / 2); }
172
+ .tjv-item--left .tjv-axis-dot, .tjv-item--right .tjv-axis-dot { margin: 0; }
169
173
  .tjv-tip-dot { width: 8px; height: 8px; border-radius: 999px; background: var(--tjv-item-color, var(--accent-primary)); flex-shrink: 0; }
170
174
  .tjv-stem { width: var(--tjv-stem-w); height: 1px; background-image: repeating-linear-gradient(to right, var(--line-strong) 0 4px, transparent 4px 8px); flex-shrink: 0; }
171
175
  .tjv-label { display: flex; flex-direction: column; gap: 3px; }
172
- .tjv-item--left .tjv-label { text-align: right; align-items: flex-end; padding-right: 14px; max-width: 220px; }
173
- .tjv-item--right .tjv-label { text-align: left; align-items: flex-start; padding-left: 14px; max-width: 220px; }
176
+ .tjv-item--left .tjv-label { text-align: right; align-items: flex-end; padding-right: 10px; max-width: 180px; }
177
+ .tjv-item--right .tjv-label { text-align: left; align-items: flex-start; padding-left: 10px; max-width: 180px; }
174
178
  .tjv-date { font-size: 11px; font-weight: 800; letter-spacing: 0.14em; text-transform: uppercase; color: var(--tjv-item-color, var(--accent-primary)); line-height: 1.3; white-space: nowrap; }
175
- .tjv-title { font-size: 17px; font-weight: 700; line-height: 1.15; color: var(--text-primary); }
176
- .tjv-text { font-size: 13px; line-height: 1.4; color: var(--text-secondary); max-width: 210px; }
179
+ .tjv-title { font-size: 15px; font-weight: 700; line-height: 1.28; color: var(--text-primary); }
180
+ .tjv-text { font-size: 12px; line-height: 1.35; color: var(--text-secondary); max-width: 190px; }
177
181
  .svg-motif { position: relative; pointer-events: none; color: var(--text-primary); }
178
182
  .svg-motif svg { display: block; width: 100%; height: 100%; overflow: visible; }
179
183
  .svg-motif--bottom { position: absolute; left: 0; right: 0; bottom: 0; height: 30%; }
180
184
  .svg-motif--side { position: absolute; right: 0; top: 0; bottom: 0; width: 34%; }
181
185
  .svg-motif--corner { position: absolute; right: 40px; bottom: 36px; width: 360px; height: 220px; }
182
186
  .svg-motif--hero { width: 100%; height: 100%; }
187
+ .timeline-preview { display: grid; grid-template-rows: 1fr 46px 1fr; gap: 14px; height: 100%; }
188
+ .timeline-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; align-items: end; }
189
+ .timeline-row--bottom { align-items: start; }
190
+ .timeline-node { display: flex; flex-direction: column; align-items: center; justify-self: center; gap: 4px; width: min(220px, 100%); min-width: 0; text-align: center; }
191
+ .timeline-row--top .timeline-node:nth-child(even), .timeline-row--bottom .timeline-node:nth-child(odd) { visibility: hidden; }
192
+ .timeline-axis-preview { position: relative; display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; align-items: center; }
193
+ .timeline-axis-preview::before { content: ""; position: absolute; left: 0; right: 0; top: 50%; height: 1px; background: var(--line-strong); }
194
+ .timeline-dot { position: relative; z-index: 1; width: 12px; height: 12px; background: var(--dot); justify-self: center; border-radius: 999px; }
195
+ .vertical-timeline-preview { display: block; position: relative; height: 100%; min-height: 260px; }
183
196
  </style>
184
197
  </head>
185
198
  <body>
186
- <section class="slide" slide-qa="false" data-index="0" data-slide-role="cover">
199
+ <section class="slide" slide-qa="false" data-index="0" data-slide-role="cover" data-preview-layout="fullbleed" data-preview-component="hero">
187
200
  <div class="slide-canvas">
188
201
  <div class="page" style="padding:0;">
189
202
  <div class="image-title image-title--left">
@@ -193,16 +206,16 @@
193
206
  <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>
194
207
  </div>
195
208
  <div class="image-title-fg">
196
- <div class="brand-watermark"><span></span><strong>Starter</strong></div>
197
- <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>
209
+ <div class="brand-watermark" data-preview-component="brand-watermark"><span></span><strong>Starter</strong></div>
210
+ <div class="image-title-body reveal"><p class="image-title-eyebrow">Neutral base design</p><h1>Design Preview</h1><p class="image-title-subtitle">A structural scaffold for AI-authored Revela themes. Preserve the system; replace the visual identity.</p></div>
198
211
  </div>
199
- <div class="page-number page-number--light">01</div>
212
+ <div class="page-number page-number--light" data-preview-component="page-number">01</div>
200
213
  </div>
201
214
  </div>
202
215
  </div>
203
216
  </section>
204
217
 
205
- <section class="slide" slide-qa="false" data-index="1">
218
+ <section class="slide" slide-qa="false" data-index="1" data-preview-layout="toc" data-preview-component="toc">
206
219
  <div class="slide-canvas">
207
220
  <div class="page" style="padding:0;">
208
221
  <div class="toc-panel">
@@ -225,30 +238,30 @@
225
238
  </div>
226
239
  </section>
227
240
 
228
- <section class="slide" slide-qa="false" data-index="2">
241
+ <section class="slide" slide-qa="false" data-index="2" data-preview-layout="narrative">
229
242
  <div class="slide-canvas">
230
243
  <div class="page" style="padding:0;">
231
244
  <div class="narrative-grid">
232
- <div class="text-panel text-panel--light reveal">
233
- <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>
245
+ <div class="text-panel text-panel--light reveal" data-preview-component="text-panel">
246
+ <div class="text-panel-body"><p class="eyebrow">Visual schema first</p><h2>Preserve composition before changing style</h2><ul class="editorial-list"><li class="editorial-list__red"><strong>Reference type.</strong> Identify whether the source is vector, photo, UI, page, or motif.</li><li class="editorial-list__wide"><strong>Scale and anchor.</strong> Keep a bottom strip low, a corner motif small, and a hero visual dominant only when requested.</li><li class="editorial-list__green"><strong>Implementation path.</strong> Use SVG for flat motifs; use image/surface rules for photo and UI references.</li></ul></div>
234
247
  <div class="text-panel-footer"><span class="caption">Authoring constraint</span><span class="caption">03</span></div>
235
248
  </div>
236
249
  <div class="text-panel text-panel--dark reveal">
237
250
  <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>
238
- <div class="stat-card"><div class="stat-card-value">6</div><p>Baseline layouts remain available as neutral structure.</p></div>
251
+ <div class="stat-card" data-preview-component="stat-card"><div class="stat-card-value">67</div><p>Baseline layouts remain available as neutral structure.</p></div>
239
252
  </div>
240
253
  </div>
241
254
  </div>
242
255
  </div>
243
256
  </section>
244
257
 
245
- <section class="slide" slide-qa="false" data-index="3">
258
+ <section class="slide" slide-qa="false" data-index="3" data-preview-layout="highlight-cols">
246
259
  <div class="slide-canvas">
247
260
  <div class="page">
248
- <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>
261
+ <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</h2></div>
249
262
  <div class="highlight-cols-grid" style="flex:1;min-height:0;">
250
- <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>
251
- <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>
263
+ <div class="editorial-image-top reveal" data-preview-component="media"><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>
264
+ <div class="editorial-text-top reveal" data-preview-component="box"><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>
252
265
  <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>
253
266
  </div>
254
267
  <div class="page-number">04</div>
@@ -256,25 +269,23 @@
256
269
  </div>
257
270
  </section>
258
271
 
259
- <section class="slide" slide-qa="false" data-index="4">
272
+ <section class="slide" slide-qa="false" data-index="4" data-preview-layout="stacked">
260
273
  <div class="slide-canvas">
261
274
  <div class="page" style="padding:0;">
262
275
  <div class="stacked-grid">
263
276
  <div class="stacked-top text-panel reveal" style="padding:42px 56px 20px;"><div class="text-panel-body"><p class="eyebrow">Data and process</p><h2>Evidence components stay structural</h2><p>Charts, tables, and journey timelines inherit the active theme while keeping predictable geometry.</p></div></div>
264
- <div class="stacked-bottom" style="display:grid;grid-template-columns:1fr 1fr;grid-template-rows:minmax(0,1fr) 250px;gap:26px;padding:0 56px 56px;">
265
- <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>
266
- <div class="roadmap-vertical timeline-journey-vertical reveal" data-preview-component="roadmap-vertical">
277
+ <div class="stacked-bottom" style="display:grid;grid-template-columns:1fr 1fr;grid-template-rows:minmax(0,1fr) 250px;gap:26px;padding:0 56px 56px;overflow:visible;" data-preview-layout="halves">
278
+ <div class="echart-panel reveal" data-preview-component="echart-panel"><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>
279
+ <div class="roadmap-vertical timeline-journey-vertical vertical-timeline-preview reveal" data-preview-component="roadmap-vertical">
267
280
  <div class="tjv-axis"></div>
268
- <div class="tjv-item tjv-item--left" style="top:18%; --tjv-item-color:var(--accent-primary);"><div class="tjv-axis-dot"></div><div class="tjv-stem"></div><div class="tjv-tip-dot"></div><div class="tjv-label"><span class="tjv-date">Discover</span><span class="tjv-title">Signal scan</span><span class="tjv-text">Map inputs and identify the base pattern.</span></div></div>
269
- <div class="tjv-item tjv-item--right" style="top:50%; --tjv-item-color:var(--accent-secondary);"><div class="tjv-axis-dot"></div><div class="tjv-stem"></div><div class="tjv-tip-dot"></div><div class="tjv-label"><span class="tjv-date">Build</span><span class="tjv-title">Theme draft</span><span class="tjv-text">Apply visual schema without changing structure.</span></div></div>
270
- <div class="tjv-item tjv-item--left" style="top:82%; --tjv-item-color:var(--accent-danger);"><div class="tjv-axis-dot"></div><div class="tjv-stem"></div><div class="tjv-tip-dot"></div><div class="tjv-label"><span class="tjv-date">Verify</span><span class="tjv-title">Preview pass</span><span class="tjv-text">Check roles, components, and slide geometry.</span></div></div>
281
+ <div class="tjv-item tjv-item--left" style="top:18%;--tjv-item-color:var(--accent-primary);"><div class="tjv-axis-dot"></div><div class="tjv-stem"></div><div class="tjv-tip-dot"></div><div class="tjv-label"><span class="tjv-date">Discover</span><span class="tjv-title">Scan</span><span class="tjv-text">Map inputs.</span></div></div>
282
+ <div class="tjv-item tjv-item--right" style="top:50%;--tjv-item-color:var(--accent-secondary);"><div class="tjv-axis-dot"></div><div class="tjv-stem"></div><div class="tjv-tip-dot"></div><div class="tjv-label"><span class="tjv-date">Build</span><span class="tjv-title">Draft</span><span class="tjv-text">Apply schema.</span></div></div>
283
+ <div class="tjv-item tjv-item--left" style="top:82%;--tjv-item-color:var(--accent-danger);"><div class="tjv-axis-dot"></div><div class="tjv-stem"></div><div class="tjv-tip-dot"></div><div class="tjv-label"><span class="tjv-date">Verify</span><span class="tjv-title">Preview</span><span class="tjv-text">Check geometry.</span></div></div>
271
284
  </div>
272
- <div class="roadmap-horizontal timeline-journey-horizontal reveal" data-preview-component="roadmap-horizontal" style="grid-column:1 / -1;">
273
- <div class="tjh-axis"></div>
274
- <div class="tjh-item tjh-item--up" style="left:14%; --tjh-item-color:var(--accent-primary);"><div class="tjh-label"><span class="tjh-date">01</span><span class="tjh-title">Brief</span><span class="tjh-text">Clarify source style.</span></div><div class="tjh-tip-dot"></div><div class="tjh-stem"></div><div class="tjh-axis-dot"></div></div>
275
- <div class="tjh-item tjh-item--down" style="left:38%; --tjh-item-color:var(--accent-secondary);"><div class="tjh-axis-dot"></div><div class="tjh-stem"></div><div class="tjh-tip-dot"></div><div class="tjh-label"><span class="tjh-date">02</span><span class="tjh-title">Tokens</span><span class="tjh-text">Set color and type.</span></div></div>
276
- <div class="tjh-item tjh-item--up" style="left:62%; --tjh-item-color:var(--accent-danger);"><div class="tjh-label"><span class="tjh-date">03</span><span class="tjh-title">Modules</span><span class="tjh-text">Skin components.</span></div><div class="tjh-tip-dot"></div><div class="tjh-stem"></div><div class="tjh-axis-dot"></div></div>
277
- <div class="tjh-item tjh-item--down" style="left:86%; --tjh-item-color:var(--text-muted);"><div class="tjh-axis-dot"></div><div class="tjh-stem"></div><div class="tjh-tip-dot"></div><div class="tjh-label"><span class="tjh-date">04</span><span class="tjh-title">Validate</span><span class="tjh-text">Inspect preview.</span></div></div>
285
+ <div class="roadmap-horizontal timeline-preview reveal" data-preview-component="roadmap-horizontal" style="grid-column:1 / -1;">
286
+ <div class="timeline-row timeline-row--top"><div class="timeline-node"><span class="tjh-date">01</span><span class="tjh-title">Brief</span><span class="tjh-text">Clarify style.</span></div><div class="timeline-node"></div><div class="timeline-node"><span class="tjh-date">03</span><span class="tjh-title">Modules</span><span class="tjh-text">Skin blocks.</span></div><div class="timeline-node"></div></div>
287
+ <div class="timeline-axis-preview"><span class="timeline-dot" style="--dot:var(--accent-primary);"></span><span class="timeline-dot" style="--dot:var(--accent-secondary);"></span><span class="timeline-dot" style="--dot:var(--accent-danger);"></span><span class="timeline-dot" style="--dot:var(--text-muted);"></span></div>
288
+ <div class="timeline-row timeline-row--bottom"><div class="timeline-node"></div><div class="timeline-node"><span class="tjh-date">02</span><span class="tjh-title">Tokens</span><span class="tjh-text">Set type.</span></div><div class="timeline-node"></div><div class="timeline-node"><span class="tjh-date">04</span><span class="tjh-title">Validate</span><span class="tjh-text">Inspect.</span></div></div>
278
289
  </div>
279
290
  </div>
280
291
  </div>
@@ -283,13 +294,23 @@
283
294
  </div>
284
295
  </section>
285
296
 
286
- <section class="slide" slide-qa="false" data-index="5" data-slide-role="closing">
297
+ <section class="slide" slide-qa="false" data-index="5" data-slide-role="closing" data-preview-layout="narrative-reverse">
287
298
  <div class="slide-canvas">
288
299
  <div class="page">
289
300
  <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>
290
301
  <div style="height:100%;display:flex;flex-direction:column;justify-content:space-between;max-width:1040px;" class="reveal">
291
302
  <div class="brand-watermark"><span></span><strong>Starter</strong></div>
292
- <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>
303
+ <div class="quote-block" data-preview-component="quote"><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>
304
+ <div style="display:grid;grid-template-columns:1fr 1fr;gap:28px;max-width:900px;">
305
+ <ol class="steps--horizontal" data-preview-component="steps" style="list-style:none;">
306
+ <li class="step-item"><span class="step-number" data-n="1"></span><div class="step-body"><h4>Read</h4><p>Inspect the design.</p></div></li>
307
+ <li class="step-item"><span class="step-number" data-n="2"></span><div class="step-body"><h4>Render</h4><p>Apply the theme.</p></div></li>
308
+ </ol>
309
+ <table data-preview-component="data-table" style="width:100%;border-collapse:collapse;font-size:16px;">
310
+ <thead><tr><th style="text-align:left;">Check</th><th style="text-align:left;">State</th></tr></thead>
311
+ <tbody><tr><td>Canvas</td><td>Fixed</td></tr><tr><td>Preview</td><td>Complete</td></tr></tbody>
312
+ </table>
313
+ </div>
293
314
  <p class="caption">Activate derived designs after preview inspection.</p>
294
315
  </div>
295
316
  <div class="page-number">06</div>
@@ -36,6 +36,24 @@ Apply this visual style when generating all slides in this session.
36
36
  --font-size-body: 17px;
37
37
  --font-size-meta: 17px;
38
38
  --font-size-body-strong: 20px;
39
+ --grid-page-inset: 40px;
40
+ --grid-content-width: 1480px;
41
+ --grid-text-col: 480px;
42
+ --grid-image-col: 880px;
43
+ --grid-gutter: 40px;
44
+ --grid-safe-x: 80px;
45
+ --grid-safe-y: 72px;
46
+ --space-1: 8px;
47
+ --space-2: 16px;
48
+ --space-3: 24px;
49
+ --space-4: 32px;
50
+ --space-5: 48px;
51
+ --space-6: 72px;
52
+ --font-size-h3: 24px;
53
+ --font-size-h2: 36px;
54
+ --font-size-hero: 116px;
55
+ --surface-radius: 0px;
56
+ --surface-shadow: 0 24px 80px var(--shadow-soft);
39
57
  }
40
58
  ```
41
59
 
@@ -87,6 +105,14 @@ All sizes are fixed `px` for the 1920x1080 canvas. JS `transform: scale()` handl
87
105
  - Headings align to the text column, not to the full canvas.
88
106
  - Let images carry visual weight; text should remain narrow, calm, and readable.
89
107
 
108
+ Design contract:
109
+ - Grid: use `--grid-page-inset`, `--grid-content-width`, and editorial split ratios as the source of layout alignment; avoid one-off absolute positioning that bypasses the chosen layout.
110
+ - Safe area: image captions, source notes, page numbers, brand marks, and roadmap labels stay inside `--grid-safe-x` / `--grid-safe-y` unless the `hero` component owns the full canvas.
111
+ - Spacing: use the `--space-*` scale for page rhythm, component padding, card gaps, and table density. Dense slides may tighten within the scale, but should not introduce unrelated gap values.
112
+ - Type scale: use fixed 1920x1080 type tokens and the Summit sans-serif stack. Do not use viewport-relative text sizing, serif substitutions, text shadows, or glows.
113
+ - Surfaces: panels should feel like warm paper and expedition documentation. Use tonal blocks, image blocks, whitespace, and grounded shadows; avoid default container outlines, glass, neon, blobs, or dashboard chrome.
114
+ - Chart tokens: charts use Summit accents, muted axes, transparent backgrounds, explicit text colors, and stable `echart-panel` containers.
115
+
90
116
  ### Image Treatment
91
117
 
92
118
  - Use real photography or realistic documentary imagery.
@@ -869,7 +895,7 @@ Card/group primitive for one idea, case, evidence item, metric, objection, risk,
869
895
  ```
870
896
 
871
897
  ```css
872
- .box { height: 100%; min-height: 0; padding: 28px; border: 1px solid var(--line); background: transparent; display: flex; flex-direction: column; gap: 18px; overflow: hidden; }
898
+ .box { height: 100%; min-height: 0; padding: 28px; background: transparent; display: flex; flex-direction: column; gap: 18px; overflow: hidden; }
873
899
  .box--quiet { background: transparent; }
874
900
  .box--paper { background: rgba(247,244,238,0.72); }
875
901
  .box--dark { background: #2c2828; --text-primary:#f7f4ee; --text-secondary:rgba(247,244,238,0.72); --text-muted:rgba(247,244,238,0.55); --line:rgba(247,244,238,0.16); }
@@ -2415,6 +2441,7 @@ A horizontal milestone timeline with a central axis line. Nodes sit on the axis;
2415
2441
 
2416
2442
  Rules:
2417
2443
  - Position nodes with `left: X%` inline style. For N nodes, space them at `(100/(N+1)) * k %` or manually distribute to reflect time proportions.
2444
+ - Treat `left: X%` as the milestone centreline. The label, tip dot, stem, and axis dot must remain centered on that same x-position; do not left-align the label block away from the marker.
2418
2445
  - Each node requires `--tjh-item-color` set inline (use any summit accent colour).
2419
2446
  - **`--up` DOM order**: label → tip-dot → stem → axis-dot (label at top, axis-dot at bottom touching axis).
2420
2447
  - **`--down` DOM order**: axis-dot → stem → tip-dot → label (axis-dot at top touching axis, label at bottom).
@@ -2501,19 +2528,20 @@ Can be placed inside any layout slot that provides a defined height (`narrative`
2501
2528
  position: absolute;
2502
2529
  display: flex;
2503
2530
  align-items: center;
2531
+ min-width: 260px;
2504
2532
  height: 80px; /* vertical size of the clickable/hover zone */
2505
2533
  transform: translateY(-50%); /* center the row on the top: Y% point */
2506
2534
  }
2507
2535
 
2508
2536
  /* LEFT: row-reverse flips DOM order so axis-dot appears on the right (on the axis) */
2509
2537
  .tjv-item--left {
2510
- right: 50%;
2538
+ right: calc(50% - var(--tjv-node) / 2);
2511
2539
  flex-direction: row-reverse;
2512
2540
  }
2513
2541
 
2514
2542
  /* RIGHT: standard row; axis-dot appears on the left (on the axis) */
2515
2543
  .tjv-item--right {
2516
- left: 50%;
2544
+ left: calc(50% - var(--tjv-node) / 2);
2517
2545
  flex-direction: row;
2518
2546
  }
2519
2547
 
@@ -2529,13 +2557,9 @@ Can be placed inside any layout slot that provides a defined height (`narrative`
2529
2557
  }
2530
2558
 
2531
2559
  /* LEFT: axis-dot is visually rightmost (row-reverse); push right to straddle axis */
2532
- .tjv-item--left .tjv-axis-dot {
2533
- margin-right: calc(-1 * var(--tjv-node) / 2);
2534
- }
2535
-
2536
- /* RIGHT: axis-dot is visually leftmost; push left to straddle axis */
2560
+ .tjv-item--left .tjv-axis-dot,
2537
2561
  .tjv-item--right .tjv-axis-dot {
2538
- margin-left: calc(-1 * var(--tjv-node) / 2);
2562
+ margin: 0;
2539
2563
  }
2540
2564
 
2541
2565
  /* Tip dot — smaller circle at the stem end near the label */
@@ -2614,6 +2638,9 @@ Can be placed inside any layout slot that provides a defined height (`narrative`
2614
2638
  Rules:
2615
2639
  - **DOM order is identical for left and right nodes**: `axis-dot → stem → tip-dot → label`. The visual direction is controlled by CSS (`row-reverse` for left, `row` for right) — never by changing the DOM order.
2616
2640
  - Position each node with `top: Y%` inline style. For N nodes, distribute evenly: `(100 / (N + 1)) * k %` or manually to reflect actual time proportions.
2641
+ - Treat `top: Y%` as the milestone row centre. The axis dot, stem, tip dot, and label row must stay vertically centered on that same y-position.
2642
+ - Anchor left/right rows at `calc(50% - var(--tjv-node) / 2)` rather than using negative margins on `.tjv-axis-dot`; this keeps the marker centered on the axis without creating export/QA overflow.
2643
+ - Give `.tjv-item` an explicit `min-width` large enough to include label + tip + stem + axis-dot, rather than relying on intrinsic content width.
2617
2644
  - Every node must set `--tjv-item-color` inline (use any Summit accent: `--accent-earth`, `--accent-gold`, `--accent-olive`, `--accent-sage`).
2618
2645
  - Alternate `--left` and `--right` across nodes for visual rhythm. Do not place consecutive same-side nodes unless intentional.
2619
2646
  - The parent container must have a defined height. Use `height: 100%` when inside a layout slot, or set an explicit `px` height when used standalone.