// brand.jsx — OKxProject / InstaSatış brand tokens + shared primitives // Expose to window at bottom so other babel files can read them. const I18N = { tr: { nav_explore: 'Keşfet', nav_how: 'Nasıl çalışır', nav_about: 'Hakkımızda', nav_help: 'Yardım', nav_sell: 'İlan Ver', hero_kicker: 'Aged + Konsept Instagram Pazaryeri', hero_title: 'Doğru hesap, doğru fiyat.', hero_sub: 'Yaşlandırılmış ve nişe özel Instagram hesaplarını emin ellerde satın al. SSL koruması, iade garantisi.', hero_cta: 'İlanları Gör', hero_cta2: 'İletişime Geç', stat_listings: 'aktif ilan', stat_sold: 'teslim edilen hesap', stat_uptime: 'güvenli işlem', filter_title: 'Filtrele', filter_age: 'Hesap Yaşı', filter_niche: 'Kategori', filter_followers: 'Takipçi', filter_price: 'Fiyat', filter_reset: 'Sıfırla', filter_apply: 'Uygula', age_any: 'Tümü', age_1: '1+ Yıl', age_3: '3+ Yıl', age_5: '5+ Yıl', sort_new: 'En Yeni', sort_price_low: 'Fiyat ↑', sort_price_high: 'Fiyat ↓', sort_followers: 'Takipçi ↓', sort_age: 'Yaş ↓', card_followers: 'takipçi', card_age: 'yaş', card_age_years: 'yıl', card_age_months: 'ay', card_buy: 'Şimdi Al', card_view: 'İncele', card_saved: 'Kaydedildi', card_save: 'Kaydet', detail_overview: 'Genel Bakış', detail_metrics: 'Metrikler', detail_content: 'İçerik Örnekleri', detail_seller: 'Satıcı', detail_buy_now: 'Şimdi Al', detail_add_fav: 'Favorilere Ekle', detail_report: 'Bildir', trust_ssl: 'SSL Koruması', trust_card: 'Kredi Kartı', trust_iban: 'IBAN / Havale', trust_refund: '7 gün iade', trust_verified: 'Doğrulanmış', pay_title: 'Ödeme', pay_sub: 'İki güvenli yöntemden birini seç.', pay_method_card: 'Kredi / Banka Kartı', pay_method_iban: 'IBAN · Havale/EFT', pay_card_number: 'Kart Numarası', pay_card_name: 'Kart Üzerindeki İsim', pay_card_exp: 'Son Kullanma', pay_card_cvv: 'CVV', pay_iban_owner: 'Hesap Sahibi', pay_iban_num: 'IBAN', pay_iban_note: 'Havale açıklamasına sipariş numaranı yaz. Onay 10 dk içinde gelir.', pay_order_summary: 'Sipariş Özeti', pay_subtotal: 'Ara Toplam', pay_fee: 'Hizmet Bedeli (%2)', pay_total: 'Toplam', pay_cta_card: 'Kartla Öde', pay_cta_iban: 'IBAN Bilgilerini Göster', pay_installment: 'Taksit seçenekleri', pay_3d: '3D Secure ile korunur', auth_welcome: 'Hoş geldin', auth_sub: 'Pazaryerine giriş yap veya hesap oluştur.', auth_email: 'E-posta', auth_pass: 'Şifre', auth_login: 'Giriş Yap', auth_signup: 'Kayıt Ol', auth_or: 'ya da', auth_google: 'Google ile devam et', auth_tos: 'Devam ederek koşulları kabul edersin', auth_tab_login: 'Giriş', auth_tab_signup: 'Kayıt', dash_hello: 'Merhaba', dash_fav: 'Favorilerim', dash_watch: 'Takibimdeki', dash_offers: 'Tekliflerim', dash_purchases: 'Satın Aldıklarım', empty_fav: 'Henüz favori eklemedin.', price_ttl: 'Fiyat', niche_fashion: 'Moda', niche_food: 'Yemek', niche_travel: 'Seyahat', niche_meme: 'Mizah', niche_sport: 'Spor', niche_tech: 'Teknoloji', niche_art: 'Sanat', niche_lifestyle: 'Yaşam', niche_music: 'Müzik', niche_beauty: 'Güzellik', niche_fitness: 'Fitness', niche_auto: 'Otomobil', new_badge: 'YENİ', hot_badge: 'POPÜLER', rare_badge: 'NADİR', search_ph: 'Kategori, niş veya @kullaniciadi ara…', }, en: { nav_explore: 'Explore', nav_how: 'How it works', nav_about: 'About', nav_help: 'Help', nav_sell: 'Sell Account', hero_kicker: 'Aged + Niche Instagram Marketplace', hero_title: 'The right account, at the right price.', hero_sub: 'Buy aged and niche Instagram accounts in trusted hands. SSL protection, refund policy.', hero_cta: 'See Listings', hero_cta2: 'Contact Us', stat_listings: 'active listings', stat_sold: 'accounts delivered', stat_uptime: 'safe transactions', filter_title: 'Filter', filter_age: 'Account Age', filter_niche: 'Niche', filter_followers: 'Followers', filter_price: 'Price', filter_reset: 'Reset', filter_apply: 'Apply', age_any: 'Any', age_1: '1+ Year', age_3: '3+ Years', age_5: '5+ Years', sort_new: 'Newest', sort_price_low: 'Price ↑', sort_price_high: 'Price ↓', sort_followers: 'Followers ↓', sort_age: 'Age ↓', card_followers: 'followers', card_age: 'age', card_age_years: 'yrs', card_age_months: 'mo', card_buy: 'Buy Now', card_view: 'View', card_saved: 'Saved', card_save: 'Save', detail_overview: 'Overview', detail_metrics: 'Metrics', detail_content: 'Content Samples', detail_seller: 'Seller', detail_buy_now: 'Buy Now', detail_add_fav: 'Add to favorites', detail_report: 'Report', trust_ssl: 'SSL Protected', trust_card: 'Credit Card', trust_iban: 'IBAN · Wire', trust_refund: '7-day refund', trust_verified: 'Verified', pay_title: 'Checkout', pay_sub: 'Choose one of two secure methods.', pay_method_card: 'Credit / Debit Card', pay_method_iban: 'IBAN · Wire Transfer', pay_card_number: 'Card Number', pay_card_name: 'Name on Card', pay_card_exp: 'Expiry', pay_card_cvv: 'CVV', pay_iban_owner: 'Account Owner', pay_iban_num: 'IBAN', pay_iban_note: 'Write your order ID in the transfer note. Confirmed in ~10 min.', pay_order_summary: 'Order Summary', pay_subtotal: 'Subtotal', pay_fee: 'Service Fee (2%)', pay_total: 'Total', pay_cta_card: 'Pay by Card', pay_cta_iban: 'Show IBAN Details', pay_installment: 'Installment options', pay_3d: 'Protected by 3D Secure', escrow_word: 'Escrow', auth_welcome: 'Welcome', auth_sub: 'Sign in to the marketplace or create an account.', auth_email: 'Email', auth_pass: 'Password', auth_login: 'Log In', auth_signup: 'Sign Up', auth_or: 'or', auth_google: 'Continue with Google', auth_tos: 'By continuing you accept the terms', auth_tab_login: 'Login', auth_tab_signup: 'Signup', dash_hello: 'Hello', dash_fav: 'Favorites', dash_watch: 'Watching', dash_offers: 'My Offers', dash_purchases: 'Purchases', empty_fav: 'No favorites yet.', price_ttl: 'Price', niche_fashion: 'Fashion', niche_food: 'Food', niche_travel: 'Travel', niche_meme: 'Humor', niche_sport: 'Sport', niche_tech: 'Tech', niche_art: 'Art', niche_lifestyle: 'Lifestyle', niche_music: 'Music', niche_beauty: 'Beauty', niche_fitness: 'Fitness', niche_auto: 'Auto', new_badge: 'NEW', hot_badge: 'HOT', rare_badge: 'RARE', search_ph: 'Search by niche, category or @handle…', }, }; // Color palettes — each palette defines the gradient accent stops + neutrals // Work in oklch for harmony. Keep chroma roughly matched across hues. const PALETTES = { sunset: { name: 'Sunset', // warm coral → magenta → violet — this is the default, instagram-adjacent g1: 'oklch(0.74 0.19 35)', // coral g2: 'oklch(0.66 0.25 350)', // pink-magenta g3: 'oklch(0.58 0.22 300)', // violet accent: 'oklch(0.66 0.22 15)', accentInk: '#ffffff', }, citrus: { name: 'Citrus', g1: 'oklch(0.86 0.18 95)', // lemon g2: 'oklch(0.75 0.22 55)', // orange g3: 'oklch(0.65 0.22 25)', // red accent: 'oklch(0.70 0.22 45)', accentInk: '#1a1308', }, ocean: { name: 'Ocean', g1: 'oklch(0.78 0.15 210)', g2: 'oklch(0.64 0.18 245)', g3: 'oklch(0.52 0.22 285)', accent: 'oklch(0.62 0.20 240)', accentInk: '#ffffff', }, matcha: { name: 'Matcha', g1: 'oklch(0.85 0.14 120)', g2: 'oklch(0.70 0.18 155)', g3: 'oklch(0.55 0.15 185)', accent: 'oklch(0.62 0.16 160)', accentInk: '#06120c', }, }; // Derived CSS variable map for a theme: dark flag + palette + density function themeVars({ dark, palette, density }) { const p = PALETTES[palette] || PALETTES.sunset; const base = dark ? { '--bg': 'oklch(0.16 0.01 280)', '--bg-2': 'oklch(0.20 0.015 280)', '--bg-3': 'oklch(0.24 0.018 280)', '--ink': 'oklch(0.97 0.005 280)', '--ink-2': 'oklch(0.82 0.01 280)', '--ink-3': 'oklch(0.62 0.01 280)', '--line': 'oklch(0.32 0.01 280 / 0.7)', '--line-2': 'oklch(0.28 0.01 280 / 0.5)', '--card': 'oklch(0.20 0.015 280)', '--card-2': 'oklch(0.24 0.018 280)', '--chip': 'oklch(0.26 0.02 280)', '--hover': 'oklch(0.26 0.02 280)', '--success': 'oklch(0.75 0.17 155)', '--warn': 'oklch(0.78 0.17 70)', '--danger': 'oklch(0.68 0.22 25)', } : { '--bg': 'oklch(0.99 0.003 80)', '--bg-2': 'oklch(0.97 0.004 80)', '--bg-3': 'oklch(0.94 0.006 80)', '--ink': 'oklch(0.18 0.01 280)', '--ink-2': 'oklch(0.38 0.01 280)', '--ink-3': 'oklch(0.55 0.01 280)', '--line': 'oklch(0.90 0.005 280)', '--line-2': 'oklch(0.94 0.004 280)', '--card': '#ffffff', '--card-2': 'oklch(0.98 0.003 80)', '--chip': 'oklch(0.96 0.005 80)', '--hover': 'oklch(0.96 0.005 80)', '--success': 'oklch(0.55 0.16 155)', '--warn': 'oklch(0.65 0.18 70)', '--danger': 'oklch(0.58 0.22 25)', }; const d = density === 'compact' ? { '--gap': '10px', '--card-pad': '14px', '--row-h': '36px' } : density === 'comfy' ? { '--gap': '20px', '--card-pad': '22px', '--row-h': '44px' } : { '--gap': '14px', '--card-pad': '18px', '--row-h': '40px' }; return { ...base, ...d, '--g1': p.g1, '--g2': p.g2, '--g3': p.g3, '--accent': p.accent, '--accent-ink': p.accentInk, '--grad': `linear-gradient(135deg, ${p.g1} 0%, ${p.g2} 50%, ${p.g3} 100%)`, '--grad-soft': `linear-gradient(135deg, ${p.g1} 0%, ${p.g2} 100%)`, '--paletteName': p.name, }; } // ───────────────────────────────────────────────────────────── // Logo — OKxProject's InstaSatış wordmark. Original geometric mark: // a stacked "OK" monogram inside a rounded squircle with a small node // in the bottom-right representing "x" / transaction. Not a copy of // any existing logo. // ───────────────────────────────────────────────────────────── function Logo({ size = 32, showWord = true, wordColor = 'currentColor' }) { return (
is
{showWord && (
instasatış
)}
); } // ───────────────────────────────────────────────────────────── // Icons — small set, stroke-based // ───────────────────────────────────────────────────────────── function Icon({ name, size = 18, color = 'currentColor', strokeWidth = 1.75 }) { const s = size; const common = { width: s, height: s, viewBox: '0 0 24 24', fill: 'none', stroke: color, strokeWidth, strokeLinecap: 'round', strokeLinejoin: 'round' }; switch (name) { case 'search': return (); case 'heart': return (); case 'heart-fill': return (); case 'shield': return (); case 'bolt': return (); case 'users': return (); case 'calendar': return (); case 'tag': return (); case 'check': return (); case 'lock': return (); case 'mail': return (); case 'sparkle': return (); case 'flame': return (); case 'verified': return (); case 'chevron-right': return (); case 'chevron-left': return (); case 'chevron-down': return (); case 'chevron-up': return (); case 'info': return (); case 'arrow-right': return (); case 'filter': return (); case 'grid': return (); case 'globe': return (); case 'bell': return (); case 'x': return (); case 'plus': return (); case 'menu': return (); case 'star': return (); case 'upload': return (); case 'eye': return (); case 'flag': return (); case 'share': return (); case 'chat': return (); case 'send': return (); case 'arrow-right-up': return (); default: return null; } } // ───────────────────────────────────────────────────────────── // Global styles — injected once per document // ───────────────────────────────────────────────────────────── function injectGlobalStyles() { if (document.getElementById('is-global-styles')) return; const s = document.createElement('style'); s.id = 'is-global-styles'; s.textContent = ` :root { --font-display: 'Space Grotesk', ui-sans-serif, system-ui, sans-serif; --font-body: 'Inter', ui-sans-serif, system-ui, sans-serif; --font-mono: 'JetBrains Mono', ui-monospace, monospace; } * { box-sizing: border-box; } .is-surface { font-family: var(--font-body); color: var(--ink); background: var(--bg); } .is-btn { font-family: var(--font-body); font-weight: 600; border: 0; cursor: pointer; border-radius: 999px; padding: 10px 18px; font-size: 14px; display: inline-flex; align-items: center; gap: 8px; transition: transform .12s, box-shadow .12s, background .12s; white-space: nowrap; } .is-btn:hover { transform: translateY(-1px); } .is-btn-primary { background: var(--grad); color: #fff; box-shadow: 0 6px 20px -6px oklch(0.66 0.25 350 / 0.5); } .is-btn-ghost { background: var(--chip); color: var(--ink); } .is-btn-outline { background: transparent; color: var(--ink); box-shadow: inset 0 0 0 1px var(--line); } .is-chip { display: inline-flex; align-items: center; gap: 6px; padding: 4px 10px; border-radius: 999px; background: var(--chip); color: var(--ink-2); font-size: 12px; font-weight: 500; font-family: var(--font-body); } .is-chip-accent { background: var(--grad); color: #fff; } .is-card { background: var(--card); border-radius: 18px; box-shadow: 0 0 0 1px var(--line-2); overflow: hidden; transition: transform .15s, box-shadow .15s; } .is-card:hover { box-shadow: 0 0 0 1px var(--line), 0 12px 30px -12px rgba(0,0,0,0.12); } .is-kicker { font-family: var(--font-mono); font-size: 11px; letter-spacing: 0.14em; text-transform: uppercase; color: var(--ink-3); } .is-h1 { font-family: var(--font-display); font-weight: 700; letter-spacing: -0.03em; line-height: 1.02; color: var(--ink); } .is-h2 { font-family: var(--font-display); font-weight: 600; letter-spacing: -0.02em; line-height: 1.05; color: var(--ink); } .is-mono { font-family: var(--font-mono); font-variant-numeric: tabular-nums; } .is-scroll-x { overflow-x: auto; scrollbar-width: none; } .is-scroll-x::-webkit-scrollbar { display: none; } /* Subtle striped placeholder for imagery */ .is-ph { background-image: repeating-linear-gradient(45deg, var(--bg-3) 0 8px, var(--bg-2) 8px 16px); color: var(--ink-3); font-family: var(--font-mono); font-size: 11px; display: grid; place-items: center; } .is-grad-text { background: var(--grad); -webkit-background-clip: text; background-clip: text; color: transparent; } .is-ring { border-radius: 50%; background: var(--grad); padding: 2px; } .is-ring > div { border-radius: 50%; background: var(--card); width: 100%; height: 100%; overflow: hidden; display: grid; place-items: center; } input.is-input, textarea.is-input { appearance: none; background: var(--card-2); border: 1px solid var(--line); border-radius: 12px; padding: 12px 14px; font-size: 14px; color: var(--ink); font-family: var(--font-body); width: 100%; outline: none; transition: border-color .12s, box-shadow .12s; } input.is-input:focus, textarea.is-input:focus { border-color: transparent; box-shadow: 0 0 0 2px var(--accent); } `; document.head.appendChild(s); } // ───────────────────────────────────────────────────────────── // Mock listings — realistic shape; usernames are invented, not scraped // ───────────────────────────────────────────────────────────── const NICHE_COLORS = { fashion: ['#ff6b9d', '#c94b8d'], food: ['#ff9558', '#e25822'], travel: ['#4ec0ca', '#2a7a8c'], meme: ['#ffce55', '#e1a11c'], sport: ['#4cd964', '#1a8b3c'], tech: ['#6c7cff', '#3a47c8'], art: ['#c56bff', '#8a3cd8'], lifestyle: ['#f6a6c1', '#d06a8a'], music: ['#ff5a8a', '#b02a5e'], beauty: ['#ff8fb0', '#d45a80'], fitness: ['#66d0a5', '#2e8a6a'], auto: ['#8793a6', '#4a5365'], }; let LISTINGS = [ // Travel — 3 listings { id: 'l1', handle: '@citytrails', niche: 'travel', followers: 128400, age: 62, price: 18500, er: 4.2, verified: true, badge: 'hot', country: 'TR', postsStyle: 'travel' }, { id: 'l1b', handle: '@nomad.notes', niche: 'travel', followers: 76200, age: 41, price: 12400, er: 5.6, verified: false, badge: null, country: 'TR', postsStyle: 'travel' }, { id: 'l1c', handle: '@aegean.diary', niche: 'travel', followers: 195300, age: 73, price: 28900, er: 3.9, verified: true, badge: 'rare', country: 'TR', postsStyle: 'travel' }, // Fashion — 3 { id: 'l2', handle: '@velvet.looks', niche: 'fashion', followers: 87200, age: 48, price: 14900, er: 5.1, verified: false, badge: null, country: 'TR', postsStyle: 'fashion' }, { id: 'l2b', handle: '@minimal.thread', niche: 'fashion', followers: 134500, age: 56, price: 21800, er: 4.4, verified: true, badge: 'hot', country: 'TR', postsStyle: 'fashion' }, { id: 'l2c', handle: '@runway.daily', niche: 'fashion', followers: 58900, age: 33, price: 10200, er: 6.2, verified: false, badge: 'new', country: 'TR', postsStyle: 'fashion' }, // Food — 3 { id: 'l3', handle: '@kitchenlab.tr', niche: 'food', followers: 54300, age: 36, price: 9800, er: 6.4, verified: false, badge: 'new', country: 'TR', postsStyle: 'food' }, { id: 'l3b', handle: '@bistro.notes', niche: 'food', followers: 112800, age: 58, price: 17600, er: 5.0, verified: true, badge: null, country: 'TR', postsStyle: 'food' }, { id: 'l3c', handle: '@street.bites', niche: 'food', followers: 89400, age: 44, price: 13900, er: 5.7, verified: false, badge: null, country: 'TR', postsStyle: 'food' }, // Tech — 2 { id: 'l4', handle: '@byte.daily', niche: 'tech', followers: 212800, age: 71, price: 32500, er: 3.8, verified: true, badge: 'rare', country: 'US', postsStyle: 'tech' }, { id: 'l4b', handle: '@gadget.lab', niche: 'tech', followers: 73600, age: 39, price: 11800, er: 4.5, verified: false, badge: 'new', country: 'TR', postsStyle: 'tech' }, // Sport — 2 { id: 'l5', handle: '@pitchside', niche: 'sport', followers: 43100, age: 52, price: 7200, er: 5.8, verified: false, badge: null, country: 'TR', postsStyle: 'sport' }, { id: 'l5b', handle: '@matchday.tr', niche: 'sport', followers: 168400, age: 64, price: 24600, er: 4.7, verified: true, badge: 'hot', country: 'TR', postsStyle: 'sport' }, // Art — 2 { id: 'l6', handle: '@soft.studio', niche: 'art', followers: 96500, age: 44, price: 16200, er: 4.9, verified: false, badge: null, country: 'TR', postsStyle: 'art' }, { id: 'l6b', handle: '@inkwell.daily', niche: 'art', followers: 47800, age: 31, price: 8400, er: 6.0, verified: false, badge: 'new', country: 'TR', postsStyle: 'art' }, // Meme — 2 { id: 'l7', handle: '@gigglesnap', niche: 'meme', followers: 318700, age: 55, price: 24800, er: 7.9, verified: false, badge: 'hot', country: 'TR', postsStyle: 'meme' }, { id: 'l7b', handle: '@daily.lol', niche: 'meme', followers: 142300, age: 42, price: 13200, er: 8.4, verified: false, badge: null, country: 'TR', postsStyle: 'meme' }, // Lifestyle — 2 { id: 'l8', handle: '@room.tonic', niche: 'lifestyle', followers: 68900, age: 40, price: 10400, er: 5.3, verified: false, badge: null, country: 'TR', postsStyle: 'lifestyle' }, { id: 'l8b', handle: '@slow.weekday', niche: 'lifestyle', followers: 52100, age: 27, price: 7800, er: 6.1, verified: false, badge: 'new', country: 'TR', postsStyle: 'lifestyle' }, // Beauty — 2 { id: 'l9', handle: '@glow.mirror', niche: 'beauty', followers: 142600, age: 34, price: 19800, er: 4.6, verified: true, badge: null, country: 'TR', postsStyle: 'beauty' }, { id: 'l9b', handle: '@blush.lab', niche: 'beauty', followers: 81700, age: 38, price: 12600, er: 5.5, verified: false, badge: null, country: 'TR', postsStyle: 'beauty' }, // Fitness — 2 { id: 'l10', handle: '@lift.journal', niche: 'fitness', followers: 71400, age: 29, price: 8900, er: 6.1, verified: false, badge: 'new', country: 'TR', postsStyle: 'fitness' }, { id: 'l10b',handle: '@move.method', niche: 'fitness', followers: 124800, age: 51, price: 18400, er: 5.2, verified: true, badge: null, country: 'TR', postsStyle: 'fitness' }, // Music — 2 { id: 'l11', handle: '@low.cadence', niche: 'music', followers: 49800, age: 66, price: 11200, er: 4.0, verified: false, badge: null, country: 'TR', postsStyle: 'music' }, { id: 'l11b',handle: '@indie.tape', niche: 'music', followers: 92400, age: 47, price: 14600, er: 4.8, verified: false, badge: null, country: 'TR', postsStyle: 'music' }, // Auto — 2 { id: 'l12', handle: '@garagekeys', niche: 'auto', followers: 185200, age: 78, price: 27500, er: 3.4, verified: true, badge: 'rare', country: 'TR', postsStyle: 'auto' }, { id: 'l12b',handle: '@apex.shift', niche: 'auto', followers: 64300, age: 35, price: 9400, er: 4.2, verified: false, badge: 'new', country: 'TR', postsStyle: 'auto' }, ]; // Format large numbers: 128400 -> "128.4K" function fmtNum(n, lang = 'tr') { if (n < 1000) return String(n); if (n < 1_000_000) return (n / 1000).toFixed(n < 10000 ? 1 : 0).replace(/\.0$/, '') + 'K'; return (n / 1_000_000).toFixed(1) + 'M'; } function fmtPrice(n, lang = 'tr') { const sep = lang === 'tr' ? '.' : ','; const s = Math.round(n).toString().replace(/\B(?=(\d{3})+(?!\d))/g, sep); return lang === 'tr' ? `${s} ₺` : `₺${s}`; } function fmtAge(months, lang = 'tr', L = I18N.tr) { const y = Math.floor(months / 12); const m = months % 12; if (y === 0) return `${m} ${L.card_age_months}`; if (m === 0) return `${y} ${L.card_age_years}`; return `${y}${lang === 'tr' ? 'y' : 'y'} ${m}${lang === 'tr' ? 'a' : 'm'}`; } // Pseudo-hash for deterministic post patterns function hashPost(seed, i) { let h = 0; const s = seed + ':' + i; for (let k = 0; k < s.length; k++) h = (h * 31 + s.charCodeAt(k)) | 0; return Math.abs(h); } // Generate a 9-grid of stylized "post" placeholders for a handle function PostGrid({ handle, postsStyle, gap = 2, radius = 2, cols = 3, rows = 3, size }) { const stops = NICHE_COLORS[postsStyle] || ['#888', '#444']; const tiles = []; for (let i = 0; i < cols * rows; i++) { const h = hashPost(handle, i); const variant = h % 5; const angle = (h >> 3) % 360; const shade = ((h >> 8) % 40) / 100; // 0..0.4 const bg = `linear-gradient(${angle}deg, ${stops[0]} 0%, ${stops[1]} 100%)`; tiles.push(
{/* decorative shape overlays so posts feel varied */} {variant === 0 &&
} {variant === 1 &&
} {variant === 2 &&
} {variant === 3 &&
} {variant === 4 &&
}
); } return (
{tiles}
); } // Avatar — gradient ring + niche-tinted circle with first letter of handle function Avatar({ handle, postsStyle, size = 52, ring = true }) { const stops = NICHE_COLORS[postsStyle] || ['#888', '#444']; const letter = handle.replace('@', '')[0].toUpperCase(); const inner = (
{letter}
); if (!ring) return inner; return (
{inner}
); } Object.assign(window, { I18N, PALETTES, themeVars, Logo, Icon, injectGlobalStyles, LISTINGS, NICHE_COLORS, fmtNum, fmtPrice, fmtAge, PostGrid, Avatar, });