SPB Git

spb/job-ka

Public

apparence : classes métier alignées sur la signature « éditorial sharp » Groupe KA

- job-card/sheet/tile/table : bordures encre 1,5 px + ombres décalées
  (--shadow-off-*), hover translate signature, tuiles avec liseré accent.
- badges → chips du groupe (mono 10,5 px, uppercase, pilule bordée) ;
  salaire (vert bordé) et « offre directe » (accent) conservent leur sens.
- filtres du héros : champs sharp (bordure encre, focus 3px 3px 0 accent,
  case « Salaire affiché » cochée = fond accent-soft).
- héros : kicker signature « Pages carrières · Zéro intermédiaire » +
  surligné d'accent incliné (.hl) sur « à la source ».
- pagination et titres de section en font-display 700 ; identité propre à
  l'emploi conservée (header encre, accent cyan, transparence salariale).
- Vérifié Playwright : accueil desktop/mobile + fiche (localhost:8096),
  build Vite OK, pm2 job-ka-web redémarré, www.job-ka.com 200.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Simon-Pierre Boucher committed (Aug 23, 2026) parent a5260cc Browse files

3 changed files +81 −51

modified frontend/src/pages/Home.tsx +2 −1
@@ -5,7 +5,7 @@
5 * Contact : contact@spboucher.ai 5 * Contact : contact@spboucher.ai
6 * Fichier : frontend/src/pages/Home.tsx 6 * Fichier : frontend/src/pages/Home.tsx
7 * Rôle : Page d'accueil — recherche, filtres, liste paginée des offres 7 * Rôle : Page d'accueil — recherche, filtres, liste paginée des offres
8− * Créé : 2026-08-17 Modifié : 2026-08-17 8+ * Créé : 2026-08-17 Modifié : 2026-08-22
9 * ============================================================================= 9 * =============================================================================
10 */ 10 */
11 import { useEffect, useMemo, useState } from "react"; 11 import { useEffect, useMemo, useState } from "react";
@@ -60,6 +60,7 @@ export default function Home() {
60 <> 60 <>
61 <section className="hero"> 61 <section className="hero">
62 <div className="container"> 62 <div className="container">
63+ <span className="kicker">Pages carrières · Zéro intermédiaire</span>
63 <h1>L'emploi au Québec, <em>à la source</em>.</h1> 64 <h1>L'emploi au Québec, <em>à la source</em>.</h1>
64 <p> 65 <p>
65 Job·Ka agrège les offres directement depuis les pages carrières des 66 Job·Ka agrège les offres directement depuis les pages carrières des
modified frontend/src/pages/Job.tsx +2 −2
@@ -5,7 +5,7 @@
5 * Contact : contact@spboucher.ai 5 * Contact : contact@spboucher.ai
6 * Fichier : frontend/src/pages/Job.tsx 6 * Fichier : frontend/src/pages/Job.tsx
7 * Rôle : Fiche d'une offre — faits, description, lien vers l'offre originale 7 * Rôle : Fiche d'une offre — faits, description, lien vers l'offre originale
8− * Créé : 2026-08-17 Modifié : 2026-08-17 8+ * Créé : 2026-08-17 Modifié : 2026-08-22
9 * ============================================================================= 9 * =============================================================================
10 */ 10 */
11 import { useEffect, useState } from "react"; 11 import { useEffect, useState } from "react";
@@ -40,7 +40,7 @@ export default function JobPage() {
40 <img 40 <img
41 src={job.company_logo} 41 src={job.company_logo}
42 alt={`Logo ${job.employer}`} 42 alt={`Logo ${job.employer}`}
43− style={{ width: 56, height: 56, objectFit: "contain", borderRadius: 8, background: "#fff", border: "1px solid var(--border, #e5e5e5)", flexShrink: 0 }} 43+ style={{ width: 56, height: 56, objectFit: "contain", borderRadius: 8, background: "#fff", border: "1.5px solid var(--ink)", flexShrink: 0 }}
44 onError={(e) => { (e.target as HTMLImageElement).style.display = "none"; }} 44 onError={(e) => { (e.target as HTMLImageElement).style.display = "none"; }}
45 /> 45 />
46 )} 46 )}
modified frontend/src/styles.css +77 −48
@@ -7,9 +7,11 @@ Fichier : frontend/src/styles.css
7 Rôle : CSS local Job·Ka — s'appuie sur le design system commun Groupe KA 7 Rôle : CSS local Job·Ka — s'appuie sur le design system commun Groupe KA
8 (ka/tokens.css, importé AVANT ce fichier dans main.tsx). Ici : 8 (ka/tokens.css, importé AVANT ce fichier dans main.tsx). Ici :
9 seulement l'accent de la marque + les classes métier (offres, 9 seulement l'accent de la marque + les classes métier (offres,
10− filtres, carte). Le socle (body, grain, sélection, .container, 10+ filtres, carte) au style « éditorial sharp » du groupe (bordures
11− .btn, .card, .chip, ka-footer…) vit dans tokens.css. 11+ encre 1,5 px + ombres décalées dures, étiquettes mono). Le socle
12−Créé : 2026-08-17 Modifié : 2026-08-17 12+ (body, grain, sélection, .container, .btn, .card, .chip,
13+ ka-footer…) vit dans tokens.css.
14+Créé : 2026-08-17 Modifié : 2026-08-22
13 ============================================================================= 15 =============================================================================
14 */ 16 */
15 17
@@ -147,71 +149,92 @@ nav.main a.active { color: var(--accent-soft); background: rgb(255 255 255 / 10%
147 .mobile-menu { display: block; } 149 .mobile-menu { display: block; }
148 } 150 }
149 151
150−/* --- héros ------------------------------------------------------------------ */ 152+/* --- héros (encre — identité Job·Ka) ---------------------------------------- */
151−.hero { background: var(--brand); color: #fff; padding: 40px 0 34px; } 153+.hero { background: var(--brand); color: #fff; padding: 42px 0 36px; }
152−.hero h1 { margin: 0 0 6px; font-size: 30px; font-weight: 700; letter-spacing: -0.5px; color: #fff; } 154+.hero .kicker { color: var(--accent-soft); }
153−.hero h1 em { color: var(--accent-soft); font-style: normal; } 155+.hero .kicker::before { background: var(--accent); }
154−.hero p { margin: 0 0 20px; color: #b9c2be; max-width: 640px; } 156+.hero h1 { margin: 6px 0 8px; font-size: clamp(28px, 2.6vw + 16px, 42px); font-weight: 700; letter-spacing: -0.03em; color: #fff; line-height: 1.08; }
157+.hero h1 em {
158+ /* surligné d'accent incliné — signature du groupe (.hl), déclinaison encre */
159+ display: inline-block; font-style: normal; background: var(--accent);
160+ color: var(--on-accent); border-radius: 8px; padding: 0 10px 2px;
161+ transform: rotate(-1deg);
162+}
163+.hero p { margin: 0 0 22px; color: #b9c2be; max-width: 640px; }
155 164
156−/* --- filtres ------------------------------------------------------------------ */ 165+/* --- filtres (champs sharp : bordure encre + focus accent décalé) ------------ */
157 .filters { display: flex; flex-wrap: wrap; gap: 10px; } 166 .filters { display: flex; flex-wrap: wrap; gap: 10px; }
158 .filters input[type="search"], .filters select { 167 .filters input[type="search"], .filters select {
159− height: 42px; padding: 0 12px; border-radius: 10px; border: 1px solid var(--border); 168+ height: 44px; padding: 0 12px; border-radius: var(--r-ctl);
160− background: #fff; color: var(--ink); font: inherit; min-width: 130px; 169+ border: 1.5px solid var(--ink);
170+ background: var(--surface); color: var(--ink); font: inherit; min-width: 130px;
171+}
172+.filters input[type="search"]:focus, .filters select:focus {
173+ outline: none; box-shadow: 3px 3px 0 var(--accent);
161 } 174 }
162 .filters input[type="search"] { flex: 1 1 220px; } 175 .filters input[type="search"] { flex: 1 1 220px; }
176+.filters input[type="search"]::placeholder { color: var(--ink-3); }
163 .filters label.check { 177 .filters label.check {
164− display: inline-flex; align-items: center; gap: 7px; background: #fff; 178+ display: inline-flex; align-items: center; gap: 7px; background: var(--surface);
165 color: var(--ink); /* le héros est blanc sur encre — ne pas hériter */ 179 color: var(--ink); /* le héros est blanc sur encre — ne pas hériter */
166− border: 1px solid var(--border); border-radius: 10px; padding: 0 14px; 180+ border: 1.5px solid var(--ink); border-radius: var(--r-ctl); padding: 0 14px;
167− height: 42px; cursor: pointer; user-select: none; white-space: nowrap; 181+ height: 44px; cursor: pointer; user-select: none; white-space: nowrap;
182+}
183+.filters label.check:has(input:checked) {
184+ background: var(--accent-soft); box-shadow: 3px 3px 0 var(--accent);
168 } 185 }
169 /* champs >=16px sur mobile : évite le zoom automatique d'iOS au focus */ 186 /* champs >=16px sur mobile : évite le zoom automatique d'iOS au focus */
170 @media (max-width: 700px) { 187 @media (max-width: 700px) {
171 .filters input[type="search"], .filters select, .filters label.check { font-size: 16px; } 188 .filters input[type="search"], .filters select, .filters label.check { font-size: 16px; }
172 } 189 }
173 190
174−/* --- cartes d'offres ------------------------------------------------------------ */ 191+/* --- cartes d'offres (sharp : bordure encre + ombre décalée) --------------------- */
175−.job-list { display: grid; gap: 12px; margin: 22px 0; } 192+.job-list { display: grid; gap: 14px; margin: 22px 0; }
176 .job-card { 193 .job-card {
177− display: block; background: var(--surface); border: 1px solid var(--border); 194+ display: block; background: var(--surface); border: 1.5px solid var(--ink);
178− border-radius: var(--radius); padding: 18px 20px; color: inherit; 195+ border-radius: var(--r-card); box-shadow: var(--shadow-off-soft);
179− transition: border-color 0.12s, box-shadow 0.12s; 196+ padding: 18px 20px; color: inherit;
180−} 197+ transition: transform 0.15s, box-shadow 0.15s;
181−.job-card:hover { border-color: var(--accent); box-shadow: var(--shadow); text-decoration: none; } 198+}
182−.job-card h3 { margin: 0 0 2px; font-size: 17px; font-weight: 700; color: var(--ink); } 199+.job-card:hover { transform: translate(-2px, -2px); box-shadow: var(--shadow-off-mid); text-decoration: none; }
200+.job-card h3 { margin: 0 0 2px; font-family: var(--font-display); font-size: 17.5px; font-weight: 700; color: var(--ink); letter-spacing: -0.02em; }
201+.job-card:hover h3 { text-decoration: underline; text-decoration-color: var(--accent); text-decoration-thickness: 2px; text-underline-offset: 3px; }
183 .job-card .employer { color: var(--accent-deep); font-weight: 600; } 202 .job-card .employer { color: var(--accent-deep); font-weight: 600; }
184−.job-card .meta { color: var(--ink-3); font-size: 13.5px; margin-top: 6px; display: flex; flex-wrap: wrap; gap: 6px 14px; } 203+.job-card .meta { color: var(--ink-3); font-size: 13px; margin-top: 8px; display: flex; flex-wrap: wrap; align-items: center; gap: 6px 12px; }
185 204
205+/* étiquettes façon .chip du groupe : mono, uppercase, pilule bordée */
186 .badge { 206 .badge {
187− display: inline-block; padding: 2px 9px; border-radius: 999px; 207+ display: inline-flex; align-items: center; gap: 5px;
188− font-size: 12.5px; font-weight: 600; background: var(--surface-2); color: var(--ink-2); 208+ padding: 3px 10px; border-radius: var(--r-pill);
189−} 209+ font-family: var(--font-mono); font-size: 10.5px; font-weight: 700;
190−.badge.salary { background: var(--green-soft); color: var(--green); } 210+ text-transform: uppercase; letter-spacing: 0.05em;
191−.badge.mode { background: var(--accent-soft); color: var(--accent-deep); } 211+ background: var(--surface-2); color: var(--ink-2);
192−.badge.direct { 212+ border: 1.5px solid var(--line);
193− background: transparent;
194− border: 1px solid var(--accent, #0c8599);
195− color: var(--accent-deep, #0b7285);
196 } 213 }
214+.badge.salary { background: var(--green-soft); color: var(--green); border-color: var(--green); }
215+.badge.mode { background: var(--accent-soft); color: var(--accent-deep); border-color: var(--line); }
216+.badge.direct { background: transparent; border-color: var(--accent); color: var(--accent-deep); }
197 217
198 /* --- fiche ------------------------------------------------------------------------- */ 218 /* --- fiche ------------------------------------------------------------------------- */
199 .sheet { 219 .sheet {
200− background: var(--surface); border: 1px solid var(--border); 220+ background: var(--surface); border: 1.5px solid var(--ink);
201− border-radius: var(--radius); padding: 28px 32px; margin: 24px 0; 221+ border-radius: var(--r-card); box-shadow: var(--shadow-off-soft);
222+ padding: 28px 32px; margin: 24px 0;
202 } 223 }
203 .sheet h1 { margin: 0 0 4px; font-size: 24px; letter-spacing: -0.3px; } 224 .sheet h1 { margin: 0 0 4px; font-size: 24px; letter-spacing: -0.3px; }
204 .sheet .facts { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 20px; } 225 .sheet .facts { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 20px; }
205 .sheet .description { white-space: pre-line; color: var(--ink-2); } 226 .sheet .description { white-space: pre-line; color: var(--ink-2); }
206 227
207 /* --- tuiles de statistiques (hero numbers) --------------------------------------- */ 228 /* --- tuiles de statistiques (hero numbers) --------------------------------------- */
208−.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 12px; margin: 22px 0; } 229+.tiles { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; margin: 22px 0; }
209 .tile { 230 .tile {
210− background: var(--surface); border: 1px solid var(--border); 231+ background: var(--surface); border: 1.5px solid var(--ink);
211− border-radius: var(--radius); padding: 18px 20px; 232+ border-radius: var(--r-card); box-shadow: var(--shadow-off-soft);
233+ padding: 18px 20px; position: relative; overflow: hidden;
212 } 234 }
213−.tile .value { font-family: var(--font-display); font-size: 26px; font-weight: 700; letter-spacing: -0.5px; } 235+.tile::before { content: ""; position: absolute; top: 0; left: 0; right: 0; height: 4px; background: var(--accent); }
214−.tile .label { color: var(--ink-3); font-size: 13px; margin-top: 2px; } 236+.tile .value { font-family: var(--font-display); font-size: 27px; font-weight: 700; letter-spacing: -0.5px; }
237+.tile .label { color: var(--ink-3); font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; margin-top: 4px; }
215 238
216 /* --- barres horizontales (magnitude, teinte unique) --------------------------------- */ 239 /* --- barres horizontales (magnitude, teinte unique) --------------------------------- */
217 .bars { display: grid; gap: 8px; margin: 10px 0 26px; } 240 .bars { display: grid; gap: 8px; margin: 10px 0 26px; }
@@ -222,9 +245,9 @@ nav.main a.active { color: var(--accent-soft); background: rgb(255 255 255 / 10%
222 .bar-row .n { font-size: 13px; color: var(--ink-2); text-align: right; font-variant-numeric: tabular-nums; } 245 .bar-row .n { font-size: 13px; color: var(--ink-2); text-align: right; font-variant-numeric: tabular-nums; }
223 246
224 /* --- tableaux ----------------------------------------------------------------------- */ 247 /* --- tableaux ----------------------------------------------------------------------- */
225−table.data { width: 100%; border-collapse: collapse; background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); overflow: hidden; } 248+table.data { width: 100%; border-collapse: separate; border-spacing: 0; background: var(--surface); border: 1.5px solid var(--ink); border-radius: var(--r-card); overflow: hidden; box-shadow: var(--shadow-off-soft); }
226 table.data th, table.data td { text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--border); font-size: 14px; } 249 table.data th, table.data td { text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--border); font-size: 14px; }
227−table.data th { background: var(--surface-2); color: var(--ink-2); font-weight: 600; } 250+table.data th { background: var(--surface-2); color: var(--ink-2); font-family: var(--font-mono); font-size: 10.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.08em; border-bottom: 1.5px solid var(--ink); }
228 table.data tr:last-child td { border-bottom: none; } 251 table.data tr:last-child td { border-bottom: none; }
229 252
230 /* --- carte -------------------------------------------------------------------------- */ 253 /* --- carte -------------------------------------------------------------------------- */
@@ -238,21 +261,27 @@ table.data tr:last-child td { border-bottom: none; }
238 .map-wrap .maplibregl-map { height: 100%; } 261 .map-wrap .maplibregl-map { height: 100%; }
239 .map-count { 262 .map-count {
240 position: absolute; top: 14px; left: 14px; z-index: 5; 263 position: absolute; top: 14px; left: 14px; z-index: 5;
241− background: var(--brand); color: #fff; border-radius: 10px; 264+ background: var(--brand); color: #fff; border-radius: var(--r-card);
242− padding: 8px 14px; font-size: 13.5px; box-shadow: var(--shadow); 265+ border: 1.5px solid var(--ink); box-shadow: var(--shadow-off-mid);
266+ padding: 8px 14px; font-size: 13px; font-family: var(--font-display); font-weight: 700;
243 } 267 }
244 .map-popup h4 { margin: 0 0 2px; font-size: 14px; } 268 .map-popup h4 { margin: 0 0 2px; font-size: 14px; }
245 .map-popup { font: 13px "Inter", sans-serif; } 269 .map-popup { font: 13px "Inter", sans-serif; }
246 270
247 /* --- pagination / divers ------------------------------------------------------------- */ 271 /* --- pagination / divers ------------------------------------------------------------- */
248−.pager { display: flex; gap: 8px; justify-content: center; margin: 26px 0; } 272+.pager { display: flex; gap: 10px; justify-content: center; margin: 26px 0; }
249 .pager button { 273 .pager button {
250− background: var(--surface); border: 1px solid var(--border); border-radius: 8px; 274+ background: var(--surface); border: 1.5px solid var(--ink); border-radius: var(--r-ctl);
251− padding: 8px 16px; cursor: pointer; font: inherit; min-height: var(--touch); 275+ padding: 8px 16px; cursor: pointer; font: inherit;
252−} 276+ font-family: var(--font-display); font-weight: 700; font-size: 14px;
277+ min-height: var(--touch);
278+ transition: transform 0.15s, box-shadow 0.15s;
279+}
280+.pager button:hover:not(:disabled) { transform: translate(-2px, -2px); box-shadow: var(--shadow-off-mid); }
281+.pager button:active { transform: none; box-shadow: none; }
253 .pager button:disabled { opacity: 0.4; cursor: default; } 282 .pager button:disabled { opacity: 0.4; cursor: default; }
254 .empty { text-align: center; color: var(--ink-3); padding: 60px 0; } 283 .empty { text-align: center; color: var(--ink-3); padding: 60px 0; }
255−.section-title { font-size: 19px; font-weight: 700; margin: 30px 0 4px; } 284+.section-title { font-family: var(--font-display); font-size: 19px; font-weight: 700; letter-spacing: -0.02em; margin: 30px 0 4px; }
256 .muted { color: var(--ink-3); font-size: 13px; } 285 .muted { color: var(--ink-3); font-size: 13px; }
257 286
258 /* --- page Contact (commune Groupe KA) -------------------------------------------------- */ 287 /* --- page Contact (commune Groupe KA) -------------------------------------------------- */
259 288
Menu

Theme