Groupe KA — site du holding + KA ID (compte unique & SSO des 7 plateformes). Next.js 16, SQLite, Google & Apple login.
TypeScript 70.4%
HTML 18.4%
JavaScript 4%
Python 3.8%
CSS 3.4%
1<!DOCTYPE html>2<!-- Auteur : Simon-Pierre Boucher — contact@spboucher.ai -->3<!-- Document « L'agrégation, expliquée » — 12 pages A4 paysage.4 Rendu PDF : chromium --headless --print-to-pdf (les figures sont générées en JS). -->5<html lang="fr">6<head>7<meta charset="UTF-8" />8<title>Groupe KA — L'agrégation, expliquée</title>9<link rel="preconnect" href="https://fonts.googleapis.com" />10<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />11<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;700&family=Inter:wght@400;600&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet" />12<style>13 :root {14 --paper: #f5f3ee;15 --surface: #ffffff;16 --ink: #141814;17 --ink-2: #4d5551;18 --ink-3: #8b928c;19 --green: #1c5c41;20 --green-deep: #123f2e;21 --lime: #d9f26b;22 --lime-soft: #f0f9d2;23 --display: "Space Grotesk", system-ui, sans-serif;24 --body: "Inter", system-ui, sans-serif;25 --mono: "JetBrains Mono", ui-monospace, monospace;26 }27 * { margin: 0; padding: 0; box-sizing: border-box; }28 @page { size: 297mm 210mm; margin: 0; }29 html, body { background: #1a1e1a; }30 body { font-family: var(--body); color: var(--ink); }3132 .page {33 width: 297mm;34 height: 210mm;35 background: var(--paper);36 position: relative;37 overflow: hidden;38 page-break-after: always;39 padding: 12mm 14mm 11mm;40 display: flex;41 flex-direction: column;42 }43 .page::after {44 content: "";45 position: absolute; inset: 0;46 pointer-events: none;47 opacity: 0.05;48 background-image: radial-gradient(var(--ink) 0.6px, transparent 0.6px);49 background-size: 5px 5px;50 }51 .page.dark { background: var(--ink); color: var(--paper); }52 .page.dark::after { background-image: radial-gradient(var(--lime) 0.6px, transparent 0.6px); opacity: 0.04; }5354 .mono { font-family: var(--mono); }55 .display { font-family: var(--display); }5657 /* ---------- En-tête / pied de page communs ---------- */58 .phead {59 display: flex;60 align-items: baseline;61 justify-content: space-between;62 border-bottom: 2px solid var(--ink);63 padding-bottom: 4mm;64 }65 .dark .phead { border-bottom-color: rgba(245,243,238,0.25); }66 .wordmark {67 font-family: var(--display);68 font-weight: 700;69 font-size: 17px;70 letter-spacing: -0.04em;71 display: inline-flex;72 align-items: baseline;73 gap: 5px;74 }75 .kabox {76 display: inline-block;77 background: var(--ink);78 color: var(--lime);79 border-radius: 5px;80 padding: 0 6px 2px;81 transform: rotate(-2deg);82 }83 .dark .kabox { background: var(--lime); color: var(--ink); }84 .phead .doc {85 font-family: var(--mono);86 font-weight: 700;87 font-size: 9px;88 letter-spacing: 0.16em;89 text-transform: uppercase;90 color: var(--ink-3);91 }92 .dark .phead .doc { color: rgba(245,243,238,0.55); }93 .pnum { font-family: var(--mono); font-weight: 700; font-size: 10px; color: var(--green); }94 .dark .pnum { color: var(--lime); }9596 .pfoot {97 margin-top: auto;98 border-top: 1.5px dashed rgba(20,24,20,0.3);99 padding-top: 3mm;100 display: flex;101 justify-content: space-between;102 font-family: var(--mono);103 font-size: 8.5px;104 letter-spacing: 0.1em;105 text-transform: uppercase;106 color: var(--ink-3);107 }108 .dark .pfoot { border-top-color: rgba(245,243,238,0.2); color: rgba(245,243,238,0.5); }109110 /* ---------- Typo de section ---------- */111 .kicker {112 font-family: var(--mono);113 font-weight: 700;114 font-size: 10px;115 letter-spacing: 0.18em;116 text-transform: uppercase;117 color: var(--green);118 display: inline-flex;119 align-items: center;120 gap: 8px;121 margin-top: 6mm;122 }123 .kicker::before { content: ""; width: 22px; height: 2px; background: var(--green); }124 .dark .kicker { color: var(--lime); }125 .dark .kicker::before { background: var(--lime); }126 h2 {127 font-family: var(--display);128 font-weight: 700;129 font-size: 34px;130 line-height: 1;131 letter-spacing: -0.03em;132 text-transform: uppercase;133 margin-top: 3.5mm;134 }135 .hl {136 display: inline-block;137 background: var(--lime);138 color: var(--ink);139 border-radius: 6px;140 padding: 0 8px 2px;141 transform: rotate(-1deg);142 }143 .outline { color: transparent; -webkit-text-stroke: 2px var(--ink); }144 .dark .outline { -webkit-text-stroke: 2px var(--paper); }145 .lede { margin-top: 3.5mm; font-size: 12px; line-height: 1.55; color: var(--ink-2); max-width: 150mm; }146 .dark .lede { color: rgba(245,243,238,0.75); }147148 /* ---------- Cartes & pilules ---------- */149 .card {150 background: var(--surface);151 border: 1.5px solid var(--ink);152 border-radius: 9px;153 box-shadow: 6px 6px 0 rgba(20,24,20,0.12);154 }155 .chip {156 display: inline-flex;157 align-items: center;158 gap: 6px;159 padding: 5px 11px;160 background: var(--surface);161 border: 1.5px solid var(--ink);162 border-radius: 999px;163 font-family: var(--mono);164 font-size: 9.5px;165 font-weight: 700;166 box-shadow: 3px 3px 0 rgba(20,24,20,0.12);167 white-space: nowrap;168 }169 .caption {170 border-top: 1.5px solid var(--ink);171 background: #faf9f5;172 padding: 3mm 5mm;173 font-size: 10.5px;174 color: var(--ink-2);175 border-radius: 0 0 8px 8px;176 }177 .caption b { font-family: var(--mono); color: var(--green); }178179 /* ---------- Page 1 : couverture ---------- */180 .cover h1 {181 font-family: var(--display);182 font-weight: 700;183 font-size: 96px;184 line-height: 0.95;185 letter-spacing: -0.04em;186 text-transform: uppercase;187 margin-top: 8mm;188 }189 .cover .sub { margin-top: 7mm; font-size: 14.5px; color: var(--ink-2); max-width: 165mm; line-height: 1.6; }190 .cover-chips { display: flex; gap: 8px; margin-top: 8mm; flex-wrap: wrap; }191 .cover-marks { display: flex; gap: 6px; margin-top: auto; flex-wrap: wrap; padding-bottom: 2mm; }192 .markpill {193 font-family: var(--display); font-weight: 700; font-size: 12.5px;194 border: 1.5px solid var(--ink); border-radius: 999px; padding: 4px 12px 5px;195 background: var(--surface); box-shadow: 3px 3px 0 rgba(20,24,20,0.15);196 }197 .markpill i { font-style: normal; border-radius: 4px; padding: 0 4px 1px; margin-left: 2px; display: inline-block; transform: rotate(-2deg); }198199 /* ---------- Page 2 : définition ---------- */200 .def-grid { display: grid; grid-template-columns: 1.15fr 1fr; gap: 8mm; margin-top: 7mm; align-items: stretch; }201 .defcard { padding: 8mm 9mm; }202 .defcard .word { font-family: var(--display); font-weight: 700; font-size: 52px; letter-spacing: -0.03em; }203 .defcard .pos { font-family: var(--mono); font-size: 12px; color: var(--ink-3); margin-left: 8px; }204 .defcard ol { margin-top: 6mm; list-style: none; }205 .defcard li { display: flex; gap: 10px; font-size: 12.5px; line-height: 1.55; color: var(--ink-2); margin-top: 4mm; }206 .defcard li b.n { font-family: var(--mono); color: var(--green); }207 .defcard .quote { margin-top: 6mm; border-top: 1.5px dashed rgba(20,24,20,0.3); padding-top: 5mm; font-style: italic; font-size: 12.5px; color: var(--ink-2); }208 .eqcard { background: var(--ink); color: var(--paper); border-radius: 9px; border: 1.5px solid var(--ink); padding: 8mm 9mm; box-shadow: 6px 6px 0 rgba(20,24,20,0.25); display: flex; flex-direction: column; }209 .eqcard .k { font-family: var(--mono); font-weight: 700; font-size: 10px; letter-spacing: 0.18em; text-transform: uppercase; color: var(--lime); }210 .eqcard .eq { font-family: var(--display); font-weight: 700; font-size: 33px; line-height: 1.12; letter-spacing: -0.03em; text-transform: uppercase; margin-top: 5mm; }211 .eqcard .eq .lime { color: var(--lime); }212 .eqcard p { margin-top: 5mm; font-size: 11.5px; line-height: 1.6; color: rgba(245,243,238,0.75); }213214 /* ---------- Figures pleine page ---------- */215 .figwrap { margin-top: 5mm; border: 1.5px solid var(--ink); border-radius: 9px; background: var(--surface); box-shadow: 6px 6px 0 rgba(20,24,20,0.12); overflow: hidden; flex: 1; display: flex; flex-direction: column; }216 .figwrap svg { display: block; width: 100%; flex: 1; }217 .figbody { flex: 1; display: flex; align-items: center; justify-content: center; padding: 4mm 6mm; }218219 /* ---------- Pages barres & matrice ---------- */220 .bars { padding: 5.5mm 9mm 4mm; }221 .barrow { margin-top: 3.8mm; }222 .barrow:first-child { margin-top: 0; }223 .barhead { display: flex; justify-content: space-between; align-items: baseline; }224 .barhead .nm { font-family: var(--display); font-weight: 700; font-size: 13px; display: inline-flex; align-items: center; gap: 7px; }225 .brand { width: 13px; height: 13px; border-radius: 3.5px; background: var(--ink); display: inline-flex; align-items: center; justify-content: center; }226 .brand i { width: 8px; height: 8px; border-radius: 2px; display: block; }227 .barhead .u { font-family: var(--mono); font-size: 9px; color: var(--ink-3); font-weight: 400; margin-left: 4px; }228 .barhead .v { font-family: var(--mono); font-weight: 700; font-size: 11.5px; }229 .bartrack { margin-top: 1.5mm; height: 4.4mm; background: rgba(20,24,20,0.06); border-radius: 0 3px 3px 0; }230 .barfill { height: 100%; background: var(--green); border-radius: 0 3px 3px 0; }231232 .dots-block { margin-top: 4.2mm; }233 .dots-block:first-child { margin-top: 0; }234 .dots { display: flex; flex-wrap: wrap; gap: 2.1px; margin-top: 1.6mm; max-width: 235mm; }235 .dots i { width: 6.5px; height: 6.5px; border-radius: 2px; background: var(--green); display: block; }236237 /* ---------- Page moteurs d'évaluation ---------- */238 .eval-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8mm; margin-top: 6mm; flex: 1; }239 .evalcard { padding: 8mm 9mm; display: flex; flex-direction: column; }240 .evalcard .k { font-family: var(--mono); font-weight: 700; font-size: 9.5px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); display: flex; align-items: center; gap: 7px; }241 .evalcard .big { font-family: var(--display); font-weight: 700; font-size: 46px; letter-spacing: -0.03em; margin-top: 4mm; }242 .evalcard .lbl { font-family: var(--display); font-weight: 700; font-size: 13px; text-transform: uppercase; color: var(--green); margin-top: 1mm; }243 .evalcard p { font-size: 11px; color: var(--ink-2); margin-top: 3mm; line-height: 1.55; }244 .gauge { margin-top: auto; padding-top: 6mm; }245 .gauge .glab { display: flex; justify-content: space-between; font-family: var(--mono); font-size: 8.5px; color: var(--ink-3); margin-bottom: 1.4mm; }246 .gtrack { position: relative; height: 7mm; border: 1.5px solid var(--ink); border-radius: 5px; background: var(--surface); overflow: hidden; }247 .gband { position: absolute; top: 0; bottom: 0; background: var(--lime); opacity: 0.85; }248 .gmid { position: absolute; top: -1mm; bottom: -1mm; width: 2.2px; background: var(--ink); }249250 /* ---------- Page socle : tableau ---------- */251 .tbl { margin-top: 6mm; border: 1.5px solid var(--ink); border-radius: 9px; overflow: hidden; background: var(--surface); box-shadow: 6px 6px 0 rgba(20,24,20,0.12); }252 table { width: 100%; border-collapse: collapse; font-size: 11px; }253 th { font-family: var(--mono); font-size: 8.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; text-align: left; color: var(--ink-3); background: #faf9f5; padding: 2.6mm 4mm; border-bottom: 1.5px solid var(--ink); }254 td { padding: 2.45mm 4mm; border-bottom: 1px solid rgba(20,24,20,0.14); vertical-align: middle; }255 tr:last-child td { border-bottom: none; }256 td.nm { font-family: var(--display); font-weight: 700; white-space: nowrap; }257 td.url { font-family: var(--mono); font-size: 9.5px; white-space: nowrap; color: var(--green); }258 td .brand { vertical-align: -2px; margin-right: 6px; }259260 /* ---------- Page manifeste (fin, sombre) ---------- */261 .mani-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 7mm; margin-top: 8mm; }262 .mani { border: 1.5px solid rgba(245,243,238,0.3); border-radius: 9px; padding: 7mm; }263 .mani .n { font-family: var(--mono); font-weight: 700; font-size: 11px; color: var(--lime); }264 .mani h3 { font-family: var(--display); font-weight: 700; font-size: 16.5px; text-transform: uppercase; margin-top: 3mm; }265 .mani p { font-size: 11px; line-height: 1.6; color: rgba(245,243,238,0.75); margin-top: 3mm; }266 .contact { margin-top: 10mm; display: flex; gap: 6mm; align-items: baseline; flex-wrap: wrap; }267 .contact .mail { font-family: var(--mono); font-weight: 700; font-size: 13px; color: var(--lime); }268 .contact .role { font-family: var(--mono); font-size: 9px; color: rgba(245,243,238,0.5); }269270 /* ---------- Légendes SVG en HTML ---------- */271 svg text { font-family: var(--mono); }272 svg .t-display { font-family: var(--display); }273 svg .t-body { font-family: var(--body); }274</style>275</head>276<body>277278<!-- ============================ PAGE 1 — COUVERTURE ============================ -->279<section class="page cover">280 <header class="phead">281 <span class="wordmark">Groupe <span class="kabox">KA</span></span>282 <span class="doc">Document de référence · 2026</span>283 <span class="pnum">01 / 12</span>284 </header>285 <p class="kicker">Holding d'agrégateurs automatisés · Québec</p>286 <h1>L'agrégation,<br /><span class="outline">expliquée</span> <span class="hl">·Ka</span></h1>287 <p class="sub">288 Comment mille sites deviennent un seul endroit : les connecteurs, le pipeline, le cycle,289 les éclaireurs, le moteur de recherche et les dix plateformes du Groupe KA — chaque290 mécanisme dessiné, chaque chiffre compté. Zéro saisie manuelle, zéro boîte noire.291 </p>292 <div class="cover-chips">293 <span class="chip">10 agrégateurs en ligne</span>294 <span class="chip">1 moteur de recherche québécois</span>295 <span class="chip">450+ connecteurs sources</span>296 <span class="chip">22 M+ d'observations immobilières</span>297 <span class="chip">100 % données à la source</span>298 </div>299 <div class="cover-marks" id="cover-marks"></div>300 <footer class="pfoot"><span>groupe-ka.com</span><span>© 2026 Groupe KA — Simon-Pierre Boucher</span></footer>301</section>302303<!-- ============================ PAGE 2 — LE NOM ============================ -->304<section class="page">305 <header class="phead">306 <span class="wordmark">Groupe <span class="kabox">KA</span></span>307 <span class="doc">L'agrégation, expliquée</span>308 <span class="pnum">02 / 12</span>309 </header>310 <p class="kicker">Chapitre 01 · Le nom</p>311 <h2>·Ka, le suffixe qui veut dire <span class="hl">agréger</span></h2>312 <div class="def-grid">313 <div class="card defcard">314 <span class="word">·Ka</span><span class="pos">/ka/ suffixe</span>315 <ol>316 <li><b class="n">1.</b><span><b>Agréger</b> — rassembler en un seul endroit ce qui était éparpillé317 sur des centaines de sites : annonces, prix, menus, événements, profils.</span></li>318 <li><b class="n">2.</b><span>Marque de fabrique du groupe : Lou·Ka loge, Immo·Ka vend, Auto·Ka roule,319 Fabri·Ka fabrique, Food·Ka nourrit, Resto·Ka régale, Sorti·Ka divertit, Créa·Ka rassemble.</span></li>320 <li><b class="n">3.</b><span>Par extension : toute machine qui lit les sources en continu, normalise la321 donnée et publie sans jamais rien inventer.</span></li>322 </ol>323 <p class="quote">« Tout ce qui finit en <b class="display">·Ka</b> agrège. »</p>324 </div>325 <div class="eqcard">326 <span class="k">L'équation ·Ka</span>327 <p class="eq">1 000+ sites lus<br /><span class="lime">→ 450+ connecteurs</span><br />→ 10 plateformes</p>328 <p>La donnée entre éparpillée, elle ressort rangée. Entre les deux, aucune main humaine —329 c'est le suffixe ·Ka qui travaille : lecture à la source, normalisation, dédoublonnage,330 géocodage, publication traçable. Les pages qui suivent montrent la machine, à découvert.</p>331 </div>332 </div>333 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 01 · Le nom</span></footer>334</section>335336<!-- ============================ PAGE 3 — LE SABLIER ============================ -->337<section class="page">338 <header class="phead">339 <span class="wordmark">Groupe <span class="kabox">KA</span></span>340 <span class="doc">L'agrégation, expliquée</span>341 <span class="pnum">03 / 12</span>342 </header>343 <p class="kicker">Chapitre 02 · Le geste fondateur</p>344 <h2>Plein de sites. <span class="hl">Une seule flèche.</span></h2>345 <div class="figwrap">346 <div class="figbody" id="fig-sablier"></div>347 <div class="caption"><b>LE SABLIER ·KA —</b> des centaines de sites éparpillés, lus à la source par des348 connecteurs dédiés ; tout converge vers KA, qui normalise, dédoublonne et redistribue vers dix349 plateformes. Une flèche entre, dix flèches sortent : c'est ça, agréger.</div>350 </div>351 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 02 · Le sablier</span></footer>352</section>353354<!-- ============================ PAGE 4 — LE PIPELINE ============================ -->355<section class="page">356 <header class="phead">357 <span class="wordmark">Groupe <span class="kabox">KA</span></span>358 <span class="doc">L'agrégation, expliquée</span>359 <span class="pnum">04 / 12</span>360 </header>361 <p class="kicker">Chapitre 03 · De la page web à la donnée propre</p>362 <h2>Le pipeline, <span class="hl">station par station</span></h2>363 <div class="figwrap">364 <div class="figbody" id="fig-pipeline"></div>365 <div class="caption"><b>LE PIPELINE —</b> cinq stations, aucune main humaine. La boucle verte est le secret :366 tout le pipeline se rejoue en continu, donc une annonce retirée à la source disparaît d'elle-même.</div>367 </div>368 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 03 · Le pipeline</span></footer>369</section>370371<!-- ============================ PAGE 5 — LE CYCLE ============================ -->372<section class="page">373 <header class="phead">374 <span class="wordmark">Groupe <span class="kabox">KA</span></span>375 <span class="doc">L'agrégation, expliquée</span>376 <span class="pnum">05 / 12</span>377 </header>378 <p class="kicker">Chapitre 04 · La boucle jour et nuit</p>379 <h2>Pas un instantané, <span class="hl">un battement</span></h2>380 <div class="figwrap">381 <div class="figbody" id="fig-cycle"></div>382 <div class="caption"><b>LE CYCLE ·KA —</b> quatre gestes, en boucle, sans intervention humaine : lire les383 sources, comparer à hier, mettre à jour, publier et tracer. C'est la définition maison de l'agrégation.</div>384 </div>385 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 04 · Le cycle</span></footer>386</section>387388<!-- ============================ PAGE 6 — LES ÉCLAIREURS ============================ -->389<section class="page">390 <header class="phead">391 <span class="wordmark">Groupe <span class="kabox">KA</span></span>392 <span class="doc">L'agrégation, expliquée</span>393 <span class="pnum">06 / 12</span>394 </header>395 <p class="kicker">Chapitre 05 · Avant d'agréger, découvrir</p>396 <h2>Les éclaireurs : <span class="hl">Ka2 · Ka4 · Ka6</span></h2>397 <div class="figwrap">398 <div class="figbody" id="fig-bots"></div>399 <div class="caption"><b>LA DÉCOUVERTE —</b> les connecteurs lisent des sources connues ; les bots IA les400 trouvent. Ka2, Ka4 et Ka6 cartographient le web québécois entité par entité (robots.txt respecté,401 données publiques seulement) et alimentent tout l'écosystème en nouvelles sources.</div>402 </div>403 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 05 · Les éclaireurs</span></footer>404</section>405406<!-- ============================ PAGE 7 — TROUVE·KA ============================ -->407<section class="page">408 <header class="phead">409 <span class="wordmark">Groupe <span class="kabox">KA</span></span>410 <span class="doc">L'agrégation, expliquée</span>411 <span class="pnum">07 / 12</span>412 </header>413 <p class="kicker">Chapitre 06 · Le produit phare</p>414 <h2>Trouve·Ka <span class="hl">cherche le Québec</span></h2>415 <div class="figwrap">416 <div class="figbody" id="fig-trouveka"></div>417 <div class="caption"><b>LE MOTEUR —</b> les grands moteurs cherchent le monde ; Trouve·Ka ne contient que418 le web d'ici. Un commerce de Rimouski ou un blogue de Limoilou, noyés dans un index mondial, sont en419 première page dans un index 100 % Québec. C'est l'agrégation poussée à sa conclusion logique.</div>420 </div>421 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 06 · Trouve·Ka</span></footer>422</section>423424<!-- ============================ PAGE 8 — L'INVENTAIRE ============================ -->425<section class="page">426 <header class="phead">427 <span class="wordmark">Groupe <span class="kabox">KA</span></span>428 <span class="doc">L'agrégation, expliquée</span>429 <span class="pnum">08 / 12</span>430 </header>431 <p class="kicker">Chapitre 07 · La preuve par les nombres</p>432 <h2>L'inventaire <span class="hl">vivant</span></h2>433 <div class="figwrap" style="flex:1">434 <div class="bars" id="fig-bars" style="flex:1"></div>435 <div class="caption"><b>L'INVENTAIRE —</b> chaque barre est vivante : elle grossit quand les connecteurs436 trouvent du neuf, elle maigrit quand une annonce disparaît à la source. Compté aujourd'hui, pas promis.</div>437 </div>438 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 07 · L'inventaire</span></footer>439</section>440441<!-- ============================ PAGE 9 — LA FLOTTE ============================ -->442<section class="page">443 <header class="phead">444 <span class="wordmark">Groupe <span class="kabox">KA</span></span>445 <span class="doc">L'agrégation, expliquée</span>446 <span class="pnum">09 / 12</span>447 </header>448 <p class="kicker">Chapitre 08 · Un point = un connecteur</p>449 <h2>340 connecteurs, <span class="hl">dessinés un par un</span></h2>450 <div class="figwrap" style="flex:1">451 <div class="bars" id="fig-dots" style="flex:1"></div>452 <div class="caption"><b>LA FLOTTE —</b> chaque point est un petit programme qui connaît un site par cœur et453 le relit sans arrêt. S'y ajoutent les flux des 1 204 boutiques de Fabri·Ka, les données publiques de454 Vrai-Prix et ValoPlex, et l'annuaire multi-plateformes de Créa·Ka.</div>455 </div>456 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 08 · La flotte</span></footer>457</section>458459<!-- ============================ PAGE 10 — LES MOTEURS D'ÉVALUATION ============================ -->460<section class="page">461 <header class="phead">462 <span class="wordmark">Groupe <span class="kabox">KA</span></span>463 <span class="doc">L'agrégation, expliquée</span>464 <span class="pnum">10 / 12</span>465 </header>466 <p class="kicker">Chapitre 09 · Agréger pour évaluer</p>467 <h2>Deux moteurs, <span class="hl">tout le Québec</span></h2>468 <div class="eval-grid">469 <div class="card evalcard">470 <span class="k"><span class="brand"><i style="background:#ff5148"></i></span>Vrai-Prix · résidentiel</span>471 <span class="big">3 747 008</span>472 <span class="lbl">propriétés couvertes</span>473 <p>Toutes les unités du rôle foncier du Québec, estimées par un moteur hybride — modèle hédonique +474 comparables réels ajustés (745 119 ventes publiées 2021-2026, MdAPE 11 %). Chaque ajustement est475 affiché en dollars.</p>476 <div class="gauge">477 <div class="glab"><span>P10</span><span>fourchette honnête — jamais un faux prix unique</span><span>P90</span></div>478 <div class="gtrack"><div class="gband" style="left:18%;width:64%"></div><div class="gmid" style="left:50%"></div></div>479 </div>480 </div>481 <div class="card evalcard">482 <span class="k"><span class="brand"><i style="background:#ff9f45"></i></span>ValoPlex · immeubles à revenus</span>483 <span class="big">393 867</span>484 <span class="lbl">plex évalués · 1 733 744 portes</span>485 <p>Le moteur spécialisé des plex, entraîné exclusivement sur ~91 060 ventes réelles d'immeubles à486 revenus. L'unité d'analyse : la porte. Fourchette calibrée — 8 fois sur 10, le vrai prix tombe dedans.</p>487 <div class="gauge">488 <div class="glab"><span>P10</span><span>valeur totale et valeur par porte, calcul montré en entier</span><span>P90</span></div>489 <div class="gtrack"><div class="gband" style="left:22%;width:56%"></div><div class="gmid" style="left:50%"></div></div>490 </div>491 </div>492 </div>493 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 09 · Les moteurs d'évaluation</span></footer>494</section>495496<!-- ============================ PAGE 11 — LE SOCLE ============================ -->497<section class="page">498 <header class="phead">499 <span class="wordmark">Groupe <span class="kabox">KA</span></span>500 <span class="doc">L'agrégation, expliquée</span>501 <span class="pnum">11 / 12</span>502 </header>503 <p class="kicker">Chapitre 10 · Une seule fondation</p>504 <h2>Le socle : <span class="hl">onze plateformes</span></h2>505 <div class="tbl">506 <table id="socle-table">507 <thead><tr><th>Plateforme</th><th>Marché</th><th>Moteur</th><th>Adresse</th></tr></thead>508 <tbody></tbody>509 </table>510 </div>511 <footer class="pfoot"><span>groupe-ka.com</span><span>Chapitre 10 · Le socle</span></footer>512</section>513514<!-- ============================ PAGE 12 — MANIFESTE ============================ -->515<section class="page dark">516 <header class="phead">517 <span class="wordmark">Groupe <span class="kabox">KA</span></span>518 <span class="doc">L'agrégation, expliquée</span>519 <span class="pnum">12 / 12</span>520 </header>521 <p class="kicker">Notre manifeste</p>522 <h2>Trois principes, <span class="hl">aucune exception</span></h2>523 <div class="mani-grid">524 <div class="mani"><span class="n">01</span><h3>Zéro boîte noire</h3>525 <p>Un score magique n'est pas une réponse. Chaque estimation montre ses comparables, ses ajustements526 en dollars et sa fourchette d'incertitude. Si le calcul ne peut pas être montré, il ne sort pas.</p></div>527 <div class="mani"><span class="n">02</span><h3>Données réelles</h3>528 <p>Rôles d'évaluation foncière, ventes publiées, annonces vérifiées à la source. Aucun prix inventé :529 quand la donnée n'existe pas, on affiche qu'elle n'existe pas. Validé sur des ventes jamais vues.</p></div>530 <div class="mani"><span class="n">03</span><h3>Indépendance</h3>531 <p>Aucun courtier ni annonceur ne paie pour influencer un résultat. Pas de traceur publicitaire, pas de532 revente de données. Le français d'abord, le Québec comme terrain, la Loi 25 comme plancher.</p></div>533 </div>534 <div class="contact">535 <span><span class="mail">contact@groupe-ka.com</span><br /><span class="role">Projets, partenariats & données</span></span>536 <span><span class="mail">info@groupe-ka.com</span><br /><span class="role">Médias & questions générales</span></span>537 <span><span class="mail">admin@groupe-ka.com</span><br /><span class="role">Légal, vie privée & Loi 25</span></span>538 </div>539 <footer class="pfoot"><span>groupe-ka.com</span><span>© 2026 Groupe KA — Simon-Pierre Boucher · contact@spboucher.ai</span></footer>540</section>541542<script>543"use strict";544/* Figures générées : mêmes données et même langage graphique que le site groupe-ka.com. */545546const INK = "#141814", GREEN = "#1c5c41", LIME = "#d9f26b", PAPER = "#f5f3ee",547 INK3 = "#8b928c", WHITE = "#ffffff";548549const PLATFORMS = [550 { name: "Lou·Ka", accent: "#d9f26b", domain: "lou-ka.com" },551 { name: "Immo·Ka", accent: "#e23744", domain: "immo-ka.com" },552 { name: "Vrai-Prix",accent: "#ff5148", domain: "vrai-prix.com" },553 { name: "ValoPlex", accent: "#ff9f45", domain: "valoplex.com" },554 { name: "Auto·Ka", accent: "#ff5a2a", domain: "auto-ka.com" },555 { name: "Fabri·Ka", accent: "#C4532E", domain: "fabri-ka.com" },556 { name: "Food·Ka", accent: "#d9f26b", domain: "food-ka.com" },557 { name: "Resto·Ka", accent: "#ffc53d", domain: "resto-ka.com" },558 { name: "Sorti·Ka", accent: "#ff6a00", domain: "sorti-ka.com" },559 { name: "Créa·Ka", accent: "#7da2ff", domain: "crea-ka.com" },560];561const ACCENT = Object.fromEntries(PLATFORMS.map(p => [p.name, p.accent]));562563const SOURCES = [564 "Gestionnaires immobiliers", "Agences de courtage", "Rôles fonciers (MAMH)",565 "Registres de ventes", "Concessionnaires autos", "Marchands d'occasion",566 "Boutiques québécoises", "Sites de fabricants", "Bannières d'épicerie",567 "Circulaires & soldes", "Menus de restaurants", "Billetteries d'événements",568 "Profils de créateurs",569];570571/* ---------- Couverture : pilules des marques ---------- */572(function () {573 const wrap = document.getElementById("cover-marks");574 const marks = [575 ["Trouve","Ka","#b9cfee","#141814"], ["Lou","Ka","#d9f26b","#141814"],576 ["Immo","Ka","#e23744","#1a1214"], ["Vrai","Prix","#ff5148","#141814"],577 ["Valo","Plex","#ff9f45","#141814"], ["Auto","Ka","#ff5a2a","#17181c"],578 ["Fabri","Ka","#C4532E","#1E1B16"], ["Food","Ka","#d9f26b","#14231a"],579 ["Resto","Ka","#ffc53d","#1a1410"], ["Sorti","Ka","#ff6a00","#0b1330"],580 ["Créa","Ka","#7da2ff","#10162b"],581 ];582 for (const [l, r, accent, box] of marks) {583 const s = document.createElement("span");584 s.className = "markpill";585 s.innerHTML = `${l}<i style="background:${box};color:${accent}">${r}</i>`;586 wrap.appendChild(s);587 }588})();589590/* ---------- Utilitaire SVG ---------- */591function svgEl(tag, attrs, text) {592 const el = document.createElementNS("http://www.w3.org/2000/svg", tag);593 for (const k in attrs) el.setAttribute(k, attrs[k]);594 if (text != null) el.textContent = text;595 return el;596}597function makeSvg(w, h, label) {598 const svg = svgEl("svg", { viewBox: `0 0 ${w} ${h}`, role: "img", "aria-label": label });599 const marker = svgEl("marker", { id: "arr" + Math.floor(w), viewBox: "0 0 10 10", refX: 8, refY: 5, markerWidth: 6.5, markerHeight: 6.5, orient: "auto-start-reverse" });600 marker.appendChild(svgEl("path", { d: "M0,0 L10,5 L0,10 z", fill: INK }));601 const defs = svgEl("defs", {});602 defs.appendChild(marker);603 svg.appendChild(defs);604 svg.dataset.marker = "arr" + Math.floor(w);605 return svg;606}607function brandChip(svg, x, y, accent, s = 16) {608 svg.appendChild(svgEl("rect", { x, y, width: s, height: s, rx: 4, fill: INK }));609 svg.appendChild(svgEl("rect", { x: x + 3, y: y + 3, width: s - 6, height: s - 6, rx: 2.5, fill: accent }));610}611612/* ---------- 1. Le sablier (page 3) ---------- */613(function () {614 const W = 1150, H = 640;615 const svg = makeSvg(W, H, "Le sablier de l'agrégation KA");616 const M = svg.dataset.marker;617 const srcX = 218, kaL = 500, kaR = 648, kaY = H / 2, dstX = 900;618619 const srcYs = SOURCES.map((_, i) => 50 + i * (H - 100) / (SOURCES.length - 1));620 const dstYs = PLATFORMS.map((_, i) => 62 + i * (H - 124) / (PLATFORMS.length - 1));621622 srcYs.forEach((y, i) => svg.appendChild(svgEl("path", {623 d: `M ${srcX} ${y} C ${srcX + 140} ${y}, ${kaL - 120} ${kaY}, ${kaL - 8} ${kaY + (i - (SOURCES.length - 1) / 2) * 6}`,624 fill: "none", stroke: INK, "stroke-width": 1.5, "stroke-opacity": 0.5, "stroke-dasharray": "7 7",625 })));626 dstYs.forEach((y, i) => svg.appendChild(svgEl("path", {627 d: `M ${kaR + 4} ${kaY + (i - (PLATFORMS.length - 1) / 2) * 8} C ${kaR + 120} ${kaY}, ${dstX - 130} ${y}, ${dstX - 12} ${y}`,628 fill: "none", stroke: INK, "stroke-width": 2, "stroke-opacity": 0.75, "marker-end": `url(#${M})`, "stroke-dasharray": "7 7",629 })));630631 SOURCES.forEach((label, i) => {632 svg.appendChild(svgEl("rect", { x: 16, y: srcYs[i] - 15, width: srcX - 16, height: 30, rx: 6, fill: WHITE, stroke: INK, "stroke-width": 1.5 }));633 svg.appendChild(svgEl("circle", { cx: 33, cy: srcYs[i], r: 3.5, fill: GREEN }));634 svg.appendChild(svgEl("text", { x: 46, y: srcYs[i] + 3.5, "font-size": 11, "font-weight": 700, fill: INK }, label));635 });636 svg.appendChild(svgEl("text", { x: 16, y: 24, "font-size": 11.5, "font-weight": 700, "letter-spacing": 1.5, fill: INK3 }, "DES CENTAINES DE SITES"));637638 const gLbl = svgEl("g", { transform: `translate(${(srcX + kaL) / 2 - 6} ${kaY - 128}) rotate(-4)` });639 gLbl.appendChild(svgEl("rect", { x: -102, y: -25, width: 204, height: 50, rx: 13, fill: LIME, stroke: INK, "stroke-width": 1.5 }));640 gLbl.appendChild(svgEl("text", { x: 0, y: -4, "text-anchor": "middle", "font-size": 12, "font-weight": 700, "letter-spacing": 1, fill: INK }, "450+ CONNECTEURS"));641 gLbl.appendChild(svgEl("text", { x: 0, y: 14, "text-anchor": "middle", "font-size": 9, fill: "#2c3a2c" }, "lecture à la source · normalisation"));642 svg.appendChild(gLbl);643644 const gKa = svgEl("g", { transform: `translate(${(kaL + kaR) / 2} ${kaY}) rotate(-2)` });645 gKa.appendChild(svgEl("rect", { x: -(kaR - kaL) / 2 + 6, y: -66, width: kaR - kaL, height: 146, rx: 12, fill: "rgba(20,24,20,0.18)" }));646 gKa.appendChild(svgEl("rect", { x: -(kaR - kaL) / 2, y: -72, width: kaR - kaL, height: 146, rx: 12, fill: INK }));647 const kaTxt = svgEl("text", { x: 0, y: 8, "text-anchor": "middle", "font-size": 62, "font-weight": 700, "letter-spacing": -2, fill: LIME }, "KA");648 kaTxt.setAttribute("class", "t-display");649 gKa.appendChild(kaTxt);650 gKa.appendChild(svgEl("text", { x: 0, y: 37, "text-anchor": "middle", "font-size": 11, "font-weight": 700, "letter-spacing": 2, fill: "rgba(245,243,238,0.75)" }, "= AGRÉGATION"));651 gKa.appendChild(svgEl("text", { x: 0, y: 55, "text-anchor": "middle", "font-size": 8.5, fill: "rgba(245,243,238,0.55)" }, "dédoublonner · géocoder"));652 svg.appendChild(gKa);653654 PLATFORMS.forEach((p, i) => {655 const y = dstYs[i];656 svg.appendChild(svgEl("rect", { x: dstX, y: y - 21, width: W - dstX - 14, height: 42, rx: 8, fill: WHITE, stroke: INK, "stroke-width": 1.5 }));657 brandChip(svg, dstX + 13, y - 8, p.accent);658 const nm = svgEl("text", { x: dstX + 40, y: y - 1, "font-size": 15.5, "font-weight": 700, fill: INK }, p.name);659 nm.setAttribute("class", "t-display");660 svg.appendChild(nm);661 svg.appendChild(svgEl("text", { x: dstX + 40, y: y + 14, "font-size": 9, fill: INK3 }, p.domain));662 });663 svg.appendChild(svgEl("text", { x: dstX, y: 30, "font-size": 11.5, "font-weight": 700, "letter-spacing": 1.5, fill: INK3 }, "DIX PLATEFORMES"));664665 document.getElementById("fig-sablier").appendChild(svg);666})();667668/* ---------- 2. Le pipeline horizontal (page 4) ---------- */669(function () {670 const STEPS = [671 ["01", "Site source", "La page publique, telle que tout le monde la voit."],672 ["02", "Connecteur", "Un lecteur dédié par site — il connaît sa structure par cœur."],673 ["03", "Normalisation", "Mêmes champs, mêmes unités : un 3½ est un 3½ partout."],674 ["04", "Dédoublonnage & géocodage", "Une seule fiche par annonce réelle, posée sur la carte."],675 ["05", "Publication", "En ligne, datée, traçable jusqu'à la source originale."],676 ];677 const W = 1150, H = 430, boxW = 205, boxH = 210, gap = (W - 40 - 5 * boxW) / 4, top = 90;678 const svg = makeSvg(W, H, "Le pipeline de la donnée KA");679 const M = svg.dataset.marker;680681 STEPS.forEach((s, i) => {682 const x = 20 + i * (boxW + gap);683 const last = i === STEPS.length - 1;684 svg.appendChild(svgEl("rect", { x: x + 5, y: top + 5, width: boxW, height: boxH, rx: 12, fill: "rgba(20,24,20,0.14)" }));685 svg.appendChild(svgEl("rect", { x, y: top, width: boxW, height: boxH, rx: 12, fill: last ? INK : WHITE, stroke: INK, "stroke-width": 1.5 }));686 svg.appendChild(svgEl("text", { x: x + 18, y: top + 36, "font-size": 13, "font-weight": 700, fill: last ? LIME : GREEN }, s[0]));687 const t = svgEl("text", { x: x + 18, y: top + 68, "font-size": 16.5, "font-weight": 700, fill: last ? PAPER : INK });688 t.setAttribute("class", "t-display");689 // titre sur 1-2 lignes690 const words = s[1].split(" ");691 let line = "", lines = [];692 for (const w of words) {693 if ((line + " " + w).trim().length > 15) { lines.push(line.trim()); line = w; } else line += " " + w;694 }695 lines.push(line.trim());696 lines.forEach((ln, li) => t.appendChild(svgEl("tspan", { x: x + 18, dy: li === 0 ? 0 : 21 }, ln)));697 svg.appendChild(t);698 // description699 const d = svgEl("text", { x: x + 18, y: top + 68 + lines.length * 21 + 12, "font-size": 10.5, fill: last ? "rgba(245,243,238,0.7)" : "#4d5551" });700 d.setAttribute("class", "t-body");701 let dl = "", dls = [];702 for (const w of s[2].split(" ")) {703 if ((dl + " " + w).trim().length > 28) { dls.push(dl.trim()); dl = w; } else dl += " " + w;704 }705 dls.push(dl.trim());706 dls.forEach((ln, li) => d.appendChild(svgEl("tspan", { x: x + 18, dy: li === 0 ? 0 : 15 }, ln)));707 svg.appendChild(d);708 if (!last) svg.appendChild(svgEl("line", {709 x1: x + boxW + 6, y1: top + boxH / 2, x2: x + boxW + gap - 8, y2: top + boxH / 2,710 stroke: INK, "stroke-width": 2, "marker-end": `url(#${M})`, "stroke-dasharray": "7 7",711 }));712 });713714 // boucle de resynchronisation : dernière station → première715 const y0 = top + boxH + 44;716 svg.appendChild(svgEl("path", {717 d: `M ${20 + 4 * (boxW + gap) + boxW / 2} ${top + boxH + 6} L ${20 + 4 * (boxW + gap) + boxW / 2} ${y0}718 L ${20 + boxW / 2} ${y0} L ${20 + boxW / 2} ${top + boxH + 14}`,719 fill: "none", stroke: GREEN, "stroke-width": 2.5, "marker-end": `url(#${M})`, "stroke-dasharray": "7 7",720 }));721 const gR = svgEl("g", { transform: `translate(${W / 2} ${y0}) rotate(-2)` });722 gR.appendChild(svgEl("rect", { x: -110, y: -17, width: 220, height: 34, rx: 17, fill: LIME, stroke: INK, "stroke-width": 1.5 }));723 gR.appendChild(svgEl("text", { x: 0, y: 4.5, "text-anchor": "middle", "font-size": 11.5, "font-weight": 700, "letter-spacing": 1, fill: INK }, "RESYNC EN CONTINU"));724 svg.appendChild(gR);725 svg.appendChild(svgEl("text", { x: 20, y: 34, "font-size": 11.5, "font-weight": 700, "letter-spacing": 1.5, fill: INK3 }, "CINQ STATIONS · AUCUNE MAIN HUMAINE"));726727 document.getElementById("fig-pipeline").appendChild(svg);728})();729730/* ---------- 3. Le cycle (page 5) ---------- */731(function () {732 const STEPS = [733 ["01", "Lire les sources", -90], ["02", "Comparer à hier", 0],734 ["03", "Mettre à jour", 90], ["04", "Publier & tracer", 180],735 ];736 const W = 1150, S = 440, cx = W / 2, cy = S / 2 + 4, R = 150;737 const svg = makeSvg(W, S, "Le cycle KA, jour et nuit");738 const M = svg.dataset.marker;739740 svg.appendChild(svgEl("circle", { cx, cy, r: R, fill: "none", stroke: INK, "stroke-width": 2, "stroke-opacity": 0.65, "stroke-dasharray": "7 7" }));741 [-45, 45, 135, 225].forEach((a) => {742 const rad = a * Math.PI / 180, x = cx + R * Math.cos(rad), y = cy + R * Math.sin(rad);743 const tx = -Math.sin(rad), ty = Math.cos(rad);744 svg.appendChild(svgEl("line", { x1: x - tx, y1: y - ty, x2: x + tx * 2, y2: y + ty * 2, stroke: INK, "stroke-width": 2, "marker-end": `url(#${M})` }));745 });746747 const gKa = svgEl("g", { transform: `translate(${cx} ${cy}) rotate(-2)` });748 gKa.appendChild(svgEl("rect", { x: -43, y: -37, width: 96, height: 88, rx: 10, fill: "rgba(20,24,20,0.18)" }));749 gKa.appendChild(svgEl("rect", { x: -48, y: -42, width: 96, height: 88, rx: 10, fill: INK }));750 const t = svgEl("text", { x: 0, y: 8, "text-anchor": "middle", "font-size": 40, "font-weight": 700, "letter-spacing": -1.5, fill: LIME }, "KA");751 t.setAttribute("class", "t-display");752 gKa.appendChild(t);753 gKa.appendChild(svgEl("text", { x: 0, y: 30, "text-anchor": "middle", "font-size": 8, "letter-spacing": 1.5, fill: "rgba(245,243,238,0.65)" }, "JOUR ET NUIT"));754 svg.appendChild(gKa);755756 STEPS.forEach(([num, label, angle]) => {757 const rad = angle * Math.PI / 180, x = cx + R * Math.cos(rad), y = cy + R * Math.sin(rad), w = 178;758 const g = svgEl("g", { transform: `translate(${x} ${y})` });759 g.appendChild(svgEl("rect", { x: -w / 2, y: -21, width: w, height: 42, rx: 9, fill: WHITE, stroke: INK, "stroke-width": 1.5 }));760 g.appendChild(svgEl("text", { x: -w / 2 + 13, y: 5, "font-size": 11, "font-weight": 700, fill: GREEN }, num));761 const l = svgEl("text", { x: -w / 2 + 38, y: 5, "font-size": 14, "font-weight": 700, fill: INK }, label);762 l.setAttribute("class", "t-display");763 g.appendChild(l);764 svg.appendChild(g);765 });766767 // légendes latérales768 const notes = [769 [30, "Une annonce retirée à la source", "disparaît d'elle-même du site."],770 [W - 260, "Une baisse de prix est détectée", "et historisée automatiquement."],771 ];772 notes.forEach(([x, l1, l2]) => {773 svg.appendChild(svgEl("rect", { x, y: cy - 34, width: 230, height: 68, rx: 9, fill: "#faf9f5", stroke: INK, "stroke-width": 1.5, "stroke-dasharray": "5 5" }));774 const n = svgEl("text", { x: x + 16, y: cy - 8, "font-size": 11, fill: "#4d5551" });775 n.setAttribute("class", "t-body");776 n.appendChild(svgEl("tspan", { x: x + 16, dy: 0 }, l1));777 n.appendChild(svgEl("tspan", { x: x + 16, dy: 17 }, l2));778 svg.appendChild(n);779 });780781 document.getElementById("fig-cycle").appendChild(svg);782})();783784/* ---------- 4. Les éclaireurs (page 6) ---------- */785(function () {786 const W = 1300, H = 470;787 const svg = makeSvg(W, H, "Les bots de découverte Ka2, Ka4 et Ka6");788 const M = svg.dataset.marker;789790 // nuage du web québécois (points)791 const cloud = { x: 30, y: 60, w: 260, h: 340 };792 svg.appendChild(svgEl("rect", { x: cloud.x, y: cloud.y, width: cloud.w, height: cloud.h, rx: 14, fill: WHITE, stroke: INK, "stroke-width": 1.5 }));793 let seed = 7;794 const rnd = () => (seed = (seed * 16807) % 2147483647) / 2147483647;795 for (let i = 0; i < 130; i++) {796 svg.appendChild(svgEl("circle", {797 cx: cloud.x + 18 + rnd() * (cloud.w - 36), cy: cloud.y + 34 + rnd() * (cloud.h - 56),798 r: 2 + rnd() * 2.4, fill: rnd() > 0.82 ? GREEN : "rgba(20,24,20,0.35)",799 }));800 }801 svg.appendChild(svgEl("text", { x: cloud.x + 16, y: cloud.y + 22, "font-size": 10.5, "font-weight": 700, "letter-spacing": 1.2, fill: INK3 }, "LE WEB QUÉBÉCOIS"));802803 // bots804 const bots = [805 ["Ka", "2", "#d9f26b", "cartographie les entités", 96],806 ["Ka", "4", "#ff9f45", "activité à découvert", 232],807 ["Ka", "6", "#b9cfee", "nourrit Trouve·Ka", 368],808 ];809 const botX = 430, botW = 250;810 bots.forEach(([l, d, accent, sub, y]) => {811 svg.appendChild(svgEl("path", { d: `M ${cloud.x + cloud.w + 6} ${cloud.y + cloud.h / 2} C ${botX - 90} ${cloud.y + cloud.h / 2}, ${botX - 90} ${y}, ${botX - 8} ${y}`, fill: "none", stroke: INK, "stroke-width": 1.7, "stroke-opacity": 0.6, "stroke-dasharray": "7 7", "marker-end": `url(#${M})` }));812 svg.appendChild(svgEl("rect", { x: botX, y: y - 36, width: botW, height: 72, rx: 11, fill: WHITE, stroke: INK, "stroke-width": 1.5 }));813 const t = svgEl("text", { x: botX + 18, y: y + 2, "font-size": 25, "font-weight": 700, "letter-spacing": -1, fill: INK });814 t.setAttribute("class", "t-display");815 t.appendChild(svgEl("tspan", {}, l));816 svg.appendChild(t);817 svg.appendChild(svgEl("rect", { x: botX + 55, y: y - 20, width: 28, height: 28, rx: 6, fill: INK, transform: `rotate(-4 ${botX + 69} ${y - 6})` }));818 const dt = svgEl("text", { x: botX + 69, y: y + 2, "text-anchor": "middle", "font-size": 19, "font-weight": 700, fill: accent });819 dt.setAttribute("class", "t-display");820 dt.textContent = d;821 svg.appendChild(dt);822 svg.appendChild(svgEl("text", { x: botX + 100, y: y - 2, "font-size": 10.5, "font-weight": 700, fill: GREEN }, "BOT IA"));823 const s = svgEl("text", { x: botX + 100, y: y + 15, "font-size": 10.5, fill: "#4d5551" }, sub);824 s.setAttribute("class", "t-body");825 svg.appendChild(s);826 svg.appendChild(svgEl("path", { d: `M ${botX + botW + 4} ${y} C ${botX + botW + 80} ${y}, ${botX + botW + 80} ${H / 2}, ${botX + botW + 130} ${H / 2}`, fill: "none", stroke: INK, "stroke-width": 1.7, "stroke-opacity": 0.6, "stroke-dasharray": "7 7", "marker-end": `url(#${M})` }));827 });828829 // registre d'entités830 const regX = botX + botW + 140, regW = 180;831 svg.appendChild(svgEl("rect", { x: regX + 5, y: H / 2 - 55 + 5, width: regW, height: 110, rx: 12, fill: "rgba(20,24,20,0.14)" }));832 svg.appendChild(svgEl("rect", { x: regX, y: H / 2 - 55, width: regW, height: 110, rx: 12, fill: INK }));833 const rt = svgEl("text", { x: regX + regW / 2, y: H / 2 - 12, "text-anchor": "middle", "font-size": 17, "font-weight": 700, fill: LIME });834 rt.setAttribute("class", "t-display");835 rt.textContent = "Registre";836 svg.appendChild(rt);837 const rt2 = svgEl("text", { x: regX + regW / 2, y: H / 2 + 10, "text-anchor": "middle", "font-size": 17, "font-weight": 700, fill: LIME });838 rt2.setAttribute("class", "t-display");839 rt2.textContent = "d'entités";840 svg.appendChild(rt2);841 svg.appendChild(svgEl("text", { x: regX + regW / 2, y: H / 2 + 34, "text-anchor": "middle", "font-size": 8.5, "letter-spacing": 1, fill: "rgba(245,243,238,0.6)" }, "entreprises · personnes · sites"));842843 // vers les connecteurs844 svg.appendChild(svgEl("line", { x1: regX + regW + 6, y1: H / 2, x2: regX + regW + 78, y2: H / 2, stroke: INK, "stroke-width": 2.2, "marker-end": `url(#${M})`, "stroke-dasharray": "7 7" }));845 const outX = regX + regW + 90;846 svg.appendChild(svgEl("rect", { x: outX, y: H / 2 - 62, width: W - outX - 16, height: 124, rx: 12, fill: LIME, stroke: INK, "stroke-width": 1.5 }));847 const ot = svgEl("text", { x: outX + 18, y: H / 2 - 26, "font-size": 16, "font-weight": 700, fill: INK });848 ot.setAttribute("class", "t-display");849 ot.textContent = "Nouvelles sources";850 svg.appendChild(ot);851 const ol = svgEl("text", { x: outX + 18, y: H / 2 - 2, "font-size": 10.5, fill: "#2c3a2c" });852 ol.setAttribute("class", "t-body");853 ["Boutique qui ouvre, gestionnaire,", "concessionnaire : repérés par les", "bots, branchés par les ·Ka."].forEach((ln, i) =>854 ol.appendChild(svgEl("tspan", { x: outX + 18, dy: i === 0 ? 0 : 16 }, ln)));855 svg.appendChild(ol);856857 document.getElementById("fig-bots").appendChild(svg);858})();859860/* ---------- 5. Trouve·Ka (page 7) ---------- */861(function () {862 const W = 1150, H = 470;863 const svg = makeSvg(W, H, "Trouve·Ka, le moteur de recherche du web québécois");864 const M = svg.dataset.marker;865866 // robot → index → barre de recherche → résultats867 const steps = [868 { x: 30, w: 250, title: "Le robot", sub: ["Parcourt le web québécois", "jour et nuit — et lui seul.", "robots.txt respecté."], tag: "CRAWLER DÉDIÉ" },869 { x: 330, w: 250, title: "L'index", sub: ["Des milliers de domaines d'ici,", "recherche plein texte,", "croissance heure par heure."], tag: "100 % QUÉBEC" },870 ];871 steps.forEach((s) => {872 svg.appendChild(svgEl("rect", { x: s.x, y: 80, width: s.w, height: 170, rx: 12, fill: WHITE, stroke: INK, "stroke-width": 1.5 }));873 svg.appendChild(svgEl("text", { x: s.x + 18, y: 112, "font-size": 10, "font-weight": 700, "letter-spacing": 1.2, fill: GREEN }, s.tag));874 const t = svgEl("text", { x: s.x + 18, y: 144, "font-size": 21, "font-weight": 700, fill: INK });875 t.setAttribute("class", "t-display");876 t.textContent = s.title;877 svg.appendChild(t);878 const d = svgEl("text", { x: s.x + 18, y: 170, "font-size": 11, fill: "#4d5551" });879 d.setAttribute("class", "t-body");880 s.sub.forEach((ln, i) => d.appendChild(svgEl("tspan", { x: s.x + 18, dy: i === 0 ? 0 : 17 }, ln)));881 svg.appendChild(d);882 });883 svg.appendChild(svgEl("line", { x1: 284, y1: 165, x2: 322, y2: 165, stroke: INK, "stroke-width": 2, "marker-end": `url(#${M})`, "stroke-dasharray": "7 7" }));884 svg.appendChild(svgEl("line", { x1: 584, y1: 165, x2: 622, y2: 165, stroke: INK, "stroke-width": 2, "marker-end": `url(#${M})`, "stroke-dasharray": "7 7" }));885886 // barre de recherche887 const sbX = 634, sbW = 480;888 svg.appendChild(svgEl("rect", { x: sbX + 4, y: 134 + 4, width: sbW, height: 62, rx: 31, fill: "rgba(20,24,20,0.5)" }));889 svg.appendChild(svgEl("rect", { x: sbX, y: 134, width: sbW, height: 62, rx: 31, fill: WHITE, stroke: INK, "stroke-width": 2 }));890 svg.appendChild(svgEl("text", { x: sbX + 26, y: 172, "font-size": 18, "font-weight": 700, fill: INK }, "⌕"));891 svg.appendChild(svgEl("text", { x: sbX + 54, y: 171, "font-size": 12.5, fill: INK3 }, "poutine · plex à vendre · Gaspésie…"));892 svg.appendChild(svgEl("rect", { x: sbX + sbW - 116, y: 145, width: 102, height: 40, rx: 20, fill: INK }));893 const st = svgEl("text", { x: sbX + sbW - 65, y: 170, "text-anchor": "middle", "font-size": 13.5, "font-weight": 700, fill: "#b9cfee" });894 st.setAttribute("class", "t-display");895 st.textContent = "Chercher";896 svg.appendChild(st);897 const wm = svgEl("text", { x: sbX, y: 118, "font-size": 21, "font-weight": 700, "letter-spacing": -0.7, fill: INK });898 wm.setAttribute("class", "t-display");899 wm.textContent = "Trouve";900 svg.appendChild(wm);901 svg.appendChild(svgEl("rect", { x: sbX + 78, y: 98, width: 34, height: 26, rx: 6, fill: INK, transform: `rotate(-3 ${sbX + 95} 111)` }));902 const wk = svgEl("text", { x: sbX + 95, y: 117, "text-anchor": "middle", "font-size": 16, "font-weight": 700, fill: "#b9cfee" });903 wk.setAttribute("class", "t-display");904 wk.textContent = "Ka";905 svg.appendChild(wk);906 svg.appendChild(svgEl("text", { x: sbX + 124, y: 114, "font-size": 9.5, fill: INK3 }, "www.trouve-ka.com"));907908 // résultats (3 lignes)909 ["Microbrasserie — Rimouski", "Érablière — Lanaudière", "Blogue de quartier — Limoilou"].forEach((r, i) => {910 const y = 232 + i * 46;911 svg.appendChild(svgEl("rect", { x: sbX, y, width: sbW, height: 36, rx: 8, fill: "#faf9f5", stroke: INK, "stroke-width": 1.2 }));912 svg.appendChild(svgEl("circle", { cx: sbX + 20, cy: y + 18, r: 3.5, fill: GREEN }));913 const rt = svgEl("text", { x: sbX + 34, y: y + 23, "font-size": 12.5, "font-weight": 600, fill: INK });914 rt.setAttribute("class", "t-body");915 rt.textContent = r;916 svg.appendChild(rt);917 svg.appendChild(svgEl("text", { x: sbX + sbW - 20, y: y + 23, "text-anchor": "end", "font-size": 9, fill: GREEN }, "1re page"));918 });919920 // note comparaison921 svg.appendChild(svgEl("rect", { x: 30, y: 290, width: 554, height: 130, rx: 12, fill: INK }));922 const nt = svgEl("text", { x: 56, y: 330, "font-size": 20, "font-weight": 700, "letter-spacing": -0.5, fill: PAPER });923 nt.setAttribute("class", "t-display");924 nt.appendChild(svgEl("tspan", { x: 56, dy: 0 }, "LES GRANDS MOTEURS CHERCHENT LE MONDE."));925 const sp = svgEl("tspan", { x: 56, dy: 28, fill: LIME }, "TROUVE·KA CHERCHE LE QUÉBEC.");926 nt.appendChild(sp);927 svg.appendChild(nt);928 svg.appendChild(svgEl("text", { x: 56, y: 396, "font-size": 10, "letter-spacing": 1, fill: "rgba(245,243,238,0.6)" }, "NOURRI PAR LES ÉCLAIREURS KA2 · KA4 · KA6 — ZÉRO PUBLICITÉ, ZÉRO PROFILAGE"));929930 document.getElementById("fig-trouveka").appendChild(svg);931})();932933/* ---------- 6. Barres d'inventaire (page 8) ---------- */934(function () {935 const INVENTORY = [936 ["Fabri·Ka", 281000, "produits québécois"],937 ["Resto·Ka", 61000, "plats & prix réels"],938 ["Immo·Ka", 54000, "propriétés à vendre"],939 ["Food·Ka", 23700, "prix d'épicerie"],940 ["Auto·Ka", 15900, "véhicules d'occasion"],941 ["Sorti·Ka", 11100, "événements & sorties"],942 ["Lou·Ka", 7000, "logements à louer"],943 ["Créa·Ka", 2200, "créateurs d'ici"],944 ];945 const max = Math.max(...INVENTORY.map((d) => d[1]));946 const fmt = (n) => n.toLocaleString("fr-CA");947 const wrap = document.getElementById("fig-bars");948 for (const [name, value, unit] of INVENTORY) {949 const row = document.createElement("div");950 row.className = "barrow";951 row.innerHTML =952 `<div class="barhead"><span class="nm"><span class="brand"><i style="background:${ACCENT[name]}"></i></span>${name}<span class="u">${unit}</span></span>` +953 `<span class="v">${fmt(value)}+</span></div>` +954 `<div class="bartrack"><div class="barfill" style="width:${Math.max((value / max) * 100, 1.6)}%"></div></div>`;955 wrap.appendChild(row);956 }957})();958959/* ---------- 7. Matrice de connecteurs (page 9) ---------- */960(function () {961 const CONNECTORS = [962 ["Auto·Ka", 124, "concessionnaires"],963 ["Lou·Ka", 108, "gestionnaires"],964 ["Immo·Ka", 65, "agences"],965 ["Food·Ka", 20, "bannières"],966 ["Resto·Ka", 19, "chaînes de restos"],967 ["Sorti·Ka", 4, "billetteries & données ouvertes"],968 ];969 const wrap = document.getElementById("fig-dots");970 for (const [name, count, kind] of CONNECTORS) {971 const b = document.createElement("div");972 b.className = "dots-block";973 b.innerHTML =974 `<div class="barhead"><span class="nm"><span class="brand"><i style="background:${ACCENT[name]}"></i></span>${name}<span class="u">${kind}</span></span>` +975 `<span class="v">${count}</span></div>` +976 `<div class="dots">${"<i></i>".repeat(count)}</div>`;977 wrap.appendChild(b);978 }979})();980981/* ---------- 8. Tableau du socle (page 11) ---------- */982(function () {983 const ROWS = [984 ["Trouve·Ka", "#b9cfee", "Recherche — tout le web québécois", "Crawler dédié + index de recherche plein texte", "www.trouve-ka.com"],985 ["Lou·Ka", "#d9f26b", "Location résidentielle", "108 connecteurs sources + synchronisation horaire", "www.lou-ka.com"],986 ["Immo·Ka", "#e23744", "Propriétés à vendre", "65 connecteurs d'agences + détection des ventes", "www.immo-ka.com"],987 ["Vrai-Prix", "#ff5148", "Résidentiel — tout le Québec", "Hédonique LightGBM + comparables réels ajustés", "www.vrai-prix.com"],988 ["ValoPlex", "#ff9f45", "Immeubles à revenus (plex)", "Hédonique monotone + ventes de plex comparables", "www.valoplex.com"],989 ["Auto·Ka", "#ff5a2a", "Voitures usagées", "125 connecteurs concessionnaires + suivi des prix", "www.auto-ka.com"],990 ["Fabri·Ka", "#C4532E", "Produits québécois", "1 204 boutiques en ligne indexées par région", "www.fabri-ka.com"],991 ["Food·Ka", "#d9f26b", "Épicerie", "20 bannières — prix, soldes et prix unitaires", "www.food-ka.com"],992 ["Resto·Ka", "#ffc53d", "Restaurants — menus & prix", "19 chaînes intégrées — 61 000+ plats suivis", "www.resto-ka.com"],993 ["Sorti·Ka", "#ff6a00", "Sorties & événements", "Billetteries + données ouvertes — MàJ horaire", "www.sorti-ka.com"],994 ["Créa·Ka", "#7da2ff", "Créateurs de contenu", "Annuaire multi-plateformes + résolution d'identité", "www.crea-ka.com"],995 ];996 const tbody = document.querySelector("#socle-table tbody");997 for (const [name, accent, market, engine, url] of ROWS) {998 const tr = document.createElement("tr");999 tr.innerHTML =1000 `<td class="nm"><span class="brand"><i style="background:${accent}"></i></span>${name}</td>` +1001 `<td>${market}</td><td>${engine}</td><td class="url">${url}</td>`;1002 tbody.appendChild(tr);1003 }1004})();1005</script>1006</body>1007</html>1008