@runwell/shopify-toolkit 0.17.4 → 0.18.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.
Files changed (25) hide show
  1. package/bin/runwell-shopify +4 -1
  2. package/lib/list.js +120 -0
  3. package/modules/INDEX.md +52 -19
  4. package/modules/_shared/css-tokens/assets/runwell-tokens.css +24 -4
  5. package/modules/_shared/css-tokens/module.json +2 -2
  6. package/modules/_shared/css-typography/assets/runwell-typography.css +14 -6
  7. package/modules/_shared/css-typography/module.json +2 -2
  8. package/modules/care-coaching-medvi/README.md +46 -0
  9. package/modules/care-coaching-medvi/assets/runwell-care-coaching-medvi.css +241 -0
  10. package/modules/care-coaching-medvi/module.json +80 -0
  11. package/modules/care-coaching-medvi/sections/runwell-care-coaching-medvi.liquid +274 -0
  12. package/modules/care-coaching-medvi/snippets/runwell-care-coaching-medvi-circular-text.liquid +25 -0
  13. package/modules/collection-block-medvi/README.md +50 -0
  14. package/modules/collection-block-medvi/assets/runwell-collection-block-medvi.css +242 -0
  15. package/modules/collection-block-medvi/module.json +83 -0
  16. package/modules/collection-block-medvi/sections/runwell-collection-block-medvi.liquid +355 -0
  17. package/modules/product-trio-medvi/README.md +35 -0
  18. package/modules/product-trio-medvi/assets/runwell-product-trio-medvi.css +119 -0
  19. package/modules/product-trio-medvi/module.json +48 -0
  20. package/modules/product-trio-medvi/sections/runwell-product-trio-medvi.liquid +188 -0
  21. package/modules/testimonials-medvi/README.md +44 -0
  22. package/modules/testimonials-medvi/assets/runwell-testimonials-medvi.css +239 -0
  23. package/modules/testimonials-medvi/module.json +68 -0
  24. package/modules/testimonials-medvi/sections/runwell-testimonials-medvi.liquid +355 -0
  25. package/package.json +2 -2
