@dloizides/marketing-astro-kit 1.3.3 → 1.4.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.
@@ -1,516 +1,524 @@
1
- ---
2
- // Reusable trust / credibility section for product marketing sites — the
3
- // markers an executive scans for: security & compliance cards, a discreet
4
- // "built by" line, plus clearly-labeled PLACEHOLDER slots for customer logos
5
- // and testimonials the site owner fills in with real ones.
6
- //
7
- // Data-driven (schema.ts → TrustSectionData); themed via host CSS vars.
8
- //
9
- // <TrustSection data={trust} id="trust" />
10
- import type { TrustSectionData } from './schema';
11
- import { ctaAttrs } from './schema';
12
- import { TRUST_ICONS } from './icons';
13
-
14
- interface Props {
15
- data: TrustSectionData;
16
- id?: string;
17
- }
18
-
19
- const { data, id = 'trust' } = Astro.props as Props;
20
-
21
- // A product can inject bespoke mock markup for the sample-deliverable showcase
22
- // via <TrustSection><Fragment slot="sample-deliverable">…</Fragment></TrustSection>
23
- // while the eyebrow/title/caption chrome stays shared.
24
- const hasSampleSlot = Astro.slots.has('sample-deliverable');
25
- ---
26
-
27
- <section class="tmk-trust" id={id} aria-labelledby={`${id}-title`}>
28
- <div class="tmk-container">
29
- <p class="tmk-eyebrow" data-reveal>{data.eyebrow}</p>
30
- <h2 class="tmk-title" id={`${id}-title`} data-reveal>{data.title}</h2>
31
- {data.subtitle && <p class="tmk-sub" data-reveal>{data.subtitle}</p>}
32
-
33
- <div class="tmk-grid">
34
- {data.items.map((item, i) => (
35
- <article class="tmk-card" data-reveal style={`--d:${(i % 4) + 1}`}>
36
- <span class="tmk-ico" set:html={TRUST_ICONS[item.icon]} />
37
- <h3 class="tmk-card-t">{item.title}</h3>
38
- <p class="tmk-card-b">{item.body}</p>
39
- </article>
40
- ))}
41
- </div>
42
-
43
- {data.sampleDeliverable && (
44
- <div class="tmk-sample" data-reveal>
45
- <div class="tmk-sample-copy">
46
- <p class="tmk-sample-eyebrow">{data.sampleDeliverable.eyebrow}</p>
47
- <h3 class="tmk-sample-t">{data.sampleDeliverable.title}</h3>
48
- <p class="tmk-sample-cap">{data.sampleDeliverable.caption}</p>
49
- </div>
50
- <div class="tmk-sample-media">
51
- {hasSampleSlot ? (
52
- <slot name="sample-deliverable" />
53
- ) : data.sampleDeliverable.image ? (
54
- <img class="tmk-sample-img" src={data.sampleDeliverable.image} alt={data.sampleDeliverable.title} loading="lazy" />
55
- ) : null}
56
- </div>
57
- </div>
58
- )}
59
-
60
- {data.logos && (
61
- <div class="tmk-logos" data-reveal>
62
- <p class="tmk-logos-label">{data.logos.label}</p>
63
- <div class="tmk-logos-row">
64
- {data.logos.items.map((logo) =>
65
- logo.placeholder ? (
66
- <span class="tmk-logo tmk-logo--ph" aria-hidden="true">Your logo</span>
67
- ) : logo.href ? (
68
- <a class="tmk-logo" href={logo.href} target="_blank" rel="noopener">{logo.name}</a>
69
- ) : (
70
- <span class="tmk-logo">{logo.name}</span>
71
- ),
72
- )}
73
- </div>
74
- {data.logos.note && <p class="tmk-ph-note">{data.logos.note}</p>}
75
- </div>
76
- )}
77
-
78
- {data.testimonials && (
79
- <div class="tmk-quotes" data-reveal>
80
- <p class="tmk-logos-label">{data.testimonials.label}</p>
81
- <div class="tmk-quotes-row">
82
- {data.testimonials.items.map((t) => (
83
- <figure class={`tmk-quote${t.placeholder ? ' tmk-quote--ph' : ''}`}>
84
- {t.placeholder && <span class="tmk-ph-tag">Placeholder</span>}
85
- <blockquote class="tmk-quote-b">{t.quote}</blockquote>
86
- <figcaption class="tmk-quote-cite">
87
- <span class="tmk-quote-name">{t.authorName}</span>
88
- {t.authorRole && <span class="tmk-quote-role">{t.authorRole}</span>}
89
- </figcaption>
90
- </figure>
91
- ))}
92
- </div>
93
- {data.testimonials.note && <p class="tmk-ph-note">{data.testimonials.note}</p>}
94
- </div>
95
- )}
96
-
97
- {data.foundingPartner && (
98
- <aside class="tmk-founding" data-reveal>
99
- <div class="tmk-founding-body">
100
- <p class="tmk-founding-eyebrow">{data.foundingPartner.eyebrow}</p>
101
- <h3 class="tmk-founding-t">{data.foundingPartner.title}</h3>
102
- <p class="tmk-founding-b">{data.foundingPartner.body}</p>
103
- <ul class="tmk-founding-perks">
104
- {data.foundingPartner.perks.map((perk) => <li>{perk}</li>)}
105
- </ul>
106
- </div>
107
- {data.foundingPartner.cta && (
108
- <a class="tmk-founding-cta" {...ctaAttrs(data.foundingPartner.cta)}>
109
- {data.foundingPartner.cta.label}
110
- </a>
111
- )}
112
- </aside>
113
- )}
114
-
115
- {data.founder && (
116
- <figure class="tmk-founder" data-reveal>
117
- {data.founder.avatar ? (
118
- <img class="tmk-founder-av" src={data.founder.avatar} alt={data.founder.name ?? 'Founder'} loading="lazy" />
119
- ) : (
120
- <span class="tmk-founder-av tmk-founder-av--ph" aria-hidden="true">
121
- {(data.founder.name ?? '·').trim().charAt(0)}
122
- </span>
123
- )}
124
- <figcaption class="tmk-founder-cap">
125
- <p class="tmk-founder-line">{data.founder.line}</p>
126
- {(data.founder.name || data.founder.role) && (
127
- <p class="tmk-founder-cite">
128
- {data.founder.name && <span class="tmk-founder-name">{data.founder.name}</span>}
129
- {data.founder.role && <span class="tmk-founder-role">{data.founder.role}</span>}
130
- </p>
131
- )}
132
- </figcaption>
133
- </figure>
134
- )}
135
-
136
- {data.builtBy && (
137
- <p class="tmk-builtby" data-reveal>
138
- {data.builtBy.label}
139
- <a href={data.builtBy.href} target="_blank" rel="noopener">{data.builtBy.name}</a>
140
- </p>
141
- )}
142
- </div>
143
- </section>
144
-
145
- <style>
146
- .tmk-trust {
147
- --_brand: var(--brand, #d8332a);
148
- --_accent: var(--accent, #f5a300);
149
- --_ink: var(--ink, #0a0a1f);
150
- --_paper: var(--paper, #fff);
151
- --_bg: var(--bg, #fbf9f4);
152
- --_bg-tint: var(--bg-tint, #f1ede1);
153
- --_muted: var(--muted, rgba(10, 10, 31, 0.62));
154
- --_hairline: var(--hairline, rgba(10, 10, 31, 0.1));
155
- --_r-md: var(--radius-md, 14px);
156
- --_r-lg: var(--radius-lg, 24px);
157
- --_shadow: var(--shadow, 0 30px 60px -30px rgba(10, 10, 31, 0.4));
158
- padding: 96px 0;
159
- background: var(--_paper);
160
- border-top: 1px solid var(--_hairline);
161
- border-bottom: 1px solid var(--_hairline);
162
- }
163
- .tmk-container {
164
- width: min(1200px, 100% - 48px);
165
- margin-inline: auto;
166
- }
167
- .tmk-eyebrow {
168
- font-family: 'Oswald', sans-serif;
169
- font-size: 12px;
170
- font-weight: 600;
171
- letter-spacing: 0.22em;
172
- text-transform: uppercase;
173
- color: var(--_brand);
174
- margin: 0;
175
- }
176
- .tmk-title {
177
- font-family: 'Oswald', 'Inter', sans-serif;
178
- font-size: clamp(30px, 3.8vw, 46px);
179
- font-weight: 700;
180
- line-height: 1.08;
181
- letter-spacing: -0.01em;
182
- margin: 12px 0 14px;
183
- max-width: 22ch;
184
- color: var(--_ink);
185
- }
186
- .tmk-sub {
187
- color: var(--_muted);
188
- max-width: 60ch;
189
- margin: 0 0 44px;
190
- }
191
-
192
- /* Cards --------------------------------------------------------------- */
193
- .tmk-grid {
194
- display: grid;
195
- grid-template-columns: repeat(4, 1fr);
196
- gap: 18px;
197
- }
198
- @media (max-width: 1024px) { .tmk-grid { grid-template-columns: repeat(2, 1fr); } }
199
- @media (max-width: 560px) { .tmk-grid { grid-template-columns: 1fr; } }
200
- .tmk-card {
201
- position: relative;
202
- padding: 26px 22px;
203
- border-radius: var(--_r-md);
204
- background: var(--_bg);
205
- border: 1px solid var(--_hairline);
206
- transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
207
- }
208
- .tmk-card:hover {
209
- transform: translateY(-4px);
210
- box-shadow: var(--_shadow);
211
- border-color: transparent;
212
- }
213
- .tmk-ico {
214
- display: inline-grid;
215
- place-items: center;
216
- width: 44px;
217
- height: 44px;
218
- border-radius: 12px;
219
- background: color-mix(in srgb, var(--_brand) 10%, transparent);
220
- color: var(--_brand);
221
- margin-bottom: 16px;
222
- }
223
- .tmk-ico :global(svg) { width: 22px; height: 22px; }
224
- .tmk-card-t {
225
- font-family: 'Oswald', 'Inter', sans-serif;
226
- font-size: 18px;
227
- font-weight: 600;
228
- margin: 0 0 8px;
229
- color: var(--_ink);
230
- }
231
- .tmk-card-b { color: var(--_muted); margin: 0; font-size: 14.5px; }
232
-
233
- /* Logos --------------------------------------------------------------- */
234
- .tmk-logos { margin-top: 52px; }
235
- .tmk-logos-label {
236
- font-family: 'Oswald', sans-serif;
237
- font-size: 12px;
238
- letter-spacing: 0.2em;
239
- text-transform: uppercase;
240
- color: var(--_muted);
241
- margin: 0 0 18px;
242
- text-align: center;
243
- }
244
- .tmk-logos-row {
245
- display: flex;
246
- align-items: center;
247
- justify-content: center;
248
- flex-wrap: wrap;
249
- gap: 14px 18px;
250
- }
251
- .tmk-logo {
252
- font-family: 'Oswald', sans-serif;
253
- font-weight: 600;
254
- font-size: 17px;
255
- letter-spacing: 0.02em;
256
- color: var(--_ink);
257
- padding: 12px 22px;
258
- border-radius: var(--_r-md);
259
- background: var(--_bg-tint);
260
- border: 1px solid var(--_hairline);
261
- transition: color 0.14s ease, border-color 0.14s ease;
262
- }
263
- a.tmk-logo:hover { color: var(--_brand); border-color: var(--_brand); }
264
- .tmk-logo--ph {
265
- color: var(--_muted);
266
- background: transparent;
267
- border: 1px dashed var(--_hairline);
268
- opacity: 0.75;
269
- }
270
-
271
- /* Testimonials -------------------------------------------------------- */
272
- .tmk-quotes { margin-top: 52px; }
273
- .tmk-quotes-row {
274
- display: grid;
275
- grid-template-columns: repeat(3, 1fr);
276
- gap: 18px;
277
- }
278
- @media (max-width: 900px) { .tmk-quotes-row { grid-template-columns: 1fr; } }
279
- .tmk-quote {
280
- position: relative;
281
- padding: 26px 24px 22px;
282
- border-radius: var(--_r-md);
283
- background: var(--_bg);
284
- border: 1px solid var(--_hairline);
285
- }
286
- .tmk-quote--ph { border-style: dashed; background: transparent; }
287
- .tmk-ph-tag {
288
- position: absolute;
289
- top: 14px;
290
- right: 14px;
291
- font-family: 'Oswald', sans-serif;
292
- font-size: 9.5px;
293
- font-weight: 600;
294
- letter-spacing: 0.14em;
295
- text-transform: uppercase;
296
- color: var(--_muted);
297
- background: var(--_bg-tint);
298
- padding: 3px 8px;
299
- border-radius: 999px;
300
- }
301
- .tmk-quote-b {
302
- margin: 0 0 16px;
303
- font-size: 16px;
304
- line-height: 1.5;
305
- color: var(--_ink);
306
- }
307
- .tmk-quote--ph .tmk-quote-b { color: var(--_muted); }
308
- .tmk-quote-b::before { content: '“'; color: var(--_brand); font-weight: 700; }
309
- .tmk-quote-cite { font-style: normal; }
310
- .tmk-quote-name {
311
- display: block;
312
- font-family: 'Oswald', sans-serif;
313
- font-weight: 600;
314
- font-size: 14.5px;
315
- color: var(--_ink);
316
- }
317
- .tmk-quote-role { display: block; font-size: 12.5px; color: var(--_muted); }
318
-
319
- .tmk-ph-note {
320
- text-align: center;
321
- color: var(--_muted);
322
- font-size: 12.5px;
323
- margin: 16px 0 0;
324
- font-style: italic;
325
- }
326
-
327
- /* Sample deliverable -------------------------------------------------- */
328
- .tmk-sample {
329
- margin-top: 52px;
330
- display: grid;
331
- grid-template-columns: 0.92fr 1.08fr;
332
- gap: 34px;
333
- align-items: center;
334
- padding: 30px;
335
- border-radius: var(--_r-lg);
336
- background: var(--_bg);
337
- border: 1px solid var(--_hairline);
338
- }
339
- @media (max-width: 860px) {
340
- .tmk-sample { grid-template-columns: 1fr; gap: 24px; padding: 24px; }
341
- }
342
- .tmk-sample-eyebrow {
343
- font-family: 'Oswald', sans-serif;
344
- font-size: 11px;
345
- font-weight: 600;
346
- letter-spacing: 0.2em;
347
- text-transform: uppercase;
348
- color: var(--_brand);
349
- margin: 0 0 8px;
350
- }
351
- .tmk-sample-t {
352
- font-family: 'Oswald', 'Inter', sans-serif;
353
- font-size: clamp(20px, 2.4vw, 26px);
354
- font-weight: 700;
355
- line-height: 1.14;
356
- margin: 0 0 10px;
357
- color: var(--_ink);
358
- }
359
- .tmk-sample-cap { color: var(--_muted); margin: 0; font-size: 14.5px; }
360
- .tmk-sample-media { min-width: 0; }
361
- .tmk-sample-img {
362
- display: block;
363
- width: 100%;
364
- height: auto;
365
- border-radius: var(--_r-md);
366
- border: 1px solid var(--_hairline);
367
- }
368
-
369
- /* Founding-partner panel ---------------------------------------------- */
370
- .tmk-founding {
371
- margin-top: 52px;
372
- display: flex;
373
- align-items: center;
374
- justify-content: space-between;
375
- gap: 30px;
376
- flex-wrap: wrap;
377
- padding: 30px 32px;
378
- border-radius: var(--_r-lg);
379
- background: var(--_ink);
380
- color: var(--_paper);
381
- border: 1px solid var(--_ink);
382
- }
383
- .tmk-founding-body { flex: 1 1 420px; }
384
- .tmk-founding-eyebrow {
385
- font-family: 'Oswald', sans-serif;
386
- font-size: 11px;
387
- font-weight: 600;
388
- letter-spacing: 0.2em;
389
- text-transform: uppercase;
390
- color: var(--_accent);
391
- margin: 0 0 8px;
392
- }
393
- .tmk-founding-t {
394
- font-family: 'Oswald', 'Inter', sans-serif;
395
- font-size: clamp(22px, 2.6vw, 28px);
396
- font-weight: 700;
397
- line-height: 1.12;
398
- margin: 0 0 10px;
399
- color: var(--_paper);
400
- }
401
- .tmk-founding-b {
402
- color: rgba(255, 255, 255, 0.78);
403
- margin: 0 0 16px;
404
- font-size: 14.5px;
405
- max-width: 60ch;
406
- }
407
- .tmk-founding-perks {
408
- list-style: none;
409
- padding: 0;
410
- margin: 0;
411
- display: grid;
412
- grid-template-columns: repeat(2, minmax(0, 1fr));
413
- gap: 8px 22px;
414
- }
415
- @media (max-width: 560px) { .tmk-founding-perks { grid-template-columns: 1fr; } }
416
- .tmk-founding-perks li {
417
- position: relative;
418
- padding-left: 22px;
419
- color: rgba(255, 255, 255, 0.9);
420
- font-size: 13.8px;
421
- }
422
- .tmk-founding-perks li::before {
423
- content: '';
424
- position: absolute;
425
- left: 0;
426
- top: 7px;
427
- width: 8px;
428
- height: 8px;
429
- border-radius: 50%;
430
- background: var(--_accent);
431
- }
432
- .tmk-founding-cta {
433
- display: inline-flex;
434
- align-items: center;
435
- justify-content: center;
436
- flex-shrink: 0;
437
- padding: 14px 24px;
438
- border-radius: 999px;
439
- background: var(--_accent);
440
- color: var(--_ink);
441
- font-family: 'Inter', system-ui, sans-serif;
442
- font-weight: 700;
443
- font-size: 14.5px;
444
- letter-spacing: 0.01em;
445
- text-decoration: none;
446
- border: 1px solid transparent;
447
- transition: transform 0.12s ease, box-shadow 0.12s ease;
448
- cursor: pointer;
449
- }
450
- .tmk-founding-cta:hover {
451
- transform: translateY(-1px);
452
- box-shadow: 0 12px 26px -12px rgba(0, 0, 0, 0.6);
453
- }
454
-
455
- /* Founder line -------------------------------------------------------- */
456
- .tmk-founder {
457
- margin: 40px 0 0;
458
- display: flex;
459
- align-items: center;
460
- gap: 16px;
461
- max-width: 78ch;
462
- }
463
- .tmk-founder-av {
464
- flex-shrink: 0;
465
- width: 52px;
466
- height: 52px;
467
- border-radius: 50%;
468
- object-fit: cover;
469
- border: 1px solid var(--_hairline);
470
- }
471
- .tmk-founder-av--ph {
472
- display: inline-grid;
473
- place-items: center;
474
- background: color-mix(in srgb, var(--_brand) 12%, transparent);
475
- color: var(--_brand);
476
- font-family: 'Oswald', sans-serif;
477
- font-weight: 700;
478
- font-size: 20px;
479
- text-transform: uppercase;
480
- }
481
- .tmk-founder-cap { margin: 0; }
482
- .tmk-founder-line {
483
- margin: 0;
484
- color: var(--_ink);
485
- font-size: 15.5px;
486
- line-height: 1.5;
487
- }
488
- .tmk-founder-cite { margin: 4px 0 0; }
489
- .tmk-founder-name {
490
- font-family: 'Oswald', sans-serif;
491
- font-weight: 600;
492
- font-size: 13.5px;
493
- color: var(--_ink);
494
- }
495
- .tmk-founder-role {
496
- font-size: 12.5px;
497
- color: var(--_muted);
498
- margin-left: 8px;
499
- }
500
-
501
- /* Built by ------------------------------------------------------------ */
502
- .tmk-builtby {
503
- margin: 48px 0 0;
504
- text-align: center;
505
- color: var(--_muted);
506
- font-size: 13px;
507
- }
508
- .tmk-builtby a {
509
- color: var(--_ink);
510
- border-bottom: 1px dotted var(--_muted);
511
- margin-left: 5px;
512
- }
513
- .tmk-builtby a:hover { color: var(--_brand); }
514
-
515
- @media (max-width: 560px) { .tmk-trust { padding: 64px 0; } }
516
- </style>
1
+ ---
2
+ // Reusable trust / credibility section for product marketing sites — the
3
+ // markers an executive scans for: security & compliance cards, a discreet
4
+ // "built by" line, plus clearly-labeled PLACEHOLDER slots for customer logos
5
+ // and testimonials the site owner fills in with real ones.
6
+ //
7
+ // Data-driven (schema.ts → TrustSectionData); themed via host CSS vars.
8
+ //
9
+ // <TrustSection data={trust} id="trust" />
10
+ import type { TrustSectionData } from './schema';
11
+ import './a11y.css';
12
+ import { ctaAttrs } from './schema';
13
+ import { TRUST_ICONS } from './icons';
14
+
15
+ interface Props {
16
+ data: TrustSectionData;
17
+ id?: string;
18
+ }
19
+
20
+ const { data, id = 'trust' } = Astro.props as Props;
21
+
22
+ // A product can inject bespoke mock markup for the sample-deliverable showcase
23
+ // via <TrustSection><Fragment slot="sample-deliverable">…</Fragment></TrustSection>
24
+ // while the eyebrow/title/caption chrome stays shared.
25
+ const hasSampleSlot = Astro.slots.has('sample-deliverable');
26
+ ---
27
+
28
+ <section class="tmk-trust" id={id} aria-labelledby={`${id}-title`}>
29
+ <div class="tmk-container">
30
+ <p class="tmk-eyebrow" data-reveal>{data.eyebrow}</p>
31
+ <h2 class="tmk-title" id={`${id}-title`} data-reveal>{data.title}</h2>
32
+ {data.subtitle && <p class="tmk-sub" data-reveal>{data.subtitle}</p>}
33
+
34
+ <div class="tmk-grid">
35
+ {data.items.map((item, i) => (
36
+ <article class="tmk-card" data-reveal style={`--d:${(i % 4) + 1}`}>
37
+ <span class="tmk-ico" set:html={TRUST_ICONS[item.icon]} />
38
+ <h3 class="tmk-card-t">{item.title}</h3>
39
+ <p class="tmk-card-b">{item.body}</p>
40
+ </article>
41
+ ))}
42
+ </div>
43
+
44
+ {data.sampleDeliverable && (
45
+ <div class="tmk-sample" data-reveal>
46
+ <div class="tmk-sample-copy">
47
+ <p class="tmk-sample-eyebrow">{data.sampleDeliverable.eyebrow}</p>
48
+ <h3 class="tmk-sample-t">{data.sampleDeliverable.title}</h3>
49
+ <p class="tmk-sample-cap">{data.sampleDeliverable.caption}</p>
50
+ </div>
51
+ <div class="tmk-sample-media">
52
+ {hasSampleSlot ? (
53
+ <slot name="sample-deliverable" />
54
+ ) : data.sampleDeliverable.image ? (
55
+ <img class="tmk-sample-img" src={data.sampleDeliverable.image} alt={data.sampleDeliverable.title} loading="lazy" />
56
+ ) : null}
57
+ </div>
58
+ </div>
59
+ )}
60
+
61
+ {data.logos && (
62
+ <div class="tmk-logos" data-reveal>
63
+ <p class="tmk-logos-label">{data.logos.label}</p>
64
+ <div class="tmk-logos-row">
65
+ {data.logos.items.map((logo) =>
66
+ logo.placeholder ? (
67
+ <span class="tmk-logo tmk-logo--ph" aria-hidden="true">Your logo</span>
68
+ ) : logo.href ? (
69
+ <a class="tmk-logo" href={logo.href} target="_blank" rel="noopener">{logo.name}</a>
70
+ ) : (
71
+ <span class="tmk-logo">{logo.name}</span>
72
+ ),
73
+ )}
74
+ </div>
75
+ {data.logos.note && <p class="tmk-ph-note">{data.logos.note}</p>}
76
+ </div>
77
+ )}
78
+
79
+ {data.testimonials && (
80
+ <div class="tmk-quotes" data-reveal>
81
+ <p class="tmk-logos-label">{data.testimonials.label}</p>
82
+ <div class="tmk-quotes-row">
83
+ {data.testimonials.items.map((t) => (
84
+ <figure class={`tmk-quote${t.placeholder ? ' tmk-quote--ph' : ''}`}>
85
+ {t.placeholder && <span class="tmk-ph-tag">Placeholder</span>}
86
+ <blockquote class="tmk-quote-b">{t.quote}</blockquote>
87
+ <figcaption class="tmk-quote-cite">
88
+ <span class="tmk-quote-name">{t.authorName}</span>
89
+ {t.authorRole && <span class="tmk-quote-role">{t.authorRole}</span>}
90
+ </figcaption>
91
+ </figure>
92
+ ))}
93
+ </div>
94
+ {data.testimonials.note && <p class="tmk-ph-note">{data.testimonials.note}</p>}
95
+ </div>
96
+ )}
97
+
98
+ {data.foundingPartner && (
99
+ <aside class="tmk-founding" data-reveal>
100
+ <div class="tmk-founding-body">
101
+ <p class="tmk-founding-eyebrow">{data.foundingPartner.eyebrow}</p>
102
+ <h3 class="tmk-founding-t">{data.foundingPartner.title}</h3>
103
+ <p class="tmk-founding-b">{data.foundingPartner.body}</p>
104
+ <ul class="tmk-founding-perks">
105
+ {data.foundingPartner.perks.map((perk) => <li>{perk}</li>)}
106
+ </ul>
107
+ </div>
108
+ {data.foundingPartner.cta && (
109
+ <a class="tmk-founding-cta" {...ctaAttrs(data.foundingPartner.cta)}>
110
+ {data.foundingPartner.cta.label}
111
+ </a>
112
+ )}
113
+ </aside>
114
+ )}
115
+
116
+ {data.founder && (
117
+ <figure class="tmk-founder" data-reveal>
118
+ {data.founder.avatar ? (
119
+ <img class="tmk-founder-av" src={data.founder.avatar} alt={data.founder.name ?? 'Founder'} loading="lazy" />
120
+ ) : (
121
+ <span class="tmk-founder-av tmk-founder-av--ph" aria-hidden="true">
122
+ {(data.founder.name ?? '·').trim().charAt(0)}
123
+ </span>
124
+ )}
125
+ <figcaption class="tmk-founder-cap">
126
+ <p class="tmk-founder-line">{data.founder.line}</p>
127
+ {(data.founder.name || data.founder.role) && (
128
+ <p class="tmk-founder-cite">
129
+ {data.founder.name && <span class="tmk-founder-name">{data.founder.name}</span>}
130
+ {data.founder.role && <span class="tmk-founder-role">{data.founder.role}</span>}
131
+ </p>
132
+ )}
133
+ </figcaption>
134
+ </figure>
135
+ )}
136
+
137
+ {data.builtBy && (
138
+ <p class="tmk-builtby" data-reveal>
139
+ {data.builtBy.label}
140
+ <a href={data.builtBy.href} target="_blank" rel="noopener">{data.builtBy.name}</a>
141
+ </p>
142
+ )}
143
+ </div>
144
+ </section>
145
+
146
+ <style>
147
+ .tmk-trust {
148
+ --_brand: var(--brand, #d8332a);
149
+ --_accent: var(--accent, #f5a300);
150
+ --_ink: var(--ink, #0a0a1f);
151
+ --_paper: var(--paper, #fff);
152
+ --_bg: var(--bg, #fbf9f4);
153
+ --_bg-tint: var(--bg-tint, #f1ede1);
154
+ --_muted: var(--muted, rgba(10, 10, 31, 0.62));
155
+ --_hairline: var(--hairline, rgba(10, 10, 31, 0.1));
156
+ --_r-md: var(--radius-md, 14px);
157
+ --_r-lg: var(--radius-lg, 24px);
158
+ --_shadow: var(--shadow, 0 30px 60px -30px rgba(10, 10, 31, 0.4));
159
+ padding: 96px 0;
160
+ background: var(--_paper);
161
+ border-top: 1px solid var(--_hairline);
162
+ border-bottom: 1px solid var(--_hairline);
163
+ }
164
+ .tmk-container {
165
+ width: min(1200px, 100% - 48px);
166
+ margin-inline: auto;
167
+ }
168
+ .tmk-eyebrow {
169
+ font-family: 'Oswald', sans-serif;
170
+ font-size: 12px;
171
+ font-weight: 600;
172
+ letter-spacing: 0.22em;
173
+ text-transform: uppercase;
174
+ color: var(--_brand);
175
+ margin: 0;
176
+ }
177
+ .tmk-title {
178
+ font-family: 'Oswald', 'Inter', sans-serif;
179
+ font-size: clamp(30px, 3.8vw, 46px);
180
+ font-weight: 700;
181
+ line-height: 1.08;
182
+ letter-spacing: -0.01em;
183
+ margin: 12px 0 14px;
184
+ max-width: 22ch;
185
+ color: var(--_ink);
186
+ }
187
+ .tmk-sub {
188
+ color: var(--_muted);
189
+ max-width: 60ch;
190
+ margin: 0 0 44px;
191
+ }
192
+
193
+ /* Cards --------------------------------------------------------------- */
194
+ .tmk-grid {
195
+ display: grid;
196
+ grid-template-columns: repeat(4, 1fr);
197
+ gap: 18px;
198
+ }
199
+ @media (max-width: 1024px) { .tmk-grid { grid-template-columns: repeat(2, 1fr); } }
200
+ @media (max-width: 560px) { .tmk-grid { grid-template-columns: 1fr; } }
201
+ .tmk-card {
202
+ position: relative;
203
+ padding: 26px 22px;
204
+ border-radius: var(--_r-md);
205
+ background: var(--_bg);
206
+ border: 1px solid var(--_hairline);
207
+ transition: transform 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
208
+ }
209
+ .tmk-card:hover {
210
+ transform: translateY(-4px);
211
+ box-shadow: var(--_shadow);
212
+ border-color: transparent;
213
+ }
214
+ .tmk-ico {
215
+ display: inline-grid;
216
+ place-items: center;
217
+ width: 44px;
218
+ height: 44px;
219
+ border-radius: 12px;
220
+ background: color-mix(in srgb, var(--_brand) 10%, transparent);
221
+ color: var(--_brand);
222
+ margin-bottom: 16px;
223
+ }
224
+ .tmk-ico :global(svg) { width: 22px; height: 22px; }
225
+ .tmk-card-t {
226
+ font-family: 'Oswald', 'Inter', sans-serif;
227
+ font-size: 18px;
228
+ font-weight: 600;
229
+ margin: 0 0 8px;
230
+ color: var(--_ink);
231
+ }
232
+ .tmk-card-b { color: var(--_muted); margin: 0; font-size: 14.5px; }
233
+
234
+ /* Logos --------------------------------------------------------------- */
235
+ .tmk-logos { margin-top: 52px; }
236
+ .tmk-logos-label {
237
+ font-family: 'Oswald', sans-serif;
238
+ font-size: 12px;
239
+ letter-spacing: 0.2em;
240
+ text-transform: uppercase;
241
+ color: var(--_muted);
242
+ margin: 0 0 18px;
243
+ text-align: center;
244
+ }
245
+ .tmk-logos-row {
246
+ display: flex;
247
+ align-items: center;
248
+ justify-content: center;
249
+ flex-wrap: wrap;
250
+ gap: 14px 18px;
251
+ }
252
+ .tmk-logo {
253
+ font-family: 'Oswald', sans-serif;
254
+ font-weight: 600;
255
+ font-size: 17px;
256
+ letter-spacing: 0.02em;
257
+ color: var(--_ink);
258
+ padding: 12px 22px;
259
+ border-radius: var(--_r-md);
260
+ background: var(--_bg-tint);
261
+ border: 1px solid var(--_hairline);
262
+ transition: color 0.14s ease, border-color 0.14s ease;
263
+ }
264
+ a.tmk-logo:hover { color: var(--_brand); border-color: var(--_brand); }
265
+ .tmk-logo--ph {
266
+ color: var(--_muted);
267
+ background: transparent;
268
+ border: 1px dashed var(--_hairline);
269
+ opacity: 0.75;
270
+ }
271
+
272
+ /* Testimonials -------------------------------------------------------- */
273
+ .tmk-quotes { margin-top: 52px; }
274
+ .tmk-quotes-row {
275
+ display: grid;
276
+ grid-template-columns: repeat(3, 1fr);
277
+ gap: 18px;
278
+ }
279
+ @media (max-width: 900px) { .tmk-quotes-row { grid-template-columns: 1fr; } }
280
+ .tmk-quote {
281
+ position: relative;
282
+ padding: 26px 24px 22px;
283
+ border-radius: var(--_r-md);
284
+ background: var(--_bg);
285
+ border: 1px solid var(--_hairline);
286
+ }
287
+ .tmk-quote--ph { border-style: dashed; background: transparent; }
288
+ .tmk-ph-tag {
289
+ position: absolute;
290
+ top: 14px;
291
+ right: 14px;
292
+ font-family: 'Oswald', sans-serif;
293
+ font-size: 9.5px;
294
+ font-weight: 600;
295
+ letter-spacing: 0.14em;
296
+ text-transform: uppercase;
297
+ color: var(--_muted);
298
+ background: var(--_bg-tint);
299
+ padding: 3px 8px;
300
+ border-radius: 999px;
301
+ }
302
+ .tmk-quote-b {
303
+ margin: 0 0 16px;
304
+ font-size: 16px;
305
+ line-height: 1.5;
306
+ color: var(--_ink);
307
+ }
308
+ .tmk-quote--ph .tmk-quote-b { color: var(--_muted); }
309
+ .tmk-quote-b::before { content: '“'; color: var(--_brand); font-weight: 700; }
310
+ .tmk-quote-cite { font-style: normal; }
311
+ .tmk-quote-name {
312
+ display: block;
313
+ font-family: 'Oswald', sans-serif;
314
+ font-weight: 600;
315
+ font-size: 14.5px;
316
+ color: var(--_ink);
317
+ }
318
+ .tmk-quote-role { display: block; font-size: 12.5px; color: var(--_muted); }
319
+
320
+ .tmk-ph-note {
321
+ text-align: center;
322
+ color: var(--_muted);
323
+ font-size: 12.5px;
324
+ margin: 16px 0 0;
325
+ font-style: italic;
326
+ }
327
+
328
+ /* Sample deliverable -------------------------------------------------- */
329
+ .tmk-sample {
330
+ margin-top: 52px;
331
+ display: grid;
332
+ grid-template-columns: 0.92fr 1.08fr;
333
+ gap: 34px;
334
+ align-items: center;
335
+ padding: 30px;
336
+ border-radius: var(--_r-lg);
337
+ background: var(--_bg);
338
+ border: 1px solid var(--_hairline);
339
+ }
340
+ @media (max-width: 860px) {
341
+ .tmk-sample { grid-template-columns: 1fr; gap: 24px; padding: 24px; }
342
+ }
343
+ .tmk-sample-eyebrow {
344
+ font-family: 'Oswald', sans-serif;
345
+ font-size: 11px;
346
+ font-weight: 600;
347
+ letter-spacing: 0.2em;
348
+ text-transform: uppercase;
349
+ color: var(--_brand);
350
+ margin: 0 0 8px;
351
+ }
352
+ .tmk-sample-t {
353
+ font-family: 'Oswald', 'Inter', sans-serif;
354
+ font-size: clamp(20px, 2.4vw, 26px);
355
+ font-weight: 700;
356
+ line-height: 1.14;
357
+ margin: 0 0 10px;
358
+ color: var(--_ink);
359
+ }
360
+ .tmk-sample-cap { color: var(--_muted); margin: 0; font-size: 14.5px; }
361
+ .tmk-sample-media { min-width: 0; }
362
+ .tmk-sample-img {
363
+ display: block;
364
+ width: 100%;
365
+ height: auto;
366
+ border-radius: var(--_r-md);
367
+ border: 1px solid var(--_hairline);
368
+ }
369
+
370
+ /* Founding-partner panel ---------------------------------------------- */
371
+ .tmk-founding {
372
+ margin-top: 52px;
373
+ display: flex;
374
+ align-items: center;
375
+ justify-content: space-between;
376
+ gap: 30px;
377
+ flex-wrap: wrap;
378
+ padding: 30px 32px;
379
+ border-radius: var(--_r-lg);
380
+ background: var(--_ink);
381
+ color: var(--_paper);
382
+ border: 1px solid var(--_ink);
383
+ }
384
+ .tmk-founding-body { flex: 1 1 420px; }
385
+ .tmk-founding-eyebrow {
386
+ font-family: 'Oswald', sans-serif;
387
+ font-size: 11px;
388
+ font-weight: 600;
389
+ letter-spacing: 0.2em;
390
+ text-transform: uppercase;
391
+ color: var(--_accent);
392
+ margin: 0 0 8px;
393
+ }
394
+ .tmk-founding-t {
395
+ font-family: 'Oswald', 'Inter', sans-serif;
396
+ font-size: clamp(22px, 2.6vw, 28px);
397
+ font-weight: 700;
398
+ line-height: 1.12;
399
+ margin: 0 0 10px;
400
+ color: var(--_paper);
401
+ }
402
+ .tmk-founding-b {
403
+ color: rgba(255, 255, 255, 0.78);
404
+ margin: 0 0 16px;
405
+ font-size: 14.5px;
406
+ max-width: 60ch;
407
+ }
408
+ .tmk-founding-perks {
409
+ list-style: none;
410
+ padding: 0;
411
+ margin: 0;
412
+ display: grid;
413
+ grid-template-columns: repeat(2, minmax(0, 1fr));
414
+ gap: 8px 22px;
415
+ }
416
+ @media (max-width: 560px) { .tmk-founding-perks { grid-template-columns: 1fr; } }
417
+ .tmk-founding-perks li {
418
+ position: relative;
419
+ padding-left: 22px;
420
+ color: rgba(255, 255, 255, 0.9);
421
+ font-size: 13.8px;
422
+ }
423
+ .tmk-founding-perks li::before {
424
+ content: '';
425
+ position: absolute;
426
+ left: 0;
427
+ top: 7px;
428
+ width: 8px;
429
+ height: 8px;
430
+ border-radius: 50%;
431
+ background: var(--_accent);
432
+ }
433
+ .tmk-founding-cta {
434
+ box-sizing: border-box;
435
+ min-height: var(--tmk-min-target);
436
+ min-width: var(--tmk-min-target);
437
+ display: inline-flex;
438
+ align-items: center;
439
+ justify-content: center;
440
+ flex-shrink: 0;
441
+ padding: 14px 24px;
442
+ border-radius: 999px;
443
+ background: var(--_accent);
444
+ color: var(--_ink);
445
+ font-family: 'Inter', system-ui, sans-serif;
446
+ font-weight: 700;
447
+ font-size: 14.5px;
448
+ letter-spacing: 0.01em;
449
+ text-decoration: none;
450
+ border: 1px solid transparent;
451
+ transition: transform 0.12s ease, box-shadow 0.12s ease;
452
+ cursor: pointer;
453
+ }
454
+ .tmk-founding-cta:hover {
455
+ transform: translateY(-1px);
456
+ box-shadow: 0 12px 26px -12px rgba(0, 0, 0, 0.6);
457
+ }
458
+ .tmk-founding-cta:focus-visible {
459
+ outline: 2px solid var(--_accent);
460
+ outline-offset: 3px;
461
+ }
462
+
463
+ /* Founder line -------------------------------------------------------- */
464
+ .tmk-founder {
465
+ margin: 40px 0 0;
466
+ display: flex;
467
+ align-items: center;
468
+ gap: 16px;
469
+ max-width: 78ch;
470
+ }
471
+ .tmk-founder-av {
472
+ flex-shrink: 0;
473
+ width: 52px;
474
+ height: 52px;
475
+ border-radius: 50%;
476
+ object-fit: cover;
477
+ border: 1px solid var(--_hairline);
478
+ }
479
+ .tmk-founder-av--ph {
480
+ display: inline-grid;
481
+ place-items: center;
482
+ background: color-mix(in srgb, var(--_brand) 12%, transparent);
483
+ color: var(--_brand);
484
+ font-family: 'Oswald', sans-serif;
485
+ font-weight: 700;
486
+ font-size: 20px;
487
+ text-transform: uppercase;
488
+ }
489
+ .tmk-founder-cap { margin: 0; }
490
+ .tmk-founder-line {
491
+ margin: 0;
492
+ color: var(--_ink);
493
+ font-size: 15.5px;
494
+ line-height: 1.5;
495
+ }
496
+ .tmk-founder-cite { margin: 4px 0 0; }
497
+ .tmk-founder-name {
498
+ font-family: 'Oswald', sans-serif;
499
+ font-weight: 600;
500
+ font-size: 13.5px;
501
+ color: var(--_ink);
502
+ }
503
+ .tmk-founder-role {
504
+ font-size: 12.5px;
505
+ color: var(--_muted);
506
+ margin-left: 8px;
507
+ }
508
+
509
+ /* Built by ------------------------------------------------------------ */
510
+ .tmk-builtby {
511
+ margin: 48px 0 0;
512
+ text-align: center;
513
+ color: var(--_muted);
514
+ font-size: 13px;
515
+ }
516
+ .tmk-builtby a {
517
+ color: var(--_ink);
518
+ border-bottom: 1px dotted var(--_muted);
519
+ margin-left: 5px;
520
+ }
521
+ .tmk-builtby a:hover { color: var(--_brand); }
522
+
523
+ @media (max-width: 560px) { .tmk-trust { padding: 64px 0; } }
524
+ </style>