@salifbiaye/create-boutique 0.1.5 → 0.2.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 (64) hide show
  1. package/cli/dist/commands.js +3 -3
  2. package/cli/dist/create.js +5 -5
  3. package/cli/dist/generate.js +68 -10
  4. package/cli/dist/project.js +2 -0
  5. package/cli/dist/themes.js +5 -1
  6. package/package.json +1 -1
  7. package/templates/backend/src/lib/emails.ts +8 -1
  8. package/templates/backend/src/scripts/campaign-import.ts +6 -4
  9. package/templates/backend/src/scripts/seed.ts +15 -3
  10. package/templates/storefront/locales/en.json +33 -1
  11. package/templates/storefront/locales/fr.json +33 -1
  12. package/templates/storefront/package-lock.json +7 -0
  13. package/templates/storefront/package.json +1 -0
  14. package/templates/storefront/src/app/(main)/legal/[page]/page.tsx +3 -9
  15. package/templates/storefront/src/app/(main)/page.tsx +25 -0
  16. package/templates/storefront/src/app/(main)/store/page.tsx +3 -1
  17. package/templates/storefront/src/app/layout.tsx +9 -2
  18. package/templates/storefront/src/lib/boutique/config.ts +1 -0
  19. package/templates/storefront/src/lib/boutique/i18n-client.tsx +10 -2
  20. package/templates/storefront/src/lib/boutique/schema.ts +2 -0
  21. package/templates/storefront/src/modules/account/components/account-nav/index.tsx +50 -177
  22. package/templates/storefront/src/modules/account/components/address-card/add-address.tsx +2 -2
  23. package/templates/storefront/src/modules/account/components/address-card/edit-address-modal.tsx +2 -2
  24. package/templates/storefront/src/modules/account/components/overview/index.tsx +98 -143
  25. package/templates/storefront/src/modules/account/components/profile-billing-address/index.tsx +2 -3
  26. package/templates/storefront/src/modules/account/components/profile-phone/index.tsx +2 -3
  27. package/templates/storefront/src/modules/account/components/register/index.tsx +2 -3
  28. package/templates/storefront/src/modules/account/templates/account-layout.tsx +20 -24
  29. package/templates/storefront/src/modules/checkout/components/billing_address/index.tsx +2 -2
  30. package/templates/storefront/src/modules/checkout/components/shipping-address/index.tsx +2 -2
  31. package/templates/storefront/src/modules/common/components/phone-input/index.tsx +110 -0
  32. package/templates/storefront/src/modules/store/templates/index.tsx +82 -17
  33. package/templates/storefront/src/modules/store/templates/paginated-products.tsx +5 -0
  34. package/templates/storefront/src/modules/ub/campaign-blocks.tsx +1 -1
  35. package/templates/storefront/src/modules/ub/contact-page.tsx +78 -0
  36. package/templates/storefront/src/modules/ub/footer.tsx +26 -5
  37. package/templates/storefront/src/modules/ub/mobile-menu.tsx +49 -0
  38. package/templates/storefront/src/modules/ub/nav.tsx +2 -0
  39. package/templates/storefront/src/modules/ub/showcase.tsx +137 -0
  40. package/templates/storefront/src/styles/ub/account.css +199 -0
  41. package/templates/storefront/src/styles/ub/black-friday.css +96 -0
  42. package/templates/storefront/src/styles/ub/forms.css +61 -0
  43. package/templates/storefront/src/styles/ub/pages.css +382 -0
  44. package/templates/storefront/src/styles/ub/responsive.css +57 -0
  45. package/templates/storefront/src/styles/ub/showcase.css +85 -0
  46. package/templates/storefront/src/styles/ub/variants.css +64 -0
  47. package/templates/storefront/themes/black-friday-2/campaign.en.json +31 -0
  48. package/templates/storefront/themes/black-friday-2/campaign.fr.json +31 -0
  49. package/templates/storefront/themes/black-friday-2/theme.json +10 -0
  50. package/templates/storefront/themes/cyber-monday-2/campaign.en.json +31 -0
  51. package/templates/storefront/themes/cyber-monday-2/campaign.fr.json +31 -0
  52. package/templates/storefront/themes/cyber-monday-2/theme.json +10 -0
  53. package/templates/storefront/themes/halloween-2/campaign.en.json +31 -0
  54. package/templates/storefront/themes/halloween-2/campaign.fr.json +31 -0
  55. package/templates/storefront/themes/halloween-2/theme.json +10 -0
  56. package/templates/storefront/themes/noel-2/campaign.en.json +31 -0
  57. package/templates/storefront/themes/noel-2/campaign.fr.json +31 -0
  58. package/templates/storefront/themes/noel-2/theme.json +10 -0
  59. package/templates/storefront/themes/nouvel-an-2/campaign.en.json +31 -0
  60. package/templates/storefront/themes/nouvel-an-2/campaign.fr.json +31 -0
  61. package/templates/storefront/themes/nouvel-an-2/theme.json +10 -0
  62. package/templates/storefront/themes/thanksgiving-2/campaign.en.json +31 -0
  63. package/templates/storefront/themes/thanksgiving-2/campaign.fr.json +31 -0
  64. package/templates/storefront/themes/thanksgiving-2/theme.json +10 -0
