/*
  Charte graphique Metpark.
  Les couleurs "de marque" (primary, secondary, grey...) sont fixes.
  Les fonds (--bg, --surface...) sont des tons indépendants de la charte :
  le mode sombre n'utilise PAS "dark" (#212121) comme fond, le mode clair
  n'utilise pas non plus "white"/"light" tels quels comme fond de page.
  => on peut piloter le thème simplement en (dé)posant la classe .dark sur <html>.
*/

:root {
  /* Fonds indépendants de la charte */
  --bg: #F4F5F7;
  --surface: #FFFFFF;
  --surface-2: #ECEEF1;
  --border: #E1E4E9;

  /* Textes */
  --text: #152A3B;
  --text-muted: #657C8F;

  /* Overlays */
  --overlay: rgba(21, 42, 59, 0.55);
  --scrim: rgba(21, 42, 59, 0.06);

  --shadow-color: rgba(21, 42, 59, 0.12);

  /* Dégradé clair au-dessus de la carte, sous le header de /parkings.html */
  --map-scrim-from: rgba(244, 245, 247, 0.92);
  --map-scrim-via: rgba(244, 245, 247, 0.55);

  /* Piste "off" du switch : plus contrastée que --border, qui se confond avec les
     fonds de carte (--surface/--surface-2) sur lesquels le switch est posé.
     ~3:1 face à --surface (blanc). */
  --switch-off: #8D96A1;
}

:root.dark {
  /* Fond sombre indépendant de la charte (≠ #212121) */
  --bg: #10151C;
  --surface: #1A212B;
  --surface-2: #222B37;
  --border: #2b3542;

  --text: #EEEEEF;
  --text-muted: #9AACC0;

  --overlay: rgba(0, 0, 0, 0.55);
  --scrim: rgba(255, 255, 255, 0.06);

  --shadow-color: rgba(0, 0, 0, 0.4);

  /* Dégradé foncé au-dessus de la carte, sous le header de /parkings.html */
  --map-scrim-from: rgba(8, 11, 15, 0.92);
  --map-scrim-via: rgba(8, 11, 15, 0.55);

  /* ~3:1 face à --surface/--surface-2 (couleur pleine : une valeur translucide se
     confond avec des fonds sombres proches, contrairement au mode clair). */
  --switch-off: #5C6B7D;
}

* {
  -webkit-tap-highlight-color: transparent;
}

html, body {
  background: var(--bg);
  color: var(--text);
}

body {
  font-family: "Roboto", "Helvetica Neue", Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
}

.font-title {
  font-family: "Montserrat", "Helvetica Neue", Arial, sans-serif;
}

@font-face {
  font-family: "Arsilon";
  src: url("../assets/fonts/Arsilon/Dhan Studio - Arsilon.otf") format("opentype");
  font-weight: normal;
  font-style: normal;
  font-display: swap;
}

/* Police maison Icomoon (cf. /c/Code/metpark/assets/fonts/icomoon.ttf), utilisée
   uniquement pour les pictos de type de véhicule (cf. CLAUDE.md) : les autres icônes
   sont des Heroicons en SVG inline (cf. js/icons.js). La classe pose la police, le
   glyphe est le contenu (entité HTML "&#xe9xx;" reprenant les codepoints du projet
   de référence). */
@font-face {
  font-family: "icomoon";
  src: url("../assets/fonts/icomoon.ttf") format("truetype");
  font-weight: normal;
  font-style: normal;
  font-display: block;
}
.icon-vehicle {
  font-family: "icomoon";
  font-style: normal;
  font-weight: normal;
  display: inline-flex;
  line-height: 1;
  /* Le glyphe Icomoon a une marge interne importante (déjà compensée par un facteur
     1.6 côté app mobile, cf. Icon.tsx du projet de référence) : sans quoi il paraît
     plus petit que les icônes Material à taille égale. */
  transform: scale(1.6);
}

