/* ==========================================================================
   Zones d'intervention — axe de distance
   Les villes ne sont pas rangées dans une grille : elles sont posées sur une
   ligne, à leur distance réelle d'Aix-en-Provence. L'espace entre deux noms
   est une information, pas une gouttière.
   La ligne se trace quand la section entre à l'écran, et les repères
   s'allument au passage. Le déclencheur est la classe .on déjà posée par
   l'observateur de main.js sur les éléments .rv.
   ========================================================================== */

.zones2 {
  --creme: #f4f0e6;
  --creme-haut: #faf7f0;
  --encre: #1c1408;
  --encre-mut: #4a3c1c;
  --encre-fnt: #6a6040;
  --or: #8a6818;
  --filet: rgba(100, 80, 20, 0.2);
  --gut: clamp(22px, 5vw, 76px);
  --ez: cubic-bezier(.4, 0, .2, 1);

  position: relative;
  z-index: 2;
  background: var(--creme);
  padding: clamp(72px, 10vh, 130px) var(--gut);
}

.zones2-inner {
  width: min(1220px, 100%);
  margin-inline: auto;
}

.zones2 .recit-eyebrow { color: var(--or); }
.zones2 .recit-eyebrow::before { background: var(--or); }

.zones2-h2 {
  max-width: 20ch;
  margin-top: 24px;
  font-family: var(--font-h);
  font-size: clamp(1.7rem, 3.2vw, 2.5rem);
  font-weight: 500;
  line-height: 1.14;
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--encre);
}

.zones2-h2 em { font-style: italic; color: var(--or); }

.zones2-lead {
  max-width: 50ch;
  margin-top: 20px;
  font-family: var(--font-b);
  font-size: 1rem;
  font-weight: 300;
  line-height: 1.8;
  color: var(--encre-mut);
}

/* ---- L'axe --------------------------------------------------------------- */

.zones2-axe {
  position: relative;
  margin-top: clamp(64px, 9vh, 120px);
  height: 190px;
}

/* La ligne, tracée de gauche à droite à l'entrée dans l'écran. */
.zones2-ligne {
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 1px;
  background: var(--filet);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform 1.4s var(--ez);
}

.zones2-axe.on .zones2-ligne { transform: scaleX(1); }

.zones2-ville {
  position: absolute;
  top: 50%;
  left: var(--x);
  transform: translate(-50%, -50%);
  display: grid;
  justify-items: center;
  width: max-content;
  opacity: 0;
  transition: opacity .5s var(--ez);
  transition-delay: calc(var(--t) * 1.15s);
}

.zones2-axe.on .zones2-ville { opacity: 1; }

/* Alternance haut et bas : deux noms voisins ne se marchent jamais dessus,
   et la ligne reste lisible au milieu. */
.zones2-ville--haut { grid-template-rows: auto auto 1fr; }

.zones2-marque {
  grid-row: 2;
  width: 13px;
  height: 14px;
  /* Alveole pleine et non bordee : un clip-path decoupe aussi la bordure,
     l'hexagone en contour se reduit a deux traits. */
  background: rgba(138, 104, 24, 0.34);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  transform: scale(0.6);
  transition: transform .5s var(--ez), background-color .3s var(--ez);
  transition-delay: calc(var(--t) * 1.15s);
}

/* L'alvéole pleine marque la base, les creuses marquent les zones servies. */
.zones2-ville--base .zones2-marque {
  background: var(--or);
  width: 17px;
  height: 18px;
}

.zones2-axe.on .zones2-marque { transform: scale(1); }

.zones2-txt {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  display: grid;
  justify-items: center;
  gap: 4px;
  width: max-content;
}

.zones2-ville--haut .zones2-txt { bottom: calc(50% + 18px); }
.zones2-ville--bas .zones2-txt { top: calc(50% + 18px); }

/* Un lien doit ressembler a un lien : filet permanent sous le nom, chevron
   qui avance au survol. Sans ca, l'axe se lit comme une infographie inerte. */
.zones2-nom {
  position: relative;
  display: inline-flex;
  align-items: baseline;
  gap: 7px;
  padding-bottom: 3px;
  font-family: var(--font-h);
  font-size: clamp(0.95rem, 1.3vw, 1.15rem);
  font-weight: 500;
  letter-spacing: 0.02em;
  text-transform: none;
  color: var(--encre);
  transition: color .3s var(--ez);
}

