// app-flyer.jsx — Renderer de flyers NOMADE (post + story) // ───────────────────────────────────────────────────────────────────────── // SYSTÈME DE COULEUR « DÉSERT » — charbon chaud + neutres sable + UN accent // terracotta employé avec parcimonie (1 trait / 1 pastille / 1 CTA par visuel). // Aucune valeur dorée. Hiérarchie portée par les neutres, le contraste, la typo. // ───────────────────────────────────────────────────────────────────────── const N = { // — Surfaces (dark mode chaud) — ink: '#0C0A08', // charbon de base, légèrement chaud inkDeep: '#070605', // le plus sombre inkRaise: '#16120D', // surface relevée (cartes / pochettes) // — Neutres chauds (portent la hiérarchie) — bone: '#ECE3D4', // blanc cassé / os — texte principal sand: '#CFBFA4', // sable chaud — emphase secondaire + voix serif taupe: '#9A8B73', // grège — texte secondaire / labels stone: '#5E5547', // pierre — bordures / tertiaire // — Accent terracotta (PONCTUATION uniquement) — clay: '#C16A43', // terracotta / sienne brûlée — mat, organique clayDeep: '#8E4527', // brique profonde claySoft: '#D58A62', // argile claire (dégradés CTA) // — Alias rétro-compat (mêmes clés que l'ancien système) — white: '#ECE3D4', whiteSoft: 'rgba(236,227,212,0.72)', bronze: '#C16A43', // ⟵ ré-aiguillé sur clay pour compat ; usage restreint // — Hairlines / voiles réutilisables — line: 'rgba(236,227,212,0.12)', // filet neutre standard lineSoft: 'rgba(236,227,212,0.06)', // filet très discret clayLine: 'rgba(193,106,67,0.38)', // filet accent (rare) // — Typo — display: '"Space Grotesk", system-ui, sans-serif', serif: '"Cormorant Garamond", Georgia, serif', body: '"Inter", system-ui, sans-serif', mono: '"JetBrains Mono", ui-monospace, monospace' }; function Grain() { return
; } // Logo blanc, sans halo doré — une ombre douce et neutre pour le détacher. function Logo({ height }) { return ; } function BrandRow({ size = 1, pill, accentDot = false }) { return (
NOMADE
{accentDot && } {pill}
); } // Chips neutres — filet fin grège, texte sable. Aucun remplissage coloré. function Chips({ chips, size = 1 }) { return (
{chips.filter(Boolean).map((c, i) =>
{c}
)}
); } // ── POST 1080×1350 ───────────────────────────────────────────────────────── function PostFlyer({ data }) { return (
{data.photoUrl ?
:
— Photo —
}
{data.kicker}
{data.headline}
{data.subtitle}
{data.composer &&
{data.composer}
}
{data.bottomCopy}
nomadeclan.com
); } // ── STORY 1080×1920 ──────────────────────────────────────────────────────── function StoryFlyer({ data }) { return (
{data.photoUrl ? :
— Photo —
}
{data.kicker}
{data.storyTop}
{data.storyBottom}
{data.composer &&
{data.composer}
}
{/* CTA — l'unique bloc accent terracotta de la story */}
{data.ctaLabel}
{data.ctaUrl}
); } window.N = N; window.PostFlyer = PostFlyer; window.StoryFlyer = StoryFlyer; // ═══════════════════════════════════════════════════════════════════════════ // CERTIF LAYOUT — Disque d'Or / Platine / Diamant (visuels SNEP officiels) // Les disques SNEP ne sont JAMAIS recolorés : ce sont des visuels officiels. // ═══════════════════════════════════════════════════════════════════════════ const CERTIF_TYPES = { OR: { label: "DISQUE D'OR", singleLabel: "SINGLE D'OR", file: 'assets/snep-or.png' }, PLATINE: { label: 'DISQUE DE PLATINE', singleLabel: 'SINGLE DE PLATINE', file: 'assets/snep-platine.png' }, '2PLATINE': { label: 'DOUBLE DISQUE DE PLATINE', singleLabel: null, file: 'assets/snep-2platine.png' }, '3PLATINE': { label: 'TRIPLE DISQUE DE PLATINE', singleLabel: null, file: 'assets/snep-3platine.png' }, DIAMANT: { label: 'DISQUE DE DIAMANT', singleLabel: 'SINGLE DE DIAMANT', file: 'assets/snep-diamant.png' }, '2DIAMANT': { label: 'DOUBLE DISQUE DE DIAMANT', singleLabel: 'DOUBLE DIAMANT', file: 'assets/snep-2diamant.png' } }; // Ombre neutre + halo très discret : le disque garde ses couleurs officielles. function CertifSeal({ type = 'OR', size = 300 }) { const cfg = CERTIF_TYPES[type] || CERTIF_TYPES.OR; return ( {cfg.label); } // ── CERTIF POST 1080×1350 ─────────────────────────────────────────────────── function CertifPost({ data }) { return (
{/* Top brand row */}
NOMADE
{data.pill || 'CERTIFIÉ'}
{/* Kicker */}
{data.kicker || '/ CERTIFICATION'}
{/* Artist name */}
12 ? 84 : 110, lineHeight: 0.95, letterSpacing: '-0.03em', textTransform: 'uppercase', color: N.bone }}>{data.artistName || 'ARTISTE'}
{/* Album name */}
{data.albumName || 'Titre'}
{/* Cert info */} {(() => { const cfg = CERTIF_TYPES[data.certifType] || CERTIF_TYPES.OR; const isSingle = data.certifFormat === 'single'; const label = isSingle ? cfg.singleLabel || cfg.label : cfg.label || cfg.singleLabel; const unit = isSingle ? 'streams' : 'ventes'; return (
{label}{data.salesNumber ? ` · +${data.salesNumber} ${unit}` : ''}
); })()} {/* Hero cover */}
{data.photoUrl ? :
— Pochette —
}
{/* Foil seal */} {(() => { const isWide = ['2PLATINE', '3PLATINE', '2DIAMANT'].includes(data.certifType); return (
); })()} {/* Bottom signature */}
{data.bottomCopy || "Encore une trace qui passe la barre.\nMerci à l'équipe + l'artiste."}
nomadeclan.com
); } // ── CERTIF STORY 1080×1920 ────────────────────────────────────────────────── function CertifStory({ data }) { return (
NOMADE
{data.pill || 'CERTIFIÉ'}
{data.kicker || '/ CERTIFICATION'}
10 ? 120 : 150, lineHeight: 0.95, letterSpacing: '-0.03em', textTransform: 'uppercase', color: N.bone }}>{data.artistName || 'ARTISTE'}
{data.albumName || 'Titre'}
{(() => { const cfg = CERTIF_TYPES[data.certifType] || CERTIF_TYPES.OR; const isSingle = data.certifFormat === 'single'; const label = isSingle ? cfg.singleLabel || cfg.label : cfg.label || cfg.singleLabel; const unit = isSingle ? 'streams' : 'ventes'; return (
{label}{data.salesNumber ? ` · +${data.salesNumber} ${unit}` : ''}
); })()}
{data.photoUrl ? :
— Pochette —
}
{(() => { const isWide = ['2PLATINE', '3PLATINE', '2DIAMANT'].includes(data.certifType); return (
); })()} {/* CTA — bloc accent terracotta unique */}
{data.ctaLabel || '/ Vos projets chez NOMADE'}
{data.ctaUrl || 'nomadeclan.com'}
); } window.CertifPost = CertifPost; window.CertifStory = CertifStory; window.CertifSeal = CertifSeal; // ═══════════════════════════════════════════════════════════════════════════ // SESSION layout — "EN STUDIO / live rec" // ═══════════════════════════════════════════════════════════════════════════ function SessionPost({ data }) { return (
{data.photoUrl ? :
}
{/* Filet accent fin en haut (le seul trait coloré) */}
NOMADE
{/* Pastille live REC — pastille accent unique */}
{data.pill || 'EN STUDIO'}
{data.kicker || '/ SESSION · 01'} REC {data.sessionDate || "AUJOURD'HUI"}
EN SESSION
{data.artistName || data.headline || 'ARTISTE'}
{data.subtitle || 'au studio cette nuit.'}
{(data.chips || []).filter(Boolean).map((c, i) =>
{c}
)}
{data.bottomCopy || 'Une nuit, un son, la trace.'}
nomadeclan.com
); } function SessionStory({ data }) { return (
{data.photoUrl ? :
}
NOMADE
{data.pill || 'EN STUDIO'}
{data.kicker || '/ SESSION · 01'} REC {data.sessionDate || 'NOW'}
EN SESSION
{data.kicker || '/ LIVE NOW'}
{data.artistName || data.headline || 'ARTISTE'}
{data.subtitle || 'au studio cette nuit.'}
{(data.chips || []).filter(Boolean).map((c, i) =>
{c}
)}
); } window.SessionPost = SessionPost; window.SessionStory = SessionStory; // ═══════════════════════════════════════════════════════════════════════════ // PROMO layout — carte typographique (offre). Fond charbon, accent terracotta. // ═══════════════════════════════════════════════════════════════════════════ function PromoPost({ data }) { return (
NOMADE
{data.pill || 'OFFRE'}
{data.kicker || '/ OFFRE LIMITÉE'}
{data.headline || '-30%'}
{data.subtitle || 'sur toutes les sessions studio'}
{data.promoDate || 'Jusqu\'au 30.06.2026'}
{(data.chips || []).filter(Boolean).map((c, i) =>
{c}
)}
{/* Code promo — bloc accent terracotta unique */}
— Code promo
{data.promoCode || 'NOMADE-30'}
Réserver →
{data.bottomCopy || 'Premier arrivé, premier servi.\nPlaces limitées.'}
nomadeclan.com
); } function PromoStory({ data }) { return (
NOMADE
{data.pill || 'OFFRE'}
{data.kicker || '/ OFFRE LIMITÉE'}
{data.headline || '-30%'}
{data.subtitle || 'sur toutes les sessions studio'}
{data.promoDate || 'Jusqu\'au 30.06.2026'}
{(data.chips || []).filter(Boolean).map((c, i) =>
{c}
)}
— Code promo
{data.promoCode || 'NOMADE-30'}
Réserver une session →
nomadeclan.com
); } window.PromoPost = PromoPost; window.PromoStory = PromoStory; window.CERTIF_TYPES = CERTIF_TYPES; // CertifBackdrop — fond utilisé par CertifPost / CertifStory. // Charbon chaud + sillons de vinyle en neutre discret + halo sable très léger. function CertifBackdrop({ children }) { const Disc = ({ cx, cy, r, opacity = 1 }) => { const grooves = []; for (let gr = 30; gr <= r; gr += 8) grooves.push(gr); return ( {grooves.map((gr, i) => )} ); }; return ( <>
{children} ); }