// ============================================================ // YCI · Kit de Wireframe — primitivos + blocos globais (React) // Classes em wireframe.css. Export para window no fim. // ============================================================ // ---- helpers ---- // Largura da prancheta = tela + padding(64) + (rail de notas 280) window.SHEETW = (screenW, notes = true) => screenW + 64 + (notes ? 280 : 0); // ---- Prancheta / artboard interior ---- function Sheet({ mobile, screenW, vp, notes, children, screenStyle }) { return (
{vp}
{children}
{notes && (
Notas · blocos & estados
{notes.map((n, i) => { const txt = typeof n === 'string' ? n : n.t; const isState = typeof n === 'object' && n.state; return (

${n.pin} ` : '') + txt }} /> ); })}

)}
); } // ---- primitivos ---- const Bar = ({ w = '100%', h, cls = '', style }) => ; const Lines = ({ n = 3, w = '100%', gap = 8, style }) =>
{Array.from({ length: n }).map((_, i) => )}
; const Box = ({ w, h, label, dashed, plain, children, style, cls = '' }) =>
{label &&
{label}
} {children}
; const Img = ({ w = '100%', h = 120, label = 'Foto', video, style, cls = '' }) =>
{label}
; const Avatar = ({ s = 40, label, style }) =>
{label || 'IMG'}
; const H = ({ size = 'md', children, style }) =>
{children}
; const T = ({ children, sm, style }) =>
{children}
; const Eyebrow = ({ children, style }) =>
{children}
; const Data = ({ children, style }) =>
{children}
; const Hr = ({ style }) =>
; const Pin = ({ n, style }) => {n}; const Btn = ({ children, variant = 'plain', size = '', block, ar, style }) =>
{children}{ar && }
; const Chip = ({ children, active, style }) => {children}; const Tag = ({ children, navy, style }) => {children}; const Link = ({ children, style }) => {children}; const Field = ({ label, area, focus, placeholder, select, style }) =>
{label && }
{placeholder}
; const State = ({ children, neutral, style }) => {children}; // ---- chrome global ---- const Logo = ({ small }) =>
LOGO
; const NAV = ['O Clube', 'Vida no Iate Clube', 'Notícias', 'Serviços']; // Desktop header — logged toggles the "Entrar" → "Olá, sócio" treatment. // weather: nautical clima/vento chip · mega: caret on nav items. function DeskHeader({ active, logged, weather, mega }) { return (
{weather && }
PT/EN
{/* Rev. 18/jun: Associe-se vira CTA fixo (sai da nav); Área do Sócio = botão, não item de menu. */}
Associe-se
{logged ?
SÁrea do Sócio
:
Entrar · Área do Sócio
}
); } // Clima / vento — utilidade náutica no header (componente dinâmico previsto). const WeatherChip = ({ style }) =>
🌬 14 kn SE·🌡 22°·⛴ 06–23h
; // Sub-estruturas por área (mega-menu). Rev. 18/jun: 5 áreas top-level // (O Clube, Vida no Iate Clube, Notícias, Serviços) + Associe-se como CTA. // 'O Clube' é AGRUPADO; os demais são listas. Náutica vive sob Esportes (Vida). const SUBNAV = { 'O Clube': { 'Institucional': ['70 anos (abertura)', 'Governança', 'Imprensa'], 'Lugares & estrutura': ['Onde estamos', 'Estrutura', 'Subsedes', 'Conveniados', 'Meio Ambiente'], }, // Rev. 18/jun: Gastronomia permanece sob Vida (decisão pós-reunião, validar c/ Fernando); // Eventos sociais ganha página; Notícias sobe para top-level (saiu daqui). 'Vida no Iate Clube': ['Esportes › Náutica & Vela', 'Semana de Vela (SIVI)', 'Agenda', 'Eventos sociais', 'Gastronomia'], // Rev. 18/jun: Notícias é área própria. Revista descontinuada → editorias + newsletter. 'Notícias': ['Todas as notícias', 'Náutica & Vela', 'Social', 'Gastronomia', 'Pessoas', 'História', 'Newsletter semanal'], // Serviços = só operacional (Cardápio saiu → Gastronomia). 'Serviços': ['Marina', 'Travessia', 'Combustíveis', 'Taxas', 'Regulamentos', 'Links úteis'], }; function MegaMenuPanel() { const navItem = (x) => {x}; return (
{Object.entries(SUBNAV).map(([area, items]) => (
{area}
{Array.isArray(items) ?
{items.map(navItem)}
:
{Object.entries(items).map(([g, sub]) =>
{g}
{sub.map(navItem)}
)}
}
))}
Semana de Vela
Evento-âncora · 24 jul
); } // Heritage / prova social — reconhecimento e presença internacional. function SocialProof({ wrap }) { return (
Reconhecimento & presença internacional
{['Globe40', 'Rolex', 'NY Yacht Club', 'Barcelona', 'SIVI'].map(s =>
{s}
)}
); } const Stat = ({ v, l }) =>
{v}
{l}
; const Quote = ({ style }) =>
“Citação editorial de orgulho do clube em uma ou duas linhas.”
— Nome · cargo
; const ResultRow = ({ pos }) =>
{pos}º
00:00:00
; const TierCard = ({ name, featured }) =>
{featured && Recomendado}
{name}
a partir de R$ 000
{[0, 1, 2].map(i =>
)}
Escolher
; // Patrocínio — cobrand "apresentado por" + card in-feed nativo (rotulado). const Cobrand = ({ style }) =>
Apresentado por
; function InFeedAd() { return (
Patrocinadoslot infeed-native
Apresentado por · marca
); } // Faixa "ao vivo" do hero — utilidade sobreposta (clima/vento, regata, balsa). function LiveStrip({ dark }) { return (
{[['🌬', '14 kn SE'], ['⛵', 'Próx. regata sáb 09h'], ['⛴', 'Balsa 06–23h'], ['⛽', 'R$ 6,29']].map(([i, v], n) =>
{i} {v}
)}
● ao vivo
); } function MobileHeader({ logged }) { return ( <>
9:41▰▰▰ ◢ 100%
PT/EN
{logged !== undefined && (
{logged ? <>LogadoBotão Entrar vira atalho do painel : <>Entrar · Área do Sóciosempre visível}
)} ); } // Universal footer (compact for mobile, full for desktop) function Footer({ mobile }) { const cols = [ ['Contato · 3 sedes', ['Ilhabela (sede)', 'Saco do Sombrio', 'São Sebastião', 'Sede SP']], ['Navegar', ['O Clube', 'Vida no Iate Clube', 'Notícias', 'Serviços', 'Associe-se']], ['Institucional', ['Imprensa', 'LGPD · Privacidade', 'Cookies', 'Transparência']], ]; return (
{cols.map(([t, items], i) => (
{t}
{items.map(x => {x})}
))}
Newsletter semanal
seu@email.com
Assinar
Patrocinadores
{['Master', 'Oficial', 'Oficial', 'Apoio', 'Apoio'].map((s, i) =>
)}
Desde 1956 · Ilhabela · 23°46′41″S 45°21′29″W
); } // Card primitives reused across templates const NewsCard = ({ w = '100%', tall }) =>
Categoria
Título da matéria em duas linhas
12 jun 2026 · Autor
; const EventRow = ({ status }) =>
14
JUN
Regata{status && ● {status}}
Nome do evento / regata
Marina YCI · 09:00 · Vento 12–16 kn SE
; const DocRow = ({ locked }) =>
Ata · 12 jun 2026 · 240 KB
{locked && Sócio}
; Object.assign(window, { Sheet, Bar, Lines, Box, Img, Avatar, H, T, Eyebrow, Data, Hr, Pin, Btn, Chip, Tag, Link, Field, State, Logo, DeskHeader, MobileHeader, Footer, NewsCard, EventRow, DocRow, NAV, WeatherChip, SUBNAV, MegaMenuPanel, SocialProof, Stat, Quote, ResultRow, TierCard, Cobrand, InFeedAd, LiveStrip, });