/* ==========================================================================
   Maxime Verdoni — pianist visual identity
   Near-black (#151514) & warm cream (#FEE5C7) duotone, Montserrat (headings
   + body), Tangerine (script logo wordmark) — all self-hosted, no external
   font requests. Loaded on top of Divi. Divi Theme Builder header/footer
   supply structure; this file supplies design tokens + the shared
   buttons/forms/notices system reused across every page. Global typography
   and colors (body/headings/links) are set natively in Divi, not here.
   Homepage-only styling (hero, "Listen now", releases, newsletter) lives in
   that page's own Custom CSS field, not in this shared stylesheet.
   ========================================================================== */

/* ---- Fonts (self-hosted, no external request) ---- */
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/montserrat-400.woff2') format('woff2');
}
@font-face {
	font-family: 'Montserrat';
	font-style: italic;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/montserrat-400-italic.woff2') format('woff2');
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 500;
	font-display: swap;
	src: url('../fonts/montserrat-500.woff2') format('woff2');
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 600;
	font-display: swap;
	src: url('../fonts/montserrat-600.woff2') format('woff2');
}
@font-face {
	font-family: 'Montserrat';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/montserrat-700.woff2') format('woff2');
}
@font-face {
	font-family: 'Tangerine';
	font-style: normal;
	font-weight: 400;
	font-display: swap;
	src: url('../fonts/tangerine-400.woff2') format('woff2');
}
@font-face {
	font-family: 'Tangerine';
	font-style: normal;
	font-weight: 700;
	font-display: swap;
	src: url('../fonts/tangerine-700.woff2') format('woff2');
}

/* ---- Design tokens — "Golden Hour" ----
   #1C1712 = warm brown-black (primary background, everywhere)
   #F2E8D8 = ivory (text / light surfaces)
   #D4A662 = honey gold (Link Color — reused as the site's one accent)
   All Couleurs Globales below were created in Divi's Visual Builder by the
   client (not by direct DB write — Divi 5 silently prunes named Global
   Colors it didn't create itself, confirmed empirically), so these are
   real, stable --gcid-* custom properties, not just CSS fallbacks. The
   hex values here only ever apply if Divi fails to emit a given --gcid-*
   variable on a given page (e.g. a Couleur Globale not yet "used" in any
   module there) — kept in sync with the live values as a safety net, not
   as a second source of truth. Verified against the live compiled CSS on
   2026-09-12 (previously still had stale "Nocturne" values, a palette
   rejected before Golden Hour was adopted — see mémoire
   project-maxime-verdoni-refonte-charte-2026). */
