@lukeashford/aurelius 4.5.0 → 4.7.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.
@@ -8,5 +8,6 @@
8
8
  @import './fonts.css';
9
9
  @import './theme.css';
10
10
  @import './prose.css';
11
+ @import './deliverable.css';
11
12
 
12
13
  @plugin "@tailwindcss/typography";
@@ -0,0 +1,528 @@
1
+ /* Deliverable renderer styles.
2
+ *
3
+ * Each visual class is defined as a Tailwind v4 `@utility` so the design-system
4
+ * ESLint rule recognises them. The same DOM serves both the on-screen view
5
+ * and the PDF print path; `@page` and `@media print` rules below replace the
6
+ * dark theme with a print-friendly version (black on white, page-sized
7
+ * sections, no actions). The accent color is a CSS variable scoped to the
8
+ * deliverable root and falls back to the design-system gold.
9
+ */
10
+
11
+ @utility deliverable {
12
+ --deliverable-accent: var(--color-gold);
13
+
14
+ display: flex;
15
+ flex-direction: column;
16
+ gap: var(--spacing-16);
17
+ width: 100%;
18
+ max-width: var(--container-xl);
19
+ margin-inline: auto;
20
+ padding-inline: var(--spacing-6);
21
+ padding-block: var(--spacing-12);
22
+ color: var(--color-white);
23
+ font-family: var(--font-body);
24
+ }
25
+
26
+ @utility deliverable-page {
27
+ width: 100%;
28
+ }
29
+
30
+ @utility deliverable-heading {
31
+ font-family: var(--font-heading);
32
+ font-size: var(--text-3xl);
33
+ line-height: var(--text-3xl--line-height);
34
+ color: var(--deliverable-accent);
35
+ margin-bottom: var(--spacing-6);
36
+ letter-spacing: var(--letter-spacing-tight);
37
+ }
38
+
39
+ /* === Cover === */
40
+
41
+ @utility deliverable-cover {
42
+ min-height: min(80vh, 900px);
43
+ display: flex;
44
+ align-items: center;
45
+ justify-content: center;
46
+ text-align: center;
47
+ border: 1px solid color-mix(in oklab, var(--deliverable-accent) 30%, transparent);
48
+ background-color: var(--color-charcoal);
49
+ padding: var(--spacing-16);
50
+ }
51
+
52
+ @utility deliverable-cover-inner {
53
+ display: flex;
54
+ flex-direction: column;
55
+ gap: var(--spacing-6);
56
+ max-width: 56ch;
57
+ }
58
+
59
+ @utility deliverable-cover-eyebrow {
60
+ text-transform: uppercase;
61
+ letter-spacing: var(--letter-spacing-widest);
62
+ color: var(--color-silver);
63
+ font-size: var(--text-xs);
64
+ }
65
+
66
+ @utility deliverable-cover-title {
67
+ font-family: var(--font-heading);
68
+ font-size: var(--text-6xl);
69
+ line-height: var(--text-6xl--line-height);
70
+ color: var(--deliverable-accent);
71
+ letter-spacing: var(--letter-spacing-tight);
72
+ }
73
+
74
+ @utility deliverable-cover-subtitle {
75
+ font-size: var(--text-xl);
76
+ line-height: var(--text-xl--line-height);
77
+ color: var(--color-silver);
78
+ }
79
+
80
+ @utility deliverable-cover-client {
81
+ margin-top: var(--spacing-12);
82
+ font-size: var(--text-sm);
83
+ letter-spacing: var(--letter-spacing-wider);
84
+ text-transform: uppercase;
85
+ color: var(--color-silver);
86
+ }
87
+
88
+ @utility deliverable-cover-client-name {
89
+ color: var(--color-white);
90
+ font-weight: var(--font-weight-semibold);
91
+ }
92
+
93
+ /* === Image grid === */
94
+
95
+ @utility deliverable-image-grid {
96
+ display: grid;
97
+ gap: var(--spacing-6);
98
+ }
99
+
100
+ @utility deliverable-image-grid-cols-1 {
101
+ grid-template-columns: 1fr;
102
+ }
103
+
104
+ @utility deliverable-image-grid-cols-2 {
105
+ grid-template-columns: repeat(2, minmax(0, 1fr));
106
+ }
107
+
108
+ @utility deliverable-image-grid-cols-3 {
109
+ grid-template-columns: repeat(3, minmax(0, 1fr));
110
+ }
111
+
112
+ @utility deliverable-image-item {
113
+ display: flex;
114
+ flex-direction: column;
115
+ gap: var(--spacing-2);
116
+ break-inside: avoid;
117
+ }
118
+
119
+ @utility deliverable-image-img {
120
+ width: 100%;
121
+ height: 100%;
122
+ aspect-ratio: 4 / 3;
123
+ object-fit: cover;
124
+ background-color: var(--color-graphite);
125
+ border: 1px solid var(--color-ash);
126
+ }
127
+
128
+ @utility deliverable-image-missing {
129
+ aspect-ratio: 4 / 3;
130
+ display: flex;
131
+ align-items: center;
132
+ justify-content: center;
133
+ border: 1px dashed var(--color-ash);
134
+ color: var(--color-silver);
135
+ font-size: var(--text-sm);
136
+ }
137
+
138
+ @utility deliverable-image-caption {
139
+ font-size: var(--text-sm);
140
+ color: var(--color-silver);
141
+ line-height: var(--line-height-snug);
142
+ }
143
+
144
+ /* === Spotlight === */
145
+
146
+ @utility deliverable-spotlight-media {
147
+ margin-bottom: var(--spacing-6);
148
+ }
149
+
150
+ @utility deliverable-spotlight-img {
151
+ width: 100%;
152
+ max-height: 70vh;
153
+ object-fit: contain;
154
+ background-color: var(--color-graphite);
155
+ border: 1px solid var(--color-ash);
156
+ }
157
+
158
+ @utility deliverable-spotlight-missing {
159
+ width: 100%;
160
+ height: 50vh;
161
+ display: flex;
162
+ align-items: center;
163
+ justify-content: center;
164
+ border: 1px dashed var(--color-ash);
165
+ color: var(--color-silver);
166
+ }
167
+
168
+ @utility deliverable-spotlight-body {
169
+ max-width: 72ch;
170
+ font-size: var(--text-base);
171
+ line-height: var(--line-height-relaxed);
172
+ }
173
+
174
+ /* === Text block === */
175
+
176
+ @utility deliverable-text-block {
177
+ max-width: 72ch;
178
+ font-size: var(--text-base);
179
+ line-height: var(--line-height-relaxed);
180
+ }
181
+
182
+ /* === Color palette === */
183
+
184
+ @utility deliverable-palette {
185
+ display: grid;
186
+ grid-template-columns: repeat(auto-fit, minmax(120px, 1fr));
187
+ gap: var(--spacing-4);
188
+ }
189
+
190
+ @utility deliverable-palette-item {
191
+ display: flex;
192
+ flex-direction: column;
193
+ gap: var(--spacing-1);
194
+ align-items: center;
195
+ text-align: center;
196
+ break-inside: avoid;
197
+ }
198
+
199
+ @utility deliverable-palette-chip {
200
+ width: 100%;
201
+ aspect-ratio: 1 / 1;
202
+ border: 1px solid var(--color-ash);
203
+ }
204
+
205
+ @utility deliverable-palette-label {
206
+ font-size: var(--text-sm);
207
+ color: var(--color-white);
208
+ font-weight: var(--font-weight-medium);
209
+ }
210
+
211
+ @utility deliverable-palette-hex {
212
+ font-family: var(--font-mono);
213
+ font-size: var(--text-xs);
214
+ color: var(--color-silver);
215
+ }
216
+
217
+ /* === Quote === */
218
+
219
+ @utility deliverable-quote {
220
+ display: flex;
221
+ align-items: center;
222
+ justify-content: center;
223
+ min-height: 40vh;
224
+ }
225
+
226
+ @utility deliverable-quote-body {
227
+ max-width: 64ch;
228
+ font-family: var(--font-heading);
229
+ text-align: center;
230
+ }
231
+
232
+ @utility deliverable-quote-text {
233
+ font-size: var(--text-3xl);
234
+ line-height: var(--line-height-snug);
235
+ color: var(--color-white);
236
+ }
237
+
238
+ @utility deliverable-quote-attribution {
239
+ margin-top: var(--spacing-6);
240
+ font-family: var(--font-body);
241
+ font-size: var(--text-sm);
242
+ color: var(--color-silver);
243
+ letter-spacing: var(--letter-spacing-wider);
244
+ }
245
+
246
+ /* === Floating action bar === */
247
+
248
+ @utility deliverable-actions {
249
+ position: sticky;
250
+ bottom: var(--spacing-6);
251
+ display: flex;
252
+ justify-content: flex-end;
253
+ margin-top: var(--spacing-8);
254
+ pointer-events: none;
255
+ }
256
+
257
+ @utility deliverable-action-button {
258
+ pointer-events: auto;
259
+ }
260
+
261
+ /* === Compact card ===
262
+ * Surfaced in chat-tree-style artifact lists where the full multi-page
263
+ * renderer would be cramped. Borrows the cover treatment but constrains it
264
+ * to card dimensions and adds a footer that invites the viewer to expand
265
+ * to the full presentation.
266
+ */
267
+
268
+ @utility deliverable-card {
269
+ --deliverable-accent: var(--color-gold);
270
+ display: flex;
271
+ flex-direction: column;
272
+ }
273
+
274
+ @utility deliverable-card-cover {
275
+ display: flex;
276
+ flex-direction: column;
277
+ align-items: flex-start;
278
+ gap: var(--spacing-2);
279
+ padding: var(--spacing-6);
280
+ border-bottom: 1px solid color-mix(in oklab, var(--deliverable-accent) 30%, transparent);
281
+ }
282
+
283
+ @utility deliverable-card-eyebrow {
284
+ text-transform: uppercase;
285
+ letter-spacing: var(--letter-spacing-widest);
286
+ color: var(--color-silver);
287
+ font-size: var(--text-xs);
288
+ }
289
+
290
+ @utility deliverable-card-title {
291
+ font-family: var(--font-heading);
292
+ font-size: var(--text-2xl);
293
+ line-height: var(--text-2xl--line-height);
294
+ color: var(--deliverable-accent);
295
+ letter-spacing: var(--letter-spacing-tight);
296
+ }
297
+
298
+ @utility deliverable-card-subtitle {
299
+ font-size: var(--text-sm);
300
+ color: var(--color-silver);
301
+ }
302
+
303
+ @utility deliverable-card-meta {
304
+ display: flex;
305
+ align-items: center;
306
+ padding: var(--spacing-3) var(--spacing-6);
307
+ font-size: var(--text-xs);
308
+ text-transform: uppercase;
309
+ letter-spacing: var(--letter-spacing-wider);
310
+ color: var(--color-silver);
311
+ }
312
+
313
+ /* === Print path ===
314
+ * Same React tree, different paint. The strategy:
315
+ * - Cover gets its own named page (`@page cover`) with no margins so it
316
+ * prints full-bleed, with the body running on default pages with
317
+ * normal margins.
318
+ * - Body sections flow naturally — only the cover forces a page break.
319
+ * `break-inside: avoid` on each block keeps headings with their content
320
+ * and stops grids from splitting awkwardly.
321
+ * - The palette and quote no longer claim a full page each — they were
322
+ * web-mode treatments, not print.
323
+ * - Running footer carries page numbers; the cover suppresses it via
324
+ * `@page :first`.
325
+ */
326
+
327
+ @page {
328
+ size: A4;
329
+ margin: 18mm 18mm 22mm;
330
+ @bottom-right {
331
+ content: counter(page);
332
+ font-family: var(--font-body);
333
+ font-size: 9pt;
334
+ color: var(--color-slate);
335
+ }
336
+ }
337
+
338
+ @page :first {
339
+ margin: 0;
340
+ @bottom-right {
341
+ content: none;
342
+ }
343
+ }
344
+
345
+ @media print {
346
+ .deliverable {
347
+ color: var(--color-obsidian);
348
+ padding: 0;
349
+ margin: 0;
350
+ max-width: none;
351
+ gap: 0;
352
+ font-size: 10.5pt;
353
+ line-height: var(--line-height-relaxed);
354
+ }
355
+
356
+ .deliverable-page {
357
+ /* Sections flow; break only when content needs more room. Avoid
358
+ splitting any single block across pages. */
359
+ page-break-inside: avoid;
360
+ break-inside: avoid;
361
+ margin-bottom: 14mm;
362
+ }
363
+
364
+ .deliverable-page + .deliverable-page {
365
+ margin-top: 0;
366
+ }
367
+
368
+ .deliverable-heading {
369
+ page-break-after: avoid;
370
+ break-after: avoid;
371
+ }
372
+
373
+ /* === Cover ===
374
+ * Full-bleed first page. The cover is always the first section, so
375
+ * `@page :first { margin: 0 }` lets it bleed; we still pad the content
376
+ * inside the cover so the type doesn't sit on the page edge.
377
+ */
378
+ .deliverable-cover {
379
+ page-break-after: always;
380
+ break-after: page;
381
+ background-color: var(--color-obsidian);
382
+ color: var(--color-white);
383
+ min-height: 297mm;
384
+ width: 210mm;
385
+ border: none;
386
+ padding: 36mm 28mm;
387
+ display: grid;
388
+ grid-template-rows: auto 1fr auto;
389
+ text-align: left;
390
+ }
391
+
392
+ .deliverable-cover-inner {
393
+ grid-row: 2;
394
+ align-self: end;
395
+ max-width: 28em;
396
+ }
397
+
398
+ .deliverable-cover-eyebrow {
399
+ color: var(--deliverable-accent);
400
+ font-size: 9pt;
401
+ }
402
+
403
+ .deliverable-cover-title {
404
+ font-size: 44pt;
405
+ line-height: 1.05;
406
+ color: var(--color-white);
407
+ }
408
+
409
+ .deliverable-cover-subtitle {
410
+ font-size: 13pt;
411
+ color: var(--color-silver);
412
+ margin-top: 2mm;
413
+ }
414
+
415
+ .deliverable-cover-client {
416
+ grid-row: 3;
417
+ margin-top: 0;
418
+ color: var(--color-silver);
419
+ }
420
+
421
+ .deliverable-cover-client-name {
422
+ color: var(--color-white);
423
+ }
424
+
425
+ /* === Body typography === */
426
+ .deliverable-heading {
427
+ font-size: 20pt;
428
+ margin-bottom: 4mm;
429
+ color: var(--deliverable-accent);
430
+ }
431
+
432
+ .deliverable-text-block,
433
+ .deliverable-spotlight-body {
434
+ font-size: 11pt;
435
+ line-height: 1.55;
436
+ max-width: 36em;
437
+ color: var(--color-obsidian);
438
+ }
439
+
440
+ /* === Image grid ===
441
+ * Tighter than on screen. Each item stays atomic; the grid can break
442
+ * between rows but not mid-cell.
443
+ */
444
+ .deliverable-image-grid {
445
+ gap: 4mm;
446
+ }
447
+
448
+ .deliverable-image-item {
449
+ page-break-inside: avoid;
450
+ break-inside: avoid;
451
+ }
452
+
453
+ .deliverable-image-img {
454
+ aspect-ratio: 4 / 3;
455
+ border: none;
456
+ }
457
+
458
+ .deliverable-image-caption {
459
+ color: var(--color-slate);
460
+ font-size: 9pt;
461
+ margin-top: 1.5mm;
462
+ }
463
+
464
+ /* === Spotlight === */
465
+ .deliverable-spotlight-img {
466
+ max-height: 140mm;
467
+ border: none;
468
+ background-color: transparent;
469
+ }
470
+
471
+ .deliverable-spotlight-media {
472
+ margin-bottom: 4mm;
473
+ }
474
+
475
+ /* === Palette ===
476
+ * Inline strip at body width — not a full-page chart. Smaller chips,
477
+ * label and hex below.
478
+ */
479
+ .deliverable-palette {
480
+ grid-template-columns: repeat(auto-fit, minmax(28mm, 1fr));
481
+ gap: 4mm;
482
+ max-width: 160mm;
483
+ }
484
+
485
+ .deliverable-palette-chip {
486
+ aspect-ratio: 1 / 1;
487
+ border: 1px solid var(--color-slate);
488
+ }
489
+
490
+ .deliverable-palette-label {
491
+ font-size: 10pt;
492
+ color: var(--color-obsidian);
493
+ margin-top: 2mm;
494
+ }
495
+
496
+ .deliverable-palette-hex {
497
+ font-size: 8pt;
498
+ color: var(--color-slate);
499
+ }
500
+
501
+ /* === Quote ===
502
+ * Editorial pull-quote, not a full page. Generous margins, no min-height
503
+ * heroics.
504
+ */
505
+ .deliverable-quote {
506
+ min-height: 0;
507
+ padding: 6mm 0 8mm;
508
+ }
509
+
510
+ .deliverable-quote-body {
511
+ max-width: 30em;
512
+ margin-inline: auto;
513
+ }
514
+
515
+ .deliverable-quote-text {
516
+ font-size: 18pt;
517
+ line-height: 1.3;
518
+ color: var(--color-obsidian);
519
+ }
520
+
521
+ .deliverable-quote-attribution {
522
+ color: var(--color-slate);
523
+ }
524
+
525
+ .deliverable-actions {
526
+ display: none;
527
+ }
528
+ }
@@ -175,6 +175,7 @@
175
175
  /* ===== ANIMATIONS ===== */
176
176
  --animate-fade-in: fade-in 200ms ease-out;
177
177
  --animate-fade-out: fade-out 150ms ease-in;
178
+ --animate-lightbox-in: lightbox-in 220ms var(--ease-smooth);
178
179
  --animate-slide-in-right: slide-in-right 300ms var(--ease-smooth);
179
180
  --animate-slide-out-right: slide-out-right 200ms ease-in;
180
181
  --animate-pulse-glow: pulse-glow 2s ease-in-out infinite;
@@ -208,6 +209,17 @@
208
209
  }
209
210
  }
210
211
 
212
+ @keyframes lightbox-in {
213
+ 0% {
214
+ opacity: 0;
215
+ transform: scale(0.96);
216
+ }
217
+ 100% {
218
+ opacity: 1;
219
+ transform: scale(1);
220
+ }
221
+ }
222
+
211
223
  @keyframes slide-in-right {
212
224
  0% {
213
225
  transform: translateX(100%);