@telepath-computer/television 0.1.178 → 0.1.179
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/dist/canonical/v1/components.js +13 -1
- package/dist/cli.cjs +1187 -392
- package/dist/onboarding/README.md +35 -0
- package/dist/onboarding/business-ops/about.html +150 -0
- package/dist/onboarding/business-ops/retention-vs-releases.html +572 -0
- package/dist/onboarding/business-ops/revenue-vs-goals.html +621 -0
- package/dist/onboarding/onboarding-screens.json +167 -0
- package/dist/onboarding/productivity/about.html +149 -0
- package/dist/onboarding/productivity/company-todos/index.html +121 -0
- package/dist/onboarding/productivity/company-todos/task.css +205 -0
- package/dist/onboarding/productivity/company-todos/task.js +307 -0
- package/dist/onboarding/productivity/meeting-prep.html +440 -0
- package/dist/onboarding/productivity/priorities-today.html +409 -0
- package/dist/onboarding/productivity/todays-calendar/calendar.css +1 -0
- package/dist/onboarding/productivity/todays-calendar/calendar.js +716 -0
- package/dist/onboarding/productivity/todays-calendar/index.html +52 -0
- package/dist/onboarding/research/about.html +152 -0
- package/dist/onboarding/research/draft-blog-post.md +30 -0
- package/dist/onboarding/research/open-model-research.html +542 -0
- package/dist/onboarding/research/todays-news.html +503 -0
- package/dist/onboarding/{television-onboarding → tv-guide/welcome}/index.html +2 -2
- package/dist/skills/television/SKILL.md +4 -0
- package/dist/views/markdown/index.html +1 -1
- package/dist/web/assets/calendar-DToAnkzj.png +0 -0
- package/dist/web/assets/main-5017mprd.css +1 -0
- package/dist/web/assets/main-C-OjKUzX.js +865 -0
- package/dist/web/assets/markdown-DdDrJuVK.png +0 -0
- package/dist/web/assets/table-oeG9uAN1.png +0 -0
- package/dist/web/assets/tasks-D4xqXFPl.png +0 -0
- package/dist/web/index.html +2 -2
- package/package.json +1 -1
- package/dist/web/assets/main-FDJtlHD7.js +0 -768
- package/dist/web/assets/main-o9Z-XUYA.css +0 -1
- /package/dist/onboarding/{television-onboarding → tv-guide/welcome}/assets/television.svg +0 -0
|
@@ -0,0 +1,621 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
6
|
+
<title>Revenue vs. goals</title>
|
|
7
|
+
<link rel="stylesheet" href="/canonical/v1/styles.css">
|
|
8
|
+
<script type="module" src="/canonical/v1/components.js"></script>
|
|
9
|
+
<style>
|
|
10
|
+
/* Shared base for onboarding artifacts ([[../index.md]]): document padding
|
|
11
|
+
and the centered content shell. Typography, text color, and background
|
|
12
|
+
are the canonical stylesheet's — nothing in this set restates or pins
|
|
13
|
+
them, so artifacts follow the active theme ([[../index.md#^respect-theme]]). */
|
|
14
|
+
|
|
15
|
+
* {
|
|
16
|
+
box-sizing: border-box;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
body {
|
|
20
|
+
margin: 0;
|
|
21
|
+
padding: var(--space-32, 32px) var(--space-32, 32px) var(--space-64, 64px);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
.shell {
|
|
25
|
+
max-width: 720px;
|
|
26
|
+
margin: 0 auto;
|
|
27
|
+
display: grid;
|
|
28
|
+
/* Pin the single column to the container so a wide child (a data table)
|
|
29
|
+
scrolls inside its own .table-wrap instead of stretching the track and
|
|
30
|
+
overflowing the card. */
|
|
31
|
+
grid-template-columns: minmax(0, 1fr);
|
|
32
|
+
gap: var(--space-20, 20px);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/* Card-density headings ([[../index.md]]): document-scale h1 is oversized
|
|
36
|
+
inside a TV card. */
|
|
37
|
+
h1 {
|
|
38
|
+
margin: 0;
|
|
39
|
+
font-size: var(--text-xl, 17px);
|
|
40
|
+
font-weight: 600;
|
|
41
|
+
line-height: 1.25;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/* A lead paragraph (the .lede or .summary-deck standfirst) belongs in the
|
|
45
|
+
header, tight beneath the title — not a full grid-gap below it. Every
|
|
46
|
+
onboarding artifact places its lead this way so the spacing is uniform. */
|
|
47
|
+
header > .lede,
|
|
48
|
+
header > .summary-deck {
|
|
49
|
+
margin-top: var(--space-8, 8px);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
/* The hero header idiom ([[../index.md]]): a plain document header opening a
|
|
54
|
+
dashboard-shaped artifact — the title with a fictional freshness line and
|
|
55
|
+
an optional source/meta line, sitting on the document itself rather than
|
|
56
|
+
inside a card. */
|
|
57
|
+
|
|
58
|
+
header.hero h1 {
|
|
59
|
+
margin: 0 0 var(--space-6, 6px);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
.generated {
|
|
63
|
+
color: var(--color-text-muted);
|
|
64
|
+
font-size: var(--text-sm, 12px);
|
|
65
|
+
font-weight: 500;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.meta-line {
|
|
69
|
+
margin-top: var(--space-4, 4px);
|
|
70
|
+
color: var(--color-text-muted);
|
|
71
|
+
font-size: var(--text-sm, 12px);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
/* The panel/section idioms ([[../index.md]]): a bordered surface panel with
|
|
76
|
+
a heading and optional note, the muted summary-box, the section-title row,
|
|
77
|
+
and — for artifacts that lean on headings and spacing over nested cards —
|
|
78
|
+
the borderless .section and the .summary-deck lead paragraph. */
|
|
79
|
+
|
|
80
|
+
/* Borderless section: a title row (or heading) then its stack, no box. */
|
|
81
|
+
.section {
|
|
82
|
+
display: grid;
|
|
83
|
+
gap: var(--space-16, 16px);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/* Summary/lead as a standfirst paragraph — the borderless counterpart to
|
|
87
|
+
.summary-box. */
|
|
88
|
+
/* Lead/standfirst paragraph — the same size as the About .lede (body text),
|
|
89
|
+
not enlarged; it leads by position and primary color, not scale. */
|
|
90
|
+
.summary-deck {
|
|
91
|
+
margin: 0;
|
|
92
|
+
line-height: 1.5;
|
|
93
|
+
color: var(--color-text);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.panel {
|
|
97
|
+
padding: var(--space-20, 20px);
|
|
98
|
+
border: 1px solid var(--color-border);
|
|
99
|
+
border-radius: var(--radius-12, 12px);
|
|
100
|
+
background: var(--color-surface);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
.panel h2 {
|
|
104
|
+
margin: 0 0 var(--space-4, 4px);
|
|
105
|
+
font-size: var(--text-lg, 15px);
|
|
106
|
+
font-weight: 600;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
.panel .note {
|
|
110
|
+
margin: 0 0 var(--space-16, 16px);
|
|
111
|
+
color: var(--color-text-muted);
|
|
112
|
+
font-size: var(--text-sm, 12px);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
.summary-box {
|
|
116
|
+
padding: var(--space-16, 16px) var(--space-20, 20px);
|
|
117
|
+
border: 1px solid var(--color-border-muted);
|
|
118
|
+
border-radius: var(--radius-12, 12px);
|
|
119
|
+
background: var(--color-surface-muted);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
.summary-box h2 {
|
|
123
|
+
margin: 0 0 var(--space-8, 8px);
|
|
124
|
+
font-size: var(--text-lg, 15px);
|
|
125
|
+
font-weight: 600;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
.summary-box p {
|
|
129
|
+
margin: 0;
|
|
130
|
+
line-height: 1.45;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.section-title {
|
|
134
|
+
display: flex;
|
|
135
|
+
justify-content: space-between;
|
|
136
|
+
align-items: baseline;
|
|
137
|
+
gap: var(--space-12, 12px);
|
|
138
|
+
margin-bottom: var(--space-12, 12px);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.section-title h2 {
|
|
142
|
+
margin: 0;
|
|
143
|
+
font-size: var(--text-lg, 15px);
|
|
144
|
+
font-weight: 600;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
.section-title .note {
|
|
148
|
+
margin: 0;
|
|
149
|
+
color: var(--color-text-muted);
|
|
150
|
+
font-size: var(--text-sm, 12px);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
/* The KPI row idiom ([[../index.md]]): a wrapping row of stat cards, each
|
|
155
|
+
an uppercase label, a large value (accented via --kpi-accent, a ramp
|
|
156
|
+
token), and a delta line. */
|
|
157
|
+
|
|
158
|
+
.kpi-row {
|
|
159
|
+
display: flex;
|
|
160
|
+
flex-wrap: wrap;
|
|
161
|
+
gap: var(--space-12, 12px);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
.kpi {
|
|
165
|
+
flex: 1;
|
|
166
|
+
min-width: 120px;
|
|
167
|
+
padding: var(--space-12, 12px) var(--space-16, 16px);
|
|
168
|
+
border: 1px solid var(--color-border);
|
|
169
|
+
border-radius: var(--radius-12, 12px);
|
|
170
|
+
background: var(--color-surface);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
.kpi .label {
|
|
174
|
+
margin-bottom: var(--space-4, 4px);
|
|
175
|
+
color: var(--color-text-muted);
|
|
176
|
+
font-size: var(--text-sm, 12px);
|
|
177
|
+
letter-spacing: 0.05em;
|
|
178
|
+
text-transform: uppercase;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
.kpi .value {
|
|
182
|
+
font-size: 24px;
|
|
183
|
+
font-weight: 700;
|
|
184
|
+
line-height: 1;
|
|
185
|
+
color: var(--kpi-accent, var(--color-text));
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
.kpi .delta {
|
|
189
|
+
margin-top: var(--space-4, 4px);
|
|
190
|
+
font-size: var(--text-sm, 12px);
|
|
191
|
+
font-weight: 600;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.delta.up { color: var(--green-600); }
|
|
195
|
+
.delta.down { color: var(--red-600); }
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
/* The pill idiom ([[../index.md]]): small rounded status/tag chips. The
|
|
199
|
+
base pill is neutral; variant classes tint with canonical ramp tokens
|
|
200
|
+
(stable across themes by design, [[../index.md#^respect-theme]]). */
|
|
201
|
+
|
|
202
|
+
.pill {
|
|
203
|
+
display: inline-flex;
|
|
204
|
+
align-items: center;
|
|
205
|
+
gap: var(--space-4, 4px);
|
|
206
|
+
padding: 2px var(--space-10, 10px);
|
|
207
|
+
border: 1px solid var(--color-border);
|
|
208
|
+
border-radius: var(--radius-full, 9999px);
|
|
209
|
+
background: var(--color-surface);
|
|
210
|
+
color: var(--color-text-muted);
|
|
211
|
+
font-size: var(--text-sm, 12px);
|
|
212
|
+
line-height: 1.2;
|
|
213
|
+
white-space: nowrap;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.pill.blue { color: var(--blue-700); border-color: var(--blue-200); background: var(--blue-50); }
|
|
217
|
+
.pill.green { color: var(--green-700); border-color: var(--green-200); background: var(--green-50); }
|
|
218
|
+
.pill.orange { color: var(--orange-700); border-color: var(--orange-200); background: var(--orange-50); }
|
|
219
|
+
.pill.red { color: var(--red-700); border-color: var(--red-200); background: var(--red-50); }
|
|
220
|
+
.pill.dim { color: var(--neutral-500); border-color: var(--neutral-200); background: var(--neutral-100); }
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
/* The data-table idiom ([[../index.md]]): a dense comparison table with
|
|
224
|
+
uppercase column headers, hairline row rules, hover, and right-aligned
|
|
225
|
+
numeric columns in the mono face. Wrap in .table-wrap so wide tables
|
|
226
|
+
scroll inside the card instead of the page. */
|
|
227
|
+
|
|
228
|
+
.table-wrap {
|
|
229
|
+
overflow-x: auto;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.table-wrap table {
|
|
233
|
+
width: 100%;
|
|
234
|
+
margin: 0;
|
|
235
|
+
border-collapse: collapse;
|
|
236
|
+
font-size: var(--text-sm, 12px);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/* Only horizontal row rules — clear the cells' default vertical borders so
|
|
240
|
+
the edge columns don't double up against a container border. */
|
|
241
|
+
.table-wrap th,
|
|
242
|
+
.table-wrap td {
|
|
243
|
+
border-left: 0;
|
|
244
|
+
border-right: 0;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
.table-wrap thead th {
|
|
248
|
+
padding: var(--space-8, 8px) var(--space-12, 12px);
|
|
249
|
+
border-bottom: 1px solid var(--color-border);
|
|
250
|
+
color: var(--color-text-muted);
|
|
251
|
+
font-size: var(--text-sm, 12px);
|
|
252
|
+
font-weight: 600;
|
|
253
|
+
letter-spacing: 0.04em;
|
|
254
|
+
text-align: left;
|
|
255
|
+
text-transform: uppercase;
|
|
256
|
+
white-space: nowrap;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.table-wrap thead th.num {
|
|
260
|
+
text-align: right;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
.table-wrap tbody td {
|
|
264
|
+
padding: var(--space-10, 10px) var(--space-12, 12px);
|
|
265
|
+
border-bottom: 1px solid var(--color-border-muted);
|
|
266
|
+
white-space: nowrap;
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
.table-wrap tbody td.num {
|
|
270
|
+
text-align: right;
|
|
271
|
+
font-family: var(--font-mono);
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
.table-wrap tbody tr:last-child td {
|
|
275
|
+
border-bottom: none;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
.table-wrap tbody tr:hover {
|
|
279
|
+
background: var(--color-surface-muted);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
|
|
283
|
+
/* Shared chart scaffold for the dashboard artifacts ([[../index.md]]): the
|
|
284
|
+
wide dashboard shell, the responsive inline-SVG plumbing and common
|
|
285
|
+
axis/grid chrome, the legend row, and the narrow-viewport padding. Each
|
|
286
|
+
dashboard's own styles.css keeps only its series colors, swatch shape, and
|
|
287
|
+
any chart-specific chrome — SVG presentation attributes can't take var(),
|
|
288
|
+
so fills and strokes live in CSS. */
|
|
289
|
+
|
|
290
|
+
/* Dashboards run wider than the set's default shell. */
|
|
291
|
+
.shell {
|
|
292
|
+
max-width: 920px;
|
|
293
|
+
gap: var(--space-16, 16px);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/* Responsive inline SVG chart. */
|
|
297
|
+
.chart-container {
|
|
298
|
+
position: relative;
|
|
299
|
+
width: 100%;
|
|
300
|
+
overflow: hidden;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
svg.chart {
|
|
304
|
+
display: block;
|
|
305
|
+
width: 100%;
|
|
306
|
+
height: auto;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
svg.chart text {
|
|
310
|
+
font-family: var(--font-sans);
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/* Common axis/grid chrome. */
|
|
314
|
+
svg.chart .grid { stroke: var(--color-border-muted); }
|
|
315
|
+
svg.chart .axis-line { stroke: var(--color-border); }
|
|
316
|
+
svg.chart .axis-y { fill: var(--color-text-muted); }
|
|
317
|
+
|
|
318
|
+
/* Legend row. */
|
|
319
|
+
.legend {
|
|
320
|
+
display: flex;
|
|
321
|
+
gap: var(--space-20, 20px);
|
|
322
|
+
flex-wrap: wrap;
|
|
323
|
+
margin-top: var(--space-12, 12px);
|
|
324
|
+
font-size: var(--text-sm, 12px);
|
|
325
|
+
color: var(--color-text-muted);
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
.legend-item {
|
|
329
|
+
display: flex;
|
|
330
|
+
align-items: center;
|
|
331
|
+
gap: var(--space-6, 6px);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/* Narrow viewport (the default 528px card): tighten document padding so the
|
|
335
|
+
scaled-down chart keeps as much width as possible. */
|
|
336
|
+
@media (max-width: 600px) {
|
|
337
|
+
body {
|
|
338
|
+
padding: var(--space-16, 16px) var(--space-16, 16px) var(--space-48, 48px);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
|
|
343
|
+
/* Revenue vs. goals ([[index.md]]): artifact-specific styling only — the KPI
|
|
344
|
+
accent sequence, this chart's series/label colors, and its legend swatches.
|
|
345
|
+
The dashboard shell, chart plumbing, common chrome, and legend row come from
|
|
346
|
+
the shared chart scaffold ([shared/chart.css](../../shared/chart.css)). */
|
|
347
|
+
|
|
348
|
+
/* KPI value accents are a positional sequence (green/blue/purple/orange),
|
|
349
|
+
owned here rather than carried as ramp tokens in data. Each card sets
|
|
350
|
+
the --kpi-accent custom prop the shared KPI idiom reads. */
|
|
351
|
+
.kpi-row .kpi:nth-child(1) .value { --kpi-accent: var(--green-600); }
|
|
352
|
+
.kpi-row .kpi:nth-child(2) .value { --kpi-accent: var(--blue-600); }
|
|
353
|
+
.kpi-row .kpi:nth-child(3) .value { --kpi-accent: var(--purple-600); }
|
|
354
|
+
.kpi-row .kpi:nth-child(4) .value { --kpi-accent: var(--orange-600); }
|
|
355
|
+
|
|
356
|
+
/* This chart's series and labels (SVG presentation attributes can't take
|
|
357
|
+
var(), so every fill/stroke lives here). The x-axis keeps full text
|
|
358
|
+
strength so quarter labels read above the muted goal labels. */
|
|
359
|
+
svg.chart .axis-x { fill: var(--color-text); }
|
|
360
|
+
svg.chart .goal-labels { fill: var(--color-text-muted); }
|
|
361
|
+
|
|
362
|
+
svg.chart .goal-line { stroke: var(--neutral-400); }
|
|
363
|
+
svg.chart .goal-dots { fill: var(--neutral-400); }
|
|
364
|
+
svg.chart .bar-goal { fill: var(--color-surface-muted); stroke: var(--color-border); }
|
|
365
|
+
svg.chart .bar-actual { fill: var(--green-500); }
|
|
366
|
+
|
|
367
|
+
svg.chart .bar-labels { fill: var(--color-text); }
|
|
368
|
+
svg.chart .bar-labels .accent { fill: var(--green-500); }
|
|
369
|
+
|
|
370
|
+
.legend-swatch {
|
|
371
|
+
width: 14px;
|
|
372
|
+
height: 14px;
|
|
373
|
+
border-radius: var(--radius-4, 4px);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
.legend-swatch.actual {
|
|
377
|
+
background: var(--green-500);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
.legend-swatch.goal {
|
|
381
|
+
background: var(--color-surface-muted);
|
|
382
|
+
border: 2px dashed var(--neutral-400);
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/* The breakdown table sits inside a panel; give it the mock's breathing
|
|
386
|
+
room above the wrap. */
|
|
387
|
+
.table-wrap {
|
|
388
|
+
margin-top: var(--space-16, 16px);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
</style>
|
|
392
|
+
</head>
|
|
393
|
+
<body>
|
|
394
|
+
|
|
395
|
+
|
|
396
|
+
|
|
397
|
+
|
|
398
|
+
|
|
399
|
+
|
|
400
|
+
|
|
401
|
+
|
|
402
|
+
|
|
403
|
+
|
|
404
|
+
<main class="shell">
|
|
405
|
+
<header class="hero">
|
|
406
|
+
<h1>Revenue vs. goals</h1>
|
|
407
|
+
<div class="meta-line">Sources: Stripe (actual) + Notion (quarterly targets) · Q1 2025 – Q2 2026</div>
|
|
408
|
+
</header>
|
|
409
|
+
|
|
410
|
+
<div class="kpi-row">
|
|
411
|
+
|
|
412
|
+
<div class="kpi">
|
|
413
|
+
<div class="label">Q2 2026 Revenue</div>
|
|
414
|
+
<div class="value">$2.84M</div>
|
|
415
|
+
<div class="delta up">+49% QoQ</div>
|
|
416
|
+
</div>
|
|
417
|
+
|
|
418
|
+
<div class="kpi">
|
|
419
|
+
<div class="label">Q2 2026 Goal</div>
|
|
420
|
+
<div class="value">$2.6M</div>
|
|
421
|
+
<div class="delta up">Goal exceeded by $240K</div>
|
|
422
|
+
</div>
|
|
423
|
+
|
|
424
|
+
<div class="kpi">
|
|
425
|
+
<div class="label">TTM Revenue</div>
|
|
426
|
+
<div class="value">$7.64M</div>
|
|
427
|
+
<div class="delta up">+410% YoY</div>
|
|
428
|
+
</div>
|
|
429
|
+
|
|
430
|
+
<div class="kpi">
|
|
431
|
+
<div class="label">Expansion pipeline</div>
|
|
432
|
+
<div class="value">$9.6M</div>
|
|
433
|
+
<div class="delta up">Acme expansion path</div>
|
|
434
|
+
</div>
|
|
435
|
+
|
|
436
|
+
</div>
|
|
437
|
+
|
|
438
|
+
<section class="panel">
|
|
439
|
+
<h2>Quarterly revenue vs. goals</h2>
|
|
440
|
+
<p class="note">Actual revenue (Stripe) compared to quarterly targets (Notion) · Last 6 quarters</p>
|
|
441
|
+
<div class="chart-container">
|
|
442
|
+
<svg class="chart" viewBox="0 0 860 340" xmlns="http://www.w3.org/2000/svg">
|
|
443
|
+
<!-- Background grid -->
|
|
444
|
+
<g class="grid" stroke-width="1">
|
|
445
|
+
<line x1="70" y1="40" x2="820" y2="40"/>
|
|
446
|
+
<line x1="70" y1="90" x2="820" y2="90"/>
|
|
447
|
+
<line x1="70" y1="140" x2="820" y2="140"/>
|
|
448
|
+
<line x1="70" y1="190" x2="820" y2="190"/>
|
|
449
|
+
<line x1="70" y1="240" x2="820" y2="240"/>
|
|
450
|
+
</g>
|
|
451
|
+
|
|
452
|
+
<!-- Y-axis labels -->
|
|
453
|
+
<g class="axis-y" font-size="11" text-anchor="end">
|
|
454
|
+
<text x="62" y="44">$3M</text>
|
|
455
|
+
<text x="62" y="94">$2.4M</text>
|
|
456
|
+
<text x="62" y="144">$1.8M</text>
|
|
457
|
+
<text x="62" y="194">$1.2M</text>
|
|
458
|
+
<text x="62" y="244">$600K</text>
|
|
459
|
+
</g>
|
|
460
|
+
|
|
461
|
+
<!-- Goal line (dashed) connecting goal values -->
|
|
462
|
+
<polyline class="goal-line" points="110,234 235,210 360,180 485,150 610,124 735,96"
|
|
463
|
+
fill="none" stroke-width="2" stroke-dasharray="6 4" opacity="0.6"/>
|
|
464
|
+
|
|
465
|
+
<!-- Goal data points -->
|
|
466
|
+
<g class="goal-dots" opacity="0.8">
|
|
467
|
+
<circle cx="110" cy="234" r="4"/>
|
|
468
|
+
<circle cx="235" cy="210" r="4"/>
|
|
469
|
+
<circle cx="360" cy="180" r="4"/>
|
|
470
|
+
<circle cx="485" cy="150" r="4"/>
|
|
471
|
+
<circle cx="610" cy="124" r="4"/>
|
|
472
|
+
<circle cx="735" cy="96" r="4"/>
|
|
473
|
+
</g>
|
|
474
|
+
|
|
475
|
+
<!-- Goal bars (light, behind actual) -->
|
|
476
|
+
<rect class="bar-goal" x="92" y="220" width="36" height="50" rx="4" stroke-width="1" stroke-dasharray="3 2"/>
|
|
477
|
+
<rect class="bar-goal" x="217" y="220" width="36" height="50" rx="4" stroke-width="1" stroke-dasharray="3 2"/>
|
|
478
|
+
<rect class="bar-goal" x="342" y="187" width="36" height="83" rx="4" stroke-width="1" stroke-dasharray="3 2"/>
|
|
479
|
+
<rect class="bar-goal" x="467" y="145" width="36" height="125" rx="4" stroke-width="1" stroke-dasharray="3 2"/>
|
|
480
|
+
<rect class="bar-goal" x="592" y="104" width="36" height="166" rx="4" stroke-width="1" stroke-dasharray="3 2"/>
|
|
481
|
+
<rect class="bar-goal" x="717" y="54" width="36" height="216" rx="4" stroke-width="1" stroke-dasharray="3 2"/>
|
|
482
|
+
|
|
483
|
+
<!-- Actual revenue bars (green) -->
|
|
484
|
+
<rect class="bar-actual" x="98" y="230" width="24" height="40" rx="3"/>
|
|
485
|
+
<rect class="bar-actual" x="223" y="224" width="24" height="46" rx="3"/>
|
|
486
|
+
<rect class="bar-actual" x="348" y="195" width="24" height="75" rx="3"/>
|
|
487
|
+
<rect class="bar-actual" x="473" y="150" width="24" height="120" rx="3"/>
|
|
488
|
+
<rect class="bar-actual" x="598" y="112" width="24" height="158" rx="3"/>
|
|
489
|
+
<rect class="bar-actual" x="723" y="34" width="24" height="236" rx="3"/>
|
|
490
|
+
|
|
491
|
+
<!-- Bar value labels -->
|
|
492
|
+
<g class="bar-labels" font-size="11" font-weight="600" text-anchor="middle">
|
|
493
|
+
<text x="110" y="222">$240K</text>
|
|
494
|
+
<text x="235" y="216">$560K</text>
|
|
495
|
+
<text x="360" y="187">$900K</text>
|
|
496
|
+
<text x="485" y="142">$1.44M</text>
|
|
497
|
+
<text x="610" y="104">$1.9M</text>
|
|
498
|
+
<text class="accent" x="735" y="26">$2.84M</text>
|
|
499
|
+
</g>
|
|
500
|
+
|
|
501
|
+
<!-- X-axis labels -->
|
|
502
|
+
<g class="axis-x" font-size="12" font-weight="600" text-anchor="middle">
|
|
503
|
+
<text x="110" y="300">Q1 2025</text>
|
|
504
|
+
<text x="235" y="300">Q2 2025</text>
|
|
505
|
+
<text x="360" y="300">Q3 2025</text>
|
|
506
|
+
<text x="485" y="300">Q4 2025</text>
|
|
507
|
+
<text x="610" y="300">Q1 2026</text>
|
|
508
|
+
<text x="735" y="300">Q2 2026</text>
|
|
509
|
+
</g>
|
|
510
|
+
|
|
511
|
+
<!-- Goal labels below quarter labels -->
|
|
512
|
+
<g class="goal-labels" font-size="10" text-anchor="middle">
|
|
513
|
+
<text x="110" y="316">goal: $300K</text>
|
|
514
|
+
<text x="235" y="316">goal: $600K</text>
|
|
515
|
+
<text x="360" y="316">goal: $1M</text>
|
|
516
|
+
<text x="485" y="316">goal: $1.5M</text>
|
|
517
|
+
<text x="610" y="316">goal: $2M</text>
|
|
518
|
+
<text x="735" y="316">goal: $2.6M</text>
|
|
519
|
+
</g>
|
|
520
|
+
|
|
521
|
+
<!-- X-axis line -->
|
|
522
|
+
<line class="axis-line" x1="70" y1="270" x2="820" y2="270" stroke-width="1"/>
|
|
523
|
+
</svg>
|
|
524
|
+
</div>
|
|
525
|
+
|
|
526
|
+
<div class="legend">
|
|
527
|
+
<div class="legend-item">
|
|
528
|
+
<div class="legend-swatch actual"></div>
|
|
529
|
+
Actual revenue (Stripe)
|
|
530
|
+
</div>
|
|
531
|
+
<div class="legend-item">
|
|
532
|
+
<div class="legend-swatch goal"></div>
|
|
533
|
+
Quarterly goal (Notion)
|
|
534
|
+
</div>
|
|
535
|
+
</div>
|
|
536
|
+
</section>
|
|
537
|
+
|
|
538
|
+
<section class="panel">
|
|
539
|
+
<h2>Quarterly breakdown</h2>
|
|
540
|
+
<p class="note">Actual vs. goal with variance and key drivers</p>
|
|
541
|
+
<div class="table-wrap">
|
|
542
|
+
<table>
|
|
543
|
+
<thead>
|
|
544
|
+
<tr>
|
|
545
|
+
<th>Quarter</th>
|
|
546
|
+
<th class="num">Actual</th>
|
|
547
|
+
<th class="num">Goal</th>
|
|
548
|
+
<th class="num">Variance</th>
|
|
549
|
+
<th>Status</th>
|
|
550
|
+
<th>Key driver</th>
|
|
551
|
+
</tr>
|
|
552
|
+
</thead>
|
|
553
|
+
<tbody>
|
|
554
|
+
|
|
555
|
+
<tr>
|
|
556
|
+
<td>Q1 2025</td>
|
|
557
|
+
<td class="num">$240K</td>
|
|
558
|
+
<td class="num">$300K</td>
|
|
559
|
+
<td class="num">−$60K</td>
|
|
560
|
+
<td><span class="pill red">Missed</span></td>
|
|
561
|
+
<td>Pre-launch, design partner pilots only</td>
|
|
562
|
+
</tr>
|
|
563
|
+
|
|
564
|
+
<tr>
|
|
565
|
+
<td>Q2 2025</td>
|
|
566
|
+
<td class="num">$560K</td>
|
|
567
|
+
<td class="num">$600K</td>
|
|
568
|
+
<td class="num">−$40K</td>
|
|
569
|
+
<td><span class="pill orange">Close</span></td>
|
|
570
|
+
<td>v0.2 launch, first paying pilot conversions</td>
|
|
571
|
+
</tr>
|
|
572
|
+
|
|
573
|
+
<tr>
|
|
574
|
+
<td>Q3 2025</td>
|
|
575
|
+
<td class="num">$900K</td>
|
|
576
|
+
<td class="num">$1M</td>
|
|
577
|
+
<td class="num">−$100K</td>
|
|
578
|
+
<td><span class="pill orange">Close</span></td>
|
|
579
|
+
<td>NeonBank pilot signed, expansion conversations started</td>
|
|
580
|
+
</tr>
|
|
581
|
+
|
|
582
|
+
<tr>
|
|
583
|
+
<td>Q4 2025</td>
|
|
584
|
+
<td class="num">$1.44M</td>
|
|
585
|
+
<td class="num">$1.5M</td>
|
|
586
|
+
<td class="num">−$60K</td>
|
|
587
|
+
<td><span class="pill orange">Close</span></td>
|
|
588
|
+
<td>Mallory Health onboarded, multi-seat deals began</td>
|
|
589
|
+
</tr>
|
|
590
|
+
|
|
591
|
+
<tr>
|
|
592
|
+
<td>Q1 2026</td>
|
|
593
|
+
<td class="num">$1.9M</td>
|
|
594
|
+
<td class="num">$2M</td>
|
|
595
|
+
<td class="num">−$100K</td>
|
|
596
|
+
<td><span class="pill orange">Close</span></td>
|
|
597
|
+
<td>Acme AI pilot started, v0.3.0 shipped mid-quarter</td>
|
|
598
|
+
</tr>
|
|
599
|
+
|
|
600
|
+
<tr>
|
|
601
|
+
<td>Q2 2026</td>
|
|
602
|
+
<td class="num">$2.84M</td>
|
|
603
|
+
<td class="num">$2.6M</td>
|
|
604
|
+
<td class="num">+$240K</td>
|
|
605
|
+
<td><span class="pill green">Exceeded</span></td>
|
|
606
|
+
<td>v0.4.0 shipped, Acme expansion path opened ($9.6M ARR)</td>
|
|
607
|
+
</tr>
|
|
608
|
+
|
|
609
|
+
</tbody>
|
|
610
|
+
</table>
|
|
611
|
+
</div>
|
|
612
|
+
</section>
|
|
613
|
+
|
|
614
|
+
<section class="summary-box">
|
|
615
|
+
<h2>Summary</h2>
|
|
616
|
+
<p>Revenue has grown 11.8x over the past 18 months, from $240K in Q1 2025 to $2.84M in Q2 2026. The company missed or came in just under goal for the first five quarters — typical for a pre-product-market-fit startup — but exceeded the Q2 2026 target by $240K, driven by the v0.4.0 release and the Acme expansion path. TTM revenue is $7.64M, with the $9.6M Acme expansion path central to the seed deck narrative.</p>
|
|
617
|
+
</section>
|
|
618
|
+
</main>
|
|
619
|
+
|
|
620
|
+
</body>
|
|
621
|
+
</html>
|