{a.bioSnippet}
// SONARA — EsploraArtisti // Shared artist directory used by Artist / Producer / Manager Esplora. // Reuses the .prod-card visual language (same shell, different data). // Manager gets an extra "Invita nel roster" CTA when window.openInviteModal exists. const ArtIcons = window.SonaraIcons; const { useState: useStateArt } = React; /* ─── Data ───────────────────────────────────────────────────────── */ const ART_GENRES = ["Trap", "Drill", "Hip-Hop", "R&B", "Pop", "Indie", "Cantautorato", "Electronic", "Afro"]; const ART_CITIES = ["Milano", "Roma", "Napoli", "Torino", "Bologna", "Firenze", "Bari", "Palermo", "Verona", "Genova", "Catania", "Brescia"]; const ART_NAMES = [ "Aïda Low", "Theo Marini", "Simone Caruso", "Noah Miles", "Vale Frey", "Kai Russo", "Mia Bertolino", "Yari Khan", "Luca Bianchi", "Martina Rey", "Giada Verdi", "Edo Palma", "Kaya Low", "Nora Vento", "Lume", "Selva", "Otto Pace", "Cielo R.", "Vela", "Petra K.", "Olmo", "Riva G.", "Tess", "Magma", ]; const SIG_TITLES = [ "Senza Te", "Notte Lunga", "Marble", "Vento del Sud", "Aria di Marzo", "Bianco Sporco", "Caduta libera", "Mezzanotte", "Mira", "Asfalto", "Quartiere", "Resta qui", ]; const ART_LOOKING = [ ["manager", "Cerca manager"], ["featuring", "Aperto featuring"], ["producer", "Cerca producer"], ["mix", "Cerca mix/master"], ]; function artRand(seed) { let s = seed; return () => (s = (s * 9301 + 49297) % 233280) / 233280; } function makeArtists() { const r = artRand(31); return ART_NAMES.map((name, i) => { const verified = r() > 0.45; const active = r() > 0.30; const followers = Math.floor(180 + r() * 18000); const plays = Math.floor(2000 + r() * 120000); const collabs = Math.floor(0 + r() * 22); const rating = collabs > 0 ? Math.round((4.3 + r() * 0.7) * 10) / 10 : null; const ratings = collabs; const age = 16 + Math.floor(r() * 18); const looking = ART_LOOKING.filter(() => r() > 0.55).map(([id]) => id); if (looking.length === 0 && r() > 0.5) looking.push("manager"); const tracks = 2 + Math.floor(r() * 5); // 2-6 tracks return { id: i + 1, name, handle: "@" + name.toLowerCase().replace(/[^a-z0-9]/g, ""), init: name.split(" ").map(w => w[0]).join("").slice(0, 2).toUpperCase(), art: i % 6, cover: i % 6, city: ART_CITIES[i % ART_CITIES.length], age, genres: [ART_GENRES[i % ART_GENRES.length], ART_GENRES[(i + 4) % ART_GENRES.length]], verified, active, followers, plays, collabs, rating, ratings, tracks, looking, bioSnippet: [ "Voce graffiata, scrittura tagliente. Lavoro su singoli per la prima campagna seria.", "Cantautore alt-pop, EP in lavorazione. Cerco producer per beat melodici.", "R&B contemporaneo. Già un sync moda, sto chiudendo il primo album.", "Trap-drill di scuola romana. 200k+ stream cumulati sui due singoli.", "Indie con derive elettroniche. Headliner emergente per club 200–500.", "Folk acustico, voce cristallina. Live regolari nel circuito veneto.", ][i % 6], sigTitle: SIG_TITLES[i % SIG_TITLES.length], sigDuration: ["3:24", "2:58", "3:12", "2:42", "3:51", "3:08"][i % 6], peaks: Array.from({ length: 56 }, (_, k) => { const base = 0.32 + 0.48 * Math.abs(Math.sin(i * 1.1 + k * 0.31)); return Math.min(1, base + (r() - 0.5) * 0.25); }), }; }); } const ALL_ARTISTS = makeArtists(); /* ─── Filter Rail ─────────────────────────────────────────────────── */ function ArtistsFilterRail() { const [genre, setGenre] = useStateArt("Tutti"); const [lookingFilter, setLookingFilter] = useStateArt("any"); const FS = window.FilterSection; return ( ); } /* ─── Waveform ─────────────────────────────────────────────────────── */ function ArtMiniWave({ peaks, playing }) { return (
{a.bioSnippet}