/* ==========================================================================
   Pages de localité (Aix-en-Provence, Marseille, Cannes...)
   Même famille que les pages prestations : fond noir, filets, or en accent.
   Ce fichier ne contient que ce qui est propre à une ville.

   La signature de ces pages est la ruche des communes. Sur la page d'accueil
   elle dit le territoire ; ici elle dit le voisinage, et chaque alvéole qui
   correspond à une ville où nous avons une page devient un lien. C'est le
   maillage entre localités, rendu visible plutôt que caché dans un pied de
   page.
   ========================================================================== */

/* ==========================================================================
   Les deux marchés de la ville
   Une ville n'a pas un seul visage. Aix, c'est la bastide le matin et le
   bureau du quartier d'affaires l'après-midi. Les deux blocs sont au même
   niveau : aucun n'est le principal.
   ========================================================================== */

.loc-marches { display: grid; gap: 0; }

.loc-m {
  position: relative;
  padding: clamp(28px, 4vh, 40px) 0;
  border-top: 1px solid var(--filet);
}

.loc-marches .loc-m:last-child { border-bottom: 1px solid var(--filet); }

/* Le filet d'or qui se déploie en tête du bloc quand il arrive à l'écran. */
.loc-m::before {
  content: "";
  position: absolute;
  inset-block-start: -1px;
  inset-inline-start: 0;
  width: 100%;
  height: 1px;
  background: var(--or);
  transform: scaleX(0);
  transform-origin: left center;
  transition: transform .9s var(--ez);
}

.loc-m.on::before { transform: scaleX(1); }

.loc-m-lbl {
  font-family: var(--font-b);
  font-size: 0.62rem;
  font-weight: 500;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--or);
}

.loc-m-n {
  margin-top: 14px;
  font-family: var(--font-h);
  font-size: clamp(1.3rem, 2.3vw, 1.75rem);
  font-weight: 400;
  line-height: 1.2;
  color: var(--blanc);
}

.loc-m-p {
  max-width: 58ch;
  margin-top: 14px;
  font-family: var(--font-b);
  font-size: 0.94rem;
  font-weight: 300;
  line-height: 1.78;
  color: var(--blanc-mut);
}

.loc-m-lnk {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  margin-top: 20px;
  padding-bottom: 5px;
  border-bottom: 1px solid var(--filet-fort);
  font-family: var(--font-b);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--blanc);
  transition: color .4s var(--ez), border-color .4s var(--ez);
}

.loc-m-lnk:hover { color: var(--or); border-color: var(--or); }
.loc-m-lnk span:last-child { transition: transform .4s var(--ez); }
.loc-m-lnk:hover span:last-child { transform: translate3d(5px, 0, 0); }

/* ==========================================================================
   Les quartiers
   Une preuve de connaissance du terrain, pas un remplissage de mots-clés :
   ne sont cités que des quartiers où nous intervenons réellement.
   ========================================================================== */

.loc-quartiers {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 0;
  margin-top: clamp(26px, 3.6vh, 36px);
}

.loc-q {
  display: inline-flex;
  align-items: center;
  font-family: var(--font-b);
  font-size: 0.86rem;
  font-weight: 300;
  color: var(--blanc-mut);
}

/* Le séparateur est une alvéole, pas une virgule. */
.loc-q:not(:last-child)::after {
  content: "";
  width: 7px;
  height: 8px;
  margin-inline: 14px;
  background: var(--or);
  opacity: 0.55;
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
}

/* ==========================================================================
   Les prestations disponibles sur place
   Huit liens, en lignes plutôt qu'en cartes : ce sont des portes, pas des
   produits à comparer.
   ========================================================================== */

.loc-presta { display: grid; gap: 0; }

.loc-p {
  display: grid;
  gap: 5px;
  padding: clamp(18px, 2.4vh, 24px) 0;
  border-top: 1px solid var(--filet);
  transition: border-color .4s var(--ez);
}