.zones2-km {
  font-family: var(--font-b);
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--encre-fnt);
  font-variant-numeric: tabular-nums;
}

.zones2-nom::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  height: 1px;
  background: var(--or);
  opacity: 0.35;
  transform: scaleX(1);
  transform-origin: left center;
  transition: opacity .3s var(--ez);
}

.zones2-fleche {
  font-family: var(--font-b);
  font-size: 0.78em;
  font-weight: 600;
  color: var(--or);
  transform: translateX(0);
  transition: transform .35s var(--ez);
}

.zones2-ville:hover .zones2-nom,
.zones2-ville:focus-visible .zones2-nom { color: var(--or); }

.zones2-ville:hover .zones2-nom::after,
.zones2-ville:focus-visible .zones2-nom::after { opacity: 1; }

.zones2-ville:hover .zones2-fleche,
.zones2-ville:focus-visible .zones2-fleche { transform: translateX(4px); }

/* Zone de clic confortable, sans agrandir la boite qui sert au placement. */
.zones2-ville::before {
  content: '';
  position: absolute;
  inset: -14px -18px;
}

.zones2-ville:hover .zones2-marque,
.zones2-ville:focus-visible .zones2-marque {
  background: var(--or);
  transform: scale(1.35);
  transition-delay: 0s;
}

/* Le premier et le dernier ne débordent pas de la section. */
.zones2-ville:first-of-type { transform: translate(0, -50%); }
.zones2-ville:first-of-type .zones2-txt { left: 0; transform: none; justify-items: start; }
.zones2-ville:last-of-type { transform: translate(-100%, -50%); }
.zones2-ville:last-of-type .zones2-txt { left: auto; right: 0; transform: none; justify-items: end; }

.zones2-clic {
  margin-top: clamp(28px, 4vh, 44px);
  font-family: var(--font-b);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--or);
}

.zones2-note {
  margin-top: 14px;
  font-family: var(--font-b);
  font-size: 0.8rem;
  font-weight: 300;
  line-height: 1.7;
  color: var(--encre-fnt);
}

.zones2-note a {
  color: var(--or);
  border-bottom: 1px solid currentColor;
  padding-bottom: 1px;
}

/* ==========================================================================
   Sous 860 px : l'axe bascule à la verticale. Sur un téléphone c'est même
   plus lisible, on lit la liste de haut en bas comme un itinéraire.
   ========================================================================== */

@media (max-width: 859px) {
  .zones2-axe {
    height: auto;
    min-height: 340px;
    padding-left: 34px;
  }

  .zones2-ligne {
    left: 6px;
    right: auto;
    top: 10px;
    bottom: 10px;
    width: 1px;
    height: auto;
    transform: scaleY(0);
    transform-origin: top center;
  }

  .zones2-axe.on .zones2-ligne { transform: scaleY(1); }

  .zones2-ville,
  .zones2-ville:first-of-type,
  .zones2-ville:last-of-type {
    position: relative;
    top: auto;
    left: auto;
    transform: none;
    display: flex;
    align-items: center;
    gap: 16px;
    width: 100%;
    margin-left: -34px;
    padding-block: clamp(14px, 2.4vh, 22px);
  }

  .zones2-marque { flex: none; }
  .zones2-ville::before { inset: 0; }

  .zones2-txt,
  .zones2-ville:first-of-type .zones2-txt,
  .zones2-ville:last-of-type .zones2-txt {
    position: relative;
    left: auto;
    right: auto;
    top: auto;
    bottom: auto;
    transform: none;
    justify-items: start;
    gap: 2px;
  }
}

/* ==========================================================================
   Animations réduites : sans transition, tout doit être visible d'emblée.
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .zones2-ligne { transform: none; }
  .zones2-ville { opacity: 1; }
  .zones2-marque { transform: scale(1); }
  .zones2-ligne,
  .zones2-ville,
  .zones2-marque { transition: none; }
}

/* ==========================================================================
   La ruche — le territoire, pas une liste de villes
   Un axe de distance se lisait « ces cinq villes et rien entre ». Une ruche
   dit l'inverse : une surface continue, faite de cellules jointives. Les
   alvéoles nommées sont des repères, les alvéoles nues sont le reste du
   territoire. Et la forme vient de la marque, pas d'un catalogue.
   Les cellules s'allument depuis Aix vers l'extérieur : c'est le rayonnement
   depuis la base, rendu par le délai et non par la position.
   ========================================================================== */