:root {
	--c-ink: var(--gcid-secondary-color, #1C1712);
	--c-cream: var(--gcid-primary-color, #F2E8D8);

	--c-bg: var(--gcid-secondary-color, #1C1712);
	--c-bg-alt: var(--gcid-1gphndwf8c, #26201A);
	--c-bg-dark: var(--gcid-secondary-color, #1C1712);
	--c-bg-dark-alt: var(--gcid-1gphndwf8c, #26201A);
	--c-surface: var(--gcid-1gphndwf8c, #26201A);
	--c-cream-soft: rgba(242,232,216,0.7);
	--c-line: var(--gcid-uz3jy2i7hs, #4A3F33);
	--c-line-dark: var(--gcid-uz3jy2i7hs, #4A3F33);
	--c-line-strong: var(--gcid-secondary-color, #1C1712);
	--c-accent: var(--gcid-link-color, #D4A662);
	--c-muted: var(--gcid-2aq73p2puf, #A69783);
	--c-error: var(--gcid-oqzxjvm5bw, #B5544A);
	--c-error-bg: var(--gcid-rmuirh9z24, #241A19);

	--font-body: 'Montserrat', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
	--font-script: 'Tangerine', 'Montserrat', cursive;

	--space-1: 0.4rem;
	--space-2: 0.8rem;
	--space-3: 1.2rem;
	--space-4: 1.6rem;
	--space-5: 2.4rem;
	--space-6: 3.2rem;
	--space-7: 4.8rem;
	--space-8: 6.4rem;

	--radius-sm: 10px;
	--radius-md: 6px;
	--ease: cubic-bezier(0.4, 0, 0.2, 1);
}

/* ---- Base ----
   Font family/weight and text color (body, headings, links) are set
   natively in Divi (Theme Customizer > General Settings > Typography) —
   no override here. Only what Divi has no equivalent for stays: page
   background, font smoothing, and heading letter-spacing. */
body {
	background-color: var(--c-bg);
	-webkit-font-smoothing: antialiased;
}

/* Fraunces (serif display) has generous built-in spacing — the tight
   -0.01em tracking inherited from the old Montserrat-only setup cramps its
   letterforms at large sizes. Natural tracking reads better here. */
h1, h2, h3, h4, h5, h6,
.et_pb_module h1, .et_pb_module h2, .et_pb_module h3 {
	letter-spacing: normal;
}

::selection {
	background: var(--c-ink);
	color: var(--c-cream);
}

/* ---- Logo mark (header/footer) ----
   Flex + vertical centering on the row does the alignment work, so the
   logo never needs a hand-placed position/top/left that breaks on resize.
   v3 (2026-09-13): silhouette (left, x≈0-600) + "Maxime"/"Verdoni" as
   stacked vector text (right, two text lines), viewBox 0 0 1700 595.28.
   The silhouette is two-tone by design (a base shape + carved-line detail
   paths) - the base and the text groups are hardcoded to var(--c-cream)
   (Primary Color, explicit client request) rather than currentColor:
   this module's own Divi "link color" setting turned out to be the gold
   accent (gcid-link-color), not Primary, so currentColor was silently
   pulling in the wrong color - forcing Primary directly is both what was
   asked and the correct fix for that mismatch. The white detail lines
   stay a fixed white since they're an illustration choice of the mark
   itself, not a light/dark-section concern.
   ope-logo__viewport clips the SVG to a fixed box so the
   header's scrolled state (further down) can show only the silhouette by
   shrinking the box - the silhouette sits at the very start of the
   viewBox this time, so no horizontal shift is needed, just a narrower
   crop window. */
.et-l--header .et_pb_row,
.et-l--footer .et_pb_row {
	align-items: center;
}
.ope-logo {
	display: inline-flex;
	align-items: center;
	text-decoration: none;
}
.ope-logo__viewport {
	display: block;
	overflow: hidden;
	height: 46px;
	width: 131px;
	transition: width 0.35s var(--ease), height 0.35s var(--ease);
}
.ope-logo__mark {
	display: block;
	height: 100%;
	width: auto;
	transition: transform 0.35s var(--ease);
}
.ope-logo__mark .ope-logo__silhouette-base,
.ope-logo__mark .ope-logo__maxime,
.ope-logo__mark .ope-logo__verdoni {
	fill: var(--c-cream);
}
/* Trace transparent, demande explicite : le header lui-meme est
   transparent (.et_pb_section_0_tb_header { background-color:
   rgba(0,0,0,0) }), donc ce "decoupe" laisse voir directement ce qu'il y
   a derriere (la video du hero, ou le fond flou une fois .is-scrolled). */
.ope-logo__mark .ope-logo__silhouette-detail {
	fill: transparent;
}
.ope-logo__verdoni {
	transform: translateX(3px);
}
@media (max-width: 600px) {
	.ope-logo__viewport {
		height: 36px;
		width: 103px;
	}
}

/* Entree au chargement - silhouette en fondu, puis effet "ecriture par
   lettre" : chaque trait/lettre de "Maxime" puis de "Verdoni" apparait
   l'un apres l'autre (demande explicite) - on cible directement les
   <path> de chaque groupe dans leur ordre reel dans le fichier (6 dans
   Maxime, 7 dans Verdoni, verifie en comptant les balises du SVG fourni,
   pas devine), pas des lettres "virtuelles" qu'il faudrait recreer a la
   main. Seul le header l'anime (le footer affiche le logo direct, deja
   visible/hors champ au chargement donc l'animation n'y aurait aucun
   sens tant qu'on n'a pas scrolle jusque-la).
   Delais decales de 6000ms UNIQUEMENT sur la page d'accueil (body.home) :
   c'est le delai de la propre animation d'entree du header, qui elle
   n'est configuree qu'une fois pour tout le template partage - demande
   explicite du client de ne PAS repercuter ce delai sur les autres pages,
   ou le header doit s'afficher immediatement. Sur ces autres pages, plus
   d'animation du tout (2026-09-22, revu suite retour client : rejouer la
   meme sequence en accelere sur chaque page restait visible/genant,
   demande explicite d'un affichage "normal" = statique). */
.ope-logo__silhouette,
.ope-logo__maxime path,
.ope-logo__verdoni path {
	opacity: 1;
}
.et-l--header .ope-logo__maxime path,
.et-l--header .ope-logo__verdoni path {
	animation: opeLogoLetterIn 0.35s var(--ease) both;
}
@keyframes opeLogoFadeIn {
	from { opacity: 0; }
	to { opacity: 1; }
}
@keyframes opeLogoLetterIn {
	from { opacity: 0; transform: translateY(8px); }
	to { opacity: 1; transform: translateY(0); }
}
/* Page d'accueil : silhouette a 6.1s, "Maxime" (6 traits) 6.60s-7.00s,
   "Verdoni" (7 traits) 7.08s-7.56s en suite immediate. */
body.home .et-l--header .ope-logo__silhouette {
	animation: opeLogoFadeIn 0.5s var(--ease) both;
	animation-delay: 6.1s;
}
body.home .et-l--header .ope-logo__maxime path:nth-child(1) { animation-delay: 6.60s; }
body.home .et-l--header .ope-logo__maxime path:nth-child(2) { animation-delay: 6.68s; }
body.home .et-l--header .ope-logo__maxime path:nth-child(3) { animation-delay: 6.76s; }
body.home .et-l--header .ope-logo__maxime path:nth-child(4) { animation-delay: 6.84s; }
body.home .et-l--header .ope-logo__maxime path:nth-child(5) { animation-delay: 6.92s; }
body.home .et-l--header .ope-logo__maxime path:nth-child(6) { animation-delay: 7.00s; }
body.home .et-l--header .ope-logo__verdoni path:nth-child(1) { animation-delay: 7.08s; }
body.home .et-l--header .ope-logo__verdoni path:nth-child(2) { animation-delay: 7.16s; }
body.home .et-l--header .ope-logo__verdoni path:nth-child(3) { animation-delay: 7.24s; }
body.home .et-l--header .ope-logo__verdoni path:nth-child(4) { animation-delay: 7.32s; }
body.home .et-l--header .ope-logo__verdoni path:nth-child(5) { animation-delay: 7.40s; }
body.home .et-l--header .ope-logo__verdoni path:nth-child(6) { animation-delay: 7.48s; }
body.home .et-l--header .ope-logo__verdoni path:nth-child(7) { animation-delay: 7.56s; }
/* Toutes les autres pages : logo affiche directement, sans animation
   (specificite superieure aux regles non scopees ci-dessus - 3 classes
   contre 2 - donc pas besoin de !important). */
body:not(.home) .et-l--header .ope-logo__silhouette,
body:not(.home) .et-l--header .ope-logo__maxime path,
body:not(.home) .et-l--header .ope-logo__verdoni path {
	animation: none;
	opacity: 1;
}
@media (prefers-reduced-motion: reduce) {
	.et-l--header .ope-logo__silhouette,
	.et-l--header .ope-logo__maxime path,
	.et-l--header .ope-logo__verdoni path,
	body.home .et_pb_text_0_tb_header .ope-logo {
		animation: none;
	}
}
/* L'animation d'entree du logo (fade, delai 6s) etait geree par Divi
   lui-meme (attribut "animation" du module et_pb_text_0_tb_header dans
   le Header Layout, post ID 6) - donc appliquee identiquement sur toutes
   les pages, pas seulement l'accueil. Confirme le 2026-09-23 (retour
   client, DevTools) : Divi pose un style INLINE
   (element.style.opacity/animation-*) directement sur le module, ce qui
   rendait un simple override CSS sur la section fragile (il faut cibler
   l'element exact qui porte le style inline, pas juste son parent).
   Plus simple et plus robuste : desactive cote Divi ("style":"none" dans
   le JSON, cf. wp post get 6) et recree ici en CSS pure, reservee a
   l'accueil - reprend le timing d'origine (duration 3s, delay 6s,
   ease-in-out) avec le keyframe opeLogoFadeIn deja utilise pour la
   silhouette.
   Cible .ope-logo (le lien), PAS .et_pb_text_0_tb_header entier (2026-10-
   03, retour client : le flou au scroll ne s'affichait plus du tout sur
   l'accueil) - .ope-header-blur est un SIBLING de .ope-logo dans le DOM
   (voir markup reel), pas un enfant : mettre opacity:0 sur le module
   parent assombrit TOUT ses enfants par composition (opacity se multiplie
   le long de l'arbre), blur inclus, sans qu'aucun opacity:1 pose sur le
   blur lui-meme ne puisse compenser. Cibler seulement .ope-logo laisse le
   blur intact quel que soit l'etat de l'animation. Sur les autres pages :
   plus aucun style pose sur le logo, il reste simplement visible. */
body.home .et_pb_text_0_tb_header .ope-logo {
	opacity: 0;
	animation: opeLogoFadeIn 3s ease-in-out 6s both;
}

/* ---- Header fixe + reduction au scroll ----
   --ope-header-height est posee en JS (voir header-scroll.js) sur la
   hauteur reelle du header, pour compenser son passage en position fixed
   (sinon le haut de chaque page se retrouve masque dessous).
   Vraie cause du flou trouvee (2026-09-13, apres coup) : le client a un
   CSS personnalise sur .et_pb_section_0_tb_header (position:absolute,
   centrage max-width:1200px) pour que le header s'affiche correctement -
   consequence, .et-l--header (qui l'entoure) fait 0px de haut, PLUS son
   petit-enfant .et_pb_column_0_tb_header (la colonne du logo, ~8/24 de
   large) devient le "positioning context" le plus proche pour tout enfant
   en position:absolute qu'on y place. .ope-header-blur etait injecte dans
   le module Code du logo, DANS cette colonne - en position:absolute avec
   left:0;right:0, il ne s'etendait donc que sur la largeur de cette seule
   colonne (~1/3 du header), pas sur toute la largeur - d'ou "ca ne
   s'affiche que sous la colonne de gauche". Passe en position:fixed :
   l'ancrage se fait alors directement par rapport au viewport, sans
   se soucier de la largeur de la colonne qui le contient dans le DOM
   (tant qu'aucun ancetre n'a de transform/filter/perspective, ce qui
   n'est pas le cas ici). header-scroll.js mesure aussi maintenant
   .et_pb_section_0_tb_header (la vraie barre visible) au lieu de
   .et-l--header (qui fait 0px) pour --ope-header-height. */
.et-l--header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 9999;
}
/* Pas de compensation sur la home : le header doit se superposer au
   fond (video/hero), pas pousser le contenu en dessous - demande
   explicite. Les autres pages, elles, n'ont pas de hero plein cadre a
   recouvrir : sans ce padding, leur propre contenu se retrouverait
   masque sous le header fixe. */
body:not(.home) {
	padding-top: var(--ope-header-height, 90px);
}
.ope-header-blur {
	position: fixed;
    left: 0;
    right: 0;
    top: 0;
    height: calc(var(--ope-header-height, 90px) + 10px);
    pointer-events: none;
    opacity: 0;
    z-index: -1;
    transition: opacity 0.35s var(--ease);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    mask-image: linear-gradient(to bottom, black 70%, transparent 100%);
}
.et-l--header.is-scrolled .ope-header-blur {
	opacity: 1;
}
/* Recadrage approximatif sur la silhouette seule (occupe environ
   x=0-600 dans le viewBox 1700x595.28 - deduit des coordonnees absolues
   reelles du path, pas devine au hasard, mais pas un vrai calcul de
   bounding box non plus : a ajuster au pixel pres une fois visible en
   vrai si besoin). Elle demarre au tout debut du viewBox cette fois, pas
   besoin de translateX - juste une fenetre plus etroite. */
.et-l--header.is-scrolled .ope-logo__viewport {
	width: 30px;
	height: 30px;
}
@media (max-width: 600px) {
	.et-l--header.is-scrolled .ope-logo__viewport {
		width: 24px;
		height: 24px;
	}
}

/* ---- Logo + menu toujours sur la meme ligne, y compris mobile ----
   Le header (Theme Builder, partage par toutes les pages) empile logo et
   menu en dessous de 767px par defaut : la ligne passe en flex-wrap:wrap
   ET chaque colonne devient 24/24 (pleine largeur) a ce breakpoint - les
   deux effets combines forcent le menu sur une deuxieme ligne. On desactive
   le wrap partout et on redonne aux deux colonnes une largeur naturelle
   (le logo prend sa place, le menu prend le reste) au lieu de 24/24 chacune. */
.et-l--header .et_pb_row_0_tb_header {
	flex-wrap: nowrap !important;
}
@media (max-width: 767px) {
	.et-l--header .et_pb_column_0_tb_header {
		flex: 0 0 auto !important;
		width: auto !important;
		max-width: none !important;
	}
	.et-l--header .et_pb_column_1_tb_header {
		flex: 1 1 auto !important;
		width: auto !important;
		max-width: none !important;
	}
}

/* ---- Top menu — always Primary color, no exception for the active link ----
   Divi's Menu module already colors base links, cart/search icons and the
   mobile menu bar with --gcid-primary-color (confirmed in the live
   compiled CSS) - the one exception was the "current page" link, styled
   by Divi with --gcid-link-color (the gold accent) instead, so it stood
   out differently from every other menu item. Explicit client request:
   every link stays the same color, including the active one - covering
   every "current" class WordPress/Divi might apply (current-menu-item,
   its ancestor variant, and the older current_page_item/current_page_*
   classes core nav menus also add) rather than just the one first found.
   #et-boc is needed here (matches the specificity note at the top of
   woocommerce.css) because this rule has to beat Divi's own per-module
   CSS, which loads AFTER this file and already carries 3 classes +
   !important. */
#et-boc .et_pb_menu_0_tb_header.et_pb_menu ul li.current-menu-item > a,
#et-boc .et_pb_menu_0_tb_header.et_pb_menu ul li.current-menu-ancestor > a,
#et-boc .et_pb_menu_0_tb_header.et_pb_menu ul li.current_page_item > a,
#et-boc .et_pb_menu_0_tb_header.et_pb_menu ul li.current_page_ancestor > a,
#et-boc .et_pb_menu_0_tb_header.et_pb_menu ul li.current_page_parent > a,
#et-boc .et_pb_menu_0_tb_header.et_pb_menu ul:not(.sub-menu) > li.current-menu-ancestor > a {
	color: var(--c-cream) !important;
}

/* ---- Buttons (Divi + WooCommerce share these) ----
   Default = cream bg / ink text (for use on dark sections).
   .et_pb_button_alt = ink bg / cream text (for use on light sections).
   Divi's hover-arrow icon is dropped entirely — not part of the approved
   design. Originally scoped to .et_pb_button only (the Button module) -
   elargi le 2026-10-03 (retour client, page my-account) : les boutons
   WooCommerce natifs (my-account, panier, etc.) ne sont pas des modules
   Divi Button donc n'avaient pas cette regle - meme fleche par defaut
   visible dessus. */
.et_pb_button::after,
.et_pb_button::before,
button.button::after,
button.button::before,
input.button::after,
input.button::before,
a.button::after,
a.button::before,
.woocommerce #respond input#submit::after,
.woocommerce #respond input#submit::before,
.woocommerce a.button::after,
.woocommerce a.button::before,
.woocommerce button.button::after,
.woocommerce button.button::before,
.woocommerce input.button::after,
.woocommerce input.button::before {
	display: none !important;
	content: none !important;
}
.et_pb_button,
button.button,
input.button,
a.button,
.woocommerce #respond input#submit,
.woocommerce a.button,
.woocommerce button.button,
.woocommerce input.button {
	font-family: var(--font-body) !important;
	font-weight: 700 !important;
	font-size: 0.95rem !important;
	letter-spacing: 0.01em;
	text-transform: none !important;
	background: var(--c-cream) !important;
	color: var(--c-ink) !important;
	border: 1px solid var(--c-cream) !important;
	border-radius: var(--radius-sm) !important;
	padding: 0.9em 1.8em !important;
	transition: filter 0.2s var(--ease), transform 0.2s var(--ease), box-shadow 0.2s var(--ease) !important;
	box-shadow: none !important;
}
/* Simple, contrast-safe hover: darken the button itself and lift it slightly.
   Never goes transparent, so it can never disappear against its own section. */
.et_pb_button:hover,
button.button:hover,
input.button:hover,
a.button:hover,
.woocommerce #respond input#submit:hover,
.woocommerce a.button:hover,
.woocommerce button.button:hover,
.woocommerce input.button:hover {
	filter: brightness(0.92);
	transform: translateY(-2px);
	box-shadow: 0 6px 14px rgba(21,21,20,0.18) !important;
}
.et_pb_button.et_pb_button_alt,
.woocommerce a.button.alt,
.woocommerce button.button.alt,
.woocommerce input.button.alt {
	background: var(--c-ink) !important;
	color: var(--c-cream) !important;
	border-color: var(--c-ink) !important;
}
.et_pb_button.et_pb_button_alt:hover,
.woocommerce a.button.alt:hover,
.woocommerce button.button.alt:hover,
.woocommerce input.button.alt:hover {
	filter: brightness(1.35);
	transform: translateY(-2px);
	box-shadow: 0 6px 14px rgba(21,21,20,0.35) !important;
}

/* Sold-individually digital shop — quantity is always 1, no reason to
   show the stepper on the single-product buy form. */
#et-boc .et_pb_wc_add_to_cart .quantity {
	display: none !important;
}
#et-boc .et_pb_wc_add_to_cart form.cart {
	gap: var(--space-2) !important;
}
.woocommerce-thankyou-order-received {
    padding: 10px 20px !important;
    margin-bottom: 20px;
}
.woocommerce ul.order_details li strong {
	color: var(--c-cream) !important;
}
.et_pb_wc_checkout_payment_info_0_tb_body #payment .button#place_order {
    background-color: var(--c-cream) !important;
    color: var(--c-ink) !important;
}
/* Separe du bouton place_order ci-dessus (2026-10-03) : le tableau de
   telechargements de My Account passe en fond creme (voir
   assets/css/woocommerce.css) - un bouton "creme" y serait invisible,
   contrairement au checkout qui reste sur fond sombre. */
a.woocommerce-MyAccount-downloads-file.button.alt {
    background-color: var(--c-ink) !important;
    color: var(--c-cream) !important;
}
.woocommerce-thankyou-order-received {
    color: var(--c-ink) !important;
}

/* ---- Forms (shared base — WooCommerce specifics in woocommerce.css) ---- */
input[type="text"],
input[type="email"],
input[type="tel"],
input[type="url"],
input[type="password"],
input[type="number"],
input[type="search"],
textarea,
select {
	font-family: var(--font-body);
	background: var(--c-surface);
	border: 1px solid var(--c-line);
	border-radius: var(--radius-sm);
	padding: 0.75em 1em;
	color: var(--c-ink);
	transition: border-color 0.15s var(--ease);
}
/* !important necessaire ici : Divi embarque sa propre regle de focus
   (divi-style-parent-inline-inline-css : "input.text:focus,
   input.title:focus, input[type=text]:focus, select:focus,
   textarea:focus { border-color: #2d3940; color: #3e3e3e; }") avec une
   specificite plus elevee que input:focus seul (elle cible
   input[type=text], un attribut en plus) - elle gagnait donc sur TOUS
   les champs type="text" du site, pas seulement ceux d'un formulaire en
   particulier (ex: prenom/nom au checkout), remplacant a la fois la
   couleur de bordure ET la couleur du texte au focus par des valeurs
   fixes hors palette. Sans !important ici, le probleme se represente
   ailleurs des qu'un nouveau champ type="text" est ajoute. */
input:focus,
textarea:focus,
select:focus {
	border-color: var(--c-accent) !important;
	color: var(--c-ink) !important;
	outline: none;
}

input[type="radio"],
input[type="checkbox"] {
	accent-color: var(--c-accent);
}

/* ---- Notices (WordPress + WooCommerce) ---- */
.woocommerce-message,
.woocommerce-error,
.woocommerce-info,
.woocommerce-noreviews {
	background: var(--c-bg-alt) !important;
	border: none !important;
	border-left: 3px solid var(--c-ink) !important;
	color: var(--c-ink) !important;
	border-radius: var(--radius-sm);
	padding: var(--space-3) var(--space-4) !important;
	font-size: 0.92rem;
	box-shadow: none !important;
}
.woocommerce-error {
	border-left-color: var(--c-error) !important;
	background: var(--c-error-bg) !important;
}
.woocommerce-message::before,
.woocommerce-error::before,
.woocommerce-info::before {
	display: none !important;
}

/* ---- Footer "Join Maxime" social links ----
   Real brand SVGs (same source/technique as the Listen Now widget) placed
   before each link's text - inline-flex on the <a> keeps icon + label
   aligned while the existing <br /> stacking between links is untouched. */
.ope-social-link {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
}
.ope-social-link__icon svg {
	width: 15px;
	height: 15px;
	display: block;
	fill: currentColor;
}

/* ---- Homepage "Latest releases" cards ----
   Same visual language as .ope-product-card in woocommerce.css (square
   cover, rounded corners, hover zoom) - intentionally kept in sync since
   both show the same kind of content (a release/product with cover art).
   Reconstructed 2026-09-13 after the page's own Custom CSS field (Divi
   Page Settings) was accidentally cleared - moved here instead of back
   into Custom CSS specifically so a future accidental clear in the page
   settings can't take it down again; only the homepage still needs a
   Custom CSS field at all, for nothing that's this reusable/structural. */
.ope-release {
	position: relative;
	display: block;
	aspect-ratio: 1 / 1;
	border-radius: var(--radius-md);
	overflow: hidden;
	background: var(--c-bg-dark-alt);
	margin-bottom: var(--space-3);
}
.ope-release img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.3s var(--ease);
}
.ope-release:hover img {
	transform: scale(1.04);
}
.ope-release__play {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	opacity: 0;
	background: rgba(28, 23, 18, 0.4);
	transition: opacity 0.2s var(--ease);
}
.ope-release:hover .ope-release__play,
.ope-release:focus-visible .ope-release__play {
	opacity: 1;
}
.ope-release__play::before {
	content: "";
	width: 0;
	height: 0;
	margin-left: 4px;
	border-style: solid;
	border-width: 11px 0 11px 18px;
	border-color: transparent transparent transparent var(--c-cream);
}
.ope-release__title {
	font-size: 0.98rem;
	font-weight: 500;
	line-height: 1.3;
	margin: 0 0 0.2em;
	color: var(--c-cream);
}
.ope-release__artists {
	font-size: 0.85rem;
	color: var(--c-cream-soft);
	margin: 0;
}

/* ---- Homepage "Upcoming events" cards (The Events Calendar) ----
   Same visual language as .ope-release on purpose (square media, rounded
   corners, hover zoom, title/subtitle pair) - see [ope_upcoming_events]
   shortcode in mu-plugins/ope-events.php, which outputs its own grid
   wrapper directly (not 4 separate Divi columns like the releases row),
   hence the grid rules below instead of relying on the Builder's layout. */
.ope-event-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: var(--space-4);
}
@media (max-width: 989px) {
	.ope-event-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}
@media (max-width: 767px) {
	.ope-event-grid {
		grid-template-columns: 1fr;
	}
}
.ope-event-card__media {
	position: relative;
	display: block;
	aspect-ratio: 1 / 1;
	border-radius: var(--radius-md);
	overflow: hidden;
	background: var(--c-bg-dark-alt);
	margin-bottom: var(--space-3);
}
.ope-event-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.3s var(--ease);
}
.ope-event-card:hover .ope-event-card__media img {
	transform: scale(1.04);
}
.ope-event-card__fallback {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	font-size: 2.4rem;
	color: var(--c-cream-soft);
}
.ope-event-card__title-link {
	display: block;
	text-decoration: none;
	color: inherit;
}
.ope-event-card__title-link:hover .ope-event-card__title {
	text-decoration: underline;
}
.ope-event-card__title {
	font-size: 0.98rem;
	font-weight: 500;
	line-height: 1.3;
	margin: 0 0 0.2em;
	color: var(--c-cream);
}
.ope-event-card__date {
	font-size: 0.85rem;
	color: var(--c-cream-soft);
	margin: 0;
}
.ope-event-card__venue {
	font-size: 0.85rem;
	color: var(--c-cream-soft);
	margin: 0;
}
.ope-event-empty {
	color: var(--c-cream-soft);
	font-size: 0.95rem;
}

/* ---- Events archive page (/events/) ----
   TEC's own Views v2 List/Month/Day output (search bar, view switcher,
   skeleton-mode colors) is fully bypassed via the
   tribe_events_views_v2_bootstrap_pre_get_view_html filter (see
   mu-plugins/ope-events.php) - client explicitly asked to drop that
   calendar-app chrome for a simple sober list, same card design as the
   homepage's "Upcoming events"/"Latest releases" widgets. */
.ope-events-archive {
	max-width: 1200px;
	margin: 0 auto;
	padding: var(--space-6) var(--space-4);
}
.ope-events-archive__title {
	color: var(--c-cream);
	margin: 0 0 var(--space-5);
}

/* ---- Single event page (The Events Calendar, Skeleton stylesheet mode) ----
   Skeleton mode intentionally ships almost no styling of its own (only
   layout, no color) so it doesn't fight this theme's CSS - but that also
   means its text has no color rule at all and defaults to browser black,
   same "noir sur noir" issue already found and fixed on My Account, since
   the page background is dark by default sitewide (body{background-color:
   var(--c-bg)}). Confirmed via views-skeleton.css / tribe-events-single-
   skeleton.css: no color declarations beyond `color:initial` anywhere. */
#tribe-events-content.tribe-events-single {
	color: var(--c-cream);
}
.tribe-events-single-event-title {
	color: var(--c-cream);
}
.tribe-events-schedule,
.tribe-events-schedule * {
	color: var(--c-cream-soft) !important;
}
.tribe-events-back a,
.tribe-events-nav-pagination a,
.tribe-events-single-event-description a,
.tribe-events-content a {
	color: var(--c-cream);
	text-decoration: underline;
}
.tribe-events-back a:hover,
.tribe-events-nav-pagination a:hover,
.tribe-events-single-event-description a:hover,
.tribe-events-content a:hover {
	color: var(--c-cream-soft);
}
.tribe-events-single-section-title {
	color: var(--c-cream);
}
.tribe-events-meta-list {
	list-style: none;
	margin: 0;
	padding: 0;
}
.tribe-events-meta-item {
	border-bottom: 1px solid var(--c-line-dark);
	padding: 0.6em 0;
}
.tribe-events-meta-item:first-child {
	border-top: 1px solid var(--c-line-dark);
}
.tribe-events-meta-label {
	color: var(--c-cream-soft);
	margin-right: 0.4em;
}
.tribe-events-meta-value,
.tribe-events-meta-value * {
	color: var(--c-cream) !important;
}

/* The skeleton stylesheet lays .tribe-events-meta-group out as flex
   items side by side, AND the event has two separate sibling wrappers -
   .tribe-events-event-meta.primary (Details + Organizer) and .secondary
   (Venue + the Google Map embed, .tribe-events-venue-map, which is NOT a
   .tribe-events-meta-group itself) - so both the groups within each
   wrapper and the two wrappers themselves need forcing to block/stacked.
   Every selector here is deliberately qualified with the #tribe-events-
   content ancestor (kept even though !important should already be
   enough) so this can never lose to a rule this project hasn't found. */
#tribe-events-content .tribe-events-event-meta,
#tribe-events-content .tribe-events-event-meta.primary,
#tribe-events-content .tribe-events-event-meta.secondary {
	display: block !important;
	float: none !important;
	width: 100% !important;
}
#tribe-events-content .tribe-events-meta-group {
	display: block !important;
	flex: none !important;
	float: none !important;
	width: 100% !important;
	margin: 0 0 var(--space-4) !important;
	padding: 0 !important;
}
#tribe-events-content .tribe-events-meta-group:last-child {
	margin-bottom: 0 !important;
}
#tribe-events-content .tribe-events-meta-item {
	display: block !important;
	float: none !important;
	width: 100% !important;
}
#tribe-events-content .tribe-events-venue-map {
	display: block !important;
	float: none !important;
	width: 100% !important;
	margin-top: var(--space-4);
}

