SPB Git forge

spb/fabri-ka

Public

Agrégateur de produits québécois — www.fabri-ka.com

217commits 1branches 0releases
66.1 MBsize
maindefault branch
6 h agolast push
Python 38.4% HTML 30.3% TypeScript 17.2% CSS 11% JavaScript 3.2%

DA v3 catalogue editorial : display serif Fraunces (titres+prix), masthead et tab bar vert profond a lisere terracotta, cartes produits sans cadre (photo 10px + filets), sections a regles d encre, boutiques en index a filets, KPI stats en colonnes de chiffres

Simon-Pierre Boucher committed 1 mo ago (Aug 25, 2026) parent c101937

2 changed files +219 −1

modified frontend/index.html +1 −1
@@ -17,7 +17,7 @@
17 17 <link rel="preconnect" href="https://fonts.googleapis.com" />
18 18 <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
19 19 <link
20 − href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&display=swap"
20 + href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@400;500;600;700&family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500;600&family=Fraunces:ital,opsz,wght@0,9..144,400..700;1,9..144,400..700&display=swap"
21 21 rel="stylesheet"
22 22 />
23 23 <meta property="og:image" content="https://www.fabri-ka.com/og.png" />
modified frontend/src/styles.css +218 −0
@@ -4970,3 +4970,221 @@ a.card:active { border-color: var(--ink); }
4970 4970 font-size: max(16px, 1em) !important;
4971 4971 }
4972 4972 }
4973 +
4974 +/* ==========================================================================
4975 + DA v3 « catalogue éditorial » (2026-08-25) — dernière couche, prime sur
4976 + tout le reste. Personnalité Fabri-Ka : catalogue artisanal contemporain.
4977 + · Display serif Fraunces (titres, prix) — chaleur d'imprimé
4978 + · Masthead + tab bar VERT PROFOND, accents terracotta / ambre
4979 + · Cartes produits sans cadre : photo pleine + typo + filets
4980 + · Sections et panneaux à règles d'encre (fini les boîtes ombrées)
4981 + ========================================================================== */
4982 +
4983 +:root {
4984 + --font-serif: "Fraunces", Georgia, serif;
4985 + --mast-green: #123f2e; /* vert profond du masthead */
4986 + --mast-fg: #f5f3ee;
4987 + --mast-dim: rgba(245, 243, 238, 0.62);
4988 + --mast-line: rgba(245, 243, 238, 0.18);
4989 +}
4990 +
4991 +/* ---- titres : serif éditoriale (les h3 de cartes restent en texte) ------- */
4992 +.hero-title, .section-header h2, .page-header h1, .page-header h2,
4993 +.stats-hero-title, .pd-title-row h1, .page > h1,
4994 +.seo-page h1, .seo-page h2 {
4995 + font-family: var(--font-serif);
4996 + font-weight: 600;
4997 + letter-spacing: -0.02em;
4998 +}
4999 +.hero-title { line-height: 1.02; font-weight: 600; }
5000 +.hero-title em { font-style: italic; font-weight: 500; color: var(--accent); }
5001 +
5002 +/* ---- masthead vert profond ---------------------------------------------- */
5003 +.site-header {
5004 + background: var(--mast-green);
5005 + border-bottom: 3px solid var(--accent);
5006 +}
5007 +.logo { color: var(--mast-fg); }
5008 +.logo-dot { color: var(--amber); }
5009 +.logo-ka {
5010 + background: var(--amber);
5011 + color: var(--mast-green);
5012 +}
5013 +.site-nav a {
5014 + position: relative;
5015 + border: 0; border-radius: 0;
5016 + font-family: var(--font-mono);
5017 + font-size: 11.5px; font-weight: 600;
5018 + text-transform: uppercase; letter-spacing: 0.09em;
5019 + color: var(--mast-dim);
5020 + padding: 0.55rem 0.75rem;
5021 +}
5022 +.site-nav a::after {
5023 + content: ""; position: absolute; left: 0.75rem; right: 0.75rem; bottom: 4px;
5024 + height: 2px; background: var(--amber);
5025 + transform: scaleX(0); transform-origin: left; transition: transform 0.18s ease;
5026 +}
5027 +@media (hover: hover) {
5028 + .site-nav a:hover { color: var(--mast-fg); background: transparent; border-color: transparent; text-decoration: none; }
5029 + .site-nav a:hover::after { transform: scaleX(1); }
5030 +}
5031 +.site-nav a.active,
5032 +.site-nav a[aria-current='page'] {
5033 + background: transparent; color: var(--mast-fg);
5034 +}
5035 +.site-nav a.active::after,
5036 +.site-nav a[aria-current='page']::after { transform: scaleX(1); }
5037 +/* recherche d'en-tête sur fond vert */
5038 +.site-header .searchbar-field {
5039 + border-color: var(--mast-line);
5040 + background: rgba(245, 243, 238, 0.1);
5041 +}
5042 +.site-header .searchbar-field input {
5043 + background: transparent; border: 0; color: var(--mast-fg);
5044 +}
5045 +.site-header .searchbar-field input::placeholder { color: var(--mast-dim); }
5046 +.site-header .searchbar-icon { color: var(--mast-dim); }
5047 +.site-header .searchbar-kbd {
5048 + background: transparent; border-color: var(--mast-line); color: var(--mast-dim);
5049 +}
5050 +.site-header .searchbar button[type='submit'] {
5051 + background: var(--amber); color: var(--mast-green);
5052 + border-color: transparent; box-shadow: none;
5053 +}
5054 +.site-header .gk-badge {
5055 + background: transparent; border-color: var(--mast-line); color: var(--mast-dim);
5056 +}
5057 +.site-header .gk-badge b { color: var(--mast-fg); }
5058 +.signup-link { color: var(--mast-dim); }
5059 +@media (hover: hover) { .signup-link:hover { color: var(--mast-fg); } }
5060 +
5061 +/* ---- tab bar mobile assortie au masthead --------------------------------- */
5062 +.bottom-nav {
5063 + background: var(--mast-green);
5064 + border-top: 0;
5065 + box-shadow: 0 -1px 0 rgba(245, 243, 238, 0.12);
5066 +}
5067 +.bottom-nav-item { color: var(--mast-dim); }
5068 +.bottom-nav-item.active { color: var(--amber); }
5069 +@media (hover: hover) { .bottom-nav-item:hover { color: var(--mast-fg); } }
5070 +
5071 +/* ---- héro : filet fort + chiffres serif ---------------------------------- */
5072 +.hero-stats { border-top: 2.5px solid var(--ink); padding-top: 1.1rem; gap: 0 2.25rem; }
5073 +.stat { padding-top: 0.15rem; }
5074 +.stat + .stat { border-left: 1px solid var(--line); padding-left: 2rem; }
5075 +.stat-number { font-family: var(--font-serif); font-weight: 600; }
5076 +.stat-label { font-family: var(--font-mono); letter-spacing: 0.12em; font-weight: 600; }
5077 +
5078 +/* ---- entêtes de section : règle d'encre, plus de barre latérale ---------- */
5079 +.section-header {
5080 + border-top: 2px solid var(--ink);
5081 + padding-top: 0.7rem;
5082 + margin-top: 1.6rem;
5083 +}
5084 +.section-header h2 { padding-left: 0; font-size: clamp(1.45rem, 3.8vw, 1.9rem); }
5085 +.section-header h2::before { display: none; }
5086 +.section-see-all {
5087 + font-family: var(--font-mono); font-size: 11px; font-weight: 600;
5088 + text-transform: uppercase; letter-spacing: 0.1em; color: var(--ink-2);
5089 + text-decoration: underline; text-underline-offset: 4px;
5090 + text-decoration-color: var(--line-strong);
5091 +}
5092 +@media (hover: hover) {
5093 + .section-see-all:hover { color: var(--accent-deep); text-decoration-color: var(--accent); }
5094 +}
5095 +
5096 +/* ---- cartes produits sans cadre ------------------------------------------ */
5097 +.card {
5098 + background: transparent;
5099 + border: 0; border-radius: 0;
5100 + min-width: 0;
5101 +}
5102 +@media (hover: hover) {
5103 + a.card:hover {
5104 + border-color: transparent;
5105 + box-shadow: none;
5106 + transform: none;
5107 + }
5108 +}
5109 +a.card:active { border-color: transparent; }
5110 +/* overflow:hidden conservé : il neutralise la taille min-content des images
5111 + dans les rails flex (une carte sans lui s'élargit à la largeur intrinsèque
5112 + de sa photo) ; rien ne déborde de la carte de toute façon. */
5113 +.product-card { overflow: hidden; }
5114 +.rail-item { min-width: 0; }
5115 +.product-card-media {
5116 + border-radius: 10px;
5117 +}
5118 +.product-card-media::after {
5119 + content: ""; position: absolute; inset: 0; border-radius: 10px;
5120 + box-shadow: inset 0 0 0 1px rgba(20, 24, 20, 0.1); pointer-events: none;
5121 +}
5122 +.product-card-media img { transition: transform 0.4s cubic-bezier(0.2, 0.6, 0.2, 1); }
5123 +.product-card-body { padding: 0.6rem 0.1rem 0.15rem; }
5124 +@media (min-width: 640px) { .product-card-body { padding: 0.7rem 0.1rem 0.2rem; } }
5125 +.product-card-title {
5126 + font-size: 0.88rem; font-weight: 500; color: var(--ink);
5127 + text-decoration: underline transparent; text-decoration-thickness: 1.5px;
5128 + text-underline-offset: 3px; transition: text-decoration-color 0.18s ease;
5129 +}
5130 +@media (hover: hover) { a.card:hover .product-card-title { text-decoration-color: var(--accent); } }
5131 +.price-chip {
5132 + font-family: var(--font-serif); font-weight: 600;
5133 + font-size: 1.18rem; color: var(--accent-deep); letter-spacing: -0.01em;
5134 +}
5135 +.price-chip-lg { font-size: 2rem; }
5136 +.price-chip-muted { font-family: var(--font-body); font-size: 0.85rem; }
5137 +.product-card-store {
5138 + font-family: var(--font-mono); font-size: 0.62rem; letter-spacing: 0.08em;
5139 + border-top: 1px solid var(--line);
5140 + padding-top: 0.5rem; margin-top: auto;
5141 +}
5142 +.sale-badge {
5143 + transform: rotate(-3deg);
5144 + box-shadow: 2px 2px 0 rgba(20, 24, 20, 0.22);
5145 + border: 0;
5146 +}
5147 +.product-grid { gap: 1.4rem 0.9rem; }
5148 +@media (min-width: 640px) { .product-grid { gap: 1.7rem 1.15rem; } }
5149 +
5150 +/* ---- cartes boutiques : index éditorial à filets -------------------------- */
5151 +.store-card {
5152 + background: transparent; border: 0; border-radius: 0;
5153 + border-top: 1.5px solid var(--ink);
5154 + padding: 0.85rem 0 1.1rem;
5155 +}
5156 +@media (hover: hover) {
5157 + a.store-card:hover { box-shadow: none; transform: none; }
5158 + a.store-card:hover .store-card-name { text-decoration: underline; text-decoration-color: var(--accent); text-decoration-thickness: 2px; text-underline-offset: 3px; }
5159 +}
5160 +.store-card-name { font-family: var(--font-serif); font-weight: 600; }
5161 +.store-grid { gap: 0 1.8rem; }
5162 +
5163 +/* ---- panneau de filtres (catalogue) : colonne à règles -------------------- */
5164 +.filters {
5165 + background: transparent; border: 0; border-radius: 0; box-shadow: none;
5166 + border-top: 2.5px solid var(--ink);
5167 + padding: 0.9rem 0 0;
5168 +}
5169 +.filters-title { font-family: var(--font-mono); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.14em; }
5170 +.filter-group { border-bottom: 1px solid var(--line); padding-bottom: 0.9rem; }
5171 +.filter-label { color: var(--ink-3); }
5172 +
5173 +/* ---- KPI stats : colonnes de chiffres à filet ----------------------------- */
5174 +.stats-kpi {
5175 + background: transparent; border: 0; border-radius: 0;
5176 + border-top: 2.5px solid var(--ink);
5177 + padding: 0.7rem 0 0.9rem;
5178 +}
5179 +.stats-kpi-value { font-family: var(--font-serif); font-weight: 600; }
5180 +.stats-kpi-label { font-family: var(--font-mono); letter-spacing: 0.11em; }
5181 +.stats-kpis { gap: 0 1.3rem; row-gap: 0.4rem; }
5182 +
5183 +/* ---- skeletons sans cadre -------------------------------------------------- */
5184 +.product-card-skeleton { border: 0; border-radius: 10px; }
5185 +
5186 +/* ---- fiche produit : prix serif géant ------------------------------------- */
5187 +.pd-title-row h1 { font-weight: 600; }
5188 +
5189 +/* ---- filet éditorial générique pour les blocs SSR -------------------------- */
5190 +.seo-card { border-radius: 10px; }
4973 5191