portable-agent-layer 0.30.1 → 0.31.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.
Files changed (52) hide show
  1. package/assets/skills/consulting-report/SKILL.md +68 -74
  2. package/assets/skills/consulting-report/demo/app/globals.css +344 -0
  3. package/assets/skills/consulting-report/demo/app/layout.tsx +32 -0
  4. package/assets/skills/consulting-report/demo/app/page.tsx +255 -0
  5. package/assets/skills/consulting-report/demo/bun.lock +240 -0
  6. package/assets/skills/consulting-report/demo/components/callout.tsx +13 -0
  7. package/assets/skills/consulting-report/demo/components/cover-page.tsx +34 -0
  8. package/assets/skills/consulting-report/demo/components/exhibit.tsx +21 -0
  9. package/assets/skills/consulting-report/demo/components/finding-card.tsx +28 -0
  10. package/assets/skills/consulting-report/demo/components/quote-block.tsx +17 -0
  11. package/assets/skills/consulting-report/demo/components/recommendation-card.tsx +52 -0
  12. package/assets/skills/consulting-report/demo/components/section.tsx +16 -0
  13. package/assets/skills/consulting-report/demo/components/severity-badge.tsx +19 -0
  14. package/assets/skills/consulting-report/demo/components/timeline.tsx +20 -0
  15. package/assets/skills/consulting-report/demo/lib/report-data.ts +247 -0
  16. package/assets/skills/consulting-report/demo/lib/utils.ts +6 -0
  17. package/assets/skills/consulting-report/demo/next.config.js +9 -0
  18. package/assets/skills/consulting-report/demo/package.json +27 -0
  19. package/assets/skills/consulting-report/demo/postcss.config.mjs +5 -0
  20. package/assets/skills/consulting-report/demo/tsconfig.json +41 -0
  21. package/assets/skills/consulting-report/template/app/globals.css +344 -0
  22. package/assets/skills/consulting-report/template/app/layout.tsx +32 -0
  23. package/assets/skills/consulting-report/template/app/page.tsx +255 -0
  24. package/assets/skills/consulting-report/template/bun.lock +240 -0
  25. package/assets/skills/consulting-report/template/components/callout.tsx +13 -0
  26. package/assets/skills/consulting-report/template/components/cover-page.tsx +34 -0
  27. package/assets/skills/consulting-report/template/components/exhibit.tsx +21 -0
  28. package/assets/skills/consulting-report/template/components/finding-card.tsx +28 -0
  29. package/assets/skills/consulting-report/template/components/quote-block.tsx +17 -0
  30. package/assets/skills/consulting-report/template/components/recommendation-card.tsx +52 -0
  31. package/assets/skills/consulting-report/template/components/section.tsx +16 -0
  32. package/assets/skills/consulting-report/template/components/severity-badge.tsx +19 -0
  33. package/assets/skills/consulting-report/template/components/timeline.tsx +20 -0
  34. package/assets/skills/consulting-report/template/lib/report-data.ts +176 -0
  35. package/assets/skills/consulting-report/template/lib/utils.ts +6 -0
  36. package/assets/skills/consulting-report/template/next.config.js +9 -0
  37. package/assets/skills/consulting-report/template/package.json +27 -0
  38. package/assets/skills/consulting-report/template/postcss.config.mjs +5 -0
  39. package/assets/skills/consulting-report/template/tsconfig.json +27 -0
  40. package/assets/skills/consulting-report/tools/dev.ts +47 -0
  41. package/assets/skills/consulting-report/tools/generate-pdf.ts +140 -408
  42. package/assets/skills/consulting-report/tools/scaffold.ts +83 -48
  43. package/assets/skills/presentation/SKILL.md +1 -1
  44. package/package.json +9 -9
  45. package/assets/skills/consulting-report/demo/content/current-state.md +0 -33
  46. package/assets/skills/consulting-report/demo/content/executive-summary.md +0 -19
  47. package/assets/skills/consulting-report/demo/content/report-data.ts +0 -101
  48. package/assets/skills/consulting-report/demo/diagrams/.gitkeep +0 -0
  49. package/assets/skills/consulting-report/template/README.md +0 -28
  50. package/assets/skills/consulting-report/template/content/executive-summary.md +0 -19
  51. package/assets/skills/consulting-report/template/content/report-data.ts +0 -59
  52. package/assets/skills/consulting-report/template/diagrams/.gitkeep +0 -0