/* Case de sélection icône + libellé, réutilisée partout où on choisit une option
   visuelle dans une grille (Profil "Mon déplacement favori", Parkings "Type de
   véhicule" et "Points d'intérêt"). Cf. js/icon-option.js pour le rendu/câblage. */
.icon-option {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 0.75rem;
  padding: 0.5rem;
  border-radius: 1rem;
  background: var(--bg);
  color: var(--text);
  transition: background-color 0.2s ease, color 0.2s ease;
}
.icon-option[data-active="true"] {
  background: #FF471A;
  color: #fff;
}

/* Rail horizontal pour les grilles ".icon-option" : évite les grilles à colonnes
   fixes qui laissent une rangée orpheline quand le nombre d'options n'est pas un
   multiple du nombre de colonnes. Le fondu sur les bords utilise un mask-image
   (plutôt qu'un dégradé de couleur superposé) pour rester correct quel que soit
   le fond (surface/bg, dark/light).
   Le fondu et les flèches (cf. .icon-option-scroll-arrow) ne sont affichés que du
   côté où il reste du contenu à défiler ; l'état est posé par js/scroll-arrows.js
   sous forme d'attributs data-at-start/data-at-end sur le wrapper. */
.icon-option-scroll-wrap {
  position: relative;
}
.icon-option-scroll {
  display: flex;
  gap: 0.75rem;
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  padding-inline: 0.25rem;
  margin-inline: -0.25rem;
}
.icon-option-scroll-wrap[data-at-start="false"] .icon-option-scroll {
  mask-image: linear-gradient(to right, transparent 0, black 1.25rem, black 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 1.25rem, black 100%);
}
.icon-option-scroll-wrap[data-at-end="false"] .icon-option-scroll {
  mask-image: linear-gradient(to left, transparent 0, black 1.25rem, black 100%);
  -webkit-mask-image: linear-gradient(to left, transparent 0, black 1.25rem, black 100%);
}
.icon-option-scroll-wrap[data-at-start="false"][data-at-end="false"] .icon-option-scroll {
  mask-image: linear-gradient(to right, transparent 0, black 1.25rem, black calc(100% - 1.25rem), transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, black 1.25rem, black calc(100% - 1.25rem), transparent 100%);
}

.icon-option-scroll-arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 1.75rem;
  height: 1.75rem;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--surface);
  color: var(--text);
  box-shadow: 0 1px 4px var(--shadow-color);
  z-index: 2;
}
.icon-option-scroll-arrow--start {
  left: -0.25rem;
}
.icon-option-scroll-arrow--end {
  right: -0.25rem;
}
.icon-option-scroll-wrap[data-at-start="true"] .icon-option-scroll-arrow--start,
.icon-option-scroll-wrap[data-at-end="true"] .icon-option-scroll-arrow--end {
  display: none;
}
.icon-option-scroll > .icon-option {
  flex: 0 0 4.75rem;
}

.emphasis {
  font-family: "Arsilon", "Montserrat", "Helvetica Neue", Arial, sans-serif;
  font-weight: normal;
  font-size: 1.3em;
}

/* Cache la scrollbar des rails horizontaux tout en gardant le scroll tactile */
.no-scrollbar::-webkit-scrollbar { display: none; }
.no-scrollbar { scrollbar-width: none; -ms-overflow-style: none; }

.snap-x-cards {
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 1.25rem;
}
.snap-x-cards > * {
  scroll-snap-align: start;
}

/* Placeholder animé du champ de recherche (Accueil) */
.search-placeholder-word {
  display: inline-block;
}

/* Bottom sheet (page Parkings) */
.sheet {
  transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1);
  box-shadow: 0 -8px 30px var(--shadow-color);
}
.sheet-handle {
  width: 40px;
  height: 5px;
  border-radius: 999px;
  background: var(--border);
}

/* Panneau de filtres (page Parkings) : replié par défaut, glisse du haut vers le bas
   à l'ouverture (et inversement à la fermeture). Le wrapper anime la hauteur
   (grid-template-rows, comme .accordion-panel) pendant que le panneau lui-même
   glisse et s'estompe pour renforcer l'effet de descente. */