.loc-presta .loc-p:last-child { border-bottom: 1px solid var(--filet); }

.loc-p-n {
  display: flex;
  align-items: baseline;
  gap: 12px;
  font-family: var(--font-h);
  font-size: clamp(1.02rem, 1.5vw, 1.2rem);
  font-weight: 400;
  color: var(--blanc);
  transition: color .35s var(--ez);
}

.loc-p:hover .loc-p-n { color: var(--or); }

.loc-p-fl {
  font-size: 0.9em;
  opacity: 0;
  transform: translate3d(-6px, 0, 0);
  transition: opacity .35s var(--ez), transform .35s var(--ez);
}

.loc-p:hover .loc-p-fl,
.loc-p:focus-visible .loc-p-fl { opacity: 1; transform: translate3d(0, 0, 0); }

.loc-p-d {
  font-family: var(--font-b);
  font-size: 0.88rem;
  font-weight: 300;
  line-height: 1.7;
  color: var(--blanc-mut);
}

/* ==========================================================================
   La ruche des communes
   Même géométrie que celle de la page d'accueil : un rang fait 5,5 alvéoles
   de large, décalage compris, et la taille se déduit de la largeur
   disponible. Jamais d'unité `vw` brute, sinon la ruche déborde du
   conteneur entre 720 et 1220 px et pousse la page en défilement
   horizontal.
   ========================================================================== */

.loc-ruche {
  --ecart: 5px;
  --dispo: min(760px, calc(100vw - 2 * var(--gut)));
  /* Le rang le plus large fait quatre alvéoles et trois écarts. La taille se
     déduit de lui, sinon le rang dépasse le conteneur de quelques pixels sur
     téléphone et va mordre dans la gouttière. */
  --cell: clamp(72px, calc((var(--dispo) - 3 * var(--ecart)) / 4), 124px);
  --cell-h: calc(var(--cell) * 1.1547);

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

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

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

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

.loc-cell {
  position: relative;
  width: var(--cell);
  height: var(--cell-h);
  flex: none;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 3px;
  padding: 6px 8px;
  text-align: center;
  background: rgba(201, 163, 74, 0.15);
  /* Aucune bordure : un clip-path découpe aussi la bordure et n'en laisse
     que des fragments. Les états se distinguent par le remplissage. */
  clip-path: polygon(50% 0, 100% 25%, 100% 75%, 50% 100%, 0 75%, 0 25%);
  opacity: 0;
  transform: scale(0.84);
  transition: opacity .55s var(--ez), transform .55s var(--ez),
              background-color .3s var(--ez);
  transition-delay: calc(var(--t, 0) * 0.8s);
}

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

.loc-cell--vide { background: rgba(250, 250, 250, 0.045); }
.loc-cell--lien { background: rgba(201, 163, 74, 0.3); }
.loc-cell--lien:hover { background: rgba(201, 163, 74, 0.45); }

/* 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. */
.loc-cell--lien .loc-cell-n::after {
  content: ' \2192';
  color: var(--or);
  font-family: var(--font-b);
  font-size: 0.8em;
  font-weight: 600;
}

/* La ville de la page. Pleine et dorée : on est ici. */
.loc-cell--base { background: var(--or); }

.loc-cell-n {
  font-family: var(--font-h);
  font-size: clamp(0.7rem, 0.9vw, 0.84rem);
  font-weight: 500;
  line-height: 1.25;
  color: var(--blanc);
  text-wrap: balance;
}

.loc-cell--base .loc-cell-n { color: #0a0908; }

.loc-cell-s {
  font-family: var(--font-b);
  font-size: 0.56rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(10, 9, 8, 0.66);
}

.loc-cell--lien .loc-cell-s { color: var(--blanc-fnt); }

.loc-legende {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 28px;
  margin-top: clamp(26px, 3.4vh, 40px);
}

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

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

.loc-leg--base::before { background: var(--or); }
.loc-leg--lien::before { background: rgba(201, 163, 74, 0.3); }
.loc-leg--nue::before  { background: rgba(201, 163, 74, 0.15); }

.loc-ruche-note {
  max-width: 56ch;
  margin-top: clamp(26px, 3.6vh, 36px);
  font-family: var(--font-b);
  font-size: 0.86rem;
  font-weight: 300;
  line-height: 1.75;
  color: var(--blanc-fnt);
}

.loc-ruche-note a { color: var(--blanc-mut); border-bottom: 1px solid var(--filet-fort); }
.loc-ruche-note a:hover { color: var(--or); border-color: var(--or); }

/* ==========================================================================
   La respiration de la ruche
   Repris tel quel de la ruche de la page d'accueil. Une onde dorée traverse
   les alvéoles depuis la ville de la page vers l'extérieur, puis la ruche se
   tait le reste du cycle. Le retard de chaque alvéole est le même `--t` que
   celui de l'apparition : la lueur rayonne depuis la base, elle ne balaie
   pas bêtement de gauche à droite. `drop-shadow` épouse la découpe du
   clip-path, c'est donc le contour de l'hexagone qui s'allume et non un
   rectangle.
   ========================================================================== */

@keyframes loc-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.6)) brightness(1.16);
  }
}

