Thomas Fransolet 473fc3acab Assistant IA + watermark d'essai + parcours guidés + fix du build
Assistant IA (débloque l'add-on sur le plan Essentiel, qui est web-only)
  components/assistant/ (AssistantBubble.tsx + assistant.css),
  lib/assistantSuggestions.ts + test. Suggestions dérivées du contenu réel de
  l'instance, zéro configuration côté client.

Onboarding
  TrialWatermark.tsx — bandeau « Aperçu » pendant l'essai.

Parcours & carte
  ParcoursSection.tsx (+108), LeafletMap.tsx, map.css, MapSection.tsx :
  centrage de carte et icônes corrigés (M1, M2, W2 — des champs que le client
  saisissait sans qu'ils aient le moindre effet).
  ResourceViewer.tsx : rendu des ressources d'étape.

API
  client.ts (+44) et types.ts (+41) alignés sur les nouveaux champs backend.

Fix du build
  lib/geo.ts — helper getGeoPointLatLng(). Les 7 erreurs venaient d'un unknown non
  narrowé. ⚠️ Ce type d'erreur est INVISIBLE en next dev : seul npm run build le voit.

npm run build .
Reste ouvert : W1 — LeafletMap a toujours un TileLayer en dur, un client qui choisit
« Google Hybrid » voit de l'OSM.
2026-08-09 22:15:01 +02:00

128 lines
2.9 KiB
CSS

.mim-pin-wrapper {
background: transparent !important;
border: none !important;
}
.mim-pin {
width: var(--pin-size);
height: calc(var(--pin-size) + 8px);
position: relative;
filter: drop-shadow(0 3px 6px rgba(0, 0, 0, 0.35));
transition: transform 0.2s ease;
}
.mim-pin-selected {
animation: mim-pin-bounce 0.4s ease;
}
@keyframes mim-pin-bounce {
0% { transform: translateY(0) scale(1); }
50% { transform: translateY(-6px) scale(1.05); }
100% { transform: translateY(0) scale(1); }
}
.mim-pin-head {
position: absolute;
width: var(--pin-head);
height: var(--pin-head);
left: calc((var(--pin-size) - var(--pin-head)) / 2);
top: 0;
background: var(--pin-color);
border-radius: 50% 50% 50% 0;
transform: rotate(-45deg);
border: 3px solid white;
box-sizing: border-box;
}
/* Icône de catégorie posée dans la tête du pin : contre-rotation pour compenser
le -45deg du pin, et marge pour ne pas toucher la bordure blanche. */
.mim-pin-head img {
width: 100%;
height: 100%;
padding: 15%;
object-fit: contain;
transform: rotate(45deg);
box-sizing: border-box;
display: block;
}
.mim-pin-dot {
position: absolute;
width: 8px;
height: 8px;
background: white;
border-radius: 50%;
left: calc(var(--pin-size) / 2 - 4px);
top: calc(var(--pin-head) / 2 - 4px);
}
/* Numbered step markers (parcours) */
.mim-step-wrapper {
background: transparent !important;
border: none !important;
}
.mim-step {
width: var(--step-size);
height: var(--step-size);
border-radius: 50%;
background: var(--step-color);
color: white;
font-weight: 700;
font-size: 14px;
display: flex;
align-items: center;
justify-content: center;
border: 3px solid white;
box-shadow: 0 3px 10px rgba(0, 0, 0, 0.4);
box-sizing: border-box;
transition: transform 0.2s ease;
}
.mim-step-selected,
.mim-step-current {
animation: mim-step-pulse 1.6s ease-in-out infinite;
}
@keyframes mim-step-pulse {
0%, 100% { transform: scale(1); box-shadow: 0 3px 10px rgba(0,0,0,0.4), 0 0 0 0 rgba(58, 110, 165, 0.7); }
50% { transform: scale(1.1); box-shadow: 0 3px 10px rgba(0,0,0,0.4), 0 0 0 14px rgba(58, 110, 165, 0); }
}
.mim-user-wrapper {
background: transparent !important;
border: none !important;
}
.mim-user {
width: 24px;
height: 24px;
border-radius: 50%;
background: rgba(37, 99, 235, 0.25);
display: flex;
align-items: center;
justify-content: center;
animation: mim-user-pulse 2s ease-in-out infinite;
}
.mim-user-dot {
width: 14px;
height: 14px;
border-radius: 50%;
background: #2563eb;
border: 2.5px solid white;
box-shadow: 0 1px 4px rgba(0,0,0,0.4);
}
@keyframes mim-user-pulse {
0%, 100% { box-shadow: 0 0 0 0 rgba(37, 99, 235, 0.5); }
50% { box-shadow: 0 0 0 12px rgba(37, 99, 235, 0); }
}
.leaflet-container {
font-family: inherit;
background: #e8eef3;
}
.leaflet-control-attribution {
font-size: 10px !important;
background: rgba(255, 255, 255, 0.7) !important;
}