.filters-panel-collapse {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.32s cubic-bezier(0.32, 0.72, 0, 1);
}
.filters-panel-collapse > div {
  overflow: hidden;
  min-height: 0;
}
.filters-panel-collapse #filters-panel {
  transform: translateY(-16px);
  opacity: 0;
  transition: transform 0.32s cubic-bezier(0.32, 0.72, 0, 1), opacity 0.22s ease;
}
.filters-panel-collapse.is-open {
  grid-template-rows: 1fr;
}
.filters-panel-collapse.is-open #filters-panel {
  transform: translateY(0);
  opacity: 1;
}

/* Header qui se solidifie au scroll (Accueil / Détail parking) */
.header-solidify {
  transition: background-color 0.25s ease, box-shadow 0.25s ease, backdrop-filter 0.25s ease;
}

/* Effet paralax simple sur la photo d'un parking */
.parallax-media {
  will-change: transform;
}

/* Fondu bas de carte / photo */
.fade-bottom {
  background: linear-gradient(to bottom, rgba(0,0,0,0) 0%, rgba(0,0,0,0.55) 100%);
}

/* Dégradé au-dessus de la carte plein écran, derrière le header de /parkings.html */
.map-header-scrim {
  background: linear-gradient(to bottom, var(--map-scrim-from) 0%, var(--map-scrim-via) 55%, transparent 100%);
  transition: background 0.25s ease;
}

/* Liste d'items "plate" : sans bordure/fond/arrondi par élément, séparés par un simple
   trait horizontal. Usage : <div class="item-list"> <a class="item-list-row ...">...</a> </div> */
.item-list > .item-list-row + .item-list-row {
  border-top: 1px solid var(--border);
}
.item-list-row {
  display: flex;
  padding: 1rem 0;
}

/* Switch iOS-like réutilisé en Profil */
.switch {
  width: 44px;
  height: 26px;
  border-radius: 999px;
  background: var(--switch-off);
  position: relative;
  transition: background-color 0.2s ease;
  flex-shrink: 0;
}
.switch::after {
  content: "";
  position: absolute;
  top: 3px;
  left: 3px;
  width: 20px;
  height: 20px;
  border-radius: 999px;
  background: var(--surface);
  box-shadow: 0 1px 3px var(--shadow-color);
  transition: transform 0.2s ease;
}
.switch[data-on="true"] {
  background: #FF471A;
}
.switch[data-on="true"]::after {
  transform: translateX(18px);
}

/* Boutons d'action principaux (CTA). Toujours en rouge "secondary" ;
   .secondary-button reprend le même style en gris pour un usage futur. */
.primary-button,
.secondary-button {
  display: inline-block;
  border: 1px solid transparent;
  text-decoration: none !important;
  padding: 0.7rem 1.5rem;
  border-radius: 50px;
  font-family: "Montserrat", "Helvetica Neue", Arial, sans-serif;
  font-weight: 700;
  font-size: 14px;
  text-align: center;
  transition: color 0.3s ease, border-color 0.3s ease, background-color 0.3s ease;
}

.primary-button {
  border-color: #FF471A;
  background-color: #FF471A;
  color: #fff;
}

.secondary-button {
  border-color: #445562;
  background-color: #445562;
  color: #fff;
}

/* Accordéon des types de véhicule (page Offres) : un seul item ouvert à la fois */
.accordion-panel {
  display: grid;
  grid-template-rows: 0fr;
  transition: grid-template-rows 0.3s ease;
}
.accordion-panel > div {
  overflow: hidden;
  min-height: 0;
}

.accordion-item{
  overflow: hidden;
}

.accordion-item .icon-vehicle{
  margin-left: 8px;
  margin-right: 4px;
}

.accordion-item + .accordion-item{
  border-top: 1px solid var(--border);
}

.accordion-item.is-open .accordion-panel {
  grid-template-rows: 1fr;
}
.accordion-chevron {
  transition: transform 0.25s ease;
}
.accordion-item.is-open .accordion-chevron {
  transform: rotate(180deg);
}