/* "Add to calendar" dropdown - the outer .__button is a styled container,
   but the actual clickable element inside it is a native <button> the
   skeleton stylesheet never resets, so the browser's own gray button
   chrome rendered on top of (and clashing with) the container's own
   border/color - that's the "bouton de base gris au-dessus" bug. The
   export-icon's SVG <path> also has no fill attribute of its own (default
   SVG fill is black, not currentColor), hence "noir sur noir". */
.tribe-events-c-subscribe-dropdown__button {
	display: inline-flex;
	align-items: center;
	gap: 0.5em;
	font-family: var(--font-body);
	font-size: 0.9rem;
	color: var(--c-cream) !important;
	background: transparent;
	border: 1px solid var(--c-cream);
	border-radius: var(--radius-sm);
	cursor: pointer;
	transition: background 0.2s var(--ease), color 0.2s var(--ease);
}
.tribe-events-c-subscribe-dropdown__button:hover {
	background: var(--c-cream);
	color: var(--c-ink) !important;
}
.tribe-events-c-subscribe-dropdown__button-text {
	appearance: none;
	background: none !important;
	border: none !important;
	padding: 0 !important;
	margin: 0;
	font: inherit;
	color: inherit;
	cursor: pointer;
}
.tribe-events-c-subscribe-dropdown__export-icon path:first-child {
	fill: currentColor;
}
.tribe-events-c-subscribe-dropdown__export-icon path:last-child {
	fill: none;
	stroke: currentColor;
}
.tribe-events-c-subscribe-dropdown__content {
	background: var(--c-bg-dark-alt);
	border: 1px solid var(--c-line-dark);
}
.tribe-events-c-subscribe-dropdown__list-item-link {
	font-family: var(--font-body);
	font-size: 0.9rem;
	color: var(--c-cream) !important;
	border: none;
}
.tribe-events-c-subscribe-dropdown__list-item-link:hover {
	color: var(--c-cream-soft) !important;
}

