@salifbiaye/create-boutique 0.1.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.
Files changed (316) hide show
  1. package/README.md +1 -0
  2. package/cli/dist/commands.js +382 -0
  3. package/cli/dist/create.js +194 -0
  4. package/cli/dist/docker.js +19 -0
  5. package/cli/dist/generate.js +322 -0
  6. package/cli/dist/guide.js +72 -0
  7. package/cli/dist/index.js +156 -0
  8. package/cli/dist/paths.js +29 -0
  9. package/cli/dist/ports.js +54 -0
  10. package/cli/dist/project.js +119 -0
  11. package/cli/dist/themes.js +24 -0
  12. package/docs/fiche-client.en.html +137 -0
  13. package/docs/fiche-client.html +137 -0
  14. package/docs/guide-complet.en.html +259 -0
  15. package/docs/guide-complet.fr.html +259 -0
  16. package/package.json +51 -0
  17. package/templates/backend/.dockerignore +9 -0
  18. package/templates/backend/Dockerfile +30 -0
  19. package/templates/backend/README.md +78 -0
  20. package/templates/backend/TEMPLATE_VERSION +1 -0
  21. package/templates/backend/docker/entrypoint.sh +28 -0
  22. package/templates/backend/instrumentation.ts +24 -0
  23. package/templates/backend/medusa-config.ts +114 -0
  24. package/templates/backend/package-lock.json +16222 -0
  25. package/templates/backend/package.json +39 -0
  26. package/templates/backend/src/admin/README.md +33 -0
  27. package/templates/backend/src/admin/components/image-field.tsx +61 -0
  28. package/templates/backend/src/admin/i18n/README.md +58 -0
  29. package/templates/backend/src/admin/i18n/index.ts +8 -0
  30. package/templates/backend/src/admin/i18n/json/en.json +66 -0
  31. package/templates/backend/src/admin/i18n/json/fr.json +66 -0
  32. package/templates/backend/src/admin/lib/client.ts +9 -0
  33. package/templates/backend/src/admin/routes/boutique-campaigns/campaign-drawer.tsx +286 -0
  34. package/templates/backend/src/admin/routes/boutique-campaigns/page.tsx +113 -0
  35. package/templates/backend/src/admin/tsconfig.json +24 -0
  36. package/templates/backend/src/admin/vite-env.d.ts +1 -0
  37. package/templates/backend/src/admin/widgets/category-image.tsx +56 -0
  38. package/templates/backend/src/api/README.md +135 -0
  39. package/templates/backend/src/api/admin/boutique-campaigns/[salesChannelId]/route.ts +30 -0
  40. package/templates/backend/src/api/admin/boutique-campaigns/route.ts +24 -0
  41. package/templates/backend/src/api/middlewares.ts +28 -0
  42. package/templates/backend/src/api/rate-limit.ts +30 -0
  43. package/templates/backend/src/api/route.ts +6 -0
  44. package/templates/backend/src/api/store/campaign/route.ts +25 -0
  45. package/templates/backend/src/api/store/order-lookup/route.ts +74 -0
  46. package/templates/backend/src/emails/en.json +64 -0
  47. package/templates/backend/src/emails/fr.json +64 -0
  48. package/templates/backend/src/jobs/README.md +38 -0
  49. package/templates/backend/src/lib/emails.ts +94 -0
  50. package/templates/backend/src/lib/notify.ts +148 -0
  51. package/templates/backend/src/lib/project.ts +146 -0
  52. package/templates/backend/src/links/README.md +26 -0
  53. package/templates/backend/src/links/campaign-sales-channel.ts +9 -0
  54. package/templates/backend/src/modules/README.md +117 -0
  55. package/templates/backend/src/modules/campaign/index.ts +9 -0
  56. package/templates/backend/src/modules/campaign/migrations/.snapshot-boutique-campaign.json +272 -0
  57. package/templates/backend/src/modules/campaign/migrations/Migration20260928141440.ts +16 -0
  58. package/templates/backend/src/modules/campaign/migrations/Migration20260928145243.ts +13 -0
  59. package/templates/backend/src/modules/campaign/models/campaign.ts +28 -0
  60. package/templates/backend/src/modules/campaign/service.ts +6 -0
  61. package/templates/backend/src/modules/campaign/validators.ts +94 -0
  62. package/templates/backend/src/modules/resend/index.ts +6 -0
  63. package/templates/backend/src/modules/resend/service.ts +63 -0
  64. package/templates/backend/src/scripts/README.md +63 -0
  65. package/templates/backend/src/scripts/campaign-export.ts +15 -0
  66. package/templates/backend/src/scripts/campaign-import.ts +38 -0
  67. package/templates/backend/src/scripts/price-report.ts +34 -0
  68. package/templates/backend/src/scripts/seed.ts +418 -0
  69. package/templates/backend/src/scripts/storage.ts +63 -0
  70. package/templates/backend/src/subscribers/README.md +61 -0
  71. package/templates/backend/src/subscribers/account-emails.ts +27 -0
  72. package/templates/backend/src/subscribers/fulfillment-emails.ts +42 -0
  73. package/templates/backend/src/subscribers/order-emails.ts +12 -0
  74. package/templates/backend/src/subscribers/return-refund-emails.ts +50 -0
  75. package/templates/backend/src/workflows/README.md +81 -0
  76. package/templates/backend/src/workflows/steps/upsert-campaign.ts +53 -0
  77. package/templates/backend/src/workflows/upsert-campaign.ts +30 -0
  78. package/templates/backend/tsconfig.json +36 -0
  79. package/templates/storefront/.dockerignore +7 -0
  80. package/templates/storefront/.github/ISSUE_TEMPLATE/bug-report.yml +71 -0
  81. package/templates/storefront/.prettierrc +8 -0
  82. package/templates/storefront/Dockerfile +37 -0
  83. package/templates/storefront/LICENSE +21 -0
  84. package/templates/storefront/README.md +127 -0
  85. package/templates/storefront/locales/en.json +269 -0
  86. package/templates/storefront/locales/fr.json +269 -0
  87. package/templates/storefront/next-env.d.ts +7 -0
  88. package/templates/storefront/next-sitemap.js +19 -0
  89. package/templates/storefront/next.config.js +29 -0
  90. package/templates/storefront/package-lock.json +9031 -0
  91. package/templates/storefront/package.json +49 -0
  92. package/templates/storefront/postcss.config.js +6 -0
  93. package/templates/storefront/public/favicon.ico +0 -0
  94. package/templates/storefront/scripts/sync-design.mjs +30 -0
  95. package/templates/storefront/src/app/(checkout)/checkout/page.tsx +31 -0
  96. package/templates/storefront/src/app/(checkout)/layout.tsx +29 -0
  97. package/templates/storefront/src/app/(checkout)/not-found.tsx +20 -0
  98. package/templates/storefront/src/app/(main)/account/@dashboard/addresses/page.tsx +34 -0
  99. package/templates/storefront/src/app/(main)/account/@dashboard/loading.tsx +9 -0
  100. package/templates/storefront/src/app/(main)/account/@dashboard/orders/details/[id]/page.tsx +33 -0
  101. package/templates/storefront/src/app/(main)/account/@dashboard/orders/page.tsx +37 -0
  102. package/templates/storefront/src/app/(main)/account/@dashboard/page.tsx +22 -0
  103. package/templates/storefront/src/app/(main)/account/@dashboard/profile/page.tsx +53 -0
  104. package/templates/storefront/src/app/(main)/account/@login/page.tsx +12 -0
  105. package/templates/storefront/src/app/(main)/account/layout.tsx +20 -0
  106. package/templates/storefront/src/app/(main)/account/loading.tsx +9 -0
  107. package/templates/storefront/src/app/(main)/cart/loading.tsx +5 -0
  108. package/templates/storefront/src/app/(main)/cart/not-found.tsx +21 -0
  109. package/templates/storefront/src/app/(main)/cart/page.tsx +21 -0
  110. package/templates/storefront/src/app/(main)/categories/[...category]/page.tsx +55 -0
  111. package/templates/storefront/src/app/(main)/collections/[handle]/page.tsx +55 -0
  112. package/templates/storefront/src/app/(main)/layout.tsx +43 -0
  113. package/templates/storefront/src/app/(main)/legal/[page]/page.tsx +42 -0
  114. package/templates/storefront/src/app/(main)/not-found.tsx +21 -0
  115. package/templates/storefront/src/app/(main)/order/[id]/confirmed/loading.tsx +5 -0
  116. package/templates/storefront/src/app/(main)/order/[id]/confirmed/page.tsx +23 -0
  117. package/templates/storefront/src/app/(main)/order/[id]/transfer/[token]/accept/page.tsx +42 -0
  118. package/templates/storefront/src/app/(main)/order/[id]/transfer/[token]/decline/page.tsx +42 -0
  119. package/templates/storefront/src/app/(main)/order/[id]/transfer/[token]/page.tsx +35 -0
  120. package/templates/storefront/src/app/(main)/order/track/page.tsx +32 -0
  121. package/templates/storefront/src/app/(main)/page.tsx +68 -0
  122. package/templates/storefront/src/app/(main)/products/[handle]/page.tsx +86 -0
  123. package/templates/storefront/src/app/(main)/store/page.tsx +28 -0
  124. package/templates/storefront/src/app/api/health/route.ts +13 -0
  125. package/templates/storefront/src/app/layout.tsx +42 -0
  126. package/templates/storefront/src/app/not-found.tsx +21 -0
  127. package/templates/storefront/src/app/opengraph-image.jpg +0 -0
  128. package/templates/storefront/src/app/twitter-image.jpg +0 -0
  129. package/templates/storefront/src/instrumentation-node.ts +18 -0
  130. package/templates/storefront/src/instrumentation.ts +9 -0
  131. package/templates/storefront/src/lib/boutique/campaign.ts +116 -0
  132. package/templates/storefront/src/lib/boutique/config.ts +152 -0
  133. package/templates/storefront/src/lib/boutique/fonts.ts +29 -0
  134. package/templates/storefront/src/lib/boutique/i18n-client.tsx +34 -0
  135. package/templates/storefront/src/lib/boutique/i18n.ts +43 -0
  136. package/templates/storefront/src/lib/boutique/schema.ts +131 -0
  137. package/templates/storefront/src/lib/config.ts +39 -0
  138. package/templates/storefront/src/lib/constants.tsx +75 -0
  139. package/templates/storefront/src/lib/context/modal-context.tsx +34 -0
  140. package/templates/storefront/src/lib/data/cart.ts +434 -0
  141. package/templates/storefront/src/lib/data/categories.ts +49 -0
  142. package/templates/storefront/src/lib/data/collections.ts +59 -0
  143. package/templates/storefront/src/lib/data/cookies.ts +103 -0
  144. package/templates/storefront/src/lib/data/customer.ts +261 -0
  145. package/templates/storefront/src/lib/data/fulfillment.ts +68 -0
  146. package/templates/storefront/src/lib/data/onboarding.ts +9 -0
  147. package/templates/storefront/src/lib/data/order-lookup.ts +34 -0
  148. package/templates/storefront/src/lib/data/orders.ts +112 -0
  149. package/templates/storefront/src/lib/data/payment.ts +35 -0
  150. package/templates/storefront/src/lib/data/products.ts +127 -0
  151. package/templates/storefront/src/lib/data/regions.ts +70 -0
  152. package/templates/storefront/src/lib/data/variants.ts +38 -0
  153. package/templates/storefront/src/lib/hooks/use-in-view.tsx +29 -0
  154. package/templates/storefront/src/lib/hooks/use-toggle-state.tsx +46 -0
  155. package/templates/storefront/src/lib/util/compare-addresses.ts +28 -0
  156. package/templates/storefront/src/lib/util/get-percentage-diff.ts +6 -0
  157. package/templates/storefront/src/lib/util/get-product-price.ts +79 -0
  158. package/templates/storefront/src/lib/util/isEmpty.ts +11 -0
  159. package/templates/storefront/src/lib/util/medusa-error.ts +22 -0
  160. package/templates/storefront/src/lib/util/money.ts +35 -0
  161. package/templates/storefront/src/lib/util/product.ts +5 -0
  162. package/templates/storefront/src/lib/util/repeat.ts +5 -0
  163. package/templates/storefront/src/lib/util/sort-products.ts +50 -0
  164. package/templates/storefront/src/modules/account/components/account-info/index.tsx +140 -0
  165. package/templates/storefront/src/modules/account/components/account-nav/index.tsx +198 -0
  166. package/templates/storefront/src/modules/account/components/address-book/index.tsx +28 -0
  167. package/templates/storefront/src/modules/account/components/address-card/add-address.tsx +169 -0
  168. package/templates/storefront/src/modules/account/components/address-card/edit-address-modal.tsx +241 -0
  169. package/templates/storefront/src/modules/account/components/login/index.tsx +65 -0
  170. package/templates/storefront/src/modules/account/components/order-card/index.tsx +88 -0
  171. package/templates/storefront/src/modules/account/components/order-overview/index.tsx +47 -0
  172. package/templates/storefront/src/modules/account/components/overview/index.tsx +169 -0
  173. package/templates/storefront/src/modules/account/components/profile-billing-address/index.tsx +193 -0
  174. package/templates/storefront/src/modules/account/components/profile-email/index.tsx +75 -0
  175. package/templates/storefront/src/modules/account/components/profile-name/index.tsx +79 -0
  176. package/templates/storefront/src/modules/account/components/profile-password/index.tsx +72 -0
  177. package/templates/storefront/src/modules/account/components/profile-phone/index.tsx +74 -0
  178. package/templates/storefront/src/modules/account/components/register/index.tsx +107 -0
  179. package/templates/storefront/src/modules/account/components/transfer-request-form/index.tsx +83 -0
  180. package/templates/storefront/src/modules/account/templates/account-layout.tsx +43 -0
  181. package/templates/storefront/src/modules/account/templates/login-template.tsx +27 -0
  182. package/templates/storefront/src/modules/cart/components/cart-item-select/index.tsx +75 -0
  183. package/templates/storefront/src/modules/cart/components/empty-cart-message/index.tsx +25 -0
  184. package/templates/storefront/src/modules/cart/components/item/index.tsx +144 -0
  185. package/templates/storefront/src/modules/cart/components/sign-in-prompt/index.tsx +27 -0
  186. package/templates/storefront/src/modules/cart/templates/index.tsx +51 -0
  187. package/templates/storefront/src/modules/cart/templates/items.tsx +58 -0
  188. package/templates/storefront/src/modules/cart/templates/preview.tsx +51 -0
  189. package/templates/storefront/src/modules/cart/templates/summary.tsx +50 -0
  190. package/templates/storefront/src/modules/categories/templates/index.tsx +94 -0
  191. package/templates/storefront/src/modules/checkout/components/address-select/index.tsx +117 -0
  192. package/templates/storefront/src/modules/checkout/components/addresses/index.tsx +186 -0
  193. package/templates/storefront/src/modules/checkout/components/billing_address/index.tsx +114 -0
  194. package/templates/storefront/src/modules/checkout/components/country-select/index.tsx +50 -0
  195. package/templates/storefront/src/modules/checkout/components/discount-code/index.tsx +181 -0
  196. package/templates/storefront/src/modules/checkout/components/error-message/index.tsx +13 -0
  197. package/templates/storefront/src/modules/checkout/components/payment/index.tsx +261 -0
  198. package/templates/storefront/src/modules/checkout/components/payment-button/index.tsx +195 -0
  199. package/templates/storefront/src/modules/checkout/components/payment-container/index.tsx +130 -0
  200. package/templates/storefront/src/modules/checkout/components/payment-test/index.tsx +12 -0
  201. package/templates/storefront/src/modules/checkout/components/payment-wrapper/index.tsx +42 -0
  202. package/templates/storefront/src/modules/checkout/components/payment-wrapper/stripe-wrapper.tsx +54 -0
  203. package/templates/storefront/src/modules/checkout/components/review/index.tsx +54 -0
  204. package/templates/storefront/src/modules/checkout/components/shipping/index.tsx +417 -0
  205. package/templates/storefront/src/modules/checkout/components/shipping-address/index.tsx +219 -0
  206. package/templates/storefront/src/modules/checkout/components/submit-button/index.tsx +32 -0
  207. package/templates/storefront/src/modules/checkout/templates/checkout-form/index.tsx +38 -0
  208. package/templates/storefront/src/modules/checkout/templates/checkout-summary/index.tsx +31 -0
  209. package/templates/storefront/src/modules/collections/templates/index.tsx +44 -0
  210. package/templates/storefront/src/modules/common/components/cart-totals/index.tsx +84 -0
  211. package/templates/storefront/src/modules/common/components/checkbox/index.tsx +44 -0
  212. package/templates/storefront/src/modules/common/components/delete-button/index.tsx +42 -0
  213. package/templates/storefront/src/modules/common/components/divider/index.tsx +9 -0
  214. package/templates/storefront/src/modules/common/components/filter-radio-group/index.tsx +61 -0
  215. package/templates/storefront/src/modules/common/components/input/index.tsx +79 -0
  216. package/templates/storefront/src/modules/common/components/interactive-link/index.tsx +33 -0
  217. package/templates/storefront/src/modules/common/components/line-item-options/index.tsx +26 -0
  218. package/templates/storefront/src/modules/common/components/line-item-price/index.tsx +63 -0
  219. package/templates/storefront/src/modules/common/components/line-item-unit-price/index.tsx +62 -0
  220. package/templates/storefront/src/modules/common/components/localized-client-link/index.tsx +29 -0
  221. package/templates/storefront/src/modules/common/components/modal/index.tsx +118 -0
  222. package/templates/storefront/src/modules/common/components/native-select/index.tsx +76 -0
  223. package/templates/storefront/src/modules/common/components/radio/index.tsx +27 -0
  224. package/templates/storefront/src/modules/common/icons/back.tsx +37 -0
  225. package/templates/storefront/src/modules/common/icons/bancontact.tsx +26 -0
  226. package/templates/storefront/src/modules/common/icons/chevron-down.tsx +30 -0
  227. package/templates/storefront/src/modules/common/icons/eye-off.tsx +37 -0
  228. package/templates/storefront/src/modules/common/icons/eye.tsx +37 -0
  229. package/templates/storefront/src/modules/common/icons/fast-delivery.tsx +65 -0
  230. package/templates/storefront/src/modules/common/icons/ideal.tsx +26 -0
  231. package/templates/storefront/src/modules/common/icons/map-pin.tsx +37 -0
  232. package/templates/storefront/src/modules/common/icons/package.tsx +44 -0
  233. package/templates/storefront/src/modules/common/icons/paypal.tsx +30 -0
  234. package/templates/storefront/src/modules/common/icons/placeholder-image.tsx +44 -0
  235. package/templates/storefront/src/modules/common/icons/refresh.tsx +51 -0
  236. package/templates/storefront/src/modules/common/icons/spinner.tsx +37 -0
  237. package/templates/storefront/src/modules/common/icons/trash.tsx +51 -0
  238. package/templates/storefront/src/modules/common/icons/user.tsx +37 -0
  239. package/templates/storefront/src/modules/common/icons/x.tsx +37 -0
  240. package/templates/storefront/src/modules/layout/components/cart-mismatch-banner/index.tsx +59 -0
  241. package/templates/storefront/src/modules/order/components/help/index.tsx +26 -0
  242. package/templates/storefront/src/modules/order/components/item/index.tsx +57 -0
  243. package/templates/storefront/src/modules/order/components/items/index.tsx +44 -0
  244. package/templates/storefront/src/modules/order/components/onboarding-cta/index.tsx +28 -0
  245. package/templates/storefront/src/modules/order/components/order-details/index.tsx +64 -0
  246. package/templates/storefront/src/modules/order/components/order-summary/index.tsx +61 -0
  247. package/templates/storefront/src/modules/order/components/payment-details/index.tsx +64 -0
  248. package/templates/storefront/src/modules/order/components/shipping-details/index.tsx +74 -0
  249. package/templates/storefront/src/modules/order/components/transfer-actions/index.tsx +83 -0
  250. package/templates/storefront/src/modules/order/components/transfer-image/index.tsx +275 -0
  251. package/templates/storefront/src/modules/order/templates/order-completed-template.tsx +53 -0
  252. package/templates/storefront/src/modules/order/templates/order-details-template.tsx +46 -0
  253. package/templates/storefront/src/modules/products/components/thumbnail/index.tsx +70 -0
  254. package/templates/storefront/src/modules/products/templates/index.tsx +118 -0
  255. package/templates/storefront/src/modules/shipping/components/free-shipping-price-nudge/index.tsx +285 -0
  256. package/templates/storefront/src/modules/skeletons/components/skeleton-button/index.tsx +5 -0
  257. package/templates/storefront/src/modules/skeletons/components/skeleton-card-details/index.tsx +10 -0
  258. package/templates/storefront/src/modules/skeletons/components/skeleton-cart-item/index.tsx +35 -0
  259. package/templates/storefront/src/modules/skeletons/components/skeleton-cart-totals/index.tsx +30 -0
  260. package/templates/storefront/src/modules/skeletons/components/skeleton-code-form/index.tsx +13 -0
  261. package/templates/storefront/src/modules/skeletons/components/skeleton-line-item/index.tsx +35 -0
  262. package/templates/storefront/src/modules/skeletons/components/skeleton-order-confirmed-header/index.tsx +14 -0
  263. package/templates/storefront/src/modules/skeletons/components/skeleton-order-information/index.tsx +36 -0
  264. package/templates/storefront/src/modules/skeletons/components/skeleton-order-items/index.tsx +43 -0
  265. package/templates/storefront/src/modules/skeletons/components/skeleton-order-summary/index.tsx +15 -0
  266. package/templates/storefront/src/modules/skeletons/components/skeleton-product-preview/index.tsx +15 -0
  267. package/templates/storefront/src/modules/skeletons/templates/skeleton-cart-page/index.tsx +65 -0
  268. package/templates/storefront/src/modules/skeletons/templates/skeleton-order-confirmed/index.tsx +21 -0
  269. package/templates/storefront/src/modules/skeletons/templates/skeleton-product-grid/index.tsx +23 -0
  270. package/templates/storefront/src/modules/store/components/pagination/index.tsx +114 -0
  271. package/templates/storefront/src/modules/store/components/refinement-list/index.tsx +41 -0
  272. package/templates/storefront/src/modules/store/components/refinement-list/sort-products/index.tsx +48 -0
  273. package/templates/storefront/src/modules/store/templates/index.tsx +42 -0
  274. package/templates/storefront/src/modules/store/templates/paginated-products.tsx +80 -0
  275. package/templates/storefront/src/modules/ub/button.tsx +41 -0
  276. package/templates/storefront/src/modules/ub/campaign-blocks.tsx +197 -0
  277. package/templates/storefront/src/modules/ub/campaign-ended.tsx +28 -0
  278. package/templates/storefront/src/modules/ub/category-tiles.tsx +41 -0
  279. package/templates/storefront/src/modules/ub/countdown.tsx +46 -0
  280. package/templates/storefront/src/modules/ub/footer.tsx +56 -0
  281. package/templates/storefront/src/modules/ub/icons.tsx +42 -0
  282. package/templates/storefront/src/modules/ub/nav.tsx +90 -0
  283. package/templates/storefront/src/modules/ub/pdp/buy-box.tsx +140 -0
  284. package/templates/storefront/src/modules/ub/pdp/gallery.tsx +40 -0
  285. package/templates/storefront/src/modules/ub/product-card.tsx +66 -0
  286. package/templates/storefront/src/modules/ub/top-bar.tsx +20 -0
  287. package/templates/storefront/src/modules/ub/track-form.tsx +92 -0
  288. package/templates/storefront/src/proxy.ts +89 -0
  289. package/templates/storefront/src/styles/globals.css +98 -0
  290. package/templates/storefront/src/styles/ub/bundle.css +372 -0
  291. package/templates/storefront/src/styles/ub/fonts.css +17 -0
  292. package/templates/storefront/src/styles/ub/medusa-ui.css +90 -0
  293. package/templates/storefront/src/styles/ub/overrides.css +12 -0
  294. package/templates/storefront/src/styles/ub/tokens.css +9 -0
  295. package/templates/storefront/src/types/global.ts +24 -0
  296. package/templates/storefront/src/types/icon.ts +4 -0
  297. package/templates/storefront/tailwind.config.js +164 -0
  298. package/templates/storefront/themes/black-friday/campaign.en.json +31 -0
  299. package/templates/storefront/themes/black-friday/campaign.fr.json +31 -0
  300. package/templates/storefront/themes/black-friday/theme.json +9 -0
  301. package/templates/storefront/themes/cyber-monday/campaign.en.json +31 -0
  302. package/templates/storefront/themes/cyber-monday/campaign.fr.json +31 -0
  303. package/templates/storefront/themes/cyber-monday/theme.json +9 -0
  304. package/templates/storefront/themes/halloween/campaign.en.json +31 -0
  305. package/templates/storefront/themes/halloween/campaign.fr.json +31 -0
  306. package/templates/storefront/themes/halloween/theme.json +9 -0
  307. package/templates/storefront/themes/noel/campaign.en.json +31 -0
  308. package/templates/storefront/themes/noel/campaign.fr.json +31 -0
  309. package/templates/storefront/themes/noel/theme.json +9 -0
  310. package/templates/storefront/themes/nouvel-an/campaign.en.json +31 -0
  311. package/templates/storefront/themes/nouvel-an/campaign.fr.json +31 -0
  312. package/templates/storefront/themes/nouvel-an/theme.json +9 -0
  313. package/templates/storefront/themes/thanksgiving/campaign.en.json +31 -0
  314. package/templates/storefront/themes/thanksgiving/campaign.fr.json +31 -0
  315. package/templates/storefront/themes/thanksgiving/theme.json +9 -0
  316. package/templates/storefront/tsconfig.json +53 -0