/*.accordion-item.is-open .accordion-label {
  color: #FF471A;
}*/

/* Bascule dark/light du header Accueil (remplace l'icône de notification),
   inspirée de reacticx.com/docs/components/theme-switch : un soleil plein que
   révèle, en mode sombre, un masque circulaire qui vient le recouvrir en
   partie pour dessiner un croissant de lune, rayons rétractés et légère
   rotation de l'ensemble pour accompagner la transition. */
.theme-toggle-svg {
  transition: transform 0.5s cubic-bezier(0.4, 0, 0.2, 1);
  transform: rotate(0deg);
}
.theme-toggle-mask-circle {
  transition: transform 0.45s cubic-bezier(0.4, 0, 0.2, 1);
  transform: translate(0, 0);
}
.theme-toggle-rays line {
  transition: opacity 0.25s ease, transform 0.4s cubic-bezier(0.4, 0, 0.2, 1);
  transform-origin: 12px 12px;
}
:root.dark .theme-toggle-svg {
  transform: rotate(40deg);
}
:root.dark .theme-toggle-mask-circle {
  transform: translate(-14px, 12px);
}
:root.dark .theme-toggle-rays line {
  opacity: 0;
  transform: scale(0.4);
}

@keyframes pulse-soft {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.55; }
}
.animate-pulse-soft {
  animation: pulse-soft 1.8s ease-in-out infinite;
}

/* Shimmer générique réutilisé partout où du contenu apparaît après un court délai :
   #map (chargement asynchrone du script Google Maps, cf. js/parkings.js#initMap) et le
   bloc d'infos de parking-detail.html (cf. js/parking-detail.js), retiré (.is-hidden)
   une fois le contenu réel prêt à s'afficher. */
@keyframes shimmer-sweep {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}
.shimmer-overlay {
  background-color: var(--surface-2);
  background-image: linear-gradient(100deg, transparent 35%, var(--surface) 50%, transparent 65%);
  background-size: 250% 100%;
  animation: shimmer-sweep 1.4s ease-in-out infinite;
  transition: opacity 0.25s ease-out;
}
.shimmer-overlay.is-hidden {
  opacity: 0;
  pointer-events: none;
}

/* Photo de présentation de parking-detail.html : le panel d'infos (bords arrondis) glisse
   en montant à l'arrivée sur la page, pour ne pas exposer brutalement les angles droits de
   la photo dès qu'elle a fini de s'agrandir (cf. .vt-parking-hero) — le mouvement + le
   shimmer du bloc d'infos (ci-dessus) laissent le temps à la transition de se stabiliser. */
@keyframes detail-panel-in {
  from { transform: translateY(28px); }
  to { transform: translateY(0); }
}
.detail-panel-in {
  animation: detail-panel-in 0.5s cubic-bezier(0.22, 1, 0.36, 1) both;
}

/* Menu footer (mtpk-bottom-nav), trait actif + zoom de l'icône/texte inspirés de
   reacticx.com/docs/components/tabs : le trait glisse (au lieu d'apparaître sur
   place) de l'ancien onglet actif vers le nouveau, à une vitesse "à ressort"
   (accélération puis léger dépassement avant de se stabiliser) plutôt que linéaire.
   La position de départ vient de sessionStorage (cf. js/components.js), la page
   précédente étant un document distinct sans routing côté client. */
.bottom-nav-indicator {
  transition: left 0.5s cubic-bezier(0.22, 1.61, 0.36, 1);
}

@keyframes bottom-nav-pop {
  0% { transform: scale(0.85); }
  55% { transform: scale(1.22); }
  75% { transform: scale(0.95); }
  100% { transform: scale(1.08); }
}
.bottom-nav-pop {
  transform-origin: center;
  animation: bottom-nav-pop 0.6s cubic-bezier(0.31, 1.72, 0.64, 1) both;
}