.ruche {
  /* Un rang fait 8,5 alvéoles de large, décalage des rangs pairs compris.
     La taille se déduit donc de la largeur disponible, jamais d'un vw brut :
     avec clamp(92px, 11.5vw, 138px) la ruche mesurait 1090 px dans un
     conteneur de 922 et poussait toute la page en défilement horizontal
     entre 720 et 1220 px de large. */
  --ecart: 5px;
  --dispo: min(1220px, calc(100vw - 2 * clamp(22px, 5vw, 76px)));
  --cell: clamp(88px, calc(var(--dispo) / 8.7 - var(--ecart)), 138px);
  --cell-h: calc(var(--cell) * 1.1547);

  margin-top: clamp(48px, 7vh, 88px);
  display: grid;
  justify-items: center;
}

.ruche-rang {
  display: flex;
  gap: var(--ecart);
  margin-top: calc(var(--cell-h) * -0.25 + var(--ecart));
}

.ruche-rang:first-child { margin-top: 0; }

/* Un rang sur deux est décalé d'une demi-alvéole : c'est ce décalage qui
   rend la surface continue au lieu d'une grille carrée. */
.ruche-rang:nth-child(even) {
  margin-left: calc(var(--cell) * 0.5 + var(--ecart) * 0.5);
}

.ruche-cell {
  position: relative;
  width: var(--cell);
  height: var(--cell-h);
  flex: none;
  /* Flex et non grid : avec deux enfants, place-items les repartit sur deux
     rangees et le sous-titre tombe au bas de l'alveole. */
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 4px;
  padding: 6px 8px;
  text-align: center;
  background: rgba(138, 104, 24, 0.06);
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  opacity: 0;
  transform: scale(0.82);
  transition: opacity .55s var(--ez), transform .55s var(--ez),
              background-color .3s var(--ez);
  transition-delay: calc(var(--t, 0) * 0.9s);
}

.zones2-ruche.on .ruche-cell {
  opacity: 1;
  transform: scale(1);
}

/* Trois états, trois remplissages. Aucune bordure : un clip-path découpe
   aussi la bordure et n'en laisse que des fragments. */
.ruche-cell--nom { background: rgba(138, 104, 24, 0.13); }
.ruche-cell--lien { background: rgba(138, 104, 24, 0.2); }

.ruche-cell--base {
  background: var(--or);
  color: var(--creme-haut);
}

.ruche-nom {
  font-family: var(--font-h);
  font-size: clamp(0.72rem, 0.92vw, 0.86rem);
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: 0.01em;
  text-transform: none;
  color: var(--encre);
  text-wrap: balance;
}

.ruche-cell--base .ruche-nom {
  color: var(--creme-haut);
  font-size: clamp(0.76rem, 1vw, 0.94rem);
}

.ruche-sous {
  display: block;
  margin-top: 3px;
  font-family: var(--font-b);
  font-size: 0.56rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: rgba(250, 247, 240, 0.8);
}

/* Les alvéoles cliquables portent la flèche : c'est le seul signal qui
   distingue une ville avec sa page d'une ville simplement desservie. */
.ruche-cell--lien .ruche-nom::after {
  content: ' \2192';
  color: var(--or);
  font-family: var(--font-b);
  font-size: 0.8em;
  font-weight: 600;
}

a.ruche-cell:hover,
a.ruche-cell:focus-visible {
  background: rgba(138, 104, 24, 0.34);
  transition-delay: 0s;
}

a.ruche-cell--base:hover,
a.ruche-cell--base:focus-visible { background: #6f5312; }

/* ---- Légende ------------------------------------------------------------- */

.ruche-legende {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  margin-top: clamp(32px, 4vh, 48px);
}

.ruche-leg {
  display: flex;
  align-items: center;
  gap: 10px;
  font-family: var(--font-b);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--encre-fnt);
}

