@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,428 +1,433 @@
1
- ---
2
- // Reusable "Free-vs-Pro" pricing comparison table for product marketing sites.
3
- // Data-driven (see schema.ts → PricingComparisonData); themed purely through
4
- // the host site's CSS custom properties. Drop-in for any Astro marketing site.
5
- //
6
- // <PricingComparison data={pricing} id="pricing" />
7
- //
8
- // The host page must provide the `[data-contact]` mailto-reveal handler for any
9
- // CTA with `kind: 'contact'` (the scaffold + kefi-marketing already do).
10
- //
11
- // `ctaAttrs` (link vs spam-safe contact + analytics wiring) is shared from
12
- // schema.ts so PrimaryCta.astro renders CTAs identically.
13
- import type { PricingComparisonData } from './schema';
14
- import { ctaAttrs } from './schema';
15
-
16
- interface Props {
17
- data: PricingComparisonData;
18
- id?: string;
19
- }
20
-
21
- const { data, id = 'pricing' } = Astro.props as Props;
22
-
23
- const { tiers, groups } = data;
24
- ---
25
-
26
- <section class={`pmk-pricing`} id={id} aria-labelledby={`${id}-title`}>
27
- <div class="pmk-container">
28
- <p class="pmk-eyebrow" data-reveal>{data.eyebrow}</p>
29
- <h2 class="pmk-title" id={`${id}-title`} data-reveal>{data.title}</h2>
30
- {data.subtitle && <p class="pmk-sub" data-reveal>{data.subtitle}</p>}
31
-
32
- <div class="pmk-tablewrap" data-reveal>
33
- <table class="pmk-table">
34
- <caption class="pmk-visually-hidden">Plan feature comparison</caption>
35
- <thead>
36
- <tr>
37
- <th scope="col" class="pmk-th-corner"><span class="pmk-visually-hidden">Feature</span></th>
38
- {tiers.map((t) => (
39
- <th scope="col" class={`pmk-th${t.featured ? ' is-featured' : ''}`}>
40
- {t.badge && <span class="pmk-ribbon">{t.badge}</span>}
41
- <span class="pmk-tier-name">{t.name}</span>
42
- <span class="pmk-tier-price">
43
- <b>{t.price}</b><i>{t.priceUnit}</i>
44
- </span>
45
- {t.tagline && <span class="pmk-tier-tag">{t.tagline}</span>}
46
- <a class={`pmk-cta${t.featured ? ' pmk-cta--brand' : ' pmk-cta--ink'}`} {...ctaAttrs(t.cta)}>
47
- {t.cta.label}
48
- </a>
49
- </th>
50
- ))}
51
- </tr>
52
- </thead>
53
- <tbody>
54
- {groups.map((group) => (
55
- <>
56
- {group.heading && (
57
- <tr class="pmk-grouprow">
58
- <th scope="colgroup" colspan={tiers.length + 1}>{group.heading}</th>
59
- </tr>
60
- )}
61
- {group.rows.map((row) => (
62
- <tr class="pmk-row">
63
- <th scope="row" class="pmk-rowlabel">
64
- <span class="pmk-rowlabel-t">{row.label}</span>
65
- {row.hint && <span class="pmk-rowlabel-h">{row.hint}</span>}
66
- </th>
67
- {row.cells.map((cell, ci) => (
68
- <td
69
- class={`pmk-cell${tiers[ci]?.featured ? ' is-featured' : ''}`}
70
- data-label={tiers[ci]?.name}
71
- >
72
- {typeof cell === 'boolean' ? (
73
- cell ? (
74
- <span class="pmk-yes" role="img" aria-label="Included">
75
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7" /></svg>
76
- </span>
77
- ) : (
78
- <span class="pmk-no" role="img" aria-label="Not included">
79
- <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M7 7l10 10M17 7L7 17" /></svg>
80
- </span>
81
- )
82
- ) : (
83
- <span class="pmk-val">{cell}</span>
84
- )}
85
- </td>
86
- ))}
87
- </tr>
88
- ))}
89
- </>
90
- ))}
91
- </tbody>
92
- </table>
93
- </div>
94
-
95
- {data.footnote && <p class="pmk-footnote" data-reveal>{data.footnote}</p>}
96
-
97
- {data.callout && (
98
- <aside class="pmk-callout" data-reveal>
99
- <div class="pmk-callout-body">
100
- {data.callout.badge && <span class="pmk-callout-badge">{data.callout.badge}</span>}
101
- <h3 class="pmk-callout-name">{data.callout.name}</h3>
102
- <p class="pmk-callout-price"><b>{data.callout.price}</b> <i>{data.callout.priceUnit}</i></p>
103
- {data.callout.tagline && <p class="pmk-callout-tag">{data.callout.tagline}</p>}
104
- <ul class="pmk-callout-list">
105
- {data.callout.bullets.map((b) => <li>{b}</li>)}
106
- </ul>
107
- </div>
108
- <a class="pmk-cta pmk-cta--ink pmk-callout-cta" {...ctaAttrs(data.callout.cta)}>
109
- {data.callout.cta.label}
110
- </a>
111
- </aside>
112
- )}
113
- </div>
114
- </section>
115
-
116
- <style>
117
- /* Themed via host CSS vars (fallbacks keep it rendering standalone). */
118
- .pmk-pricing {
119
- --_brand: var(--brand, #d8332a);
120
- --_brand-deep: var(--brand-deep, #a8231c);
121
- --_accent: var(--accent, #f5a300);
122
- --_ink: var(--ink, #0a0a1f);
123
- --_paper: var(--paper, #fff);
124
- --_bg: var(--bg, #fbf9f4);
125
- --_bg-tint: var(--bg-tint, #f1ede1);
126
- --_muted: var(--muted, rgba(10, 10, 31, 0.62));
127
- --_hairline: var(--hairline, rgba(10, 10, 31, 0.1));
128
- --_r-lg: var(--radius-lg, 24px);
129
- --_r-md: var(--radius-md, 14px);
130
- --_shadow: var(--shadow, 0 30px 60px -30px rgba(10, 10, 31, 0.4));
131
- padding: 96px 0;
132
- }
133
- .pmk-container {
134
- width: min(1200px, 100% - 48px);
135
- margin-inline: auto;
136
- }
137
- .pmk-eyebrow {
138
- font-family: 'Oswald', sans-serif;
139
- font-size: 12px;
140
- font-weight: 600;
141
- letter-spacing: 0.22em;
142
- text-transform: uppercase;
143
- color: var(--_brand);
144
- margin: 0;
145
- }
146
- .pmk-title {
147
- font-family: 'Oswald', 'Inter', sans-serif;
148
- font-size: clamp(30px, 3.8vw, 46px);
149
- font-weight: 700;
150
- line-height: 1.08;
151
- letter-spacing: -0.01em;
152
- margin: 12px 0 14px;
153
- max-width: 22ch;
154
- color: var(--_ink);
155
- }
156
- .pmk-sub {
157
- color: var(--_muted);
158
- max-width: 60ch;
159
- margin: 0 0 40px;
160
- }
161
-
162
- /* Table --------------------------------------------------------------- */
163
- .pmk-tablewrap {
164
- overflow-x: auto;
165
- border-radius: var(--_r-lg);
166
- -webkit-overflow-scrolling: touch;
167
- }
168
- .pmk-table {
169
- width: 100%;
170
- min-width: 640px;
171
- border-collapse: separate;
172
- border-spacing: 0;
173
- table-layout: fixed;
174
- }
175
- .pmk-table caption { text-align: left; }
176
- .pmk-th-corner,
177
- .pmk-rowlabel {
178
- width: 34%;
179
- text-align: left;
180
- }
181
- .pmk-th {
182
- position: relative;
183
- vertical-align: bottom;
184
- padding: 22px 18px 20px;
185
- text-align: center;
186
- background: var(--_paper);
187
- border-top: 1px solid var(--_hairline);
188
- border-bottom: 2px solid var(--_hairline);
189
- }
190
- .pmk-th.is-featured {
191
- background: var(--_ink);
192
- border-radius: var(--_r-md) var(--_r-md) 0 0;
193
- border-color: var(--_ink);
194
- }
195
- .pmk-th-corner {
196
- background: transparent;
197
- border-bottom: 2px solid var(--_hairline);
198
- }
199
- .pmk-ribbon {
200
- position: absolute;
201
- top: -11px;
202
- left: 50%;
203
- transform: translateX(-50%);
204
- background: var(--_brand);
205
- color: var(--_paper);
206
- padding: 4px 12px;
207
- border-radius: 999px;
208
- font-family: 'Oswald', sans-serif;
209
- font-size: 10.5px;
210
- font-weight: 600;
211
- letter-spacing: 0.16em;
212
- text-transform: uppercase;
213
- white-space: nowrap;
214
- }
215
- .pmk-tier-name {
216
- display: block;
217
- font-family: 'Oswald', sans-serif;
218
- font-size: 16px;
219
- font-weight: 600;
220
- letter-spacing: 0.06em;
221
- text-transform: uppercase;
222
- color: var(--_ink);
223
- }
224
- .is-featured .pmk-tier-name { color: var(--_paper); }
225
- .pmk-tier-price {
226
- display: block;
227
- margin: 8px 0 2px;
228
- color: var(--_ink);
229
- }
230
- .pmk-tier-price b {
231
- font-family: 'Oswald', sans-serif;
232
- font-size: 34px;
233
- font-weight: 700;
234
- line-height: 1;
235
- }
236
- .pmk-tier-price i {
237
- font-style: normal;
238
- font-size: 13px;
239
- color: var(--_muted);
240
- margin-left: 4px;
241
- }
242
- .is-featured .pmk-tier-price,
243
- .is-featured .pmk-tier-price b { color: var(--_paper); }
244
- .is-featured .pmk-tier-price i { color: rgba(255, 255, 255, 0.7); }
245
- .pmk-tier-tag {
246
- display: block;
247
- font-size: 12.5px;
248
- color: var(--_muted);
249
- margin-bottom: 14px;
250
- min-height: 1.4em;
251
- }
252
- .is-featured .pmk-tier-tag { color: rgba(255, 255, 255, 0.72); }
253
-
254
- /* CTA (self-contained — does not depend on host .btn) ----------------- */
255
- .pmk-cta {
256
- display: inline-flex;
257
- align-items: center;
258
- justify-content: center;
259
- gap: 8px;
260
- padding: 11px 18px;
261
- border-radius: 999px;
262
- font-family: 'Inter', system-ui, sans-serif;
263
- font-weight: 600;
264
- font-size: 13.5px;
265
- letter-spacing: 0.02em;
266
- border: 1px solid transparent;
267
- cursor: pointer;
268
- transition: transform 0.12s ease, background 0.12s ease, box-shadow 0.12s ease;
269
- text-decoration: none;
270
- }
271
- .pmk-cta:hover { transform: translateY(-1px); }
272
- .pmk-cta--ink { background: var(--_ink); color: var(--_paper); }
273
- .pmk-cta--ink:hover { background: var(--_brand); }
274
- .pmk-cta--brand { background: var(--_brand); color: var(--_paper); }
275
- .pmk-cta--brand:hover { background: var(--_brand-deep); }
276
- .is-featured .pmk-cta--brand { box-shadow: 0 10px 24px -10px rgba(0, 0, 0, 0.5); }
277
-
278
- /* Group + rows -------------------------------------------------------- */
279
- .pmk-grouprow th {
280
- text-align: left;
281
- padding: 22px 18px 8px;
282
- font-family: 'Oswald', sans-serif;
283
- font-size: 11px;
284
- font-weight: 600;
285
- letter-spacing: 0.18em;
286
- text-transform: uppercase;
287
- color: var(--_brand);
288
- }
289
- .pmk-row:hover .pmk-rowlabel,
290
- .pmk-row:hover .pmk-cell:not(.is-featured) {
291
- background: var(--_bg-tint);
292
- }
293
- .pmk-rowlabel {
294
- padding: 15px 18px;
295
- vertical-align: middle;
296
- border-bottom: 1px solid var(--_hairline);
297
- font-weight: 500;
298
- }
299
- .pmk-rowlabel-t { display: block; color: var(--_ink); font-size: 15px; }
300
- .pmk-rowlabel-h { display: block; color: var(--_muted); font-size: 12.5px; margin-top: 2px; }
301
- .pmk-cell {
302
- padding: 15px 18px;
303
- text-align: center;
304
- vertical-align: middle;
305
- border-bottom: 1px solid var(--_hairline);
306
- color: var(--_ink);
307
- }
308
- .pmk-cell.is-featured {
309
- background: color-mix(in srgb, var(--_ink) 5%, transparent);
310
- border-left: 1px solid var(--_hairline);
311
- border-right: 1px solid var(--_hairline);
312
- }
313
- .pmk-val {
314
- font-family: 'Oswald', sans-serif;
315
- font-weight: 600;
316
- font-size: 14px;
317
- letter-spacing: 0.01em;
318
- }
319
- .pmk-yes,
320
- .pmk-no {
321
- display: inline-grid;
322
- place-items: center;
323
- width: 24px;
324
- height: 24px;
325
- border-radius: 50%;
326
- }
327
- .pmk-yes {
328
- background: color-mix(in srgb, var(--_accent) 20%, transparent);
329
- color: var(--_brand-deep);
330
- }
331
- .pmk-yes svg { width: 15px; height: 15px; }
332
- .pmk-no { color: var(--_muted); opacity: 0.5; }
333
- .pmk-no svg { width: 15px; height: 15px; }
334
- /* last row of the featured column gets a rounded bottom */
335
- .pmk-table tbody tr:last-child .pmk-cell.is-featured {
336
- border-radius: 0 0 var(--_r-md) var(--_r-md);
337
- }
338
-
339
- .pmk-footnote {
340
- color: var(--_muted);
341
- font-size: 13.5px;
342
- margin: 18px 2px 0;
343
- }
344
-
345
- /* Concierge / one-time callout --------------------------------------- */
346
- .pmk-callout {
347
- margin-top: 26px;
348
- display: flex;
349
- align-items: center;
350
- justify-content: space-between;
351
- gap: 28px;
352
- flex-wrap: wrap;
353
- padding: 26px 30px;
354
- border-radius: var(--_r-lg);
355
- background: var(--_bg-tint);
356
- border: 1px solid var(--_hairline);
357
- }
358
- .pmk-callout-badge {
359
- display: inline-block;
360
- font-family: 'Oswald', sans-serif;
361
- font-size: 11px;
362
- font-weight: 600;
363
- letter-spacing: 0.16em;
364
- text-transform: uppercase;
365
- color: var(--_ink);
366
- background: var(--_accent);
367
- padding: 4px 10px;
368
- border-radius: 999px;
369
- margin-bottom: 12px;
370
- }
371
- .pmk-callout-name {
372
- font-family: 'Oswald', sans-serif;
373
- font-size: 22px;
374
- font-weight: 700;
375
- margin: 0;
376
- display: inline-block;
377
- }
378
- .pmk-callout-price {
379
- margin: 4px 0 8px;
380
- color: var(--_ink);
381
- }
382
- .pmk-callout-price b { font-family: 'Oswald', sans-serif; font-size: 26px; }
383
- .pmk-callout-price i { font-style: normal; font-size: 13px; color: var(--_muted); }
384
- .pmk-callout-tag { color: var(--_muted); margin: 0 0 10px; font-size: 14.5px; }
385
- .pmk-callout-list {
386
- list-style: none;
387
- padding: 0;
388
- margin: 0;
389
- display: flex;
390
- flex-wrap: wrap;
391
- gap: 6px 22px;
392
- max-width: 62ch;
393
- }
394
- .pmk-callout-list li {
395
- position: relative;
396
- padding-left: 18px;
397
- color: var(--_muted);
398
- font-size: 13.5px;
399
- }
400
- .pmk-callout-list li::before {
401
- content: '';
402
- position: absolute;
403
- left: 0;
404
- top: 8px;
405
- width: 7px;
406
- height: 7px;
407
- border-radius: 50%;
408
- background: var(--_brand);
409
- }
410
- .pmk-callout-cta { white-space: nowrap; flex-shrink: 0; }
411
-
412
- .pmk-visually-hidden {
413
- position: absolute;
414
- width: 1px;
415
- height: 1px;
416
- padding: 0;
417
- margin: -1px;
418
- overflow: hidden;
419
- clip: rect(0 0 0 0);
420
- white-space: nowrap;
421
- border: 0;
422
- }
423
-
424
- @media (max-width: 640px) {
425
- .pmk-pricing { padding: 64px 0; }
426
- .pmk-callout { flex-direction: column; align-items: flex-start; }
427
- }
428
- </style>
1
+ ---
2
+ // Reusable "Free-vs-Pro" pricing comparison table for product marketing sites.
3
+ // Data-driven (see schema.ts → PricingComparisonData); themed purely through
4
+ // the host site's CSS custom properties. Drop-in for any Astro marketing site.
5
+ //
6
+ // <PricingComparison data={pricing} id="pricing" />
7
+ //
8
+ // The host page must provide the `[data-contact]` mailto-reveal handler for any
9
+ // CTA with `kind: 'contact'` (the scaffold + kefi-marketing already do).
10
+ //
11
+ // `ctaAttrs` (link vs spam-safe contact + analytics wiring) is shared from
12
+ // schema.ts so PrimaryCta.astro renders CTAs identically.
13
+ import type { PricingComparisonData } from './schema';
14
+ import './a11y.css';
15
+ import { ctaAttrs } from './schema';
16
+
17
+ interface Props {
18
+ data: PricingComparisonData;
19
+ id?: string;
20
+ }
21
+
22
+ const { data, id = 'pricing' } = Astro.props as Props;
23
+
24
+ const { tiers, groups } = data;
25
+ ---
26
+
27
+ <section class={`pmk-pricing`} id={id} aria-labelledby={`${id}-title`}>
28
+ <div class="pmk-container">
29
+ <p class="pmk-eyebrow" data-reveal>{data.eyebrow}</p>
30
+ <h2 class="pmk-title" id={`${id}-title`} data-reveal>{data.title}</h2>
31
+ {data.subtitle && <p class="pmk-sub" data-reveal>{data.subtitle}</p>}
32
+
33
+ <div class="pmk-tablewrap" data-reveal>
34
+ <table class="pmk-table">
35
+ <caption class="pmk-visually-hidden">Plan feature comparison</caption>
36
+ <thead>
37
+ <tr>
38
+ <th scope="col" class="pmk-th-corner"><span class="pmk-visually-hidden">Feature</span></th>
39
+ {tiers.map((t) => (
40
+ <th scope="col" class={`pmk-th${t.featured ? ' is-featured' : ''}`}>
41
+ {t.badge && <span class="pmk-ribbon">{t.badge}</span>}
42
+ <span class="pmk-tier-name">{t.name}</span>
43
+ <span class="pmk-tier-price">
44
+ <b>{t.price}</b><i>{t.priceUnit}</i>
45
+ </span>
46
+ {t.tagline && <span class="pmk-tier-tag">{t.tagline}</span>}
47
+ <a class={`pmk-cta${t.featured ? ' pmk-cta--brand' : ' pmk-cta--ink'}`} {...ctaAttrs(t.cta)}>
48
+ {t.cta.label}
49
+ </a>
50
+ </th>
51
+ ))}
52
+ </tr>
53
+ </thead>
54
+ <tbody>
55
+ {groups.map((group) => (
56
+ <>
57
+ {group.heading && (
58
+ <tr class="pmk-grouprow">
59
+ <th scope="colgroup" colspan={tiers.length + 1}>{group.heading}</th>
60
+ </tr>
61
+ )}
62
+ {group.rows.map((row) => (
63
+ <tr class="pmk-row">
64
+ <th scope="row" class="pmk-rowlabel">
65
+ <span class="pmk-rowlabel-t">{row.label}</span>
66
+ {row.hint && <span class="pmk-rowlabel-h">{row.hint}</span>}
67
+ </th>
68
+ {row.cells.map((cell, ci) => (
69
+ <td
70
+ class={`pmk-cell${tiers[ci]?.featured ? ' is-featured' : ''}`}
71
+ data-label={tiers[ci]?.name}
72
+ >
73
+ {typeof cell === 'boolean' ? (
74
+ cell ? (
75
+ <span class="pmk-yes" role="img" aria-label="Included">
76
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.4" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M5 12.5l4.5 4.5L19 7" /></svg>
77
+ </span>
78
+ ) : (
79
+ <span class="pmk-no" role="img" aria-label="Not included">
80
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="M7 7l10 10M17 7L7 17" /></svg>
81
+ </span>
82
+ )
83
+ ) : (
84
+ <span class="pmk-val">{cell}</span>
85
+ )}
86
+ </td>
87
+ ))}
88
+ </tr>
89
+ ))}
90
+ </>
91
+ ))}
92
+ </tbody>
93
+ </table>
94
+ </div>
95
+
96
+ {data.footnote && <p class="pmk-footnote" data-reveal>{data.footnote}</p>}
97
+
98
+ {data.callout && (
99
+ <aside class="pmk-callout" data-reveal>
100
+ <div class="pmk-callout-body">
101
+ {data.callout.badge && <span class="pmk-callout-badge">{data.callout.badge}</span>}
102
+ <h3 class="pmk-callout-name">{data.callout.name}</h3>
103
+ <p class="pmk-callout-price"><b>{data.callout.price}</b> <i>{data.callout.priceUnit}</i></p>
104
+ {data.callout.tagline && <p class="pmk-callout-tag">{data.callout.tagline}</p>}
105
+ <ul class="pmk-callout-list">
106
+ {data.callout.bullets.map((b) => <li>{b}</li>)}
107
+ </ul>
108
+ </div>
109
+ <a class="pmk-cta pmk-cta--ink pmk-callout-cta" {...ctaAttrs(data.callout.cta)}>
110
+ {data.callout.cta.label}
111
+ </a>
112
+ </aside>
113
+ )}
114
+ </div>
115
+ </section>
116
+
117
+ <style>
118
+ /* Themed via host CSS vars (fallbacks keep it rendering standalone). */
119
+ .pmk-pricing {
120
+ --_brand: var(--brand, #d8332a);
121
+ --_brand-deep: var(--brand-deep, #a8231c);
122
+ --_accent: var(--accent, #f5a300);
123
+ --_ink: var(--ink, #0a0a1f);
124
+ --_paper: var(--paper, #fff);
125
+ --_bg: var(--bg, #fbf9f4);
126
+ --_bg-tint: var(--bg-tint, #f1ede1);
127
+ --_muted: var(--muted, rgba(10, 10, 31, 0.62));
128
+ --_hairline: var(--hairline, rgba(10, 10, 31, 0.1));
129
+ --_r-lg: var(--radius-lg, 24px);
130
+ --_r-md: var(--radius-md, 14px);
131
+ --_shadow: var(--shadow, 0 30px 60px -30px rgba(10, 10, 31, 0.4));
132
+ padding: 96px 0;
133
+ }
134
+ .pmk-container {
135
+ width: min(1200px, 100% - 48px);
136
+ margin-inline: auto;
137
+ }
138
+ .pmk-eyebrow {
139
+ font-family: 'Oswald', sans-serif;
140
+ font-size: 12px;
141
+ font-weight: 600;
142
+ letter-spacing: 0.22em;
143
+ text-transform: uppercase;
144
+ color: var(--_brand);
145
+ margin: 0;
146
+ }
147
+ .pmk-title {
148
+ font-family: 'Oswald', 'Inter', sans-serif;
149
+ font-size: clamp(30px, 3.8vw, 46px);
150
+ font-weight: 700;
151
+ line-height: 1.08;
152
+ letter-spacing: -0.01em;
153
+ margin: 12px 0 14px;
154
+ max-width: 22ch;
155
+ color: var(--_ink);
156
+ }
157
+ .pmk-sub {
158
+ color: var(--_muted);
159
+ max-width: 60ch;
160
+ margin: 0 0 40px;
161
+ }
162
+
163
+ /* Table --------------------------------------------------------------- */
164
+ .pmk-tablewrap {
165
+ overflow-x: auto;
166
+ border-radius: var(--_r-lg);
167
+ -webkit-overflow-scrolling: touch;
168
+ }
169
+ .pmk-table {
170
+ width: 100%;
171
+ min-width: 640px;
172
+ border-collapse: separate;
173
+ border-spacing: 0;
174
+ table-layout: fixed;
175
+ }
176
+ .pmk-table caption { text-align: left; }
177
+ .pmk-th-corner,
178
+ .pmk-rowlabel {
179
+ width: 34%;
180
+ text-align: left;
181
+ }
182
+ .pmk-th {
183
+ position: relative;
184
+ vertical-align: bottom;
185
+ padding: 22px 18px 20px;
186
+ text-align: center;
187
+ background: var(--_paper);
188
+ border-top: 1px solid var(--_hairline);
189
+ border-bottom: 2px solid var(--_hairline);
190
+ }
191
+ .pmk-th.is-featured {
192
+ background: var(--_ink);
193
+ border-radius: var(--_r-md) var(--_r-md) 0 0;
194
+ border-color: var(--_ink);
195
+ }
196
+ .pmk-th-corner {
197
+ background: transparent;
198
+ border-bottom: 2px solid var(--_hairline);
199
+ }
200
+ .pmk-ribbon {
201
+ position: absolute;
202
+ top: -11px;
203
+ left: 50%;
204
+ transform: translateX(-50%);
205
+ background: var(--_brand);
206
+ color: var(--_paper);
207
+ padding: 4px 12px;
208
+ border-radius: 999px;
209
+ font-family: 'Oswald', sans-serif;
210
+ font-size: 10.5px;
211
+ font-weight: 600;
212
+ letter-spacing: 0.16em;
213
+ text-transform: uppercase;
214
+ white-space: nowrap;
215
+ }
216
+ .pmk-tier-name {
217
+ display: block;
218
+ font-family: 'Oswald', sans-serif;
219
+ font-size: 16px;
220
+ font-weight: 600;
221
+ letter-spacing: 0.06em;
222
+ text-transform: uppercase;
223
+ color: var(--_ink);
224
+ }
225
+ .is-featured .pmk-tier-name { color: var(--_paper); }
226
+ .pmk-tier-price {
227
+ display: block;
228
+ margin: 8px 0 2px;
229
+ color: var(--_ink);
230
+ }
231
+ .pmk-tier-price b {
232
+ font-family: 'Oswald', sans-serif;
233
+ font-size: 34px;
234
+ font-weight: 700;
235
+ line-height: 1;
236
+ }
237
+ .pmk-tier-price i {
238
+ font-style: normal;
239
+ font-size: 13px;
240
+ color: var(--_muted);
241
+ margin-left: 4px;
242
+ }
243
+ .is-featured .pmk-tier-price,
244
+ .is-featured .pmk-tier-price b { color: var(--_paper); }
245
+ .is-featured .pmk-tier-price i { color: rgba(255, 255, 255, 0.7); }
246
+ .pmk-tier-tag {
247
+ display: block;
248
+ font-size: 12.5px;
249
+ color: var(--_muted);
250
+ margin-bottom: 14px;
251
+ min-height: 1.4em;
252
+ }
253
+ .is-featured .pmk-tier-tag { color: rgba(255, 255, 255, 0.72); }
254
+
255
+ /* CTA (self-contained — does not depend on host .btn) ----------------- */
256
+ .pmk-cta {
257
+ box-sizing: border-box;
258
+ min-height: var(--tmk-min-target);
259
+ min-width: var(--tmk-min-target);
260
+ display: inline-flex;
261
+ align-items: center;
262
+ justify-content: center;
263
+ gap: 8px;
264
+ padding: 11px 18px;
265
+ border-radius: 999px;
266
+ font-family: 'Inter', system-ui, sans-serif;
267
+ font-weight: 600;
268
+ font-size: 13.5px;
269
+ letter-spacing: 0.02em;
270
+ border: 1px solid transparent;
271
+ cursor: pointer;
272
+ transition: transform 0.12s ease, background 0.12s ease, box-shadow 0.12s ease;
273
+ text-decoration: none;
274
+ }
275
+ .pmk-cta:hover { transform: translateY(-1px); }
276
+ .pmk-cta:focus-visible { outline: 2px solid var(--_brand); outline-offset: 3px; }
277
+ .pmk-cta--ink { background: var(--_ink); color: var(--_paper); }
278
+ .pmk-cta--ink:hover { background: var(--_brand); }
279
+ .pmk-cta--brand { background: var(--_brand); color: var(--_paper); }
280
+ .pmk-cta--brand:hover { background: var(--_brand-deep); }
281
+ .is-featured .pmk-cta--brand { box-shadow: 0 10px 24px -10px rgba(0, 0, 0, 0.5); }
282
+
283
+ /* Group + rows -------------------------------------------------------- */
284
+ .pmk-grouprow th {
285
+ text-align: left;
286
+ padding: 22px 18px 8px;
287
+ font-family: 'Oswald', sans-serif;
288
+ font-size: 11px;
289
+ font-weight: 600;
290
+ letter-spacing: 0.18em;
291
+ text-transform: uppercase;
292
+ color: var(--_brand);
293
+ }
294
+ .pmk-row:hover .pmk-rowlabel,
295
+ .pmk-row:hover .pmk-cell:not(.is-featured) {
296
+ background: var(--_bg-tint);
297
+ }
298
+ .pmk-rowlabel {
299
+ padding: 15px 18px;
300
+ vertical-align: middle;
301
+ border-bottom: 1px solid var(--_hairline);
302
+ font-weight: 500;
303
+ }
304
+ .pmk-rowlabel-t { display: block; color: var(--_ink); font-size: 15px; }
305
+ .pmk-rowlabel-h { display: block; color: var(--_muted); font-size: 12.5px; margin-top: 2px; }
306
+ .pmk-cell {
307
+ padding: 15px 18px;
308
+ text-align: center;
309
+ vertical-align: middle;
310
+ border-bottom: 1px solid var(--_hairline);
311
+ color: var(--_ink);
312
+ }
313
+ .pmk-cell.is-featured {
314
+ background: color-mix(in srgb, var(--_ink) 5%, transparent);
315
+ border-left: 1px solid var(--_hairline);
316
+ border-right: 1px solid var(--_hairline);
317
+ }
318
+ .pmk-val {
319
+ font-family: 'Oswald', sans-serif;
320
+ font-weight: 600;
321
+ font-size: 14px;
322
+ letter-spacing: 0.01em;
323
+ }
324
+ .pmk-yes,
325
+ .pmk-no {
326
+ display: inline-grid;
327
+ place-items: center;
328
+ width: 24px;
329
+ height: 24px;
330
+ border-radius: 50%;
331
+ }
332
+ .pmk-yes {
333
+ background: color-mix(in srgb, var(--_accent) 20%, transparent);
334
+ color: var(--_brand-deep);
335
+ }
336
+ .pmk-yes svg { width: 15px; height: 15px; }
337
+ .pmk-no { color: var(--_muted); opacity: 0.5; }
338
+ .pmk-no svg { width: 15px; height: 15px; }
339
+ /* last row of the featured column gets a rounded bottom */
340
+ .pmk-table tbody tr:last-child .pmk-cell.is-featured {
341
+ border-radius: 0 0 var(--_r-md) var(--_r-md);
342
+ }
343
+
344
+ .pmk-footnote {
345
+ color: var(--_muted);
346
+ font-size: 13.5px;
347
+ margin: 18px 2px 0;
348
+ }
349
+
350
+ /* Concierge / one-time callout --------------------------------------- */
351
+ .pmk-callout {
352
+ margin-top: 26px;
353
+ display: flex;
354
+ align-items: center;
355
+ justify-content: space-between;
356
+ gap: 28px;
357
+ flex-wrap: wrap;
358
+ padding: 26px 30px;
359
+ border-radius: var(--_r-lg);
360
+ background: var(--_bg-tint);
361
+ border: 1px solid var(--_hairline);
362
+ }
363
+ .pmk-callout-badge {
364
+ display: inline-block;
365
+ font-family: 'Oswald', sans-serif;
366
+ font-size: 11px;
367
+ font-weight: 600;
368
+ letter-spacing: 0.16em;
369
+ text-transform: uppercase;
370
+ color: var(--_ink);
371
+ background: var(--_accent);
372
+ padding: 4px 10px;
373
+ border-radius: 999px;
374
+ margin-bottom: 12px;
375
+ }
376
+ .pmk-callout-name {
377
+ font-family: 'Oswald', sans-serif;
378
+ font-size: 22px;
379
+ font-weight: 700;
380
+ margin: 0;
381
+ display: inline-block;
382
+ }
383
+ .pmk-callout-price {
384
+ margin: 4px 0 8px;
385
+ color: var(--_ink);
386
+ }
387
+ .pmk-callout-price b { font-family: 'Oswald', sans-serif; font-size: 26px; }
388
+ .pmk-callout-price i { font-style: normal; font-size: 13px; color: var(--_muted); }
389
+ .pmk-callout-tag { color: var(--_muted); margin: 0 0 10px; font-size: 14.5px; }
390
+ .pmk-callout-list {
391
+ list-style: none;
392
+ padding: 0;
393
+ margin: 0;
394
+ display: flex;
395
+ flex-wrap: wrap;
396
+ gap: 6px 22px;
397
+ max-width: 62ch;
398
+ }
399
+ .pmk-callout-list li {
400
+ position: relative;
401
+ padding-left: 18px;
402
+ color: var(--_muted);
403
+ font-size: 13.5px;
404
+ }
405
+ .pmk-callout-list li::before {
406
+ content: '';
407
+ position: absolute;
408
+ left: 0;
409
+ top: 8px;
410
+ width: 7px;
411
+ height: 7px;
412
+ border-radius: 50%;
413
+ background: var(--_brand);
414
+ }
415
+ .pmk-callout-cta { white-space: nowrap; flex-shrink: 0; }
416
+
417
+ .pmk-visually-hidden {
418
+ position: absolute;
419
+ width: 1px;
420
+ height: 1px;
421
+ padding: 0;
422
+ margin: -1px;
423
+ overflow: hidden;
424
+ clip: rect(0 0 0 0);
425
+ white-space: nowrap;
426
+ border: 0;
427
+ }
428
+
429
+ @media (max-width: 640px) {
430
+ .pmk-pricing { padding: 64px 0; }
431
+ .pmk-callout { flex-direction: column; align-items: flex-start; }
432
+ }
433
+ </style>