/* ---- Homepage newsletter form ----
   Built via JS (see assets/js/newsletter.js) rather than raw <form>/
   <input> markup in the Code module's content, because Divi's Visual
   Builder sanitizes that content on save and silently strips those tags
   — a real, confirmed constraint, not an arbitrary choice. Structure/
   design uniformized with the donation widget (ope-donate-widget, see
   post #1's homepage "Support" Code module): every row is full-width,
   fields split evenly via flex, same font/radius/spacing tokens. */
.ope-newsletter-form {
	display: flex;
	flex-direction: column;
	gap: var(--space-3);
	max-width: 480px;
}
.ope-newsletter-form__row {
	display: flex;
	width: 100%;
	gap: var(--space-3);
}
/* Bug reel trouve ici : un simple selecteur de classe (.ope-newsletter-
   form__input, specificite 0-1-0) perd TOUJOURS face au selecteur
   d'attribut global juste au-dessus (input[type="email"] etc.,
   specificite 0-1-1 - un selecteur de type + un attribut compte plus
   qu'une seule classe) - donc font-family/border-radius/padding/border
   redeclares ici ne servaient a rien (--c-line-dark et --c-line sont de
   toute facon le meme alias, doublon pur), ET color/background
   n'appliquaient JAMAIS malgre l'ordre dans le fichier : c'est le fond
   sombre + texte encre de la regle globale qui gagnait reellement -
   d'ou le "noir sur noir". Prefixer par "input." remonte la specificite
   a egalite (0-1-1) - l'ordre dans le fichier tranche alors correctement
   en faveur de cette regle, plus specifique au composant. Le champ
   garde donc le fond sombre herite de la regle globale (coherent avec
   la section Newsletter, elle-meme sur fond sombre) et seul le texte
   est explicitement repasse en clair. */
