@dloizides/marketing-astro-kit 1.4.0 → 1.5.1
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/package.json +54 -54
- package/src/TrustSection.astro +530 -524
- package/src/a11y.css +46 -22
package/package.json
CHANGED
|
@@ -1,54 +1,54 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@dloizides/marketing-astro-kit",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Reusable, themeable Astro marketing sections for product sites — a Free-vs-Pro pricing comparison table, a trust / credibility section (security cards, customer-logo + testimonial placeholders, discreet built-by), a client-side \"try it\" demo shell, and an SEO guides/content-hub card + frontmatter schema. Data-driven via a shared TypeScript schema; themed entirely through the host site's CSS custom properties.",
|
|
5
|
-
"keywords": [
|
|
6
|
-
"astro",
|
|
7
|
-
"marketing",
|
|
8
|
-
"pricing",
|
|
9
|
-
"comparison-table",
|
|
10
|
-
"trust",
|
|
11
|
-
"demo",
|
|
12
|
-
"guides",
|
|
13
|
-
"content-hub",
|
|
14
|
-
"seo",
|
|
15
|
-
"landing-page",
|
|
16
|
-
"saas",
|
|
17
|
-
"hero",
|
|
18
|
-
"background",
|
|
19
|
-
"canvas",
|
|
20
|
-
"animation"
|
|
21
|
-
],
|
|
22
|
-
"author": "dloizides",
|
|
23
|
-
"license": "MIT",
|
|
24
|
-
"type": "module",
|
|
25
|
-
"repository": {
|
|
26
|
-
"type": "git",
|
|
27
|
-
"url": "https://github.com/openmindednewby/marketing-astro-kit.git"
|
|
28
|
-
},
|
|
29
|
-
"files": [
|
|
30
|
-
"src",
|
|
31
|
-
"README.md",
|
|
32
|
-
"CHANGELOG.md"
|
|
33
|
-
],
|
|
34
|
-
"exports": {
|
|
35
|
-
"./PricingComparison.astro": "./src/PricingComparison.astro",
|
|
36
|
-
"./TrustSection.astro": "./src/TrustSection.astro",
|
|
37
|
-
"./PrimaryCta.astro": "./src/PrimaryCta.astro",
|
|
38
|
-
"./DemoFrame.astro": "./src/DemoFrame.astro",
|
|
39
|
-
"./GuideCard.astro": "./src/GuideCard.astro",
|
|
40
|
-
"./schema": "./src/schema.ts",
|
|
41
|
-
"./a11y.css": "./src/a11y.css",
|
|
42
|
-
"./icons": "./src/icons.ts",
|
|
43
|
-
"./HeroBackdrop.astro": "./src/HeroBackdrop.astro",
|
|
44
|
-
"./heroBackdrop": "./src/heroBackdrop/presets.ts",
|
|
45
|
-
"./heroBackdrop/types": "./src/heroBackdrop/types.ts"
|
|
46
|
-
},
|
|
47
|
-
"peerDependencies": {
|
|
48
|
-
"astro": ">=4"
|
|
49
|
-
},
|
|
50
|
-
"sideEffects": false,
|
|
51
|
-
"engines": {
|
|
52
|
-
"node": ">=18.0.0"
|
|
53
|
-
}
|
|
54
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@dloizides/marketing-astro-kit",
|
|
3
|
+
"version": "1.5.1",
|
|
4
|
+
"description": "Reusable, themeable Astro marketing sections for product sites — a Free-vs-Pro pricing comparison table, a trust / credibility section (security cards, customer-logo + testimonial placeholders, discreet built-by), a client-side \"try it\" demo shell, and an SEO guides/content-hub card + frontmatter schema. Data-driven via a shared TypeScript schema; themed entirely through the host site's CSS custom properties.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"astro",
|
|
7
|
+
"marketing",
|
|
8
|
+
"pricing",
|
|
9
|
+
"comparison-table",
|
|
10
|
+
"trust",
|
|
11
|
+
"demo",
|
|
12
|
+
"guides",
|
|
13
|
+
"content-hub",
|
|
14
|
+
"seo",
|
|
15
|
+
"landing-page",
|
|
16
|
+
"saas",
|
|
17
|
+
"hero",
|
|
18
|
+
"background",
|
|
19
|
+
"canvas",
|
|
20
|
+
"animation"
|
|
21
|
+
],
|
|
22
|
+
"author": "dloizides",
|
|
23
|
+
"license": "MIT",
|
|
24
|
+
"type": "module",
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/openmindednewby/marketing-astro-kit.git"
|
|
28
|
+
},
|
|
29
|
+
"files": [
|
|
30
|
+
"src",
|
|
31
|
+
"README.md",
|
|
32
|
+
"CHANGELOG.md"
|
|
33
|
+
],
|
|
34
|
+
"exports": {
|
|
35
|
+
"./PricingComparison.astro": "./src/PricingComparison.astro",
|
|
36
|
+
"./TrustSection.astro": "./src/TrustSection.astro",
|
|
37
|
+
"./PrimaryCta.astro": "./src/PrimaryCta.astro",
|
|
38
|
+
"./DemoFrame.astro": "./src/DemoFrame.astro",
|
|
39
|
+
"./GuideCard.astro": "./src/GuideCard.astro",
|
|
40
|
+
"./schema": "./src/schema.ts",
|
|
41
|
+
"./a11y.css": "./src/a11y.css",
|
|
42
|
+
"./icons": "./src/icons.ts",
|
|
43
|
+
"./HeroBackdrop.astro": "./src/HeroBackdrop.astro",
|
|
44
|
+
"./heroBackdrop": "./src/heroBackdrop/presets.ts",
|
|
45
|
+
"./heroBackdrop/types": "./src/heroBackdrop/types.ts"
|
|
46
|
+
},
|
|
47
|
+
"peerDependencies": {
|
|
48
|
+
"astro": ">=4"
|
|
49
|
+
},
|
|
50
|
+
"sideEffects": false,
|
|
51
|
+
"engines": {
|
|
52
|
+
"node": ">=18.0.0"
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/TrustSection.astro
CHANGED
|
@@ -1,524 +1,530 @@
|
|
|
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-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
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 './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
|
+
/* 44px hit box (a11y.css --tmk-min-target) without moving the line: the
|
|
517
|
+
vertical padding is cancelled by an equal negative margin. */
|
|
518
|
+
.tmk-builtby a {
|
|
519
|
+
display: inline-block;
|
|
520
|
+
padding-block: 14px;
|
|
521
|
+
margin-block: -14px;
|
|
522
|
+
color: var(--_ink);
|
|
523
|
+
text-decoration: underline dotted var(--_muted);
|
|
524
|
+
text-underline-offset: 3px;
|
|
525
|
+
margin-left: 5px;
|
|
526
|
+
}
|
|
527
|
+
.tmk-builtby a:hover { color: var(--_brand); }
|
|
528
|
+
|
|
529
|
+
@media (max-width: 560px) { .tmk-trust { padding: 64px 0; } }
|
|
530
|
+
</style>
|
package/src/a11y.css
CHANGED
|
@@ -1,22 +1,46 @@
|
|
|
1
|
-
/* Minimum touch-target floor for every interactive box in this kit.
|
|
2
|
-
*
|
|
3
|
-
* SOURCE OF TRUTH: `MIN_TARGET_PX` in @dloizides/ui-layout
|
|
4
|
-
* (v1.27.0, src/constants.ts:134). It is re-declared here as a CSS custom
|
|
5
|
-
* property rather than imported, deliberately:
|
|
6
|
-
*
|
|
7
|
-
* 1. ui-layout is a React Native / RN-web package. Its peer dependencies are
|
|
8
|
-
* react, react-dom, react-native, react-native-svg and three more
|
|
9
|
-
* @dloizides UI packages. This kit is a zero-dependency static Astro
|
|
10
|
-
* source distribution (one peer: astro). Pulling that stack in for one
|
|
11
|
-
* integer is the wrong trade.
|
|
12
|
-
* 2. A CSS `min-height` cannot read a JS constant anyway. The value has to
|
|
13
|
-
* exist as CSS somewhere, so the only question is how many times — and
|
|
14
|
-
* this file is the one place.
|
|
15
|
-
*
|
|
16
|
-
* Keep the two in sync: if ui-layout's MIN_TARGET_PX changes, change this.
|
|
17
|
-
* A host may RAISE this (e.g. a touch-heavy kiosk build); it must never lower
|
|
18
|
-
* it below 44px, which is the WCAG 2.2 AA target-size floor.
|
|
19
|
-
*/
|
|
20
|
-
:root {
|
|
21
|
-
--tmk-min-target: 44px;
|
|
22
|
-
}
|
|
1
|
+
/* Minimum touch-target floor for every interactive box in this kit.
|
|
2
|
+
*
|
|
3
|
+
* SOURCE OF TRUTH: `MIN_TARGET_PX` in @dloizides/ui-layout
|
|
4
|
+
* (v1.27.0, src/constants.ts:134). It is re-declared here as a CSS custom
|
|
5
|
+
* property rather than imported, deliberately:
|
|
6
|
+
*
|
|
7
|
+
* 1. ui-layout is a React Native / RN-web package. Its peer dependencies are
|
|
8
|
+
* react, react-dom, react-native, react-native-svg and three more
|
|
9
|
+
* @dloizides UI packages. This kit is a zero-dependency static Astro
|
|
10
|
+
* source distribution (one peer: astro). Pulling that stack in for one
|
|
11
|
+
* integer is the wrong trade.
|
|
12
|
+
* 2. A CSS `min-height` cannot read a JS constant anyway. The value has to
|
|
13
|
+
* exist as CSS somewhere, so the only question is how many times — and
|
|
14
|
+
* this file is the one place.
|
|
15
|
+
*
|
|
16
|
+
* Keep the two in sync: if ui-layout's MIN_TARGET_PX changes, change this.
|
|
17
|
+
* A host may RAISE this (e.g. a touch-heavy kiosk build); it must never lower
|
|
18
|
+
* it below 44px, which is the WCAG 2.2 AA target-size floor.
|
|
19
|
+
*/
|
|
20
|
+
:root {
|
|
21
|
+
--tmk-min-target: 44px;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/* ---------------------------------------------------------------------------
|
|
25
|
+
* TOPNAV TOUCH TARGETS
|
|
26
|
+
*
|
|
27
|
+
* The site header is hand-rolled per marketing site (agora / ichnos / kefi each
|
|
28
|
+
* own their own `src/components/SiteNav.astro`) but all three emit the SAME
|
|
29
|
+
* class names, and none of them sets a min-height. Measured at 360x640 on the
|
|
30
|
+
* deployed sites the brand link came out 36px tall and the nav CTA 41px, on all
|
|
31
|
+
* three identically. Because the defect is in shared markup conventions rather
|
|
32
|
+
* than in a shared component, the fix is a selector here rather than a new
|
|
33
|
+
* component: a site adopts it by importing this file once from its base layout.
|
|
34
|
+
*
|
|
35
|
+
* The per-site Astro scoped styles only set colour, font and gap on these
|
|
36
|
+
* selectors, so there is no min-height to fight; source order decides and this
|
|
37
|
+
* file is imported last.
|
|
38
|
+
* ------------------------------------------------------------------------- */
|
|
39
|
+
.topnav .brand,
|
|
40
|
+
.topnav__links > a {
|
|
41
|
+
display: inline-flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
justify-content: center;
|
|
44
|
+
min-height: var(--tmk-min-target);
|
|
45
|
+
min-width: var(--tmk-min-target);
|
|
46
|
+
}
|