// ============================================================
// 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 (
{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 }) =>
;
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]) =>
)}
}
))}
![]()
Semana de VelaEvento-â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 }) => ;
const Quote = ({ style }) => “Citação editorial de orgulho do clube em uma ou duas linhas.”
— Nome · cargo ;
const ResultRow = ({ pos }) => ;
const TierCard = ({ name, featured }) => {featured &&
Recomendado}
{name}
a partir de R$ 000Escolher ;
// Patrocínio — cobrand "apresentado por" + card in-feed nativo (rotulado).
const Cobrand = ({ style }) => ;
function InFeedAd() {
return (
Patrocinadoslot infeed-native
);
}
// 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%
{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 }) =>
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,
});