input.ope-newsletter-form__input {
	flex: 1 1 0;
	min-width: 0;
	width: 100%;
	color: var(--c-cream);
}
/* La regle de focus globale ci-dessus repasse en --c-ink (pensee pour
   le fond clair par defaut) - ce champ-ci a besoin de --c-cream comme
   en dehors du focus (fond sombre herite), donc override dedie. */
input.ope-newsletter-form__input:focus {
	color: var(--c-cream) !important;
}
.ope-newsletter-form__input::placeholder {
	color: var(--c-muted);
}
.ope-newsletter-form__submit {
	width: 100%;
	text-align: center;
}
.ope-newsletter-form__msg {
	margin: 0;
	font-size: 0.85rem;
	color: var(--c-cream-soft);
	opacity: 0.85;
	min-height: 1.2em;
}
@media (max-width: 480px) {
	.ope-newsletter-form__row {
		flex-direction: column;
	}
}

/* ==========================================================================
   Responsive — buttons only
   ========================================================================== */
@media (max-width: 767px) {
	.et_pb_button,
	button.button,
	input.button,
	a.button {
		padding: 0.85em 1.4em !important;
		font-size: 0.91rem !important;
		width:100%;
		text-align:center !important;
	}

	/* Divi genere lui-meme une echelle mobile pour les titres (h1:40px,
	   h2:34px, etc, dans son propre @media max-width:767px) mais elle perd
	   face au reglage desktop du Customizer (h1:56px, h2:48px...) des que
	   le titre est dans un contexte plus specifique -- notamment
	   .et_pb_title_container h1, le module Titre de page/article Divi
	   utilise partout sur le site. Cette regle Divi n'a pas de media query
	   (elle s'applique tout le temps) et gagne sur le tentative mobile de
	   Divi (0,1,1 de specificite contre 0,0,1) meme si celle-ci vient
	   apres dans la feuille de style. On reprend EXACTEMENT les valeurs
	   mobiles deja calculees par Divi (pas une nouvelle echelle inventee),
	   juste avec assez de specificite + !important pour qu'elles gagnent
	   reellement sur mobile. Valeurs desktop confirmees via le CSS reel
	   genere sur /fr/support/ : h1 56px, h2 48px, h3 40px, h4 33px,
	   h5 29px, h6 26px. */
	h1,
	h1.et_pb_contact_main_title,
	.et_pb_title_container h1 {
		font-size: 40px !important;
	}
	h2 {
		font-size: 34px !important;
	}
	h3 {
		font-size: 29px !important;
	}
	h4 {
		font-size: 24px !important;
	}
	h5 {
		font-size: 21px !important;
	}
	h6 {
		font-size: 18px !important;
	}
}

