/* global React */ const { useState } = React; /* ---------- Icon set (Lucide-style) ---------- */ function Icon({ name, size = 18, stroke = 1.75 }) { const paths = { arrow: , arrowDown: , check: , plus: , minus: , x: , chevron: , chevronr: , globe: , calendar: , clock: , users: , user: , euro: , factory: , flask: , book: , bolt: , chart: , cpu: , shield: , droplet: , wrench: , play: , mail: , linkedin: , youtube: , download: , grid: , list: , }; return ( {paths[name] || null} ); } /* ---------- Logo (LH brand) ---------- */ function Logo({ variant = "color", height = 28 }) { const src = variant === "white" ? "assets/logo-white.svg" : variant === "mark" ? "assets/logo-mark.svg" : variant === "black" ? "assets/logo-black.svg" : "assets/logo-color.svg"; return Lean Hydrogen; } /* ---------- Wordmark for "Escuela de Protones" ---------- Lockup: custom isotype (proton-arrow inside electron orbit, with electron dot) + wordmark in display type. The isotype is supplied as a PNG asset — variants navy (default) / white (for dark bg). */ function EPMark({ height = 28, color = "var(--lh-navy)", accent = "var(--lh-cyan)", variant }) { const isDark = variant === 'white' || (typeof color === 'string' && (color === '#fff' || color === 'white')); const markSrc = isDark ? 'assets/ep-logo-white.png' : 'assets/ep-logo.png'; return (
Escuela de Protones
); } /* ---------- Pictographic mark — just the proton/orbit glyph ---------- */ function ProtonGlyph({ size = 48, color = "var(--lh-navy)", accent = "var(--lh-cyan)", strokeWidth = 1.5 }) { return ( {/* proton (nucleus) */} p+ {/* orbit 1 */} {/* orbit 2 */} {/* electron */} ); } /* ---------- Badge / chip ---------- */ function Badge({ children, variant = "default", style }) { const variants = { default: { background:'#E8F1FC', color:'#001A70', border:'1px solid transparent' }, onDark: { background:'rgba(255,255,255,.08)', color:'#fff', border:'1px solid rgba(255,255,255,.18)' }, cyan: { background:'rgba(0,181,226,.15)', color:'#00B5E2', border:'1px solid rgba(0,181,226,.35)' }, yellow: { background:'rgba(224,231,34,.22)', color:'#6B6F00', border:'1px solid rgba(224,231,34,.6)' }, outline: { background:'#fff', color:'#001A70', border:'1px solid #DDE4ED' }, soft: { background:'#F6F8FB', color:'#4A5668', border:'1px solid #EEF2F7' }, }; return ( {children} ); } /* ---------- Button ---------- */ function Button({ children, variant = "primary", size = "md", icon, iconAfter, onClick, type = "button", disabled, full, href, target, download, style }) { const base = { display:'inline-flex', alignItems:'center', justifyContent:'center', gap:8, fontFamily:'inherit', fontWeight:600, cursor: disabled?'not-allowed':'pointer', border:'1px solid transparent', borderRadius:8, transition:'all 200ms cubic-bezier(.2,.8,.2,1)', textDecoration:'none', width: full ? '100%' : 'auto', opacity: disabled ? 0.4 : 1, }; const sizes = { sm:{ padding:'7px 14px', fontSize:13 }, md:{ padding:'10px 18px', fontSize:14 }, lg:{ padding:'14px 22px', fontSize:15 }, }; const variants = { primary: { background:'#001A70', color:'#fff' }, secondary: { background:'#fff', color:'#001A70', borderColor:'#DDE4ED' }, tertiary: { background:'transparent', color:'#307FE2', padding:'10px 4px' }, accent: { background:'#E0E722', color:'#001A70' }, ghost: { background:'transparent', color:'#001A70' }, onDark: { background:'#fff', color:'#001A70' }, onDarkGhost: { background:'transparent', color:'#fff', borderColor:'rgba(255,255,255,.25)' }, cyan: { background:'#00B5E2', color:'#001A70' }, }; const hoverStyles = { primary: { background:'#1A3180' }, secondary: { background:'#F6F8FB', borderColor:'#C2CCD8' }, tertiary: { color:'#001A70' }, accent: { background:'#d6dd1f' }, ghost: { background:'#F6F8FB' }, onDark: { background:'#F6F8FB' }, onDarkGhost: { background:'rgba(255,255,255,.08)', borderColor:'rgba(255,255,255,.4)' }, cyan: { background:'#16C2EB' }, }; const [hover, setHover] = useState(false); const merged = {...base, ...sizes[size], ...variants[variant], ...(hover && !disabled ? hoverStyles[variant] : {}), ...style}; if (href) { return ( setHover(true)} onMouseLeave={()=>setHover(false)} style={merged}> {icon && } {children} {iconAfter && } ); } return ( ); } /* ---------- Card ---------- */ function Card({ children, hover = true, padding = 24, onClick, style }) { const [h, setH] = useState(false); return (
setH(true)} onMouseLeave={()=>setH(false)} onClick={onClick} style={{ background:'#fff', border:'1px solid #EEF2F7', borderRadius:12, padding, cursor: onClick?'pointer':'auto', boxShadow: hover && h ? '0 12px 32px rgba(0,26,112,.08), 0 4px 12px rgba(0,26,112,.05)' : '0 1px 2px rgba(0,26,112,.06), 0 1px 3px rgba(0,26,112,.04)', transform: hover && h ? 'translateY(-2px)' : 'none', transition:'all 200ms cubic-bezier(.2,.8,.2,1)', ...style, }}> {children}
); } /* ---------- Eyebrow ---------- */ function Eyebrow({ children, color = '#00B5E2', mono = true }) { return
{children}
; } /* ---------- Level chip ---------- */ function LevelChip({ level, size = 28, withLabel = false }) { const labels = { i: 'Introductorio', a: 'Avanzado', e: 'Experto' }; const colors = { i: { bg:'rgba(0,181,226,.14)', fg:'var(--lh-cyan)', border:'rgba(0,181,226,.35)' }, a: { bg:'rgba(48,127,226,.14)', fg:'var(--lh-blue)', border:'rgba(48,127,226,.4)' }, e: { bg:'rgba(224,231,34,.22)', fg:'#6B6F00', border:'rgba(224,231,34,.7)' }, }; const c = colors[level]; return (
{level} {withLabel && {labels[level]}}
); } Object.assign(window, { Icon, Logo, EPMark, ProtonGlyph, Badge, Button, Card, Eyebrow, LevelChip });