/* Transition entre les 4 pages du menu footer (View Transitions API, cross-document) :
   la page sortante et la page entrante glissent horizontalement au lieu du fondu par
   défaut. Le sens ("forward" = onglet suivant dans le menu, "back" = onglet précédent)
   est posé sur <html data-nav-dir> par js/nav-transition-init.js (chargé tôt dans <head>,
   avant le rendu), à partir de la valeur mémorisée en sessionStorage au clic sur le menu
   (cf. js/components.js) — nécessaire puisque chaque page est un document distinct.
   Non supporté par tous les navigateurs (Firefox/Safari) : dans ce cas la navigation
   reste instantanée, sans régression. */
@view-transition {
  navigation: auto;
}

.app-shell {
  view-transition-name: app-shell;
}

::view-transition-group(app-shell) {
  animation-duration: 0.36s;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}
::view-transition-old(app-shell),
::view-transition-new(app-shell) {
  mix-blend-mode: normal;
}

@keyframes mtpk-page-out-left { to { transform: translateX(-28%); opacity: 0; } }
@keyframes mtpk-page-in-right { from { transform: translateX(28%); opacity: 0; } }
@keyframes mtpk-page-out-right { to { transform: translateX(28%); opacity: 0; } }
@keyframes mtpk-page-in-left { from { transform: translateX(-28%); opacity: 0; } }

:root[data-nav-dir="forward"]::view-transition-old(app-shell) {
  animation: mtpk-page-out-left 0.36s cubic-bezier(0.4, 0, 0.2, 1) both;
}
:root[data-nav-dir="forward"]::view-transition-new(app-shell) {
  animation: mtpk-page-in-right 0.36s cubic-bezier(0.4, 0, 0.2, 1) both;
}
:root[data-nav-dir="back"]::view-transition-old(app-shell) {
  animation: mtpk-page-out-right 0.36s cubic-bezier(0.4, 0, 0.2, 1) both;
}
:root[data-nav-dir="back"]::view-transition-new(app-shell) {
  animation: mtpk-page-in-left 0.36s cubic-bezier(0.4, 0, 0.2, 1) both;
}

/* Faux champ de recherche de l'accueil <-> champ de recherche du header Parkings : même
   view-transition-name posé sur les deux éléments (cf. index.html / parkings.html) pour
   que le navigateur anime lui-même la taille et la position de l'un vers l'autre pendant
   la navigation cross-document, sans JS ni mesure manuelle des rects. Non supporté par
   tous les navigateurs (Firefox/Safari) : dans ce cas la navigation reste instantanée. */
.vt-search-field {
  view-transition-name: search-field;
}
::view-transition-group(search-field) {
  animation-duration: 0.36s;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

/* Photo d'un item de parking (liste /parkings.html, "Mes derniers parkings" de l'accueil,
   "Mes parkings favoris" de /activite.html) <-> photo de présentation de parking-detail.html :
   view-transition-name devant être unique dans le document, on ne peut pas le poser sur
   toutes les photos de la liste à la fois. Il est donc posé dynamiquement en JS sur la seule
   image cliquée, juste avant la navigation (cf. js/components.js), pendant que la photo de
   destination le porte en statique (cf. parking-detail.html) puisqu'elle est seule sur sa page. */
.vt-parking-hero {
  view-transition-name: parking-hero;
}
::view-transition-group(parking-hero) {
  animation-duration: 0.4s;
  animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1);
}

/* Le menu footer (mtpk-bottom-nav) est fixe et hors du contenu qui glisse : il garde son
   propre groupe de transition figé (durée nulle) pour rester immobile, au lieu d'être
   emporté dans le glissement de .app-shell ou de clignoter avec le fondu par défaut de
   la racine. Doit aussi être un sibling de .app-shell dans le DOM (pas un enfant), sans
   quoi il serait capturé dans son image et glisserait avec elle. */
.bottom-nav-shell {
  view-transition-name: bottom-nav;
}
::view-transition-group(bottom-nav) {
  animation-duration: 0s;
}
::view-transition-old(bottom-nav),
::view-transition-new(bottom-nav) {
  animation: none;
}