.ruche-leg::before {
  content: '';
  width: 13px;
  height: 15px;
  flex: none;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

.ruche-leg--base::before { background: var(--or); }
.ruche-leg--lien::before { background: rgba(138, 104, 24, 0.2); }
.ruche-leg--nue::before  { background: rgba(138, 104, 24, 0.06); }

@media (max-width: 600px) {
  .ruche { --cell: clamp(74px, 21vw, 96px); --ecart: 4px; }
  .ruche-nom { font-size: 0.66rem; letter-spacing: 0; }
  .ruche-sous { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  .ruche-cell { opacity: 1; transform: none; transition: none; }
}

/* ==========================================================================
   Sous 900 px, la ruche ne tient plus : huit alvéoles de front tomberaient
   sous 88 px et les noms de communes s'y briseraient en trois lignes. Les
   rangs passent en display: contents, les alvéoles deviennent des pastilles
   qui s'enchaînent, et les alvéoles nues disparaissent. Même balisage,
   aucune duplication.
   ========================================================================== */

@media (max-width: 899px) {
  .ruche {
    display: flex;
    flex-wrap: wrap;
    gap: 8px;
    justify-content: flex-start;
  }

  .ruche-rang { display: contents; }

  .ruche-cell--vide { display: none; }

  .ruche-cell {
    width: auto;
    height: auto;
    padding: 11px 16px;
    clip-path: none;
    border-radius: 2px;
    transform: none;
  }

  .zones2-ruche.on .ruche-cell { transform: none; }

  .ruche-nom { font-size: 0.82rem; }
  .ruche-sous { display: inline; margin-left: 8px; margin-top: 0; }

  /* Les alveoles nues sont masquees ici : leur legende n'a plus d'objet. */
  .ruche-leg--nue { display: none; }
}

/* ==========================================================================
   La respiration de la ruche
   Une onde dorée traverse les alvéoles depuis Aix vers l'extérieur, puis
   la ruche se tait pendant sept secondes. Le retard de chaque cellule est
   le meme --t que celui de l'apparition : la lueur suit le rayonnement
   depuis la base, elle ne balaie pas bêtement de gauche à droite.
   drop-shadow épouse la découpe du clip-path : c'est le contour de
   l'hexagone qui s'allume, pas un rectangle.
   ========================================================================== */

@keyframes ruche-lueur {
  0%, 62%, 100% {
    filter: drop-shadow(0 0 0 rgba(201, 163, 74, 0)) brightness(1);
  }
  72%, 78% {
    filter: drop-shadow(0 0 14px rgba(201, 163, 74, 0.75)) brightness(1.09);
  }
}

.zones2-ruche.on .ruche-cell {
  /* Cycle de 3 s : l'onde traverse en 0,9 s, la ruche se tait le reste. */
  animation: ruche-lueur 3s var(--ez) infinite;
  animation-delay: calc(var(--t, 0) * 0.9s);
}

/* Les alvéoles nommées brillent plus fort : l'onde souligne les repères. */
@keyframes ruche-lueur-forte {
  0%, 62%, 100% {
    filter: drop-shadow(0 0 0 rgba(201, 163, 74, 0)) brightness(1);
  }
  72%, 78% {
    /* brightness releve le remplissage de l'alveole elle-meme : sans lui,
       seul le halo bouge et la lueur se voit a peine sur le creme. */
    filter: drop-shadow(0 0 22px rgba(201, 163, 74, 1)) brightness(1.22);
  }
}

.zones2-ruche.on .ruche-cell--nom,
.zones2-ruche.on .ruche-cell--lien,
.zones2-ruche.on .ruche-cell--base {
  animation-name: ruche-lueur-forte;
}

/* Au survol, la lueur s'arrête : on ne clignote pas sous le curseur. */
a.ruche-cell:hover,
a.ruche-cell:focus-visible {
  animation-play-state: paused;
  filter: drop-shadow(0 0 14px rgba(201, 163, 74, 0.7));
}

/* Sur téléphone et tablette les alvéoles deviennent des pastilles : une onde
   de lueur sur vingt pastilles alignées n'aurait plus de sens, et coûterait
   cher. Même seuil que le passage en pastilles, 900 px. */
@media (max-width: 899px) {
  .zones2-ruche.on .ruche-cell { animation: none; }
}

@media (prefers-reduced-motion: reduce) {
  .zones2-ruche.on .ruche-cell { animation: none; }
}