@@ -0,0 +1,344 @@
1
+ @import "tailwindcss";
2
+
3
+ @theme {
4
+ --color-background: #ffffff;
5
+ --color-background-secondary: #f8fafc;
6
+ --color-background-tertiary: #f1f5f9;
7
+ --color-background-elevated: #e2e8f0;
8
+
9
+ --color-foreground: #0f172a;
10
+ --color-muted: #475569;
11
+ --color-muted-dark: #94a3b8;
12
+
13
+ --color-border: #e2e8f0;
14
+ --color-border-subtle: #f1f5f9;
15
+ --color-border-emphasis: #cbd5e1;
16
+
17
+ --color-primary: #1d4ed8;
18
+ --color-accent: #7c3aed;
19
+ --color-success: #16a34a;
20
+ --color-warning: #d97706;
21
+ --color-destructive: #dc2626;
22
+
23
+ --color-section: #f8fafc;
24
+ --color-callout: #eff6ff;
25
+
26
+ --font-sans: var(--font-inter), system-ui, sans-serif;
27
+ --font-serif: var(--font-source-serif), Georgia, serif;
28
+ --font-heading: var(--font-inter), system-ui, sans-serif;
29
+ --font-body: var(--font-source-serif), Georgia, serif;
30
+ }
31
+
32
+ @source "./**/*.{ts,tsx}";
33
+ @source "../components/**/*.{ts,tsx}";
34
+
35
+ body {
36
+ font-family: var(--font-body);
37
+ background: var(--color-background);
38
+ color: var(--color-foreground);
39
+ line-height: 1.7;
40
+ -webkit-font-smoothing: antialiased;
41
+ -moz-osx-font-smoothing: grayscale;
42
+ }
43
+
44
+ /* McKinsey-style report layout */
45
+ .report-container {
46
+ max-width: 850px;
47
+ margin: 0 auto;
48
+ padding: 2rem;
49
+ }
50
+
51
+ .report-section {
52
+ margin-bottom: 3rem;
53
+ page-break-inside: avoid;
54
+ }
55
+
56
+ .report-section h2 {
57
+ font-family: var(--font-heading);
58
+ font-size: 1.75rem;
59
+ font-weight: 600;
60
+ color: var(--color-foreground);
61
+ margin-bottom: 1.5rem;
62
+ padding-bottom: 0.5rem;
63
+ border-bottom: 2px solid var(--color-primary);
64
+ }
65
+
66
+ .report-section h3 {
67
+ font-family: var(--font-heading);
68
+ font-size: 1.25rem;
69
+ font-weight: 600;
70
+ color: var(--color-foreground);
71
+ margin-bottom: 1rem;
72
+ }
73
+
74
+ /* Exhibit */
75
+ .exhibit {
76
+ background: var(--color-background-secondary);
77
+ border: 1px solid var(--color-border);
78
+ border-radius: 0.5rem;
79
+ padding: 1.5rem;
80
+ margin: 1.5rem 0;
81
+ }
82
+ .exhibit-header {
83
+ display: flex;
84
+ justify-content: space-between;
85
+ align-items: baseline;
86
+ margin-bottom: 1rem;
87
+ padding-bottom: 0.5rem;
88
+ border-bottom: 1px solid var(--color-border-subtle);
89
+ }
90
+ .exhibit-number {
91
+ font-family: var(--font-sans);
92
+ font-weight: 600;
93
+ color: var(--color-primary);
94
+ font-size: 0.875rem;
95
+ text-transform: uppercase;
96
+ letter-spacing: 0.1em;
97
+ }
98
+ .exhibit-title {
99
+ font-family: var(--font-heading);
100
+ font-weight: 600;
101
+ color: var(--color-foreground);
102
+ }
103
+
104
+ /* Callout */
105
+ .callout {
106
+ background: var(--color-callout);
107
+ border-left: 4px solid var(--color-primary);
108
+ padding: 1.25rem 1.5rem;
109
+ margin: 1.5rem 0;
110
+ border-radius: 0 0.5rem 0.5rem 0;
111
+ }
112
+ .callout-label {
113
+ font-family: var(--font-sans);
114
+ font-weight: 600;
115
+ color: var(--color-primary);
116
+ font-size: 0.75rem;
117
+ text-transform: uppercase;
118
+ letter-spacing: 0.1em;
119
+ margin-bottom: 0.5rem;
120
+ }
121
+ .callout-content {
122
+ font-size: 1.125rem;
123
+ font-weight: 500;
124
+ color: var(--color-foreground);
125
+ }
126
+
127
+ /* Quote block */
128
+ .quote-block {
129
+ position: relative;
130
+ padding: 1.5rem 2rem;
131
+ margin: 1.5rem 0;
132
+ background: var(--color-background-secondary);
133
+ border-radius: 0.5rem;
134
+ border: 1px solid var(--color-border-subtle);
135
+ }
136
+ .quote-block::before {
137
+ content: "\201C";
138
+ position: absolute;
139
+ top: 0.5rem;
140
+ left: 0.75rem;
141
+ font-size: 3rem;
142
+ color: var(--color-primary);
143
+ opacity: 0.5;
144
+ font-family: Georgia, serif;
145
+ line-height: 1;
146
+ }
147
+ .quote-text {
148
+ font-style: italic;
149
+ color: var(--color-foreground);
150
+ font-size: 1.0625rem;
151
+ line-height: 1.7;
152
+ }
153
+ .quote-attribution {
154
+ margin-top: 0.75rem;
155
+ font-size: 0.875rem;
156
+ color: var(--color-muted);
157
+ }
158
+
159
+ /* Severity badges */
160
+ .severity-badge {
161
+ display: inline-flex;
162
+ align-items: center;
163
+ padding: 0.25rem 0.75rem;
164
+ border-radius: 9999px;
165
+ font-family: var(--font-sans);
166
+ font-size: 0.75rem;
167
+ font-weight: 600;
168
+ text-transform: uppercase;
169
+ letter-spacing: 0.05em;
170
+ }
171
+ .severity-critical {
172
+ background: rgba(220, 38, 38, 0.1);
173
+ color: var(--color-destructive);
174
+ border: 1px solid rgba(220, 38, 38, 0.3);
175
+ }
176
+ .severity-high {
177
+ background: rgba(234, 88, 12, 0.1);
178
+ color: #ea580c;
179
+ border: 1px solid rgba(234, 88, 12, 0.3);
180
+ }
181
+ .severity-medium {
182
+ background: rgba(217, 119, 6, 0.1);
183
+ color: var(--color-warning);
184
+ border: 1px solid rgba(217, 119, 6, 0.3);
185
+ }
186
+ .severity-low {
187
+ background: rgba(22, 163, 74, 0.1);
188
+ color: var(--color-success);
189
+ border: 1px solid rgba(22, 163, 74, 0.3);
190
+ }
191
+
192
+ /* Finding card */
193
+ .finding-card {
194
+ background: var(--color-background-secondary);
195
+ border: 1px solid var(--color-border);
196
+ border-radius: 0.5rem;
197
+ padding: 1.5rem;
198
+ margin-bottom: 1rem;
199
+ }
200
+ .finding-header {
201
+ display: flex;
202
+ justify-content: space-between;
203
+ align-items: flex-start;
204
+ margin-bottom: 0.75rem;
205
+ }
206
+ .finding-title {
207
+ font-family: var(--font-heading);
208
+ font-weight: 600;
209
+ color: var(--color-foreground);
210
+ font-size: 1.0625rem;
211
+ }
212
+ .finding-evidence {
213
+ font-size: 0.9375rem;
214
+ color: var(--color-muted);
215
+ margin-top: 0.5rem;
216
+ }
217
+
218
+ /* Timeline */
219
+ .timeline {
220
+ position: relative;
221
+ padding-left: 2rem;
222
+ }
223
+ .timeline::before {
224
+ content: "";
225
+ position: absolute;
226
+ left: 0.5rem;
227
+ top: 0;
228
+ bottom: 0;
229
+ width: 2px;
230
+ background: linear-gradient(180deg, var(--color-primary) 0%, var(--color-accent) 100%);
231
+ }
232
+ .timeline-item {
233
+ position: relative;
234
+ padding-bottom: 1.5rem;
235
+ }
236
+ .timeline-item::before {
237
+ content: "";
238
+ position: absolute;
239
+ /* Center dot on the vertical line: line is at left:0.5rem (8px) +1px,
240
+ timeline-item starts at padding 2rem (32px). Dot half-width 6px → place
241
+ left at -1.8125rem so dot center lands at 9px from .timeline left. */
242
+ left: -1.8125rem;
243
+ top: 0.4rem;
244
+ width: 0.75rem;
245
+ height: 0.75rem;
246
+ border-radius: 50%;
247
+ background: var(--color-primary);
248
+ }
249
+ .timeline-phase {
250
+ font-family: var(--font-sans);
251
+ font-weight: 600;
252
+ color: var(--color-primary);
253
+ font-size: 0.875rem;
254
+ text-transform: uppercase;
255
+ letter-spacing: 0.1em;
256
+ }
257
+ .timeline-title {
258
+ font-family: var(--font-heading);
259
+ font-weight: 600;
260
+ color: var(--color-foreground);
261
+ margin-top: 0.25rem;
262
+ }
263
+ .timeline-description {
264
+ color: var(--color-muted);
265
+ font-size: 0.9375rem;
266
+ margin-top: 0.25rem;
267
+ }
268
+
269
+ /* Cover page */
270
+ .cover-page {
271
+ min-height: 100vh;
272
+ display: flex;
273
+ flex-direction: column;
274
+ justify-content: center;
275
+ padding: 4rem;
276
+ page-break-after: always;
277
+ background: linear-gradient(180deg, var(--color-background) 0%, var(--color-background-secondary) 100%);
278
+ }
279
+ .cover-classification {
280
+ font-family: var(--font-sans);
281
+ font-size: 0.875rem;
282
+ font-weight: 600;
283
+ color: var(--color-destructive);
284
+ text-transform: uppercase;
285
+ letter-spacing: 0.15em;
286
+ margin-bottom: 4rem;
287
+ }
288
+ .cover-title {
289
+ font-family: var(--font-heading);
290
+ font-size: 3rem;
291
+ font-weight: 600;
292
+ color: var(--color-foreground);
293
+ line-height: 1.2;
294
+ margin-bottom: 1rem;
295
+ letter-spacing: -0.02em;
296
+ }
297
+ .cover-subtitle {
298
+ font-family: var(--font-heading);
299
+ font-size: 1.5rem;
300
+ color: var(--color-muted);
301
+ margin-bottom: 4rem;
302
+ font-weight: 400;
303
+ }
304
+ .cover-meta {
305
+ margin-top: auto;
306
+ padding-top: 1.5rem;
307
+ border-top: 1px solid var(--color-border);
308
+ }
309
+ .cover-date {
310
+ font-family: var(--font-sans);
311
+ font-size: 1rem;
312
+ color: var(--color-muted);
313
+ }
314
+
315
+ /* Print styles — what Playwright sees */
316
+ @media print {
317
+ body {
318
+ font-size: 11pt;
319
+ }
320
+ .report-container {
321
+ max-width: none;
322
+ padding: 0;
323
+ }
324
+ .report-section,
325
+ .callout,
326
+ .exhibit,
327
+ .finding-card,
328
+ .quote-block {
329
+ break-inside: avoid;
330
+ }
331
+ .cover-page {
332
+ page-break-after: always;
333
+ }
334
+ a {
335
+ text-decoration: none;
336
+ color: var(--color-foreground);
337
+ }
338
+ }
339
+
340
+ /* Page setup for PDF */
341
+ @page {
342
+ size: A4;
343
+ margin: 18mm 16mm;
344
+ }
@@ -0,0 +1,32 @@
1
+ import type { Metadata } from "next";
2
+ import { Inter, Source_Serif_4 } from "next/font/google";
3
+ import "./globals.css";
4
+
5
+ const inter = Inter({
6
+ subsets: ["latin"],
7
+ variable: "--font-inter",
8
+ display: "swap",
9
+ });
10
+
11
+ const sourceSerif = Source_Serif_4({
12
+ subsets: ["latin"],
13
+ variable: "--font-source-serif",
14
+ display: "swap",
15
+ });
16
+
17
+ export const metadata: Metadata = {
18
+ title: "Consulting Report",
19
+ description: "Strategic assessment and recommendations.",
20
+ };
21
+
22
+ export default function RootLayout({
23
+ children,
24
+ }: Readonly<{ children: React.ReactNode }>) {
25
+ return (
26
+ <html lang="en" className={`${inter.variable} ${sourceSerif.variable}`}>
27
+ <body className="bg-background font-body text-foreground antialiased">
28
+ {children}
29
+ </body>
30
+ </html>
31
+ );
32
+ }
@@ -0,0 +1,255 @@
1
+ import { AlertTriangle, CheckCircle2, Lightbulb, Target } from "lucide-react";
2
+ import { Callout } from "@/components/callout";
3
+ import { CoverPage } from "@/components/cover-page";
4
+ import { Exhibit } from "@/components/exhibit";
5
+ import { FindingCard } from "@/components/finding-card";
6
+ import { RecommendationCard } from "@/components/recommendation-card";
7
+ import { Section } from "@/components/section";
8
+ import { Timeline } from "@/components/timeline";
9
+ import { reportData } from "@/lib/report-data";
10
+
11
+ export default function ReportPage() {
12
+ const data = reportData;
13
+
14
+ return (
15
+ <div>
16
+ <CoverPage
17
+ clientName={data.clientName}
18
+ reportTitle={data.reportTitle}
19
+ reportDate={data.reportDate}
20
+ classification={data.classification}
21
+ consultancyName={data.consultancyName}
22
+ preTitle={data.preTitle}
23
+ />
24
+
25
+ <div className="report-container">
26
+ <Section title="Executive Summary">
27
+ <p className="text-lg mb-6">{data.executiveSummary.context}</p>
28
+
29
+ <Exhibit number={1} title="Assessment Methodology">
30
+ <div className="flex items-start gap-8">
31
+ <div>
32
+ <p className="text-3xl font-bold text-primary">
33
+ {data.executiveSummary.methodology.interviewCount}
34
+ </p>
35
+ <p className="text-sm text-muted">Interviews Conducted</p>
36
+ </div>
37
+ <div className="flex-1">
38
+ <p className="text-sm font-semibold text-foreground mb-2">
39
+ Roles Interviewed:
40
+ </p>
41
+ <div className="grid grid-cols-2 gap-1">
42
+ {data.executiveSummary.methodology.roles.map((role) => (
43
+ <p key={role} className="text-sm text-muted">
44
+ {role}
45
+ </p>
46
+ ))}
47
+ </div>
48
+ </div>
49
+ </div>
50
+ </Exhibit>
51
+
52
+ <Exhibit number={2} title="Key Findings Summary">
53
+ <ul className="space-y-2">
54
+ {data.executiveSummary.keyFindings.map((finding, i) => (
55
+ <li key={finding} className="flex items-start gap-3">
56
+ <span className="text-primary font-bold font-sans">{i + 1}.</span>
57
+ <span>{finding}</span>
58
+ </li>
59
+ ))}
60
+ </ul>
61
+ </Exhibit>
62
+
63
+ <Callout label="Primary Recommendation">
64
+ {data.executiveSummary.primaryRecommendation}
65
+ </Callout>
66
+
67
+ <h3 className="text-lg font-semibold mt-6 mb-3">Expected Outcomes</h3>
68
+ <ul className="space-y-2">
69
+ {data.executiveSummary.expectedOutcomes.map((outcome) => (
70
+ <li key={outcome} className="flex items-center gap-3">
71
+ <CheckCircle2 className="h-5 w-5 text-success shrink-0" />
72
+ <span>{outcome}</span>
73
+ </li>
74
+ ))}
75
+ </ul>
76
+ </Section>
77
+
78
+ <Section title="Situation Assessment">
79
+ <div className="grid gap-6">
80
+ <div>
81
+ <h3 className="text-lg font-semibold mb-2 flex items-center gap-2">
82
+ <Target className="h-5 w-5 text-primary" />
83
+ What You Asked For
84
+ </h3>
85
+ <p>{data.situationAssessment.clientAsk}</p>
86
+ </div>
87
+ <div>
88
+ <h3 className="text-lg font-semibold mb-2">Current State</h3>
89
+ <p>{data.situationAssessment.currentState}</p>
90
+ </div>
91
+ <div>
92
+ <h3 className="text-lg font-semibold mb-2">Why This Matters Now</h3>
93
+ <p>{data.situationAssessment.whyNow}</p>
94
+ </div>
95
+ </div>
96
+ </Section>
97
+
98
+ <Section title="Key Findings">
99
+ <p className="text-muted mb-6">
100
+ Our analysis identified {data.findings.length} significant findings that
101
+ require attention. Each finding is supported by evidence gathered during our
102
+ assessment.
103
+ </p>
104
+ <div className="space-y-4">
105
+ {data.findings.map((finding, index) => (
106
+ <FindingCard key={finding.id} finding={finding} index={index} />
107
+ ))}
108
+ </div>
109
+ </Section>
110
+
111
+ <Section title="Risk Analysis">
112
+ <div className="grid gap-6">
113
+ <Exhibit number={3} title="Existential Risks">
114
+ <div className="space-y-3">
115
+ {data.riskAnalysis.existentialRisks.map((risk) => (
116
+ <div
117
+ key={risk}
118
+ className="flex items-start gap-3 p-3 bg-destructive/5 rounded-lg border border-destructive/20"
119
+ >
120
+ <AlertTriangle className="h-5 w-5 text-destructive shrink-0 mt-0.5" />
121
+ <span>{risk}</span>
122
+ </div>
123
+ ))}
124
+ </div>
125
+ </Exhibit>
126
+
127
+ <Exhibit number={4} title="Competitive Threats">
128
+ <ul className="space-y-2">
129
+ {data.riskAnalysis.competitiveThreats.map((threat, i) => (
130
+ <li key={threat} className="flex items-start gap-3">
131
+ <span className="text-warning font-bold font-sans">{i + 1}.</span>
132
+ <span>{threat}</span>
133
+ </li>
134
+ ))}
135
+ </ul>
136
+ </Exhibit>
137
+
138
+ <div>
139
+ <h3 className="text-lg font-semibold mb-2">Timeline Pressures</h3>
140
+ <p>{data.riskAnalysis.timelinePressures}</p>
141
+ </div>
142
+ </div>
143
+ </Section>
144
+
145
+ <Section title="Strategic Opportunity">
146
+ <Callout label="The Path Forward">{data.strategicOpportunity.goodNews}</Callout>
147
+
148
+ <h3 className="text-lg font-semibold mt-6 mb-3 flex items-center gap-2">
149
+ <Lightbulb className="h-5 w-5 text-accent" />
150
+ What This Requires
151
+ </h3>
152
+ <ul className="space-y-3">
153
+ {data.strategicOpportunity.requirements.map((req, i) => (
154
+ <li
155
+ key={req}
156
+ className="flex items-start gap-3 p-3 bg-accent/5 rounded-lg border border-accent/20"
157
+ >
158
+ <span className="text-accent font-bold font-sans">{i + 1}.</span>
159
+ <span>{req}</span>
160
+ </li>
161
+ ))}
162
+ </ul>
163
+ </Section>
164
+
165
+ <Section title="Strategic Recommendations">
166
+ <p className="text-muted mb-6">
167
+ Recommendations are prioritized by urgency and impact.
168
+ </p>
169
+ <div className="space-y-4">
170
+ {data.recommendations.map((rec, index) => (
171
+ <RecommendationCard key={rec.id} recommendation={rec} index={index} />
172
+ ))}
173
+ </div>
174
+ </Section>
175
+
176
+ <Section title="Target State Vision">
177
+ <p className="text-lg mb-6">{data.targetState.description}</p>
178
+
179
+ <Exhibit number={5} title="Key Capabilities Enabled">
180
+ <div className="grid md:grid-cols-3 gap-4">
181
+ {data.targetState.keyCapabilities.map((capability) => (
182
+ <div
183
+ key={capability}
184
+ className="p-4 bg-success/5 rounded-lg border border-success/20 text-center"
185
+ >
186
+ <CheckCircle2 className="h-8 w-8 text-success mx-auto mb-2" />
187
+ <span className="font-medium">{capability}</span>
188
+ </div>
189
+ ))}
190
+ </div>
191
+ </Exhibit>
192
+
193
+ <h3 className="text-lg font-semibold mt-6 mb-3">Success Metrics</h3>
194
+ <ul className="space-y-2">
195
+ {data.targetState.successMetrics.map((metric) => (
196
+ <li key={metric} className="flex items-center gap-3">
197
+ <span className="w-2 h-2 bg-primary rounded-full" />
198
+ <span>{metric}</span>
199
+ </li>
200
+ ))}
201
+ </ul>
202
+ </Section>
203
+
204
+ <Section title="Implementation Roadmap">
205
+ <p className="text-muted mb-6">
206
+ The transformation should be executed in phases, with clear milestones and
207
+ decision points.
208
+ </p>
209
+ <Exhibit number={6} title="Phased Implementation Plan">
210
+ <Timeline phases={data.roadmap} />
211
+ </Exhibit>
212
+ </Section>
213
+
214
+ <Section title="Call to Action">
215
+ <div className="bg-primary/5 rounded-2xl p-8 border border-primary/20">
216
+ <h3 className="text-xl font-semibold mb-4">Immediate Next Steps</h3>
217
+ <ol className="space-y-3 mb-6">
218
+ {data.callToAction.immediateSteps.map((step, i) => (
219
+ <li key={step} className="flex items-start gap-3">
220
+ <span className="shrink-0 w-7 h-7 rounded-full bg-primary text-white flex items-center justify-center font-bold text-sm">
221
+ {i + 1}
222
+ </span>
223
+ <span className="pt-0.5">{step}</span>
224
+ </li>
225
+ ))}
226
+ </ol>
227
+
228
+ <h3 className="text-xl font-semibold mb-4">Decision Points Required</h3>
229
+ <ul className="space-y-2 mb-6">
230
+ {data.callToAction.decisionPoints.map((point) => (
231
+ <li key={point} className="flex items-center gap-3">
232
+ <span className="w-2 h-2 bg-accent rounded-full" />
233
+ <span>{point}</span>
234
+ </li>
235
+ ))}
236
+ </ul>
237
+
238
+ <Callout label="Commitment Required">
239
+ {data.callToAction.commitmentRequired}
240
+ </Callout>
241
+ </div>
242
+ </Section>
243
+
244
+ <div className="mt-12 pt-8 border-t border-border text-center text-sm text-muted">
245
+ <p className="font-semibold text-foreground mb-1">{data.classification}</p>
246
+ <p>
247
+ This report was prepared for {data.clientName} and contains confidential
248
+ information.
249
+ </p>
250
+ <p className="mt-2">{data.reportDate}</p>
251
+ </div>
252
+ </div>
253
+ </div>
254
+ );
255
+ }