SPB Git forge

spb/home-ka

Public
10commits 1branches 0releases
793.0 KBsize
maindefault branch
19 days agolast push
Python 49.6% TypeScript 25.5% CSS 24.1%

Frontend theme: red/white/blue US palette (Old Glory) instead of forest green — blue #1e4fd8 accent, red #b31942 brand chip/status/stripe, white paper

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Simon-Pierre Boucher committed 27 days ago (Aug 28, 2026) parent bb09ddb

4 changed files +35 −23

modified frontend/src/components/PropertyMap.tsx +1 −1
@@ -17,7 +17,7 @@ import { HOMEKA_APP_SOURCE } from "../kamaps/adapter";
17 17 import { MAPBOX_TOKEN } from "../kamaps/config";
18 18
19 19 /** Home-Ka signal green — same language as the brand accent. */
20 export const BUILDING_GREEN = "#0f7b4a";
20 +export const BUILDING_GREEN = "#1e4fd8";
21 21
22 22 export interface PropertyMapProps {
23 23 uid: string;
modified frontend/src/ka/ecosystem.json +3 −3
@@ -88,9 +88,9 @@
88 88 "id": "home-ka",
89 89 "wordmark": "Home·Ka",
90 90 "domain": "www.home-ka.com",
91 "accent": "#0f7b4a",
92 "accentSoft": "#dcefe5",
93 "accentDeep": "#0b5e38",
91 + "accent": "#1e4fd8",
92 + "accentSoft": "#e3eafc",
93 + "accentDeep": "#0a3161",
94 94 "onAccent": "#ffffff",
95 95 "tagline": "Every home for sale in America"
96 96 },
modified frontend/src/kamaps/theme.ts +3 −3
@@ -3,13 +3,13 @@
3 3 // Contact: contact@spboucher.ai
4 4 // Project: Groupe Ka / Ka Maps (Home-Ka integration)
5 5 // kamaps/theme.ts : Home-Ka Maps theme — forest-green / off-white / ink.
6 // Premium price pins: off-white with ink text; the GREEN #0f7b4a is reserved
6 +// Premium price pins: off-white with ink text; the GREEN #1e4fd8 is reserved
7 7 // for brand moments (selection, controls, highlights).
8 8 // -----------------------------------------------------------------------------
9 9 import type { KaMapTheme } from "@groupe-ka/ka-maps";
10 10
11 11 const INK = "#12181a";
12 const GREEN = "#0f7b4a";
12 +const GREEN = "#1e4fd8";
13 13 const OFFWHITE = "#fffdf8";
14 14 const WHITE = "#ffffff";
15 15
@@ -41,7 +41,7 @@ export const homeKaMapTheme: KaMapTheme = {
41 41 background: OFFWHITE,
42 42 text: INK,
43 43 border: GREEN,
44 valueText: "#0b5e38",
44 + valueText: "#0a3161",
45 45 valueHalo: "rgba(255, 253, 248, 0.92)",
46 46 },
47 47 supportsDark: false,
modified frontend/src/styles.css +28 −16
@@ -5,19 +5,31 @@
5 5 (ka/tokens.css, imported BEFORE this file in main.tsx).
6 6 · The base (paper/ink palette, type, grain, selection, focus, component
7 7 base) comes from ka/tokens.css — do NOT duplicate it here.
8 · ONLY the brand accent is overridden: Home-Ka FOREST GREEN.
8 + · ONLY the brand palette is overridden: Home-Ka RED / WHITE / BLUE
9 + (US flag — Old Glory Red #b31942, Old Glory Blue #0a3161).
9 10 ----------------------------------------------------------------------------- */
10 11 :root {
11 /* ---- Home-Ka FOREST GREEN accent (only override of ka/tokens.css) ---- */
12 --accent: #0f7b4a;
13 --accent-soft: #dcefe5;
14 --accent-deep: #0b5e38;
12 + /* ---- Home-Ka RED/WHITE/BLUE palette (only override of ka/tokens.css) ---- */
13 + --accent: #1e4fd8; /* interactive blue */
14 + --accent-soft: #e3eafc;
15 + --accent-deep: #0a3161; /* Old Glory Blue */
16 + --accent-red: #b31942; /* Old Glory Red — brand chip, statuses, stripe */
17 + --accent-red-soft: #f9e3e9;
15 18 --on-accent: #ffffff;
19 + --paper: #ffffff; /* pure white background */
16 20 /* legacy aliases — the CSS below uses --lime */
17 21 --lime: var(--accent);
18 22 --lime-soft: var(--accent-soft);
19 23 }
20 24
25 +/* US tricolor stripe under the sticky header */
26 +.header::after {
27 + content: ""; display: block; height: 3px;
28 + background: linear-gradient(90deg,
29 + var(--accent-red) 0 34%, #ffffff 34% 50%,
30 + var(--accent-deep) 50% 100%);
31 +}
32 +
21 33 /* Ancre sous le header collant (spécifique Immo-Ka) */
22 34 html { scroll-padding-top: 76px; }
23 35 h1, h2, h3, h4 { margin: 0; }
@@ -46,7 +58,7 @@ button { font-family: inherit; }
46 58 .header:has(.mobile-menu.open) { z-index: var(--z-modal, 900); }
47 59 .header-inner { display: flex; align-items: center; gap: 20px; height: 64px; }
48 60 .brand { font-family: var(--font-display); font-weight: 700; font-size: 26px; letter-spacing: -0.04em; display: flex; align-items: center; line-height: 1; }
49 .brand .ka { background: var(--ink); color: var(--lime); padding: 2px 7px 4px; border-radius: 6px; margin-left: 3px; transform: rotate(-2deg); transition: transform 0.2s ease; }
61 +.brand .ka { background: var(--accent-red); color: #ffffff; padding: 2px 7px 4px; border-radius: 6px; margin-left: 3px; transform: rotate(-2deg); transition: transform 0.2s ease; }
50 62 .brand:hover .ka { transform: rotate(0deg); }
51 63 .brand-tag { font-family: var(--font-mono); font-size: 10.5px; color: var(--ink-3); letter-spacing: 0.08em; text-transform: uppercase; margin-left: 12px; }
52 64 @media (max-width: 860px) { .brand-tag { display: none; } }
@@ -56,7 +68,7 @@ button { font-family: inherit; }
56 68 .nav a.active { background: var(--ink); color: var(--lime); }
57 69
58 70 /* ================= Ticker ================= */
59 .ticker { background: var(--ink); color: var(--lime); overflow: hidden; font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase; padding: 7px 0; white-space: nowrap; border-bottom: 1px solid rgba(15, 123, 74, 0.25); }
71 +.ticker { background: var(--ink); color: var(--lime); overflow: hidden; font-family: var(--font-mono); font-size: 11.5px; letter-spacing: 0.1em; text-transform: uppercase; padding: 7px 0; white-space: nowrap; border-bottom: 1px solid rgba(30, 79, 216, 0.25); }
60 72 .ticker-track { display: inline-flex; gap: 0; animation: ticker 48s linear infinite; will-change: transform; }
61 73 .ticker span { padding: 0 26px; position: relative; }
62 74 .ticker span::after { content: "◆"; position: absolute; right: -6px; opacity: 0.5; font-size: 8px; top: 3px; }
@@ -70,7 +82,7 @@ button { font-family: inherit; }
70 82 .hero::before {
71 83 content: ""; position: absolute; z-index: -1; top: -60px; right: -120px;
72 84 width: 580px; height: 460px; pointer-events: none;
73 background: radial-gradient(closest-side, rgba(15, 123, 74, 0.12), transparent 72%);
85 + background: radial-gradient(closest-side, rgba(30, 79, 216, 0.12), transparent 72%);
74 86 }
75 87 .hero::after {
76 88 content: ""; position: absolute; z-index: -1; inset: -20px -40px 0 0; pointer-events: none;
@@ -93,7 +105,7 @@ button { font-family: inherit; }
93 105 @media (hover: hover) { .stat-chip:hover { transform: translate(-1px, -1px); box-shadow: 4px 4px 0 rgba(26, 18, 20, 0.2); } }
94 106 .stat-chip b { color: var(--ink); font-weight: 700; font-variant-numeric: tabular-nums; }
95 107 .stat-chip .pulse { width: 8px; height: 8px; border-radius: 50%; background: var(--green); box-shadow: 0 0 0 4px var(--lime-soft); animation: pulse 2.4s ease infinite; }
96 @keyframes pulse { 50% { box-shadow: 0 0 0 7px rgba(15, 123, 74, 0.4); } }
108 +@keyframes pulse { 50% { box-shadow: 0 0 0 7px rgba(30, 79, 216, 0.4); } }
97 109
98 110 /* ================= Filter bar ================= */
99 111 .filterbar { background: var(--surface); border: 2px solid var(--ink); border-radius: 14px; box-shadow: var(--shadow-off-soft); padding: 14px; margin: 34px 0 6px; display: flex; flex-direction: column; gap: 0; min-width: 0; }
@@ -364,7 +376,7 @@ table.rooms tr:nth-child(even) td { background: var(--surface-2); }
364 376 .tile-v { font-family: var(--font-display); font-weight: 700; font-size: clamp(22px, 3vw, 32px); letter-spacing: -0.03em; line-height: 1.05; }
365 377 .tile-k { font-family: var(--font-mono); font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-3); margin-top: 6px; }
366 378 .hero-tile { background: var(--ink); color: var(--lime); border-color: var(--ink); }
367 .hero-tile .tile-k { color: rgba(15, 123, 74, 0.7); }
379 +.hero-tile .tile-k { color: rgba(30, 79, 216, 0.7); }
368 380 .viz-card { background: var(--surface); border: 1.5px solid var(--ink); border-radius: var(--r-card); box-shadow: var(--shadow-off-soft); padding: 26px 28px 20px; margin-bottom: 22px; min-width: 0; max-width: 100%; overflow-x: auto; }
369 381 /* mobile : une table large ne doit JAMAIS déborder la page (grid blowout) —
370 382 chaque bloc de la page Stats défile horizontalement en interne au besoin */
@@ -592,7 +604,7 @@ html:has(.mobile-menu.open) { overflow: hidden; }
592 604 .sheet-close { border: 1.5px solid var(--ink); background: var(--surface); border-radius: 50%; width: 36px; height: 36px; font-size: 15px; cursor: pointer; line-height: 1; }
593 605 .filterbar.open .sheet-apply { display: flex; width: 100%; min-height: 50px; position: sticky; bottom: 0; z-index: 1; box-shadow: 0 -14px 18px -12px rgba(16, 18, 16, 0.4), 5px 5px 0 var(--lime); }
594 606 .sheet-backdrop { display: block; position: fixed; inset: 0; z-index: 90; background: rgba(16, 18, 16, 0.45); backdrop-filter: blur(2px); }
595 .fab { display: flex; align-items: center; gap: 8px; position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(18px + env(safe-area-inset-bottom)); z-index: 80; background: var(--ink); color: var(--lime); border: 1.5px solid var(--ink); border-radius: 999px; padding: 13px 24px; font-family: var(--font-display); font-weight: 700; font-size: 15px; cursor: pointer; box-shadow: 0 8px 24px rgba(16, 18, 16, 0.35), 4px 4px 0 rgba(15, 123, 74, 0.55); }
607 + .fab { display: flex; align-items: center; gap: 8px; position: fixed; left: 50%; transform: translateX(-50%); bottom: calc(18px + env(safe-area-inset-bottom)); z-index: 80; background: var(--ink); color: var(--lime); border: 1.5px solid var(--ink); border-radius: 999px; padding: 13px 24px; font-family: var(--font-display); font-weight: 700; font-size: 15px; cursor: pointer; box-shadow: 0 8px 24px rgba(16, 18, 16, 0.35), 4px 4px 0 rgba(30, 79, 216, 0.55); }
596 608 .fab:active { transform: translateX(-50%) scale(0.97); }
597 609 .results-head { margin-top: 20px; }
598 610 .chips { margin-right: -16px; padding-right: 16px; }
@@ -702,7 +714,7 @@ html:has(.mobile-menu.open) { overflow: hidden; }
702 714 /* jauge Vrai-Prix : fourchette P10–P90 + marqueurs estimation / prix demandé */
703 715 .vp-gauge { margin-top: 10px; }
704 716 .vp-gauge-track { position: relative; height: 14px; border-radius: 999px; background: var(--surface); border: 1px solid var(--line-strong); overflow: hidden; }
705 .vp-gauge-band { position: absolute; inset: 3px 6%; background: linear-gradient(90deg, var(--lime-soft), rgba(15, 123, 74, 0.35), var(--lime-soft)); border-radius: 999px; }
717 +.vp-gauge-band { position: absolute; inset: 3px 6%; background: linear-gradient(90deg, var(--lime-soft), rgba(30, 79, 216, 0.35), var(--lime-soft)); border-radius: 999px; }
706 718 .vp-gauge-est { position: absolute; top: 0; bottom: 0; width: 4px; margin-left: -2px; background: var(--lime); border-radius: 2px; }
707 719 .vp-gauge-ask { position: absolute; top: 2px; bottom: 2px; width: 4px; margin-left: -2px; background: var(--ink); border-radius: 2px; }
708 720 .vp-gauge-ends { display: flex; justify-content: space-between; font-family: var(--font-mono); font-size: 10px; color: var(--ink-3); margin-top: 4px; }
@@ -799,7 +811,7 @@ html:has(.mobile-menu.open) { overflow: hidden; }
799 811 .pc-role-badge { align-self: flex-start; font-family: var(--font-mono); font-size: 9.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.1em; background: var(--accent); color: var(--on-accent); border-radius: 999px; padding: 2px 9px; }
800 812 .pc-holder-since { font-family: var(--font-mono); font-size: 10.5px; color: rgba(245, 243, 238, 0.5); letter-spacing: 0.06em; }
801 813 .pc-avatar { width: 52px; height: 52px; border-radius: 50%; border: 2px solid var(--accent); flex: none; object-fit: cover; }
802 .pc-strip { display: flex; align-items: flex-end; gap: 5px; margin: 0 -26px; padding: 9px 18px; background: rgba(15, 123, 74, 0.14); border-top: 1px solid rgba(15, 123, 74, 0.4); overflow: hidden; }
814 +.pc-strip { display: flex; align-items: flex-end; gap: 5px; margin: 0 -26px; padding: 9px 18px; background: rgba(30, 79, 216, 0.14); border-top: 1px solid rgba(30, 79, 216, 0.4); overflow: hidden; }
803 815 .pc-strip i { display: block; width: 3px; border-radius: 1px; background: var(--accent); opacity: 0.75; }
804 816 .pc-strip i:nth-child(3n) { height: 14px; opacity: 0.4; }
805 817 .pc-strip i:nth-child(3n+1) { height: 9px; }
@@ -887,7 +899,7 @@ html:has(.mobile-menu.open) { overflow: hidden; }
887 899 display: flex; flex-direction: column; align-items: center; justify-content: center;
888 900 gap: 9px; width: 100%; height: 100%; min-height: 120px;
889 901 background:
890 radial-gradient(circle at 78% 18%, rgba(15, 123, 74, 0.14), transparent 52%),
902 + radial-gradient(circle at 78% 18%, rgba(30, 79, 216, 0.14), transparent 52%),
891 903 repeating-linear-gradient(45deg, #f3ece9 0 14px, #f7f1ef 14px 28px);
892 904 color: var(--accent-deep);
893 905 }
@@ -933,7 +945,7 @@ html:has(.mobile-menu.open) { overflow: hidden; }
933 945 .q-crime-barre { flex: 1 1 auto; height: 10px; background: var(--surface-2, #f0ede8);
934 946 border-radius: 5px; overflow: hidden; }
935 947 .q-crime-barre i { display: block; height: 100%; border-radius: 5px;
936 background: var(--accent, #0f7b4a); opacity: 0.55; }
948 + background: var(--accent, #1e4fd8); opacity: 0.55; }
937 949 .q-crime-n { flex: 0 0 52px; text-align: right; font-weight: 600;
938 950 color: var(--ink, #222); white-space: nowrap; }
939 951 .q-crime-n small { font-weight: 400; color: var(--ink-3, #888); }
@@ -1792,7 +1804,7 @@ body.ka-map-mode .kaa-btn, body.ka-map-mode .kaa-hello { display: none !importan
1792 1804 font-family: var(--font-mono); font-size: 11px; font-weight: 700;
1793 1805 text-transform: uppercase; letter-spacing: 0.08em;
1794 1806 padding: 5px 10px; border-radius: 999px;
1795 background: var(--accent); color: var(--on-accent);
1807 + background: var(--accent-red); color: var(--on-accent);
1796 1808 }
1797 1809 .status-chip.st-pending { background: #b96a00; }
1798 1810 .status-chip.st-sold { background: var(--ink); color: var(--paper); }
1799 1811