.loc-ruche.on .loc-cell {
  /* Cycle de 3 s : l'onde traverse en 0,9 s, la ruche se tait le reste. */
  animation: loc-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.
   Sur fond noir, `brightness` seul ne suffit pas à relever un remplissage
   déjà sombre, d'où le halo plus large. */
@keyframes loc-lueur-forte {
  0%, 62%, 100% {
    filter: drop-shadow(0 0 0 rgba(201, 163, 74, 0)) brightness(1);
  }
  72%, 78% {
    filter: drop-shadow(0 0 22px rgba(201, 163, 74, 0.9)) brightness(1.3);
  }
}

.loc-ruche.on .loc-cell:not(.loc-cell--vide) { animation-name: loc-lueur-forte; }

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

/* ==========================================================================
   900 px : les marchés se partagent la largeur
   ========================================================================== */

@media (min-width: 900px) {
  .loc-marches {
    grid-template-columns: repeat(2, minmax(0, 1fr));
    column-gap: clamp(40px, 4.4vw, 72px);
  }

  /* Le filet du haut est porté par chaque bloc : sur deux colonnes, les deux
     filets s'alignent d'eux-mêmes et le dernier-enfant ne ferme plus qu'une
     colonne, donc on ferme les deux. */
  .loc-marches .loc-m { border-bottom: 1px solid var(--filet); }

  .loc-presta { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(40px, 4.4vw, 72px); }
  .loc-presta .loc-p:nth-last-child(2) { border-bottom: 1px solid var(--filet); }
}

/* ==========================================================================
   Sous 900 px : la ruche devient une suite de pastilles
   Même seuil et même traitement que sur la page d'accueil. Une onde de lueur
   sur une colonne de pastilles n'aurait plus de sens, et coûterait cher :
   elle s'arrête ici. Les alvéoles nues disparaissent, elles ne servaient
   qu'à dessiner la forme.
   ========================================================================== */

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

  .loc-rang { display: contents; }

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

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

  .loc-ruche.on .loc-cell { transform: none; animation: none; }

  .loc-cell-n { font-size: 0.82rem; }
  .loc-cell-s { display: inline; margin-left: 8px; }

  /* La légende de l'alvéole nue n'a plus d'objet une fois celle-ci masquée. */
  .loc-leg--nue { display: none; }
}

/* ==========================================================================
   Réduction des animations
   ========================================================================== */

@media (prefers-reduced-motion: reduce) {
  .loc-ruche.on .loc-cell { animation: none; }
  .loc-m::before { transform: scaleX(1); transition: none; }
  .loc-cell { opacity: 1; transform: none; transition: none; }
  .loc-p-fl { opacity: 1; transform: none; transition: none; }
  .loc-m-lnk span:last-child { transition: none; }
}