@@ -0,0 +1,89 @@
1
+ import { NextRequest, NextResponse } from "next/server"
2
+
3
+ /**
4
+ * Deux rôles, sans aucune logique de pays, de langue ni de redirection
5
+ * (la région, la langue et la devise sont fixées par l'instance) :
6
+ * 1. en-têtes de sécurité, dont une CSP avec nonce (Next l'applique à ses scripts) ;
7
+ * 2. identifiant de cache du visiteur (`_medusa_cache_id_<slug>`), qui nomme les
8
+ * tags de cache (panier, client…) que les server actions expirent.
9
+ */
10
+
11
+ const isDev = process.env.NODE_ENV === "development"
12
+
13
+ function origin(url?: string) {
14
+ try {
15
+ return url ? new URL(url).origin : ""
16
+ } catch {
17
+ return ""
18
+ }
19
+ }
20
+
21
+ function contentSecurityPolicy(nonce: string) {
22
+ // Images produits : stockage du projet (S3_FILE_URL) ; à défaut, toute source http(s).
23
+ const files = origin(process.env.S3_FILE_URL) || "http: https:"
24
+
25
+ return [
26
+ "default-src 'self'",
27
+ `script-src 'self' 'nonce-${nonce}' 'strict-dynamic' https://js.stripe.com${isDev ? " 'unsafe-eval'" : ""}`,
28
+ "style-src 'self' 'unsafe-inline'",
29
+ `img-src 'self' data: blob: ${files} https://*.stripe.com`,
30
+ "font-src 'self'",
31
+ `connect-src 'self' https://api.stripe.com https://m.stripe.network https://*.stripe.com${isDev ? " ws:" : ""}`,
32
+ "frame-src https://js.stripe.com https://hooks.stripe.com",
33
+ "frame-ancestors 'none'",
34
+ "form-action 'self'",
35
+ "base-uri 'self'",
36
+ "object-src 'none'",
37
+ ].join("; ")
38
+ }
39
+
40
+ export function proxy(request: NextRequest) {
41
+ const nonce = Buffer.from(crypto.randomUUID()).toString("base64")
42
+ const csp = contentSecurityPolicy(nonce)
43
+
44
+ // Next lit la CSP de la requête pour poser le nonce sur ses propres scripts.
45
+ request.headers.set("content-security-policy", csp)
46
+ request.headers.set("x-nonce", nonce)
47
+
48
+ const cacheCookie = `_medusa_cache_id_${process.env.BOUTIQUE}`
49
+ const newCacheId = request.cookies.has(cacheCookie) ? null : crypto.randomUUID()
50
+ if (newCacheId) {
51
+ // Visible dès cette requête par les server components…
52
+ request.cookies.set(cacheCookie, newCacheId)
53
+ }
54
+
55
+ const response = NextResponse.next({ request: { headers: request.headers } })
56
+
57
+ if (newCacheId) {
58
+ // …et gardé par le navigateur pour les suivantes.
59
+ response.cookies.set(cacheCookie, newCacheId, {
60
+ maxAge: 60 * 60 * 24,
61
+ httpOnly: true,
62
+ sameSite: "strict",
63
+ secure: process.env.NODE_ENV === "production",
64
+ })
65
+ }
66
+
67
+ response.headers.set("Content-Security-Policy", csp)
68
+ response.headers.set("X-Frame-Options", "DENY")
69
+ response.headers.set("X-Content-Type-Options", "nosniff")
70
+ response.headers.set("Referrer-Policy", "strict-origin-when-cross-origin")
71
+ response.headers.set("Permissions-Policy", "camera=(), microphone=(), geolocation=(), payment=(self \"https://js.stripe.com\")")
72
+ if (request.headers.get("x-forwarded-proto") === "https" || request.nextUrl.protocol === "https:") {
73
+ response.headers.set("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
74
+ }
75
+
76
+ return response
77
+ }
78
+
79
+ export const config = {
80
+ matcher: [
81
+ {
82
+ source: "/((?!api|_next/static|_next/image|favicon.ico|.*\\..*).*)",
83
+ missing: [
84
+ { type: "header", key: "next-router-prefetch" },
85
+ { type: "header", key: "purpose", value: "prefetch" },
86
+ ],
87
+ },
88
+ ],
89
+ }
@@ -0,0 +1,98 @@
1
+ @import "tailwindcss/base";
2
+ @import "tailwindcss/components";
3
+ @import "tailwindcss/utilities";
4
+
5
+ @layer utilities {
6
+ /* Chrome, Safari and Opera */
7
+ .no-scrollbar::-webkit-scrollbar {
8
+ display: none;
9
+ }
10
+
11
+ .no-scrollbar::-webkit-scrollbar-track {
12
+ background-color: transparent;
13
+ }
14
+
15
+ .no-scrollbar {
16
+ -ms-overflow-style: none; /* IE and Edge */
17
+ scrollbar-width: none; /* Firefox */
18
+ }
19
+
20
+ input:focus ~ label,
21
+ input:not(:placeholder-shown) ~ label {
22
+ @apply -translate-y-2 text-xsmall-regular;
23
+ }
24
+
25
+ input:focus ~ label {
26
+ @apply left-0;
27
+ }
28
+
29
+
30
+ input[type="search"]::-webkit-search-decoration,
31
+ input[type="search"]::-webkit-search-cancel-button,
32
+ input[type="search"]::-webkit-search-results-button,
33
+ input[type="search"]::-webkit-search-results-decoration {
34
+ -webkit-appearance: none;
35
+ }
36
+ }
37
+
38
+ @layer components {
39
+ .content-container {
40
+ @apply max-w-[1440px] w-full mx-auto px-6;
41
+ }
42
+
43
+ .contrast-btn {
44
+ @apply px-4 py-2 border border-black rounded-full hover:bg-black hover:text-white transition-colors duration-200 ease-in;
45
+ }
46
+
47
+ .text-xsmall-regular {
48
+ @apply text-[10px] leading-4 font-normal;
49
+ }
50
+
51
+ .text-small-regular {
52
+ @apply text-xs leading-5 font-normal;
53
+ }
54
+
55
+ .text-small-semi {
56
+ @apply text-xs leading-5 font-semibold;
57
+ }
58
+
59
+ .text-base-regular {
60
+ @apply text-sm leading-6 font-normal;
61
+ }
62
+
63
+ .text-base-semi {
64
+ @apply text-sm leading-6 font-semibold;
65
+ }
66
+
67
+ .text-large-regular {
68
+ @apply text-base leading-6 font-normal;
69
+ }
70
+
71
+ .text-large-semi {
72
+ @apply text-base leading-6 font-semibold;
73
+ }
74
+
75
+ .text-xl-regular {
76
+ @apply text-2xl leading-[36px] font-normal;
77
+ }
78
+
79
+ .text-xl-semi {
80
+ @apply text-2xl leading-[36px] font-semibold;
81
+ }
82
+
83
+ .text-2xl-regular {
84
+ @apply text-[30px] leading-[48px] font-normal;
85
+ }
86
+
87
+ .text-2xl-semi {
88
+ @apply text-[30px] leading-[48px] font-semibold;
89
+ }
90
+
91
+ .text-3xl-regular {
92
+ @apply text-[32px] leading-[44px] font-normal;
93
+ }
94
+
95
+ .text-3xl-semi {
96
+ @apply text-[32px] leading-[44px] font-semibold;
97
+ }
98
+ }
@@ -0,0 +1,372 @@
1
+ /* COPIE de design/ par scripts/sync-design.mjs — ne pas modifier ici. */
2
+
3
+ /* =====================================================================
4
+ Usine à Boutiques — composants
5
+ 1. PRESETS DE THÈME : chaque campagne reprend une référence (police,
6
+ arrondis, forme des boutons, casse des titres, mise en page du hero).
7
+ 2. COMPOSANTS : un seul markup, stylé par les tokens + le preset.
8
+ ===================================================================== */
9
+
10
+ /* ---------- 1. Presets ---------- */
11
+ :root,[data-theme="halloween"]{ /* Nexora, version sombre */
12
+ --ub-font-head:var(--font-space-grotesk);--ub-font-body:var(--font-inter);
13
+ --ub-head-weight:700;--ub-head-case:uppercase;--ub-head-track:-0.01em;
14
+ --ub-r-card:var(--radius-xl);--ub-r-btn:var(--radius-pill);--ub-r-tile:var(--radius-xl);--ub-r-hero:0px;--ub-r-media:var(--radius-xl);
15
+ }
16
+ [data-theme="thanksgiving"]{ /* NovaTrend */
17
+ --ub-font-head:var(--font-jakarta);--ub-font-body:var(--font-jakarta);
18
+ --ub-head-weight:800;--ub-head-case:none;--ub-head-track:-0.02em;
19
+ --ub-r-card:var(--radius-lg);--ub-r-btn:var(--radius-sm);--ub-r-tile:var(--radius-lg);--ub-r-hero:0px;--ub-r-media:var(--radius-lg);
20
+ }
21
+ [data-theme="black-friday"]{ /* Aeroflow + bloc Flash Sale NovaTrend */
22
+ --ub-font-head:var(--font-oswald);--ub-font-body:var(--font-inter);
23
+ --ub-head-weight:700;--ub-head-case:uppercase;--ub-head-track:0;
24
+ --ub-r-card:var(--radius-md);--ub-r-btn:var(--radius-pill);--ub-r-tile:var(--radius-md);--ub-r-hero:0px;--ub-r-media:var(--radius-md);
25
+ }
26
+ [data-theme="cyber-monday"]{ /* NovaTech */
27
+ --ub-font-head:var(--font-outfit);--ub-font-body:var(--font-outfit);
28
+ --ub-head-weight:600;--ub-head-case:none;--ub-head-track:-0.01em;
29
+ --ub-r-card:var(--radius-lg);--ub-r-btn:var(--radius-md);--ub-r-tile:var(--radius-lg);--ub-r-hero:0px;--ub-r-media:var(--radius-lg);
30
+ }
31
+ [data-theme="noel"]{ /* Crescendo */
32
+ --ub-font-head:var(--font-poppins);--ub-font-body:var(--font-poppins);
33
+ --ub-head-weight:700;--ub-head-case:none;--ub-head-track:-0.02em;
34
+ --ub-r-card:var(--radius-xl);--ub-r-btn:var(--radius-md);--ub-r-tile:var(--radius-xl);--ub-r-hero:var(--radius-2xl);--ub-r-media:var(--radius-xl);
35
+ }
36
+ [data-theme="nouvel-an"]{ /* Nexora, version claire */
37
+ --ub-font-head:var(--font-sora);--ub-font-body:var(--font-inter);
38
+ --ub-head-weight:600;--ub-head-case:uppercase;--ub-head-track:-0.01em;
39
+ --ub-r-card:var(--radius-xl);--ub-r-btn:var(--radius-pill);--ub-r-tile:var(--radius-xl);--ub-r-hero:0px;--ub-r-media:var(--radius-xl);
40
+ }
41
+
42
+ /* ---------- 2. Base ---------- */
43
+ .ub{font-family:var(--ub-font-body);color:var(--ink);background:var(--bg);-webkit-font-smoothing:antialiased;font-size:15px;line-height:24px}
44
+ .ub *{box-sizing:border-box}
45
+ :where(.ub) a{color:inherit;text-decoration:none}
46
+ :where(.ub) h1,:where(.ub) h2,:where(.ub) h3,:where(.ub) p{margin:0}
47
+ .ub :focus-visible{outline:2px solid var(--focus);outline-offset:2px}
48
+ .ub svg{flex:none}
49
+ .ub-wrap{max-width:var(--content-max);margin:0 auto;padding:0 var(--space-6)}
50
+ .ub-section{padding:var(--space-12) 0}
51
+ .ub-head{font-family:var(--ub-font-head);font-weight:var(--ub-head-weight);text-transform:var(--ub-head-case);letter-spacing:var(--ub-head-track)}
52
+ .ub-sec-head{display:flex;align-items:flex-end;justify-content:space-between;gap:var(--space-4);margin-bottom:var(--space-6)}
53
+ .ub-sec-head h2{font-size:28px;line-height:34px}
54
+ .ub-more{display:inline-flex;align-items:center;gap:6px;font-size:14px;font-weight:600;color:var(--ink)}
55
+ .ub-more svg{width:16px;height:16px}
56
+
57
+ /* Eyebrow : « NEXT-GEN GADGETS » (Nexora), puce « Special Offer » (NovaTech), « TRENDING NOW » (NovaTrend) */
58
+ .ub-eyebrow{display:inline-flex;align-items:center;gap:8px;font-size:12px;line-height:16px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--primary)}
59
+ .ub-eyebrow__dot{width:8px;height:8px;border-radius:var(--radius-pill);background:currentColor}
60
+ [data-theme="cyber-monday"] .ub-eyebrow{letter-spacing:0;text-transform:none;font-size:13px;padding:4px 10px;border-radius:var(--radius-pill);background:var(--accent);color:var(--on-accent)}
61
+ [data-theme="noel"] .ub-eyebrow{letter-spacing:0;text-transform:none;font-size:13px;padding:4px 12px;border-radius:var(--radius-pill);background:var(--tint-2);color:var(--accent)}
62
+ [data-theme="halloween"] .ub-eyebrow,[data-theme="nouvel-an"] .ub-eyebrow{color:var(--accent)}
63
+ [data-theme="black-friday"] .ub-eyebrow{color:var(--primary)}
64
+
65
+ /* Placeholder photo (remplacé par les images produit Medusa) */
66
+ .ub-ph{position:relative;background:var(--surface);display:flex;align-items:center;justify-content:center;color:var(--ink-muted)}
67
+ .ub-ph::before{content:"";width:28px;height:28px;opacity:.5;background:currentColor;-webkit-mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5'%3E%3Crect x='3' y='4' width='18' height='16' rx='2'/%3E%3Ccircle cx='9' cy='10' r='2'/%3E%3Cpath d='M21 16l-5-5-9 9'/%3E%3C/svg%3E") center/contain no-repeat;mask:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.5'%3E%3Crect x='3' y='4' width='18' height='16' rx='2'/%3E%3Ccircle cx='9' cy='10' r='2'/%3E%3Cpath d='M21 16l-5-5-9 9'/%3E%3C/svg%3E") center/contain no-repeat}
68
+
69
+ /* ---------- Button ---------- */
70
+ .ub-btn{display:inline-flex;align-items:center;justify-content:center;gap:10px;height:48px;padding:0 24px;border:1px solid transparent;border-radius:var(--ub-r-btn);font:600 15px/20px var(--ub-font-body);cursor:pointer;white-space:nowrap;text-decoration:none}
71
+ .ub-btn svg{width:16px;height:16px}
72
+ .ub-btn--primary{background:var(--primary);color:var(--on-primary)}
73
+ .ub-btn--dark{background:var(--accent);color:var(--on-accent)}
74
+ [data-theme="halloween"] .ub-btn--dark,[data-theme="nouvel-an"] .ub-btn--dark,[data-theme="cyber-monday"] .ub-btn--dark,[data-theme="noel"] .ub-btn--dark{background:var(--ink);color:var(--bg)}
75
+ .ub-btn--ghost{background:transparent;color:var(--ink);border-color:var(--border)}
76
+ .ub-btn--full{width:100%}
77
+ .ub-btn--sm{height:40px;padding:0 16px;font-size:14px}
78
+ /* Nexora : pastille ronde foncée avec flèche au bout du bouton */
79
+ .ub-btn__arrow{display:none}
80
+ [data-theme="halloween"] .ub-btn--primary,[data-theme="nouvel-an"] .ub-btn--primary{padding:0 6px 0 24px;text-transform:uppercase;letter-spacing:.06em;font-size:13px}
81
+ [data-theme="halloween"] .ub-btn--primary .ub-btn__arrow,[data-theme="nouvel-an"] .ub-btn--primary .ub-btn__arrow{display:inline-flex;align-items:center;justify-content:center;width:36px;height:36px;border-radius:var(--radius-pill);background:var(--on-primary);color:var(--primary)}
82
+ [data-theme="halloween"] .ub-btn--primary .ub-btn__icon,[data-theme="nouvel-an"] .ub-btn--primary .ub-btn__icon{display:none}
83
+ /* Aeroflow : boutons en capitales */
84
+ [data-theme="black-friday"] .ub-btn{text-transform:uppercase;letter-spacing:.04em}
85
+
86
+ /* ---------- TopBar ---------- */
87
+ .ub-topbar{background:var(--topbar-bg);color:var(--topbar-ink);font-size:13px;line-height:20px;font-weight:500}
88
+ .ub-topbar .ub-wrap{display:flex;justify-content:center;gap:var(--space-8);padding-top:9px;padding-bottom:9px;flex-wrap:wrap}
89
+ .ub-topbar span{display:inline-flex;align-items:center;gap:8px}
90
+ .ub-topbar svg{width:15px;height:15px}
91
+
92
+ /* ---------- Nav ---------- */
93
+ .ub-nav{background:var(--bg);border-bottom:1px solid var(--border)}
94
+ .ub-nav .ub-wrap{display:flex;align-items:center;gap:var(--space-8);height:76px}
95
+ .ub-logo{display:inline-flex;align-items:center;gap:10px;font:700 20px/24px var(--ub-font-head);letter-spacing:var(--ub-head-track);text-transform:var(--ub-head-case)}
96
+ .ub-logo__mark{width:28px;height:28px;border-radius:var(--radius-sm);background:var(--primary)}
97
+ [data-theme="halloween"] .ub-logo__mark,[data-theme="nouvel-an"] .ub-logo__mark{background:var(--accent);border-radius:var(--radius-pill)}
98
+ .ub-nav__links{display:flex;gap:var(--space-6);font-size:14px;font-weight:500;color:var(--ink);margin:0 auto}
99
+ .ub-nav__links a[aria-current]{color:var(--primary);box-shadow:0 2px 0 var(--primary)}
100
+ [data-theme="halloween"] .ub-nav__links a[aria-current],[data-theme="nouvel-an"] .ub-nav__links a[aria-current]{color:var(--ink);box-shadow:none;font-weight:700}
101
+ [data-theme="nouvel-an"] .ub-nav__links a[aria-current]{color:var(--ink)}
102
+ [data-theme="black-friday"] .ub-nav__links{text-transform:uppercase;letter-spacing:.04em;font-weight:600}
103
+ [data-theme="black-friday"] .ub-nav__links a[aria-current]{color:var(--ink);box-shadow:0 2px 0 var(--primary)}
104
+ .ub-search{display:none;align-items:center;justify-content:space-between;width:220px;height:40px;padding:0 14px;border:1px solid var(--border);border-radius:var(--radius-pill);color:var(--ink-muted);font-size:13px}
105
+ .ub-search svg{width:17px;height:17px;color:var(--ink)}
106
+ [data-theme="cyber-monday"] .ub-search{display:flex}
107
+ [data-theme="cyber-monday"] .ub-icon--search{display:none}
108
+ .ub-nav__icons{display:flex;align-items:center;gap:6px}
109
+ .ub-icon{position:relative;display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:var(--radius-pill);color:var(--ink);background:transparent;border:0}
110
+ .ub-icon svg{width:21px;height:21px}
111
+ .ub-count{position:absolute;top:2px;right:0;min-width:18px;height:18px;padding:0 5px;border-radius:var(--radius-pill);background:var(--primary);color:var(--on-primary);font:700 11px/18px var(--ub-font-body);text-align:center}
112
+ .ub-nav__cta{display:none}
113
+ [data-theme="halloween"] .ub-nav__cta,[data-theme="nouvel-an"] .ub-nav__cta,[data-theme="noel"] .ub-nav__cta{display:inline-flex}
114
+ [data-theme="noel"] .ub-nav__cta{height:40px;padding:0 18px;font-size:14px}
115
+ [data-theme="halloween"] .ub-icon--fav,[data-theme="nouvel-an"] .ub-icon--fav,[data-theme="noel"] .ub-icon--fav,[data-theme="noel"] .ub-icon--user{display:none}
116
+
117
+ /* ---------- Hero ---------- */
118
+ .ub-hero{background:var(--hero-bg);color:var(--hero-ink);overflow:hidden}
119
+ .ub-hero__in{display:grid;grid-template-columns:1.05fr 1fr;align-items:center;gap:var(--space-12);padding-top:var(--space-16);padding-bottom:var(--space-16)}
120
+ .ub-hero__text{display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-4)}
121
+ .ub-hero__title{font-size:56px;line-height:60px}
122
+ .ub-hero__title em{font-style:normal;color:var(--primary)}
123
+ [data-theme="halloween"] .ub-hero__title em,[data-theme="nouvel-an"] .ub-hero__title em,[data-theme="noel"] .ub-hero__title em{color:var(--accent)}
124
+ [data-theme="halloween"] .ub-hero__title,[data-theme="nouvel-an"] .ub-hero__title{font-size:68px;line-height:70px}
125
+ .ub-hero__sub{max-width:420px;color:var(--hero-muted);font-size:16px;line-height:26px}
126
+ .ub-hero__actions{display:flex;gap:var(--space-3);flex-wrap:wrap;margin-top:var(--space-2)}
127
+ .ub-hero .ub-btn--ghost{color:var(--hero-ink);border-color:var(--border);background:var(--bg)}
128
+ [data-theme="halloween"] .ub-hero .ub-btn--ghost,[data-theme="nouvel-an"] .ub-hero .ub-btn--ghost{display:none}
129
+ .ub-hero__trust{display:none;gap:var(--space-4);list-style:none;margin:var(--space-4) 0 0;padding:10px 14px;border-radius:var(--radius-lg);background:rgba(255,255,255,.7)}
130
+ .ub-hero__trust li{display:flex;align-items:center;gap:10px;font-size:13px;line-height:18px;font-weight:500}
131
+ .ub-hero__trust svg{width:22px;height:22px;color:var(--primary)}
132
+ .ub-hero__trust small{display:block;color:var(--hero-muted);font-size:11px;font-weight:400}
133
+ [data-theme="noel"] .ub-hero__trust{display:flex}
134
+ .ub-hero__media{position:relative;min-height:400px;display:flex;align-items:center;justify-content:center}
135
+ .ub-hero__blob{position:absolute;width:380px;height:380px;border-radius:var(--radius-pill);background:var(--accent);opacity:.35}
136
+ [data-theme="thanksgiving"] .ub-hero__blob{background:var(--primary);opacity:.9;border-radius:48% 52% 38% 62% / 55% 40% 60% 45%;width:340px;height:300px}
137
+ [data-theme="cyber-monday"] .ub-hero__blob{background:var(--primary);opacity:.1}
138
+ [data-theme="noel"] .ub-hero__blob{background:var(--bg);opacity:.9;width:420px;height:420px}
139
+ [data-theme="nouvel-an"] .ub-hero__blob{opacity:.22;width:420px;height:420px}
140
+ .ub-hero__photo{position:relative;width:74%;aspect-ratio:1/1;border-radius:var(--ub-r-media)}
141
+ .ub-hero__photo.ub-ph{background:transparent;color:var(--hero-muted)}
142
+ .ub-bubble{position:absolute;display:flex;flex-direction:column;align-items:center;justify-content:center;width:112px;height:112px;border-radius:var(--radius-pill);background:var(--bubble-bg);color:var(--bubble-ink);box-shadow:var(--shadow-pop);font:500 13px/16px var(--ub-font-body);text-align:center;left:4%;bottom:10%}
143
+ .ub-bubble b{font:700 30px/34px var(--ub-font-head)}
144
+ [data-theme="cyber-monday"] .ub-bubble{left:auto;right:14%;top:6%;bottom:auto;width:96px;height:96px}
145
+ [data-theme="cyber-monday"] .ub-bubble b{font-size:18px;line-height:22px}
146
+ [data-theme="halloween"] .ub-bubble,[data-theme="nouvel-an"] .ub-bubble{display:none}
147
+ /* Crescendo : hero dans un grand conteneur arrondi */
148
+ [data-theme="noel"] .ub-hero{background:var(--bg);padding:var(--space-6) var(--space-6) 0}
149
+ [data-theme="noel"] .ub-hero__in{background:var(--hero-bg);border-radius:var(--ub-r-hero);padding:var(--space-12)}
150
+ /* Black Friday : hero noir centré, titre géant */
151
+ [data-theme="black-friday"] .ub-hero__in{grid-template-columns:1fr;text-align:center;padding-top:88px;padding-bottom:88px}
152
+ [data-theme="black-friday"] .ub-hero__text{align-items:center}
153
+ [data-theme="black-friday"] .ub-hero__title{font-size:120px;line-height:112px}
154
+ [data-theme="black-friday"] .ub-hero__title em{display:block;font-size:56px;line-height:64px}
155
+ [data-theme="black-friday"] .ub-hero__sub{max-width:520px}
156
+ [data-theme="black-friday"] .ub-hero__media{display:none}
157
+ [data-theme="black-friday"] .ub-hero .ub-btn--ghost{background:transparent;color:var(--hero-ink);border-color:var(--hero-muted)}
158
+
159
+ /* ---------- Countdown : cases (NovaTech « 16 Days », NovaTrend Flash Sale) ---------- */
160
+ .ub-countdown{display:flex;gap:10px}
161
+ .ub-countdown__c{display:flex;flex-direction:column;align-items:center;justify-content:center;min-width:62px;height:62px;padding:0 6px;border-radius:var(--radius-md);background:var(--bg);color:var(--ink);box-shadow:var(--shadow-card)}
162
+ .ub-countdown__c b{font:700 22px/26px var(--ub-font-head);font-variant-numeric:tabular-nums}
163
+ .ub-countdown__c small{font-size:11px;line-height:14px;color:var(--ink-muted)}
164
+ [data-theme="black-friday"] .ub-countdown__c{background:transparent;color:var(--hero-ink);border:1px solid var(--hero-muted);box-shadow:none}
165
+ [data-theme="black-friday"] .ub-countdown__c small{color:var(--hero-muted)}
166
+ [data-theme="halloween"] .ub-countdown__c{background:var(--surface);color:var(--ink);box-shadow:none;border:1px solid var(--border)}
167
+ .ub-hero__cd{display:none}
168
+ [data-theme="black-friday"] .ub-hero__cd,[data-theme="cyber-monday"] .ub-hero__cd,[data-theme="halloween"] .ub-hero__cd{display:flex}
169
+
170
+ /* ---------- TrustBar ---------- */
171
+ .ub-trust{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-6);padding:var(--space-6) var(--space-8);border-radius:var(--ub-r-card);background:var(--surface);list-style:none;margin:0}
172
+ .ub-trust li{display:flex;align-items:center;gap:14px}
173
+ .ub-trust__ic{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;border-radius:var(--radius-pill);background:var(--bg);color:var(--primary)}
174
+ .ub-trust__ic svg{width:22px;height:22px}
175
+ .ub-trust b{display:block;font-size:14px;line-height:20px}
176
+ .ub-trust small{display:block;font-size:12px;line-height:18px;color:var(--ink-muted)}
177
+ [data-theme="halloween"] .ub-trust,[data-theme="nouvel-an"] .ub-trust{background:var(--band-bg);color:var(--band-ink)}
178
+ [data-theme="halloween"] .ub-trust small,[data-theme="nouvel-an"] .ub-trust small{color:var(--band-ink);opacity:.8}
179
+ [data-theme="halloween"] .ub-trust__ic,[data-theme="nouvel-an"] .ub-trust__ic{background:transparent;color:var(--primary);border:1px solid rgba(255,255,255,.18)}
180
+ [data-theme="black-friday"] .ub-trust b{text-transform:uppercase;letter-spacing:.04em}
181
+ [data-theme="black-friday"] .ub-trust__ic{color:var(--ink)}
182
+
183
+ /* ---------- Category tiles ---------- */
184
+ .ub-tiles{display:grid;grid-template-columns:repeat(6,1fr);gap:var(--space-3)}
185
+ .ub-tile{position:relative;display:flex;flex-direction:column;overflow:hidden;border-radius:var(--ub-r-tile);background:var(--surface);border:1px solid var(--border);min-height:190px}
186
+ .ub-tile__img{flex:1;min-height:130px}
187
+ .ub-tile__txt{display:flex;flex-direction:column;padding:12px 14px}
188
+ .ub-tile__name{font-weight:600;font-size:14px;line-height:20px}
189
+ .ub-tile__meta{font-size:12px;line-height:16px;color:var(--ink-muted)}
190
+ .ub-tile__ic{display:none}
191
+ .ub-tile__cta{display:none;font-size:12px;font-weight:600;color:var(--primary)}
192
+ /* NovaTech : petites tuiles blanches avec icône + « 24 items » */
193
+ [data-theme="cyber-monday"] .ub-tile{background:var(--bg);box-shadow:var(--shadow-card);align-items:center;text-align:center;min-height:0;padding:22px 8px 14px}
194
+ [data-theme="cyber-monday"] .ub-tile__img{display:none}
195
+ [data-theme="cyber-monday"] .ub-tile__ic{display:flex;width:48px;height:48px;align-items:center;justify-content:center;color:var(--primary)}
196
+ [data-theme="cyber-monday"] .ub-tile__ic svg{width:36px;height:36px}
197
+ [data-theme="cyber-monday"] .ub-tile__txt{padding:8px 0 0;align-items:center}
198
+ /* Crescendo : grandes tuiles pastel, icône en pastille, « Shop Now → », visuel en bas à droite */
199
+ [data-theme="noel"] .ub-tiles{grid-template-columns:repeat(4,1fr);gap:var(--space-6)}
200
+ [data-theme="noel"] .ub-tile:nth-child(n+5){display:none}
201
+ [data-theme="noel"] .ub-tile{border:0;background:var(--tile);min-height:230px;padding:20px}
202
+ [data-theme="noel"] .ub-tile__txt{padding:0}
203
+ [data-theme="noel"] .ub-tile__ic{display:flex;order:-1;width:44px;height:44px;border-radius:var(--radius-pill);background:var(--bg);align-items:center;justify-content:center;color:var(--primary);margin-bottom:12px}
204
+ [data-theme="noel"] .ub-tile__ic svg{width:22px;height:22px}
205
+ [data-theme="noel"] .ub-tile__name{font-size:17px;line-height:24px}
206
+ [data-theme="noel"] .ub-tile__cta{display:block;margin-top:8px}
207
+ [data-theme="noel"] .ub-tile__img{position:absolute;right:14px;bottom:14px;width:44%;min-height:0;aspect-ratio:1;border-radius:var(--radius-pill);background:rgba(255,255,255,.65)}
208
+ /* NovaTrend : tuiles photo, libellé + « Shop Now → » sur bandeau blanc */
209
+ [data-theme="thanksgiving"] .ub-tile{border:0;min-height:210px}
210
+ [data-theme="thanksgiving"] .ub-tile__txt{position:absolute;left:8px;right:8px;bottom:8px;background:var(--bg);border-radius:var(--radius-sm);padding:8px 10px}
211
+ [data-theme="thanksgiving"] .ub-tile__meta{display:none}
212
+ [data-theme="thanksgiving"] .ub-tile__cta{display:block;color:var(--ink-muted);font-weight:500}
213
+ /* Black Friday : tuiles noires, libellé en capitales */
214
+ [data-theme="black-friday"] .ub-tile{background:var(--ink);color:var(--bg);border:0}
215
+ [data-theme="black-friday"] .ub-tile__img{background:rgba(255,255,255,.08);color:var(--hero-muted)}
216
+ [data-theme="black-friday"] .ub-tile__name{text-transform:uppercase;letter-spacing:.04em;font-family:var(--ub-font-head);font-size:17px}
217
+ [data-theme="black-friday"] .ub-tile__meta{color:var(--hero-muted)}
218
+
219
+ /* ---------- Product card ---------- */
220
+ .ub-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-6)}
221
+ .ub-card{position:relative;display:flex;flex-direction:column;border-radius:var(--ub-r-card);background:var(--surface);overflow:hidden}
222
+ [data-theme="noel"] .ub-card,[data-theme="cyber-monday"] .ub-card{background:var(--bg);box-shadow:var(--shadow-card)}
223
+ .ub-card__media{aspect-ratio:1/1}
224
+ [data-theme="noel"] .ub-card__media,[data-theme="cyber-monday"] .ub-card__media{margin:12px 12px 0;border-radius:calc(var(--ub-r-card) - 8px)}
225
+ .ub-badge{position:absolute;top:12px;left:12px;z-index:1;padding:3px 9px;border-radius:var(--radius-sm);font:700 11px/16px var(--ub-font-body);background:var(--ink);color:var(--bg)}
226
+ .ub-badge--sale{background:var(--sale);color:var(--bg)}
227
+ [data-theme="cyber-monday"] .ub-badge{left:auto;right:20px;top:20px;background:var(--primary);color:var(--on-primary)}
228
+ [data-theme="noel"] .ub-badge{border-radius:var(--radius-pill);background:var(--accent);color:var(--on-accent);top:22px;left:22px}
229
+ [data-theme="noel"] .ub-badge--sale{background:var(--sale);color:var(--bg)}
230
+ .ub-card__fav{position:absolute;top:10px;right:10px;z-index:1;display:inline-flex;align-items:center;justify-content:center;width:32px;height:32px;border-radius:var(--radius-pill);background:var(--bg);border:0;color:var(--ink)}
231
+ .ub-card__fav svg{width:16px;height:16px}
232
+ [data-theme="cyber-monday"] .ub-card__fav,[data-theme="noel"] .ub-card__fav,[data-theme="halloween"] .ub-card__fav,[data-theme="nouvel-an"] .ub-card__fav{display:none}
233
+ .ub-card__body{display:flex;flex-direction:column;gap:4px;padding:14px 16px 16px}
234
+ .ub-card__cat{display:none;font-size:11px;line-height:16px;font-weight:600;letter-spacing:.08em;text-transform:uppercase;color:var(--ink-muted)}
235
+ [data-theme="noel"] .ub-card__cat,[data-theme="black-friday"] .ub-card__cat{display:block}
236
+ .ub-card__name{font:600 15px/22px var(--ub-font-body)}
237
+ [data-theme="noel"] .ub-card__name{font-size:17px;line-height:24px}
238
+ [data-theme="black-friday"] .ub-card__name{text-transform:uppercase;font-family:var(--ub-font-head);font-size:18px;letter-spacing:.02em}
239
+ [data-theme="halloween"] .ub-card__name,[data-theme="nouvel-an"] .ub-card__name{font-weight:500;font-size:14px}
240
+ .ub-rating{display:flex;align-items:center;gap:6px;font-size:12px;line-height:16px;color:var(--ink-muted)}
241
+ .ub-rating__stars{color:var(--star);letter-spacing:1px;font-size:13px}
242
+ [data-theme="halloween"] .ub-card .ub-rating,[data-theme="nouvel-an"] .ub-card .ub-rating{display:none}
243
+ .ub-card__foot{display:flex;align-items:center;justify-content:space-between;gap:8px;margin-top:6px}
244
+ .ub-price{display:flex;align-items:baseline;gap:8px;flex-wrap:wrap;font-variant-numeric:tabular-nums}
245
+ .ub-price__now{font:700 16px/22px var(--ub-font-body);color:var(--ink)}
246
+ .ub-price__was{font-size:13px;color:var(--ink-muted);text-decoration:line-through}
247
+ .ub-price--sale .ub-price__now{color:var(--sale)}
248
+ .ub-card__cart{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:var(--radius-pill);border:0;background:var(--ink);color:var(--bg)}
249
+ .ub-card__cart svg{width:17px;height:17px}
250
+ .ub-card__cart .ub-arrow{display:none}
251
+ [data-theme="noel"] .ub-card__cart{background:var(--tint-1);color:var(--primary);width:42px;height:42px}
252
+ [data-theme="cyber-monday"] .ub-card__cart{background:var(--bg);color:var(--ink);border:1px solid var(--border);border-radius:var(--radius-md)}
253
+ [data-theme="halloween"] .ub-card__cart,[data-theme="nouvel-an"] .ub-card__cart{width:28px;height:28px;background:var(--primary);color:var(--on-primary)}
254
+ [data-theme="halloween"] .ub-card__cart .ub-cart-ic,[data-theme="nouvel-an"] .ub-card__cart .ub-cart-ic{display:none}
255
+ [data-theme="halloween"] .ub-card__cart .ub-arrow,[data-theme="nouvel-an"] .ub-card__cart .ub-arrow{display:block;width:14px;height:14px}
256
+ [data-theme="black-friday"] .ub-card__cart{background:var(--primary);color:var(--on-primary)}
257
+
258
+ /* ---------- Promo banner ---------- */
259
+ .ub-promo{position:relative;display:grid;grid-template-columns:1.2fr 1fr;align-items:center;gap:var(--space-8);padding:var(--space-8) var(--space-12);border-radius:var(--ub-r-card);background:var(--band-bg);color:var(--band-ink);overflow:hidden;min-height:260px}
260
+ .ub-promo__text{display:flex;flex-direction:column;align-items:flex-start;gap:var(--space-4)}
261
+ .ub-promo h2{font-size:36px;line-height:42px}
262
+ .ub-promo .ub-eyebrow{color:inherit;background:transparent;padding:0}
263
+ [data-theme="cyber-monday"] .ub-promo .ub-eyebrow{background:var(--bg);color:var(--primary);padding:4px 10px}
264
+ .ub-promo__media{height:220px;border-radius:var(--ub-r-media);background:rgba(255,255,255,.14);color:inherit}
265
+ [data-theme="cyber-monday"] .ub-promo__media{background:rgba(74,43,214,.08)}
266
+ .ub-promo .ub-btn--primary{background:var(--band-ink);color:var(--band-bg)}
267
+ [data-theme="cyber-monday"] .ub-promo .ub-btn--primary{background:var(--primary);color:var(--on-primary)}
268
+ [data-theme="halloween"] .ub-promo .ub-btn--primary,[data-theme="nouvel-an"] .ub-promo .ub-btn--primary{background:var(--primary);color:var(--on-primary)}
269
+ [data-theme="black-friday"] .ub-promo .ub-countdown__c{border-color:var(--band-ink);color:var(--band-ink)}
270
+ [data-theme="black-friday"] .ub-promo .ub-countdown__c small{color:var(--band-ink)}
271
+ .ub-promo__seal{display:none;width:108px;height:108px;padding:12px;border-radius:var(--radius-pill);background:var(--bg);color:var(--primary);align-items:center;justify-content:center;text-align:center;font:600 15px/19px var(--ub-font-head)}
272
+ [data-theme="noel"] .ub-promo{grid-template-columns:auto 1fr;padding:var(--space-6) var(--space-8);min-height:0}
273
+ [data-theme="noel"] .ub-promo__media,[data-theme="noel"] .ub-promo .ub-countdown{display:none}
274
+ [data-theme="noel"] .ub-promo__seal{display:flex}
275
+ [data-theme="noel"] .ub-promo__text{flex-direction:row;align-items:center;justify-content:space-between;flex-wrap:wrap;width:100%}
276
+ [data-theme="noel"] .ub-promo .ub-eyebrow{display:none}
277
+
278
+ /* ---------- Product detail (Aeroflow) ---------- */
279
+ .ub-pdp{display:grid;grid-template-columns:1fr 1fr;gap:var(--space-12);align-items:start}
280
+ .ub-gallery__main{aspect-ratio:1/1;border-radius:var(--ub-r-media)}
281
+ .ub-gallery__thumbs{display:grid;grid-template-columns:repeat(4,1fr);gap:var(--space-3);margin-top:var(--space-3)}
282
+ .ub-gallery__thumbs .ub-ph{aspect-ratio:1/1;border-radius:var(--radius-md);border:2px solid transparent}
283
+ .ub-gallery__thumbs .ub-ph[aria-current]{border-color:var(--ink)}
284
+ .ub-pdp__info{display:flex;flex-direction:column;gap:var(--space-3)}
285
+ .ub-pdp__title{font-size:40px;line-height:44px}
286
+ .ub-pdp__subtitle{font-size:16px;color:var(--ink-muted)}
287
+ .ub-pdp .ub-rating{display:flex;font-size:13px;color:var(--ink)}
288
+ .ub-pdp__was{font-size:16px;color:var(--ink-muted);text-decoration:line-through;margin-top:var(--space-2)}
289
+ .ub-pdp__price{display:flex;align-items:center;gap:12px}
290
+ .ub-pdp__price b{font:700 36px/40px var(--ub-font-head);color:var(--sale)}
291
+ .ub-save{padding:3px 10px;border-radius:var(--radius-sm);border:1px solid var(--success);color:var(--success);font-size:13px;font-weight:600}
292
+ .ub-pdp__desc{color:var(--ink-muted);max-width:480px}
293
+ .ub-pdp__buy{display:flex;flex-direction:column;gap:10px;margin-top:var(--space-2)}
294
+ .ub-pdp__ship{text-align:center;font-size:13px;color:var(--ink-muted)}
295
+ .ub-pdp__ship svg{width:14px;height:14px;vertical-align:-2px;margin-right:4px}
296
+ .ub-pdp__trust{display:grid;grid-template-columns:1fr 1fr;gap:12px;padding:16px;border-radius:var(--radius-lg);background:var(--surface);font-size:13px;list-style:none;margin:var(--space-2) 0 0}
297
+ .ub-pdp__trust li{display:flex;align-items:center;gap:8px}
298
+ .ub-pdp__trust svg{width:18px;height:18px}
299
+ .ub-options{display:flex;gap:8px;flex-wrap:wrap}
300
+ .ub-opt{min-width:52px;height:40px;padding:0 14px;border-radius:var(--ub-r-btn);border:1px solid var(--border);background:var(--bg);color:var(--ink);font:500 14px/20px var(--ub-font-body)}
301
+ .ub-opt[aria-pressed="true"]{border:2px solid var(--ink)}
302
+ .ub-faq{border-top:1px solid var(--border)}
303
+ .ub-faq details{border-bottom:1px solid var(--border)}
304
+ .ub-faq summary{display:flex;justify-content:space-between;align-items:center;padding:14px 0;cursor:pointer;list-style:none;font-weight:500}
305
+ .ub-faq summary::-webkit-details-marker{display:none}
306
+ .ub-faq summary::after{content:"";width:8px;height:8px;border-right:1.5px solid currentColor;border-bottom:1.5px solid currentColor;transform:rotate(45deg);margin-right:6px}
307
+ .ub-faq details[open] summary::after{transform:rotate(-135deg)}
308
+ .ub-faq p{padding:0 0 14px;color:var(--ink-muted)}
309
+
310
+ /* ---------- Checkout : paiement international (Stripe + PayPal) ---------- */
311
+ .ub-pay{max-width:540px;display:flex;flex-direction:column;gap:var(--space-4)}
312
+ .ub-pay h2{font-size:22px;line-height:28px}
313
+ .ub-express{display:grid;grid-template-columns:repeat(3,1fr);gap:10px}
314
+ .ub-express button{height:48px;border-radius:var(--radius-md);border:1px solid var(--ink);background:var(--ink);color:var(--bg);font:600 15px/20px var(--ub-font-body);cursor:pointer}
315
+ .ub-express button.ub-express--light{background:var(--bg);color:var(--ink)}
316
+ .ub-divider{display:flex;align-items:center;gap:12px;color:var(--ink-muted);font-size:13px}
317
+ .ub-divider::before,.ub-divider::after{content:"";flex:1;height:1px;background:var(--border)}
318
+ .ub-methods{border:1px solid var(--border);border-radius:var(--radius-lg);overflow:hidden}
319
+ .ub-method{border-bottom:1px solid var(--border)}
320
+ .ub-method:last-child{border-bottom:0}
321
+ .ub-method__row{display:flex;align-items:center;gap:12px;padding:16px;cursor:pointer}
322
+ .ub-method__radio{width:18px;height:18px;border-radius:var(--radius-pill);border:1.5px solid var(--ink-muted)}
323
+ .ub-method[aria-checked="true"] .ub-method__radio{border:6px solid var(--ink)}
324
+ .ub-method[aria-checked="true"]{background:var(--surface)}
325
+ .ub-method__name{font-weight:600;flex:1}
326
+ .ub-method__tags{display:flex;gap:6px}
327
+ .ub-tag{padding:2px 8px;border-radius:var(--radius-sm);border:1px solid var(--border);background:var(--bg);font-size:11px;font-weight:700;color:var(--ink)}
328
+ .ub-method__body{display:grid;grid-template-columns:1fr 1fr;gap:10px;padding:0 16px 16px 46px}
329
+ .ub-field{display:flex;flex-direction:column;gap:6px;font-size:13px;font-weight:500}
330
+ .ub-field--full{grid-column:1/-1}
331
+ .ub-input{height:44px;padding:0 12px;display:flex;align-items:center;border:1px solid var(--border);border-radius:var(--radius-sm);background:var(--bg);color:var(--ink-muted);font-weight:400}
332
+ .ub-method__note{grid-column:1/-1;font-size:12px;color:var(--ink-muted)}
333
+
334
+ /* ---------- Cart drawer ---------- */
335
+ .ub-cart{width:400px;border-radius:var(--ub-r-card);background:var(--bg);border:1px solid var(--border);box-shadow:var(--shadow-pop);overflow:hidden}
336
+ .ub-cart__head{display:flex;justify-content:space-between;align-items:center;padding:18px 20px;border-bottom:1px solid var(--border)}
337
+ .ub-cart__head h2{font-size:20px;line-height:28px}
338
+ .ub-cart__ship{padding:14px 20px;font-size:13px;color:var(--ink-muted);border-bottom:1px solid var(--border)}
339
+ .ub-bar{height:6px;border-radius:var(--radius-pill);background:var(--surface);margin-top:8px;overflow:hidden}
340
+ .ub-bar i{display:block;height:100%;background:var(--primary)}
341
+ .ub-line{display:grid;grid-template-columns:72px 1fr auto;gap:14px;padding:16px 20px;border-bottom:1px solid var(--border)}
342
+ .ub-line .ub-ph{width:72px;height:72px;border-radius:var(--radius-md)}
343
+ .ub-line__name{font-weight:600;font-size:14px;line-height:20px}
344
+ .ub-line__meta{font-size:12px;color:var(--ink-muted)}
345
+ .ub-qty{display:inline-flex;align-items:center;margin-top:8px;border:1px solid var(--border);border-radius:var(--ub-r-btn);height:32px}
346
+ .ub-qty button{width:30px;height:30px;border:0;background:transparent;color:var(--ink)}
347
+ .ub-qty span{min-width:22px;text-align:center;font-size:13px;font-weight:600}
348
+ .ub-cart__foot{padding:18px 20px;display:flex;flex-direction:column;gap:12px}
349
+ .ub-cart__row{display:flex;justify-content:space-between;font-size:14px}
350
+ .ub-cart__row b{font-size:18px}
351
+
352
+ /* ---------- Footer ---------- */
353
+ .ub-footer{margin-top:var(--space-12);background:var(--surface);border-top:1px solid var(--border)}
354
+ [data-theme="halloween"] .ub-footer,[data-theme="nouvel-an"] .ub-footer{background:var(--band-bg);color:var(--band-ink);border:0}
355
+ [data-theme="black-friday"] .ub-footer{background:var(--ink);color:var(--bg);border:0}
356
+ .ub-footer__top{display:grid;grid-template-columns:1.5fr repeat(3,1fr);gap:var(--space-8);padding:var(--space-12) 0 var(--space-8)}
357
+ .ub-footer p{opacity:.85;font-size:14px;margin-top:10px;max-width:280px}
358
+ .ub-footer h4{margin:0 0 12px;font-size:13px;letter-spacing:.06em;text-transform:uppercase}
359
+ .ub-footer ul{list-style:none;margin:0;padding:0;font-size:14px;line-height:30px;opacity:.85}
360
+ .ub-footer__bot{display:flex;justify-content:space-between;align-items:center;gap:16px;padding:18px 0 28px;border-top:1px solid rgba(127,127,127,.25);font-size:13px;flex-wrap:wrap}
361
+ .ub-pays{display:flex;gap:6px;flex-wrap:wrap}
362
+ .ub-pays span{padding:4px 9px;border-radius:var(--radius-sm);background:#ffffff;color:#111827;border:1px solid rgba(127,127,127,.3);font-size:11px;font-weight:700}
363
+
364
+ @media (max-width:900px){
365
+ .ub-hero__in,.ub-pdp,.ub-promo{grid-template-columns:1fr}
366
+ .ub-hero__title,[data-theme="halloween"] .ub-hero__title,[data-theme="nouvel-an"] .ub-hero__title{font-size:40px;line-height:44px}
367
+ [data-theme="black-friday"] .ub-hero__title{font-size:64px;line-height:64px}
368
+ .ub-grid,.ub-tiles,[data-theme="noel"] .ub-tiles,[data-theme="cyber-monday"] .ub-tiles,.ub-trust{grid-template-columns:repeat(2,1fr)}
369
+ .ub-nav__links,.ub-search{display:none!important}
370
+ .ub-footer__top{grid-template-columns:1fr 1fr}
371
+ .ub-cart{width:100%}
372
+ }
@@ -0,0 +1,17 @@
1
+ /* Relie les polices next/font (--nf-*) aux variables du design (--font-*, définies dans tokens.css).
2
+ :root:root l'emporte sur le :root de tokens.css sans modifier ce fichier. */
3
+ :root:root {
4
+ --font-inter: var(--nf-inter, Inter), system-ui, sans-serif;
5
+ --font-jakarta: var(--nf-jakarta, "Plus Jakarta Sans"), var(--nf-inter, Inter), sans-serif;
6
+ --font-oswald: var(--nf-oswald, Oswald), "Arial Narrow", sans-serif;
7
+ --font-outfit: var(--nf-outfit, Outfit), var(--nf-inter, Inter), sans-serif;
8
+ --font-poppins: var(--nf-poppins, Poppins), var(--nf-inter, Inter), sans-serif;
9
+ --font-sora: var(--nf-sora, Sora), var(--nf-inter, Inter), sans-serif;
10
+ --font-space-grotesk: var(--nf-space-grotesk, "Space Grotesk"), var(--nf-inter, Inter), sans-serif;
11
+ }
12
+
13
+ /* Le corps de page prend le fond du thème (le starter force du blanc). */
14
+ html,
15
+ body {
16
+ background: var(--bg);
17
+ }