/* Thème dark "bento" partagé par le builder (aperçu = surface d'édition) et
   la page publique — ce sont EXACTEMENT les mêmes classes des deux côtés,
   voir render-block.js. Le conteneur grille (.ulb-masonry, rempli par
   masonry.js) vit ici pour être partagé ; ce fichier régit aussi le bloc
   lui-même.

   Échelle de hauteurs remappée sur le style bento du mockup (sm/md/lg/xl/xxl)
   tout en gardant les MÊMES noms d'énum (compact/standard/large/xl/comfortable/auto). */

:root {
  --ulb-bg: #0a0a0e;
  --ulb-surface: #111117;
  --ulb-surface2: #18181f;
  --ulb-border: rgba(255, 255, 255, 0.07);
  --ulb-border2: rgba(255, 255, 255, 0.12);
  --ulb-text: #eceae4;
  --ulb-text-dim: #908c86;
  --ulb-text-muted: #56534e;
  --ulb-green: #c8f135;
  --ulb-green-glow: rgba(200, 241, 53, 0.15);
  --ulb-coral: #ff6b55;
  --ulb-emerald: #44e87a;
  --ulb-rose: #ff4d6d;
  --ulb-blue: #5bc4ff;
}

.ulb-block {
  /* Requis pour que tout enfant absolu du bloc (ex. .ulb-block-move-handle
     dans le builder, voir builder.css) se positionne par rapport a CE bloc
     et non a un ancetre positionne plus haut dans l'arbre (repere en
     generant un vrai rendu, pas a l'oeil) - sans effet visuel par
     lui-meme, .ulb-banner/.ulb-donation/etc restent le repere de leurs
     propres enfants absolus (icon-badge, pastille...) puisqu'ils sont plus
     proches dans l'arbre. */
  position: relative;
  border-radius: 1.125rem;
  overflow: hidden;
  background: var(--ulb-block-bg, rgba(255, 255, 255, 0.04));
  border: 1px solid var(--ulb-border);
  box-shadow: none;
  transition: transform 0.15s ease, border-color 0.15s ease;
}

/* --- Bento 2 colonnes (page publique + surface d'edition du builder, voir
   masonry.js) --- grille a unite de ligne FIXE (55px, voir ROW_PX dans
   masonry.js) : chaque bloc recoit un grid-row-end en "span N" ou N est le
   nombre d'unites de sa hauteur nommee (compact=1, standard=2,
   comfortable=3, large=4), pas une mesure DOM - le meme bloc occupe donc
   TOUJOURS la meme hauteur reelle qu'importe son contenu, ce qui permet a
   grid-auto-flow: dense de composer des formes bento asymetriques (ex. un
   bloc 1 colonne x 2 lignes a cote de 2 blocs 1 colonne x 1 ligne empiles),
   contrairement a un masonry classique en colonnes independantes. Seuls les
   blocs a hauteur "auto" (Newsletter) restent mesures dans le DOM. */
.ulb-masonry {
  display: grid;
  grid-template-columns: 1fr 1fr;
  grid-auto-rows: 55px;
  grid-auto-flow: row dense;
  /* Indispensable : par defaut (stretch), un bloc a hauteur "auto"
     (Newsletter) serait ecrase a la taille d'une seule piste de grille
     AVANT le calcul de son vrai grid-row-end (voir applySpan dans
     masonry.js, qui mesure sa hauteur juste apres insertion) - sa mesure
     deviendrait donc fausse et les blocs suivants le chevaucheraient. */
  align-items: start;
  /* Grille a pistes entieres (pas de pas fin en 1px) : le gap standard
     s'applique normalement entre pistes, y compris a l'interieur du span
     d'un item (stretch etire l'item sur ses N pistes + les gaps entre
     elles) - plus besoin d'absorber le gap dans une marge comme le faisait
     l'ancien masonry a pas fin. */
  row-gap: 8px;
  column-gap: 8px;
}
.ulb-masonry .ulb-w-full { grid-column: 1 / -1; }

/* --- Largeurs --- */
.ulb-w-full { width: 100%; }
.ulb-w-half { width: 100%; } /* la répartition réelle en 2 colonnes est gérée par masonry.js */

