From c08717195ac049b5799c7742a647a38a563bf62b Mon Sep 17 00:00:00 2001 From: gcch Date: Wed, 29 Apr 2026 10:45:49 +0200 Subject: [PATCH 1/6] ref(boutique) wip scripts sous forme Effect --- .../src/scripts-effect/lib/api.ts | 17 +- .../src/scripts-effect/schemas/api.ts | 58 ++++++- .../src/scripts-effect/schemas/product.ts | 3 + .../src/scripts/page-boutique/runtime.ts | 17 ++ .../src/scripts/page-boutique/service-dom.ts | 163 ++++++++++++++++++ .../scripts/page-boutique/service-elements.ts | 26 +++ .../scripts/page-boutique/service-messages.ts | 29 ++++ .../src/scripts/scripts-page-boutique.ts | 87 ++-------- 8 files changed, 323 insertions(+), 77 deletions(-) create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-elements.ts create mode 100644 web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-messages.ts diff --git a/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts b/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts index dc58274a..9903664c 100644 --- a/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts-effect/lib/api.ts @@ -1,4 +1,4 @@ -import { Console, Context, Effect, Layer, Match, pipe, Schedule, Schema, SchemaIssue } from "effect"; +import { Console, Context, Effect, Layer, Match, pipe, References, Schedule, Schema, SchemaIssue } from "effect"; import type { SchemaError } from "effect/Schema"; import type { HttpClientError, @@ -11,6 +11,7 @@ import { } from "effect/unstable/http"; import { HttpClientErrorSchema } from "effect/unstable/http/HttpClientError"; import type { CartProduct, GetProducts } from "../schemas/api.ts"; +import { Product } from "../schemas/api.ts"; import { WooCommerceCart } from "../schemas/cart.ts"; /** Le nombre maximal d'essais pour une Requête. */ @@ -52,7 +53,7 @@ const APIFetchClient = FetchHttpClient.layer.pipe( Layer.succeed( FetchHttpClient.RequestInit, { - credentials: "same-origin", + credentials: "include", headers: { Accept: "application/json", "Content-Type": "application/json", @@ -135,18 +136,22 @@ class APIClient extends Context.Service()("haikuatelier.fr/APIClient" ); const GetProducts = Effect.fn("APIClient.GetProducts")( - function*(nonce: string, authString: string, queryParams: GetProducts) { + function*(nonce: string, queryParams: GetProducts) { const request = pipe( - HttpClientRequest.get(`/wp-json/wc/store/products`), + HttpClientRequest.get(`/wp-json/wc/v3/products`), HttpClientRequest.setHeader("Nonce", nonce), - HttpClientRequest.bearerToken(authString), + // TODO: Utiliser l'environnement + HttpClientRequest.basicAuth( + "ck_eded693107df0dbc19dab937e0c71325db810a4a", + "cs_a68c0f3e711c4a21be51495d09e6fe807649bbfb", + ), // Le corps de la Requête a été validée en amont, on peut utiliser Unsafe. HttpClientRequest.setUrlParams(queryParams), ); const response = yield* pipe( haikuHTTPClient.execute(request), - Effect.flatMap(HttpClientResponse.schemaBodyJson(Schema.Unknown)), + Effect.flatMap(HttpClientResponse.schemaBodyJson(Schema.Array(Product))), Effect.mapError(error => matchAPIError(error)), Effect.tapError(error => printErrorAsSuccinctMessage(error)), ); diff --git a/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/api.ts b/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/api.ts index e3480331..69342d57 100644 --- a/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/api.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/api.ts @@ -1,5 +1,5 @@ import { Schema } from "effect"; -import { ProductId, ProductQuantity, ProductVariationAttribute } from "./product.ts"; +import { ProductId, ProductQuantity, ProductStatus, ProductVariationAttribute } from "./product.ts"; class CartProduct extends Schema.Class("CartProduct")({ id: ProductId, @@ -7,4 +7,58 @@ class CartProduct extends Schema.Class("CartProduct")({ variation: Schema.Array(ProductVariationAttribute), }) {} -export { CartProduct }; +class GetProducts extends Schema.Class("GetProducts")({ + /** L'ID de la Catégorie de Produits demandé. */ + category: Schema.Int.pipe(Schema.optional), + /** Le numéro de page demandé. */ + page: Schema.Int, + /** Le nombre de Produits par page demandé. */ + per_page: Schema.Int, + /** Le statut demandé des Produits. */ + status: ProductStatus, +}) {} + +class Product extends Schema.Class("Product")({ + attributes: Schema.Unknown, + brands: Schema.Unknown, + // TODO: Pourrait être une énumération. + catalog_visibility: Schema.String, + categories: Schema.Unknown, + description: Schema.String, + dimensions: Schema.Unknown, + featured: Schema.Boolean, + grouped_products: Schema.Unknown, + has_options: Schema.Boolean, + id: Schema.Int, + // NOTE: Non-standard, injecté dans la Réponse. + image_repos: Schema.String, + // NOTE: Non-standard, injecté dans la Réponse. + image_survol: Schema.String, + images: Schema.Unknown, + low_stock_amount: Schema.Union([Schema.Number, Schema.Null]), + menu_order: Schema.Int, + meta_data: Schema.Unknown, + name: Schema.String, + on_sale: Schema.Boolean, + parent_id: Schema.Int, + permalink: Schema.URLFromString, + price: Schema.String, + // NOTE: Non-standard, injecté dans la Réponse. + prix_maximal: Schema.String, + regular_price: Schema.String, + sale_price: Schema.String, + short_description: Schema.String, + sku: Schema.String, + slug: Schema.String, + sold_individually: Schema.Boolean, + stock_quantity: Schema.Union([Schema.Int, Schema.Null]), + // TODO: Pourrait être une énumération. + stock_status: Schema.String, + tags: Schema.Unknown, + type: Schema.Literals(["external", "grouped", "simple", "variable"]), + variations: Schema.Array(Schema.Int), + virtual: Schema.Boolean, + weight: Schema.String, +}) {} + +export { CartProduct, GetProducts, Product }; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/product.ts b/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/product.ts index 80cb0405..825adeb7 100644 --- a/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/product.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts-effect/schemas/product.ts @@ -2,6 +2,8 @@ import { Effect, Option, pipe, Schema, SchemaIssue, SchemaTransformation } from "effect"; import type { SchemaError } from "effect/Schema"; +const ProductStatus = Schema.Literals(["any", "draft", "future", "pending", "private", "publish", "trash"]); + /** Représente l'identifiant numérique unique d'un Produit. */ const ProductId = Schema.Int.pipe(Schema.brand("ProductId")).check(Schema.isGreaterThan(0)); @@ -78,6 +80,7 @@ export { ProductId, ProductQuantity, ProductQuantityFromString, + ProductStatus, ProductVariation, ProductVariationAttribute, }; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts new file mode 100644 index 00000000..5ae434cd --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/runtime.ts @@ -0,0 +1,17 @@ +import { Console, Layer, ManagedRuntime, pipe } from "effect"; + +import { APIClient } from "../../scripts-effect/lib/api.ts"; +import ShopPageDOM from "./service-dom.ts"; +import ShopPageElements from "./service-elements.ts"; +import ShopPageMessages from "./service-messages.ts"; + +const ShopPageRuntime = ManagedRuntime.make( + pipe( + ShopPageDOM.Live, + Layer.provideMerge(ShopPageMessages.Live), + Layer.provideMerge(ShopPageElements.Live), + Layer.provide(APIClient.Live), + Layer.tapError(error => Console.error("ProductPageRuntime", "Impossible de créer le Layer :", error)), + ), +); +export default ShopPageRuntime; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts new file mode 100644 index 00000000..9a404aea --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-dom.ts @@ -0,0 +1,163 @@ +import { + Array as FxArray, + Console, + Context, + Effect, + Layer, + Option, + pipe, + Ref, + Schema, + SchemaIssue, + Stream, + SubscriptionRef, +} from "effect"; +import { SchemaError } from "effect/Schema"; +import html from "html-template-tag"; +import { APIClient } from "../../scripts-effect/lib/api.ts"; +import { setLoadingState } from "../../scripts-effect/lib/elements.ts"; +import { GetProducts, Product } from "../../scripts-effect/schemas/api.ts"; +import { ATTRIBUT_HIDDEN, ATTRIBUT_ID_CATEGORIE_PRODUITS, ATTRIBUT_PAGE } from "../constantes/dom.ts"; +import ShopPageElements from "./service-elements.ts"; +import ShopPageMessages from "./service-messages.ts"; + +/** Le nombre de Produits à afficher par « page ». */ +const PRODUCTS_PER_PAGE = 18; + +/** Forme attendue des données injectées dans la page sous forme de JSON. */ +class PageStates extends Schema.Opaque()( + Schema.Struct({ + authString: Schema.NonEmptyString, + nonce: Schema.NonEmptyString, + }), +) {} + +/** Représente une Erreur liée à un état de page invalide ou incohérent empêchant la poursuite des interactions/de la navigation. */ +class InvalidShopPageStateError + extends Schema.TaggedErrorClass()("InvalidShopPageStateError", { + cause: Schema.String, + }) +{ + /** Créé une `InvalidShopPageStateError` depuis une `SchemaError` levée suite à une validation. */ + static readonly fromSchemaError = (schemaError: SchemaError): InvalidShopPageStateError => + new InvalidShopPageStateError({ + cause: SchemaIssue.makeFormatterDefault()(schemaError.issue), + }); +} + +class ShopPageDOM extends Context.Service()("haikuatelier.fr/Shop/ShopPageDOM", { + make: Effect.gen(function*() { + const { PageStatesRawJson, ProductsGrid, ShowMoreButton } = yield* ShopPageElements; + const { ShowMoreButtonText } = yield* ShopPageMessages; + const API = yield* APIClient; + + const { authString, nonce } = yield* pipe( + PageStatesRawJson.textContent, + (textContent: string) => + Schema.decodeUnknownEffect(Schema.fromJsonString(PageStates))(textContent, { errors: "all" }), + Effect.mapError(InvalidShopPageStateError.fromSchemaError), + ); + + /** ID de la Catégorie des Produits de la Page, si la Page courante est une Archive. */ + const ProductsCategoryId = yield* pipe( + ProductsGrid.getAttribute(ATTRIBUT_ID_CATEGORIE_PRODUITS), + Number, + Option.fromNullishOr, + Ref.make, + ); + + // TODO: Créer une SubscriptionRef mettant à jour le DOM au changement de valeur. + const PageNumber = yield* Ref.make(1); + + const createProductDOM = (product: Product): HTMLElement => { + const article = document.createElement("article"); + article.classList.add("produit"); + article.innerHTML = html`
+ + + $${product.image_repos} + + + + $${product.image_survol} + + + +
+

+ ${product.name} +

+

+ ${product.prix_maximal}€ +

+
+
+ `; + return article; + }; + const createNewPageDOM = (products: ReadonlyArray) => { + const fragment: DocumentFragment = document.createDocumentFragment(); + + // Ajoute le HTML des cartes des Produits au fragment. + pipe( + FxArray.take(products, PRODUCTS_PER_PAGE), + FxArray.forEach(product => { + const productHTML = createProductDOM(product); + fragment.append(productHTML); + }), + ); + + return fragment; + }; + + const onMoreProductedWantedHandler = Effect.fn("onMoreProductedWantedHandler")(function*() { + yield* Console.debug("onMoreProductedWantedHandler"); + + /** Le numéro de page souhaitée. */ + const newPageNumber = yield* Ref.updateAndGet(PageNumber, pageNumber => pageNumber + 1); + /** L'ID de la Catégorie de Produits affichée dans la page si elle existe. */ + const categoryId = pipe(yield* Ref.get(ProductsCategoryId), Option.getOrUndefined); + + const requestBody = yield* GetProducts.makeEffect({ + page: newPageNumber, + per_page: PRODUCTS_PER_PAGE, + status: "publish", + ...(categoryId && { category: categoryId }), + }); + + // Désactive les interactions et affiche un texte de chargement le temps de la requête. + yield* setLoadingState(ShowMoreButton, true); + yield* SubscriptionRef.set(ShowMoreButtonText, "Getting Products..."); + + const newProducts = yield* API.GetProducts(nonce, requestBody); + yield* Console.debug("onMoreProductedWantedHandler", newProducts); + + // Rétablis le texte du Bouton et réactive les interactions. + yield* SubscriptionRef.set(ShowMoreButtonText, "Show more"); + yield* setLoadingState(ShowMoreButton, false); + + // Cache le bouton s'il y a moins de Produits disponibles que PRODUCTS_PER_PAGE (que l'on est donc à la dernière page). + ShowMoreButton.toggleAttribute(ATTRIBUT_HIDDEN, newProducts.length < PRODUCTS_PER_PAGE); + + // Ajoute les nouveaux Produits dans le DOM. + ProductsGrid.append(fragment); + ProductsGrid.setAttribute(ATTRIBUT_PAGE, String(newPageNumber)); + }); + + const initLoadMoreProductsOnButtonClick = Effect.fn("initLoadMoreProductsOnButtonClick")(function*() { + return yield* pipe( + Stream.fromEventListener(ShowMoreButton, "click"), + Stream.tap(onMoreProductedWantedHandler), + Stream.runDrain, + ); + }); + + return { + ProductsCategoryId, + initLoadMoreProductsOnButtonClick, + }; + }), +}) { + static readonly Live = Layer.effect(this, this.make); +} +export default ShopPageDOM; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-elements.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-elements.ts new file mode 100644 index 00000000..208f4dbf --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-elements.ts @@ -0,0 +1,26 @@ +import { Context, Effect, Layer } from "effect"; +import { getFirstSelectorFromDocument } from "../../scripts-effect/lib/dom.ts"; +import { IncoherentDOMError } from "../page-produit/errors.ts"; + +class ShopPageElements extends Context.Service()("haikuatelier.fr/Shop/ShopPageElements", { + make: Effect.gen(function*() { + const PageStatesRawJson = yield* getFirstSelectorFromDocument("#page-states"); + + /** Le Bouton « Show more » pour afficher plus de Produits à la suite de la Grille. */ + const ShowMoreButton = yield* getFirstSelectorFromDocument( + "#page-boutique #bouton-plus-de-produits", + ); + + /** Le conteneur de la Grille des Produits. */ + const ProductsGrid = yield* getFirstSelectorFromDocument("#page-boutique .grille-produits"); + + return { + PageStatesRawJson, + ProductsGrid, + ShowMoreButton, + }; + }).pipe(Effect.mapErrorEager(IncoherentDOMError.fromNoSuchElementError)), +}) { + static readonly Live = Layer.effect(this, this.make); +} +export default ShopPageElements; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-messages.ts b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-messages.ts new file mode 100644 index 00000000..dcb27d02 --- /dev/null +++ b/web/app/themes/haiku-atelier-2024/src/scripts/page-boutique/service-messages.ts @@ -0,0 +1,29 @@ +import { Context, Effect, Layer, pipe, Stream, SubscriptionRef } from "effect"; + +import ShopPageElements from "./service-elements.ts"; + +class ShopPageMessages extends Context.Service()("haikuatelier.fr/Shop/Messages", { + make: Effect.gen(function*() { + const { ShowMoreButton } = yield* ShopPageElements; + + const ShowMoreButtonText = yield* SubscriptionRef.make("Show more"); + // Const ShowMoreErrorText = yield* SubscriptionRef.make>(Option.none()); + + const initShowMoreButtonUpdates = Effect.fn("initShowMoreButtonUpdates")(function*() { + return yield* pipe( + SubscriptionRef.changes(ShowMoreButtonText), + Stream.tap(newText => { + ShowMoreButton.textContent = newText; + return Effect.succeed(newText); + }), + Stream.runDrain, + ); + }); + + return { ShowMoreButtonText, initShowMoreButtonUpdates }; + }), +}) { + static readonly Live = Layer.effect(this, this.make); +} + +export default ShopPageMessages; diff --git a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts index 5f8b9d50..d3b9efc9 100755 --- a/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts +++ b/web/app/themes/haiku-atelier-2024/src/scripts/scripts-page-boutique.ts @@ -2,75 +2,24 @@ * Scripts pour les fonctionnalités de la page Boutique. */ -import { pipe } from "@mobily/ts-belt"; -import { tap } from "@mobily/ts-belt/Function"; -import { EitherAsync } from "purify-ts"; -import { match, P } from "ts-pattern"; -import { ValiError } from "valibot"; - -import type { APIFetchErrors } from "./lib/types/api/erreurs"; -import type { WCV3Products, WCV3ProductsArgs } from "./lib/types/api/v3/products.ts"; -import type { GenericPageState } from "./lib/types/pages"; - -import { ROUTE_API_NOUVELLE_PRODUCTS } from "./constantes/api.ts"; -import { PRODUCT_STATUTES } from "./constantes/api/products.ts"; -import { - ATTRIBUT_CHARGEMENT, - ATTRIBUT_DESACTIVE, - ATTRIBUT_HIDDEN, - ATTRIBUT_ID_CATEGORIE_PRODUITS, - ATTRIBUT_PAGE, - DOM_BOUTON_PLUS_PRODUITS, - DOM_GRILLE_PRODUITS, -} from "./constantes/dom.ts"; -import { lanceAnimationCycleLoading } from "./lib/animations.ts"; -import { html, mustGetEleInDocument } from "./lib/dom.ts"; -import { BadRequestError, reporteErreur, ServerError } from "./lib/erreurs.ts"; -import { getBackendAvecParametresUrl, newPartialResponse } from "./lib/reseau.ts"; -import { WCV3ProductsArgsSchema, WCV3ProductsSchema } from "./lib/schemas/api/v3/products.ts"; -import { safeSchemaParse } from "./lib/validation.ts"; - -type APIProductsErrors = - | APIFetchErrors - | ValiError - | ValiError; - -// @ts-expect-error -- États injectés par le modèle PHP -// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment -- États injectés par le modèle PHP -const ETATS_PAGE: GenericPageState = _etats; - -// Numéros magiques -const PRODUCTS_PER_PAGE = 12; - -// Éléments d'intérêt -const E = { - BOUTON_PLUS_DE_PRODUITS: mustGetEleInDocument(DOM_BOUTON_PLUS_PRODUITS), - GRILLE_PRODUITS: mustGetEleInDocument(DOM_GRILLE_PRODUITS), -}; - -/** - * TODO - */ -const initialisePageBoutique = (): void => { - /** ID de la Catégorie de Produits si la Page courante est l'Archive d'une Catégorie. */ - const idCategorieProduits: null | string = E.GRILLE_PRODUITS.getAttribute(ATTRIBUT_ID_CATEGORIE_PRODUITS); - - E.BOUTON_PLUS_DE_PRODUITS.addEventListener("click", (): void => { - /** Le numéro de page demandée par l'Utilisateur. */ - const nouveauNumeroPage = Number(E.GRILLE_PRODUITS.getAttribute(ATTRIBUT_PAGE)) + 1; - /** Les arguments passés à la requête auprès Backend pour la nouvelle page de Produits. */ - const args: WCV3ProductsArgs = { - page: nouveauNumeroPage, - per_page: PRODUCTS_PER_PAGE, - status: PRODUCT_STATUTES.PUBLISH, - // Ajoute conditionnellement la Catégorie de Produits - ...(idCategorieProduits && { category: idCategorieProduits }), - }; - - undefined; - }); -}; +import { Console, Effect } from "effect"; +import ShopPageRuntime from "./page-boutique/runtime.ts"; +import ShopPageDOM from "./page-boutique/service-dom.ts"; +import ShopPageElements from "./page-boutique/service-elements.ts"; +import ShopPageMessages from "./page-boutique/service-messages.ts"; document.addEventListener("DOMContentLoaded", (): void => { - initialisePageBoutique(); + console.debug("scripts-page-boutique"); + // initialisePageBoutique(); + ShopPageRuntime.runFork(Effect.gen(function*() { + const Elements = yield* ShopPageElements; + const DOM = yield* ShopPageDOM; + const Messages = yield* ShopPageMessages; + + yield* Effect.all([DOM.initLoadMoreProductsOnButtonClick(), Messages.initShowMoreButtonUpdates()], { + concurrency: "unbounded", + }).pipe(Effect.tapError(Console.error)); + + console.debug(Elements.ProductsGrid); + })); }); From b643443b57b55c97361a662aaf4f09d57b9428da Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 2/6] =?UTF-8?q?corv=C3=A9e(deps)=20met=20=C3=A0=20jour=20l?= =?UTF-8?q?es=20d=C3=A9pendances?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- aube-lock.yaml | 88 +++++++++++++++++++++++++------------------------- package.json | 2 +- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/aube-lock.yaml b/aube-lock.yaml index f12c431a..6720acf8 100644 --- a/aube-lock.yaml +++ b/aube-lock.yaml @@ -13,7 +13,7 @@ importers: version: 4.0.0-rc.5 '@sentry/browser': specifier: ^10.50.0 - version: 10.50.0 + version: 10.51.0 a11y-dialog: specifier: ^8.1.5 version: 8.1.5 @@ -52,8 +52,8 @@ importers: specifier: ^0.85.1 version: 0.85.1 '@effect/tsgo': - specifier: 0.5.1 - version: 0.5.1 + specifier: ^0.5.1 + version: 0.5.2 '@gcch/configuration-eslint': specifier: git+https://git.gcch.fr/gcch/configuration-eslint#888eb4aa54 version: https://git.gcch.fr/gcch/configuration-eslint#888eb4aa54e5bfd6251566d7469ee99204c19f45 @@ -68,7 +68,7 @@ importers: version: 1.59.1 '@sentry/core': specifier: ^10.50.0 - version: 10.50.0 + version: 10.51.0 '@types/bun': specifier: ^1.3.13 version: 1.3.13 @@ -116,7 +116,7 @@ importers: version: 2.6.1 knip: specifier: ^6.8.0 - version: 6.8.0 + version: 6.9.0 lightningcss: specifier: ^1.32.0 version: 1.32.0 @@ -740,15 +740,15 @@ packages: resolution: {integrity: sha512-EXnJjIy6zQ3nUO/MZ+ynWUb8B895KZPotd1++oTs9JjDkplwM7cb6zo8Zq2zU6piwq+KflO7amXbEfj1UMpHkw==} hasBin: true - '@effect/tsgo-linux-x64@0.5.1': - resolution: {integrity: sha512-70dMv3/H+P3KDNWb31qPXJiJh6s78k3+J+QXN8RatKiQYrJw2HhREYL6ToVx9y5WOV7XFvC0eCIIa4/AMwQLTw==} + '@effect/tsgo-linux-x64@0.5.2': + resolution: {integrity: sha512-V6sHIZlKQv693ABb9REX0RzIvzyCbNg2uP5+4MXwetlSxz8pmeAUCpraAQLXBkKlYL5rG9kMIobDFU9A88Nqig==} os: - linux cpu: - x64 - '@effect/tsgo@0.5.1': - resolution: {integrity: sha512-INANZ/NK9akOwSQVWpQgSDLjlegrs4gui21nuQsgN7zCjCmj4m/ixUDuVgtW2C0UfqhPWWabyFWCDntu7ryCZQ==} + '@effect/tsgo@0.5.2': + resolution: {integrity: sha512-LEKmx1rwP1j3l9mPW6Bx8VIdGKW+uEvvML89z4xiWnPC+h/uFm3y6FGHULop9Kl09Ybwn2TVuZzVPSZLj+ydmg==} hasBin: true '@es-joy/jsdoccomment@0.86.0': @@ -969,28 +969,28 @@ packages: '@rolldown/pluginutils@1.0.0-rc.17': resolution: {integrity: sha512-n8iosDOt6Ig1UhJ2AYqoIhHWh/isz0xpicHTzpKBeotdVsTEcxsSA/i3EVM7gQAj0rU27OLAxCjzlj15IWY7bg==} - '@sentry-internal/browser-utils@10.50.0': - resolution: {integrity: sha512-42bxyRTxnCmYlWnvz4CxikuQNanw8UNma2WJrtxJ0f1MAJV2GhQGSHDLnA+lvFlmiz6qct3pfen/NXGyOTegTA==} + '@sentry-internal/browser-utils@10.51.0': + resolution: {integrity: sha512-lNKBS4P7RUvf1niojXQWe9bU3gnBUCbST4Dj0pSiyat1N96cXVyHkeE+uGxowD0RrVWhs+kGHiVX3FcmRWF6sA==} engines: {node: '>=18'} - '@sentry-internal/feedback@10.50.0': - resolution: {integrity: sha512-0k9XZF0wn86f77mIO2U3gNNyDZooy139CnEanRzHinrN106vVzvBZ6TUEQoHtoO1fqQxr+nWWVrqV/PXUqk47w==} + '@sentry-internal/feedback@10.51.0': + resolution: {integrity: sha512-bCM95bcpphx28e6aU0bwRLxOgwosYsdNzezM1sM0pVOkb0TB3hDFRamramVDK+/Hp1o8qmRxS4c5w/A7YBZGkA==} engines: {node: '>=18'} - '@sentry-internal/replay-canvas@10.50.0': - resolution: {integrity: sha512-jx6RKBmcJSWdI92qDGS/sBv1w+7Cww879Z/moX7bw7ipHa/Ts3iDcB3rgZwvhmi17U+mvYsbJeL2DXkPo3TjPw==} + '@sentry-internal/replay-canvas@10.51.0': + resolution: {integrity: sha512-8PW1Pp+Yl3lPwYqhBCr5SgkuhDanu9ZLzUqD2bPKL/ElqbM2eDVIWxq4z4ZzePrmZa6IcCjTv6sVQJ7Z4dLyLA==} engines: {node: '>=18'} - '@sentry-internal/replay@10.50.0': - resolution: {integrity: sha512-51FYNfnvVLAWw1rrEWPFfwHuMRb9mkVCFGA4J9/un7SpeGBsQDziGB0Di4fsCxI7+EdSBpfLHPF0csKtCCw0oQ==} + '@sentry-internal/replay@10.51.0': + resolution: {integrity: sha512-jCpI5HXSwK6ZT2HX70+mDRciAocHzSiDk4DTgvzV69Wvd+Ei5WLgE+d39eaEPsm8lUC0Ydntb5sJIB6uG9D4bw==} engines: {node: '>=18'} - '@sentry/browser@10.50.0': - resolution: {integrity: sha512-1f6rAvET6myiTaSeYqvaaBwvq1LfxqWjAPIoAW/NVC9bPMkeEcuvgDajHrnZMrBeWoJ81NMyoLkyX+iOc7MoFA==} + '@sentry/browser@10.51.0': + resolution: {integrity: sha512-Zdc0sKfenxUtW/OGhtJ7xHFN44bXR7YqxJ1zBDzlZfW0nTbeTTUZBq9z5NUw6qdS0Vs/i3V4qzAKTbRKWfqSEA==} engines: {node: '>=18'} - '@sentry/core@10.50.0': - resolution: {integrity: sha512-J4A+vzUO3adl0TkFCjaN1+4miamrjHiEIYuLHiuu1lmAjq5WIVw32ObvAh4yMwNtxyaEMosTrrh5M6f12XSJFg==} + '@sentry/core@10.51.0': + resolution: {integrity: sha512-Y45V/YXvVLEXmOdkbD1oG1gkRWFi9guCEGg3PlIlIpRjAbZUrvLGgjRJIc1E7XpSzmOnWbs5BbUxMv4PDaPj2w==} engines: {node: '>=18'} '@sindresorhus/base62@1.0.0': @@ -2164,8 +2164,8 @@ packages: resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} engines: {node: '>=0.10.0'} - knip@6.8.0: - resolution: {integrity: sha512-FaTrNiqc74KTUMI4KZ5CWWxR2oVTm/bEEik16NKz7usiUJXG4+Df2XA2SPAm+mG9bBY22NvBMM4IeBcUZFslyg==} + knip@6.9.0: + resolution: {integrity: sha512-2GLjxteBwmsSA3Z5sJZpPDaNPBIMnlm4/9Nx4CZadEK7YccJZ2/4kwKgPWhVYEqxhwhD0WO4txWXNGTO/Odkkg==} engines: {node: ^20.19.0 || >=22.12.0} hasBin: true @@ -3830,11 +3830,11 @@ snapshots: '@effect/language-service@0.85.1': {} - '@effect/tsgo-linux-x64@0.5.1': {} + '@effect/tsgo-linux-x64@0.5.2': {} - '@effect/tsgo@0.5.1': + '@effect/tsgo@0.5.2': optionalDependencies: - '@effect/tsgo-linux-x64': 0.5.1 + '@effect/tsgo-linux-x64': 0.5.2 '@es-joy/jsdoccomment@0.86.0': dependencies: @@ -4007,33 +4007,33 @@ snapshots: '@rolldown/pluginutils@1.0.0-rc.17': {} - '@sentry-internal/browser-utils@10.50.0': + '@sentry-internal/browser-utils@10.51.0': dependencies: - '@sentry/core': 10.50.0 + '@sentry/core': 10.51.0 - '@sentry-internal/feedback@10.50.0': + '@sentry-internal/feedback@10.51.0': dependencies: - '@sentry/core': 10.50.0 + '@sentry/core': 10.51.0 - '@sentry-internal/replay-canvas@10.50.0': + '@sentry-internal/replay-canvas@10.51.0': dependencies: - '@sentry-internal/replay': 10.50.0 - '@sentry/core': 10.50.0 + '@sentry-internal/replay': 10.51.0 + '@sentry/core': 10.51.0 - '@sentry-internal/replay@10.50.0': + '@sentry-internal/replay@10.51.0': dependencies: - '@sentry-internal/browser-utils': 10.50.0 - '@sentry/core': 10.50.0 + '@sentry-internal/browser-utils': 10.51.0 + '@sentry/core': 10.51.0 - '@sentry/browser@10.50.0': + '@sentry/browser@10.51.0': dependencies: - '@sentry-internal/browser-utils': 10.50.0 - '@sentry-internal/feedback': 10.50.0 - '@sentry-internal/replay': 10.50.0 - '@sentry-internal/replay-canvas': 10.50.0 - '@sentry/core': 10.50.0 + '@sentry-internal/browser-utils': 10.51.0 + '@sentry-internal/feedback': 10.51.0 + '@sentry-internal/replay': 10.51.0 + '@sentry-internal/replay-canvas': 10.51.0 + '@sentry/core': 10.51.0 - '@sentry/core@10.50.0': {} + '@sentry/core@10.51.0': {} '@sindresorhus/base62@1.0.0': {} @@ -5310,7 +5310,7 @@ snapshots: kind-of@6.0.3: {} - knip@6.8.0: + knip@6.9.0: dependencies: fdir: 6.5.0(picomatch@4.0.4) formatly: 0.3.0 diff --git a/package.json b/package.json index 5e0a9dd9..45806203 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,7 @@ }, "devDependencies": { "@effect/language-service": "^0.85.1", - "@effect/tsgo": "0.5.1", + "@effect/tsgo": "^0.5.1", "@gcch/configuration-eslint": "git+https://git.gcch.fr/gcch/configuration-eslint#888eb4aa54", "@gcch/configuration-oxlint": "git+https://git.gcch.fr/gcch/configuration-oxlint#83547fc1ebfd", "@gcch/configuration-prettier": "git+https://git.gcch.fr/gcch/configuration-prettier#d267d6dc5e", From de0a175624dded0980f97ead29d17e356985a2c0 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 3/6] =?UTF-8?q?corv=C3=A9e(deps)=20installe=20html-templat?= =?UTF-8?q?e-tag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .zed/settings.json | 1 + aube-lock.yaml | 21 +++++++++++++++++++++ package.json | 1 + 3 files changed, 23 insertions(+) diff --git a/.zed/settings.json b/.zed/settings.json index c4e389e2..8ba0003e 100644 --- a/.zed/settings.json +++ b/.zed/settings.json @@ -11,6 +11,7 @@ "!oxlint", "!prettier", "!tailwindcss-language-server", + "!tsgo", "!vtsls", "..." ], diff --git a/aube-lock.yaml b/aube-lock.yaml index 6720acf8..64c19c98 100644 --- a/aube-lock.yaml +++ b/aube-lock.yaml @@ -20,6 +20,9 @@ importers: effect: specifier: ^4.0.0-beta.59 version: 4.0.0-beta.59 + html-template-tag: + specifier: ^5.0.0 + version: 5.0.0 lit-html: specifier: ^3.3.2 version: 3.3.2 @@ -1928,13 +1931,22 @@ packages: hookified@2.2.0: resolution: {integrity: sha512-p/LgFzRN5FeoD3DLS6bkUapeye6E4SI6yJs6KetENd18S+FBthqYq2amJUWpt5z0EQwwHemidjY5OqJGEKm5uA==} + html-element-attributes@3.5.0: + resolution: {integrity: sha512-rU2BFhp0kQla9sqPBI46C+zbP6PFOtD7z6XNAJ6as+cGecCDXLx0W3aIs6XdPLmBBG/Fy1meRi/n65Exofz4Qw==} + html-entities@2.6.0: resolution: {integrity: sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==} + html-es6cape@2.0.2: + resolution: {integrity: sha512-utzhH8rq2VABdW1LsPdv5tmxeMNOtP83If0jKCa79xPBgLWfcMvdf9K+EZoxJ5P7KioCxTs6WBnSDWLQHJ2lWA==} + html-tags@5.1.0: resolution: {integrity: sha512-n6l5uca7/y5joxZ3LUePhzmBFUJ+U2YWzhMa8XUTecSeSlQiZdF5XAd/Q3/WUl0VsXgUwWi8I7CNIwdI5WN1SQ==} engines: {node: '>=20.10'} + html-template-tag@5.0.0: + resolution: {integrity: sha512-FwF3Fi+v5Dr6ygxqqyJwJWdHteQtDusRXF5ae1syxTKbbVRC8UPtlfIua5KWbgXGneRAc7zNc+Z6x9efFl0W/w==} + ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -5102,10 +5114,19 @@ snapshots: hookified@2.2.0: {} + html-element-attributes@3.5.0: {} + html-entities@2.6.0: {} + html-es6cape@2.0.2: {} + html-tags@5.1.0: {} + html-template-tag@5.0.0: + dependencies: + html-element-attributes: 3.5.0 + html-es6cape: 2.0.2 + ignore@5.3.2: {} ignore@7.0.5: {} diff --git a/package.json b/package.json index 45806203..507f7550 100644 --- a/package.json +++ b/package.json @@ -16,6 +16,7 @@ "@sentry/browser": "^10.50.0", "a11y-dialog": "^8.1.5", "effect": "^4.0.0-beta.59", + "html-template-tag": "^5.0.0", "lit-html": "^3.3.2", "purify-ts": "2.1.2", "ts-pattern": "^5.9.0", From 50f2b67bc45309b57541b22634618de954f1960e Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 4/6] ref(styles) wip harmonisation des Boutons --- web/app/themes/haiku-atelier-2024/assets/css/main.css | 6 +++--- web/app/themes/haiku-atelier-2024/assets/css/main.min.css | 2 +- .../src/sass/base/elements/_formulaires.scss | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/web/app/themes/haiku-atelier-2024/assets/css/main.css b/web/app/themes/haiku-atelier-2024/assets/css/main.css index b229b3cc..9ac1598c 100755 --- a/web/app/themes/haiku-atelier-2024/assets/css/main.css +++ b/web/app/themes/haiku-atelier-2024/assets/css/main.css @@ -462,8 +462,8 @@ input[type="checkbox"], input[type="radio"] { transition: 0.2s background; } input[type="checkbox"]:checked, input[type="radio"]:checked { - color: var(--couleur-blanc); - background: var(--couleur-gris-fonce); + color: var(--couleur-noir); + background: var(--arriere-plan-points); } input[type="checkbox"]:checked::before, input[type="radio"]:checked::before { content: "x"; @@ -492,7 +492,7 @@ input[type="radio"] + label { } @media (hover: hover) { input[type="checkbox"]:hover, input[type="radio"]:hover { - background: var(--couleur-gris-fonce); + background: var(--arriere-plan-points); } } diff --git a/web/app/themes/haiku-atelier-2024/assets/css/main.min.css b/web/app/themes/haiku-atelier-2024/assets/css/main.min.css index b920d260..6c22705f 100755 --- a/web/app/themes/haiku-atelier-2024/assets/css/main.min.css +++ b/web/app/themes/haiku-atelier-2024/assets/css/main.min.css @@ -1 +1 @@ -@font-face{font-family:Lato;font-weight:100 900;font-style:normal;font-display:swap;src:url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2")tech(variations),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2-variations"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.ttf)format("truetype");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Lato;font-weight:100 900;font-style:italic;font-display:swap;src:url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2")tech(variations),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2-variations"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.ttf)format("truetype");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Myriad;font-weight:300 900;font-style:normal;font-display:swap;font-stretch:70% 110%;src:url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.ttf)format("truetype")}@font-face{font-family:Myriad;font-weight:300 900;font-style:italic;font-display:swap;font-stretch:70% 110%;src:url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.ttf)format("truetype")}:root{--couleur-blanc:oklch(100% 0 0);--couleur-blanc-fond:oklch(100% 0 0/.8);--couleur-gris:oklch(93.89% .0025 345.21);--couleur-gris-fond:oklch(93.89% .0025 345.21/.8);--couleur-gris-fond-extra:oklch(93.89% .0025 345.21/.6);--couleur-gris-fonce:oklch(59.99% 0 0);--couleur-gris-fonce-fond:oklch(59.99% 0 0/.8);--couleur-noir:oklch(24.35% 0 0);--arriere-plan-points:repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px .5px/2px 2px;--police-lato:"Lato", sans-serif;--hauteur-ligne-classique:1.5;--hauteur-ligne-moitie:1.2;--hauteur-ligne-compacte:1.1;--hauteur-ligne-rapprochee:1;--espacement-inter-lettres-rapproche-m:-1px;--espacement-inter-lettres-rapproche-s:-.5px;--espacement-inter-lettres-etendu-s:.5px;--espacement-inter-lettres-etendu-m:1px;--espacement-inter-lettres-etendu-l:1.5px;--espacement-inter-lettres-etendu-xl:2px;--en-tete-hauteur:61px;--menu-categories-produits-hauteur:calc(var(--espace-m) * 2 + 1rlh);--pied-de-page-hauteur:calc(.8rem * 1.5 * 3 + var(--espace-s) * 2);--contenu-page-hauteur-minimale-sans-categories:calc(100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur));--contenu-page-hauteur-minimale-avec-categories:calc(100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur) - var(--menu-categories-produits-hauteur));--espace-2xs:.1rem;--espace-xs:.25rem;--espace-s:.5rem;--espace-m:1rem;--espace-l:1.25rem;--espace-xl:2rem}html{scrollbar-gutter:stable;box-sizing:border-box}*,:before,:after{box-sizing:inherit;font:inherit;color:inherit;outline-offset:-2px;outline:2px dashed #0000;margin:0;padding:0}@view-transition{navigation:auto}body{overscroll-behavior:none;accent-color:var(--couleur-gris-fonce);background:var(--couleur-gris)}button,input,select,textarea{font:inherit}::selection{background:var(--couleur-gris-fonce)}[hidden]{display:none!important}:focus-visible{outline-color:var(--couleur-noir);transition:outline-color .2s}.visuellement-cache:not(:focus,:active,:focus-within){white-space:nowrap;clip-path:inset(50%);width:1px;height:1px;position:absolute;overflow:hidden}[disabled]{cursor:not-allowed}html{font:1rem/var(--hauteur-ligne-classique) Lato;font-optical-sizing:auto;font-variant-ligatures:common-ligatures no-discretionary-ligatures no-historical-ligatures contextual;font-kerning:normal;color:var(--couleur-noir);text-decoration-skip-ink:auto;text-size-adjust:none;text-rendering:geometricprecision;letter-spacing:var(--espacement-inter-lettres-etendu-s);-webkit-font-smoothing:antialiased}strong{font-weight:600}em{font-style:italic}code{font-family:monospace;font-size:.9rem}button{all:initial;cursor:pointer;box-sizing:border-box;font:inherit;text-align:center;letter-spacing:inherit;outline-offset:-2px;outline:2px dashed #0000;transition:background .2s,font-weight .2s,color .2s,outline-color .2s}button:focus-visible{z-index:5;outline-color:var(--couleur-noir)}button:active{background:var(--arriere-plan-points)}button:disabled{color:inherit;background:var(--arriere-plan-points);outline-color:#0000}button.bouton-case-pleine{width:100%;height:100%}@media (hover:hover){button.bouton-case-pleine:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}button.bouton-inverse{color:var(--couleur-blanc);background:var(--couleur-noir)}button.bouton-inverse:focus-visible{outline-color:var(--couleur-blanc)}button.bouton-inverse:active{color:var(--couleur-noir);background:var(--arriere-plan-points)}button.bouton-inverse:disabled{color:var(--couleur-blanc)}@media (hover:hover){button.bouton-inverse:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}button.bouton-retour-haut{z-index:500;right:var(--espace-xl);bottom:calc(var(--espace-l) + var(--pied-de-page-hauteur));padding:var(--espace-m);border:1px solid var(--couleur-noir);visibility:hidden;opacity:0;background:var(--couleur-gris-fond);box-shadow:initial;border-radius:100%;transition:background .2s,opacity .2s,visibility .2s;position:fixed;transform:rotate(180deg)}button.bouton-retour-haut img{background:0 0;width:1rem;height:1rem}button.bouton-retour-haut[data-actif]{visibility:visible;opacity:.5}@media (hover:hover){button.bouton-retour-haut[data-actif]:hover{opacity:1;background:var(--couleur-gris-fond)}button:hover{color:var(--couleur-blanc);background:var(--couleur-gris-fonce)}}dialog{z-index:999;padding:var(--espace-l);opacity:0;background:var(--couleur-blanc);transition-behavior:allow-discrete;flex-flow:column;place-self:center;transition:display .3s,opacity .3s,overlay .3s}dialog::backdrop{transition-behavior:allow-discrete;background-color:#0000;transition:background-color .3s,display .3s,overlay .3s}dialog:open{opacity:1;display:flex}dialog:open::backdrop{background-color:var(--couleur-gris-fond)}dialog *+*{margin-block-start:var(--espace-m)}dialog p{max-inline-size:50ch}dialog button{inline-size:fit-content;padding:var(--espace-s);align-self:end}@starting-style{dialog:open{opacity:0}}@starting-style{dialog:open::backdrop{background-color:#0000}}fieldset{all:initial;margin-top:var(--espace-l);font:inherit;flex-flow:column;display:flex}input,select,textarea{padding:var(--espace-xs);border:1px solid var(--couleur-noir);accent-color:var(--couleur-gris-fonce);background:var(--couleur-gris);transition:background .2s}input:focus-visible,input:focus-within,select:focus-visible,select:focus-within,textarea:focus-visible,textarea:focus-within{z-index:10;outline:2px dashed var(--couleur-noir)}input:active,select:active,textarea:active{background:var(--arriere-plan-points)}input:disabled,select:disabled,textarea:disabled{background:var(--arriere-plan-points);outline-color:#0000}input:is([type=email],[type=text],[type=tel])::placeholder,textarea::placeholder{text-transform:lowercase;letter-spacing:var(--espacement-inter-lettres-etendu-s)}input:is([type=email],[type=text],[type=tel])::selection,textarea::selection{color:var(--couleur-blanc);background:var(--couleur-noir)}input:is([type=email],[type=text],[type=tel]):user-valid,textarea:user-valid{color:var(--couleur-noir);background:var(--arriere-plan-points);font-weight:500}input:is([type=email],[type=text],[type=tel]):user-invalid,textarea:user-invalid{background:var(--couleur-gris)}input,label,select,textarea{cursor:pointer}input[type=checkbox],input[type=radio]{width:var(--espace-l);height:var(--espace-l);padding:initial;border:1px solid var(--couleur-noir);appearance:none;transition:background .2s}input[type=checkbox]:checked,input[type=radio]:checked{color:var(--couleur-blanc);background:var(--couleur-gris-fonce)}input[type=checkbox]:checked:before,input[type=radio]:checked:before{content:"x";position:relative;bottom:.1rem;left:.35rem}@media (hover:hover){input[type=checkbox]:checked:hover,input[type=radio]:checked:hover{color:var(--couleur-noir)}}input[type=checkbox]:not(:checked):user-valid,input[type=radio]:not(:checked):user-valid{background:initial}label:has(~input[type=checkbox],~input[type=radio]),input[type=checkbox]+label,input[type=radio]+label{padding-top:1px;font-size:.9rem}@media (hover:hover){input[type=checkbox]:hover,input[type=radio]:hover{background:var(--couleur-gris-fonce)}}input[type=radio]{appearance:initial;border-radius:100%}input[type=radio]:checked{place-content:center;place-items:center;display:inline-flex}input[type=radio]:checked:before{content:" ";inset:initial;width:calc(var(--espace-l) / 2);height:calc(var(--espace-l) / 2);background:var(--couleur-noir);border-radius:100%;display:inline-block}@media (hover:hover){textarea:hover{color:var(--couleur-noir)}}img,picture{max-width:100%;display:block}img{object-fit:cover;background:var(--couleur-gris-fonce)}a{--lien-contour-couleur-focus:var(--couleur-noir);text-decoration-skip-ink:auto;text-decoration-skip:edges;text-decoration:underline #0000;transition:background .2s,border-color .2s,color .2s,font-weight .2s,outline-color .2s,letter-spacing .2s,text-decoration-color .2s}a:focus-visible{outline-color:var(--lien-contour-couleur-focus)}a.lien-bouton{--lien-bouton-marges-internes-bloc:var(--espace-xs);--lien-bouton-marges-internes-ligne:var(--espace-m);--lien-bouton-arriere-plan-couleur-survol:var(--couleur-gris-fonce);padding:var(--lien-bouton-marges-internes-bloc) var(--lien-bouton-marges-internes-ligne);border:1px solid var(--couleur-noir)}a.lien-bouton:focus-visible{background:var(--lien-bouton-arriere-plan-couleur-survol)}a.lien-bouton:active{border-color:var(--lien-bouton-arriere-plan-couleur-survol)}@media (hover:hover){a.lien-bouton:hover{background:var(--lien-bouton-arriere-plan-couleur-survol)}}a.lien-lien{text-decoration:underline}a.lien-lien:active{text-decoration-color:var(--couleur-gris-fonce);background:var(--couleur-gris-fonce)}@media (hover:hover){a.lien-lien:hover{text-decoration-color:var(--couleur-gris-fonce);background:var(--couleur-gris-fonce)}a:not([class]):hover{text-decoration-color:var(--couleur-noir)}}ul{list-style:none}ul.avec-puce-cercle{--liste-puce-cercle-lien-marges-internes-ligne-debut:2ch;--liste-puce-cercle-puce-position-horizontale:1ch;--liste-puce-cercle-puce-taille:1.25ex}ul.avec-puce-cercle a{padding-left:var(--liste-puce-cercle-lien-marges-internes-ligne-debut);background:no-repeat var(--liste-puce-cercle-puce-position-horizontale) center/var(--liste-puce-cercle-puce-taille) url(/app/themes/haiku-atelier-2024/assets/img/icons/dot.svg)}video{block-size:100%;inline-size:100%;min-inline-size:100%;min-block-size:inherit;object-fit:cover;display:block}.bandeau{column-gap:var(--espace-m);border-top:1px solid var(--couleur-noir);width:100%;color:var(--couleur-noir);text-transform:uppercase;white-space:nowrap;background:var(--couleur-gris-fonce);font-style:italic;display:flex;overflow:hidden}.bandeau__conteneur{column-gap:var(--espace-m);flex-flow:row;animation:15s linear infinite both marquee;display:flex}.bandeau__conteneur ::selection{color:var(--couleur-gris-fonce);background:var(--couleur-noir)}.bandeau__conteneur p{padding:var(--espace-s) 0;display:inline-block}.bandeau__conteneur p strong{font-weight:600}@media (hover:hover){.bandeau:hover .bandeau__conteneur{animation-play-state:paused}}@keyframes marquee{0%{transform:translate(0%)}to{transform:translate(-100%)}}body:has(#menu-mobile:not([aria-hidden=true])){touch-action:none;overflow:hidden}#menu-mobile{--menu-mobile-hauteur:calc(100svh - var(--en-tete-hauteur));z-index:997;inset:var(--en-tete-hauteur) 0 0 0;overscroll-behavior:contain;width:100vw;height:var(--menu-mobile-hauteur);transition:display .4s;transition:display .4s allow-discrete;-webkit-overflow-scrolling:none;display:flex;position:fixed;overflow:hidden}#menu-mobile[aria-hidden=true]{animation:.4s both fade-out;display:none}#menu-mobile[aria-hidden=true] .menu-modale__fond{animation:.4s both fade-out}#menu-mobile .menu-modale__fond{z-index:998;inset:var(--en-tete-hauteur) 0 0 0;height:var(--menu-mobile-hauteur);opacity:0;background-color:var(--couleur-gris-fond);animation:.4s both fade-in;position:fixed}#menu-mobile .menu-modale__conteneur{z-index:999;width:100%;height:fit-content;padding:var(--espace-xl);border-bottom:1px solid var(--couleur-noir);opacity:0;background-color:var(--couleur-gris);flex-flow:column;animation:.4s .2s both fade-in;display:flex;position:relative}#menu-mobile .menu-modale__conteneur .menu-navigation{grid-template-columns:1fr}#menu-mobile .menu-modale__conteneur .menu-navigation ul{grid-column:initial;flex-flow:column;place-items:center}#menu-mobile .menu-modale__conteneur .menu-navigation ul>span{width:fit-content}#menu-mobile .menu-modale__conteneur .menu-navigation ul>span li a{padding-top:var(--espace-m);padding-bottom:var(--espace-m)}@media (width>1000px){#menu-mobile{display:none}}@keyframes fade-in{to{opacity:1}}@keyframes fade-out{to{opacity:0}}@keyframes slide-in{to{transform:translateY(0)}}#en-tete{--en-tete-marges-internes-ligne:var(--espace-xl);--en-tete-marges-internes-bloc:var(--espace-m);--en-tete-section-hauteur:var(--en-tete-hauteur);--en-tete-logo-longueur:160px;z-index:60;min-width:100vw;max-width:100vw;height:var(--en-tete-hauteur);padding:var(--en-tete-marges-internes-bloc) var(--en-tete-marges-internes-ligne);border-bottom:1px solid var(--couleur-noir);background:var(--couleur-gris-fond-extra);backdrop-filter:brightness(125%)blur(6px);flex-flow:row;justify-content:space-between;place-items:center;display:flex;position:fixed;top:0}#en-tete picture,#en-tete img{background:0 0}#en-tete .logo{width:var(--en-tete-logo-longueur)}#en-tete .logo img{object-fit:contain;width:100%;height:40px;image-rendering:crisp-edges;shape-rendering:geometricprecision;margin-left:-6px}#en-tete .menu-navigation{text-align:center;text-transform:lowercase;flex:1;grid-template-columns:1fr auto 1fr;font-size:1.1rem;display:grid}#en-tete .menu-navigation ul{gap:var(--espace-m);flex-flow:row;grid-column:2;justify-content:space-between;display:flex}#en-tete .menu-navigation__entree{--nav-entree-marges-internes-bloc:var(--espace-xs);--nav-entree-marges-internes-ligne:3rem;--liste-puce-cercle-lien-marges-internes-ligne-debut:calc(var(--espace-m) + 1.5ch);--liste-puce-cercle-puce-position-horizontale:3.5ch}#en-tete .menu-navigation__entree:has(a[aria-current=page]),#en-tete .menu-navigation__entree--courante{background:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche-gris.svg) bottom/auto 90% no-repeat}#en-tete .menu-navigation__entree a{padding:var(--nav-entree-marges-internes-bloc) var(--nav-entree-marges-internes-ligne);text-align:center;display:inline-block}@media (hover:hover){#en-tete .menu-navigation__entree:hover{background:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche-gris.svg) bottom/auto 90% no-repeat}}@media (width<=1000px){#en-tete .menu-navigation#menu-navigation-en-tete{display:none}}#en-tete .compte-panier{text-align:center;flex-flow:row;place-items:center;gap:1rem;display:flex}#en-tete .compte-panier[disabled]{background:var(--arriere-plan-points)}#en-tete .compte-panier[disabled] a:hover,#en-tete .compte-panier[disabled] a:active,#en-tete .compte-panier[disabled] a:focus-within{border:1px solid var(--couleur-noir)}#en-tete .compte-panier a{padding-block:var(--espace-2xs);padding-inline:var(--espace-s);text-transform:lowercase;background:0 0}#en-tete .compte-panier a[data-contient-articles=true]{background:var(--couleur-gris-fond)}#en-tete .compte-panier a:hover,#en-tete .compte-panier a:focus-within{color:var(--couleur-blanc);background:var(--couleur-gris-fonce-fond)}#en-tete .compte-panier a:active{color:var(--couleur-noir);background:var(--arriere-plan-points)}#en-tete .conteneur{column-gap:var(--espace-m);display:flex}#en-tete .bouton-menu-mobile{--hauteur-bouton-menu:22px;align-content:center;display:none}#en-tete .bouton-menu-mobile img{height:var(--hauteur-bouton-menu);object-fit:contain;image-rendering:crisp-edges;shape-rendering:geometricprecision}@media (hover:hover){#en-tete .bouton-menu-mobile:hover{background:initial!important}}@media (width<=1000px){#en-tete .bouton-menu-mobile{display:block}}@media (width<=600px){#en-tete{--en-tete-marges-internes-ligne:var(--espace-l)}}#menu-categories-produits{--menu-entree-longueur-minimale:13ch;--menu-section-marges-bloc-debut:var(--en-tete-hauteur);--menu-entree-marges-internes-ligne:var(--espace-m);margin-top:var(--menu-section-marges-bloc-debut);position:relative}#menu-categories-produits[data-entrees-presentes-debut] svg:first-of-type,#menu-categories-produits[data-entrees-presentes-fin] svg:last-of-type{opacity:1}#menu-categories-produits svg{pointer-events:none;opacity:0;mix-blend-mode:exclusion;shape-rendering:geometricprecision;block-size:.8rem;inline-size:.8rem;transition:opacity .2s;position:absolute;bottom:calc(17.59px - .35rem)}#menu-categories-produits svg:first-of-type{left:var(--espace-xs)}#menu-categories-produits svg:last-of-type{right:var(--espace-xs)}@media (width>600px){#menu-categories-produits svg{visibility:hidden}}#menu-categories-produits ul{grid-template-columns:repeat(auto-fit, minmax(var(--menu-entree-longueur-minimale), 1fr));place-items:center;gap:1px;display:grid}#menu-categories-produits ul li{inline-size:100%;color:var(--couleur-gris);text-align:center;text-transform:uppercase;letter-spacing:var(--espacement-inter-lettres-etendu-m);background:var(--couleur-noir);font-style:italic;font-weight:500}#menu-categories-produits ul li:hover{background:var(--couleur-gris)}#menu-categories-produits ul li a{inline-size:inherit;padding:var(--menu-entree-marges-internes-ligne) 0;text-decoration:none;display:inline-block}#menu-categories-produits ul li a:focus-visible{outline-color:var(--couleur-blanc)}@media (hover:hover){#menu-categories-produits ul li a:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}#menu-categories-produits ul li.categorie-courante{background:var(--couleur-gris)}#menu-categories-produits ul li.categorie-courante a{color:var(--couleur-noir);background:var(--arriere-plan-points);font-weight:600}#menu-categories-produits ul li.categorie-courante a:focus-visible{outline-color:var(--couleur-noir)}@media (hover:hover){#menu-categories-produits ul li.categorie-courante a:hover{background:var(--arriere-plan-points)}}@media (width<=1000px){#menu-categories-produits ul{--menu-entree-marges-internes-ligne:var(--espace-s);flex-flow:wrap;font-size:.8rem;display:flex}#menu-categories-produits ul li{flex-grow:1;inline-size:min(140px,100%)}#menu-categories-produits ul li a{border:initial;inline-size:100%}}@media (width<=600px){#menu-categories-produits ul{scrollbar-width:none;flex-flow:row;overflow-x:scroll}#menu-categories-produits ul li{inline-size:initial;min-inline-size:140px}}.photos-produit{--colonne-gauche-position-haut:var(--menu-categories-produits-hauteur);--colonne-gauche-photo-hauteur:calc(100svh - var(--menu-categories-produits-hauteur));--colonne-droite-photo-hauteur-minimale:calc(100svh + var(--en-tete-hauteur) + var(--menu-categories-produits-hauteur));--colonne-photo-longueur-minimale:30rem;--section-marges-externes-bloc-fin:1rem;flex-flow:row;max-width:100%;display:flex;position:relative}.photos-produit .colonne{width:min(var(--colonne-photo-longueur-minimale), 100%);flex-flow:column;flex-grow:1;display:flex;position:relative}.photos-produit .colonne.colonne-gauche{top:var(--colonne-gauche-position-haut);height:var(--colonne-gauche-photo-hauteur);position:sticky}.photos-produit .colonne.colonne-gauche figure,.photos-produit .colonne.colonne-gauche picture,.photos-produit .colonne.colonne-gauche img{height:100%}.photos-produit .colonne.colonne-droite img{width:100%;max-height:var(--colonne-droite-photo-hauteur-minimale)}.photos-produit .colonne.colonne-droite figure picture img:only-child{min-height:var(--colonne-droite-photo-hauteur-minimale);max-height:var(--colonne-droite-photo-hauteur-minimale)}@media (width<=60rem){.photos-produit{--colonne-droite-photo-hauteur-minimale:var(--photo-hauteur-maximum);--photo-longueur-maximum:calc(100% - var(--espace-xl));--photo-hauteur-maximum:calc(100svh - var(--en-tete-hauteur) - 87px);scroll-behavior:smooth;scrollbar-width:none;scroll-snap-type:x mandatory;width:fit-content;max-width:initial;flex-flow:row;overflow-x:scroll}.photos-produit::-webkit-scrollbar{display:none}.photos-produit .colonne{scroll-snap-type:x mandatory;width:100%;min-width:100%}.photos-produit .colonne figure{scroll-snap-align:none center}.photos-produit .colonne img{max-height:var(--photo-hauteur-maximum)}.photos-produit .colonne.colonne-gauche{position:initial;min-width:var(--photo-longueur-maximum);height:initial}.photos-produit .colonne.colonne-droite{flex-flow:row}.photos-produit .colonne.colonne-droite figure{min-width:var(--photo-longueur-maximum);flex-grow:1}.photos-produit .colonne.colonne-droite:has(figure:only-child){min-width:var(--photo-longueur-maximum)}}.grille-produits{--grille-produits-hauteur-minimale:var(--contenu-page-hauteur-minimale-avec-categories);--aucun-produit-hauteur:var(--contenu-page-hauteur-minimale-avec-categories);--carte-produit-longueur-minimale:448px;--carte-produit-longueur-maximale:1000px;grid-auto-rows:1fr;grid-template-columns:repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr));min-height:var(--grille-produits-hauteur-minimale);gap:1px;display:grid}.grille-produits article{max-width:var(--carte-produit-longueur-maximale);box-shadow:0 0 0 1px var(--couleur-noir)}.grille-produits article figure{row-gap:var(--espace-xl);flex-flow:column;display:flex}.grille-produits article figure a{position:relative}@media (hover:hover){.grille-produits article figure a:hover .produit__illustration__survol{visibility:visible;opacity:1;transition:opacity .3s,visibility .3s}}.grille-produits article figure img{position:inherit;aspect-ratio:9/16;object-fit:cover;background:0 0;width:100%;max-height:70vh}.grille-produits article figure .produit__illustration__principale{display:block}.grille-produits article figure .produit__illustration__principale:before{content:"";z-index:-1;opacity:0;filter:opacity(20%);background-image:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-gris.svg);background-position:50%;background-repeat:no-repeat;background-size:50%;width:100%;height:100%;animation:1.5s linear .5s infinite alternate both test;position:absolute;top:0;left:0}.grille-produits article figure .produit__illustration__principale img{opacity:0;transition:opacity 1s}.grille-produits article figure .produit__illustration__survol{visibility:hidden;opacity:0;width:100%;height:100%;transition:opacity .15s,visibility .15s;display:block;position:absolute;top:0;left:0}.grille-produits article figure .produit__illustration__survol img{background:var(--couleur-gris-fond)}.grille-produits article figure figcaption{margin-bottom:var(--espace-xl);padding:var(--espace-m);flex-flow:row;justify-content:space-between;display:flex}.grille-produits article figure figcaption h3{letter-spacing:var(--espacement-inter-lettres-etendu-m);font-style:italic}.grille-produits article figure figcaption p{letter-spacing:var(--espacement-inter-lettres-rapproche-s);font-weight:500}.grille-produits__aucun-produit{min-height:var(--aucun-produit-hauteur);text-align:center;grid-column:span 3;align-content:center}.grille-produits__aucun-produit p+p{margin-top:var(--espace-l);font-size:1.25rem}@media (width<=700px){.grille-produits{grid-template-columns:100%}.grille-produits article figure img{max-height:50svh}}@keyframes test{to{opacity:1}}.resume-produit{--resume-position-basse:0%;--section-marges-internes:var(--espace-l);--espace-inter-colonne:var(--espace-xl);--resume-police-graisse:500;--resume-police-style:italic;--resume-police-taille:var(--espace-l);--resume-police-nom-taille:1.33rem;--resume-police-selecteur-graisse:400;--resume-police-selecteur-taille:var(--espace-m);bottom:var(--resume-position-basse);position:sticky}.resume-produit .selecteur-produit{column-gap:var(--espace-inter-colonne);border-block:1px solid var(--couleur-noir);font-size:var(--resume-police-taille);font-weight:var(--resume-police-graisse);font-style:var(--resume-police-style);line-height:var(--hauteur-ligne-compacte);background:var(--couleur-blanc-fond);grid-template-columns:repeat(3,1fr);grid-auto-flow:column;place-items:center;display:grid;position:relative}.resume-produit .selecteur-produit>*{width:100%;height:100%;padding:var(--section-marges-internes);flex-flow:row;place-content:center;place-items:center;display:flex}.resume-produit .selecteur-produit>:nth-child(2){border-inline-start:1px solid var(--couleur-noir);border-inline-end:1px solid var(--couleur-noir)}.resume-produit .selecteur-produit__nom{font-size:var(--resume-police-nom-taille)}.resume-produit .selecteur-produit__attribut-variation{gap:var(--espace-m) var(--espace-l);font-size:var(--resume-police-selecteur-taille);font-weight:var(--resume-police-selecteur-graisse);text-transform:lowercase;flex-flow:wrap;display:flex}.resume-produit .selecteur-produit__attribut-variation label{margin-right:var(--espace-s)}.resume-produit .selecteur-produit__attribut-variation select{padding:var(--espace-xs) var(--espace-l);border:1px solid var(--couleur-noir);text-align:center;letter-spacing:initial;appearance:none;background:var(--couleur-gris-fond);position:relative}@supports selector(:user-valid){.resume-produit .selecteur-produit__attribut-variation select:user-valid{background:var(--couleur-gris-fond)}}.resume-produit .selecteur-produit__attribut-variation option{background:var(--couleur-gris-fond)}.resume-produit .selecteur-produit__attribut-variation__selecteurs{gap:var(--espace-m);flex-flow:wrap;place-content:center;place-items:center;display:flex;position:relative}.resume-produit .selecteur-produit__prix{font-style:initial}@media (width<=800px){.resume-produit{--section-marges-internes:var(--espace-m);--espace-inter-colonne:var(--espace-m)}}@media (width<=700px){.resume-produit{--resume-police-taille:var(--espace-m);--resume-police-nom-taille:var(--espace-m);--section-marges-internes:var(--espace-m);--espace-inter-colonne:var(--espace-s)}}@media (width<=500px){.resume-produit .selecteur-produit__selection-variation-attribut{row-gap:var(--espace-inter-colonne);flex-flow:column}.resume-produit .selecteur-produit__selection-variation-attribut h3{flex-basis:100%}}.details-produit{--bouton-marges-internes-bloc:var(--espace-l);--espace-inter-lignes:var(--espace-l);--espace-inter-texte:var(--espace-m);--section-marges-internes:var(--espace-l);--textuel-marges-internes-ligne:calc(var(--espace-l) * 2);background-color:var(--couleur-blanc)}.details-produit__textes{grid-template-columns:1fr;grid-auto-flow:row;display:grid}.details-produit__textes .section-textuelle:not(:last-of-type){border-block-end:1px solid var(--couleur-noir)}.details-produit__textes .section-textuelle:has(button[aria-expanded=false]) .section-textuelle__contenu{display:none}.details-produit__textes .section-textuelle h3{line-height:var(--hauteur-ligne-rapprochee)}.details-produit__textes .section-textuelle h3 button{width:100%;min-block-size:1lh;padding:var(--section-marges-internes);text-align:start;display:inline-block}.details-produit__textes .section-textuelle h3 button:active{background:var(--arriere-plan-points)}@media (hover:hover){.details-produit__textes .section-textuelle h3 button:hover{color:inherit;background:inherit}}.details-produit__textes .section-textuelle .section-textuelle__contenu{padding-block-end:var(--section-marges-internes);padding-inline:var(--textuel-marges-internes-ligne)}.details-produit__textes .section-textuelle .section-textuelle__contenu ul{list-style:inside}.details-produit__textes .section-textuelle .section-textuelle__contenu a{text-decoration-color:var(--couleur-noir)}.details-produit__textes .section-textuelle .section-textuelle__contenu>*+*{margin-top:var(--espace-inter-texte)}.details-produit__actions{--section-marges-internes:var(--espace-l);border-block:1px solid var(--couleur-noir);background:var(--arriere-plan-points);transition:background .2s;overflow:hidden}.details-produit__actions:has(button[disabled]){background:var(--couleur-gris-fond)}.details-produit__actions button{padding:var(--section-marges-internes);text-transform:uppercase;font-style:italic}@media (hover:hover){.details-produit__actions button:not([disabled]):hover{color:var(--couleur-blanc);background:var(--couleur-gris-fonce-fond);font-weight:600}}.produits-similaires{--carte-produit-longueur-minimale:448px;--carte-produit-longueur-maximale:1000px;--en-tete-flottante-hauteur:calc(1rem + var(--espace-l) * 2 + 1px);grid-template-rows:1fr auto;grid-template-columns:repeat(3,1fr);grid-template-areas:"en-tete en-tete en-tete""produits produits produits";place-items:center;display:grid;position:relative}.produits-similaires header{z-index:10;top:var(--en-tete-flottante-hauteur);width:100%;padding:var(--espace-l) 0;color:var(--couleur-blanc);text-align:center;background:var(--couleur-noir);grid-area:en-tete;position:sticky}.produits-similaires header h2{font-style:italic;line-height:var(--hauteur-ligne-rapprochee);text-transform:uppercase;letter-spacing:var(--espacement-inter-lettres-etendu-m)}.produits-similaires .grille-produits-similaires{grid-area:produits;grid-auto-rows:1fr;grid-template-columns:repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr));gap:1px;width:100%;display:grid}.produits-similaires .grille-produits-similaires article{max-width:var(--carte-produit-longueur-maximale);box-shadow:0 0 0 1px var(--couleur-noir)}.produits-similaires .grille-produits-similaires article figure{row-gap:var(--espace-xl);flex-flow:column;display:flex}.produits-similaires .grille-produits-similaires article figure a{position:relative}@media (hover:hover){.produits-similaires .grille-produits-similaires article figure a:hover .produit__illustration__survol{visibility:visible;opacity:1;transition:opacity .3s,visibility .3s}}.produits-similaires .grille-produits-similaires article figure .produit__illustration__principale{display:block}.produits-similaires .grille-produits-similaires article figure .produit__illustration__survol{visibility:hidden;opacity:0;width:100%;height:100%;transition:opacity .15s,visibility .15s;display:block;position:absolute;top:0;left:0}.produits-similaires .grille-produits-similaires article figure img{aspect-ratio:9/16;object-fit:cover;width:100%;max-height:70svh}.produits-similaires .grille-produits-similaires article figure figcaption{margin-bottom:var(--espace-xl);padding:0 var(--espace-m);flex-flow:row;justify-content:space-between;display:flex}.produits-similaires .grille-produits-similaires article figure figcaption h3{letter-spacing:var(--espacement-inter-lettres-etendu-m);font-style:italic}.produits-similaires .grille-produits-similaires article figure figcaption p{letter-spacing:var(--espacement-inter-lettres-rapproche-s);font-weight:500}@media (width<=700px){.produits-similaires .grille-produits-similaires{grid-template-columns:100%}.produits-similaires .grille-produits-similaires article figure img{max-height:50svh}}#pied-de-page{max-width:100vw;height:var(--pied-de-page-hauteur);padding:var(--espace-s) var(--espace-m);border-top:1px solid var(--couleur-noir);grid-template-columns:1fr 1fr;place-items:center;font-size:.8rem;display:grid}#pied-de-page .zone-menu-navigation-secondaire{text-transform:lowercase;justify-self:start;width:100%;height:100%}#pied-de-page .zone-liens-reseaux-sociaux{text-align:right;justify-items:end;width:100%;height:100%} \ No newline at end of file +@font-face{font-family:Lato;font-weight:100 900;font-style:normal;font-display:swap;src:url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2")tech(variations),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2-variations"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-webfont.ttf)format("truetype");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Lato;font-weight:100 900;font-style:italic;font-display:swap;src:url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2")tech(variations),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2-variations"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/lato/lato-variable-italic-webfont.ttf)format("truetype");unicode-range:U+??,U+131,U+152-153,U+2BB-2BC,U+2C6,U+2DA,U+2DC,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}@font-face{font-family:Myriad;font-weight:300 900;font-style:normal;font-display:swap;font-stretch:70% 110%;src:url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable.ttf)format("truetype")}@font-face{font-family:Myriad;font-weight:300 900;font-style:italic;font-display:swap;font-stretch:70% 110%;src:url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.woff2)format("woff2"),url(/app/themes/haiku-atelier-2024/assets/fonts/myriad/myriad-variable-italic.ttf)format("truetype")}:root{--couleur-blanc:oklch(100% 0 0);--couleur-blanc-fond:oklch(100% 0 0/.8);--couleur-gris:oklch(93.89% .0025 345.21);--couleur-gris-fond:oklch(93.89% .0025 345.21/.8);--couleur-gris-fond-extra:oklch(93.89% .0025 345.21/.6);--couleur-gris-fonce:oklch(59.99% 0 0);--couleur-gris-fonce-fond:oklch(59.99% 0 0/.8);--couleur-noir:oklch(24.35% 0 0);--arriere-plan-points:repeating-conic-gradient(var(--couleur-noir) 0% 25%, transparent 0% 100%) 1px .5px/2px 2px;--police-lato:"Lato", sans-serif;--hauteur-ligne-classique:1.5;--hauteur-ligne-moitie:1.2;--hauteur-ligne-compacte:1.1;--hauteur-ligne-rapprochee:1;--espacement-inter-lettres-rapproche-m:-1px;--espacement-inter-lettres-rapproche-s:-.5px;--espacement-inter-lettres-etendu-s:.5px;--espacement-inter-lettres-etendu-m:1px;--espacement-inter-lettres-etendu-l:1.5px;--espacement-inter-lettres-etendu-xl:2px;--en-tete-hauteur:61px;--menu-categories-produits-hauteur:calc(var(--espace-m) * 2 + 1rlh);--pied-de-page-hauteur:calc(.8rem * 1.5 * 3 + var(--espace-s) * 2);--contenu-page-hauteur-minimale-sans-categories:calc(100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur));--contenu-page-hauteur-minimale-avec-categories:calc(100svh - var(--en-tete-hauteur) - var(--pied-de-page-hauteur) - var(--menu-categories-produits-hauteur));--espace-2xs:.1rem;--espace-xs:.25rem;--espace-s:.5rem;--espace-m:1rem;--espace-l:1.25rem;--espace-xl:2rem}html{scrollbar-gutter:stable;box-sizing:border-box}*,:before,:after{box-sizing:inherit;font:inherit;color:inherit;outline-offset:-2px;outline:2px dashed #0000;margin:0;padding:0}@view-transition{navigation:auto}body{overscroll-behavior:none;accent-color:var(--couleur-gris-fonce);background:var(--couleur-gris)}button,input,select,textarea{font:inherit}::selection{background:var(--couleur-gris-fonce)}[hidden]{display:none!important}:focus-visible{outline-color:var(--couleur-noir);transition:outline-color .2s}.visuellement-cache:not(:focus,:active,:focus-within){white-space:nowrap;clip-path:inset(50%);width:1px;height:1px;position:absolute;overflow:hidden}[disabled]{cursor:not-allowed}html{font:1rem/var(--hauteur-ligne-classique) Lato;font-optical-sizing:auto;font-variant-ligatures:common-ligatures no-discretionary-ligatures no-historical-ligatures contextual;font-kerning:normal;color:var(--couleur-noir);text-decoration-skip-ink:auto;text-size-adjust:none;text-rendering:geometricprecision;letter-spacing:var(--espacement-inter-lettres-etendu-s);-webkit-font-smoothing:antialiased}strong{font-weight:600}em{font-style:italic}code{font-family:monospace;font-size:.9rem}button{all:initial;cursor:pointer;box-sizing:border-box;font:inherit;text-align:center;letter-spacing:inherit;outline-offset:-2px;outline:2px dashed #0000;transition:background .2s,font-weight .2s,color .2s,outline-color .2s}button:focus-visible{z-index:5;outline-color:var(--couleur-noir)}button:active{background:var(--arriere-plan-points)}button:disabled{color:inherit;background:var(--arriere-plan-points);outline-color:#0000}button.bouton-case-pleine{width:100%;height:100%}@media (hover:hover){button.bouton-case-pleine:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}button.bouton-inverse{color:var(--couleur-blanc);background:var(--couleur-noir)}button.bouton-inverse:focus-visible{outline-color:var(--couleur-blanc)}button.bouton-inverse:active{color:var(--couleur-noir);background:var(--arriere-plan-points)}button.bouton-inverse:disabled{color:var(--couleur-blanc)}@media (hover:hover){button.bouton-inverse:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}button.bouton-retour-haut{z-index:500;right:var(--espace-xl);bottom:calc(var(--espace-l) + var(--pied-de-page-hauteur));padding:var(--espace-m);border:1px solid var(--couleur-noir);visibility:hidden;opacity:0;background:var(--couleur-gris-fond);box-shadow:initial;border-radius:100%;transition:background .2s,opacity .2s,visibility .2s;position:fixed;transform:rotate(180deg)}button.bouton-retour-haut img{background:0 0;width:1rem;height:1rem}button.bouton-retour-haut[data-actif]{visibility:visible;opacity:.5}@media (hover:hover){button.bouton-retour-haut[data-actif]:hover{opacity:1;background:var(--couleur-gris-fond)}button:hover{color:var(--couleur-blanc);background:var(--couleur-gris-fonce)}}dialog{z-index:999;padding:var(--espace-l);opacity:0;background:var(--couleur-blanc);transition-behavior:allow-discrete;flex-flow:column;place-self:center;transition:display .3s,opacity .3s,overlay .3s}dialog::backdrop{transition-behavior:allow-discrete;background-color:#0000;transition:background-color .3s,display .3s,overlay .3s}dialog:open{opacity:1;display:flex}dialog:open::backdrop{background-color:var(--couleur-gris-fond)}dialog *+*{margin-block-start:var(--espace-m)}dialog p{max-inline-size:50ch}dialog button{inline-size:fit-content;padding:var(--espace-s);align-self:end}@starting-style{dialog:open{opacity:0}}@starting-style{dialog:open::backdrop{background-color:#0000}}fieldset{all:initial;margin-top:var(--espace-l);font:inherit;flex-flow:column;display:flex}input,select,textarea{padding:var(--espace-xs);border:1px solid var(--couleur-noir);accent-color:var(--couleur-gris-fonce);background:var(--couleur-gris);transition:background .2s}input:focus-visible,input:focus-within,select:focus-visible,select:focus-within,textarea:focus-visible,textarea:focus-within{z-index:10;outline:2px dashed var(--couleur-noir)}input:active,select:active,textarea:active{background:var(--arriere-plan-points)}input:disabled,select:disabled,textarea:disabled{background:var(--arriere-plan-points);outline-color:#0000}input:is([type=email],[type=text],[type=tel])::placeholder,textarea::placeholder{text-transform:lowercase;letter-spacing:var(--espacement-inter-lettres-etendu-s)}input:is([type=email],[type=text],[type=tel])::selection,textarea::selection{color:var(--couleur-blanc);background:var(--couleur-noir)}input:is([type=email],[type=text],[type=tel]):user-valid,textarea:user-valid{color:var(--couleur-noir);background:var(--arriere-plan-points);font-weight:500}input:is([type=email],[type=text],[type=tel]):user-invalid,textarea:user-invalid{background:var(--couleur-gris)}input,label,select,textarea{cursor:pointer}input[type=checkbox],input[type=radio]{width:var(--espace-l);height:var(--espace-l);padding:initial;border:1px solid var(--couleur-noir);appearance:none;transition:background .2s}input[type=checkbox]:checked,input[type=radio]:checked{color:var(--couleur-noir);background:var(--arriere-plan-points)}input[type=checkbox]:checked:before,input[type=radio]:checked:before{content:"x";position:relative;bottom:.1rem;left:.35rem}@media (hover:hover){input[type=checkbox]:checked:hover,input[type=radio]:checked:hover{color:var(--couleur-noir)}}input[type=checkbox]:not(:checked):user-valid,input[type=radio]:not(:checked):user-valid{background:initial}label:has(~input[type=checkbox],~input[type=radio]),input[type=checkbox]+label,input[type=radio]+label{padding-top:1px;font-size:.9rem}@media (hover:hover){input[type=checkbox]:hover,input[type=radio]:hover{background:var(--arriere-plan-points)}}input[type=radio]{appearance:initial;border-radius:100%}input[type=radio]:checked{place-content:center;place-items:center;display:inline-flex}input[type=radio]:checked:before{content:" ";inset:initial;width:calc(var(--espace-l) / 2);height:calc(var(--espace-l) / 2);background:var(--couleur-noir);border-radius:100%;display:inline-block}@media (hover:hover){textarea:hover{color:var(--couleur-noir)}}img,picture{max-width:100%;display:block}img{object-fit:cover;background:var(--couleur-gris-fonce)}a{--lien-contour-couleur-focus:var(--couleur-noir);text-decoration-skip-ink:auto;text-decoration-skip:edges;text-decoration:underline #0000;transition:background .2s,border-color .2s,color .2s,font-weight .2s,outline-color .2s,letter-spacing .2s,text-decoration-color .2s}a:focus-visible{outline-color:var(--lien-contour-couleur-focus)}a.lien-bouton{--lien-bouton-marges-internes-bloc:var(--espace-xs);--lien-bouton-marges-internes-ligne:var(--espace-m);--lien-bouton-arriere-plan-couleur-survol:var(--couleur-gris-fonce);padding:var(--lien-bouton-marges-internes-bloc) var(--lien-bouton-marges-internes-ligne);border:1px solid var(--couleur-noir)}a.lien-bouton:focus-visible{background:var(--lien-bouton-arriere-plan-couleur-survol)}a.lien-bouton:active{border-color:var(--lien-bouton-arriere-plan-couleur-survol)}@media (hover:hover){a.lien-bouton:hover{background:var(--lien-bouton-arriere-plan-couleur-survol)}}a.lien-lien{text-decoration:underline}a.lien-lien:active{text-decoration-color:var(--couleur-gris-fonce);background:var(--couleur-gris-fonce)}@media (hover:hover){a.lien-lien:hover{text-decoration-color:var(--couleur-gris-fonce);background:var(--couleur-gris-fonce)}a:not([class]):hover{text-decoration-color:var(--couleur-noir)}}ul{list-style:none}ul.avec-puce-cercle{--liste-puce-cercle-lien-marges-internes-ligne-debut:2ch;--liste-puce-cercle-puce-position-horizontale:1ch;--liste-puce-cercle-puce-taille:1.25ex}ul.avec-puce-cercle a{padding-left:var(--liste-puce-cercle-lien-marges-internes-ligne-debut);background:no-repeat var(--liste-puce-cercle-puce-position-horizontale) center/var(--liste-puce-cercle-puce-taille) url(/app/themes/haiku-atelier-2024/assets/img/icons/dot.svg)}video{block-size:100%;inline-size:100%;min-inline-size:100%;min-block-size:inherit;object-fit:cover;display:block}.bandeau{column-gap:var(--espace-m);border-top:1px solid var(--couleur-noir);width:100%;color:var(--couleur-noir);text-transform:uppercase;white-space:nowrap;background:var(--couleur-gris-fonce);font-style:italic;display:flex;overflow:hidden}.bandeau__conteneur{column-gap:var(--espace-m);flex-flow:row;animation:15s linear infinite both marquee;display:flex}.bandeau__conteneur ::selection{color:var(--couleur-gris-fonce);background:var(--couleur-noir)}.bandeau__conteneur p{padding:var(--espace-s) 0;display:inline-block}.bandeau__conteneur p strong{font-weight:600}@media (hover:hover){.bandeau:hover .bandeau__conteneur{animation-play-state:paused}}@keyframes marquee{0%{transform:translate(0%)}to{transform:translate(-100%)}}body:has(#menu-mobile:not([aria-hidden=true])){touch-action:none;overflow:hidden}#menu-mobile{--menu-mobile-hauteur:calc(100svh - var(--en-tete-hauteur));z-index:997;inset:var(--en-tete-hauteur) 0 0 0;overscroll-behavior:contain;width:100vw;height:var(--menu-mobile-hauteur);transition:display .4s;transition:display .4s allow-discrete;-webkit-overflow-scrolling:none;display:flex;position:fixed;overflow:hidden}#menu-mobile[aria-hidden=true]{animation:.4s both fade-out;display:none}#menu-mobile[aria-hidden=true] .menu-modale__fond{animation:.4s both fade-out}#menu-mobile .menu-modale__fond{z-index:998;inset:var(--en-tete-hauteur) 0 0 0;height:var(--menu-mobile-hauteur);opacity:0;background-color:var(--couleur-gris-fond);animation:.4s both fade-in;position:fixed}#menu-mobile .menu-modale__conteneur{z-index:999;width:100%;height:fit-content;padding:var(--espace-xl);border-bottom:1px solid var(--couleur-noir);opacity:0;background-color:var(--couleur-gris);flex-flow:column;animation:.4s .2s both fade-in;display:flex;position:relative}#menu-mobile .menu-modale__conteneur .menu-navigation{grid-template-columns:1fr}#menu-mobile .menu-modale__conteneur .menu-navigation ul{grid-column:initial;flex-flow:column;place-items:center}#menu-mobile .menu-modale__conteneur .menu-navigation ul>span{width:fit-content}#menu-mobile .menu-modale__conteneur .menu-navigation ul>span li a{padding-top:var(--espace-m);padding-bottom:var(--espace-m)}@media (width>1000px){#menu-mobile{display:none}}@keyframes fade-in{to{opacity:1}}@keyframes fade-out{to{opacity:0}}@keyframes slide-in{to{transform:translateY(0)}}#en-tete{--en-tete-marges-internes-ligne:var(--espace-xl);--en-tete-marges-internes-bloc:var(--espace-m);--en-tete-section-hauteur:var(--en-tete-hauteur);--en-tete-logo-longueur:160px;z-index:60;min-width:100vw;max-width:100vw;height:var(--en-tete-hauteur);padding:var(--en-tete-marges-internes-bloc) var(--en-tete-marges-internes-ligne);border-bottom:1px solid var(--couleur-noir);background:var(--couleur-gris-fond-extra);backdrop-filter:brightness(125%)blur(6px);flex-flow:row;justify-content:space-between;place-items:center;display:flex;position:fixed;top:0}#en-tete picture,#en-tete img{background:0 0}#en-tete .logo{width:var(--en-tete-logo-longueur)}#en-tete .logo img{object-fit:contain;width:100%;height:40px;image-rendering:crisp-edges;shape-rendering:geometricprecision;margin-left:-6px}#en-tete .menu-navigation{text-align:center;text-transform:lowercase;flex:1;grid-template-columns:1fr auto 1fr;font-size:1.1rem;display:grid}#en-tete .menu-navigation ul{gap:var(--espace-m);flex-flow:row;grid-column:2;justify-content:space-between;display:flex}#en-tete .menu-navigation__entree{--nav-entree-marges-internes-bloc:var(--espace-xs);--nav-entree-marges-internes-ligne:3rem;--liste-puce-cercle-lien-marges-internes-ligne-debut:calc(var(--espace-m) + 1.5ch);--liste-puce-cercle-puce-position-horizontale:3.5ch}#en-tete .menu-navigation__entree:has(a[aria-current=page]),#en-tete .menu-navigation__entree--courante{background:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche-gris.svg) bottom/auto 90% no-repeat}#en-tete .menu-navigation__entree a{padding:var(--nav-entree-marges-internes-bloc) var(--nav-entree-marges-internes-ligne);text-align:center;display:inline-block}@media (hover:hover){#en-tete .menu-navigation__entree:hover{background:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-penche-gris.svg) bottom/auto 90% no-repeat}}@media (width<=1000px){#en-tete .menu-navigation#menu-navigation-en-tete{display:none}}#en-tete .compte-panier{text-align:center;flex-flow:row;place-items:center;gap:1rem;display:flex}#en-tete .compte-panier[disabled]{background:var(--arriere-plan-points)}#en-tete .compte-panier[disabled] a:hover,#en-tete .compte-panier[disabled] a:active,#en-tete .compte-panier[disabled] a:focus-within{border:1px solid var(--couleur-noir)}#en-tete .compte-panier a{padding-block:var(--espace-2xs);padding-inline:var(--espace-s);text-transform:lowercase;background:0 0}#en-tete .compte-panier a[data-contient-articles=true]{background:var(--couleur-gris-fond)}#en-tete .compte-panier a:hover,#en-tete .compte-panier a:focus-within{color:var(--couleur-blanc);background:var(--couleur-gris-fonce-fond)}#en-tete .compte-panier a:active{color:var(--couleur-noir);background:var(--arriere-plan-points)}#en-tete .conteneur{column-gap:var(--espace-m);display:flex}#en-tete .bouton-menu-mobile{--hauteur-bouton-menu:22px;align-content:center;display:none}#en-tete .bouton-menu-mobile img{height:var(--hauteur-bouton-menu);object-fit:contain;image-rendering:crisp-edges;shape-rendering:geometricprecision}@media (hover:hover){#en-tete .bouton-menu-mobile:hover{background:initial!important}}@media (width<=1000px){#en-tete .bouton-menu-mobile{display:block}}@media (width<=600px){#en-tete{--en-tete-marges-internes-ligne:var(--espace-l)}}#menu-categories-produits{--menu-entree-longueur-minimale:13ch;--menu-section-marges-bloc-debut:var(--en-tete-hauteur);--menu-entree-marges-internes-ligne:var(--espace-m);margin-top:var(--menu-section-marges-bloc-debut);position:relative}#menu-categories-produits[data-entrees-presentes-debut] svg:first-of-type,#menu-categories-produits[data-entrees-presentes-fin] svg:last-of-type{opacity:1}#menu-categories-produits svg{pointer-events:none;opacity:0;mix-blend-mode:exclusion;shape-rendering:geometricprecision;block-size:.8rem;inline-size:.8rem;transition:opacity .2s;position:absolute;bottom:calc(17.59px - .35rem)}#menu-categories-produits svg:first-of-type{left:var(--espace-xs)}#menu-categories-produits svg:last-of-type{right:var(--espace-xs)}@media (width>600px){#menu-categories-produits svg{visibility:hidden}}#menu-categories-produits ul{grid-template-columns:repeat(auto-fit, minmax(var(--menu-entree-longueur-minimale), 1fr));place-items:center;gap:1px;display:grid}#menu-categories-produits ul li{inline-size:100%;color:var(--couleur-gris);text-align:center;text-transform:uppercase;letter-spacing:var(--espacement-inter-lettres-etendu-m);background:var(--couleur-noir);font-style:italic;font-weight:500}#menu-categories-produits ul li:hover{background:var(--couleur-gris)}#menu-categories-produits ul li a{inline-size:inherit;padding:var(--menu-entree-marges-internes-ligne) 0;text-decoration:none;display:inline-block}#menu-categories-produits ul li a:focus-visible{outline-color:var(--couleur-blanc)}@media (hover:hover){#menu-categories-produits ul li a:hover{color:var(--couleur-noir);background:var(--arriere-plan-points)}}#menu-categories-produits ul li.categorie-courante{background:var(--couleur-gris)}#menu-categories-produits ul li.categorie-courante a{color:var(--couleur-noir);background:var(--arriere-plan-points);font-weight:600}#menu-categories-produits ul li.categorie-courante a:focus-visible{outline-color:var(--couleur-noir)}@media (hover:hover){#menu-categories-produits ul li.categorie-courante a:hover{background:var(--arriere-plan-points)}}@media (width<=1000px){#menu-categories-produits ul{--menu-entree-marges-internes-ligne:var(--espace-s);flex-flow:wrap;font-size:.8rem;display:flex}#menu-categories-produits ul li{flex-grow:1;inline-size:min(140px,100%)}#menu-categories-produits ul li a{border:initial;inline-size:100%}}@media (width<=600px){#menu-categories-produits ul{scrollbar-width:none;flex-flow:row;overflow-x:scroll}#menu-categories-produits ul li{inline-size:initial;min-inline-size:140px}}.photos-produit{--colonne-gauche-position-haut:var(--menu-categories-produits-hauteur);--colonne-gauche-photo-hauteur:calc(100svh - var(--menu-categories-produits-hauteur));--colonne-droite-photo-hauteur-minimale:calc(100svh + var(--en-tete-hauteur) + var(--menu-categories-produits-hauteur));--colonne-photo-longueur-minimale:30rem;--section-marges-externes-bloc-fin:1rem;flex-flow:row;max-width:100%;display:flex;position:relative}.photos-produit .colonne{width:min(var(--colonne-photo-longueur-minimale), 100%);flex-flow:column;flex-grow:1;display:flex;position:relative}.photos-produit .colonne.colonne-gauche{top:var(--colonne-gauche-position-haut);height:var(--colonne-gauche-photo-hauteur);position:sticky}.photos-produit .colonne.colonne-gauche figure,.photos-produit .colonne.colonne-gauche picture,.photos-produit .colonne.colonne-gauche img{height:100%}.photos-produit .colonne.colonne-droite img{width:100%;max-height:var(--colonne-droite-photo-hauteur-minimale)}.photos-produit .colonne.colonne-droite figure picture img:only-child{min-height:var(--colonne-droite-photo-hauteur-minimale);max-height:var(--colonne-droite-photo-hauteur-minimale)}@media (width<=60rem){.photos-produit{--colonne-droite-photo-hauteur-minimale:var(--photo-hauteur-maximum);--photo-longueur-maximum:calc(100% - var(--espace-xl));--photo-hauteur-maximum:calc(100svh - var(--en-tete-hauteur) - 87px);scroll-behavior:smooth;scrollbar-width:none;scroll-snap-type:x mandatory;width:fit-content;max-width:initial;flex-flow:row;overflow-x:scroll}.photos-produit::-webkit-scrollbar{display:none}.photos-produit .colonne{scroll-snap-type:x mandatory;width:100%;min-width:100%}.photos-produit .colonne figure{scroll-snap-align:none center}.photos-produit .colonne img{max-height:var(--photo-hauteur-maximum)}.photos-produit .colonne.colonne-gauche{position:initial;min-width:var(--photo-longueur-maximum);height:initial}.photos-produit .colonne.colonne-droite{flex-flow:row}.photos-produit .colonne.colonne-droite figure{min-width:var(--photo-longueur-maximum);flex-grow:1}.photos-produit .colonne.colonne-droite:has(figure:only-child){min-width:var(--photo-longueur-maximum)}}.grille-produits{--grille-produits-hauteur-minimale:var(--contenu-page-hauteur-minimale-avec-categories);--aucun-produit-hauteur:var(--contenu-page-hauteur-minimale-avec-categories);--carte-produit-longueur-minimale:448px;--carte-produit-longueur-maximale:1000px;grid-auto-rows:1fr;grid-template-columns:repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr));min-height:var(--grille-produits-hauteur-minimale);gap:1px;display:grid}.grille-produits article{max-width:var(--carte-produit-longueur-maximale);box-shadow:0 0 0 1px var(--couleur-noir)}.grille-produits article figure{row-gap:var(--espace-xl);flex-flow:column;display:flex}.grille-produits article figure a{position:relative}@media (hover:hover){.grille-produits article figure a:hover .produit__illustration__survol{visibility:visible;opacity:1;transition:opacity .3s,visibility .3s}}.grille-produits article figure img{position:inherit;aspect-ratio:9/16;object-fit:cover;background:0 0;width:100%;max-height:70vh}.grille-produits article figure .produit__illustration__principale{display:block}.grille-produits article figure .produit__illustration__principale:before{content:"";z-index:-1;opacity:0;filter:opacity(20%);background-image:url(/app/themes/haiku-atelier-2024/assets/img/icons/cloud-gris.svg);background-position:50%;background-repeat:no-repeat;background-size:50%;width:100%;height:100%;animation:1.5s linear .5s infinite alternate both test;position:absolute;top:0;left:0}.grille-produits article figure .produit__illustration__principale img{opacity:0;transition:opacity 1s}.grille-produits article figure .produit__illustration__survol{visibility:hidden;opacity:0;width:100%;height:100%;transition:opacity .15s,visibility .15s;display:block;position:absolute;top:0;left:0}.grille-produits article figure .produit__illustration__survol img{background:var(--couleur-gris-fond)}.grille-produits article figure figcaption{margin-bottom:var(--espace-xl);padding:var(--espace-m);flex-flow:row;justify-content:space-between;display:flex}.grille-produits article figure figcaption h3{letter-spacing:var(--espacement-inter-lettres-etendu-m);font-style:italic}.grille-produits article figure figcaption p{letter-spacing:var(--espacement-inter-lettres-rapproche-s);font-weight:500}.grille-produits__aucun-produit{min-height:var(--aucun-produit-hauteur);text-align:center;grid-column:span 3;align-content:center}.grille-produits__aucun-produit p+p{margin-top:var(--espace-l);font-size:1.25rem}@media (width<=700px){.grille-produits{grid-template-columns:100%}.grille-produits article figure img{max-height:50svh}}@keyframes test{to{opacity:1}}.resume-produit{--resume-position-basse:0%;--section-marges-internes:var(--espace-l);--espace-inter-colonne:var(--espace-xl);--resume-police-graisse:500;--resume-police-style:italic;--resume-police-taille:var(--espace-l);--resume-police-nom-taille:1.33rem;--resume-police-selecteur-graisse:400;--resume-police-selecteur-taille:var(--espace-m);bottom:var(--resume-position-basse);position:sticky}.resume-produit .selecteur-produit{column-gap:var(--espace-inter-colonne);border-block:1px solid var(--couleur-noir);font-size:var(--resume-police-taille);font-weight:var(--resume-police-graisse);font-style:var(--resume-police-style);line-height:var(--hauteur-ligne-compacte);background:var(--couleur-blanc-fond);grid-template-columns:repeat(3,1fr);grid-auto-flow:column;place-items:center;display:grid;position:relative}.resume-produit .selecteur-produit>*{width:100%;height:100%;padding:var(--section-marges-internes);flex-flow:row;place-content:center;place-items:center;display:flex}.resume-produit .selecteur-produit>:nth-child(2){border-inline-start:1px solid var(--couleur-noir);border-inline-end:1px solid var(--couleur-noir)}.resume-produit .selecteur-produit__nom{font-size:var(--resume-police-nom-taille)}.resume-produit .selecteur-produit__attribut-variation{gap:var(--espace-m) var(--espace-l);font-size:var(--resume-police-selecteur-taille);font-weight:var(--resume-police-selecteur-graisse);text-transform:lowercase;flex-flow:wrap;display:flex}.resume-produit .selecteur-produit__attribut-variation label{margin-right:var(--espace-s)}.resume-produit .selecteur-produit__attribut-variation select{padding:var(--espace-xs) var(--espace-l);border:1px solid var(--couleur-noir);text-align:center;letter-spacing:initial;appearance:none;background:var(--couleur-gris-fond);position:relative}@supports selector(:user-valid){.resume-produit .selecteur-produit__attribut-variation select:user-valid{background:var(--couleur-gris-fond)}}.resume-produit .selecteur-produit__attribut-variation option{background:var(--couleur-gris-fond)}.resume-produit .selecteur-produit__attribut-variation__selecteurs{gap:var(--espace-m);flex-flow:wrap;place-content:center;place-items:center;display:flex;position:relative}.resume-produit .selecteur-produit__prix{font-style:initial}@media (width<=800px){.resume-produit{--section-marges-internes:var(--espace-m);--espace-inter-colonne:var(--espace-m)}}@media (width<=700px){.resume-produit{--resume-police-taille:var(--espace-m);--resume-police-nom-taille:var(--espace-m);--section-marges-internes:var(--espace-m);--espace-inter-colonne:var(--espace-s)}}@media (width<=500px){.resume-produit .selecteur-produit__selection-variation-attribut{row-gap:var(--espace-inter-colonne);flex-flow:column}.resume-produit .selecteur-produit__selection-variation-attribut h3{flex-basis:100%}}.details-produit{--bouton-marges-internes-bloc:var(--espace-l);--espace-inter-lignes:var(--espace-l);--espace-inter-texte:var(--espace-m);--section-marges-internes:var(--espace-l);--textuel-marges-internes-ligne:calc(var(--espace-l) * 2);background-color:var(--couleur-blanc)}.details-produit__textes{grid-template-columns:1fr;grid-auto-flow:row;display:grid}.details-produit__textes .section-textuelle:not(:last-of-type){border-block-end:1px solid var(--couleur-noir)}.details-produit__textes .section-textuelle:has(button[aria-expanded=false]) .section-textuelle__contenu{display:none}.details-produit__textes .section-textuelle h3{line-height:var(--hauteur-ligne-rapprochee)}.details-produit__textes .section-textuelle h3 button{width:100%;min-block-size:1lh;padding:var(--section-marges-internes);text-align:start;display:inline-block}.details-produit__textes .section-textuelle h3 button:active{background:var(--arriere-plan-points)}@media (hover:hover){.details-produit__textes .section-textuelle h3 button:hover{color:inherit;background:inherit}}.details-produit__textes .section-textuelle .section-textuelle__contenu{padding-block-end:var(--section-marges-internes);padding-inline:var(--textuel-marges-internes-ligne)}.details-produit__textes .section-textuelle .section-textuelle__contenu ul{list-style:inside}.details-produit__textes .section-textuelle .section-textuelle__contenu a{text-decoration-color:var(--couleur-noir)}.details-produit__textes .section-textuelle .section-textuelle__contenu>*+*{margin-top:var(--espace-inter-texte)}.details-produit__actions{--section-marges-internes:var(--espace-l);border-block:1px solid var(--couleur-noir);background:var(--arriere-plan-points);transition:background .2s;overflow:hidden}.details-produit__actions:has(button[disabled]){background:var(--couleur-gris-fond)}.details-produit__actions button{padding:var(--section-marges-internes);text-transform:uppercase;font-style:italic}@media (hover:hover){.details-produit__actions button:not([disabled]):hover{color:var(--couleur-blanc);background:var(--couleur-gris-fonce-fond);font-weight:600}}.produits-similaires{--carte-produit-longueur-minimale:448px;--carte-produit-longueur-maximale:1000px;--en-tete-flottante-hauteur:calc(1rem + var(--espace-l) * 2 + 1px);grid-template-rows:1fr auto;grid-template-columns:repeat(3,1fr);grid-template-areas:"en-tete en-tete en-tete""produits produits produits";place-items:center;display:grid;position:relative}.produits-similaires header{z-index:10;top:var(--en-tete-flottante-hauteur);width:100%;padding:var(--espace-l) 0;color:var(--couleur-blanc);text-align:center;background:var(--couleur-noir);grid-area:en-tete;position:sticky}.produits-similaires header h2{font-style:italic;line-height:var(--hauteur-ligne-rapprochee);text-transform:uppercase;letter-spacing:var(--espacement-inter-lettres-etendu-m)}.produits-similaires .grille-produits-similaires{grid-area:produits;grid-auto-rows:1fr;grid-template-columns:repeat(auto-fit, minmax(var(--carte-produit-longueur-minimale), 1fr));gap:1px;width:100%;display:grid}.produits-similaires .grille-produits-similaires article{max-width:var(--carte-produit-longueur-maximale);box-shadow:0 0 0 1px var(--couleur-noir)}.produits-similaires .grille-produits-similaires article figure{row-gap:var(--espace-xl);flex-flow:column;display:flex}.produits-similaires .grille-produits-similaires article figure a{position:relative}@media (hover:hover){.produits-similaires .grille-produits-similaires article figure a:hover .produit__illustration__survol{visibility:visible;opacity:1;transition:opacity .3s,visibility .3s}}.produits-similaires .grille-produits-similaires article figure .produit__illustration__principale{display:block}.produits-similaires .grille-produits-similaires article figure .produit__illustration__survol{visibility:hidden;opacity:0;width:100%;height:100%;transition:opacity .15s,visibility .15s;display:block;position:absolute;top:0;left:0}.produits-similaires .grille-produits-similaires article figure img{aspect-ratio:9/16;object-fit:cover;width:100%;max-height:70svh}.produits-similaires .grille-produits-similaires article figure figcaption{margin-bottom:var(--espace-xl);padding:0 var(--espace-m);flex-flow:row;justify-content:space-between;display:flex}.produits-similaires .grille-produits-similaires article figure figcaption h3{letter-spacing:var(--espacement-inter-lettres-etendu-m);font-style:italic}.produits-similaires .grille-produits-similaires article figure figcaption p{letter-spacing:var(--espacement-inter-lettres-rapproche-s);font-weight:500}@media (width<=700px){.produits-similaires .grille-produits-similaires{grid-template-columns:100%}.produits-similaires .grille-produits-similaires article figure img{max-height:50svh}}#pied-de-page{max-width:100vw;height:var(--pied-de-page-hauteur);padding:var(--espace-s) var(--espace-m);border-top:1px solid var(--couleur-noir);grid-template-columns:1fr 1fr;place-items:center;font-size:.8rem;display:grid}#pied-de-page .zone-menu-navigation-secondaire{text-transform:lowercase;justify-self:start;width:100%;height:100%}#pied-de-page .zone-liens-reseaux-sociaux{text-align:right;justify-items:end;width:100%;height:100%} \ No newline at end of file diff --git a/web/app/themes/haiku-atelier-2024/src/sass/base/elements/_formulaires.scss b/web/app/themes/haiku-atelier-2024/src/sass/base/elements/_formulaires.scss index 869974b1..4f01cd72 100755 --- a/web/app/themes/haiku-atelier-2024/src/sass/base/elements/_formulaires.scss +++ b/web/app/themes/haiku-atelier-2024/src/sass/base/elements/_formulaires.scss @@ -66,8 +66,8 @@ input[type="checkbox"], input[type="radio"] { transition: 0.2s background; &:checked { - color: var(--couleur-blanc); - background: var(--couleur-gris-fonce); + color: var(--couleur-noir); + background: var(--arriere-plan-points); // TODO: Utiliser un SVG plutôt qu'un « x » ? &::before { @@ -98,7 +98,7 @@ input[type="checkbox"], input[type="radio"] { @media (hover: hover) { &:hover { - background: var(--couleur-gris-fonce); + background: var(--arriere-plan-points); } } } From 53d71ea18363ad515813db84def51629ead9c488 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 5/6] =?UTF-8?q?ref(justfile)=20utilise=20watchexec=20pour?= =?UTF-8?q?=20la=20t=C3=A2che=20de=20compilation=20JS=20=C3=A0=20la=20m?= =?UTF-8?q?=C3=A0j=20des=20fichiers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- justfile | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/justfile b/justfile index c9fe13a2..5ee66b34 100755 --- a/justfile +++ b/justfile @@ -90,6 +90,11 @@ watch-css: build-js: aube x vite build --config "cfg/vite.config.ts" +# Compile TypeScript à chaque changement de fichier. +[group('js')] +watch-js: + @watchexec -w "web/app/themes/haiku-atelier-2024/src/scripts" -w "web/app/themes/haiku-atelier-2024/src/scripts-effect" -- just build-js treefmt + # Compile tout. [group('css')] [group('js')] @@ -98,11 +103,6 @@ build-all: @just build-js @just format -# Compile TypeScript à chaque changement de fichier. -[group('js')] -watch-js: - aube x vite build --config "cfg/vite.config.ts" --watch - # Vérifie le code TypeScript avec des analyseurs statiques. [group('js')] [group('qualité')] From c61e63117276d8b7a0de33290ee3c88e6f105d52 Mon Sep 17 00:00:00 2001 From: gcch Date: Thu, 30 Apr 2026 10:56:01 +0200 Subject: [PATCH 6/6] ref(env) wip --- config/environments/development.php | 5 +++ config/environments/production.php | 5 +++ config/environments/staging.php | 5 +++ .../haiku-atelier-2024/archive-product.php | 8 +---- .../src/inc/FonctionnalitesWooCommerce.php | 31 ++++++++++--------- 5 files changed, 33 insertions(+), 21 deletions(-) diff --git a/config/environments/development.php b/config/environments/development.php index cfacfcb8..df784947 100755 --- a/config/environments/development.php +++ b/config/environments/development.php @@ -8,6 +8,7 @@ declare(strict_types=1); use Roots\WPConfig\Config; +use function base64_encode; use function Env\env; Config::define('SAVEQUERIES', true); @@ -25,6 +26,10 @@ Config::define('DISALLOW_FILE_MODS', false); // WooCommerce Config::define('WOOCOMMERCE_API_CONSUMER_KEY', env('WOOCOMMERCE_API_CONSUMER_KEY')); Config::define('WOOCOMMERCE_API_CONSUMER_SECRET', env('WOOCOMMERCE_API_CONSUMER_SECRET')); +Config::define( + 'WOOCOMMERCE_API_AUTH_STRING', + base64_encode(env('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . env('WOOCOMMERCE_API_CONSUMER_SECRET')), +); // Stripe Config::define('STRIPE_API_SECRET', env('STRIPE_API_SECRET')); diff --git a/config/environments/production.php b/config/environments/production.php index 93b792c3..0047176f 100755 --- a/config/environments/production.php +++ b/config/environments/production.php @@ -8,6 +8,7 @@ declare(strict_types=1); use Roots\WPConfig\Config; +use function base64_encode; use function Env\env; Config::define('WP_DEBUG', true); @@ -20,6 +21,10 @@ Config::define('DISALLOW_FILE_MODS', false); Config::define('WOOCOMMERCE_API_CONSUMER_KEY', env('WOOCOMMERCE_API_CONSUMER_KEY')); Config::define('WOOCOMMERCE_API_CONSUMER_SECRET', env('WOOCOMMERCE_API_CONSUMER_SECRET')); +Config::define( + 'WOOCOMMERCE_API_AUTH_STRING', + base64_encode(env('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . env('WOOCOMMERCE_API_CONSUMER_SECRET')), +); // Stripe Config::define('STRIPE_API_SECRET', env('STRIPE_API_SECRET')); diff --git a/config/environments/staging.php b/config/environments/staging.php index 1651c055..0f7ba42b 100755 --- a/config/environments/staging.php +++ b/config/environments/staging.php @@ -8,8 +8,13 @@ declare(strict_types=1); use Roots\WPConfig\Config; +use function base64_encode; use function Env\env; Config::define('DISALLOW_INDEXING', true); Config::define('WOOCOMMERCE_API_CONSUMER_KEY', env('WOOCOMMERCE_API_CONSUMER_KEY')); Config::define('WOOCOMMERCE_API_CONSUMER_SECRET', env('WOOCOMMERCE_API_CONSUMER_SECRET')); +Config::define( + 'WOOCOMMERCE_API_AUTH_STRING', + base64_encode(env('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . env('WOOCOMMERCE_API_CONSUMER_SECRET')), +); diff --git a/web/app/themes/haiku-atelier-2024/archive-product.php b/web/app/themes/haiku-atelier-2024/archive-product.php index 2a97be56..a2b49c0f 100755 --- a/web/app/themes/haiku-atelier-2024/archive-product.php +++ b/web/app/themes/haiku-atelier-2024/archive-product.php @@ -17,7 +17,6 @@ use WC_Product; use function add_action; use function array_map; use function assert; -use function base64_encode; use function is_string; use function wc_get_products; use function wp_create_nonce; @@ -33,12 +32,7 @@ $products = array_map(callback: Product::from_wc_product(...), array: $wc_produc $context['products'] = $products; // Injecte les états initiaux des données du Produit sous forme de JSON dans le contexte. -$page_states = [ - 'nonce' => wp_create_nonce('wc_store_api'), - 'authString' => base64_encode( - Config::get('WOOCOMMERCE_API_CONSUMER_KEY') . ':' . Config::get('WOOCOMMERCE_API_CONSUMER_SECRET'), - ), -] +$page_states = ['authString' => Config::get('WOOCOMMERCE_API_AUTH_STRING'), 'nonce' => wp_create_nonce('wc_store_api')] |> wp_json_encode(...); assert(is_string($page_states)); $context['page_states'] = $page_states; diff --git a/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php b/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php index 479b02e7..adb6c205 100755 --- a/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php +++ b/web/app/themes/haiku-atelier-2024/src/inc/FonctionnalitesWooCommerce.php @@ -131,7 +131,8 @@ function retire_merdes_wc(): void { */ function genere_balises_img_dans_produit_dans_reponse_rest( WP_REST_Response $response, - mixed $_product, + WC_Data $_product, + WP_REST_Request $_request, ): WP_REST_Response { // Vérifie que la Réponse a des données if (empty($response->data)) { @@ -169,37 +170,34 @@ function genere_balises_img_dans_produit_dans_reponse_rest( return $response; } -add_filter('woocommerce_rest_prepare_product_object', 'genere_balises_img_dans_produit_dans_reponse_rest', 10, 2); - /** * TODO. */ function genere_prix_maximal_produit_variable_dans_reponse_rest( - WP_REST_Response $reponse, - WC_Data $_produit, + WP_REST_Response $response, + WC_Data $_product, + WP_REST_Request $_request, ): WP_REST_Response { // Vérifie que la Réponse a des données - if (empty($reponse->data)) { - return $reponse; + if (empty($response->data)) { + return $response; } // Si le Produit n'est pas Variable, assigner le prix du Produit comme prix maximal - if ('variable' !== $reponse->data['type']) { - $reponse->data['prix_maximal'] = $reponse->data['regular_price']; + if ('variable' !== $response->data['type']) { + $response->data['prix_maximal'] = $response->data['regular_price']; - return $reponse; + return $response; } // Assigne le prix de la Variation la plus chère dans la Réponse - $reponse->data['prix_maximal'] = collect($reponse->data['variations']) + $response->data['prix_maximal'] = collect($response->data['variations']) ->map(wc_get_product(...)) ->map(static fn($p) => $p->get_price())->max(); - return $reponse; + return $response; } -add_filter('woocommerce_rest_prepare_product_object', 'genere_prix_maximal_produit_variable_dans_reponse_rest', 10, 2); - /** * Retire la propagande commerciale de WooCommerce du menu. */ @@ -216,3 +214,8 @@ add_action('init', 'retire_script_galerie'); add_action('template_redirect', 'retire_merdes_wc'); add_action('wp_enqueue_scripts', 'dequeue_woocommerce_styles_scripts'); add_filter('woocommerce_enqueue_styles', '__return_empty_array'); +add_filter('woocommerce_rest_prepare_product_object', 'genere_balises_img_dans_produit_dans_reponse_rest', 10, 3); +add_filter('woocommerce_rest_prepare_product_object', 'genere_prix_maximal_produit_variable_dans_reponse_rest', 10, 3); + +// DEBUG +// add_filter('woocommerce_store_api_disable_nonce_check', '__return_true');