@cyber-dash-tech/revela 0.19.9 → 0.20.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/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  **English** | [中文](README.zh-CN.md)
4
4
 
5
- [![npm version](https://img.shields.io/npm/v/@cyber-dash-tech/revela)](https://www.npmjs.com/package/@cyber-dash-tech/revela) [![license](https://img.shields.io/npm/l/@cyber-dash-tech/revela)](LICENSE) [![tests](https://img.shields.io/badge/tests-772%20passing-brightgreen)](tests/) [![Codex MCP](https://img.shields.io/badge/Codex-MCP-blue)](https://github.com/openai/codex) [![Bun](https://img.shields.io/badge/Bun-%E2%89%A51.0-orange)](https://bun.sh)
5
+ [![npm version](https://img.shields.io/npm/v/@cyber-dash-tech/revela)](https://www.npmjs.com/package/@cyber-dash-tech/revela) [![license](https://img.shields.io/npm/l/@cyber-dash-tech/revela)](LICENSE) [![tests](https://img.shields.io/badge/tests-779%20passing-brightgreen)](tests/) [![Codex MCP](https://img.shields.io/badge/Codex-MCP-blue)](https://github.com/openai/codex) [![Bun](https://img.shields.io/badge/Bun-%E2%89%A51.0-orange)](https://bun.sh)
6
6
 
7
7
  <p align="center">
8
8
  <img src="assets/img/logo-wordmark.png" alt="Revela" width="320" />
package/README.zh-CN.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  [English](README.md) | **中文**
4
4
 
5
- [![npm version](https://img.shields.io/npm/v/@cyber-dash-tech/revela)](https://www.npmjs.com/package/@cyber-dash-tech/revela) [![license](https://img.shields.io/npm/l/@cyber-dash-tech/revela)](LICENSE) [![tests](https://img.shields.io/badge/tests-772%20passing-brightgreen)](tests/) [![Codex MCP](https://img.shields.io/badge/Codex-MCP-blue)](https://github.com/openai/codex) [![Bun](https://img.shields.io/badge/Bun-%E2%89%A51.0-orange)](https://bun.sh)
5
+ [![npm version](https://img.shields.io/npm/v/@cyber-dash-tech/revela)](https://www.npmjs.com/package/@cyber-dash-tech/revela) [![license](https://img.shields.io/npm/l/@cyber-dash-tech/revela)](LICENSE) [![tests](https://img.shields.io/badge/tests-779%20passing-brightgreen)](tests/) [![Codex MCP](https://img.shields.io/badge/Codex-MCP-blue)](https://github.com/openai/codex) [![Bun](https://img.shields.io/badge/Bun-%E2%89%A51.0-orange)](https://bun.sh)
6
6
 
7
7
  <p align="center">
8
8
  <img src="assets/img/logo-wordmark.png" alt="Revela" width="320" />
@@ -260,11 +260,13 @@ Lucent skins Revela built-in page templates without owning their semantic struct
260
260
  - `cover`, `section-divider`, `closing`: use full-bleed hero treatment with Lucent package assets.
261
261
  - `agenda`, `executive-summary`, `problem-context`, `key-message-evidence`, `claim-supporting-visual`: use report-story/card-grid language with quiet surfaces.
262
262
  - Agenda typography follows design tokens: title and numbers use `--font-display`; item labels and footer use `--font-body`.
263
+ - `team`: use luminous portrait-led member cards with one photo, name, role, two concise highlights, and one education line. Prefer 3-4 members per page.
263
264
  - `metric-highlight`, `chart-takeaways`, `table`, `table-comparison`: use data-forward Lucent panels with explicit interpretation regions.
264
265
  - Text panels use explicit variants: `template-text-panel--clear` is transparent with no border or background, `template-text-panel--plain` is theme-neutral, and `template-text-panel--color` is the multicolor emphasis treatment used by chart and timeline reading panels.
265
266
  - `milestone`: map to the horizontal roadmap visual system. Dots remain milestone anchors inside each milestone item; do not absolutely position detached decorative dots.
266
267
  - `timeline`: map to the vertical timeline visual system. Dots remain event anchors inside each timeline item; do not absolutely position detached decorative dots.
267
268
  - `process-steps`, `recommendation-decision`, `risks-tradeoffs`: use recommendation and steps surfaces with no nested card-in-card framing.
269
+ - `free`: use a plain title plus one semantic placeholder region; the agent may later replace that region with multiple images, charts, text blocks, tables, or mixed content.
268
270
 
269
271
  <!-- @design:page-templates:end -->
270
272
 
@@ -226,6 +226,25 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
226
226
  .template-timeline--vertical .template-timeline-item:nth-child(even) .template-timeline-copy { grid-column: 3; text-align: left; align-self: center; }
227
227
  .template-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }
228
228
  .template-step-number { font-size: 48px; color: var(--accent-primary); font-weight: 800; margin-bottom: 30px; }
229
+ .template-team-grid { height: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; align-items: stretch; }
230
+ .template-team-card { min-width: 0; min-height: 0; display: grid; grid-template-rows: 330px minmax(0, 1fr); overflow: hidden; background: rgba(255,255,255,0.86); border: 1px solid var(--line); border-radius: var(--surface-radius); box-shadow: 0 18px 44px var(--shadow-soft); }
231
+ .template-team-photo { margin: 0; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(135deg, var(--accent-soft), rgba(24,168,216,0.16)); display: grid; place-items: center; }
232
+ .template-team-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
233
+ .template-team-photo span { font-family: var(--font-display); font-size: 72px; line-height: 1; color: var(--accent-primary); font-weight: 800; }
234
+ .template-team-copy { min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 26px; }
235
+ .template-team-name { margin: 0; font-size: 30px; line-height: 1.18; color: var(--text-primary); padding-bottom: 3px; overflow: visible; }
236
+ .template-team-role { margin: 0; font-size: 15px; line-height: 1.35; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
237
+ .template-team-highlights { margin: 4px 0 0; padding: 0; list-style: none; display: grid; gap: 9px; }
238
+ .template-team-highlights li { position: relative; padding-left: 18px; font-size: 17px; line-height: 1.36; color: var(--text-secondary); }
239
+ .template-team-highlights li::before { content: ""; position: absolute; left: 0; top: 9px; width: 6px; height: 6px; background: var(--accent-primary); border-radius: 999px; }
240
+ .template-team-education { margin: auto 0 0; padding-top: 14px; border-top: 1px solid var(--line); font-size: 14px; line-height: 1.35; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; }
241
+ .template-free-stage { height: 100%; display: grid; grid-template-columns: minmax(0, 1fr); }
242
+ .template-free-placeholder { min-width: 0; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 16px; padding: 42px; border: 1px dashed var(--line-strong); border-radius: var(--surface-radius); background: linear-gradient(135deg, rgba(49,94,234,0.06), rgba(24,168,216,0.07)); overflow: hidden; }
243
+ .template-free-placeholder-label { align-self: flex-start; font-size: 13px; line-height: 1; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
244
+ .template-free-placeholder h2 { margin: 0; font-size: 38px; line-height: 1.18; color: var(--text-primary); padding-bottom: 4px; overflow: visible; }
245
+ .template-free-placeholder p { margin: 0; max-width: 980px; font-size: 23px; line-height: 1.42; color: var(--text-secondary); }
246
+ .template-free-placeholder-hints { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
247
+ .template-free-placeholder-hint { display: inline-flex; align-items: center; min-height: 32px; padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px; font-size: 13px; line-height: 1; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; background: rgba(255,255,255,0.58); }
229
248
  .template-image-card { width: 100%; margin: 18px 0 0; display: grid; gap: 8px; }
230
249
  .template-image-frame { width: 100%; height: 128px; border-radius: var(--surface-radius); overflow: hidden; background: var(--surface-tint, #f1f6fc); border: 1px solid var(--line); }
231
250
  .template-image-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
@@ -305,6 +324,20 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
305
324
  .template-frame--catalog .template-timeline-copy p:last-child { font-size: 15px; line-height: 1.24; }
306
325
  .template-frame--catalog .template-steps { gap: 16px; }
307
326
  .template-frame--catalog .template-step-number { font-size: 40px; margin-bottom: 20px; }
327
+ .template-frame--catalog .template-team-grid { gap: 16px; }
328
+ .template-frame--catalog .template-team-card { grid-template-rows: 230px minmax(0, 1fr); }
329
+ .template-frame--catalog .template-team-copy { padding: 18px; gap: 8px; }
330
+ .template-frame--catalog .template-team-name { font-size: 22px; line-height: 1.14; }
331
+ .template-frame--catalog .template-team-role { font-size: 11px; line-height: 1.25; }
332
+ .template-frame--catalog .template-team-highlights { gap: 6px; }
333
+ .template-frame--catalog .template-team-highlights li { font-size: 13px; line-height: 1.25; padding-left: 14px; }
334
+ .template-frame--catalog .template-team-highlights li::before { top: 7px; width: 5px; height: 5px; }
335
+ .template-frame--catalog .template-team-education { font-size: 10px; line-height: 1.25; padding-top: 9px; }
336
+ .template-frame--catalog .template-free-placeholder { padding: 28px; gap: 10px; }
337
+ .template-frame--catalog .template-free-placeholder-label { font-size: 10px; }
338
+ .template-frame--catalog .template-free-placeholder h2 { font-size: 28px; line-height: 1.16; }
339
+ .template-frame--catalog .template-free-placeholder p { font-size: 17px; line-height: 1.3; }
340
+ .template-frame--catalog .template-free-placeholder-hint { min-height: 26px; padding: 6px 9px; font-size: 10px; }
308
341
  .template-frame--catalog .template-image-frame { height: 86px; }
309
342
  .template-frame--catalog .template-image-caption { font-size: 11px; }
310
343
  .template-frame--catalog .template-visual-placeholder-frame { height: 110px; }
@@ -260,11 +260,13 @@ Lucent skins Revela built-in page templates without owning their semantic struct
260
260
  - `cover`, `section-divider`, `closing`: use full-bleed hero treatment with Lucent package assets.
261
261
  - `agenda`, `executive-summary`, `problem-context`, `key-message-evidence`, `claim-supporting-visual`: use report-story/card-grid language with quiet surfaces.
262
262
  - Agenda typography follows design tokens: title and numbers use `--font-display`; item labels and footer use `--font-body`.
263
+ - `team`: use dark luminous portrait-led member cards with one photo, name, role, two concise highlights, and one education line. Prefer 3-4 members per page.
263
264
  - `metric-highlight`, `chart-takeaways`, `table`, `table-comparison`: use data-forward Lucent panels with explicit interpretation regions.
264
265
  - Text panels use explicit variants: `template-text-panel--clear` is transparent with no border or background, `template-text-panel--plain` is theme-neutral, and `template-text-panel--color` is the multicolor emphasis treatment used by chart and timeline reading panels.
265
266
  - `milestone`: map to the horizontal roadmap visual system. Dots remain milestone anchors inside each milestone item; do not absolutely position detached decorative dots.
266
267
  - `timeline`: map to the vertical timeline visual system. Dots remain event anchors inside each timeline item; do not absolutely position detached decorative dots.
267
268
  - `process-steps`, `recommendation-decision`, `risks-tradeoffs`: use recommendation and steps surfaces with no nested card-in-card framing.
269
+ - `free`: use a plain title plus one semantic placeholder region; the agent may later replace that region with multiple images, charts, text blocks, tables, or mixed content.
268
270
 
269
271
  <!-- @design:page-templates:end -->
270
272
 
@@ -226,6 +226,25 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
226
226
  .template-timeline--vertical .template-timeline-item:nth-child(even) .template-timeline-copy { grid-column: 3; text-align: left; align-self: center; }
227
227
  .template-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }
228
228
  .template-step-number { font-size: 48px; color: var(--accent-primary); font-weight: 800; margin-bottom: 30px; }
229
+ .template-team-grid { height: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; align-items: stretch; }
230
+ .template-team-card { min-width: 0; min-height: 0; display: grid; grid-template-rows: 330px minmax(0, 1fr); overflow: hidden; background: rgba(255,255,255,0.86); border: 1px solid var(--line); border-radius: var(--surface-radius); box-shadow: 0 18px 44px var(--shadow-soft); }
231
+ .template-team-photo { margin: 0; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(135deg, var(--accent-soft), rgba(24,168,216,0.16)); display: grid; place-items: center; }
232
+ .template-team-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
233
+ .template-team-photo span { font-family: var(--font-display); font-size: 72px; line-height: 1; color: var(--accent-primary); font-weight: 800; }
234
+ .template-team-copy { min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 26px; }
235
+ .template-team-name { margin: 0; font-size: 30px; line-height: 1.18; color: var(--text-primary); padding-bottom: 3px; overflow: visible; }
236
+ .template-team-role { margin: 0; font-size: 15px; line-height: 1.35; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
237
+ .template-team-highlights { margin: 4px 0 0; padding: 0; list-style: none; display: grid; gap: 9px; }
238
+ .template-team-highlights li { position: relative; padding-left: 18px; font-size: 17px; line-height: 1.36; color: var(--text-secondary); }
239
+ .template-team-highlights li::before { content: ""; position: absolute; left: 0; top: 9px; width: 6px; height: 6px; background: var(--accent-primary); border-radius: 999px; }
240
+ .template-team-education { margin: auto 0 0; padding-top: 14px; border-top: 1px solid var(--line); font-size: 14px; line-height: 1.35; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; }
241
+ .template-free-stage { height: 100%; display: grid; grid-template-columns: minmax(0, 1fr); }
242
+ .template-free-placeholder { min-width: 0; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 16px; padding: 42px; border: 1px dashed var(--line-strong); border-radius: var(--surface-radius); background: linear-gradient(135deg, rgba(49,94,234,0.06), rgba(24,168,216,0.07)); overflow: hidden; }
243
+ .template-free-placeholder-label { align-self: flex-start; font-size: 13px; line-height: 1; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
244
+ .template-free-placeholder h2 { margin: 0; font-size: 38px; line-height: 1.18; color: var(--text-primary); padding-bottom: 4px; overflow: visible; }
245
+ .template-free-placeholder p { margin: 0; max-width: 980px; font-size: 23px; line-height: 1.42; color: var(--text-secondary); }
246
+ .template-free-placeholder-hints { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
247
+ .template-free-placeholder-hint { display: inline-flex; align-items: center; min-height: 32px; padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px; font-size: 13px; line-height: 1; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; background: rgba(255,255,255,0.58); }
229
248
  .template-image-card { width: 100%; margin: 18px 0 0; display: grid; gap: 8px; }
230
249
  .template-image-frame { width: 100%; height: 128px; border-radius: var(--surface-radius); overflow: hidden; background: var(--surface-tint, #f1f6fc); border: 1px solid var(--line); }
231
250
  .template-image-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
@@ -305,6 +324,20 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
305
324
  .template-frame--catalog .template-timeline-copy p:last-child { font-size: 15px; line-height: 1.24; }
306
325
  .template-frame--catalog .template-steps { gap: 16px; }
307
326
  .template-frame--catalog .template-step-number { font-size: 40px; margin-bottom: 20px; }
327
+ .template-frame--catalog .template-team-grid { gap: 16px; }
328
+ .template-frame--catalog .template-team-card { grid-template-rows: 230px minmax(0, 1fr); }
329
+ .template-frame--catalog .template-team-copy { padding: 18px; gap: 8px; }
330
+ .template-frame--catalog .template-team-name { font-size: 22px; line-height: 1.14; }
331
+ .template-frame--catalog .template-team-role { font-size: 11px; line-height: 1.25; }
332
+ .template-frame--catalog .template-team-highlights { gap: 6px; }
333
+ .template-frame--catalog .template-team-highlights li { font-size: 13px; line-height: 1.25; padding-left: 14px; }
334
+ .template-frame--catalog .template-team-highlights li::before { top: 7px; width: 5px; height: 5px; }
335
+ .template-frame--catalog .template-team-education { font-size: 10px; line-height: 1.25; padding-top: 9px; }
336
+ .template-frame--catalog .template-free-placeholder { padding: 28px; gap: 10px; }
337
+ .template-frame--catalog .template-free-placeholder-label { font-size: 10px; }
338
+ .template-frame--catalog .template-free-placeholder h2 { font-size: 28px; line-height: 1.16; }
339
+ .template-frame--catalog .template-free-placeholder p { font-size: 17px; line-height: 1.3; }
340
+ .template-frame--catalog .template-free-placeholder-hint { min-height: 26px; padding: 6px 9px; font-size: 10px; }
308
341
  .template-frame--catalog .template-image-frame { height: 86px; }
309
342
  .template-frame--catalog .template-image-caption { font-size: 11px; }
310
343
  .template-frame--catalog .template-visual-placeholder-frame { height: 110px; }
@@ -342,11 +375,16 @@ body { background: var(--bg-frame); color: var(--text-primary); }
342
375
  .template-card,
343
376
  .template-table,
344
377
  .template-insight-panel,
345
- .template-catalog-panel {
378
+ .template-catalog-panel,
379
+ .template-team-card {
346
380
  background: rgba(12, 22, 40, 0.82);
347
381
  border-color: var(--line);
348
382
  box-shadow: 0 22px 58px rgba(0, 0, 0, 0.34);
349
383
  }
384
+ .template-team-photo { background: linear-gradient(135deg, rgba(117,167,255,0.18), rgba(53,214,242,0.12)); }
385
+ .template-team-photo img { filter: saturate(0.9) contrast(1.08) brightness(0.86); }
386
+ .template-free-placeholder { background: linear-gradient(135deg, rgba(117,167,255,0.12), rgba(53,214,242,0.06)), rgba(12, 22, 40, 0.7); border-color: var(--line-strong); }
387
+ .template-free-placeholder-hint { background: rgba(16, 27, 49, 0.82); }
350
388
  .template-card h2,
351
389
  .template-card h3,
352
390
  .template-title,
@@ -2800,11 +2800,13 @@ Monet skins Revela built-in page templates with soft editorial rhythm, painterly
2800
2800
  - `cover`, `section-divider`, `closing`: use expressive title-led structural pages.
2801
2801
  - `agenda`, `executive-summary`, `problem-context`, `key-message-evidence`, `claim-supporting-visual`: use soft narrative regions with no heavy outer box.
2802
2802
  - Agenda typography follows design tokens: title and numbers use `--font-display`; item labels and footer use `--font-body`.
2803
+ - `team`: use soft editorial portrait-led member cards with one photo, name, role, two concise highlights, and one education line. Prefer 3-4 members per page.
2803
2804
  - `metric-highlight`, `chart-takeaways`, `table`, `table-comparison`: use calm data surfaces and readable interpretation zones.
2804
2805
  - Text panels use explicit variants: `template-text-panel--clear` is transparent with no border or background, `template-text-panel--plain` is theme-neutral, and `template-text-panel--color` is the multicolor emphasis treatment used by chart and timeline reading panels.
2805
2806
  - `milestone`: dots remain milestone anchors inside each horizontal milestone item; do not position detached decorative markers.
2806
2807
  - `timeline`: dots remain event anchors inside each vertical timeline item; do not position detached decorative markers.
2807
2808
  - `process-steps`, `recommendation-decision`, `risks-tradeoffs`: use quiet action and tradeoff panels.
2809
+ - `free`: use a plain title plus one semantic placeholder region; the agent may later replace that region with multiple images, charts, text blocks, tables, or mixed content.
2808
2810
 
2809
2811
  <!-- @design:page-templates:end -->
2810
2812
 
@@ -226,6 +226,25 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
226
226
  .template-timeline--vertical .template-timeline-item:nth-child(even) .template-timeline-copy { grid-column: 3; text-align: left; align-self: center; }
227
227
  .template-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }
228
228
  .template-step-number { font-size: 48px; color: var(--accent-primary); font-weight: 800; margin-bottom: 30px; }
229
+ .template-team-grid { height: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; align-items: stretch; }
230
+ .template-team-card { min-width: 0; min-height: 0; display: grid; grid-template-rows: 330px minmax(0, 1fr); overflow: hidden; background: rgba(255,255,255,0.86); border: 1px solid var(--line); border-radius: var(--surface-radius); box-shadow: 0 18px 44px var(--shadow-soft); }
231
+ .template-team-photo { margin: 0; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(135deg, var(--accent-soft), rgba(24,168,216,0.16)); display: grid; place-items: center; }
232
+ .template-team-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
233
+ .template-team-photo span { font-family: var(--font-display); font-size: 72px; line-height: 1; color: var(--accent-primary); font-weight: 800; }
234
+ .template-team-copy { min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 26px; }
235
+ .template-team-name { margin: 0; font-size: 30px; line-height: 1.18; color: var(--text-primary); padding-bottom: 3px; overflow: visible; }
236
+ .template-team-role { margin: 0; font-size: 15px; line-height: 1.35; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
237
+ .template-team-highlights { margin: 4px 0 0; padding: 0; list-style: none; display: grid; gap: 9px; }
238
+ .template-team-highlights li { position: relative; padding-left: 18px; font-size: 17px; line-height: 1.36; color: var(--text-secondary); }
239
+ .template-team-highlights li::before { content: ""; position: absolute; left: 0; top: 9px; width: 6px; height: 6px; background: var(--accent-primary); border-radius: 999px; }
240
+ .template-team-education { margin: auto 0 0; padding-top: 14px; border-top: 1px solid var(--line); font-size: 14px; line-height: 1.35; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; }
241
+ .template-free-stage { height: 100%; display: grid; grid-template-columns: minmax(0, 1fr); }
242
+ .template-free-placeholder { min-width: 0; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 16px; padding: 42px; border: 1px dashed var(--line-strong); border-radius: var(--surface-radius); background: linear-gradient(135deg, rgba(49,94,234,0.06), rgba(24,168,216,0.07)); overflow: hidden; }
243
+ .template-free-placeholder-label { align-self: flex-start; font-size: 13px; line-height: 1; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
244
+ .template-free-placeholder h2 { margin: 0; font-size: 38px; line-height: 1.18; color: var(--text-primary); padding-bottom: 4px; overflow: visible; }
245
+ .template-free-placeholder p { margin: 0; max-width: 980px; font-size: 23px; line-height: 1.42; color: var(--text-secondary); }
246
+ .template-free-placeholder-hints { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
247
+ .template-free-placeholder-hint { display: inline-flex; align-items: center; min-height: 32px; padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px; font-size: 13px; line-height: 1; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; background: rgba(255,255,255,0.58); }
229
248
  .template-image-card { width: 100%; margin: 18px 0 0; display: grid; gap: 8px; }
230
249
  .template-image-frame { width: 100%; height: 128px; border-radius: var(--surface-radius); overflow: hidden; background: var(--surface-tint, #f1f6fc); border: 1px solid var(--line); }
231
250
  .template-image-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
@@ -305,6 +324,20 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
305
324
  .template-frame--catalog .template-timeline-copy p:last-child { font-size: 15px; line-height: 1.24; }
306
325
  .template-frame--catalog .template-steps { gap: 16px; }
307
326
  .template-frame--catalog .template-step-number { font-size: 40px; margin-bottom: 20px; }
327
+ .template-frame--catalog .template-team-grid { gap: 16px; }
328
+ .template-frame--catalog .template-team-card { grid-template-rows: 230px minmax(0, 1fr); }
329
+ .template-frame--catalog .template-team-copy { padding: 18px; gap: 8px; }
330
+ .template-frame--catalog .template-team-name { font-size: 22px; line-height: 1.14; }
331
+ .template-frame--catalog .template-team-role { font-size: 11px; line-height: 1.25; }
332
+ .template-frame--catalog .template-team-highlights { gap: 6px; }
333
+ .template-frame--catalog .template-team-highlights li { font-size: 13px; line-height: 1.25; padding-left: 14px; }
334
+ .template-frame--catalog .template-team-highlights li::before { top: 7px; width: 5px; height: 5px; }
335
+ .template-frame--catalog .template-team-education { font-size: 10px; line-height: 1.25; padding-top: 9px; }
336
+ .template-frame--catalog .template-free-placeholder { padding: 28px; gap: 10px; }
337
+ .template-frame--catalog .template-free-placeholder-label { font-size: 10px; }
338
+ .template-frame--catalog .template-free-placeholder h2 { font-size: 28px; line-height: 1.16; }
339
+ .template-frame--catalog .template-free-placeholder p { font-size: 17px; line-height: 1.3; }
340
+ .template-frame--catalog .template-free-placeholder-hint { min-height: 26px; padding: 6px 9px; font-size: 10px; }
308
341
  .template-frame--catalog .template-image-frame { height: 86px; }
309
342
  .template-frame--catalog .template-image-caption { font-size: 11px; }
310
343
  .template-frame--catalog .template-visual-placeholder-frame { height: 110px; }
@@ -340,11 +373,18 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
340
373
  .template-card,
341
374
  .template-table,
342
375
  .template-insight-panel,
343
- .template-catalog-panel {
376
+ .template-catalog-panel,
377
+ .template-team-card {
344
378
  background: rgba(255, 250, 243, 0.84);
345
379
  border-color: var(--line);
346
380
  box-shadow: 0 20px 50px rgba(69, 53, 38, 0.09);
347
381
  }
382
+ .template-team-photo { background: linear-gradient(135deg, rgba(65,111,136,0.14), rgba(156,111,58,0.14)); }
383
+ .template-team-photo img { filter: saturate(0.78) contrast(1.02); }
384
+ .template-team-name { font-family: var(--font-display); font-size: 34px; font-weight: 700; }
385
+ .template-team-highlights li { font-size: 18px; }
386
+ .template-free-placeholder { background: linear-gradient(135deg, rgba(65,111,136,0.08), rgba(156,111,58,0.08)), rgba(255, 250, 243, 0.72); border-color: var(--line-strong); }
387
+ .template-free-placeholder-hint { background: rgba(255, 250, 243, 0.9); }
348
388
  .template-title { font-size: 68px; line-height: 1.12; }
349
389
  .template-card p,
350
390
  .template-text-panel-body,
@@ -903,11 +903,13 @@ Starter skins Revela built-in page templates as a neutral authoring system. The
903
903
  - `cover`, `section-divider`, `closing`: use clear title-first structural pages.
904
904
  - `agenda`, `executive-summary`, `problem-context`, `key-message-evidence`, `claim-supporting-visual`: use plain narrative and card-grid surfaces.
905
905
  - Agenda typography follows design tokens: title and numbers use `--font-display`; item labels and footer use `--font-body`.
906
+ - `team`: use portrait-led member cards with one photo, name, role, two concise highlights, and one education line. Prefer 3-4 members per page.
906
907
  - `metric-highlight`, `chart-takeaways`, `table`, `table-comparison`: use direct data panels with minimal decoration.
907
908
  - Text panels use explicit variants: `template-text-panel--clear` is transparent with no border or background, `template-text-panel--plain` is theme-neutral, and `template-text-panel--color` is the multicolor emphasis treatment used by chart and timeline reading panels.
908
909
  - `milestone`: dots remain milestone anchors inside each horizontal milestone item; do not position detached decorative markers.
909
910
  - `timeline`: dots remain event anchors inside each vertical timeline item; do not position detached decorative markers.
910
911
  - `process-steps`, `recommendation-decision`, `risks-tradeoffs`: use simple step and decision panels.
912
+ - `free`: use a plain title plus one semantic placeholder region; the agent may later replace that region with multiple images, charts, text blocks, tables, or mixed content.
911
913
 
912
914
  <!-- @design:page-templates:end -->
913
915
 
@@ -226,6 +226,25 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
226
226
  .template-timeline--vertical .template-timeline-item:nth-child(even) .template-timeline-copy { grid-column: 3; text-align: left; align-self: center; }
227
227
  .template-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }
228
228
  .template-step-number { font-size: 48px; color: var(--accent-primary); font-weight: 800; margin-bottom: 30px; }
229
+ .template-team-grid { height: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; align-items: stretch; }
230
+ .template-team-card { min-width: 0; min-height: 0; display: grid; grid-template-rows: 330px minmax(0, 1fr); overflow: hidden; background: rgba(255,255,255,0.86); border: 1px solid var(--line); border-radius: var(--surface-radius); box-shadow: 0 18px 44px var(--shadow-soft); }
231
+ .template-team-photo { margin: 0; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(135deg, var(--accent-soft), rgba(24,168,216,0.16)); display: grid; place-items: center; }
232
+ .template-team-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
233
+ .template-team-photo span { font-family: var(--font-display); font-size: 72px; line-height: 1; color: var(--accent-primary); font-weight: 800; }
234
+ .template-team-copy { min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 26px; }
235
+ .template-team-name { margin: 0; font-size: 30px; line-height: 1.18; color: var(--text-primary); padding-bottom: 3px; overflow: visible; }
236
+ .template-team-role { margin: 0; font-size: 15px; line-height: 1.35; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
237
+ .template-team-highlights { margin: 4px 0 0; padding: 0; list-style: none; display: grid; gap: 9px; }
238
+ .template-team-highlights li { position: relative; padding-left: 18px; font-size: 17px; line-height: 1.36; color: var(--text-secondary); }
239
+ .template-team-highlights li::before { content: ""; position: absolute; left: 0; top: 9px; width: 6px; height: 6px; background: var(--accent-primary); border-radius: 999px; }
240
+ .template-team-education { margin: auto 0 0; padding-top: 14px; border-top: 1px solid var(--line); font-size: 14px; line-height: 1.35; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; }
241
+ .template-free-stage { height: 100%; display: grid; grid-template-columns: minmax(0, 1fr); }
242
+ .template-free-placeholder { min-width: 0; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 16px; padding: 42px; border: 1px dashed var(--line-strong); border-radius: var(--surface-radius); background: linear-gradient(135deg, rgba(49,94,234,0.06), rgba(24,168,216,0.07)); overflow: hidden; }
243
+ .template-free-placeholder-label { align-self: flex-start; font-size: 13px; line-height: 1; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
244
+ .template-free-placeholder h2 { margin: 0; font-size: 38px; line-height: 1.18; color: var(--text-primary); padding-bottom: 4px; overflow: visible; }
245
+ .template-free-placeholder p { margin: 0; max-width: 980px; font-size: 23px; line-height: 1.42; color: var(--text-secondary); }
246
+ .template-free-placeholder-hints { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
247
+ .template-free-placeholder-hint { display: inline-flex; align-items: center; min-height: 32px; padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px; font-size: 13px; line-height: 1; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; background: rgba(255,255,255,0.58); }
229
248
  .template-image-card { width: 100%; margin: 18px 0 0; display: grid; gap: 8px; }
230
249
  .template-image-frame { width: 100%; height: 128px; border-radius: var(--surface-radius); overflow: hidden; background: var(--surface-tint, #f1f6fc); border: 1px solid var(--line); }
231
250
  .template-image-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
@@ -305,6 +324,20 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
305
324
  .template-frame--catalog .template-timeline-copy p:last-child { font-size: 15px; line-height: 1.24; }
306
325
  .template-frame--catalog .template-steps { gap: 16px; }
307
326
  .template-frame--catalog .template-step-number { font-size: 40px; margin-bottom: 20px; }
327
+ .template-frame--catalog .template-team-grid { gap: 16px; }
328
+ .template-frame--catalog .template-team-card { grid-template-rows: 230px minmax(0, 1fr); }
329
+ .template-frame--catalog .template-team-copy { padding: 18px; gap: 8px; }
330
+ .template-frame--catalog .template-team-name { font-size: 22px; line-height: 1.14; }
331
+ .template-frame--catalog .template-team-role { font-size: 11px; line-height: 1.25; }
332
+ .template-frame--catalog .template-team-highlights { gap: 6px; }
333
+ .template-frame--catalog .template-team-highlights li { font-size: 13px; line-height: 1.25; padding-left: 14px; }
334
+ .template-frame--catalog .template-team-highlights li::before { top: 7px; width: 5px; height: 5px; }
335
+ .template-frame--catalog .template-team-education { font-size: 10px; line-height: 1.25; padding-top: 9px; }
336
+ .template-frame--catalog .template-free-placeholder { padding: 28px; gap: 10px; }
337
+ .template-frame--catalog .template-free-placeholder-label { font-size: 10px; }
338
+ .template-frame--catalog .template-free-placeholder h2 { font-size: 28px; line-height: 1.16; }
339
+ .template-frame--catalog .template-free-placeholder p { font-size: 17px; line-height: 1.3; }
340
+ .template-frame--catalog .template-free-placeholder-hint { min-height: 26px; padding: 6px 9px; font-size: 10px; }
308
341
  .template-frame--catalog .template-image-frame { height: 86px; }
309
342
  .template-frame--catalog .template-image-caption { font-size: 11px; }
310
343
  .template-frame--catalog .template-visual-placeholder-frame { height: 110px; }
@@ -335,7 +368,10 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
335
368
  .template-card,
336
369
  .template-table,
337
370
  .template-insight-panel,
338
- .template-catalog-panel { box-shadow: none; }
371
+ .template-catalog-panel,
372
+ .template-team-card { box-shadow: none; }
373
+ .template-team-photo img { filter: saturate(0.92) contrast(1.04); }
374
+ .template-free-placeholder { box-shadow: none; }
339
375
  .template-slide[data-template="cover"] .slide-canvas,
340
376
  .template-slide[data-template="agenda"] .slide-canvas,
341
377
  .template-slide[data-template="section-divider"] .slide-canvas {
@@ -2604,11 +2604,13 @@ Summit skins Revela built-in page templates with editorial hierarchy, broad whit
2604
2604
  - `cover`, `section-divider`, `closing`: use strong editorial title pages.
2605
2605
  - `agenda`, `executive-summary`, `problem-context`, `key-message-evidence`, `claim-supporting-visual`: use borderless narrative groupings with clear hierarchy.
2606
2606
  - Agenda typography follows design tokens: title and numbers use `--font-display`; item labels and footer use `--font-body`.
2607
+ - `team`: use portrait-led member cards with one clear photo, name, role, two project/career highlights, and one highest-education line. Optimize for 3-4 members per page; 5-6 members require short copy and consistent portraits.
2607
2608
  - `metric-highlight`, `chart-takeaways`, `table`, `table-comparison`: use evidence-first data regions without outer container borders.
2608
2609
  - Text panels use explicit variants: `template-text-panel--clear` is transparent with no border or background, `template-text-panel--plain` is theme-neutral, and `template-text-panel--color` is the multicolor emphasis treatment used by chart and timeline reading panels.
2609
2610
  - `milestone`: dots remain milestone anchors inside each horizontal milestone item; do not position detached decorative markers.
2610
2611
  - `timeline`: dots remain event anchors inside each vertical timeline item; do not position detached decorative markers.
2611
2612
  - `process-steps`, `recommendation-decision`, `risks-tradeoffs`: use decisive action panels with minimal framing.
2613
+ - `free`: use a plain title plus one semantic placeholder region. The agent may later replace that region with multiple images, charts, text blocks, tables, or mixed content; do not use it as raw arbitrary HTML.
2612
2614
 
2613
2615
  <!-- @design:page-templates:end -->
2614
2616
 
@@ -226,6 +226,25 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
226
226
  .template-timeline--vertical .template-timeline-item:nth-child(even) .template-timeline-copy { grid-column: 3; text-align: left; align-self: center; }
227
227
  .template-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }
228
228
  .template-step-number { font-size: 48px; color: var(--accent-primary); font-weight: 800; margin-bottom: 30px; }
229
+ .template-team-grid { height: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; align-items: stretch; }
230
+ .template-team-card { min-width: 0; min-height: 0; display: grid; grid-template-rows: 330px minmax(0, 1fr); overflow: hidden; background: rgba(255,255,255,0.86); border: 1px solid var(--line); border-radius: var(--surface-radius); box-shadow: 0 18px 44px var(--shadow-soft); }
231
+ .template-team-photo { margin: 0; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(135deg, var(--accent-soft), rgba(24,168,216,0.16)); display: grid; place-items: center; }
232
+ .template-team-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
233
+ .template-team-photo span { font-family: var(--font-display); font-size: 72px; line-height: 1; color: var(--accent-primary); font-weight: 800; }
234
+ .template-team-copy { min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 26px; }
235
+ .template-team-name { margin: 0; font-size: 30px; line-height: 1.18; color: var(--text-primary); padding-bottom: 3px; overflow: visible; }
236
+ .template-team-role { margin: 0; font-size: 15px; line-height: 1.35; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
237
+ .template-team-highlights { margin: 4px 0 0; padding: 0; list-style: none; display: grid; gap: 9px; }
238
+ .template-team-highlights li { position: relative; padding-left: 18px; font-size: 17px; line-height: 1.36; color: var(--text-secondary); }
239
+ .template-team-highlights li::before { content: ""; position: absolute; left: 0; top: 9px; width: 6px; height: 6px; background: var(--accent-primary); border-radius: 999px; }
240
+ .template-team-education { margin: auto 0 0; padding-top: 14px; border-top: 1px solid var(--line); font-size: 14px; line-height: 1.35; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; }
241
+ .template-free-stage { height: 100%; display: grid; grid-template-columns: minmax(0, 1fr); }
242
+ .template-free-placeholder { min-width: 0; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 16px; padding: 42px; border: 1px dashed var(--line-strong); border-radius: var(--surface-radius); background: linear-gradient(135deg, rgba(49,94,234,0.06), rgba(24,168,216,0.07)); overflow: hidden; }
243
+ .template-free-placeholder-label { align-self: flex-start; font-size: 13px; line-height: 1; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
244
+ .template-free-placeholder h2 { margin: 0; font-size: 38px; line-height: 1.18; color: var(--text-primary); padding-bottom: 4px; overflow: visible; }
245
+ .template-free-placeholder p { margin: 0; max-width: 980px; font-size: 23px; line-height: 1.42; color: var(--text-secondary); }
246
+ .template-free-placeholder-hints { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
247
+ .template-free-placeholder-hint { display: inline-flex; align-items: center; min-height: 32px; padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px; font-size: 13px; line-height: 1; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; background: rgba(255,255,255,0.58); }
229
248
  .template-image-card { width: 100%; margin: 18px 0 0; display: grid; gap: 8px; }
230
249
  .template-image-frame { width: 100%; height: 128px; border-radius: var(--surface-radius); overflow: hidden; background: var(--surface-tint, #f1f6fc); border: 1px solid var(--line); }
231
250
  .template-image-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
@@ -305,6 +324,20 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
305
324
  .template-frame--catalog .template-timeline-copy p:last-child { font-size: 15px; line-height: 1.24; }
306
325
  .template-frame--catalog .template-steps { gap: 16px; }
307
326
  .template-frame--catalog .template-step-number { font-size: 40px; margin-bottom: 20px; }
327
+ .template-frame--catalog .template-team-grid { gap: 16px; }
328
+ .template-frame--catalog .template-team-card { grid-template-rows: 230px minmax(0, 1fr); }
329
+ .template-frame--catalog .template-team-copy { padding: 18px; gap: 8px; }
330
+ .template-frame--catalog .template-team-name { font-size: 22px; line-height: 1.14; }
331
+ .template-frame--catalog .template-team-role { font-size: 11px; line-height: 1.25; }
332
+ .template-frame--catalog .template-team-highlights { gap: 6px; }
333
+ .template-frame--catalog .template-team-highlights li { font-size: 13px; line-height: 1.25; padding-left: 14px; }
334
+ .template-frame--catalog .template-team-highlights li::before { top: 7px; width: 5px; height: 5px; }
335
+ .template-frame--catalog .template-team-education { font-size: 10px; line-height: 1.25; padding-top: 9px; }
336
+ .template-frame--catalog .template-free-placeholder { padding: 28px; gap: 10px; }
337
+ .template-frame--catalog .template-free-placeholder-label { font-size: 10px; }
338
+ .template-frame--catalog .template-free-placeholder h2 { font-size: 28px; line-height: 1.16; }
339
+ .template-frame--catalog .template-free-placeholder p { font-size: 17px; line-height: 1.3; }
340
+ .template-frame--catalog .template-free-placeholder-hint { min-height: 26px; padding: 6px 9px; font-size: 10px; }
308
341
  .template-frame--catalog .template-image-frame { height: 86px; }
309
342
  .template-frame--catalog .template-image-caption { font-size: 11px; }
310
343
  .template-frame--catalog .template-visual-placeholder-frame { height: 110px; }
@@ -348,6 +381,34 @@ body { margin: 0; background: var(--bg-frame, #07111f); color: var(--text-primar
348
381
  .template-timeline-layout .template-text-panel--color {
349
382
  background: linear-gradient(135deg, #176c63 0%, #2a8f84 54%, #b0822e 125%);
350
383
  }
384
+ .template-team-card {
385
+ background: rgba(255,255,255,0.9);
386
+ border-color: transparent;
387
+ box-shadow: 0 24px 58px rgba(18, 37, 34, 0.11);
388
+ }
389
+ .template-team-photo {
390
+ background: linear-gradient(135deg, rgba(23,108,99,0.16), rgba(176,130,46,0.16));
391
+ }
392
+ .template-team-photo img { filter: saturate(0.92) contrast(1.04); }
393
+ .template-team-name { font-family: var(--font-display); font-weight: 600; }
394
+ .template-team-role,
395
+ .template-team-education,
396
+ .template-free-placeholder-label,
397
+ .template-free-placeholder-hint {
398
+ font-family: var(--font-body);
399
+ }
400
+ .template-team-role,
401
+ .template-team-highlights li::before,
402
+ .template-free-placeholder-label {
403
+ color: var(--accent-primary);
404
+ }
405
+ .template-free-placeholder {
406
+ background:
407
+ linear-gradient(135deg, rgba(10,16,16,0.08), rgba(23,108,99,0.09)),
408
+ rgba(255,255,255,0.68);
409
+ border-color: rgba(35, 53, 49, 0.22);
410
+ box-shadow: none;
411
+ }
351
412
  .template-slide[data-template="cover"] .slide-canvas,
352
413
  .template-slide[data-template="agenda"] .slide-canvas,
353
414
  .template-slide[data-template="section-divider"] .slide-canvas {
@@ -12,7 +12,7 @@
12
12
  <div class="slide-canvas">
13
13
  <div class="template-frame template-hero template-hero--cover">
14
14
  <div data-template-slot="hero"><header>
15
- <p class="template-eyebrow">Template 01 / 17</p>
15
+ <p class="template-eyebrow">Template 01 / 19</p>
16
16
  <h1 class="template-title template-hero-title">cover</h1>
17
17
  </header></div>
18
18
 
@@ -24,7 +24,7 @@
24
24
  <div class="slide-canvas">
25
25
  <div class="template-frame template-hero template-hero--section-divider">
26
26
  <div data-template-slot="hero"><header>
27
- <p class="template-eyebrow">Template 02 / 17</p>
27
+ <p class="template-eyebrow">Template 02 / 19</p>
28
28
  <h1 class="template-title template-hero-title">section-divider</h1>
29
29
  </header></div>
30
30
 
@@ -36,7 +36,7 @@
36
36
  <div class="slide-canvas">
37
37
  <div class="template-frame template-hero template-hero--closing">
38
38
  <div data-template-slot="hero"><header>
39
- <p class="template-eyebrow">Template 03 / 17</p>
39
+ <p class="template-eyebrow">Template 03 / 19</p>
40
40
  <h1 class="template-title template-hero-title">closing</h1>
41
41
  </header></div>
42
42
 
@@ -50,7 +50,7 @@
50
50
  <div class="template-body template-agenda-panel" data-template-slot="agenda">
51
51
  <div class="template-agenda-inner">
52
52
  <div class="template-agenda-header">
53
- <p class="template-eyebrow">Template 04 / 17</p>
53
+ <p class="template-eyebrow">Template 04 / 19</p>
54
54
  <h1 class="template-title">agenda</h1>
55
55
  <p class="template-agenda-footer">Structure-First-Design</p>
56
56
  </div>
@@ -66,7 +66,7 @@
66
66
  <div class="slide-canvas">
67
67
  <div class="template-frame">
68
68
  <header>
69
- <p class="template-eyebrow">Template 05 / 17</p>
69
+ <p class="template-eyebrow">Template 05 / 19</p>
70
70
  <h1 class="template-title">executive-summary</h1>
71
71
  </header><div class="template-body template-grid cols-3" data-template-slot="summary-cards"><article class="template-card"><h2>Decision is ready</h2><p>The facts support moving from discussion to selection without adding another analysis cycle.</p><figure class="template-visual-placeholder"><div class="template-visual-placeholder-frame"><span class="template-visual-placeholder-label">image / chart slot (optional)</span></div></figure></article><article class="template-card"><h2>Risk is bounded</h2><p>Known caveats are visible, named, and can be managed through rollout gates.</p><figure class="template-visual-placeholder"><div class="template-visual-placeholder-frame"><span class="template-visual-placeholder-label">image / chart slot (optional)</span></div></figure></article><article class="template-card"><h2>Next step is narrow</h2><p>A pilot decision creates more learning without overcommitting capital or team capacity.</p><figure class="template-visual-placeholder"><div class="template-visual-placeholder-frame"><span class="template-visual-placeholder-label">image / chart slot (optional)</span></div></figure></article></div>
72
72
 
@@ -74,23 +74,67 @@
74
74
  <div class="template-page-number">05</div>
75
75
  </div>
76
76
  </section>
77
- <section class="slide template-slide" slide-qa="true" data-slide-index="6" data-design="built-in-preview" data-template="problem-context">
77
+ <section class="slide template-slide" slide-qa="true" data-slide-index="6" data-design="built-in-preview" data-template="team">
78
78
  <div class="slide-canvas">
79
79
  <div class="template-frame">
80
80
  <header>
81
- <p class="template-eyebrow">Template 06 / 17</p>
81
+ <p class="template-eyebrow">Template 06 / 19</p>
82
+ <h1 class="template-title">team</h1>
83
+ </header><div class="template-body"><div class="template-team-grid" data-template-slot="members"><article class="template-team-card">
84
+ <figure class="template-team-photo"><img src="./assets/card-lens.jpg" alt="Portrait placeholder"></figure>
85
+ <div class="template-team-copy">
86
+ <h2 class="template-team-name">Maya Chen</h2>
87
+ <p class="template-team-role">Product and AI systems</p>
88
+ <ul class="template-team-highlights"><li>Led the decision workspace launch from zero to enterprise pilot.</li><li>Built source-linked review loops for regulated teams.</li></ul>
89
+ <p class="template-team-education">M.S., Human-Computer Interaction</p>
90
+ </div>
91
+ </article><article class="template-team-card">
92
+ <figure class="template-team-photo"><img src="./assets/report-visual.jpg" alt="Portrait placeholder"></figure>
93
+ <div class="template-team-copy">
94
+ <h2 class="template-team-name">Jon Bell</h2>
95
+ <p class="template-team-role">Go-to-market and partnerships</p>
96
+ <ul class="template-team-highlights"><li>Scaled strategic accounts across finance and healthcare.</li><li>Opened channel partnerships with implementation teams.</li></ul>
97
+ <p class="template-team-education">MBA, Strategy and Operations</p>
98
+ </div>
99
+ </article><article class="template-team-card">
100
+ <figure class="template-team-photo"><img src="./assets/soft-texture.jpg" alt="Portrait placeholder"></figure>
101
+ <div class="template-team-copy">
102
+ <h2 class="template-team-name">Ari Patel</h2>
103
+ <p class="template-team-role">Data and platform engineering</p>
104
+ <ul class="template-team-highlights"><li>Architected reliable artifact generation and QA pipelines.</li><li>Shipped analytics systems used by executive teams.</li></ul>
105
+ <p class="template-team-education">B.S., Computer Science</p>
106
+ </div>
107
+ </article><article class="template-team-card">
108
+ <figure class="template-team-photo"><img src="./assets/toc-orb.png" alt="Portrait placeholder"></figure>
109
+ <div class="template-team-copy">
110
+ <h2 class="template-team-name">Lina Gomez</h2>
111
+ <p class="template-team-role">Research and narrative design</p>
112
+ <ul class="template-team-highlights"><li>Directed research synthesis for high-stakes board materials.</li><li>Designed traceable evidence models for complex decisions.</li></ul>
113
+ <p class="template-team-education">M.A., Communication Design</p>
114
+ </div>
115
+ </article></div></div>
116
+
117
+ </div>
118
+ <div class="template-page-number">06</div>
119
+ </div>
120
+ </section>
121
+ <section class="slide template-slide" slide-qa="true" data-slide-index="7" data-design="built-in-preview" data-template="problem-context">
122
+ <div class="slide-canvas">
123
+ <div class="template-frame">
124
+ <header>
125
+ <p class="template-eyebrow">Template 07 / 19</p>
82
126
  <h1 class="template-title">problem-context</h1>
83
127
  </header><div class="template-body template-grid cols-2"><div class="template-card" data-template-slot="context"><p>Use this template when the audience needs the situation, tension, and implication before seeing recommendations.</p></div><div class="template-card" data-template-slot="supporting-points"><ul class="template-list"><li><strong>Situation</strong> A shift has changed the operating baseline.</li><li><strong>Tension</strong> Current process cannot absorb the new variance cleanly.</li><li><strong>Implication</strong> Delay increases rework and weakens decision confidence.</li></ul></div></div>
84
128
 
85
129
  </div>
86
- <div class="template-page-number">06</div>
130
+ <div class="template-page-number">07</div>
87
131
  </div>
88
132
  </section>
89
- <section class="slide template-slide" slide-qa="true" data-slide-index="7" data-design="built-in-preview" data-template="key-message-evidence">
133
+ <section class="slide template-slide" slide-qa="true" data-slide-index="8" data-design="built-in-preview" data-template="key-message-evidence">
90
134
  <div class="slide-canvas">
91
135
  <div class="template-frame">
92
136
  <header>
93
- <p class="template-eyebrow">Template 07 / 17</p>
137
+ <p class="template-eyebrow">Template 08 / 19</p>
94
138
  <h1 class="template-title">key-message-evidence</h1>
95
139
  </header><div class="template-body template-grid cols-2"><div class="template-key-message-panel" data-template-slot="key-message">
96
140
  <h2 class="template-key-message-kicker">Key message</h2>
@@ -98,14 +142,14 @@
98
142
  </div><div class="template-evidence-grid" data-template-slot="evidence"><article class="template-card template-evidence-card"><h3>Evidence 1</h3><p>The generated HTML separates the key-message panel from the evidence grid, so the claim cannot collapse into generic card content.</p></article><article class="template-card template-evidence-card"><h3>Evidence 2</h3><p>Each evidence slot has a stable title and explanation area, giving the agent a predictable place for proof, caveat, or source-backed detail.</p></article><article class="template-card template-evidence-card"><h3>Evidence 3</h3><p>QA can inspect the DOM contract before visual styling, which keeps template structure from depending on a design skin.</p></article></div></div>
99
143
 
100
144
  </div>
101
- <div class="template-page-number">07</div>
145
+ <div class="template-page-number">08</div>
102
146
  </div>
103
147
  </section>
104
- <section class="slide template-slide" slide-qa="true" data-slide-index="8" data-design="built-in-preview" data-template="claim-supporting-visual">
148
+ <section class="slide template-slide" slide-qa="true" data-slide-index="9" data-design="built-in-preview" data-template="claim-supporting-visual">
105
149
  <div class="slide-canvas">
106
150
  <div class="template-frame">
107
151
  <header>
108
- <p class="template-eyebrow">Template 08 / 17</p>
152
+ <p class="template-eyebrow">Template 09 / 19</p>
109
153
  <h1 class="template-title">claim-supporting-visual</h1>
110
154
  </header><div class="template-body template-grid cols-2"><div class="template-claim-text-panel" data-template-slot="claim">
111
155
  <h2 class="template-claim-text-title">A single visual should carry one argument.</h2>
@@ -114,14 +158,14 @@
114
158
  </div><div class="template-chart-panel template-visual-slot-panel" data-template-slot="visual"><span class="template-visual-slot-label">image / chart slot (optional)</span></div></div>
115
159
 
116
160
  </div>
117
- <div class="template-page-number">08</div>
161
+ <div class="template-page-number">09</div>
118
162
  </div>
119
163
  </section>
120
- <section class="slide template-slide" slide-qa="true" data-slide-index="9" data-design="built-in-preview" data-template="metric-highlight">
164
+ <section class="slide template-slide" slide-qa="true" data-slide-index="10" data-design="built-in-preview" data-template="metric-highlight">
121
165
  <div class="slide-canvas">
122
166
  <div class="template-frame">
123
167
  <header>
124
- <p class="template-eyebrow">Template 09 / 17</p>
168
+ <p class="template-eyebrow">Template 10 / 19</p>
125
169
  <h1 class="template-title">metric-highlight</h1>
126
170
  </header><div class="template-body"><div class="template-metric-layout template-metric-layout--insight-bottom"><div class="template-stat-grid" data-template-slot="metrics"><article class="template-card"><div class="template-stat-value">67%</div><h2>Adoption signal</h2><p>Primary number plus interpretation.</p></article><article class="template-card"><div class="template-stat-value">3x</div><h2>Review speed</h2><p>Comparison is stated beside the metric.</p></article><article class="template-card"><div class="template-stat-value">14d</div><h2>Pilot window</h2><p>Time bound keeps the ask concrete.</p></article></div><div class="template-insight-panel">
127
171
  <h2 class="template-insight-title"><i class="template-insight-icon" data-lucide="scan-search" aria-hidden="true"></i><span>Read the signal</span></h2>
@@ -129,14 +173,14 @@
129
173
  </div></div></div>
130
174
 
131
175
  </div>
132
- <div class="template-page-number">09</div>
176
+ <div class="template-page-number">10</div>
133
177
  </div>
134
178
  </section>
135
- <section class="slide template-slide" slide-qa="true" data-slide-index="10" data-design="built-in-preview" data-template="chart-takeaways">
179
+ <section class="slide template-slide" slide-qa="true" data-slide-index="11" data-design="built-in-preview" data-template="chart-takeaways">
136
180
  <div class="slide-canvas">
137
181
  <div class="template-frame">
138
182
  <header>
139
- <p class="template-eyebrow">Template 10 / 17</p>
183
+ <p class="template-eyebrow">Template 11 / 19</p>
140
184
  <h1 class="template-title">chart-takeaways</h1>
141
185
  </header><div class="template-body template-grid template-chart-layout"><div class="template-chart-panel template-visual-slot-panel" data-template-slot="visual"><span class="template-visual-slot-label">image / chart slot (optional)</span></div><div class="template-text-panel template-text-panel--color template-chart-takeaway-panel" data-template-slot="takeaways">
142
186
  <h2 class="template-text-panel-title">What to read</h2>
@@ -145,26 +189,26 @@
145
189
  </div></div>
146
190
 
147
191
  </div>
148
- <div class="template-page-number">10</div>
192
+ <div class="template-page-number">11</div>
149
193
  </div>
150
194
  </section>
151
- <section class="slide template-slide" slide-qa="true" data-slide-index="11" data-design="built-in-preview" data-template="table">
195
+ <section class="slide template-slide" slide-qa="true" data-slide-index="12" data-design="built-in-preview" data-template="table">
152
196
  <div class="slide-canvas">
153
197
  <div class="template-frame">
154
198
  <header>
155
- <p class="template-eyebrow">Template 11 / 17</p>
199
+ <p class="template-eyebrow">Template 12 / 19</p>
156
200
  <h1 class="template-title">table</h1>
157
201
  </header><div class="template-body"><div class="template-table-layout"><div class="template-side-panel template-text-panel template-text-panel--clear" data-template-slot="text-card"><h2 class="template-side-panel-title template-text-panel-title">Financial readout</h2><p class="template-side-panel-body template-text-panel-body">Read top-line growth first, then check margin, cash conversion, and retention to see whether the plan is financially durable.</p><blockquote class="template-text-panel-quote">Durability shows up when growth, margin, and cash all point in the same direction.</blockquote></div><div class="template-table-region" data-template-slot="table"><div class="template-table-wrap"><table class="template-table"><thead><tr><th>Line item</th><th>FY2025</th><th>FY2026 Plan</th><th>YoY / note</th></tr></thead><tbody><tr><td>Revenue</td><td>$84.2M</td><td>$104.8M</td><td>+24% planned growth</td></tr><tr><td>Gross margin</td><td>68.4%</td><td>71.2%</td><td>+280 bps mix shift</td></tr><tr><td>Operating expense</td><td>$42.7M</td><td>$49.1M</td><td>Scale hiring below revenue growth</td></tr><tr><td>EBITDA</td><td>$14.9M</td><td>$23.6M</td><td>+58% operating leverage</td></tr><tr><td>Free cash flow</td><td>$9.8M</td><td>$16.4M</td><td>Cash conversion improves to 69%</td></tr><tr><td>Net retention</td><td>116%</td><td>121%</td><td>Expansion supports plan quality</td></tr></tbody></table></div></div></div></div>
158
202
 
159
203
  </div>
160
- <div class="template-page-number">11</div>
204
+ <div class="template-page-number">12</div>
161
205
  </div>
162
206
  </section>
163
- <section class="slide template-slide" slide-qa="true" data-slide-index="12" data-design="built-in-preview" data-template="table-comparison">
207
+ <section class="slide template-slide" slide-qa="true" data-slide-index="13" data-design="built-in-preview" data-template="table-comparison">
164
208
  <div class="slide-canvas">
165
209
  <div class="template-frame">
166
210
  <header>
167
- <p class="template-eyebrow">Template 12 / 17</p>
211
+ <p class="template-eyebrow">Template 13 / 19</p>
168
212
  <h1 class="template-title">table-comparison</h1>
169
213
  </header><div class="template-body" data-template-slot="table"><div class="template-table-wrap"><table class="template-table"><thead><tr><th>Layer</th><th>Owns</th><th>Agent task</th></tr></thead><tbody><tr><td>Template</td><td>Structure and DOM contract</td><td>Select the page pattern</td></tr><tr><td>Content</td><td>Claim, evidence, caveat</td><td>Fill the meaning</td></tr><tr><td>Design</td><td>Color, type, surfaces</td><td>Skin stable classes</td></tr></tbody></table><div class="template-insight-panel">
170
214
  <h2 class="template-insight-title"><i class="template-insight-icon" data-lucide="lightbulb" aria-hidden="true"></i><span>Insight</span></h2>
@@ -172,14 +216,14 @@
172
216
  </div></div></div>
173
217
 
174
218
  </div>
175
- <div class="template-page-number">12</div>
219
+ <div class="template-page-number">13</div>
176
220
  </div>
177
221
  </section>
178
- <section class="slide template-slide" slide-qa="true" data-slide-index="13" data-design="built-in-preview" data-template="milestone">
222
+ <section class="slide template-slide" slide-qa="true" data-slide-index="14" data-design="built-in-preview" data-template="milestone">
179
223
  <div class="slide-canvas">
180
224
  <div class="template-frame">
181
225
  <header>
182
- <p class="template-eyebrow">Template 13 / 17</p>
226
+ <p class="template-eyebrow">Template 14 / 19</p>
183
227
  <h1 class="template-title">milestone</h1>
184
228
  </header><div class="template-body"><div class="template-timeline template-timeline--horizontal" data-template-slot="timeline" style="--timeline-count:5"><article class="template-timeline-item">
185
229
  <div class="template-timeline-copy template-card">
@@ -224,14 +268,14 @@
224
268
  </article></div></div>
225
269
 
226
270
  </div>
227
- <div class="template-page-number">13</div>
271
+ <div class="template-page-number">14</div>
228
272
  </div>
229
273
  </section>
230
- <section class="slide template-slide" slide-qa="true" data-slide-index="14" data-design="built-in-preview" data-template="timeline">
274
+ <section class="slide template-slide" slide-qa="true" data-slide-index="15" data-design="built-in-preview" data-template="timeline">
231
275
  <div class="slide-canvas">
232
276
  <div class="template-frame">
233
277
  <header>
234
- <p class="template-eyebrow">Template 14 / 17</p>
278
+ <p class="template-eyebrow">Template 15 / 19</p>
235
279
  <h1 class="template-title">timeline</h1>
236
280
  </header><div class="template-body"><div class="template-timeline-layout template-timeline-layout--left"><div class="template-side-panel template-text-panel template-text-panel--color" data-template-slot="insight"><h2 class="template-side-panel-title template-text-panel-title">Reading the journey</h2><p class="template-side-panel-body template-text-panel-body">The timeline should show sequence and decision rhythm, while the side panel explains why the milestones matter.</p><blockquote class="template-text-panel-quote">Sequence is evidence when each step changes what the audience can believe.</blockquote></div><div class="template-timeline template-timeline--vertical" data-template-slot="timeline" style="--timeline-count:4"><article class="template-timeline-item">
237
281
  <span class="template-timeline-dot" aria-hidden="true"></span>
@@ -264,43 +308,60 @@
264
308
  </article></div></div></div>
265
309
 
266
310
  </div>
267
- <div class="template-page-number">14</div>
311
+ <div class="template-page-number">15</div>
268
312
  </div>
269
313
  </section>
270
- <section class="slide template-slide" slide-qa="true" data-slide-index="15" data-design="built-in-preview" data-template="process-steps">
314
+ <section class="slide template-slide" slide-qa="true" data-slide-index="16" data-design="built-in-preview" data-template="process-steps">
271
315
  <div class="slide-canvas">
272
316
  <div class="template-frame">
273
317
  <header>
274
- <p class="template-eyebrow">Template 15 / 17</p>
318
+ <p class="template-eyebrow">Template 16 / 19</p>
275
319
  <h1 class="template-title">process-steps</h1>
276
320
  </header><div class="template-body"><div class="template-steps" data-template-slot="steps"><article class="template-card"><div class="template-step-number">1</div><h2>Choose</h2><p>Select the page template that matches the communication job.</p><figure class="template-visual-placeholder"><div class="template-visual-placeholder-frame"><span class="template-visual-placeholder-label">image / chart slot (optional)</span></div></figure></article><article class="template-card"><div class="template-step-number">2</div><h2>Fill</h2><p>Provide only the content fields the template needs.</p><figure class="template-visual-placeholder"><div class="template-visual-placeholder-frame"><span class="template-visual-placeholder-label">image / chart slot (optional)</span></div></figure></article><article class="template-card"><div class="template-step-number">3</div><h2>Style</h2><p>Let the active design control type, color, and surfaces.</p><figure class="template-visual-placeholder"><div class="template-visual-placeholder-frame"><span class="template-visual-placeholder-label">image / chart slot (optional)</span></div></figure></article><article class="template-card"><div class="template-step-number">4</div><h2>QA</h2><p>Run contract and visual checks before export.</p><figure class="template-visual-placeholder"><div class="template-visual-placeholder-frame"><span class="template-visual-placeholder-label">image / chart slot (optional)</span></div></figure></article></div></div>
277
321
 
278
322
  </div>
279
- <div class="template-page-number">15</div>
323
+ <div class="template-page-number">16</div>
280
324
  </div>
281
325
  </section>
282
- <section class="slide template-slide" slide-qa="true" data-slide-index="16" data-design="built-in-preview" data-template="recommendation-decision">
326
+ <section class="slide template-slide" slide-qa="true" data-slide-index="17" data-design="built-in-preview" data-template="recommendation-decision">
283
327
  <div class="slide-canvas">
284
328
  <div class="template-frame">
285
329
  <header>
286
- <p class="template-eyebrow">Template 16 / 17</p>
330
+ <p class="template-eyebrow">Template 17 / 19</p>
287
331
  <h1 class="template-title">recommendation-decision</h1>
288
332
  </header><div class="template-body template-grid cols-3"><div class="template-card" data-template-slot="recommendation"><h2>Recommendation</h2><p>Adopt page templates as the structural layer, with designs remaining user-customizable.</p><figure class="template-image-card"><div class="template-image-frame"><img src="./assets/card-lens.jpg" alt="Lucent design asset"></div><figcaption class="template-image-caption">Design asset example</figcaption></figure></div><div data-template-slot="rationale"><article class="template-card"><h3>Rationale</h3><p>This keeps generation reliable while leaving style expressive and replaceable.</p></article></div><div class="template-card" data-template-slot="next-steps"><h2>Next steps</h2><ol class="template-list"><li><strong>Pilot</strong> Use the built-in preview to tune every template.</li><li><strong>Validate</strong> Promote only contracts that pass QA and browser review.</li><li><strong>Ship</strong> Document the add-slide workflow for agents.</li></ol></div></div>
289
333
 
290
334
  </div>
291
- <div class="template-page-number">16</div>
335
+ <div class="template-page-number">17</div>
292
336
  </div>
293
337
  </section>
294
- <section class="slide template-slide" slide-qa="true" data-slide-index="17" data-design="built-in-preview" data-template="risks-tradeoffs">
338
+ <section class="slide template-slide" slide-qa="true" data-slide-index="18" data-design="built-in-preview" data-template="risks-tradeoffs">
295
339
  <div class="slide-canvas">
296
340
  <div class="template-frame">
297
341
  <header>
298
- <p class="template-eyebrow">Template 17 / 17</p>
342
+ <p class="template-eyebrow">Template 18 / 19</p>
299
343
  <h1 class="template-title">risks-tradeoffs</h1>
300
344
  </header><div class="template-body template-grid cols-3" data-template-slot="risks"><article class="template-card"><h3>Constraint</h3><p>Templates can over-constrain if they become decorative presets instead of communication jobs.</p><figure class="template-image-card"><div class="template-image-frame"><img src="./assets/report-visual.jpg" alt="Report visual"></div><figcaption class="template-image-caption">Design asset example</figcaption></figure></article><article class="template-card"><h3>Mitigation</h3><p>Keep bounded HTML edit flow after scaffold insertion so agents can improve the page directly.</p></article><article class="template-card"><h3>Tradeoff</h3><p>More structure improves QA, but only if template contracts stay small and semantic.</p></article></div>
301
345
 
302
346
  </div>
303
- <div class="template-page-number">17</div>
347
+ <div class="template-page-number">18</div>
348
+ </div>
349
+ </section>
350
+ <section class="slide template-slide" slide-qa="true" data-slide-index="19" data-design="built-in-preview" data-template="free">
351
+ <div class="slide-canvas">
352
+ <div class="template-frame">
353
+ <header>
354
+ <p class="template-eyebrow">Template 19 / 19</p>
355
+ <h1 class="template-title">free</h1>
356
+ </header><div class="template-body"><div class="template-free-stage" data-template-slot="placeholder"><section class="template-free-placeholder">
357
+ <span class="template-free-placeholder-label">placeholder</span>
358
+ <h2>Flexible content placeholder</h2>
359
+ <p>Agent may replace this single region with multiple images, charts, text blocks, tables, or a mixed composition.</p>
360
+ <div class="template-free-placeholder-hints"><span class="template-free-placeholder-hint">images</span><span class="template-free-placeholder-hint">charts</span><span class="template-free-placeholder-hint">text</span><span class="template-free-placeholder-hint">tables</span></div>
361
+ </section></div></div>
362
+
363
+ </div>
364
+ <div class="template-page-number">19</div>
304
365
  </div>
305
366
  </section>
306
367
  <!-- revela-slides:end -->
@@ -7,7 +7,7 @@ export type PageTemplateStatus = "metadata-only" | "renderable"
7
7
 
8
8
  export interface PageTemplateField {
9
9
  name: string
10
- type: "string" | "string[]" | "items[]" | "metrics[]" | "milestones[]" | "rows[]" | "steps[]"
10
+ type: "string" | "string[]" | "items[]" | "metrics[]" | "milestones[]" | "rows[]" | "steps[]" | "members[]" | "placeholder"
11
11
  required?: boolean
12
12
  description: string
13
13
  }
@@ -112,6 +112,10 @@ const templates: PageTemplateDefinition[] = [
112
112
  field("title", "string", "Slide title.", true),
113
113
  field("items", "items[]", "Summary takeaways.", true),
114
114
  ], ["Use 3-4 takeaways.", "Each takeaway needs a short label and support line."], ["Contains summary cards."]),
115
+ define("team", "Team", "Introduce the people behind the work with portrait-led member cards.", [
116
+ field("title", "string", "Slide title.", true),
117
+ field("members", "members[]", "Team members with portrait, role, highlights, and education.", true),
118
+ ], ["Use 3-4 members for a readable 16:9 page.", "Each member should have one portrait, two concise highlights, and one highest education line."], ["Contains team member cards.", "Each card keeps portrait and credentials distinct."]),
115
119
  define("problem-context", "Problem / Context", "Frame why the topic matters now.", [
116
120
  field("title", "string", "Slide title.", true),
117
121
  field("body", "string", "Context paragraph.", true),
@@ -189,6 +193,10 @@ const templates: PageTemplateDefinition[] = [
189
193
  field("title", "string", "Slide title.", true),
190
194
  field("items", "items[]", "Risks or caveats.", true),
191
195
  ], ["Name uncertainty instead of hiding it."], ["Contains risk/tradeoff cards."]),
196
+ define("free", "Free / Plain", "Start from a title and one flexible placeholder that can later hold images, charts, text, or mixed content.", [
197
+ field("title", "string", "Slide title.", true),
198
+ field("placeholder", "placeholder", "One flexible placeholder region for agent-decided content composition.", true),
199
+ ], ["Use for pages that need a simple title and one replaceable working area.", "The placeholder may later contain multiple images, charts, text blocks, tables, or mixed content selected by the agent."], ["Contains one free placeholder stage.", "The single placeholder remains visible and replaceable."]),
192
200
  ]
193
201
 
194
202
  export function listPageTemplates(): { ok: true; templates: PageTemplateDefinition[] } {
@@ -241,6 +249,15 @@ export function builtInPreviewFixtures(): BuiltInPreviewFixture[] {
241
249
  { label: "Next step is narrow", description: "A pilot decision creates more learning without overcommitting capital or team capacity." },
242
250
  ],
243
251
  }),
252
+ fixture("team", {
253
+ title: "team",
254
+ members: [
255
+ { name: "Maya Chen", role: "Product and AI systems", image: "./assets/card-lens.jpg", imageAlt: "Portrait placeholder", highlights: ["Led the decision workspace launch from zero to enterprise pilot.", "Built source-linked review loops for regulated teams."], education: "M.S., Human-Computer Interaction" },
256
+ { name: "Jon Bell", role: "Go-to-market and partnerships", image: "./assets/report-visual.jpg", imageAlt: "Portrait placeholder", highlights: ["Scaled strategic accounts across finance and healthcare.", "Opened channel partnerships with implementation teams."], education: "MBA, Strategy and Operations" },
257
+ { name: "Ari Patel", role: "Data and platform engineering", image: "./assets/soft-texture.jpg", imageAlt: "Portrait placeholder", highlights: ["Architected reliable artifact generation and QA pipelines.", "Shipped analytics systems used by executive teams."], education: "B.S., Computer Science" },
258
+ { name: "Lina Gomez", role: "Research and narrative design", image: "./assets/toc-orb.png", imageAlt: "Portrait placeholder", highlights: ["Directed research synthesis for high-stakes board materials.", "Designed traceable evidence models for complex decisions."], education: "M.A., Communication Design" },
259
+ ],
260
+ }),
244
261
  fixture("problem-context", {
245
262
  title: "problem-context",
246
263
  body: "Use this template when the audience needs the situation, tension, and implication before seeing recommendations.",
@@ -371,6 +388,14 @@ export function builtInPreviewFixtures(): BuiltInPreviewFixture[] {
371
388
  { label: "Tradeoff", description: "More structure improves QA, but only if template contracts stay small and semantic." },
372
389
  ],
373
390
  }),
391
+ fixture("free", {
392
+ title: "free",
393
+ placeholder: {
394
+ label: "Flexible content placeholder",
395
+ description: "Agent may replace this single region with multiple images, charts, text blocks, tables, or a mixed composition.",
396
+ hints: ["images", "charts", "text", "tables"],
397
+ },
398
+ }),
374
399
  ]
375
400
  }
376
401
 
@@ -655,6 +680,25 @@ ${lucentClosingBackgroundCss}
655
680
  .template-timeline--vertical .template-timeline-item:nth-child(even) .template-timeline-copy { grid-column: 3; text-align: left; align-self: center; }
656
681
  .template-steps { display: grid; grid-template-columns: repeat(4, 1fr); gap: 22px; }
657
682
  .template-step-number { font-size: 48px; color: var(--accent-primary); font-weight: 800; margin-bottom: 30px; }
683
+ .template-team-grid { height: 100%; display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 24px; align-items: stretch; }
684
+ .template-team-card { min-width: 0; min-height: 0; display: grid; grid-template-rows: 330px minmax(0, 1fr); overflow: hidden; background: rgba(255,255,255,0.86); border: 1px solid var(--line); border-radius: var(--surface-radius); box-shadow: 0 18px 44px var(--shadow-soft); }
685
+ .template-team-photo { margin: 0; width: 100%; height: 100%; overflow: hidden; background: linear-gradient(135deg, var(--accent-soft), rgba(24,168,216,0.16)); display: grid; place-items: center; }
686
+ .template-team-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
687
+ .template-team-photo span { font-family: var(--font-display); font-size: 72px; line-height: 1; color: var(--accent-primary); font-weight: 800; }
688
+ .template-team-copy { min-height: 0; display: flex; flex-direction: column; gap: 12px; padding: 26px; }
689
+ .template-team-name { margin: 0; font-size: 30px; line-height: 1.18; color: var(--text-primary); padding-bottom: 3px; overflow: visible; }
690
+ .template-team-role { margin: 0; font-size: 15px; line-height: 1.35; letter-spacing: 0.1em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
691
+ .template-team-highlights { margin: 4px 0 0; padding: 0; list-style: none; display: grid; gap: 9px; }
692
+ .template-team-highlights li { position: relative; padding-left: 18px; font-size: 17px; line-height: 1.36; color: var(--text-secondary); }
693
+ .template-team-highlights li::before { content: ""; position: absolute; left: 0; top: 9px; width: 6px; height: 6px; background: var(--accent-primary); border-radius: 999px; }
694
+ .template-team-education { margin: auto 0 0; padding-top: 14px; border-top: 1px solid var(--line); font-size: 14px; line-height: 1.35; letter-spacing: 0.08em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; }
695
+ .template-free-stage { height: 100%; display: grid; grid-template-columns: minmax(0, 1fr); }
696
+ .template-free-placeholder { min-width: 0; min-height: 0; display: flex; flex-direction: column; justify-content: flex-end; gap: 16px; padding: 42px; border: 1px dashed var(--line-strong); border-radius: var(--surface-radius); background: linear-gradient(135deg, rgba(49,94,234,0.06), rgba(24,168,216,0.07)); overflow: hidden; }
697
+ .template-free-placeholder-label { align-self: flex-start; font-size: 13px; line-height: 1; letter-spacing: 0.14em; text-transform: uppercase; color: var(--accent-primary); font-weight: 800; }
698
+ .template-free-placeholder h2 { margin: 0; font-size: 38px; line-height: 1.18; color: var(--text-primary); padding-bottom: 4px; overflow: visible; }
699
+ .template-free-placeholder p { margin: 0; max-width: 980px; font-size: 23px; line-height: 1.42; color: var(--text-secondary); }
700
+ .template-free-placeholder-hints { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 6px; }
701
+ .template-free-placeholder-hint { display: inline-flex; align-items: center; min-height: 32px; padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px; font-size: 13px; line-height: 1; letter-spacing: 0.1em; text-transform: uppercase; color: var(--text-muted); font-weight: 800; background: rgba(255,255,255,0.58); }
658
702
  .template-image-card { width: 100%; margin: 18px 0 0; display: grid; gap: 8px; }
659
703
  .template-image-frame { width: 100%; height: 128px; border-radius: var(--surface-radius); overflow: hidden; background: var(--surface-tint, #f1f6fc); border: 1px solid var(--line); }
660
704
  .template-image-frame img { display: block; width: 100%; height: 100%; object-fit: cover; }
@@ -734,6 +778,20 @@ ${lucentClosingBackgroundCss}
734
778
  .template-frame--catalog .template-timeline-copy p:last-child { font-size: 15px; line-height: 1.24; }
735
779
  .template-frame--catalog .template-steps { gap: 16px; }
736
780
  .template-frame--catalog .template-step-number { font-size: 40px; margin-bottom: 20px; }
781
+ .template-frame--catalog .template-team-grid { gap: 16px; }
782
+ .template-frame--catalog .template-team-card { grid-template-rows: 230px minmax(0, 1fr); }
783
+ .template-frame--catalog .template-team-copy { padding: 18px; gap: 8px; }
784
+ .template-frame--catalog .template-team-name { font-size: 22px; line-height: 1.14; }
785
+ .template-frame--catalog .template-team-role { font-size: 11px; line-height: 1.25; }
786
+ .template-frame--catalog .template-team-highlights { gap: 6px; }
787
+ .template-frame--catalog .template-team-highlights li { font-size: 13px; line-height: 1.25; padding-left: 14px; }
788
+ .template-frame--catalog .template-team-highlights li::before { top: 7px; width: 5px; height: 5px; }
789
+ .template-frame--catalog .template-team-education { font-size: 10px; line-height: 1.25; padding-top: 9px; }
790
+ .template-frame--catalog .template-free-placeholder { padding: 28px; gap: 10px; }
791
+ .template-frame--catalog .template-free-placeholder-label { font-size: 10px; }
792
+ .template-frame--catalog .template-free-placeholder h2 { font-size: 28px; line-height: 1.16; }
793
+ .template-frame--catalog .template-free-placeholder p { font-size: 17px; line-height: 1.3; }
794
+ .template-frame--catalog .template-free-placeholder-hint { min-height: 26px; padding: 6px 9px; font-size: 10px; }
737
795
  .template-frame--catalog .template-image-frame { height: 86px; }
738
796
  .template-frame--catalog .template-image-caption { font-size: 11px; }
739
797
  .template-frame--catalog .template-visual-placeholder-frame { height: 110px; }
@@ -1008,6 +1066,7 @@ function renderBody(templateId: string, content: Record<string, any>): string {
1008
1066
  if (["cover", "section-divider", "closing"].includes(templateId)) return `<div data-template-slot="hero">${renderHeader(content, templateId, { hero: true })}</div>`
1009
1067
  if (templateId === "agenda") return renderAgenda(content)
1010
1068
  if (templateId === "executive-summary") return `${renderHeader(content, "Executive Summary")}<div class="template-body template-grid cols-3" data-template-slot="summary-cards">${cards(items(content), "h2", { visualPlaceholder: true })}</div>`
1069
+ if (templateId === "team") return `${renderHeader(content, "Team")}<div class="template-body"><div class="template-team-grid" data-template-slot="members">${teamCards(content.members)}</div></div>`
1011
1070
  if (templateId === "problem-context") return `${renderHeader(content, "Problem / Context")}<div class="template-body template-grid cols-2"><div class="template-card" data-template-slot="context"><p>${escapeHtml(stringValue(content.body))}</p></div><div class="template-card" data-template-slot="supporting-points">${list(items(content))}</div></div>`
1012
1071
  if (templateId === "key-message-evidence") return `${renderHeader(content, "Key Message + Evidence")}<div class="template-body template-grid cols-2">${keyMessagePanel(content)}<div class="template-evidence-grid" data-template-slot="evidence">${evidenceCards(items(content))}</div></div>`
1013
1072
  if (templateId === "claim-supporting-visual") return `${renderHeader(content, "Claim + Supporting Visual")}<div class="template-body template-grid cols-2">${claimTextPanel(content)}${visualSlotPanel()}</div>`
@@ -1021,6 +1080,7 @@ function renderBody(templateId: string, content: Record<string, any>): string {
1021
1080
  if (templateId === "process-steps") return `${renderHeader(content, "Process / Steps")}<div class="template-body"><div class="template-steps" data-template-slot="steps">${steps(content.steps)}</div></div>`
1022
1081
  if (templateId === "recommendation-decision") return `${renderHeader(content, "Recommendation / Decision")}<div class="template-body template-grid cols-3"><div class="template-card" data-template-slot="recommendation"><h2>Recommendation</h2><p>${escapeHtml(stringValue(content.recommendation))}</p>${imageCard(content)}</div><div data-template-slot="rationale">${cards(items(content).slice(0, 1), "h3")}</div><div class="template-card" data-template-slot="next-steps"><h2>Next steps</h2>${orderedSteps(content.steps)}</div></div>`
1023
1082
  if (templateId === "risks-tradeoffs") return `${renderHeader(content, "Risks / Tradeoffs")}<div class="template-body template-grid cols-3" data-template-slot="risks">${cards(items(content), "h3")}</div>`
1083
+ if (templateId === "free") return `${renderHeader(content, "Free / Plain")}<div class="template-body"><div class="template-free-stage" data-template-slot="placeholder">${freePlaceholder(content.placeholder ?? content.placeholders)}</div></div>`
1024
1084
  return renderHeader(content, templateId)
1025
1085
  }
1026
1086
 
@@ -1059,6 +1119,45 @@ function evidenceCards(items: Array<{ label: string; description: string; image?
1059
1119
  return items.map((item, index) => `<article class="template-card template-evidence-card"><h3>${escapeHtml(item.label || `Evidence ${index + 1}`)}</h3><p>${escapeHtml(item.description)}</p>${imageCard(item)}</article>`).join("")
1060
1120
  }
1061
1121
 
1122
+ function teamCards(input: any): string {
1123
+ const members = Array.isArray(input) ? input : []
1124
+ return members.slice(0, 6).map((member, index) => {
1125
+ const name = stringValue(member?.name) || `Member ${index + 1}`
1126
+ const role = stringValue(member?.role || member?.title)
1127
+ const image = safeImagePath(stringValue(member?.image))
1128
+ const alt = stringValue(member?.imageAlt) || name
1129
+ const highlights = stringArray(member?.highlights).slice(0, 3)
1130
+ const education = stringValue(member?.education || member?.highestEducation)
1131
+ return `<article class="template-team-card">
1132
+ <figure class="template-team-photo">${image ? `<img src="${escapeAttribute(image)}" alt="${escapeAttribute(alt)}">` : `<span>${escapeHtml(initials(name))}</span>`}</figure>
1133
+ <div class="template-team-copy">
1134
+ <h2 class="template-team-name">${escapeHtml(name)}</h2>
1135
+ ${role ? `<p class="template-team-role">${escapeHtml(role)}</p>` : ""}
1136
+ ${highlights.length > 0 ? `<ul class="template-team-highlights">${highlights.map((item) => `<li>${escapeHtml(item)}</li>`).join("")}</ul>` : ""}
1137
+ ${education ? `<p class="template-team-education">${escapeHtml(education)}</p>` : ""}
1138
+ </div>
1139
+ </article>`
1140
+ }).join("")
1141
+ }
1142
+
1143
+ function freePlaceholder(input: any): string {
1144
+ const legacy = Array.isArray(input) ? input : []
1145
+ const value = legacy.length > 0 ? {
1146
+ label: "Flexible content placeholder",
1147
+ description: "Agent may replace this single region with multiple images, charts, text blocks, tables, or a mixed composition.",
1148
+ hints: legacy.map((item) => stringValue(item?.type || item?.label)).filter(Boolean),
1149
+ } : input
1150
+ const label = stringValue(value?.label) || "Flexible content placeholder"
1151
+ const description = stringValue(value?.description) || "Agent may decide whether this placeholder becomes multiple images, charts, text blocks, tables, or a mixed composition."
1152
+ const hints = stringArray(value?.hints || value?.accepts).slice(0, 6)
1153
+ return `<section class="template-free-placeholder">
1154
+ <span class="template-free-placeholder-label">placeholder</span>
1155
+ <h2>${escapeHtml(label)}</h2>
1156
+ <p>${escapeHtml(description)}</p>
1157
+ ${hints.length > 0 ? `<div class="template-free-placeholder-hints">${hints.map((hint) => `<span class="template-free-placeholder-hint">${escapeHtml(hint)}</span>`).join("")}</div>` : ""}
1158
+ </section>`
1159
+ }
1160
+
1062
1161
  function chartTakeawayPanel(content: Record<string, any>): string {
1063
1162
  const takeawayItems = items(content)
1064
1163
  const title = stringValue(content.takeawaysTitle) || "What to read"
@@ -1230,6 +1329,12 @@ function items(content: Record<string, any>): Array<{ label: string; description
1230
1329
  }))
1231
1330
  }
1232
1331
 
1332
+ function stringArray(value: any): string[] {
1333
+ if (Array.isArray(value)) return value.map(stringValue).filter(Boolean)
1334
+ const single = stringValue(value)
1335
+ return single ? [single] : []
1336
+ }
1337
+
1233
1338
  function scaffoldSeed(templateId: string, seed: Record<string, any>): Record<string, any> {
1234
1339
  const title = stringValue(seed.title) || getPageTemplate(templateId).title
1235
1340
  const base = { ...seed, title }
@@ -1238,6 +1343,7 @@ function scaffoldSeed(templateId: string, seed: Record<string, any>): Record<str
1238
1343
  if (templateId === "closing") return { ...base }
1239
1344
  if (templateId === "agenda") return { items: defaultItems(["Situation", "Evidence", "Decision"]), ...base }
1240
1345
  if (templateId === "executive-summary") return { items: defaultItems(["Decision is ready", "Risk is bounded", "Next step is narrow"]), ...base }
1346
+ if (templateId === "team") return { members: [{ name: "Member One", role: "Role or function", highlights: ["Replace with a standout project.", "Replace with a standout experience."], education: "Highest education" }, { name: "Member Two", role: "Role or function", highlights: ["Replace with a standout project.", "Replace with a standout experience."], education: "Highest education" }, { name: "Member Three", role: "Role or function", highlights: ["Replace with a standout project.", "Replace with a standout experience."], education: "Highest education" }], ...base }
1241
1347
  if (templateId === "problem-context") return { body: "Replace with context, tension, and why now.", items: defaultItems(["Context", "Implication"]), ...base }
1242
1348
  if (templateId === "key-message-evidence") return { body: "Replace with the key message the audience should remember.", items: defaultItems(["Evidence 1", "Evidence 2", "Evidence 3"]), ...base }
1243
1349
  if (templateId === "claim-supporting-visual") return { claim: "Replace with one visual claim.", body: "Use this copy to guide how the visual should be read.", items: defaultItems(["Anchor", "Callout"]), ...base }
@@ -1250,6 +1356,7 @@ function scaffoldSeed(templateId: string, seed: Record<string, any>): Record<str
1250
1356
  if (templateId === "process-steps") return { steps: defaultItems(["Step 1", "Step 2", "Step 3"]), ...base }
1251
1357
  if (templateId === "recommendation-decision") return { recommendation: "Replace with the recommended decision.", items: defaultItems(["Rationale"]), steps: defaultItems(["Pilot", "Validate", "Ship"]), ...base }
1252
1358
  if (templateId === "risks-tradeoffs") return { items: defaultItems(["Risk", "Tradeoff", "Mitigation"]), ...base }
1359
+ if (templateId === "free") return { placeholder: { label: "Flexible content placeholder", description: "Replace this single region with one or more images, charts, text blocks, tables, or mixed content.", hints: ["images", "charts", "text", "tables"] }, ...base }
1253
1360
  return base
1254
1361
  }
1255
1362
 
@@ -1298,6 +1405,11 @@ function safeImagePath(value: string): string {
1298
1405
  return image
1299
1406
  }
1300
1407
 
1408
+ function initials(value: string): string {
1409
+ const parts = value.split(/\s+/).filter(Boolean)
1410
+ return parts.slice(0, 2).map((part) => part.charAt(0).toUpperCase()).join("") || "?"
1411
+ }
1412
+
1301
1413
  function escapeHtml(value: string): string {
1302
1414
  return value
1303
1415
  .replace(/&/g, "&amp;")
@@ -0,0 +1,3 @@
1
+ import { templateModule } from "./shared"
2
+
3
+ export const freeTemplate = templateModule("free")
@@ -8,6 +8,7 @@ export * from "./claim-supporting-visual"
8
8
  export * from "./closing"
9
9
  export * from "./cover"
10
10
  export * from "./executive-summary"
11
+ export * from "./free"
11
12
  export * from "./key-message-evidence"
12
13
  export * from "./metric-highlight"
13
14
  export * from "./milestone"
@@ -18,5 +19,6 @@ export * from "./risks-tradeoffs"
18
19
  export * from "./section-divider"
19
20
  export * from "./table"
20
21
  export * from "./table-comparison"
22
+ export * from "./team"
21
23
  export * from "./timeline"
22
24
  export * from "./timeline-roadmap"
@@ -0,0 +1,3 @@
1
+ import { templateModule } from "./shared"
2
+
3
+ export const teamTemplate = templateModule("team")
@@ -51,6 +51,7 @@ export const PAGE_TEMPLATE_VOCABULARY: PageTemplateVocabulary[] = [
51
51
  vocab("closing", ["template-hero"], ["hero"], ["hero"], ["Closing uses the same hero-safe structure as cover."]),
52
52
  vocab("agenda", ["template-agenda-panel"], ["agenda", "agenda-list"], ["agenda", "agenda-list"], ["Agenda numbers must remain in DOM order."]),
53
53
  vocab("executive-summary", ["template-card"], ["summary-cards"], ["summary-cards"], ["Cards are editable; visual placeholders are optional and may become image/chart slots."]),
54
+ vocab("team", ["template-team-grid", "template-team-card", "template-team-photo", "template-team-highlights", "template-team-education"], ["members"], ["members"], ["Team cards keep portrait, name/role, highlights, and education as distinct regions.", "Use 3-4 members for a readable 16:9 page; 5-6 members require shorter copy."]),
54
55
  vocab("problem-context", ["template-card"], ["context", "supporting-points"], ["context", "supporting-points"], ["Context should stay separate from supporting bullets."]),
55
56
  vocab("key-message-evidence", ["template-key-message-panel", "template-evidence-grid"], ["key-message", "evidence"], ["key-message", "evidence"], ["Key message and evidence regions must remain distinct."]),
56
57
  vocab("claim-supporting-visual", ["template-claim-text-panel", "template-visual-slot-panel"], ["claim", "visual"], ["claim", "visual"], ["Visual slot may be replaced by image, chart, table, or diagram container."]),
@@ -63,6 +64,7 @@ export const PAGE_TEMPLATE_VOCABULARY: PageTemplateVocabulary[] = [
63
64
  vocab("process-steps", ["template-steps", "template-step-number"], ["steps"], ["steps"], ["Steps should remain ordered in DOM order."]),
64
65
  vocab("recommendation-decision", ["template-card"], ["recommendation", "rationale", "next-steps"], ["recommendation", "rationale", "next-steps"], ["Keep recommendation, rationale, and next steps separate."]),
65
66
  vocab("risks-tradeoffs", ["template-card"], ["risks"], ["risks"], ["Risk/tradeoff cards should name uncertainty explicitly."]),
67
+ vocab("free", ["template-free-stage", "template-free-placeholder"], ["placeholder"], ["placeholder"], ["Free pages keep a title plus one semantic placeholder region for agent-decided image, chart, text, table, or mixed content.", "Do not split the placeholder into multiple top-level slots when bounded-editing the page."]),
66
68
  ]
67
69
 
68
70
  const additionalClasses = [
@@ -128,6 +130,19 @@ const additionalClasses = [
128
130
  "template-timeline-date",
129
131
  "template-steps",
130
132
  "template-step-number",
133
+ "template-team-grid",
134
+ "template-team-card",
135
+ "template-team-photo",
136
+ "template-team-copy",
137
+ "template-team-name",
138
+ "template-team-role",
139
+ "template-team-highlights",
140
+ "template-team-education",
141
+ "template-free-stage",
142
+ "template-free-placeholder",
143
+ "template-free-placeholder-label",
144
+ "template-free-placeholder-hints",
145
+ "template-free-placeholder-hint",
131
146
  "template-catalog-panel",
132
147
  "template-catalog-kicker",
133
148
  "template-catalog-title",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cyber-dash-tech/revela",
3
- "version": "0.19.9",
3
+ "version": "0.20.0",
4
4
  "description": "Codex-first CLI/MCP workspace for trusted narrative artifacts from local sources, research, and evidence",
5
5
  "type": "module",
6
6
  "main": "./index.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "revela",
3
- "version": "0.19.9",
3
+ "version": "0.20.0",
4
4
  "description": "Use Revela in Codex to specify, research, plan, make, review, and export trusted narrative decision artifacts.",
5
5
  "author": {
6
6
  "name": "cyber-dash-tech",