@@ -44,7 +44,10 @@ function help() {
44
44
 
45
45
  Commands:
46
46
  sync Apply runwell.config.json to the target theme
47
- list List available + installed modules
47
+ list List available + installed modules.
48
+ --tenants prints a cross-tenant matrix
49
+ (tenants x baseline pin x toolkit pin x
50
+ drift) read from shopify-toolkit-deployments.json.
48
51
  add <module> Enable a module in runwell.config.json
49
52
  remove <module> Disable + clean a module's files
50
53
  doctor Detect drift between manifest and theme
package/lib/list.js CHANGED
@@ -1,8 +1,16 @@
1
1
  import path from 'node:path';
2
2
  import fs from 'node:fs';
3
+ import os from 'node:os';
3
4
  import { listAvailableModules, loadModuleManifest, loadConfig } from './config-loader.js';
4
5
 
5
6
  export async function list(flags) {
7
+ if (flags.tenants) {
8
+ return listTenants(flags);
9
+ }
10
+ return listModules(flags);
11
+ }
12
+
13
+ function listModules(flags) {
6
14
  const available = listAvailableModules(flags.toolkitRoot);
7
15
 
8
16
  let installed = new Set();
@@ -29,3 +37,115 @@ export async function list(flags) {
29
37
 
30
38
  console.log(`\nTotal: ${available.length} modules. Installed in current config: ${installed.size}.`);
31
39
  }
40
+
41
+ function listTenants(flags) {
42
+ const registryPath = resolveRegistryPath(flags);
43
+ if (!registryPath) {
44
+ console.error('Could not locate shopify-toolkit-deployments.json.');
45
+ console.error('Pass --registry <path>, set RUNWELL_DEPLOYMENT_REGISTRY env var, or place the file at ~/Documents/Code/claude-PM/infrastructure/config/shopify-toolkit-deployments.json');
46
+ process.exit(1);
47
+ }
48
+
49
+ const registry = JSON.parse(fs.readFileSync(registryPath, 'utf-8'));
50
+ const deployments = registry.deployments || {};
51
+ const tenants = Object.entries(deployments);
52
+
53
+ if (tenants.length === 0) {
54
+ console.log('No tenants in registry.');
55
+ return;
56
+ }
57
+
58
+ const toolkitCurrent = readToolkitVersion(flags.toolkitRoot);
59
+
60
+ console.log(`Runwell Shopify tenants (registry: ${registryPath})\n`);
61
+ console.log(`Toolkit current: ${toolkitCurrent}\n`);
62
+ console.log(' Tenant Store Baseline pin Config pin Synced ver Modules Drift Status');
63
+ console.log(' --------- ------------------------------------------- --------------------------------- ------------ ----------- ------- ----- ----------');
64
+
65
+ let drifters = 0;
66
+
67
+ for (const [slug, t] of tenants.sort((a, b) => a[0].localeCompare(b[0]))) {
68
+ const store = (t.store || '?').padEnd(43);
69
+ const tenantConfig = readTenantConfig(t.theme_repo_local);
70
+ const basePin = (tenantConfig?.baseline || t.baseline || '?').padEnd(33);
71
+ const configPin = (tenantConfig?.toolkit_version || '?').padEnd(12);
72
+ const syncedVer = (readManifestToolkit(t.theme_repo_local) || '?').padEnd(11);
73
+ const moduleCount = (t.modules_enabled || []).length.toString().padEnd(7);
74
+ const drift = computeDrift(tenantConfig?.toolkit_version, toolkitCurrent);
75
+ if (drift !== 'ok') drifters++;
76
+ const driftStr = drift.padEnd(5);
77
+ const status = (t.status || '?');
78
+ console.log(` ${slug.padEnd(9)} ${store} ${basePin} ${configPin} ${syncedVer} ${moduleCount} ${driftStr} ${status}`);
79
+ }
80
+
81
+ console.log(`\nTotal: ${tenants.length} tenants. Drift: ${drifters} of ${tenants.length} pinned below toolkit current (${toolkitCurrent}).`);
82
+
83
+ if (flags.verbose) {
84
+ console.log('\nLegend:');
85
+ console.log(' Baseline pin: from runwell.config.json baseline field (truth source).');
86
+ console.log(' Config pin: from runwell.config.json toolkit_version (truth source). ^X.Y.Z accepts forward minor bumps.');
87
+ console.log(' Synced ver: actual toolkit version recorded by the last `runwell-shopify sync` (from runwell-manifest.json).');
88
+ console.log(' Drift: "ok" if config-pin minor >= toolkit-current minor; "stale" if behind. "stale" with synced=current means the files are current but the pin lies.');
89
+ }
90
+ }
91
+
92
+ function resolveRegistryPath(flags) {
93
+ if (flags.registry) {
94
+ return path.resolve(flags.registry);
95
+ }
96
+ if (process.env.RUNWELL_DEPLOYMENT_REGISTRY) {
97
+ return path.resolve(process.env.RUNWELL_DEPLOYMENT_REGISTRY);
98
+ }
99
+ const guesses = [
100
+ path.join(os.homedir(), 'Documents/Code/claude-PM/infrastructure/config/shopify-toolkit-deployments.json'),
101
+ path.resolve(flags.toolkitRoot, '../claude-PM/infrastructure/config/shopify-toolkit-deployments.json'),
102
+ ];
103
+ return guesses.find(p => fs.existsSync(p));
104
+ }
105
+
106
+ function readToolkitVersion(toolkitRoot) {
107
+ try {
108
+ const pkg = JSON.parse(fs.readFileSync(path.join(toolkitRoot, 'package.json'), 'utf-8'));
109
+ return pkg.version;
110
+ } catch {
111
+ return null;
112
+ }
113
+ }
114
+
115
+ function readManifestToolkit(themeRepoLocal) {
116
+ if (!themeRepoLocal) return null;
117
+ const manifestPath = path.join(themeRepoLocal, 'runwell-manifest.json');
118
+ if (!fs.existsSync(manifestPath)) return null;
119
+ try {
120
+ const m = JSON.parse(fs.readFileSync(manifestPath, 'utf-8'));
121
+ return m.toolkit_version || null;
122
+ } catch {
123
+ return null;
124
+ }
125
+ }
126
+
127
+ function readTenantConfig(themeRepoLocal) {
128
+ if (!themeRepoLocal) return null;
129
+ const configPath = path.join(themeRepoLocal, 'runwell.config.json');
130
+ if (!fs.existsSync(configPath)) return null;
131
+ try {
132
+ return JSON.parse(fs.readFileSync(configPath, 'utf-8'));
133
+ } catch {
134
+ return null;
135
+ }
136
+ }
137
+
138
+ function computeDrift(pin, current) {
139
+ if (!pin || !current) return '?';
140
+ const pinMinor = extractMinor(pin);
141
+ const curMinor = extractMinor(current);
142
+ if (pinMinor == null || curMinor == null) return '?';
143
+ if (pinMinor >= curMinor) return 'ok';
144
+ return 'stale';
145
+ }
146
+
147
+ function extractMinor(version) {
148
+ const m = String(version).match(/(\d+)\.(\d+)/);
149
+ if (!m) return null;
150
+ return parseInt(m[1], 10) * 1000 + parseInt(m[2], 10);
151
+ }
package/modules/INDEX.md CHANGED
@@ -3,45 +3,49 @@
3
3
  Auto-generated by `scripts/generate-index.mjs`. Do not edit by hand.
4
4
  Skills (shopify-storefront, shopify-cro, shopify-cli-ops, shopify-admin-browser) grep this file before writing custom Liquid.
5
5
 
6
- Total modules: 34.
6
+ Total modules: 38.
7
7
 
8
8
  ## By category
9
9
 
10
+ - **branding**: care-coaching-medvi, product-trio-medvi
10
11
  - **catalog**: bundle-builder, quantity-breaks, subscriptions
11
12
  - **conversion**: cart-cross-sell, cart-freeship-progress, cart-usps, exit-intent, gift-with-purchase, post-purchase-upsell, quick-view, risk-reversal, shipping-bar, sticky-atc
12
13
  - **customer**: loyalty-tiers, wishlist
13
14
  - **pdp**: comparison-table, delivery-estimate, inventory-urgency, pdp-ingredients, pdp-journal-link, pdp-trust-checks, recently-viewed
14
- - **social-proof**: press-bar, product-badges, reviews, scrolling-ticker, social-proof-banner, stats-bar, testimonials, trust-badges
15
- - **storefront**: editorial-block, editorial-hero, faq, how-it-works
15
+ - **social-proof**: press-bar, product-badges, reviews, scrolling-ticker, social-proof-banner, stats-bar, testimonials, testimonials-medvi, trust-badges
16
+ - **storefront**: collection-block-medvi, editorial-block, editorial-hero, faq, how-it-works
16
17
 
17
18
  ## Modules
18
19
 
19
20
  | Name | Category | Replaces | Files | Config keys | Variants | Admin steps |
20
21
  |---|---|---|---|---|---|---|
21
22
  | `bundle-builder` | catalog | BYOB-style bundle apps | sections:1 assets:1 | heading, sale_prefix, show_rating, rating_score, rating_count, show_trust_badges, trust_1, trust_2, trust_3, fomo_mode, fomo_cycle_days, fomo_stock_count | (none) | (none) |
23
+ | `care-coaching-medvi` | branding | (native build) | sections:1 snippets:1 assets:1 | section_eyebrow, headline_pre, headline_post, headline_accent_color, block_heading, circular_text, circular_text_position, footer_link_label, layout, bg_band | (none) | (none) |
22
24
  | `cart-cross-sell` | conversion | Rebuy / OneClickUpsell pre-purchase upsell | snippets:1 | eyebrow, cta_label | (none) | (none) |
23
25
  | `cart-freeship-progress` | conversion | Bold Free Shipping Manager and similar app features | snippets:1 | threshold_cents, away_text, unlocked_message | (none) | (none) |
24
26
  | `cart-usps` | conversion | (native build) | snippets:1 | icon, usp_1, usp_2, usp_3 | (none) | (none) |
27
+ | `collection-block-medvi` | storefront | (native build) | sections:1 assets:1 | eyebrow, headline_pre, headline_post, headline_accent_color, show_product_card, product_card_bg, benefits_heading, subhead, cta_label, layout, bg_band | (none) | (none) |
25
28
  | `comparison-table` | pdp | app-driven comparison widgets | | eyebrow, heading, lede, background_color, text_color | feature-columns, feature-rows | (none) |
26
29
  | `delivery-estimate` | pdp | (native build) | snippets:1 | (none) | (none) | (none) |
27
- | `editorial-block` | storefront | (native build) | sections:1 | eyebrow, heading, lede, background_color, text_color | (none) | (none) |
30
+ | `editorial-block` | storefront | (native build) | sections:1 assets:1 | eyebrow, heading, lede, background_color, text_color | (none) | (none) |
28
31
  | `editorial-hero` | storefront | Dawn's image-banner / video-banner | | eyebrow, heading, subheading | video-bg, hero-with-card | (none) |
29
- | `exit-intent` | conversion | Privy / Justuno display layer | sections:1 assets:1 | eyebrow, heading, lede | (none) | (none) |
30
- | `faq` | storefront | (native build) | sections:1 | eyebrow, heading, background_color, text_color | (none) | (none) |
32
+ | `exit-intent` | conversion | Privy / Justuno display layer | sections:1 assets:2 | eyebrow, heading, lede | (none) | (none) |
33
+ | `faq` | storefront | (native build) | sections:1 assets:1 | eyebrow, heading, background_color, text_color | (none) | (none) |
31
34
  | `gift-with-purchase` | conversion | (native build) | snippets:1 assets:1 | threshold_cents, gift_handle, unlocked_message, locked_message_suffix | (none) | create-gift-product + create-gift-discount |
32
- | `how-it-works` | storefront | (native build) | sections:1 | eyebrow, heading, lede, image, asset_filename, background_color, text_color, cta_label, cta_link | (none) | (none) |
35
+ | `how-it-works` | storefront | (native build) | sections:1 assets:1 | eyebrow, heading, lede, image, asset_filename, background_color, text_color, cta_label, cta_link | (none) | (none) |
33
36
  | `inventory-urgency` | pdp | (native build) | snippets:1 | (none) | (none) | (none) |
34
- | `loyalty-tiers` | customer | (native build) | sections:1 | tier_0_name, tier_1_name, tier_1_threshold, tier_1_perk_pct, tier_2_name, tier_2_threshold, tier_2_perk_pct | (none) | create-tier-tags-and-flows + create-tier-discounts + add-tier-card-to-account |
37
+ | `loyalty-tiers` | customer | (native build) | sections:1 assets:1 | tier_0_name, tier_1_name, tier_1_threshold, tier_1_perk_pct, tier_2_name, tier_2_threshold, tier_2_perk_pct | (none) | create-tier-tags-and-flows + create-tier-discounts + add-tier-card-to-account |
35
38
  | `pdp-ingredients` | pdp | (native build) | sections:1 | eyebrow, heading, lede, background_color, text_color | (none) | (none) |
36
39
  | `pdp-journal-link` | pdp | (native build) | sections:1 | eyebrow, article, background_color, text_color, fallback_title, fallback_body, fallback_link_label, fallback_link_url | (none) | (none) |
37
40
  | `pdp-trust-checks` | pdp | (native build) | sections:1 | eyebrow, heading, lede, background_color, text_color, link_label, link_url | (none) | (none) |
38
41
  | `post-purchase-upsell` | conversion | Reconvert / OneClickUpsell / AfterSell display layer | assets:2 | discount_code, discount_label, max_items, heading, eyebrow, lede, cross_category_logic | (none) | create-discount + paste-bootstrap |
39
42
  | `press-bar` | social-proof | (native build) | sections:1 | eyebrow, background_color, text_color | (none) | (none) |
40
43
  | `product-badges` | social-proof | (native build) | snippets:1 | label_best_seller, label_new, label_editor_pick | (none) | (none) |
44
+ | `product-trio-medvi` | branding | (native build) | sections:1 assets:1 | panel_heading, panel_bg, layout, bg_band | (none) | (none) |
41
45
  | `quantity-breaks` | catalog | (native build) | snippets:1 | eyebrow, fineprint | (none) | define-breaks-metafield + set-product-breaks + create-discount-function |
42
46
  | `quick-view` | conversion | (native build) | snippets:2 assets:1 | (none) | (none) | (none) |
43
- | `recently-viewed` | pdp | (native build) | sections:1 assets:1 | eyebrow, heading, background_color | (none) | (none) |
44
- | `reviews` | social-proof | (native build) | sections:1 | heading | (none) | (none) |
47
+ | `recently-viewed` | pdp | (native build) | sections:1 assets:2 | eyebrow, heading, background_color | (none) | (none) |
48
+ | `reviews` | social-proof | (native build) | sections:1 assets:1 | heading | (none) | (none) |
45
49
  | `risk-reversal` | conversion | (native build) | sections:1 | icon, heading, body, link_label, link_url, background_color, text_color | (none) | (none) |
46
50
  | `scrolling-ticker` | social-proof | announcement-bar / scrolling-text apps | sections:1 assets:1 | (none) | (none) | (none) |
47
51
  | `shipping-bar` | conversion | (native build) | sections:1 | threshold_cents, message_below, message_qualified, message_default, background_color, text_color | (none) | (none) |
@@ -50,8 +54,9 @@ Total modules: 34.
50
54
  | `sticky-atc` | conversion | Sticky Add To Cart Booster Pro and similar | sections:1 assets:1 | (none) | (none) | (none) |
51
55
  | `subscriptions` | catalog | Recharge / Bold Subscriptions / Appstle for the storefront display layer; subscription management still uses Shopify's native customer account | snippets:1 | one_time_label, subscribe_label, fineprint | (none) | install-shopify-subscriptions + create-selling-plan-group + enable-customer-account-tab |
52
56
  | `testimonials` | social-proof | app-driven review widgets at the social-proof display layer | | eyebrow, heading, background_color, text_color | grid-quotes, carousel-ugc | (none) |
57
+ | `testimonials-medvi` | social-proof | (native build) | sections:1 assets:1 | section_eyebrow, headline_pre, headline_post, headline_accent_color, lede, card_bg, star_color, bg_band | (none) | (none) |
53
58
  | `trust-badges` | social-proof | (native build) | sections:1 | background_color, text_color | (none) | (none) |
54
- | `wishlist` | customer | Wishlist Plus, Wishlist King, Globo Wishlist | sections:1 snippets:1 assets:1 templates:1 | max_items | (none) | create-wishlist-page |
59
+ | `wishlist` | customer | Wishlist Plus, Wishlist King, Globo Wishlist | sections:1 snippets:1 assets:2 templates:1 | max_items | (none) | create-wishlist-page |
55
60
 
56
61
  ## Descriptions
57
62
 
@@ -63,6 +68,13 @@ Total modules: 34.
63
68
  - Files: sections:1 assets:1
64
69
  - Config: heading, sale_prefix, show_rating, rating_score, rating_count, show_trust_badges, trust_1, trust_2, trust_3, fomo_mode, fomo_cycle_days, fomo_stock_count
65
70
 
71
+ ### care-coaching-medvi
72
+
73
+ - Category: branding
74
+ - What: Brand-promise section: portrait card + circular rotating text mark + 2-color headline + body + footer CTA line.
75
+ - Files: sections:1 snippets:1 assets:1
76
+ - Config: section_eyebrow, headline_pre, headline_post, headline_accent_color, block_heading, circular_text, circular_text_position, footer_link_label, layout, bg_band
77
+
66
78
  ### cart-cross-sell
67
79
 
68
80
  - Category: conversion
@@ -86,6 +98,13 @@ Total modules: 34.
86
98
  - Files: snippets:1
87
99
  - Config: icon, usp_1, usp_2, usp_3
88
100
 
101
+ ### collection-block-medvi
102
+
103
+ - Category: storefront
104
+ - What: Duplex category section: product hero card on one side; eyebrow + split-color headline + benefits checklist + 2 lifestyle photos + CTA on the other.
105
+ - Files: sections:1 assets:1
106
+ - Config: eyebrow, headline_pre, headline_post, headline_accent_color, show_product_card, product_card_bg, benefits_heading, subhead, cta_label, layout, bg_band
107
+
89
108
  ### comparison-table
90
109
 
91
110
  - Category: pdp
@@ -104,7 +123,7 @@ Total modules: 34.
104
123
 
105
124
  - Category: storefront
106
125
  - What: Editorial introduction block: eyebrow + serif italic heading + lede + body.
107
- - Files: sections:1
126
+ - Files: sections:1 assets:1
108
127
  - Config: eyebrow, heading, lede, background_color, text_color
109
128
 
110
129
  ### editorial-hero
@@ -120,14 +139,14 @@ Total modules: 34.
120
139
  - Category: conversion
121
140
  - Replaces: Privy / Justuno display layer
122
141
  - What: Exit-intent popup with email capture.
123
- - Files: sections:1 assets:1
142
+ - Files: sections:1 assets:2
124
143
  - Config: eyebrow, heading, lede
125
144
 
126
145
  ### faq
127
146
 
128
147
  - Category: storefront
129
148
  - What: FAQ accordion.
130
- - Files: sections:1
149
+ - Files: sections:1 assets:1
131
150
  - Config: eyebrow, heading, background_color, text_color
132
151
 
133
152
  ### gift-with-purchase
@@ -142,7 +161,7 @@ Total modules: 34.
142
161
 
143
162
  - Category: storefront
144
163
  - What: How-it-works section: side-image + multi-step explainer.
145
- - Files: sections:1
164
+ - Files: sections:1 assets:1
146
165
  - Config: eyebrow, heading, lede, image, asset_filename, background_color, text_color, cta_label, cta_link
147
166
 
148
167
  ### inventory-urgency
@@ -155,7 +174,7 @@ Total modules: 34.
155
174
 
156
175
  - Category: customer
157
176
  - What: Lifetime-spend tier card on the customer account page.
158
- - Files: sections:1
177
+ - Files: sections:1 assets:1
159
178
  - Config: tier_0_name, tier_1_name, tier_1_threshold, tier_1_perk_pct, tier_2_name, tier_2_threshold, tier_2_perk_pct
160
179
  - Admin steps: create-tier-tags-and-flows + create-tier-discounts + add-tier-card-to-account
161
180
 
@@ -203,6 +222,13 @@ Total modules: 34.
203
222
  - Files: snippets:1
204
223
  - Config: label_best_seller, label_new, label_editor_pick
205
224
 
225
+ ### product-trio-medvi
226
+
227
+ - Category: branding
228
+ - What: 3-product showcase, fan layout with center product foregrounded, soft-corner copy panel beside.
229
+ - Files: sections:1 assets:1
230
+ - Config: panel_heading, panel_bg, layout, bg_band
231
+
206
232
  ### quantity-breaks
207
233
 
208
234
  - Category: catalog
@@ -221,14 +247,14 @@ Total modules: 34.
221
247
 
222
248
  - Category: pdp
223
249
  - What: recently viewed.
224
- - Files: sections:1 assets:1
250
+ - Files: sections:1 assets:2
225
251
  - Config: eyebrow, heading, background_color
226
252
 
227
253
  ### reviews
228
254
 
229
255
  - Category: social-proof
230
256
  - What: PDP reviews.
231
- - Files: sections:1
257
+ - Files: sections:1 assets:1
232
258
  - Config: heading
233
259
 
234
260
  ### risk-reversal
@@ -290,6 +316,13 @@ Total modules: 34.
290
316
  - Config: eyebrow, heading, background_color, text_color
291
317
  - Variants: grid-quotes, carousel-ugc
292
318
 
319
+ ### testimonials-medvi
320
+
321
+ - Category: social-proof
322
+ - What: Two horizontal marquee rows of testimonial cards.
323
+ - Files: sections:1 assets:1
324
+ - Config: section_eyebrow, headline_pre, headline_post, headline_accent_color, lede, card_bg, star_color, bg_band
325
+
293
326
  ### trust-badges
294
327
 
295
328
  - Category: social-proof
@@ -302,7 +335,7 @@ Total modules: 34.
302
335
  - Category: customer
303
336
  - Replaces: Wishlist Plus, Wishlist King, Globo Wishlist
304
337
  - What: Native wishlist using localStorage.
305
- - Files: sections:1 snippets:1 assets:1 templates:1
338
+ - Files: sections:1 snippets:1 assets:2 templates:1
306
339
  - Config: max_items
307
340
  - Admin steps: create-wishlist-page
308
341
 
@@ -1,7 +1,10 @@
1
- /* Runwell Shopify Toolkit: brand tokens.
2
- Generated from runwell.config.json brand vars. Every other module
3
- references these via var(--runwell-X). Do not hand-edit in client
4
- themes; re-run runwell-shopify sync to update.
1
+ /* Runwell Shopify Toolkit: brand and design tokens.
2
+
3
+ Section 1 (brand): generated from runwell.config.json brand vars.
4
+ Re-run runwell-shopify sync to update.
5
+
6
+ Section 2 (design system): toolkit-wide constants. Tenants override
7
+ in their own tenant-brand.css if they need a different scale.
5
8
 
6
9
  --runwell-tertiary is the canonical brand-tertiary token; the
7
10
  --runwell-rain-forrest alias is preserved for one minor cycle of
@@ -10,6 +13,7 @@
10
13
  brand.tertiary in runwell.config.json.
11
14
  */
12
15
  :root {
16
+ /* Brand colors (interpolated from runwell.config.json) */
13
17
  --runwell-primary: {{brand.primary}};
14
18
  --runwell-accent: {{brand.accent}};
15
19
  --runwell-cream: {{brand.cream}};
@@ -18,4 +22,20 @@
18
22
  --runwell-blue: {{brand.blue}};
19
23
  --runwell-tertiary: {{brand.tertiary}};
20
24
  --runwell-rain-forrest: {{brand.tertiary}};
25
+
26
+ /* Design system: semantic surfaces.
27
+ Components reference these so the theme controls the default look.
28
+ Tenants override in tenant-brand.css to retarget any brand color. */
29
+ --runwell-surface-card: var(--runwell-oat);
30
+ --runwell-surface-card-alt: color-mix(in srgb, var(--runwell-celadon) 18%, white);
31
+
32
+ /* Design system: corner radii */
33
+ --runwell-radius-sm: 4px;
34
+ --runwell-radius-md: 12px;
35
+ --runwell-radius-lg: 20px;
36
+ --runwell-radius-xl: 32px;
37
+
38
+ /* Design system: elevation */
39
+ --runwell-shadow-card: 0 2px 8px rgba(0, 0, 0, 0.04);
40
+ --runwell-shadow-elevated: 0 8px 24px rgba(0, 0, 0, 0.06);
21
41
  }
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "_shared/css-tokens",
3
- "version": "0.1.0",
3
+ "version": "0.3.0",
4
4
  "category": "foundation",
5
- "description": "CSS custom properties published as :root vars so every Runwell module pulls brand colors from one source. Always synced.",
5
+ "description": "CSS custom properties published as :root vars. Brand colors interpolated from runwell.config.json. Design system tokens (radii, shadows) hardcoded as toolkit-wide constants. Always synced.",
6
6
  "always_enabled": true,
7
7
  "files": {
8
8
  "assets": ["assets/runwell-tokens.css"]
@@ -4,6 +4,11 @@
4
4
  sliders in layout/theme.liquid) so every toolkit module renders type
5
5
  that scales uniformly when a merchant adjusts the sliders.
6
6
 
7
+ Sizes are Dawn-aligned. Dawn sets html font-size to
8
+ calc(var(--font-body-scale) * 62.5%), so 1rem equals 10px when body
9
+ scale is 1.0. Our tokens land in the readability range Dawn uses for
10
+ its own headings and captions (1.2rem to 1.8rem).
11
+
7
12
  Modules reference these via var(--runwell-X-size). Tenant CSS may also
8
13
  reference them directly OR compose its own scale-aware sizes using
9
14
  calc(var(--font-body-scale) * Xrem) and calc(var(--font-heading-scale) * Xrem).
@@ -11,13 +16,16 @@
11
16
  Do not hand-edit in client themes; re-run runwell-shopify sync to update.
12
17
  */
13
18
  :root {
14
- /* Body-scale derived. Eyebrows, captions, ledes, body, CTAs. */
15
- --runwell-eyebrow-size: calc(var(--font-body-scale) * 0.78rem);
16
- --runwell-caption-size: calc(var(--font-body-scale) * 0.85rem);
17
- --runwell-meta-size: calc(var(--font-body-scale) * 0.92rem);
18
- --runwell-cta-size: calc(var(--font-body-scale) * 1.15rem);
19
+ /* Body-scale derived. Eyebrows, captions, meta, body, ledes, CTAs.
20
+ Dawn-aligned: smallest readable text at 1.2rem (12px), Dawn body at
21
+ 1.5rem (15px), our body slightly larger at 1.6rem (16px) for
22
+ component readability inside cards and sections. */
23
+ --runwell-eyebrow-size: calc(var(--font-body-scale) * 1.2rem);
24
+ --runwell-caption-size: calc(var(--font-body-scale) * 1.3rem);
25
+ --runwell-meta-size: calc(var(--font-body-scale) * 1.4rem);
26
+ --runwell-cta-size: calc(var(--font-body-scale) * 1.5rem);
19
27
  --runwell-body-size: calc(var(--font-body-scale) * 1.6rem);
20
- --runwell-lede-size: calc(var(--font-body-scale) * 1.7rem);
28
+ --runwell-lede-size: calc(var(--font-body-scale) * 1.8rem);
21
29
 
22
30
  /* Heading-scale derived. Section titles, big numbers, hero/aura titles. */
23
31
  --runwell-h4-size: calc(var(--font-heading-scale) * 1.7rem);
@@ -1,8 +1,8 @@
1
1
  {
2
2
  "name": "_shared/css-typography",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "category": "foundation",
5
- "description": "Typography tokens published as :root vars. Every Runwell module references these instead of hardcoding rem values, so type scale responds to Dawn's body_scale and heading_scale Theme Editor sliders. Always synced.",
5
+ "description": "Typography tokens published as :root vars. Every Runwell module references these instead of hardcoding rem values, so type scale responds to Dawn's body_scale and heading_scale Theme Editor sliders. Sizes are Dawn-aligned (eyebrow 1.2rem, body 1.6rem, etc.). Always synced.",
6
6
  "always_enabled": true,
7
7
  "files": {
8
8
  "assets": ["assets/runwell-typography.css"]
@@ -0,0 +1,46 @@
1
+ # care-coaching-medvi
2
+
3
+ Brand-promise section. Centered eyebrow + 2-color headline at top; large portrait card on one side; block (heading + body) on the other; circular rotating text mark anchored to a corner of the section; footer eyebrow + link below.
4
+
5
+ Category: `branding`
6
+
7
+ The distinguishing visual is the **circular rotating text mark** ("WITH YOU FROM START TO SUCCESS" in medvi's reference), rendered as inline SVG `textPath` along a closed circle, slowly rotating via CSS animation. Respects `prefers-reduced-motion`.
8
+
9
+ ## Files
10
+
11
+ - `sections/runwell-care-coaching-medvi.liquid`
12
+ - `snippets/runwell-care-coaching-medvi-circular-text.liquid` (SVG textPath generator, isolated for reuse)
13
+ - `assets/runwell-care-coaching-medvi.css`
14
+
15
+ ## Layout
16
+
17
+ - Section eyebrow (centered, tracked uppercase) + 2-color split headline span across the top, full width.
18
+ - Inner grid: portrait card on one side (4:5), block (eyebrow + heading + body) on the other.
19
+ - Circular text mark anchored to a corner of the section (`top-right` default, `top-left` / `bottom-right` / `bottom-left` available).
20
+ - Footer line: small eyebrow plus link, centered below the inner.
21
+
22
+ ## Tokens consumed
23
+
24
+ Brand: `--runwell-primary`, `--runwell-tertiary`, `--runwell-oat`, `--runwell-blue`. Design system: `--runwell-radius-xl`. Typography: `--runwell-eyebrow-size`, `--runwell-h2-size`, `--runwell-h3-size`, `--runwell-body-size`, `--runwell-meta-size`.
25
+
26
+ ## Lineage
27
+
28
+ Extracted from `https://home.medvi.org/` on 2026-05-06. Framer label: `Care Coaching`. Scrape path: `_clients/capital-v/lushi/research/medvi-reference/site-scrape/`.
29
+
30
+ The medvi reference shot:
31
+ - Eyebrow: `BETTER IS POSSIBLE, AND WE BUILT FOR IT.`
32
+ - Headline: `Modern healthcare,` (black) `built around you` (green accent), centered.
33
+ - Portrait: woman in beige sweater on warm-grey background.
34
+ - Circular mark: `WITH YOU FROM START TO SUCCESS` in soft tan, top-right of inner card.
35
+
36
+ ## Tenant overrides
37
+
38
+ - `runwell.config.json` brand block: rewires the global tokens.
39
+ - Per-instance Theme Editor: section eyebrow, headline split, accent color, portrait + card tint, block heading/eyebrow/body, circular text content + color + corner position, footer eyebrow + link, layout (portrait-left vs portrait-right), bg band.
40
+
41
+ ## Notes
42
+
43
+ - Circular mark animation: 30s per full turn, linear, infinite. Stops on `prefers-reduced-motion: reduce`.
44
+ - The SVG `textPath` snippet uses `id_suffix: section.id` to avoid id collisions when the section is dropped multiple times on the same page.
45
+ - Mobile: stacks portrait above block. Circular mark scales smaller and pulls in to corners.
46
+ - Block has its own oat-tinted background by default to lift it visually from the white section bg, mirroring medvi's reference. Override via `portrait_card_bg`-style additions if a different background is needed.