/* --- Hauteurs nommées (échelle bento) --- hauteur = N pistes de 55px + les
   (N-1) row-gaps de 8px qu'une piste de grille de N pistes couvre reellement
   (voir grid-row: span N, applique par masonry.js) : sans ce +8px par palier,
   un bloc qui span N pistes finit 8px plus court qu'une pile de N blocs
   1-ligne empiles dans la colonne voisine (repere en mesurant les rects DOM
   des deux, pas a l'oeil) - les deux doivent s'aligner pile pour un vrai
   bento (ex. un bloc 1 colonne x 2 lignes a cote de 2 blocs 1x1 empiles). */
.ulb-h-compact { height: 55px; }      /* 1 ligne */
.ulb-h-standard { height: 118px; }    /* 2 lignes (2×55 + 1×8) — aussi la forme fixe du carrousel/galerie */
.ulb-h-comfortable { height: 181px; } /* 3 lignes (3×55 + 2×8) */
.ulb-h-large { height: 244px; }       /* 4 lignes (4×55 + 3×8) */
.ulb-h-xl { height: 250px; }          /* legacy uniquement, plus proposée pour un nouveau bloc */
.ulb-h-auto { height: auto; }


/* --- Icône (Font Awesome ou emoji legacy) en médaillon flottant --- */
.ulb-icon-badge {
  position: absolute;
  top: 8px;
  left: 8px;
  z-index: 3;
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: rgba(0, 0, 0, 0.55);
  display: flex;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-size: 0.8rem;
}

/* --- Badge (pastille colorée) --- */
.ulb-badge {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 3;
  font-size: 0.6rem;
  font-weight: 700;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(0, 0, 0, 0.75);
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.5);
  white-space: nowrap;
}

/* --- Bouton d'action générique (Bannière/Carte/Promo) --- */
.ulb-cta {
  display: inline-block;
  width: fit-content;
  background: var(--ulb-green);
  color: #0a0a0e;
  font-weight: 600;
  font-size: 0.7rem;
  padding: 5px 12px;
  border-radius: 999px;
  border: none;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.25);
}

/* --- Lien / Liste : bandeau compact --- */
.ulb-list {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0 1rem;
  text-decoration: none;
  color: var(--ulb-text);
  height: 100%;
  transition: background 0.1s ease;
}
.ulb-list:hover { background: rgba(255, 255, 255, 0.03); }
.ulb-list__icon { font-size: 1.15rem; flex: none; color: var(--ulb-text-dim); display: flex; align-items: center; justify-content: center; }
.ulb-list__title { font-weight: 700; font-size: 0.9375rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }

/* --- Lien / Bannière ("hero") : image de fond pleine largeur + texte incrusté --- */
.ulb-banner {
  position: relative;
  display: block;
  text-decoration: none;
  color: #fff;
  width: 100%;
  height: 100%;
}
.ulb-banner__bg {
  position: absolute;
  inset: -12% -4%;
  background-size: cover;
  background-position: center;
  will-change: transform;
}
.ulb-banner__overlay {
  position: absolute;
  inset: 0;
  background: linear-gradient(to top, rgba(0, 0, 0, 0.75), rgba(0, 0, 0, 0.05) 60%);
}
.ulb-banner__text {
  position: relative;
  z-index: 1;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  align-items: flex-start;
  gap: 0.5rem;
  padding: 0.875rem 1rem;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
}
/* Quand une icone flotte en haut-gauche (.ulb-icon-badge : 26px, top/left
   8px, donc jusqu'a 34px du bord), le titre doit toujours commencer plus
   bas pour ne jamais s'en approcher - sinon collision visible sur les
   hauteurs compact/standard (repere en generant un vrai rendu produit pour
   la page d'accueil marketing, jamais couvert par un test avant). Un
   contenu tres charge (icone + titre + sous-titre + CTA) sur une hauteur
   "standard" reste serre malgre tout : c'est une limite de place assumee,
   pas un bug - a cette hauteur le champ sous-titre est deja optionnel. */
