DOCS/claude design/refonte-gabarit-canevas.html
2026-09-04 16:48:04 +02:00

515 lines
28 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<title>Le canevas de Map et Événement</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css2?family=IBM+Plex+Mono:wght@400;500;600&family=IBM+Plex+Sans:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap">
<style>
:root {
--ground: #f4f6f8;
--surface: #ffffff;
--surface-2: #eef1f5;
--surface-3: #e3e9ef;
--line: #d8dfe6;
--line-soft: #e8edf2;
--ink: #16222c;
--ink-2: #3f4e5a;
--ink-3: #788793;
--brand: #264863;
--brand-tint: #e3eaf1;
--go: #5d7f33;
--go-tint: #e9efdf;
--stop: #a24a47;
--stop-tint: #f6e6e5;
--map: #cfdcd2;
--map-2: #bccfc2;
--water: #b9cddb;
--r: 8px;
}
@media (prefers-color-scheme: dark) {
:root:not([data-theme="light"]) {
--ground: #11171c;
--surface: #19212a;
--surface-2: #212b35;
--surface-3: #2a3641;
--line: #2f3c48;
--line-soft: #26313a;
--ink: #e9eef2;
--ink-2: #b4c1cc;
--ink-3: #7e8e9a;
--brand: #8fb6d6;
--brand-tint: #22303d;
--go: #a3c471;
--go-tint: #232d1e;
--stop: #e0918e;
--stop-tint: #33211f;
--map: #2c3a33;
--map-2: #35473c;
--water: #26384a;
}
}
:root[data-theme="dark"] {
--ground: #11171c;
--surface: #19212a;
--surface-2: #212b35;
--surface-3: #2a3641;
--line: #2f3c48;
--line-soft: #26313a;
--ink: #e9eef2;
--ink-2: #b4c1cc;
--ink-3: #7e8e9a;
--brand: #8fb6d6;
--brand-tint: #22303d;
--go: #a3c471;
--go-tint: #232d1e;
--stop: #e0918e;
--stop-tint: #33211f;
--map: #2c3a33;
--map-2: #35473c;
--water: #26384a;
}
* { box-sizing: border-box; }
body {
background: var(--ground);
color: var(--ink);
font-family: "IBM Plex Sans", system-ui, -apple-system, sans-serif;
font-size: 16px;
line-height: 1.6;
-webkit-font-smoothing: antialiased;
}
.wrap { max-width: 1000px; margin: 0 auto; padding: 52px 22px 88px; display: flex; flex-direction: column; gap: 44px; }
code {
font-family: "IBM Plex Mono", ui-monospace, monospace;
font-size: .84em; background: var(--surface-2); border-radius: 3px;
padding: .1em .34em; color: var(--ink-2);
}
.eyebrow {
font-family: "IBM Plex Mono", monospace; font-size: 11px;
letter-spacing: .14em; text-transform: uppercase; color: var(--ink-3);
}
header { display: flex; flex-direction: column; gap: 9px; }
h1 {
font-size: clamp(29px, 4.6vw, 40px); font-weight: 700; line-height: 1.08;
letter-spacing: -.024em; margin: 0; text-wrap: balance;
}
.lede { font-size: 17.5px; color: var(--ink-2); max-width: 64ch; margin: 0; }
section { display: flex; flex-direction: column; gap: 15px; }
.head { display: flex; gap: 15px; align-items: baseline; }
.head .num {
font-family: "IBM Plex Mono", monospace; font-size: 12px; font-weight: 600;
color: var(--brand); background: var(--brand-tint); border-radius: 4px;
padding: 3px 7px; flex: none;
}
h2 { font-size: 21px; font-weight: 600; letter-spacing: -.014em; margin: 0; text-wrap: balance; }
.sub { font-size: 15px; color: var(--ink-2); margin: 4px 0 0; max-width: 66ch; }
p { margin: 0; max-width: 68ch; color: var(--ink-2); }
p strong { color: var(--ink); font-weight: 600; }
.callout {
background: var(--surface); border: 1px solid var(--line);
border-left: 3px solid var(--brand); border-radius: 0 var(--r) var(--r) 0;
padding: 15px 19px; display: flex; flex-direction: column; gap: 8px;
}
.callout.warn { border-left-color: var(--stop); }
.callout p { font-size: 15px; }
table { width: 100%; border-collapse: collapse; font-size: 14.5px; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); overflow: hidden; }
th {
text-align: left; font-family: "IBM Plex Mono", monospace; font-weight: 500;
font-size: 10.5px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3);
padding: 10px 15px; background: var(--surface-2); border-bottom: 1px solid var(--line);
}
td { padding: 12px 15px; border-bottom: 1px solid var(--line-soft); color: var(--ink-2); vertical-align: top; }
tr:last-child td { border-bottom: none; }
td:first-child { color: var(--ink); font-weight: 600; white-space: nowrap; }
.scroller { overflow-x: auto; }
.go { color: var(--go); font-weight: 600; }
.stop { color: var(--stop); font-weight: 600; }
/* ─── Maquette ─── */
figure { margin: 0; display: flex; flex-direction: column; gap: 11px; }
.stage {
background: var(--surface-2); border: 1px solid var(--line);
border-radius: var(--r); padding: 18px;
}
figcaption { font-size: 14px; color: var(--ink-2); }
figcaption b { color: var(--ink); }
.app { background: var(--surface); border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.app-head {
display: flex; align-items: center; gap: 9px; padding: 9px 13px;
border-bottom: 1px solid var(--line); font-size: 12.5px; font-weight: 600;
}
.app-head .chip {
font-family: "IBM Plex Mono", monospace; font-size: 9.5px; letter-spacing: .08em;
text-transform: uppercase; background: var(--surface-3); color: var(--brand);
padding: 3px 7px; border-radius: 4px; font-weight: 600;
}
.app-head .spacer { flex: 1; }
.app-body { padding: 13px; display: flex; flex-direction: column; gap: 11px; }
.pane { border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.pane-t {
font-size: 12px; font-weight: 600; padding: 8px 11px;
border-bottom: 1px solid var(--line-soft); display: flex; align-items: center; gap: 7px;
}
.pane-t .spacer { flex: 1; }
.pane-t .hint { font-weight: 400; font-size: 10.5px; color: var(--ink-3); }
/* trois zones du gabarit C */
.c3 { display: grid; grid-template-columns: 150px minmax(0, 1fr) 300px; }
@media (max-width: 860px) { .c3 { grid-template-columns: 1fr; } }
.zlist { background: var(--ground); border-right: 1px solid var(--line); padding: 8px; display: flex; flex-direction: column; gap: 4px; }
@media (max-width: 860px) { .zlist { border-right: none; border-bottom: 1px solid var(--line); } }
.li {
display: flex; align-items: center; gap: 6px; padding: 6px 7px;
border-radius: 4px; font-size: 11.5px; color: var(--ink-2);
}
.li .dot { width: 7px; height: 7px; border-radius: 50%; background: var(--ink-3); flex: none; }
.li .n { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.li.sel { background: var(--surface); border: 1px solid var(--brand); color: var(--ink); font-weight: 500; }
.li.sel .dot { background: var(--brand); }
.li.new { border: 1px dashed var(--ink-3); color: var(--brand); justify-content: center; font-weight: 500; }
.li .cat { width: 7px; height: 7px; border-radius: 2px; flex: none; }
.zform { padding: 12px 14px; display: flex; flex-direction: column; gap: 11px; }
.fgrid { display: grid; grid-template-columns: repeat(6, 1fr); gap: 9px 11px; }
.f { display: flex; flex-direction: column; gap: 4px; min-width: 0; }
.f > label { font-size: 10.5px; font-weight: 600; color: var(--ink-2); }
.f .in {
border: 1px solid var(--line); background: var(--surface-2); border-radius: 4px;
padding: 5px 8px; font-size: 11px; color: var(--ink); min-height: 26px;
display: flex; align-items: center; gap: 6px;
}
.f .in .v { flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.f .in .st { font-family: "IBM Plex Mono", monospace; font-size: 9px; color: var(--ink-3); }
.fold {
border: 1px solid var(--line); border-radius: 5px; padding: 7px 10px;
font-size: 11.5px; color: var(--ink-2); display: flex; align-items: center; gap: 7px;
}
.fold .caret { color: var(--ink-3); font-size: 10px; }
.fold .spacer { flex: 1; }
.fold .count { font-family: "IBM Plex Mono", monospace; font-size: 9.5px; color: var(--ink-3); }
.strip { display: flex; gap: 6px; }
.strip .th {
width: 42px; height: 32px; border-radius: 4px; background: var(--surface-3);
border: 1px solid var(--line); flex: none;
}
.strip .th.img { background: linear-gradient(135deg, #4a7fa5, #9dc0d8); border-color: transparent; }
.strip .th.add { display: grid; place-items: center; color: var(--brand); font-size: 15px; border-style: dashed; }
/* le canevas */
.zmap { border-left: 1px solid var(--line); position: relative; min-height: 268px; background: var(--map); overflow: hidden; }
@media (max-width: 860px) { .zmap { border-left: none; border-top: 1px solid var(--line); } }
.zmap .roads { position: absolute; inset: 0; }
.zmap .tools {
position: absolute; top: 8px; left: 8px; display: flex; gap: 3px;
background: var(--surface); border: 1px solid var(--line); border-radius: 5px; padding: 3px;
}
.zmap .tool {
width: 24px; height: 24px; display: grid; place-items: center; border-radius: 3px;
font-size: 12px; color: var(--ink-2);
}
.zmap .tool.on { background: var(--brand); color: #fff; }
.zmap .swatch { width: 24px; height: 24px; border-radius: 3px; background: #c0623f; border: 2px solid var(--surface); }
.zmap .pin {
position: absolute; width: 13px; height: 13px; border-radius: 50% 50% 50% 0;
transform: rotate(-45deg); background: var(--brand); border: 2px solid #fff;
box-shadow: 0 1px 3px rgba(0,0,0,.35);
}
.zmap .pin.ghost { background: var(--ink-3); opacity: .55; }
.zmap .pin.sel { background: #c0623f; width: 17px; height: 17px; }
.zmap .zone {
position: absolute; border: 2px solid #c0623f; background: rgba(192, 98, 63, .18);
border-radius: 3px;
}
.zmap .foot {
position: absolute; left: 0; right: 0; bottom: 0; padding: 6px 9px;
background: var(--surface); border-top: 1px solid var(--line);
font-family: "IBM Plex Mono", monospace; font-size: 9.5px; color: var(--ink-3);
display: flex; align-items: center; gap: 8px;
}
.zmap .foot .spacer { flex: 1; }
.zmap .foot .live { color: var(--go); font-weight: 600; }
/* avant / après */
.ba { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 780px) { .ba { grid-template-columns: 1fr; } }
.stack { background: var(--surface-2); border: 1px solid var(--line); border-radius: var(--r); padding: 16px; display: flex; flex-direction: column; gap: 9px; }
.stack .lab { font-family: "IBM Plex Mono", monospace; font-size: 10px; letter-spacing: .1em; text-transform: uppercase; color: var(--ink-3); }
.layer {
background: var(--surface); border: 1px solid var(--line); border-radius: 5px;
padding: 9px 11px; font-size: 12px; color: var(--ink-2);
}
.layer .t { font-weight: 600; color: var(--ink); font-size: 12.5px; }
.layer.l2 { margin-left: 16px; }
.layer.l3 { margin-left: 32px; border-color: var(--stop); }
.layer.flat { border-color: var(--go); }
ol.steps { display: flex; flex-direction: column; gap: 9px; margin: 0; padding: 0; list-style: none; }
ol.steps li {
display: flex; gap: 13px; align-items: baseline; font-size: 15px; color: var(--ink-2);
padding-bottom: 9px; border-bottom: 1px solid var(--line-soft);
}
ol.steps li:last-child { border-bottom: none; }
ol.steps .n { font-family: "IBM Plex Mono", monospace; font-size: 11.5px; color: var(--ink-3); flex: none; }
footer { border-top: 1px solid var(--line); padding-top: 16px; font-size: 13.5px; color: var(--ink-3); }
</style>
<div class="wrap">
<header>
<div class="eyebrow">Refonte manager-app · gabarit C</div>
<h1>Le canevas de Map et Événement</h1>
<p class="lede">Tout le reste de la refonte est codé. Il manque une seule chose, et c'est la même dans les deux écrans : poser un point ou une zone <em>sur</em> la carte de l'écran, au lieu d'ouvrir une carte dans une modale ouverte depuis une modale.</p>
</header>
<section>
<div class="head">
<span class="num">01</span>
<div>
<h2>Trois niveaux de modale pour placer un point</h2>
<p class="sub">C'est le geste le plus contraint que l'app propose aujourd'hui, et c'est aussi le plus fréquent sur une section Map.</p>
</div>
</div>
<div class="ba">
<div class="stack">
<div class="lab">Aujourd'hui</div>
<div class="layer"><div class="t">Écran de la section</div>La grille des points, 8 colonnes, sous les réglages de carte.</div>
<div class="layer l2"><div class="t">Modale « Point / Zone »</div><code>0,88 × largeur</code> · neuf champs traduits, une image, une catégorie, une liste de contenus.</div>
<div class="layer l3"><div class="t">Modale « Géométrie »</div>La carte où l'on dessine enfin. On ne voit plus ni la fiche, ni les autres points.</div>
</div>
<div class="stack">
<div class="lab">Proposé</div>
<div class="layer flat"><div class="t">Écran de la section</div>La liste des points, la fiche du point sélectionné, et la carte — les trois en même temps. Cliquer sur la carte place le point ouvert dans la fiche.</div>
<div style="font-size: 13px; color: var(--ink-3); padding: 4px 2px">Aucune modale. La carte est le troisième volet, pas une fenêtre.</div>
</div>
</div>
<div class="callout">
<span class="eyebrow">Ce que ça règle, concrètement</span>
<p>On place un point <strong>en voyant les autres</strong> — impossible aujourd'hui, alors que c'est la seule chose qui compte quand on répartit des points d'intérêt sur un plan. Et la fiche reste lisible pendant qu'on dessine, donc on sait quel point on est en train de déplacer.</p>
</div>
</section>
<section>
<div class="head">
<span class="num">02</span>
<div>
<h2>Le gabarit C, dessiné</h2>
<p class="sub">Liste, fiche, canevas. C'est le gabarit B auquel on ajoute une troisième colonne — et le rail droit de l'écran (Habillage, Diffusion) repasse au-dessus, comme annoncé.</p>
</div>
</div>
<figure>
<div class="stage">
<div class="app">
<div class="app-head">
<span>Plan du parc</span>
<span class="chip">Map</span>
<span class="spacer"></span>
<span style="font-size: 11px; color: var(--ink-3); font-weight: 400">Annuler · Enregistrer</span>
</div>
<div class="app-body">
<div class="pane">
<div class="pane-t">Réglages de la carte<span class="spacer"></span><span class="hint">déjà codé</span></div>
<div class="zform">
<div class="fgrid">
<div class="f" style="grid-column: span 2"><label>Service</label><div class="in"><span class="v">Google</span></div></div>
<div class="f" style="grid-column: span 2"><label>Type</label><div class="in"><span class="v">hybrid</span></div></div>
<div class="f" style="grid-column: span 2"><label>Zoom</label><div class="in"><span class="v">18</span></div></div>
<div class="f" style="grid-column: span 2"><label>Icône</label><div class="in"><span class="v">pin-parc.svg</span></div></div>
<div class="f" style="grid-column: span 2"><label>Catégories</label><div class="in"><span class="v">4 catégories</span></div></div>
<div class="f" style="grid-column: span 2"><label>Vue liste</label><div class="in"><span class="v">Activée</span></div></div>
</div>
</div>
</div>
<div class="pane">
<div class="pane-t">Points d'intérêt<span class="spacer"></span><span class="hint">12 points · le centre de la carte se règle ici aussi</span></div>
<div class="c3">
<div class="zlist">
<div class="li"><span class="cat" style="background:#5d7f33"></span><span class="n">Entrée nord</span></div>
<div class="li sel"><span class="cat" style="background:#c0623f"></span><span class="n">Serre tropicale</span></div>
<div class="li"><span class="cat" style="background:#c0623f"></span><span class="n">Volière</span></div>
<div class="li"><span class="cat" style="background:#264863"></span><span class="n">Buvette</span></div>
<div class="li"><span class="cat" style="background:#264863"></span><span class="n">Toilettes est</span></div>
<div class="li"><span class="cat" style="background:#5d7f33"></span><span class="n">Aire de jeux</span></div>
<div class="li new">+ Nouveau point</div>
</div>
<div class="zform">
<div class="fgrid">
<div class="f" style="grid-column: span 4"><label>Titre *</label><div class="in"><span class="v">Serre tropicale</span><span class="st">3/3</span></div></div>
<div class="f" style="grid-column: span 2"><label>Catégorie</label><div class="in"><span class="v">À voir</span></div></div>
<div class="f" style="grid-column: span 4"><label>Description</label><div class="in"><span class="v">Palmiers, orchidées et bassin à nénuphars.</span><span class="st">3/3</span></div></div>
<div class="f" style="grid-column: span 2"><label>Image</label><div class="in"><span class="v">serre.jpg</span></div></div>
</div>
<div class="fold">
<span class="caret"></span>Informations pratiques
<span class="spacer"></span>
<span class="count">2 / 5 remplies</span>
</div>
<div class="f">
<label>Contenus du point</label>
<div class="strip">
<span class="th img"></span>
<span class="th"></span>
<span class="th add">+</span>
</div>
</div>
</div>
<div class="zmap">
<svg class="roads" viewBox="0 0 300 268" preserveAspectRatio="none" aria-hidden="true">
<rect x="0" y="0" width="300" height="268" fill="var(--map)"/>
<path d="M-10 90 C 60 70, 120 130, 200 100 S 300 60, 320 80" stroke="var(--map-2)" stroke-width="16" fill="none"/>
<path d="M70 -10 C 90 80, 60 150, 110 280" stroke="var(--map-2)" stroke-width="11" fill="none"/>
<ellipse cx="235" cy="190" rx="52" ry="33" fill="var(--water)"/>
</svg>
<div class="tools">
<span class="tool on">📍</span>
<span class="tool"></span>
<span class="tool"></span>
<span class="swatch"></span>
</div>
<span class="pin ghost" style="left: 42px; top: 62px"></span>
<span class="pin ghost" style="left: 118px; top: 44px"></span>
<span class="pin ghost" style="left: 96px; top: 152px"></span>
<span class="pin ghost" style="left: 205px; top: 88px"></span>
<span class="pin ghost" style="left: 158px; top: 196px"></span>
<span class="zone" style="left: 128px; top: 96px; width: 66px; height: 52px"></span>
<span class="pin sel" style="left: 152px; top: 112px"></span>
<div class="foot">
<span>50.42933, 4.89143</span>
<span class="spacer"></span>
<span class="live">Serre tropicale</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<figcaption>
<b>Comment ça se lit</b> — Les points non sélectionnés restent visibles en gris : c'est l'information qui manquait. Le point ouvert dans la fiche est en couleur, et c'est lui que le clic sur la carte déplace. La barre d'outils en haut à gauche est celle de <code>MapGeometryPicker</code>, déplacée telle quelle : point, ligne, zone, couleur. Le pied de carte dit ce qu'on modifie et où, pour qu'aucun clic ne soit ambigu.
</figcaption>
</figure>
<div class="callout">
<span class="eyebrow">Neuf champs traduits, ça ne tient pas à plat — et ça n'a pas à tenir</span>
<p>Un point porte titre, description, site, prix, téléphone, e-mail, horaires, image et catégorie. Les quatre premiers d'un musée sont presque toujours remplis, les cinq autres presque jamais. La fiche montre donc <strong>titre, description, catégorie, image</strong>, et replie les <strong>informations pratiques</strong> derrière une ligne qui dit combien sont remplies. Rien n'est retiré, seulement rangé par fréquence d'usage réelle.</p>
</div>
<div class="callout">
<span class="eyebrow">Faut-il tout centrer sur la carte ? Non — mais deux modes, oui</span>
<p>Tentant, et je pense que ce serait une erreur en permanence : un point porte <strong>neuf champs traduits</strong>, une image, une catégorie et une liste de contenus ; la carte n'en porte qu'un seul, la géométrie. Donner en permanence le plus de place au champ qu'on modifie le moins ferait de la saisie — le vrai travail de cet écran — le parent pauvre. Le back-office est un outil de saisie ; la belle carte, le visiteur l'a déjà dans l'app.</p>
<p><strong>En revanche, 300 px ne suffisent pas</strong> pour juger d'une répartition de points. Le canevas passe donc à <strong>420 px de haut</strong> par défaut, et gagne un bouton <strong>« agrandir »</strong> qui lui donne toute la largeur : la liste reste en rail étroit, la fiche se replie. Deux moments distincts, deux dispositions — on écrit une fiche, ou on répartit des points, rarement les deux dans la même minute.</p>
</div>
<div class="callout">
<span class="eyebrow">Le centre de la carte n'a plus besoin de son propre sélecteur</span>
<p>Le canevas sait déjà afficher une carte et recevoir un clic. Le point central se règle donc par un mode du canevas, et <code>geoloc_input_container</code> — repris à la coquille standard cette semaine — n'a plus d'appelant sur cet écran. Il reste utile ailleurs tant que d'autres écrans le référencent.</p>
</div>
</section>
<section>
<div class="head">
<span class="num">03</span>
<div>
<h2>Événement : le même canevas, un autre fond</h2>
<p class="sub">Un événement pose des annotations sur le plan du site plutôt que des points d'intérêt sur une carte. La mécanique ne change pas, le fond de plan si.</p>
</div>
</div>
<p>Le canevas d'Événement affiche la <strong>carte de base</strong> choisie dans <code>baseSectionMapId</code>, et les annotations globales se posent dessus, exactement comme les points. Trois différences, et elles sont toutes dans le contenu, pas dans la forme :</p>
<div class="scroller">
<table>
<thead><tr><th>Ce qu'on pose</th><th>Gabarit</th><th>Pourquoi</th></tr></thead>
<tbody>
<tr><td>Annotations du plan</td><td class="go">C — canevas</td><td>Elles ont une position : elles se posent sur le plan, comme les points de Map. Même liste, même fiche, même canevas.</td></tr>
<tr><td>Blocs de programme</td><td>B — liste</td><td>Ils ont une heure de début et de fin, pas une position. Une liste ordonnée suffit — et c'est déjà ce qu'ils sont.</td></tr>
<tr><td>Parcours de l'événement</td><td>déjà fait</td><td>L'éditeur à fenêtre unique est raccordé et reste tel quel.</td></tr>
</tbody>
</table>
</div>
<div class="callout warn">
<span class="eyebrow">⚠️ Une question à laquelle le code ne répond pas</span>
<p>Quand aucune carte de base n'est choisie (<code>baseSectionMapId</code> vaut <code>null</code>), le canevas n'a pas de fond. Deux réponses possibles : afficher une carte vide comme sur Map, ou afficher un message qui invite à choisir un plan d'abord. <strong>Je propose la seconde</strong> — poser des annotations sur un fond qui va changer, c'est du travail à refaire — mais c'est un choix produit, pas technique.</p>
</div>
</section>
<section>
<div class="head">
<span class="num">04</span>
<div>
<h2>Ce qui disparaît</h2>
<p class="sub">Le canevas n'ajoute pas une brique : il en absorbe quatre.</p>
</div>
</div>
<div class="scroller">
<table>
<thead><tr><th>Fichier</th><th>Sort</th><th>Détail</th></tr></thead>
<tbody>
<tr><td><code>showNewOrUpdateGeoPoint.dart</code><br><span style="font-weight:400;color:var(--ink-3);font-size:13px">362 lignes</span></td><td class="go">supprimé</td><td>Absorbé par la fiche du gabarit C. Ses champs ne changent pas, ils changent de contenant.</td></tr>
<tr><td><code>geometry_input_container.dart</code></td><td class="go">supprimé</td><td>Le champ qui ouvrait la carte de dessin n'a plus lieu d'être quand la carte est à l'écran. ⚠️ Deux autres appelants à traiter d'abord : <code>etape_fields</code> et <code>showNewOrUpdateEventAgenda</code>.</td></tr>
<tr><td><code>map_geometry_picker.dart</code></td><td>déplacé</td><td><strong>Le dessin existe déjà et fonctionne.</strong> Il sort de son dialogue pour devenir le canevas. C'est le cœur du lot, et c'est du déplacement, pas de l'écriture.</td></tr>
<tr><td><code>showNewOrUpdateMapAnnotation.dart</code><br><span style="font-weight:400;color:var(--ink-3);font-size:13px">182 lignes</span></td><td class="go">supprimé</td><td>Même chose côté Événement.</td></tr>
<tr><td><code>geoloc_input_container.dart</code></td><td>conservé</td><td>Plus d'appelant sur Map, mais il reste référencé ailleurs. On le garde tant qu'il sert.</td></tr>
</tbody>
</table>
</div>
</section>
<section>
<div class="head">
<span class="num">05</span>
<div>
<h2>Dans quel ordre</h2>
<p class="sub">Les points d'un Map vivent côté serveur : l'éditeur de collection sait déjà leur parler depuis cette semaine.</p>
</div>
</div>
<ol class="steps">
<li><span class="n">1</span><span><strong>Fait.</strong> <code>MapCanvas</code> est sorti du dialogue : il reçoit une géométrie, la rend modifiable, rend la main à chaque changement, et affiche les autres tracés en fond. <code>MapGeometryPicker</code> n'est plus qu'une coquille autour de lui, pour ses deux appelants restants.</span></li>
<li><span class="n">2</span><span>Poser le gabarit C : liste, fiche, canevas, avec la liste en mode distant (les points sont chargés et écrits par l'API, comme les questions de Quiz).</span></li>
<li><span class="n">3</span><span>Migrer les champs du point depuis <code>showNewOrUpdateGeoPoint</code>, avec le repli des informations pratiques, puis supprimer la modale.</span></li>
<li><span class="n">4</span><span>Brancher les filtres qui existent déjà — recherche et catégories — sur la liste <em>et</em> sur le canevas, pour qu'ils cachent les mêmes points des deux côtés.</span></li>
<li><span class="n">5</span><span>Refaire le même geste sur Événement, avec la carte de base en fond, et traiter les deux autres appelants de <code>GeometryInputContainer</code>.</span></li>
</ol>
<div class="callout">
<span class="eyebrow">Ce que ça ne touche pas</span>
<p>Aucun DTO, aucun endpoint, aucune migration. <code>GeoPointDTO</code> garde ses neuf champs traduits, sa géométrie et sa couleur ; <code>MapDTO</code> garde ses catégories. Le risque est dans le comportement de la carte, pas dans les données — et il est réversible par <code>git</code>.</p>
</div>
</section>
<footer>
Proposition pour <strong>manager-app</strong> · même palette et mêmes tokens que la refonte Configuration &amp; Sections (<code>#264863</code>, <code>#f5f5f7</code>, <code>kRadiusCard</code>, <code>kLabelField</code>) · aucune dépendance nouvelle, la carte et le dessin sont déjà là.
</footer>
</div>