spb/ora-ka Public
Ora-Ka — cinq agrégateurs Ka, une barre de recherche hybride (exact + sémantique)
Python 80%
TypeScript 12.9%
CSS 6.8%
1# -----------------------------------------------------------------------------2# Ora-Ka — Landing : LA barre de recherche. Verre dépoli, épurée, moderne.3# Auteur : Simon-Pierre Boucher — contact@spboucher.ai4# -----------------------------------------------------------------------------56LANDING = """<!doctype html>7<html lang="fr">8<head>9<meta charset="utf-8">10<meta name="viewport" content="width=device-width, initial-scale=1, viewport-fit=cover">11<title>Ora·Ka — Cherchez tout le Québec</title>12<meta name="description" content="Ora-Ka : une seule barre de recherche pour tout le Québec — propriétés, logements, produits d'ici, véhicules et épicerie. Recherche exacte et sémantique.">13<link rel="icon" href="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 64 64'%3E%3Crect width='64' height='64' rx='14' fill='%23141518'/%3E%3Ctext x='32' y='42' font-family='Arial Black,sans-serif' font-size='26' font-weight='900' fill='%23ffffff' text-anchor='middle'%3EOK%3C/text%3E%3C/svg%3E">14<link rel="preconnect" href="https://fonts.googleapis.com">15<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>16<link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@500;600;700&family=Inter:wght@400;500;600&family=JetBrains+Mono:wght@500;700&display=swap" rel="stylesheet">17<style>18:root{19 --bg:#f5f3ee; --ink:#141814; --ink-2:#4d5551; --ink-3:#8b928c;20 --lime:#d9f26b; --lime-soft:#f0f9d2;21 --glass:rgba(255,255,255,.58); --glass-2:rgba(255,255,255,.44);22 --gline:rgba(255,255,255,.65); --gline-2:rgba(20,24,20,.08);23 --iline:rgba(20,24,20,.85);24 --d-immo:#e23744; --d-lou:#1c5c41; --d-fabri:#c4532e; --d-auto:#ff5a2a; --d-food:#1f7a4d;25 --mono:"JetBrains Mono",ui-monospace,monospace;26 --shadow:0 8px 32px rgba(20,24,20,.08);27 --shadow-lg:0 18px 48px rgba(20,24,20,.12);28 --off:4px 4px 0 var(--ink);29 --off-lg:7px 8px 0 var(--ink);30}31*{box-sizing:border-box;margin:0;padding:0}32html{scroll-behavior:smooth}33body{background:var(--bg);color:var(--ink);font-family:Inter,system-ui,sans-serif;font-size:16px;line-height:1.5;34 -webkit-font-smoothing:antialiased;min-height:100vh;display:flex;flex-direction:column}35::selection{background:var(--lime);color:var(--ink)}36/* halos doux + grain de papier — la texture signature de la famille Ka */37body::before{content:"";position:fixed;inset:-10%;z-index:-1;pointer-events:none;38 background:39 radial-gradient(640px 520px at 12% 12%, rgba(226,55,68,.08), transparent 62%),40 radial-gradient(720px 560px at 88% 8%, rgba(255,90,42,.06), transparent 62%),41 radial-gradient(820px 640px at 78% 92%, rgba(31,122,77,.08), transparent 62%),42 radial-gradient(700px 560px at 8% 88%, rgba(217,242,107,.10), transparent 62%);43 filter:blur(6px)}44body::after{content:"";position:fixed;inset:0;pointer-events:none;z-index:2000;opacity:.35;45 background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='120' height='120'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2'/%3E%3CfeColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 .04 0'/%3E%3C/filter%3E%3Crect width='120' height='120' filter='url(%23n)'/%3E%3C/svg%3E")}46main{flex:1;width:100%}47.container{max-width:1180px;margin:0 auto;padding:0 22px;width:100%}48.glass{background:var(--glass);backdrop-filter:blur(20px) saturate(1.5);-webkit-backdrop-filter:blur(20px) saturate(1.5);49 border:1px solid var(--gline);box-shadow:var(--shadow)}5051/* ------- en-tête / compte KA ID ------- */52.topbar{position:fixed;top:0;left:0;right:0;z-index:120;display:flex;justify-content:flex-end;53 padding:14px 18px;pointer-events:none}54.topbar>*{pointer-events:auto}55#auth{position:relative;display:flex;align-items:center;min-height:38px}56.ka-btn{display:inline-flex;align-items:center;gap:9px;background:var(--ink);color:#f4f5f7;57 border-radius:999px;padding:8px 16px 8px 9px;font-size:13px;font-weight:600;letter-spacing:.01em;58 text-decoration:none;font-family:Inter,sans-serif;border:1px solid rgba(255,255,255,.08);59 box-shadow:0 6px 20px rgba(20,22,26,.18);transition:transform .18s,box-shadow .18s}60.ka-btn:hover{transform:translateY(-1px);box-shadow:0 10px 26px rgba(20,22,26,.24)}61.ka-badge{display:inline-flex;align-items:center;justify-content:center;background:#d9f26b;color:#16181c;62 border-radius:6px;padding:3px 6px;font-family:"Space Grotesk",sans-serif;font-size:10.5px;font-weight:700;63 letter-spacing:.04em;transform:rotate(-2deg)}64.ka-avatar{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;border-radius:50%;65 border:1px solid var(--gline);background:var(--ink);color:#d9f26b;font-family:"Space Grotesk",sans-serif;66 font-size:15px;font-weight:700;cursor:pointer;overflow:hidden;padding:0;67 box-shadow:0 6px 20px rgba(20,22,26,.16);transition:transform .18s,box-shadow .18s}68.ka-avatar:hover{transform:translateY(-1px);box-shadow:0 10px 26px rgba(20,22,26,.22)}69.ka-avatar img{width:100%;height:100%;object-fit:cover;display:block}70.ka-menu{position:absolute;top:46px;right:0;width:min(272px,calc(100vw - 36px));border-radius:18px;padding:16px;71 display:none;text-align:left;background:rgba(255,255,255,.86);backdrop-filter:blur(22px) saturate(1.5);72 -webkit-backdrop-filter:blur(22px) saturate(1.5);border:1px solid var(--gline);box-shadow:var(--shadow-lg)}73.ka-menu.open{display:block;animation:menu-in .18s cubic-bezier(.2,.6,.2,1) both}74@keyframes menu-in{from{opacity:0;transform:translateY(-5px) scale(.98)}to{opacity:1;transform:none}}75.ka-menu .m-name{font-size:14px;font-weight:600;color:var(--ink);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}76.ka-menu .m-mail{font-size:12px;color:var(--ink-2);margin-top:1px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}77.ka-menu .m-id{font-family:ui-monospace,SFMono-Regular,Menlo,monospace;font-size:11px;color:var(--ink-3);78 margin-top:7px;letter-spacing:.02em}79.ka-menu .m-role{display:inline-flex;align-items:center;margin-top:8px;border-radius:999px;padding:3px 10px;80 font-size:10.5px;font-weight:600;letter-spacing:.05em;text-transform:uppercase;color:var(--ink);81 background:#d9f26b}82.ka-menu hr{border:0;border-top:1px solid var(--gline-2);margin:12px 0}83.ka-menu .m-link{display:block;font-size:13px;font-weight:500;color:var(--ink-2);text-decoration:none;84 padding:7px 8px;margin:0 -8px;border-radius:10px}85.ka-menu .m-link:hover{color:var(--ink);background:rgba(22,24,28,.05)}86.ka-menu .m-out{display:block;width:calc(100% + 16px);margin:0 -8px;border:0;background:transparent;cursor:pointer;87 text-align:left;font-family:Inter,sans-serif;font-size:13px;font-weight:500;color:#b03540;88 padding:7px 8px;border-radius:10px}89.ka-menu .m-out:hover{background:rgba(221,74,85,.08)}90@media(max-width:560px){.topbar{padding:12px 14px}.ka-btn{padding:7px 13px 7px 8px;font-size:12.5px}}9192/* ------- splash Groupe KA ------- */93#splash{position:fixed;inset:0;z-index:900;background:var(--bg);display:flex;align-items:center;justify-content:center;94 transition:opacity .55s ease,visibility .55s}95#splash::before{content:"";position:absolute;inset:-10%;pointer-events:none;96 background:radial-gradient(640px 520px at 20% 20%, rgba(221,74,85,.07), transparent 62%),97 radial-gradient(720px 560px at 80% 80%, rgba(61,143,102,.07), transparent 62%);filter:blur(6px)}98#splash.done{opacity:0;visibility:hidden}99.sp-inner{position:relative;text-align:center}100.sp-kicker{font-family:var(--mono);font-size:11.5px;font-weight:700;color:var(--ink-2);101 text-transform:uppercase;animation:sp-track 1.1s cubic-bezier(.2,.6,.2,1) both}102@keyframes sp-track{from{letter-spacing:.65em;opacity:0;transform:translateY(6px)}to{letter-spacing:.3em;opacity:1;transform:none}}103.sp-brand{font-family:"Space Grotesk",sans-serif;font-weight:700;letter-spacing:-.045em;font-size:clamp(46px,7vw,72px);104 line-height:1.05;margin-top:10px;animation:sp-brand 1s .12s cubic-bezier(.2,.6,.2,1) both}105@keyframes sp-brand{from{opacity:0;transform:scale(.94) translateY(10px);filter:blur(8px)}to{opacity:1;transform:none;filter:blur(0)}}106.sp-brand .ka{display:inline-block;background:var(--ink);color:var(--lime);border-radius:.14em;107 padding:.02em .16em .06em;margin-left:.06em;animation:sp-ka 1s .3s cubic-bezier(.3,1.5,.5,1) both}108@keyframes sp-ka{from{transform:rotate(-11deg) scale(.85);opacity:0}to{transform:rotate(-2deg) scale(1);opacity:1}}109.sp-dots{display:flex;justify-content:center;gap:10px;margin-top:26px}110.sp-dots i{width:9px;height:9px;border-radius:50%;animation:sp-wave 1.05s ease-in-out infinite}111.sp-dots i:nth-child(1){background:var(--d-immo);animation-delay:0s}112.sp-dots i:nth-child(2){background:var(--d-lou);animation-delay:.09s}113.sp-dots i:nth-child(3){background:var(--d-fabri);animation-delay:.18s}114.sp-dots i:nth-child(4){background:var(--d-auto);animation-delay:.27s}115.sp-dots i:nth-child(5){background:var(--d-food);animation-delay:.36s}116@keyframes sp-wave{0%,60%,100%{transform:translateY(0);opacity:.55}30%{transform:translateY(-9px);opacity:1}}117.sp-line{width:180px;height:2px;border-radius:2px;background:rgba(22,24,28,.09);margin:24px auto 0;overflow:hidden}118.sp-line i{display:block;height:100%;width:100%;border-radius:2px;119 background:linear-gradient(90deg,var(--ink) 55%,var(--lime));120 transform-origin:left;animation:sp-fill 1.25s .1s cubic-bezier(.3,.1,.2,1) both}121@keyframes sp-fill{from{transform:scaleX(0)}to{transform:scaleX(1)}}122.sp-tag{margin-top:20px;font-family:var(--mono);font-size:10.5px;color:var(--ink-3);letter-spacing:.08em;text-transform:uppercase;123 animation:sp-tag .8s .5s ease both}124@keyframes sp-tag{from{opacity:0;transform:translateY(6px)}to{opacity:1;transform:none}}125@media(prefers-reduced-motion:reduce){#splash{display:none}}126127/* ------- entrée en cascade du héros ------- */128body:not(.ready) .hero>*{opacity:0}129body.ready .hero>*{animation:rise .65s cubic-bezier(.2,.6,.2,1) both}130body.ready .hero>*:nth-child(1){animation-delay:.05s}131body.ready .hero>*:nth-child(2){animation-delay:.14s}132body.ready .hero>*:nth-child(3){animation-delay:.23s}133body.ready .hero>*:nth-child(4){animation-delay:.34s}134body.ready .hero>*:nth-child(5){animation-delay:.45s}135body.ready .hero>*:nth-child(6){animation-delay:.56s}136body.ready .hero>*:nth-child(7){animation-delay:.68s}137@keyframes rise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}138@media(prefers-reduced-motion:reduce){body:not(.ready) .hero>*{opacity:1}body.ready .hero>*{animation:none}}139140/* ------- héro / barre ------- */141.hero{display:flex;flex-direction:column;align-items:center;justify-content:center;text-align:center;142 min-height:64vh;padding:60px 22px 30px;transition:min-height .45s cubic-bezier(.4,0,.2,1),padding .45s cubic-bezier(.4,0,.2,1)}143body.searching .hero{min-height:0;padding:32px 22px 6px}144.kicker{display:inline-flex;align-items:center;gap:10px;font-family:var(--mono);font-size:11.5px;font-weight:700;145 letter-spacing:.16em;text-transform:uppercase;color:var(--ink-2)}146.kicker::before,.kicker::after{content:"";display:inline-block;width:30px;height:2px;background:var(--ink)}147body.searching .kicker{display:none}148.brand{font-family:"Space Grotesk",sans-serif;font-weight:700;letter-spacing:-.045em;font-size:clamp(42px,6.6vw,68px);149 line-height:1;user-select:none;transition:font-size .45s cubic-bezier(.4,0,.2,1);margin-top:14px}150body.searching .brand{font-size:26px;margin-top:0}151.brand .ka{display:inline-block;background:var(--ink);color:var(--lime);border-radius:.14em;152 padding:.02em .16em .06em;margin-left:.06em;transform:rotate(-2deg);transition:transform .3s cubic-bezier(.3,1.4,.5,1)}153.brand:hover .ka{transform:rotate(0)}154body.fetching .brand .ka{animation:ka-tilt .9s ease-in-out infinite}155@keyframes ka-tilt{0%,100%{transform:rotate(-2deg)}50%{transform:rotate(2deg)}}156.sub{margin-top:14px;color:var(--ink-2);font-size:15.5px;font-weight:400;transition:opacity .3s}157.sub b{color:var(--ink);font-weight:600;background:linear-gradient(transparent 62%,var(--lime) 62%)}158body.searching .sub{display:none}159160.barwrap{position:relative;width:min(720px,100%);margin-top:36px;transition:margin .45s}161body.searching .barwrap{margin-top:18px}162.bar{display:flex;align-items:center;border-radius:18px;border:2px solid var(--ink) !important;163 box-shadow:var(--off-lg),var(--shadow) !important;transition:box-shadow .22s,transform .22s}164.bar:focus-within{transform:translate(-2px,-3px);box-shadow:10px 11px 0 var(--ink),var(--shadow-lg) !important}165.bar input{caret-color:var(--d-immo)}166.bar .lens{padding:0 4px 0 22px;font-size:19px;color:var(--ink-3);display:flex;align-items:center;min-width:45px}167.bar .spin{display:none;width:17px;height:17px;border-radius:50%;168 border:2px solid rgba(22,24,28,.14);border-top-color:var(--ink);animation:rot .65s linear infinite}169@keyframes rot{to{transform:rotate(360deg)}}170body.fetching .bar .lg{display:none}171body.fetching .bar .spin{display:block}172body.fetching .bar{box-shadow:var(--shadow-lg)}173.bar input{flex:1;border:0;outline:0;background:transparent;font-family:Inter,sans-serif;174 font-size:17.5px;font-weight:500;color:var(--ink);padding:20px 10px;min-width:0}175.bar input::placeholder{color:var(--ink-3);font-weight:400}176.bar input::-webkit-search-cancel-button{display:none}177.bar .x{display:none;border:0;background:transparent;cursor:pointer;font-size:14px;color:var(--ink-3);padding:10px 20px 10px 6px}178.bar .x:hover{color:var(--ink)}179.barwrap.has-q .x{display:block}180@media(max-width:560px){.bar input{font-size:16px;padding:16px 8px}.bar .lens{padding-left:17px}}181182/* ------- portées ------- */183.scopes{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:20px}184.scope{display:inline-flex;align-items:center;gap:8px;border-radius:999px;padding:8px 15px;185 font-family:var(--mono);font-size:11.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;186 color:var(--ink);cursor:pointer;transition:all .16s;187 background:var(--glass);backdrop-filter:blur(14px);-webkit-backdrop-filter:blur(14px);border:1.5px solid var(--ink)}188.scope .dot{width:7px;height:7px;border-radius:50%}189.scope:hover{transform:translate(-1px,-2px);box-shadow:3px 3px 0 var(--ink)}190.scope.on{background:var(--ink);border-color:var(--ink);color:var(--lime);animation:pop .28s cubic-bezier(.3,1.5,.5,1)}191@keyframes pop{0%{transform:scale(.94)}60%{transform:scale(1.045)}100%{transform:scale(1)}}192.suggests{display:flex;flex-wrap:wrap;justify-content:center;gap:8px;margin-top:26px;transition:opacity .3s}193body.searching .suggests{display:none}194.suggest{border:1px dashed var(--ink-3);background:transparent;padding:5px 12px;font-family:var(--mono);195 font-size:11.5px;color:var(--ink-2);cursor:pointer;border-radius:999px;transition:all .15s}196.suggest:hover{color:var(--ink);border-color:var(--ink);background:var(--glass)}197198/* ------- ticker famille Ka ------- */199.ticker{width:100vw;margin:44px calc(50% - 50vw) 0;background:var(--ink);color:var(--lime);overflow:hidden;200 border-top:2px solid var(--ink);border-bottom:2px solid var(--ink)}201body.searching .ticker{display:none}202.ticker-inner{display:flex;gap:44px;white-space:nowrap;padding:8px 0;font-family:var(--mono);font-size:11.5px;203 font-weight:700;letter-spacing:.1em;text-transform:uppercase;width:max-content;animation:tick 44s linear infinite}204.ticker-inner span::after{content:"◆";margin-left:44px;opacity:.5}205@keyframes tick{from{transform:translateX(0)}to{transform:translateX(-50%)}}206@media(prefers-reduced-motion:reduce){.ticker-inner{animation:none}}207208/* ------- résultats ------- */209#results{padding:6px 0 70px;display:none}210.rhead{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:12px 0 18px}211.rinfo{font-family:var(--mono);font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2)}212.rinfo b{color:var(--ink);font-weight:700;font-size:13px}213.rinfo .ai{display:inline-flex;align-items:center;gap:5px;margin-left:10px;color:var(--ink-3)}214.fchips{display:flex;flex-wrap:wrap;gap:7px}215.fchip{display:inline-flex;align-items:center;gap:7px;border-radius:999px;padding:6px 13px;216 font-family:var(--mono);font-size:11px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;217 color:var(--ink);cursor:pointer;transition:all .15s;text-decoration:none;218 background:var(--glass);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1.5px solid var(--ink)}219.fchip .dot{width:6px;height:6px;border-radius:50%}220.fchip b{color:var(--ink);font-weight:700}221.fchip:hover{transform:translate(-1px,-2px);box-shadow:3px 3px 0 var(--ink)}222.rgrid{display:grid;grid-template-columns:repeat(auto-fill,minmax(216px,1fr));gap:16px}223.rcard{display:flex;flex-direction:column;border-radius:14px;overflow:hidden;text-decoration:none;color:var(--ink);224 background:var(--glass);backdrop-filter:blur(18px) saturate(1.4);-webkit-backdrop-filter:blur(18px) saturate(1.4);225 border:1.5px solid var(--ink);box-shadow:var(--off);transition:transform .16s,box-shadow .16s;animation:up .35s both}226.rcard:hover{transform:translate(-2px,-3px);box-shadow:var(--off-lg)}227@keyframes up{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}228.rimg{aspect-ratio:4/3;background:rgba(255,255,255,.35);overflow:hidden;position:relative}229.rimg .ph{position:absolute;inset:0;display:flex;align-items:center;justify-content:center;font-size:30px;opacity:.75}230.rimg img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block;transition:transform .45s cubic-bezier(.2,.6,.2,1)}231.rcard:hover .rimg img{transform:scale(1.045)}232.rtag{position:absolute;top:9px;left:9px;display:inline-flex;align-items:center;gap:6px;border-radius:999px;233 padding:4px 10px;font-family:var(--mono);font-size:9.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;color:var(--ink);234 background:rgba(255,255,255,.85);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid var(--iline)}235.rtag .dot{width:6px;height:6px;border-radius:50%}236.rscore{position:absolute;top:9px;right:9px;display:inline-flex;align-items:center;gap:4px;border-radius:999px;237 padding:4px 9px;font-family:var(--mono);font-size:9.5px;font-weight:700;letter-spacing:.02em;color:var(--ink);238 background:rgba(255,255,255,.85);backdrop-filter:blur(10px);-webkit-backdrop-filter:blur(10px);border:1px solid var(--iline)}239.rscore.exact{background:var(--lime);border-color:var(--ink)}240.rbody{padding:12px 14px 14px;display:flex;flex-direction:column;gap:4px;flex:1}241.rtitle{font-size:14px;font-weight:500;line-height:1.35;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}242.rtitle mark{background:var(--lime);color:inherit;border-radius:3px;padding:0 2px;font-weight:600}243.rmeter{height:3px;border-radius:2px;background:rgba(20,24,20,.1);margin-top:8px;overflow:hidden}244.rmeter i{display:block;height:100%;border-radius:2px;background:var(--ink)}245.rsub{font-family:var(--mono);font-size:10px;letter-spacing:.03em;text-transform:uppercase;color:var(--ink-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}246.rprice{font-family:"Space Grotesk",sans-serif;font-size:16px;font-weight:600;margin-top:auto;padding-top:6px;color:var(--ink)}247.notice{margin:36px auto;text-align:center;max-width:430px;color:var(--ink-2);padding:44px 26px;border-radius:14px;248 border:2px dashed rgba(20,24,20,.25);background:transparent !important;box-shadow:none !important}249.notice .big{font-size:36px;margin-bottom:10px}250.loading .rgrid,.loading .rhead{opacity:.45}251.skel{border-radius:14px;overflow:hidden;background:var(--glass-2);border:1.5px solid rgba(20,24,20,.35);position:relative;animation:up .35s both}252.skel::after{content:"";position:absolute;inset:0;transform:translateX(-100%);253 background:linear-gradient(100deg,transparent 30%,rgba(255,255,255,.65) 50%,transparent 70%);254 animation:shimmer 1.4s ease-in-out infinite}255@keyframes shimmer{to{transform:translateX(100%)}}256.skel .si{aspect-ratio:4/3;background:rgba(255,255,255,.45)}257.skel .sb{padding:12px 14px 16px}258.skel .sl{height:11px;border-radius:6px;background:rgba(22,24,28,.07);margin-bottom:8px}259.skel .sl.w60{width:60%}260.ka-loader{display:inline-flex;gap:6px;margin-left:10px;vertical-align:middle}261.ka-loader i{width:6px;height:6px;border-radius:50%;animation:sp-wave 1.05s ease-in-out infinite}262.ka-loader i:nth-child(1){background:var(--d-immo)}263.ka-loader i:nth-child(2){background:var(--d-lou);animation-delay:.09s}264.ka-loader i:nth-child(3){background:var(--d-fabri);animation-delay:.18s}265.ka-loader i:nth-child(4){background:var(--d-auto);animation-delay:.27s}266.ka-loader i:nth-child(5){background:var(--d-food);animation-delay:.36s}267.morewrap{display:flex;justify-content:center;margin-top:28px}268.morebtn{border-radius:999px;padding:11px 26px;font-family:var(--mono);font-size:11.5px;font-weight:700;269 letter-spacing:.06em;text-transform:uppercase;color:var(--ink);cursor:pointer;270 background:var(--glass);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);border:1.5px solid var(--ink);transition:all .15s}271.morebtn:hover{transform:translate(-1px,-2px);box-shadow:var(--off)}272273/* ------- « Mon univers Ka » (favoris du hub, toutes plateformes) ------- */274#kafavs{display:none;padding:4px 0 34px}275#kafavs.show{display:block;animation:up .35s both}276body.searching #kafavs.show{display:none}277.uhead{display:flex;align-items:baseline;justify-content:space-between;gap:8px 18px;flex-wrap:wrap;padding:10px 0 16px}278.utitle{font-family:var(--mono);font-size:11.5px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--ink-2)}279.utitle .uht{color:var(--d-immo);margin-right:6px}280.ulink{font-family:var(--mono);font-size:10.5px;font-weight:700;letter-spacing:.05em;text-transform:uppercase;281 color:var(--ink-3);text-decoration:none;border-bottom:2px solid var(--lime);padding-bottom:1px;transition:color .15s}282.ulink:hover{color:var(--ink)}283284/* ------- pied ------- */285footer{padding:26px 22px 34px;text-align:center}286.flinks{display:flex;justify-content:center;flex-wrap:wrap;gap:4px 20px;margin-bottom:12px}287.flinks a{display:inline-flex;align-items:center;gap:7px;font-family:var(--mono);font-size:11px;font-weight:700;288 letter-spacing:.05em;text-transform:uppercase;color:var(--ink-2);text-decoration:none;padding:4px 2px;transition:color .15s;289 border-bottom:2px solid var(--lime)}290.flinks a .dot{width:6px;height:6px;border-radius:50%;opacity:.7}291.flinks a:hover{color:var(--ink)}292.fgroup{font-size:12px;color:var(--ink-2);margin-bottom:8px}293.fgroup a{color:var(--ink-2);text-decoration:underline;text-underline-offset:2px}294.fgroup a:hover{color:var(--ink)}295.flegal-links{font-size:11.5px;color:var(--ink-3);margin-bottom:8px}296.flegal-links a{color:var(--ink-3);text-decoration:none;margin:0 8px}297.flegal-links a:hover{color:var(--ink)}298.legal{font-size:11px;color:var(--ink-3)}299@media(prefers-reduced-motion:reduce){.rcard{animation:none}}300</style>301</head>302<body>303304<header class="topbar">305 <div id="auth"></div>306</header>307308<div id="splash" aria-hidden="true">309 <div class="sp-inner">310 <div class="sp-kicker">Groupe KA</div>311 <div class="sp-brand">Ora<span class="ka">Ka</span></div>312 <div class="sp-dots"><i></i><i></i><i></i><i></i><i></i></div>313 <div class="sp-line"><i></i></div>314 <div class="sp-tag">Une application du Groupe KA</div>315 </div>316</div>317318<main>319 <section class="hero">320 <div class="kicker">Un moteur · Cinq univers · Tout le Québec</div>321 <h1 class="brand">Ora<span class="ka">Ka</span></h1>322 <p class="sub" id="sub">Une barre. <b>Tout le Québec.</b></p>323324 <div class="barwrap" id="barwrap">325 <div class="bar glass">326 <span class="lens"><span class="lg">⌕</span><span class="spin" aria-hidden="true"></span></span>327 <input id="q" type="search" placeholder="Cherchez n'importe quoi…" autocomplete="off" spellcheck="false" autofocus>328 <button class="x" id="clear" aria-label="Effacer">✕</button>329 </div>330 </div>331332 <div class="scopes" id="scopes">333 <button class="scope on" data-scope="">Tout</button>334 <button class="scope" data-scope="immo"><span class="dot" style="background:var(--d-immo)"></span>Propriétés</button>335 <button class="scope" data-scope="lou"><span class="dot" style="background:var(--d-lou)"></span>Logements</button>336 <button class="scope" data-scope="fabri"><span class="dot" style="background:var(--d-fabri)"></span>Produits QC</button>337 <button class="scope" data-scope="auto"><span class="dot" style="background:var(--d-auto)"></span>Véhicules</button>338 <button class="scope" data-scope="food"><span class="dot" style="background:var(--d-food)"></span>Épicerie</button>339 </div>340341 <div class="suggests">342 <button class="suggest">condo avec vue à Montréal</button>343 <button class="suggest">4½ près de Limoilou</button>344 <button class="suggest">sirop d'érable artisanal</button>345 <button class="suggest">VUS hybride récent</button>346 <button class="suggest">café de spécialité</button>347 </div>348349 <div class="ticker"><div class="ticker-inner" id="ticker">350 <span>ORA·KA — LE MOTEUR DES AGRÉGATEURS</span><span>IMMO·KA — PROPRIÉTÉS À VENDRE</span><span>LOU·KA — LOGEMENTS À LOUER</span><span>FABRI·KA — PRODUITS QUÉBÉCOIS</span><span>AUTO·KA — VÉHICULES D'OCCASION</span><span>FOOD·KA — ÉPICERIE COMPARÉE</span><span>MISE À JOUR AUTOMATIQUE</span><span>ORA·KA — LE MOTEUR DES AGRÉGATEURS</span><span>IMMO·KA — PROPRIÉTÉS À VENDRE</span><span>LOU·KA — LOGEMENTS À LOUER</span><span>FABRI·KA — PRODUITS QUÉBÉCOIS</span><span>AUTO·KA — VÉHICULES D'OCCASION</span><span>FOOD·KA — ÉPICERIE COMPARÉE</span><span>MISE À JOUR AUTOMATIQUE</span>351 </div></div>352 </section>353354 <section id="kafavs" class="container" aria-label="Mon univers Ka">355 <div class="uhead">356 <div class="utitle"><span class="uht">♥</span>Mon univers Ka — tout ce que j'ai sauvegardé</div>357 <a class="ulink" href="https://www.groupe-ka.com/compte" target="_blank" rel="noopener">gérer sur groupe-ka.com/compte ↗</a>358 </div>359 <div class="rgrid" id="kafavs-grid"></div>360 </section>361362 <section id="results" class="container"></section>363</main>364365<footer>366 <div class="flinks">367 <a href="/immo/"><span class="dot" style="background:var(--d-immo)"></span>Immo·Ka</a>368 <a href="/lou/"><span class="dot" style="background:var(--d-lou)"></span>Lou·Ka</a>369 <a href="/fabri/"><span class="dot" style="background:var(--d-fabri)"></span>Fabri·Ka</a>370 <a href="/auto/"><span class="dot" style="background:var(--d-auto)"></span>Auto·Ka</a>371 <a href="/food/"><span class="dot" style="background:var(--d-food)"></span>Food·Ka</a>372 </div>373 <div class="fgroup">Ora-Ka est une application du <a href="https://www.groupe-ka.com" rel="noopener">Groupe KA</a> — <a href="mailto:contact@groupe-ka.com">contact@groupe-ka.com</a></div>374 <div class="flegal-links"><a href="/conditions">Conditions d'utilisation</a>·<a href="/confidentialite">Politique de confidentialité</a></div>375 <div class="legal">© 2026 Groupe KA — Ora-Ka agrège des données publiques ; chaque inscription reste la propriété de sa source.</div>376</footer>377378<script>379(function(){380 /* ---- splash Groupe KA ---- */381 var splash = document.getElementById('splash');382 var reduced = window.matchMedia('(prefers-reduced-motion: reduce)').matches;383 var seen = false;384 try { seen = sessionStorage.getItem('oraka-splash') === '1'; } catch(e){}385 var hasQ = new URLSearchParams(location.search).has('q');386 var dur = (reduced || !splash) ? 0 : (seen || hasQ ? 450 : 1600);387 function boot(){388 document.body.classList.add('ready');389 if(splash){390 splash.classList.add('done');391 setTimeout(function(){ if(splash.parentNode) splash.parentNode.removeChild(splash); }, 650);392 }393 try { sessionStorage.setItem('oraka-splash', '1'); } catch(e){}394 }395 if(dur === 0){ boot(); } else { setTimeout(boot, dur); }396})();397(function(){398 var fmt = new Intl.NumberFormat('fr-CA');399 var PLACE = {immo:'🏡', lou:'🔑', fabri:'📦', auto:'🚗', food:'🛒'};400 var COLOR = {immo:'var(--d-immo)', lou:'var(--d-lou)', fabri:'var(--d-fabri)', auto:'var(--d-auto)', food:'var(--d-food)'};401 var LABEL = {immo:'Propriétés', lou:'Logements', fabri:'Produits QC', auto:'Véhicules', food:'Épicerie'};402403 var input = document.getElementById('q');404 var barwrap = document.getElementById('barwrap');405 var results = document.getElementById('results');406 var scope = '', timer = null, ctrl = null, seq = 0;407 var lastData = null, shown = 0;408 var PAGE = 24;409410 fetch('/api/overview').then(function(r){return r.json()}).then(function(d){411 document.getElementById('sub').innerHTML = 'Une barre. <b>' + fmt.format(d.total) + ' inscriptions.</b> Tout le Québec.';412 if(!input.value) input.placeholder = 'Cherchez parmi ' + fmt.format(d.total) + ' inscriptions…';413 var a = d.apps;414 var parts = [415 'ORA·KA — '+fmt.format(d.total)+' INSCRIPTIONS DANS LE MOTEUR',416 'IMMO·KA — '+fmt.format(a.immo.n)+' PROPRIÉTÉS À VENDRE',417 'LOU·KA — '+fmt.format(a.lou.n)+' LOGEMENTS À LOUER',418 'FABRI·KA — '+fmt.format(a.fabri.n)+' PRODUITS QUÉBÉCOIS',419 'AUTO·KA — '+fmt.format(a.auto.n)+' VÉHICULES D\\'OCCASION',420 'FOOD·KA — '+fmt.format(a.food.n)+' ARTICLES D\\'ÉPICERIE',421 'MISE À JOUR AUTOMATIQUE'422 ];423 var html = parts.map(function(p){return '<span>'+p+'</span>'}).join('');424 var tk = document.getElementById('ticker');425 if(tk) tk.innerHTML = html + html;426 }).catch(function(){});427428 function esc(s){ var d=document.createElement('div'); d.textContent=s==null?'':String(s); return d.innerHTML; }429 function norm(s){ return s.normalize('NFD').replace(/[\\u0300-\\u036f]/g,'').toLowerCase(); }430431 var STOP = {avec:1,pour:1,dans:1,pres:1,sur:1,les:1,des:1,une:1,aux:1,est:1,par:1,chez:1,tout:1,tres:1};432 function hl(title, q){433 var t = esc(title);434 var toks = q.split(/[^0-9A-Za-zÀ-ÖØ-öø-ÿ½'-]+/).filter(function(w){435 return w.length>=3 && !STOP[norm(w)];436 });437 if(!toks.length) return t;438 var nt = norm(t);439 var marks = [];440 toks.forEach(function(tok){441 var n = norm(tok), from = 0, idx;442 while((idx = nt.indexOf(n, from)) !== -1){443 var prev = idx > 0 ? nt[idx-1] : ' ';444 if(!/[a-z0-9]/.test(prev)) marks.push([idx, idx+n.length]);445 from = idx+n.length;446 }447 });448 if(!marks.length) return t;449 marks.sort(function(a,b){return a[0]-b[0]});450 var merged = [marks[0]];451 for(var i=1;i<marks.length;i++){452 var last = merged[merged.length-1];453 if(marks[i][0] <= last[1]) last[1] = Math.max(last[1], marks[i][1]);454 else merged.push(marks[i]);455 }456 var out = '', pos = 0;457 merged.forEach(function(m){458 out += t.slice(pos, m[0]) + '<mark>' + t.slice(m[0], m[1]) + '</mark>';459 pos = m[1];460 });461 return out + t.slice(pos);462 }463464 function pct(it, best){465 if(typeof it.score !== 'number' || !best) return null;466 return Math.max(1, Math.min(100, Math.round(100 * it.score / best)));467 }468469 function card(it, i, best, q){470 var p = pct(it, best);471 var badge = p == null ? '' :472 '<span class="rscore'+(it.match==='exact'?' exact':'')+'" title="'+(it.match==='exact'?'Correspondance exacte':'Correspondance sémantique')+' — pertinence relative">'+473 (it.match==='exact'?'✓':'✦')+' '+p+' %</span>';474 var img = it.image475 ? '<img loading="lazy" src="'+esc(it.image)+'" alt="" onerror="this.remove()">'476 : '';477 return '<a class="rcard" style="animation-delay:'+Math.min(i*20,360)+'ms" href="'+esc(it.href)+'">'+478 '<div class="rimg"><span class="ph">'+PLACE[it.app]+'</span>'+img+479 '<span class="rtag"><span class="dot" style="background:'+COLOR[it.app]+'"></span>'+LABEL[it.app]+'</span>'+480 badge+481 '</div>'+482 '<div class="rbody"><div class="rtitle">'+hl(it.title, q)+'</div>'+483 (it.sub ? '<div class="rsub">'+esc(it.sub)+'</div>' : '')+484 (it.price ? '<div class="rprice">'+esc(it.price)+'</div>' : '')+485 (p != null ? '<div class="rmeter" aria-hidden="true"><i style="width:'+p+'%"></i></div>' : '')+486 '</div></a>';487 }488489 function render(){490 var d = lastData;491 if(!d || !d.q){ hide(); return; }492 var totalExact = 0;493 Object.keys(d.totals||{}).forEach(function(k){ totalExact += d.totals[k]; });494 var chips = Object.keys(d.counts).map(function(a){495 var target = (d.more && d.more[a]) || '#';496 var n = (d.totals && d.totals[a]) ? d.totals[a] : d.counts[a];497 return '<a class="fchip" href="'+esc(target)+'"><span class="dot" style="background:'+COLOR[a]+'"></span>'+498 LABEL[a]+' <b>'+fmt.format(n)+'</b></a>';499 }).join('');500 var best = 0;501 d.hits.forEach(function(h){ if(typeof h.score === 'number' && h.score > best) best = h.score; });502 var html = '<div class="rhead"><div class="rinfo"><b>'+fmt.format(Math.max(totalExact, d.hits.length))+'</b> résultat'+(d.hits.length>1?'s':'')+503 ' pour « '+esc(d.q)+' » — triés par pertinence'+(d.semantic ? '<span class="ai">✦ sémantique active</span>' : '')+'</div>'+504 '<div class="fchips">'+chips+'</div></div>';505 if(d.hits.length){506 html += '<div class="rgrid">'+d.hits.slice(0, shown).map(function(it,i){return card(it,i,best,d.q)}).join('')+'</div>';507 if(shown < d.hits.length){508 html += '<div class="morewrap"><button class="morebtn" id="more">Afficher plus (' + (d.hits.length - shown) + ')</button></div>';509 }510 } else {511 html += '<div class="notice glass"><div class="big">🧭</div>Rien trouvé pour « '+esc(d.q)+' ».<br>Essayez d\\'autres mots — le moteur comprend aussi les descriptions.</div>';512 }513 results.innerHTML = html;514 results.style.display = 'block';515 document.body.classList.add('searching');516 results.classList.remove('loading');517 var more = document.getElementById('more');518 if(more) more.addEventListener('click', function(){ shown += PAGE; render(); });519 }520521 function hide(){522 results.style.display = 'none';523 results.innerHTML = '';524 document.body.classList.remove('searching');525 document.body.classList.remove('fetching');526 }527528 function run(){529 var q = input.value.trim();530 barwrap.classList.toggle('has-q', q.length > 0);531 if(ctrl) ctrl.abort();532 if(!q){ lastData = null; hide(); return; }533 ctrl = new AbortController();534 var my = ++seq;535 document.body.classList.add('fetching');536 if(!lastData){537 var sk = '';538 for(var i=0;i<10;i++) sk += '<div class="skel" style="animation-delay:'+(i*45)+'ms"><div class="si"></div><div class="sb"><div class="sl"></div><div class="sl w60"></div></div></div>';539 results.innerHTML = '<div class="rhead"><div class="rinfo">Recherche dans les cinq univers<span class="ka-loader"><i></i><i></i><i></i><i></i><i></i></span></div></div><div class="rgrid">'+sk+'</div>';540 results.style.display = 'block';541 document.body.classList.add('searching');542 } else {543 results.classList.add('loading');544 }545 fetch('/api/search?q='+encodeURIComponent(q)+(scope?'&scope='+scope:''), {signal: ctrl.signal})546 .then(function(r){return r.json()})547 .then(function(d){ if(my === seq){ lastData = d; shown = PAGE; render(); } })548 .catch(function(){})549 .finally(function(){ if(my === seq) document.body.classList.remove('fetching'); });550 }551552 input.addEventListener('input', function(){553 clearTimeout(timer);554 timer = setTimeout(run, 280);555 });556 input.addEventListener('keydown', function(e){557 if(e.key === 'Enter'){ clearTimeout(timer); run(); }558 if(e.key === 'Escape'){ input.value = ''; run(); }559 });560 document.getElementById('clear').addEventListener('click', function(){ input.value=''; input.focus(); run(); });561562 document.getElementById('scopes').addEventListener('click', function(e){563 var b = e.target.closest('.scope');564 if(!b) return;565 scope = b.dataset.scope || '';566 document.querySelectorAll('.scope').forEach(function(x){ x.classList.toggle('on', x === b); });567 if(input.value.trim()){ clearTimeout(timer); run(); }568 input.focus();569 });570 document.querySelectorAll('.suggest').forEach(function(b){571 b.addEventListener('click', function(){ input.value = b.textContent; run(); input.focus(); });572 });573 document.addEventListener('keydown', function(e){574 if(e.key === '/' && document.activeElement !== input){ e.preventDefault(); input.focus(); }575 });576 var uq = new URLSearchParams(location.search).get('q');577 if(uq){ input.value = uq; run(); }578})();579(function(){580 /* ---- compte KA ID (SSO du Groupe KA) ---- */581 var box = document.getElementById('auth');582 if(!box) return;583 function esc(s){ var d=document.createElement('div'); d.textContent=s==null?'':String(s); return d.innerHTML; }584 function renderBtn(){585 box.innerHTML = '<a class="ka-btn" href="/api/auth/ka/login?next=/"><span class="ka-badge">KA</span>KA ID</a>';586 }587 function renderUser(u){588 var initial = String(u.name || u.email || '?').trim().charAt(0).toUpperCase();589 var av = u.picture ? '<img src="'+esc(u.picture)+'" alt="" onerror="this.remove()">' : esc(initial);590 box.innerHTML =591 '<button class="ka-avatar" id="ka-avatar" aria-label="Compte KA ID" aria-haspopup="true">'+av+'</button>'+592 '<div class="ka-menu" id="ka-menu" role="menu">'+593 '<div class="m-name">'+esc(u.name || 'Compte KA ID')+'</div>'+594 (u.email ? '<div class="m-mail">'+esc(u.email)+'</div>' : '')+595 (u.ka_id ? '<div class="m-id">'+esc(u.ka_id)+'</div>' : '')+596 (u.role ? '<div class="m-role">'+esc(u.role)+'</div>' : '')+597 '<hr>'+598 '<a class="m-link" href="https://www.groupe-ka.com/compte" target="_blank" rel="noopener">Mon profil Groupe KA ↗</a>'+599 '<button class="m-out" id="ka-out">Se déconnecter</button>'+600 '</div>';601 var menu = document.getElementById('ka-menu');602 document.getElementById('ka-avatar').addEventListener('click', function(e){603 e.stopPropagation();604 menu.classList.toggle('open');605 });606 document.addEventListener('click', function(e){607 if(menu.classList.contains('open') && !menu.contains(e.target)) menu.classList.remove('open');608 });609 document.addEventListener('keydown', function(e){610 if(e.key === 'Escape') menu.classList.remove('open');611 });612 document.getElementById('ka-out').addEventListener('click', function(){613 fetch('/api/auth/logout', {method:'POST'})614 .then(function(){ location.reload(); })615 .catch(function(){ location.reload(); });616 });617 }618 fetch('/api/auth/me').then(function(r){return r.json()}).then(function(d){619 if(d && d.user) renderUser(d.user);620 else if(d && d.enabled) renderBtn();621 }).catch(function(){});622})();623(function(){624 /* ---- « Mon univers Ka » : les favoris du membre, toutes plateformes du625 groupe (Lou·Ka, Immo·Ka, Auto·Ka, Fabri·Ka, Food·Ka…), lus du hub.626 Visible seulement si connecté ET s'il y a au moins un favori. ---- */627 var sec = document.getElementById('kafavs');628 var grid = document.getElementById('kafavs-grid');629 if(!sec || !grid) return;630 function esc(s){ var d=document.createElement('div'); d.textContent=s==null?'':String(s); return d.innerHTML; }631 /* pastille d'univers — même principe que celle des résultats de recherche */632 var UNIVERS = {633 'lou-ka': {label:'Lou·Ka', color:'#d9f26b'},634 'immo-ka': {label:'Immo·Ka', color:'#e23744'},635 'auto-ka': {label:'Auto·Ka', color:'#ff5a2a'},636 'fabri-ka': {label:'Fabri·Ka', color:'#C4532E'},637 'food-ka': {label:'Food·Ka', color:'#d9f26b'}638 };639 function card(it, i){640 var u = UNIVERS[it.app] || {label: esc(it.app || 'Ka'), color:'var(--ink-3)'};641 var img = it.image_url642 ? '<img loading="lazy" src="'+esc(it.image_url)+'" alt="" onerror="this.remove()">'643 : '';644 return '<a class="rcard" style="animation-delay:'+Math.min(i*20,360)+'ms" href="'+645 (it.url ? esc(it.url) : '#')+'" target="_blank" rel="noopener">'+646 '<div class="rimg"><span class="ph">♥</span>'+img+647 '<span class="rtag"><span class="dot" style="background:'+u.color+'"></span>'+u.label+'</span>'+648 '</div>'+649 '<div class="rbody"><div class="rtitle">'+esc(it.title)+'</div>'+650 (it.subtitle ? '<div class="rsub">'+esc(it.subtitle)+'</div>' : '')+651 (it.price_label ? '<div class="rprice">'+esc(it.price_label)+'</div>' : '')+652 '</div></a>';653 }654 fetch('/api/auth/me').then(function(r){return r.json()}).then(function(d){655 if(!d || !d.user) return;656 fetch('/api/favorites').then(function(r){ return r.ok ? r.json() : null; }).then(function(f){657 var favs = (f && f.favorites) || [];658 if(!favs.length) return;659 grid.innerHTML = favs.map(card).join('');660 sec.classList.add('show');661 }).catch(function(){});662 }).catch(function(){});663})();664</script>665</body>666</html>667"""668