.ulb-banner--has-icon .ulb-banner__text { padding-top: 2.25rem; }
.ulb-banner__title { font-weight: 700; font-size: 1rem; line-height: 1.2; }
.ulb-banner__subtitle { font-size: 0.8125rem; opacity: 0.85; margin-top: 0.125rem; }
/* Le CTA est impose au centre (jamais aligne avec le titre/sous-titre a
   gauche) : c'est l'element le plus bas du template visuel unique. */
.ulb-banner__text .ulb-cta { align-self: center; }
/* Bloc sans image, couleur automatique (voir AUTO_COLOR_PALETTE dans
   render-block.js) : le degrade sombre et l'ombre portee de .ulb-banner__text
   n'ont de sens que pour garantir la lisibilité d'un texte blanc sur une
   photo - sur un aplat de couleur pleine ils l'assombriraient inutilement et
   masqueraient la teinte choisie. */
.ulb-banner--auto-color { color: var(--ulb-banner-auto-fg, #0a0a0e); }
.ulb-banner--auto-color .ulb-banner__overlay { background: none; }
.ulb-banner--auto-color .ulb-banner__text { text-shadow: none; }

/* --- Don --- */
.ulb-donation {
  padding: 1rem;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.5rem;
  height: 100%;
  color: var(--ulb-text);
}
.ulb-donation__title { font-weight: 700; font-size: 0.9375rem; }
.ulb-donation__subtitle { font-size: 0.8125rem; color: var(--ulb-text-dim); }
.ulb-donation__amounts { display: flex; gap: 0.375rem; flex-wrap: wrap; }
.ulb-donation__amount { border: 1px solid var(--ulb-border2); border-radius: 999px; padding: 0.25rem 0.75rem; font-size: 0.8125rem; background: var(--ulb-surface2); color: var(--ulb-text); cursor: pointer; }
.ulb-donation__cta { margin-top: auto; background: var(--ulb-coral); color: #fff; border-radius: 0.5rem; padding: 0.5rem; font-weight: 600; font-size: 0.875rem; text-align: center; cursor: pointer; border: none; }
.ulb-donation__recurring { font-size: 0.75rem; display: flex; align-items: center; gap: 0.375rem; color: var(--ulb-text-dim); }

/* --- Newsletter --- */
.ulb-newsletter { padding: 1.25rem; text-align: center; color: var(--ulb-text); }
.ulb-newsletter__form { display: flex; gap: 0.5rem; margin-top: 0.625rem; }
.ulb-newsletter__input { flex: 1; border: 1px solid var(--ulb-border2); border-radius: 999px; padding: 0.5rem 0.875rem; font-size: 0.875rem; background: var(--ulb-surface2); color: var(--ulb-text); }
.ulb-newsletter__submit { background: var(--ulb-green); color: #0a0a0e; border-radius: 999px; padding: 0.5rem 1rem; font-weight: 700; font-size: 0.875rem; border: none; cursor: pointer; }

/* --- Galerie : mode "images" (carrousel a defilement continu, voir
   renderGalleryImages dans render-block.js) --- 2.5 images visibles par
   defaut (flex-basis ~38%), PAS de scroll-snap ici : l'auto-scroll doit
   glisser en continu, un snap se battrait avec le scrollLeft anime en JS. */
.ulb-gallery { display: flex; gap: 0.5rem; overflow-x: auto; padding: 0.75rem; }
.ulb-gallery__item { flex: 0 0 38%; border-radius: 0.75rem; overflow: hidden; aspect-ratio: 4 / 3; cursor: pointer; }
.ulb-gallery__item img { width: 100%; height: 100%; object-fit: cover; display: block; }

/* --- Galerie : mode "products" (cartes produit/vidéo) --- carte HORIZONTALE
   (miniature carrée + texte a cote), pas verticale : la Galerie a desormais
   une forme fixe et non modifiable (pleine largeur x standard = ~118px reels,
   voir block-sizing.ts isLargeShape/ruleFor) - une carte verticale classique
   (image 16:9 + titre + sous-titre + prix + CTA empiles) deborderait tres
   largement de cette hauteur et se ferait tronquer par overflow:hidden
   (repere en generant un vrai rendu produit, pas a l'oeil). Sous-titre et
   CTA textuel disparaissent a cette taille (meme logique que le "cramped" de
   render-block.js pour les autres types) : la carte entiere reste cliquable,
   image + titre + prix suffisent a comprendre l'offre. */
.ulb-gallery--products { padding: 0.75rem; gap: 0.75rem; scroll-snap-type: x mandatory; }
.ulb-gallery__card {
  flex: 0 0 190px;
  scroll-snap-align: start;
  display: flex;
  align-items: center;
  gap: 0.625rem;
  background: var(--ulb-surface2);
  border: 1px solid var(--ulb-border);
  border-radius: 0.875rem;
  overflow: hidden;
  text-decoration: none;
  color: var(--ulb-text);
  padding: 0.5rem;
}
.ulb-gallery__card-img { width: auto; height: 100%; aspect-ratio: 1 / 1; flex-shrink: 0; border-radius: 0.625rem; background-size: cover; background-position: center; background-color: var(--ulb-surface); }
.ulb-gallery__card-img--empty { display: flex; align-items: center; justify-content: center; font-size: 1.1rem; color: var(--ulb-text-dim); }

/* --- Repere du point focal (builder uniquement, voir placeFocalMarker
   dans render-block.js/render-header.js) : sans lui, rien n'indique qu'une
   image est cliquable ni ou est passe le point choisi. --- */
.ulb-focal-marker {
  position: absolute;
  width: 22px;
  height: 22px;
  border-radius: 999px;
  transform: translate(-50%, -50%);
  background: var(--ulb-green, #c8f135);
  border: 2px solid #0a0a0e;
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.9), 0 1px 4px rgba(0, 0, 0, 0.5);
  pointer-events: none;
  z-index: 5;
}

/* --- Agrandissement plein ecran d'une image de galerie au clic --- */
.ulb-lightbox { position: fixed; inset: 0; background: rgba(0,0,0,.85); display: flex; align-items: center; justify-content: center; padding: 24px; z-index: 9999; opacity: 0; pointer-events: none; transition: opacity .15s ease; }
.ulb-lightbox--open { opacity: 1; pointer-events: auto; }
.ulb-lightbox img { max-width: 100%; max-height: 100%; border-radius: 12px; object-fit: contain; cursor: zoom-out; }
.ulb-gallery__card-body { padding: 0; min-width: 0; } /* min-width:0 indispensable dans un flex row pour que le titre puisse tronquer au lieu de forcer la carte a s'elargir */
.ulb-gallery__card-title { font-weight: 600; font-size: 0.8rem; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.ulb-gallery__card-subtitle { display: none; } /* pas de place a cote d'une miniature carree sur ~94px de haut */
.ulb-gallery__card-price { font-size: 0.7rem; font-weight: 700; color: var(--ulb-green); margin-top: 0.25rem; }
.ulb-gallery__card-cta { display: none; } /* la carte entiere est deja cliquable (voir renderGalleryProducts) */

/* --- Promo (offre à durée limitée) --- */
.ulb-promo {
  position: relative;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: 0.5rem;
  padding: 1rem 1.25rem;
  color: #fff;
  background: linear-gradient(135deg, var(--ulb-coral), var(--ulb-rose));
}
.ulb-promo__icon { font-size: 1.1rem; opacity: 0.9; }
.ulb-promo__title { font-weight: 800; font-size: 1.0625rem; }
.ulb-promo__subtitle { font-size: 0.8rem; opacity: 0.9; }
.ulb-promo__timer { display: flex; gap: 6px; font-variant-numeric: tabular-nums; }
.ulb-promo__unit { background: rgba(0, 0, 0, 0.2); border-radius: 8px; padding: 4px 6px; text-align: center; min-width: 34px; }
.ulb-promo__unit b { display: block; font-size: 0.9rem; font-weight: 800; line-height: 1; }
.ulb-promo__unit span { font-size: 0.55rem; opacity: 0.8; text-transform: uppercase; }
.ulb-promo__cta { margin-top: 0.25rem; background: #fff; color: #111; }