@@ -0,0 +1,137 @@
1
+ import Link from "next/link"
2
+ import { t } from "@lib/boutique/i18n"
3
+ import { getProductPrice } from "@lib/util/get-product-price"
4
+ import { HttpTypes } from "@medusajs/types"
5
+ import { Icon } from "./icons"
6
+
7
+ type P = HttpTypes.StoreProduct
8
+ const imageOf = (p: P) => p.thumbnail ?? p.images?.[0]?.url ?? undefined
9
+ const priceOf = (p: P) => {
10
+ const { cheapestPrice: price } = getProductPrice({ product: p })
11
+ return { price, onSale: price?.price_type === "sale" }
12
+ }
13
+
14
+ /**
15
+ * « Offres phares » en accordéon : les cartes repliées montrent le nom à la verticale ; au survol ou au focus
16
+ * (clavier, toucher) une carte s'ouvre en grand avec photo, prix et remise. CSS seul, aucun JavaScript.
17
+ */
18
+ export function DealsFold({ products, title }: { products: P[]; title: string }) {
19
+ const items = products.slice(0, 5)
20
+ if (items.length < 3) return null
21
+
22
+ return (
23
+ <section className="ub-section">
24
+ <div className="ub-wrap">
25
+ <h2 className="ub-head ub-fold__title">{title}</h2>
26
+ <ul className="ub-fold">
27
+ {items.map((p, i) => {
28
+ const { price, onSale } = priceOf(p)
29
+ const image = imageOf(p)
30
+ return (
31
+ <li key={p.id} className="ub-fold__item">
32
+ <Link href={`/products/${p.handle}`} className="ub-fold__link" aria-label={t("card.view", { name: p.title ?? "" })}>
33
+ {image ? (
34
+ // eslint-disable-next-line @next/next/no-img-element
35
+ <img className="ub-fold__img" src={image} alt="" loading="lazy" />
36
+ ) : (
37
+ <span className="ub-fold__img ub-ph" />
38
+ )}
39
+ <span className="ub-fold__label">
40
+ <span className="ub-fold__num">{String(i + 1).padStart(2, "0")}</span>
41
+ {p.title}
42
+ </span>
43
+ <span className="ub-fold__body">
44
+ {onSale && price?.percentage_diff && <b className="ub-fold__off">-{price.percentage_diff}%</b>}
45
+ <span className="ub-fold__name">{p.title}</span>
46
+ {price && (
47
+ <span className="ub-fold__price">
48
+ {price.calculated_price}
49
+ {onSale && <s>{price.original_price}</s>}
50
+ </span>
51
+ )}
52
+ <span className="ub-fold__go" aria-hidden>
53
+ <Icon name="arrowUpRight" />
54
+ </span>
55
+ </span>
56
+ </Link>
57
+ </li>
58
+ )
59
+ })}
60
+ </ul>
61
+ </div>
62
+ </section>
63
+ )
64
+ }
65
+
66
+ /**
67
+ * Grande carte sombre : visuel du produit choisi à gauche, liste d'offres à droite (onglets radio + :has(),
68
+ * sans JavaScript). La première offre est sélectionnée par défaut.
69
+ */
70
+ export function DealsSpotlight({ products, eyebrow, title }: { products: P[]; eyebrow?: string; title: string }) {
71
+ const items = products.slice(0, 4)
72
+ if (items.length < 2) return null
73
+
74
+ return (
75
+ <section className="ub-section">
76
+ <div className="ub-wrap">
77
+ <div className="ub-spot">
78
+ <div className="ub-spot__head">
79
+ {eyebrow && (
80
+ <span className="ub-eyebrow">
81
+ <span className="ub-eyebrow__dot" />
82
+ {eyebrow}
83
+ </span>
84
+ )}
85
+ <h2 className="ub-head ub-spot__title">{title}</h2>
86
+ </div>
87
+ <div className="ub-spot__grid">
88
+ <div className="ub-spot__stage">
89
+ {items.map((p, i) => {
90
+ const image = imageOf(p)
91
+ return (
92
+ <div key={p.id} className="ub-spot__media" data-i={i}>
93
+ {image ? (
94
+ // eslint-disable-next-line @next/next/no-img-element
95
+ <img src={image} alt={p.title ?? ""} loading="lazy" />
96
+ ) : (
97
+ <span className="ub-ph" />
98
+ )}
99
+ </div>
100
+ )
101
+ })}
102
+ </div>
103
+ <div className="ub-spot__list" role="radiogroup" aria-label={title}>
104
+ {items.map((p, i) => {
105
+ const { price, onSale } = priceOf(p)
106
+ return (
107
+ <div key={p.id} className="ub-spot__item" data-i={i}>
108
+ <input type="radio" name="ub-spot" id={`ub-spot-${i}`} defaultChecked={i === 0} className="ub-spot__radio" />
109
+ <label htmlFor={`ub-spot-${i}`} className="ub-spot__label">
110
+ <span className="ub-spot__num">{String(i + 1).padStart(2, "0")}</span>
111
+ <span className="ub-spot__name">{p.title}</span>
112
+ {onSale && price?.percentage_diff && <b className="ub-spot__off">-{price.percentage_diff}%</b>}
113
+ </label>
114
+ <div className="ub-spot__more">
115
+ {p.description && <p>{p.description}</p>}
116
+ <div className="ub-spot__buy">
117
+ {price && (
118
+ <span className="ub-spot__price">
119
+ {price.calculated_price}
120
+ {onSale && <s>{price.original_price}</s>}
121
+ </span>
122
+ )}
123
+ <Link href={`/products/${p.handle}`} className="ub-spot__cta">
124
+ {t("card.viewShort")} <Icon name="arrowRight" />
125
+ </Link>
126
+ </div>
127
+ </div>
128
+ </div>
129
+ )
130
+ })}
131
+ </div>
132
+ </div>
133
+ </div>
134
+ </div>
135
+ </section>
136
+ )
137
+ }
@@ -0,0 +1,199 @@
1
+ /* Espace client : menu latéral, tableau de bord, formulaires de connexion. Tokens du thème uniquement. */
2
+ .ub-account { padding-top: var(--space-12); padding-bottom: var(--space-12); }
3
+ .ub-account__grid { display: grid; grid-template-columns: 280px minmax(0, 1fr); gap: var(--space-8); align-items: start; }
4
+ .ub-account__solo { display: grid; justify-items: center; }
5
+ .ub-account__solo .ub-account__main {
6
+ width: 100%;
7
+ max-width: 480px;
8
+ padding: clamp(24px, 4vw, 40px);
9
+ background: var(--surface);
10
+ border: 1px solid var(--border);
11
+ border-radius: var(--ub-r-card);
12
+ }
13
+ .ub-account__main { min-width: 0; }
14
+
15
+ /* ---------- Menu latéral ---------- */
16
+ .ub-accnav { position: sticky; top: 96px; display: grid; gap: var(--space-4); }
17
+ .ub-accnav__me {
18
+ display: flex;
19
+ align-items: center;
20
+ gap: var(--space-3);
21
+ padding: var(--space-4);
22
+ background: var(--surface);
23
+ border: 1px solid var(--border);
24
+ border-radius: var(--ub-r-card);
25
+ }
26
+ .ub-accnav__avatar {
27
+ flex: none;
28
+ display: grid;
29
+ place-items: center;
30
+ width: 48px;
31
+ height: 48px;
32
+ border-radius: 50%;
33
+ background: var(--primary);
34
+ color: var(--on-primary);
35
+ font-family: var(--ub-font-head);
36
+ font-weight: 700;
37
+ font-size: 17px;
38
+ letter-spacing: 0.02em;
39
+ }
40
+ .ub-accnav__who { display: grid; min-width: 0; }
41
+ .ub-accnav__who b { font-size: 15px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
42
+ .ub-accnav__who small { font-size: 12px; color: var(--ink-muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
43
+ .ub-accnav__list {
44
+ display: grid;
45
+ gap: 4px;
46
+ margin: 0;
47
+ padding: var(--space-2);
48
+ list-style: none;
49
+ background: var(--surface);
50
+ border: 1px solid var(--border);
51
+ border-radius: var(--ub-r-card);
52
+ }
53
+ .ub-accnav__link {
54
+ position: relative;
55
+ display: flex;
56
+ align-items: center;
57
+ gap: var(--space-3);
58
+ width: 100%;
59
+ padding: 11px 12px;
60
+ border-radius: calc(var(--ub-r-card) * 0.6);
61
+ font-size: 15px;
62
+ font-weight: 500;
63
+ color: var(--ink-muted);
64
+ text-align: left;
65
+ transition: background 0.15s, color 0.15s;
66
+ }
67
+ .ub-accnav__link:hover { background: var(--tint-1); color: var(--ink); }
68
+ .ub-accnav__link[aria-current="page"] { background: color-mix(in srgb, var(--primary) 14%, transparent); color: var(--ink); font-weight: 700; }
69
+ .ub-accnav__link[aria-current="page"] .ub-accnav__ic { color: var(--primary); }
70
+ .ub-accnav__ic { display: inline-grid; place-items: center; width: 20px; height: 20px; }
71
+ .ub-accnav__ic svg { width: 20px; height: 20px; }
72
+ .ub-accnav__logout { margin-top: 4px; border-top: 1px solid var(--border); border-radius: 0 0 calc(var(--ub-r-card) * 0.6) calc(var(--ub-r-card) * 0.6); }
73
+ .ub-accnav__logout:hover { color: var(--sale); }
74
+
75
+ /* ---------- Tableau de bord ---------- */
76
+ .ub-acc { display: grid; gap: var(--space-6); }
77
+ .ub-acc__hello {
78
+ position: relative;
79
+ overflow: hidden;
80
+ display: flex;
81
+ align-items: flex-end;
82
+ justify-content: space-between;
83
+ gap: var(--space-4);
84
+ flex-wrap: wrap;
85
+ padding: clamp(24px, 4vw, 40px);
86
+ background: var(--hero-bg);
87
+ color: var(--hero-ink);
88
+ border-radius: var(--ub-r-card);
89
+ }
90
+ .ub-acc__hello::before {
91
+ content: "";
92
+ position: absolute;
93
+ right: -80px;
94
+ top: -120px;
95
+ width: 320px;
96
+ aspect-ratio: 1;
97
+ border-radius: 50%;
98
+ background: radial-gradient(circle, color-mix(in srgb, var(--primary) 35%, transparent), transparent 65%);
99
+ pointer-events: none;
100
+ }
101
+ .ub-acc__hello h1 { position: relative; font-size: clamp(28px, 3.4vw, 42px); line-height: 1.05; }
102
+ .ub-acc__hello p { position: relative; margin-top: 8px !important; font-size: 14px; color: var(--hero-muted); }
103
+ .ub-acc__hello p b { color: var(--hero-ink); }
104
+ .ub-acc__shop {
105
+ position: relative;
106
+ display: inline-flex;
107
+ align-items: center;
108
+ gap: 6px;
109
+ padding: 10px 18px;
110
+ border-radius: var(--ub-r-btn);
111
+ background: var(--primary);
112
+ color: var(--on-primary);
113
+ font-size: 14px;
114
+ font-weight: 700;
115
+ }
116
+ .ub-acc__shop svg, .ub-acc__more svg, .ub-acc__order > svg { width: 16px; height: 16px; }
117
+ .ub-acc__stats { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--space-4); margin: 0; padding: 0; list-style: none; }
118
+ .ub-acc__stat {
119
+ display: grid;
120
+ gap: 4px;
121
+ padding: var(--space-6);
122
+ background: var(--surface);
123
+ border: 1px solid var(--border);
124
+ border-radius: var(--ub-r-card);
125
+ transition: transform 0.2s, border-color 0.2s;
126
+ }
127
+ .ub-acc__stat:hover { transform: translateY(-2px); border-color: var(--primary); }
128
+ .ub-acc__stat b { margin-top: var(--space-3); font-family: var(--ub-font-head); font-size: 36px; line-height: 1; }
129
+ .ub-acc__stat small { font-size: 13px; color: var(--ink-muted); }
130
+ .ub-acc__ic {
131
+ display: inline-grid;
132
+ place-items: center;
133
+ width: 40px;
134
+ height: 40px;
135
+ border-radius: 12px;
136
+ background: color-mix(in srgb, var(--primary) 16%, transparent);
137
+ color: var(--primary);
138
+ }
139
+ .ub-acc__ic svg { width: 20px; height: 20px; }
140
+ .ub-acc__progress { display: grid; gap: 8px; font-size: 13px; color: var(--ink-muted); }
141
+ .ub-acc__progress i { display: block; height: 6px; border-radius: 99px; background: var(--tint-1); overflow: hidden; }
142
+ .ub-acc__progress i::before { content: ""; display: block; width: var(--p); height: 100%; background: var(--primary); border-radius: inherit; }
143
+ .ub-acc__head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--space-4); }
144
+ .ub-acc__head h2 { font-size: 22px; }
145
+ .ub-acc__more { display: inline-flex; align-items: center; gap: 6px; font-size: 14px; font-weight: 600; color: var(--primary); }
146
+ .ub-acc__orders { display: grid; gap: var(--space-2); margin: 0; padding: 0; list-style: none; }
147
+ .ub-acc__order {
148
+ display: grid;
149
+ grid-template-columns: auto 1fr auto auto;
150
+ align-items: center;
151
+ gap: var(--space-4);
152
+ padding: var(--space-4);
153
+ background: var(--surface);
154
+ border: 1px solid var(--border);
155
+ border-radius: var(--ub-r-card);
156
+ transition: border-color 0.15s;
157
+ }
158
+ .ub-acc__order:hover { border-color: var(--primary); }
159
+ .ub-acc__order span:nth-child(2) { display: grid; }
160
+ .ub-acc__order small { font-size: 13px; color: var(--ink-muted); }
161
+ .ub-acc__amount { font-weight: 700; }
162
+ .ub-acc__empty {
163
+ display: grid;
164
+ justify-items: center;
165
+ gap: var(--space-3);
166
+ padding: var(--space-12) var(--space-6);
167
+ text-align: center;
168
+ background: var(--surface);
169
+ border: 1px dashed var(--border);
170
+ border-radius: var(--ub-r-card);
171
+ }
172
+
173
+ /* ---------- Aide ---------- */
174
+ .ub-account__help {
175
+ display: flex;
176
+ align-items: center;
177
+ justify-content: space-between;
178
+ gap: var(--space-6);
179
+ flex-wrap: wrap;
180
+ margin-top: var(--space-12);
181
+ padding: var(--space-6) var(--space-8);
182
+ background: var(--surface);
183
+ border: 1px solid var(--border);
184
+ border-radius: var(--ub-r-card);
185
+ }
186
+ .ub-account__help h3 { font-size: 22px; }
187
+ .ub-account__help p { margin-top: 4px !important; color: var(--ink-muted); font-size: 14px; }
188
+
189
+ @media (max-width: 900px) {
190
+ .ub-account__grid { grid-template-columns: minmax(0, 1fr); gap: var(--space-4); }
191
+ .ub-accnav { position: static; }
192
+ .ub-accnav__list { display: flex; overflow-x: auto; scrollbar-width: none; }
193
+ .ub-accnav__list li { flex: none; }
194
+ .ub-accnav__link { white-space: nowrap; }
195
+ .ub-accnav__logout { margin-top: 0; border-top: 0; }
196
+ .ub-acc__stats { grid-template-columns: minmax(0, 1fr); }
197
+ .ub-acc__order { grid-template-columns: auto 1fr auto; }
198
+ .ub-acc__order > svg { display: none; }
199
+ }
@@ -0,0 +1,96 @@
1
+ /* Black Friday (thème de base, clair) : jaune / noir / blanc. Sections volontairement différentes de la variante
2
+ « Blackout » (black-friday-2, sombre) : grille bento au lieu de l'accordéon, carte jaune, bandeau « ruban de chantier ».
3
+ :not([data-variant]) : la variante halloween-2 emprunte la mise en page black-friday et ne doit pas hériter de ceci. */
4
+ [data-theme="black-friday"]:not([data-variant]) {
5
+ --bg: #ffffff; --surface: #f6f6f3; --tint-1: #fff6c2; --tint-2: #f4f4f2; --tint-3: #fde8e8; --tint-4: #f1f1ee;
6
+ --ink: #0a0a0a; --ink-muted: #525252; --border: #e6e6e1;
7
+ --primary: #ffd400; --on-primary: #0a0a0a; --accent: #0a0a0a; --on-accent: #ffd400;
8
+ --sale: #e11d48; --star: #f59e0b; --success: #15803d;
9
+ --hero-bg: #0a0a0a; --hero-ink: #ffffff; --hero-muted: #a3a3a3;
10
+ --band-bg: #ffd400; --band-ink: #0a0a0a; --bubble-bg: #ffd400; --bubble-ink: #0a0a0a;
11
+ --topbar-bg: #0a0a0a; --topbar-ink: #ffd400; --focus: #2563eb;
12
+ }
13
+ :root:not([data-variant])[data-theme="black-friday"] .ub-hero__title em { color: var(--primary); font-style: normal; }
14
+
15
+ /* ---------- Cartes produit : blanches, fine bordure, contour noir au survol ---------- */
16
+ [data-theme="black-friday"]:not([data-variant]) .ub-card { border: 1px solid var(--border); box-shadow: none; transition: transform 0.2s, border-color 0.2s; }
17
+ [data-theme="black-friday"]:not([data-variant]) .ub-card:hover { transform: translateY(-3px); border-color: var(--ink); }
18
+ [data-theme="black-friday"]:not([data-variant]) .ub-badge--sale { background: var(--primary); color: #0a0a0a; }
19
+
20
+ /* ---------- Offres phares : grille bento (toutes les cartes ouvertes) ---------- */
21
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold {
22
+ display: grid;
23
+ grid-template-columns: 2fr 1fr 1fr;
24
+ grid-template-rows: 1fr 1fr;
25
+ height: clamp(460px, 48vw, 640px);
26
+ }
27
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__item { flex: none !important; }
28
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__item:first-child { grid-row: span 2; }
29
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__link { border-radius: var(--radius-md); border: 1px solid var(--border); background: var(--surface); }
30
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__link::after { display: none; }
31
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__img { opacity: 1 !important; transform: none !important; }
32
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__item:hover .ub-fold__img { transform: scale(1.04) !important; }
33
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__label { display: none; }
34
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__body {
35
+ opacity: 1 !important;
36
+ transform: none !important;
37
+ left: 12px;
38
+ right: 12px;
39
+ bottom: 12px;
40
+ padding: 12px 64px 12px 14px;
41
+ background: var(--bg);
42
+ color: var(--ink);
43
+ border-radius: var(--radius-md);
44
+ box-shadow: 0 8px 24px rgb(0 0 0 / 0.12);
45
+ }
46
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__name { font-size: clamp(16px, 1.6vw, 22px); }
47
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__item:first-child .ub-fold__name { font-size: clamp(22px, 2.6vw, 34px); }
48
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__price { font-size: 17px; }
49
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__price s { opacity: 0.5; }
50
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__off { position: absolute; top: -14px; left: 14px; background: var(--sale); color: #fff; }
51
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__go { right: 12px; bottom: 50%; transform: translateY(50%); width: 40px; height: 40px; background: var(--primary); color: #0a0a0a; backdrop-filter: none; }
52
+
53
+ /* ---------- Carte d'offres : jaune, zone visuelle noire ---------- */
54
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot { background: var(--primary); color: #0a0a0a; }
55
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot::before { background: radial-gradient(circle, rgb(255 255 255 / 0.45), transparent 65%); }
56
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot .ub-eyebrow { color: #0a0a0a; }
57
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__stage { background: #0a0a0a; box-shadow: 18px 18px 0 rgb(0 0 0 / 0.9); border-radius: var(--radius-md); }
58
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__item { border-bottom-color: rgb(0 0 0 / 0.15); }
59
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__item::before { background: #0a0a0a; width: 4px; }
60
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__item:has(.ub-spot__radio:checked) { background: rgb(255 255 255 / 0.45); }
61
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__num,
62
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__off { color: #0a0a0a; }
63
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__off { background: rgb(0 0 0 / 0.1); }
64
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__more p { color: rgb(10 10 10 / 0.72); }
65
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__cta { background: #0a0a0a; color: var(--primary); }
66
+
67
+ /* ---------- Bandeau CTA « ruban de chantier » + pied de page clair ---------- */
68
+ [data-theme="black-friday"]:not([data-variant]) .ub-footwrap { --cta-bg: #0a0a0a; --cta-ink: #ffffff; --foot-bg: var(--surface); --foot-ink: var(--ink); }
69
+ [data-theme="black-friday"]:not([data-variant]) .ub-footcta { background: #0a0a0a; border-radius: var(--radius-md); padding-top: clamp(64px, 8vw, 104px); padding-bottom: clamp(64px, 8vw, 104px); }
70
+ [data-theme="black-friday"]:not([data-variant]) .ub-footcta__shape { display: none; }
71
+ [data-theme="black-friday"]:not([data-variant]) .ub-footcta::before,
72
+ [data-theme="black-friday"]:not([data-variant]) .ub-footcta::after {
73
+ content: "";
74
+ position: absolute;
75
+ left: 0;
76
+ right: 0;
77
+ height: 16px;
78
+ background: repeating-linear-gradient(-45deg, var(--primary) 0 18px, #0a0a0a 18px 36px);
79
+ }
80
+ [data-theme="black-friday"]:not([data-variant]) .ub-footcta::before { top: 0; }
81
+ [data-theme="black-friday"]:not([data-variant]) .ub-footcta::after { bottom: 0; }
82
+ [data-theme="black-friday"]:not([data-variant]) .ub-footcta__title em { color: var(--primary); text-decoration: none; }
83
+ [data-theme="black-friday"]:not([data-variant]) .ub-footcta__eyebrow { background: var(--primary); color: #0a0a0a; }
84
+ [data-theme="black-friday"]:not([data-variant]) .ub-footcta .ub-footcta__btn { background: var(--primary); color: #0a0a0a; border-color: var(--primary); }
85
+ [data-theme="black-friday"]:not([data-variant]) .ub-footwrap .ub-footer { border: 1px solid var(--border); border-radius: var(--radius-md); }
86
+ [data-theme="black-friday"]:not([data-variant]) .ub-footwrap .ub-footer .ub-logo__mark { background: var(--primary); }
87
+ [data-theme="black-friday"]:not([data-variant]) .ub-footwrap .ub-pays span { background: var(--bg); }
88
+
89
+ @media (max-width: 900px) {
90
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold { grid-template-columns: 1fr 1fr; grid-template-rows: none; grid-auto-rows: 220px; height: auto; flex-direction: row; }
91
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__item { height: auto !important; }
92
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__item:first-child { grid-column: span 2; grid-row: span 1; }
93
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__body { padding-right: 52px; }
94
+ [data-theme="black-friday"]:not([data-variant]) .ub-fold__item:not(:first-child) .ub-fold__price s { display: none; }
95
+ [data-theme="black-friday"]:not([data-variant]) .ub-spot__stage { box-shadow: 10px 10px 0 rgb(0 0 0 / 0.9); }
96
+ }
@@ -0,0 +1,61 @@
1
+ /* Téléphone avec indicatif pays (modules/common/components/phone-input). Même hauteur et mêmes couleurs
2
+ que les autres champs (variables Medusa UI rebranchées sur le thème dans medusa-ui.css). */
3
+ .ub-phone { display: flex; gap: 8px; width: 100%; }
4
+ .ub-phone__country {
5
+ position: relative;
6
+ flex: none;
7
+ display: flex;
8
+ align-items: center;
9
+ height: 44px;
10
+ padding: 0 32px 0 14px;
11
+ border: 1px solid var(--border-base);
12
+ border-radius: 0.375rem;
13
+ background: var(--bg-field);
14
+ font-size: 14px;
15
+ font-weight: 600;
16
+ white-space: nowrap;
17
+ cursor: pointer;
18
+ }
19
+ .ub-phone__country::after {
20
+ content: "";
21
+ position: absolute;
22
+ right: 12px;
23
+ top: 50%;
24
+ width: 7px;
25
+ height: 7px;
26
+ border-right: 1.5px solid currentColor;
27
+ border-bottom: 1.5px solid currentColor;
28
+ transform: translateY(-70%) rotate(45deg);
29
+ opacity: 0.6;
30
+ }
31
+ .ub-phone__country:hover { background: var(--bg-field-hover); }
32
+ .ub-phone__country:focus-within { box-shadow: var(--borders-interactive-with-active); }
33
+ .ub-phone__country select { position: absolute; inset: 0; width: 100%; opacity: 0; cursor: pointer; }
34
+ .ub-phone__flag { pointer-events: none; }
35
+ .ub-phone__field { position: relative; z-index: 0; flex: 1; min-width: 0; font-size: 14px; }
36
+ .ub-phone__field input {
37
+ display: block;
38
+ width: 100%;
39
+ height: 44px;
40
+ padding: 16px 16px 4px;
41
+ border: 1px solid var(--border-base);
42
+ border-radius: 0.375rem;
43
+ background: var(--bg-field);
44
+ color: inherit;
45
+ outline: none;
46
+ }
47
+ .ub-phone__field input:hover { background: var(--bg-field-hover); }
48
+ .ub-phone__field input:focus { box-shadow: var(--borders-interactive-with-active); }
49
+ .ub-phone__field label {
50
+ position: absolute;
51
+ top: 12px;
52
+ left: 0;
53
+ z-index: 1;
54
+ margin: 0 12px;
55
+ padding: 0 4px;
56
+ color: var(--fg-subtle);
57
+ transform-origin: 0 0;
58
+ transition: transform 0.3s, font-size 0.3s;
59
+ pointer-events: none;
60
+ }
61
+ .ub-phone[data-invalid] .ub-phone__field input { border-color: var(--sale); }