SPB Git

spb/lou-ka

Public

Lou·Ka — tous les logements à louer du Québec, un seul endroit.

Accueil : refonte majeure du rendu — CTA hero, filtres et boutons peaufines

- Hero : halo d accent + trame de points decorative, rangee CTA (Explorer /
  Voir la carte) avec ombres decalees accent, stat-chips interactives
  (tabular-nums, survol), avantages en mini-cartes bordees encre
- Filterbar : cadre 2px + rayon 16, recherche 52px focus accent (ombre 3x3),
  selects survolables, bouton Plus de filtres avec icone, badge compteur et
  chevron anime, panneau avance en pointille avec easing
- Segments : etat actif encre + souligne accent interieur ; pastilles actives
  avec animation d apparition et survol danger (intention de retrait)
- Chips 42px avec icones alignees ; bascule Liste/Carte etat actif encre
- Mobile : poignee de sheet, bouton Voir les resultats sticky en bas de la
  feuille, FAB avec badge compteur
Simon-Pierre Boucher committed (Aug 25, 2026) parent bc6aef3 Browse files

2 changed files +161 −56

modified frontend/src/pages/Home.tsx +26 −2
@@ -254,6 +254,26 @@ export default function Home() {
254 Tous les logements à louer au Québec, regroupés au même endroit — mis à jour 254 Tous les logements à louer au Québec, regroupés au même endroit — mis à jour
255 automatiquement, avec toutes les photos et un lien direct vers l'annonce originale. 255 automatiquement, avec toutes les photos et un lien direct vers l'annonce originale.
256 </p> 256 </p>
257+ <div className="hero-cta">
258+ <button
259+ className="btn btn-primary btn-lg"
260+ onClick={() => {
261+ setView("liste");
262+ resultsRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
263+ }}
264+ >
265+ <IcoSearch size={16} /> Explorer les logements
266+ </button>
267+ <button
268+ className="btn btn-lg"
269+ onClick={() => {
270+ setView("carte");
271+ resultsRef.current?.scrollIntoView({ behavior: "smooth", block: "start" });
272+ }}
273+ >
274+ <IcoMap size={16} /> Voir la carte
275+ </button>
276+ </div>
257 <div className="benefits" aria-label="Avantages"> 277 <div className="benefits" aria-label="Avantages">
258 <div className="benefit"> 278 <div className="benefit">
259 <span className="benefit-ico"><IcoHouse size={20} /></span> 279 <span className="benefit-ico"><IcoHouse size={20} /></span>
@@ -299,6 +319,7 @@ export default function Home() {
299 <div className="sheet-backdrop" onClick={() => setSheetOpen(false)} aria-hidden="true" /> 319 <div className="sheet-backdrop" onClick={() => setSheetOpen(false)} aria-hidden="true" />
300 )} 320 )}
301 <section className={`filterbar ${sheetOpen ? "open" : ""}`} aria-label="Filtres"> 321 <section className={`filterbar ${sheetOpen ? "open" : ""}`} aria-label="Filtres">
322+ <div className="sheet-handle" aria-hidden="true" />
302 <div className="sheet-head"> 323 <div className="sheet-head">
303 <span>Filtres</span> 324 <span>Filtres</span>
304 <button className="sheet-close" onClick={() => setSheetOpen(false)} aria-label="Fermer les filtres"> 325 <button className="sheet-close" onClick={() => setSheetOpen(false)} aria-label="Fermer les filtres">
@@ -366,7 +387,9 @@ export default function Home() {
366 onClick={() => setAdvOpen(!advOpen)} 387 onClick={() => setAdvOpen(!advOpen)}
367 aria-expanded={advOpen} 388 aria-expanded={advOpen}
368 > 389 >
369− Plus de filtres{advCount > 0 ? ` · ${advCount}` : ""} {advOpen ? "▴" : "▾"} 390+ <IcoSliders size={14} /> Plus de filtres
391+ {advCount > 0 && <span className="f-more-badge">{advCount}</span>}
392+ <span className={`f-chev${advOpen ? " up" : ""}`} aria-hidden="true" />
370 </button> 393 </button>
371 </div> 394 </div>
372 395
@@ -603,7 +626,8 @@ export default function Home() {
603 onClick={() => setSheetOpen(true)} 626 onClick={() => setSheetOpen(true)}
604 aria-label="Ouvrir les filtres" 627 aria-label="Ouvrir les filtres"
605 > 628 >
606− <IcoSliders size={15} /> Filtres{activeFilters > 0 ? ` · ${activeFilters}` : ""} 629+ <IcoSliders size={15} /> Filtres
630+ {activeFilters > 0 && <span className="fab-badge">{activeFilters}</span>}
607 </button> 631 </button>
608 </div> 632 </div>
609 ); 633 );
modified frontend/src/styles.css +135 −54
@@ -88,22 +88,52 @@ html, body { overflow-x: clip; }
88 } 88 }
89 89
90 /* ================= Hero ================= */ 90 /* ================= Hero ================= */
91−.hero { padding: 58px 0 22px; } 91+.hero { position: relative; padding: 64px 0 26px; }
92−@media (max-width: 640px) { .hero { padding: 34px 0 14px; } } 92+@media (max-width: 640px) { .hero { padding: 36px 0 14px; } }
93+/* halo d'accent + trame de points en fond — purement décoratif, sous le texte */
94+.hero::before {
95+ content: ""; position: absolute; z-index: -1; top: -60px; right: -120px;
96+ width: 560px; height: 460px; pointer-events: none;
97+ background: radial-gradient(closest-side, rgba(255, 106, 0, 0.13), transparent 72%);
98+}
99+.hero::after {
100+ content: ""; position: absolute; z-index: -1; inset: -20px -40px 0 0; pointer-events: none;
101+ background-image: radial-gradient(rgba(20, 24, 20, 0.16) 1px, transparent 1.5px);
102+ background-size: 24px 24px;
103+ -webkit-mask-image: linear-gradient(112deg, transparent 58%, rgba(0, 0, 0, 0.85));
104+ mask-image: linear-gradient(112deg, transparent 58%, rgba(0, 0, 0, 0.85));
105+}
93 .hero h1 { 106 .hero h1 {
94 font-size: clamp(36px, 5.4vw, 56px); font-weight: 700; line-height: 1.06; 107 font-size: clamp(36px, 5.4vw, 56px); font-weight: 700; line-height: 1.06;
95 letter-spacing: -0.03em; max-width: 900px; margin-top: 14px; color: var(--navy); 108 letter-spacing: -0.03em; max-width: 900px; margin-top: 14px; color: var(--navy);
96 } 109 }
97 .hero h1 .outline { color: var(--navy); } 110 .hero h1 .outline { color: var(--navy); }
98 .hero p.lede { color: var(--ink-2); font-size: 17px; max-width: 640px; margin: 18px 0 0; } 111 .hero p.lede { color: var(--ink-2); font-size: 17px; max-width: 640px; margin: 18px 0 0; }
99−.stat-row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 26px; } 112+
113+/* — CTA du héro : accès direct aux résultats / à la carte — */
114+.hero-cta { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 28px; }
115+.btn-lg { min-height: 52px; padding: 14px 26px; font-size: 15px; border-radius: 12px; }
116+.btn-lg svg { flex: none; }
117+.hero-cta .btn-primary { box-shadow: 5px 5px 0 var(--accent); }
118+.hero-cta .btn-primary:hover { transform: translate(-2px, -2px); box-shadow: 7px 7px 0 var(--accent); }
119+.hero-cta .btn-primary:active { transform: none; box-shadow: 3px 3px 0 var(--accent); }
120+@media (max-width: 640px) {
121+ .hero-cta { gap: 10px; }
122+ .hero-cta .btn { flex: 1 1 45%; }
123+}
124+
125+.stat-row { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 28px; }
100 .stat-chip { 126 .stat-chip {
101 background: var(--surface); border: 1.5px solid var(--ink); border-radius: var(--r-pill); 127 background: var(--surface); border: 1.5px solid var(--ink); border-radius: var(--r-pill);
102 padding: 8px 16px; font-size: 12.5px; font-weight: 500; 128 padding: 8px 16px; font-size: 12.5px; font-weight: 500;
103 color: var(--ink-2); display: flex; gap: 8px; align-items: center; 129 color: var(--ink-2); display: flex; gap: 8px; align-items: center;
104 box-shadow: var(--shadow-flat); 130 box-shadow: var(--shadow-flat);
131+ transition: transform 0.13s ease, box-shadow 0.13s ease;
132+}
133+@media (hover: hover) {
134+ .stat-chip:hover { transform: translate(-1px, -1px); box-shadow: var(--shadow-off-mid); }
105 } 135 }
106−.stat-chip b { color: var(--navy); font-weight: 700; } 136+.stat-chip b { color: var(--navy); font-weight: 700; font-variant-numeric: tabular-nums; }
107 .stat-chip .pulse { 137 .stat-chip .pulse {
108 width: 8px; height: 8px; border-radius: 50%; background: var(--orange); 138 width: 8px; height: 8px; border-radius: 50%; background: var(--orange);
109 box-shadow: 0 0 0 4px var(--orange-soft); animation: pulse 2.4s ease infinite; 139 box-shadow: 0 0 0 4px var(--orange-soft); animation: pulse 2.4s ease infinite;
@@ -115,13 +145,22 @@ html, body { overflow-x: clip; }
115 display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); 145 display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr));
116 gap: 14px; margin-top: 30px; 146 gap: 14px; margin-top: 30px;
117 } 147 }
118−.benefit { display: flex; align-items: center; gap: 12px; } 148+.benefit {
149+ display: flex; align-items: center; gap: 12px;
150+ background: var(--surface); border: 1.5px solid var(--ink); border-radius: var(--r-card);
151+ padding: 11px 14px; box-shadow: var(--shadow-flat);
152+ transition: transform 0.15s ease, box-shadow 0.15s ease;
153+}
154+@media (hover: hover) {
155+ .benefit:hover { transform: translate(-2px, -2px); box-shadow: var(--shadow-off-mid); }
156+}
119 .benefit-ico { 157 .benefit-ico {
120 width: 42px; height: 42px; border-radius: var(--r-pill); flex: none; 158 width: 42px; height: 42px; border-radius: var(--r-pill); flex: none;
121 display: flex; align-items: center; justify-content: center; 159 display: flex; align-items: center; justify-content: center;
122 background: var(--orange-soft); color: var(--orange); 160 background: var(--orange-soft); color: var(--orange);
161+ border: 1px solid rgba(255, 106, 0, 0.25);
123 } 162 }
124−.benefit-ico.blue { background: var(--blue-soft); color: var(--blue); } 163+.benefit-ico.blue { background: var(--blue-soft); color: var(--blue); border-color: rgba(28, 92, 65, 0.25); }
125 .benefit-label { 164 .benefit-label {
126 font-size: 11.5px; font-weight: 700; text-transform: uppercase; 165 font-size: 11.5px; font-weight: 700; text-transform: uppercase;
127 letter-spacing: 0.08em; color: var(--navy); 166 letter-spacing: 0.08em; color: var(--navy);
@@ -132,40 +171,43 @@ html, body { overflow-x: clip; }
132 171
133 /* ================= Filter bar ================= */ 172 /* ================= Filter bar ================= */
134 .filterbar { 173 .filterbar {
135− background: var(--surface); border: 1.5px solid var(--ink); border-radius: var(--r-card); 174+ background: var(--surface); border: 2px solid var(--ink); border-radius: 16px;
136− box-shadow: var(--shadow-off-soft); padding: 14px; margin: 30px 0 6px; 175+ box-shadow: var(--shadow-off-soft); padding: 14px; margin: 34px 0 6px;
137 display: flex; flex-direction: column; gap: 0; min-width: 0; 176 display: flex; flex-direction: column; gap: 0; min-width: 0;
138 } 177 }
139 178
140 /* — rangée principale — */ 179 /* — rangée principale — */
141 .f-primary { display: flex; gap: 10px; align-items: stretch; flex-wrap: wrap; min-width: 0; } 180 .f-primary { display: flex; gap: 10px; align-items: stretch; flex-wrap: wrap; min-width: 0; }
142 .f-search { 181 .f-search {
143− flex: 1 1 220px; min-width: 0; max-width: 440px; align-self: center; 182+ flex: 1 1 240px; min-width: 0; max-width: 460px;
144− display: flex; align-items: center; gap: 8px; 183+ display: flex; align-items: center; gap: 9px;
145− border: 1px solid transparent; border-radius: var(--r-pill); background: var(--grey); 184+ border: 1.5px solid var(--ink); border-radius: var(--r-pill); background: var(--grey);
146− padding: 0 15px; min-height: 42px; color: var(--ink-2); 185+ padding: 0 16px; min-height: 52px; color: var(--ink-2);
147− transition: box-shadow 0.15s ease, border-color 0.15s ease, background 0.15s ease; 186+ transition: box-shadow 0.15s ease, border-color 0.15s ease, background 0.15s ease, color 0.15s ease;
148 } 187 }
149 .f-search:focus-within { 188 .f-search:focus-within {
150− background: var(--white); border-color: var(--blue); 189+ background: var(--white); border-color: var(--ink);
151− box-shadow: 0 0 0 3px rgba(28, 92, 65, 0.15); 190+ box-shadow: 3px 3px 0 var(--accent); color: var(--accent-deep);
152 } 191 }
153 .f-search input { 192 .f-search input {
154 border: none; background: none; outline: none; flex: 1; min-width: 0; 193 border: none; background: none; outline: none; flex: 1; min-width: 0;
155− font-size: 14px; color: var(--ink); font-family: inherit; 194+ font-size: 14.5px; color: var(--ink); font-family: inherit;
156 } 195 }
196+.f-search input::placeholder { color: var(--ink-3); }
157 .f-clear { 197 .f-clear {
158 border: none; background: var(--line); color: var(--ink-2); border-radius: 50%; 198 border: none; background: var(--line); color: var(--ink-2); border-radius: 50%;
159− width: 20px; height: 20px; font-size: 10px; cursor: pointer; flex: none; 199+ width: 22px; height: 22px; font-size: 10px; cursor: pointer; flex: none;
160− display: grid; place-items: center; 200+ display: grid; place-items: center; transition: background 0.12s ease, color 0.12s ease;
161 } 201 }
202+.f-clear:hover { background: var(--ink); color: var(--white); }
162 .f-ctl { 203 .f-ctl {
163 flex: 0 1 auto; min-width: 0; display: flex; flex-direction: column; justify-content: center; 204 flex: 0 1 auto; min-width: 0; display: flex; flex-direction: column; justify-content: center;
164 gap: 2px; border: 1.5px solid var(--ink); border-radius: 14px; background: var(--surface); 205 gap: 2px; border: 1.5px solid var(--ink); border-radius: 14px; background: var(--surface);
165 padding: 7px 14px 6px; min-height: 52px; cursor: pointer; 206 padding: 7px 14px 6px; min-height: 52px; cursor: pointer;
166− transition: box-shadow 0.15s ease, border-color 0.15s ease; 207+ transition: box-shadow 0.15s ease, background 0.15s ease;
167 } 208 }
168−.f-ctl:focus-within { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(28, 92, 65, 0.15); } 209+@media (hover: hover) { .f-ctl:hover { background: var(--grey); } }
210+.f-ctl:focus-within { background: var(--white); box-shadow: 3px 3px 0 var(--accent); }
169 .f-ctl > span { 211 .f-ctl > span {
170 font-size: 9.5px; font-weight: 700; 212 font-size: 9.5px; font-weight: 700;
171 text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-3); 213 text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-3);
@@ -182,21 +224,35 @@ html, body { overflow-x: clip; }
182 .range-pair select { max-width: 86px; } 224 .range-pair select { max-width: 86px; }
183 .range-sep { color: var(--ink-3); font-size: 11px; } 225 .range-sep { color: var(--ink-3); font-size: 11px; }
184 .f-more { 226 .f-more {
185− flex: none; align-self: stretch; border: 1.5px solid var(--ink); border-radius: var(--r-pill); 227+ flex: none; align-self: stretch; display: inline-flex; align-items: center; gap: 8px;
228+ border: 1.5px solid var(--ink); border-radius: var(--r-pill);
186 background: var(--surface); color: var(--navy); padding: 0 20px; cursor: pointer; 229 background: var(--surface); color: var(--navy); padding: 0 20px; cursor: pointer;
187− font-family: var(--font-display); font-weight: 600; font-size: 14px; min-height: 52px; 230+ font-family: var(--font-display); font-weight: 700; font-size: 14px; min-height: 52px;
188− transition: all 0.13s ease; 231+ transition: transform 0.13s ease, box-shadow 0.13s ease, background 0.13s ease, color 0.13s ease;
232+}
233+.f-more:hover { transform: translate(-1px, -1px); box-shadow: var(--shadow-off-mid); }
234+.f-more:active { transform: none; box-shadow: none; }
235+.f-more.on { background: var(--ink); border-color: var(--ink); color: var(--white); box-shadow: 3px 3px 0 var(--accent); }
236+.f-more.on:hover { transform: none; }
237+.f-more-badge {
238+ display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px;
239+ border-radius: var(--r-pill); background: var(--accent); color: var(--on-accent);
240+ font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums;
189 } 241 }
190−.f-more:hover { background: var(--blue-soft); border-color: var(--blue); color: var(--blue); } 242+.f-chev {
191−.f-more.on { background: var(--blue); border-color: var(--blue); color: var(--white); } 243+ width: 8px; height: 8px; flex: none;
244+ border-right: 2px solid currentColor; border-bottom: 2px solid currentColor;
245+ transform: rotate(45deg); margin-top: -4px; transition: transform 0.18s ease, margin 0.18s ease;
246+}
247+.f-chev.up { transform: rotate(-135deg); margin-top: 4px; }
192 248
193 /* — panneau avancé — */ 249 /* — panneau avancé — */
194 .f-adv { 250 .f-adv {
195− display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 16px 22px; 251+ display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: 18px 26px;
196− border-top: 1px solid var(--line); margin-top: 14px; padding-top: 14px; min-width: 0; 252+ border-top: 1.5px dashed var(--line); margin-top: 14px; padding-top: 16px; min-width: 0;
197− animation: adv-in 0.18s ease; 253+ animation: adv-in 0.22s cubic-bezier(0.2, 0.9, 0.3, 1);
198 } 254 }
199−@keyframes adv-in { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } } 255+@keyframes adv-in { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
200 .f-group { display: flex; flex-direction: column; gap: 7px; min-width: 0; } 256 .f-group { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
201 .f-group > label { 257 .f-group > label {
202 font-size: 10.5px; font-weight: 700; 258 font-size: 10.5px; font-weight: 700;
@@ -212,33 +268,39 @@ html, body { overflow-x: clip; }
212 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23141814'/%3E%3C/svg%3E"); 268 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='10' height='6'%3E%3Cpath d='M0 0l5 6 5-6z' fill='%23141814'/%3E%3C/svg%3E");
213 background-repeat: no-repeat; background-position: right 12px center; 269 background-repeat: no-repeat; background-position: right 12px center;
214 } 270 }
215−.f-native:focus { border-color: var(--blue); box-shadow: 0 0 0 3px rgba(28, 92, 65, 0.15); background: var(--white); } 271+.f-native:focus { border-color: var(--ink); box-shadow: 3px 3px 0 var(--accent); background: var(--white); }
216 272
217 /* segments (pilules soudées) */ 273 /* segments (pilules soudées) */
218 .seg { display: inline-flex; flex-wrap: wrap; row-gap: 6px; } 274 .seg { display: inline-flex; flex-wrap: wrap; row-gap: 6px; }
219 .seg button { 275 .seg button {
220 border: 1.5px solid var(--ink); background: var(--surface); color: var(--ink-2); 276 border: 1.5px solid var(--ink); background: var(--surface); color: var(--ink-2);
221 padding: 8px 14px; font-family: var(--font-display); font-weight: 600; font-size: 13px; 277 padding: 8px 14px; font-family: var(--font-display); font-weight: 600; font-size: 13px;
222− cursor: pointer; margin-left: -1px; white-space: nowrap; min-height: 38px; 278+ cursor: pointer; margin-left: -1.5px; white-space: nowrap; min-height: 40px;
223− transition: all 0.12s ease; 279+ transition: background 0.12s ease, color 0.12s ease, box-shadow 0.12s ease;
224 } 280 }
225 .seg button:first-child { border-radius: var(--r-pill) 0 0 var(--r-pill); margin-left: 0; padding-left: 16px; } 281 .seg button:first-child { border-radius: var(--r-pill) 0 0 var(--r-pill); margin-left: 0; padding-left: 16px; }
226 .seg button:last-child { border-radius: 0 var(--r-pill) var(--r-pill) 0; padding-right: 16px; } 282 .seg button:last-child { border-radius: 0 var(--r-pill) var(--r-pill) 0; padding-right: 16px; }
227−.seg button:hover { background: var(--blue-soft); color: var(--blue); } 283+.seg button:hover { background: var(--orange-soft); color: var(--orange-deep); }
228−.seg button.on { background: var(--blue); border-color: var(--blue); color: var(--white); position: relative; z-index: 1; } 284+.seg button.on {
285+ background: var(--ink); border-color: var(--ink); color: var(--white);
286+ position: relative; z-index: 1; box-shadow: inset 0 -2.5px 0 var(--accent);
287+}
229 288
230−/* pastilles de filtres actifs */ 289+/* pastilles de filtres actifs — survol = intention de retrait (danger) */
231−.pills { display: flex; flex-wrap: wrap; gap: 8px; margin: 10px 0 2px; } 290+.pills { display: flex; flex-wrap: wrap; gap: 8px; margin: 12px 0 2px; }
232−.pill { 291+.pills .pill {
233 display: inline-flex; align-items: center; gap: 7px; 292 display: inline-flex; align-items: center; gap: 7px;
234− border: 1px solid rgba(28, 92, 65, 0.3); background: var(--blue-soft); color: var(--blue); 293+ border: 1.5px solid var(--ink); background: var(--surface); color: var(--ink);
235 border-radius: var(--r-pill); padding: 6px 14px; font-size: 12.5px; font-weight: 600; 294 border-radius: var(--r-pill); padding: 6px 14px; font-size: 12.5px; font-weight: 600;
236− cursor: pointer; transition: all 0.13s ease; 295+ cursor: pointer; transition: all 0.13s ease; box-shadow: 2px 2px 0 var(--orange-soft);
237−} 296+ animation: pill-in 0.18s ease;
238−.pill:hover { background: var(--blue); color: var(--white); } 297+}
239−.pill-x { font-size: 10px; opacity: 0.65; } 298+@keyframes pill-in { from { opacity: 0; transform: scale(0.9); } to { opacity: 1; transform: none; } }
240−.pill-clear { background: var(--surface); border-color: var(--danger); color: var(--danger); } 299+.pills .pill:hover { background: var(--danger-soft); border-color: var(--danger); color: var(--danger); box-shadow: none; }
241−.pill-clear:hover { background: var(--danger); color: #fff; } 300+.pills .pill:hover .pill-x { opacity: 1; }
301+.pill-x { font-size: 10px; opacity: 0.6; }
302+.pills .pill-clear { background: var(--surface); border-color: var(--danger); color: var(--danger); box-shadow: none; }
303+.pills .pill-clear:hover { background: var(--danger); color: #fff; }
242 .chip-sep { width: 1px; align-self: stretch; background: var(--line); margin: 4px 4px; flex: none; } 304 .chip-sep { width: 1px; align-self: stretch; background: var(--line); margin: 4px 4px; flex: none; }
243 .link-btn { 305 .link-btn {
244 background: none; border: none; padding: 0; color: var(--blue); font: inherit; 306 background: none; border: none; padding: 0; color: var(--blue); font: inherit;
@@ -266,15 +328,17 @@ html, body { overflow-x: clip; }
266 /* .btn / .btn-primary / .btn-ghost : fournis par tokens.css (ka-ui). */ 328 /* .btn / .btn-primary / .btn-ghost : fournis par tokens.css (ka-ui). */
267 329
268 /* ================= Chips ================= */ 330 /* ================= Chips ================= */
269−.chips { display: flex; gap: 8px; margin: 16px 0 4px; overflow-x: auto; padding-bottom: 6px; scrollbar-width: none; } 331+.chips { display: flex; gap: 8px; margin: 18px 0 4px; overflow-x: auto; padding: 2px 0 8px; scrollbar-width: none; }
270 .chips::-webkit-scrollbar { display: none; } 332 .chips::-webkit-scrollbar { display: none; }
271 .chip { 333 .chip {
334+ display: inline-flex; align-items: center; gap: 7px;
272 border: 1.5px solid var(--ink); background: var(--surface); color: var(--ink); 335 border: 1.5px solid var(--ink); background: var(--surface); color: var(--ink);
273− border-radius: var(--r-pill); padding: 8px 18px; font-size: 13px; font-weight: 700; cursor: pointer; 336+ border-radius: var(--r-pill); padding: 9px 18px; font-size: 13px; font-weight: 700; cursor: pointer;
274− font-family: var(--font-display); white-space: nowrap; min-height: 40px; 337+ font-family: var(--font-display); white-space: nowrap; min-height: 42px;
275 transition: transform 0.13s, box-shadow 0.13s, background 0.13s, color 0.13s; 338 transition: transform 0.13s, box-shadow 0.13s, background 0.13s, color 0.13s;
276 } 339 }
277 .chip:hover { transform: translate(-1px, -1px); box-shadow: var(--shadow-off-mid); } 340 .chip:hover { transform: translate(-1px, -1px); box-shadow: var(--shadow-off-mid); }
341+.chip:active { transform: none; box-shadow: none; }
278 .chip.on { background: var(--ink); border-color: var(--ink); color: var(--accent); box-shadow: 3px 3px 0 var(--accent); } 342 .chip.on { background: var(--ink); border-color: var(--ink); color: var(--accent); box-shadow: 3px 3px 0 var(--accent); }
279 343
280 /* ================= Results ================= */ 344 /* ================= Results ================= */
@@ -542,9 +606,15 @@ html, body { overflow-x: clip; }
542 606
543 /* ================= Mobile : feuille de filtres + FAB ================= */ 607 /* ================= Mobile : feuille de filtres + FAB ================= */
544 .sheet-head { display: none; } 608 .sheet-head { display: none; }
609+.sheet-handle { display: none; }
545 .sheet-apply { display: none; } 610 .sheet-apply { display: none; }
546 .sheet-backdrop { display: none; } 611 .sheet-backdrop { display: none; }
547 .fab { display: none; } 612 .fab { display: none; }
613+.fab-badge {
614+ display: inline-grid; place-items: center; min-width: 20px; height: 20px; padding: 0 6px;
615+ border-radius: var(--r-pill); background: var(--white); color: var(--accent-deep);
616+ font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums; margin-left: 2px;
617+}
548 618
549 @media (max-width: 640px) { 619 @media (max-width: 640px) {
550 /* En-tête compact */ 620 /* En-tête compact */
@@ -554,6 +624,7 @@ html, body { overflow-x: clip; }
554 .ticker { font-size: 10.5px; padding: 6px 0; } 624 .ticker { font-size: 10.5px; padding: 6px 0; }
555 625
556 /* Héro resserré + stats en rangée défilante */ 626 /* Héro resserré + stats en rangée défilante */
627+ .hero::before { width: 320px; height: 260px; top: -30px; right: -90px; }
557 .hero h1 { font-size: clamp(30px, 8.6vw, 42px); } 628 .hero h1 { font-size: clamp(30px, 8.6vw, 42px); }
558 .hero p.lede { font-size: 15px; } 629 .hero p.lede { font-size: 15px; }
559 .stat-row { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: 6px; margin-right: -16px; padding-right: 16px; } 630 .stat-row { flex-wrap: nowrap; overflow-x: auto; scrollbar-width: none; padding-bottom: 6px; margin-right: -16px; padding-right: 16px; }
@@ -573,23 +644,31 @@ html, body { overflow-x: clip; }
573 position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-modal, 900); 644 position: fixed; left: 0; right: 0; bottom: 0; z-index: var(--z-modal, 900);
574 margin: 0; border-radius: 24px 24px 0 0; border: none; 645 margin: 0; border-radius: 24px 24px 0 0; border: none;
575 max-height: 82dvh; overflow-y: auto; -webkit-overflow-scrolling: touch; 646 max-height: 82dvh; overflow-y: auto; -webkit-overflow-scrolling: touch;
576− padding: 16px 18px calc(18px + env(safe-area-inset-bottom)); 647+ padding: 10px 18px calc(18px + env(safe-area-inset-bottom));
577 box-shadow: 0 -16px 48px rgba(20, 24, 20, 0.28); 648 box-shadow: 0 -16px 48px rgba(20, 24, 20, 0.28);
578− animation: sheet-up 0.22s ease; 649+ animation: sheet-up 0.24s cubic-bezier(0.2, 0.9, 0.3, 1);
579 } 650 }
580 @keyframes sheet-up { from { transform: translateY(30%); opacity: 0.4; } to { transform: none; opacity: 1; } } 651 @keyframes sheet-up { from { transform: translateY(30%); opacity: 0.4; } to { transform: none; opacity: 1; } }
652+ .filterbar.open .sheet-handle {
653+ display: block; flex: none; width: 44px; height: 5px; border-radius: var(--r-pill);
654+ background: var(--line); margin: 0 auto 2px;
655+ }
581 .filterbar.open .sheet-head { 656 .filterbar.open .sheet-head {
582 display: flex; justify-content: space-between; align-items: center; 657 display: flex; justify-content: space-between; align-items: center;
583 font-family: var(--font-display); font-weight: 700; font-size: 17px; 658 font-family: var(--font-display); font-weight: 700; font-size: 17px;
584 letter-spacing: -0.01em; color: var(--navy); 659 letter-spacing: -0.01em; color: var(--navy);
585− position: sticky; top: -16px; background: var(--surface); padding: 6px 0 8px; 660+ position: sticky; top: -10px; background: var(--surface); padding: 6px 0 8px;
586 border-bottom: 1px solid var(--line); margin-bottom: 2px; z-index: 1; 661 border-bottom: 1px solid var(--line); margin-bottom: 2px; z-index: 1;
587 } 662 }
588 .sheet-close { 663 .sheet-close {
589 border: 1.5px solid var(--ink); background: var(--surface); border-radius: 50%; 664 border: 1.5px solid var(--ink); background: var(--surface); border-radius: 50%;
590 width: 36px; height: 36px; font-size: 15px; cursor: pointer; line-height: 1; color: var(--navy); 665 width: 36px; height: 36px; font-size: 15px; cursor: pointer; line-height: 1; color: var(--navy);
591 } 666 }
592− .filterbar.open .sheet-apply { display: block; width: 100%; } 667+ .filterbar.open .sheet-apply {
668+ display: block; width: 100%; min-height: 50px;
669+ position: sticky; bottom: 0; z-index: 1;
670+ box-shadow: 0 -14px 18px -12px rgba(20, 24, 20, 0.35), 5px 5px 0 var(--accent);
671+ }
593 .sheet-backdrop { 672 .sheet-backdrop {
594 display: block; position: fixed; inset: 0; z-index: var(--z-overlay, 800); 673 display: block; position: fixed; inset: 0; z-index: var(--z-overlay, 800);
595 background: rgba(20, 24, 20, 0.45); backdrop-filter: blur(2px); 674 background: rgba(20, 24, 20, 0.45); backdrop-filter: blur(2px);
@@ -674,15 +753,17 @@ html, body { overflow-x: clip; }
674 box-shadow: var(--shadow-flat); 753 box-shadow: var(--shadow-flat);
675 } 754 }
676 .view-toggle button { 755 .view-toggle button {
677− border: 0; background: transparent; padding: 7px 16px; cursor: pointer; 756+ border: 0; background: transparent; padding: 8px 16px; cursor: pointer;
678− font-size: 12.5px; font-weight: 600; color: var(--ink-2); 757+ font-size: 12.5px; font-weight: 700; color: var(--ink-2);
758+ font-family: var(--font-display); transition: background 0.12s ease, color 0.12s ease;
679 } 759 }
760+.view-toggle button:hover { background: var(--grey); color: var(--ink); }
680 /* zone tactile >= 44 px au doigt (coarse pointer = mobile/tablette) */ 761 /* zone tactile >= 44 px au doigt (coarse pointer = mobile/tablette) */
681 @media (pointer: coarse) { 762 @media (pointer: coarse) {
682 .view-toggle button { min-height: 44px; padding: 10px 18px; } 763 .view-toggle button { min-height: 44px; padding: 10px 18px; }
683 } 764 }
684 .view-toggle button + button { border-left: 1px solid var(--line); } 765 .view-toggle button + button { border-left: 1px solid var(--line); }
685−.view-toggle button.on { background: var(--blue); color: var(--white); } 766+.view-toggle button.on { background: var(--ink); color: var(--white); box-shadow: inset 0 -2.5px 0 var(--accent); }
686 767
687 .map-split { 768 .map-split {
688 display: grid; grid-template-columns: minmax(300px, 400px) 1fr; gap: 18px; 769 display: grid; grid-template-columns: minmax(300px, 400px) 1fr; gap: 18px;
689 770
Menu

Theme