/* ==========================================================================
   Breadcrumb (module natif Divi 5, wp:divi/breadcrumbs)
   Deplace depuis woocommerce.css (2026-09-16) : ce fichier ne se charge que
   sur les pages WooCommerce (voir ope_is_woocommerce_page_context() dans
   functions.php), or ce module breadcrumb est utilise sur N'IMPORTE QUELLE
   page (ex: /support/, une page standard) -- la regle ne s'appliquait donc
   jamais en dehors du contexte boutique, d'ou l'incoherence visuelle
   remontee entre pages. theme.css charge partout, c'est le bon endroit.
   Classes confirmees via le HTML reel rendu (jamais devinees) : nav.et_pb_
   breadcrumbs--trail, liens/segments .et_pb_breadcrumbs--breadcrumb,
   accueil .et_pb_breadcrumbs--home, separateur .et_pb_breadcrumbs--separator,
   item courant (non lien) .et_pb_breadcrumbs--current.
   ========================================================================== */
.et_pb_breadcrumbs--trail {
	font-size: 0.82rem;
	color: var(--c-cream-soft);
	text-transform: uppercase;
	letter-spacing: 0.04em;
	margin-bottom: var(--space-5) !important;
}
.et_pb_breadcrumbs--breadcrumb,
.et_pb_breadcrumbs--separator,
.et_pb_breadcrumbs--current {
	color: var(--c-cream-soft);
	text-decoration: none;
}
a.et_pb_breadcrumbs--breadcrumb:hover {
	color: var(--c-cream);
}
