<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Archivo — Portfolio</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin="">
<link href="https://fonts.googleapis.com/css2?family=Archivo+Black&family=Archivo:ital,wght@0,400;0,500;0,600;0,700;1,400&display=swap" rel="stylesheet">
<style>
:root{
--bg:#161616;
--surface:#1f1f1f;
--line:#2d2d2d;
--text:#f2f0ec;
--text-dim:#8f8c86;
--red:#e2382b;
--red-dim:#7a1f18;
--yellow:#f3c012;
--yellow-dim:#7a610a;
}
*{margin:0;padding:0;box-sizing:border-box;}
html{scroll-behavior:smooth;}
body{
background:var(--bg);
color:var(--text);
font-family:'Archivo',sans-serif;
overflow-x:hidden;
}
::selection{background:var(--yellow);color:#161616;}
a{color:inherit;text-decoration:none;}
/* ---------- Loader ---------- */
.loader{
position:fixed;inset:0;background:var(--bg);
display:flex;align-items:center;justify-content:center;
z-index:999;
transition:opacity .6s ease, visibility .6s ease;
}
.loader.done{opacity:0;visibility:hidden;}
.loader-mark{
font-family:'Archivo Black',sans-serif;
font-size:14px;letter-spacing:.3em;
color:var(--text-dim);
display:flex;gap:10px;align-items:center;
}
.loader-bar{width:120px;height:2px;background:var(--line);overflow:hidden;}
.loader-bar span{
display:block;height:100%;width:0%;background:var(--red);
animation:loadbar 1s ease forwards;
}
@keyframes loadbar{to{width:100%;}}
/* ---------- Top nav ---------- */
header{
position:fixed;top:0;left:0;right:0;
display:flex;justify-content:space-between;align-items:center;
padding:28px 48px;
z-index:50;
mix-blend-mode:difference;
}
.logo{
font-family:'Archivo Black',sans-serif;
font-size:18px;letter-spacing:.04em;
}
.logo span{color:var(--yellow);}
nav{display:flex;gap:32px;}
nav a{
font-size:13px;letter-spacing:.08em;text-transform:uppercase;
color:var(--text-dim);
position:relative;padding-bottom:4px;
}
nav a::after{
content:"";position:absolute;left:0;bottom:0;
width:0;height:1px;background:var(--red);
transition:width .3s ease;
}
nav a:hover{color:var(--text);}
nav a:hover::after{width:100%;}
nav a.is-active{color:var(--text);}
nav a.is-active::after{width:100%;background:var(--yellow);}
/* ---------- Hero ---------- */
.hero{
min-height:100vh;
display:flex;flex-direction:column;justify-content:center;
padding:0 48px;position:relative;
}
.hero-eyebrow{
font-size:13px;letter-spacing:.2em;text-transform:uppercase;
color:var(--text-dim);margin-bottom:24px;
display:flex;align-items:center;gap:12px;
opacity:0;transform:translateY(12px);
animation:rise .7s ease forwards;
animation-delay:.15s;
}
.hero-eyebrow::before{
content:"";width:8px;height:8px;border-radius:50%;
background:var(--red);
animation:pulse 2s ease-in-out infinite;
}
@keyframes pulse{0%,100%{opacity:1;}50%{opacity:.3;}}
.hero-title{
font-family:'Archivo Black',sans-serif;
font-size:clamp(48px,11vw,140px);
line-height:.92;letter-spacing:-.01em;
text-transform:uppercase;
}
.hero-title .line{
display:block;overflow:hidden;
}
.hero-title .line span{
display:block;
opacity:0;transform:translateY(110%);
animation:rise .8s cubic-bezier(.16,1,.3,1) forwards;
}
.hero-title .line:nth-child(1) span{animation-delay:.25s;}
.hero-title .line:nth-child(2) span{animation-delay:.38s;color:var(--red);}
.hero-title .line:nth-child(3) span{animation-delay:.51s;}
@keyframes rise{to{opacity:1;transform:translateY(0);}}
.hero-foot{
display:flex;justify-content:space-between;align-items:flex-end;
margin-top:48px;
opacity:0;animation:rise .7s ease forwards;animation-delay:.75s;
flex-wrap:wrap;gap:24px;
}
.hero-desc{
max-width:360px;font-size:15px;line-height:1.6;color:var(--text-dim);
}
.hero-desc strong{color:var(--text);font-weight:600;}
.scroll-cue{
display:flex;align-items:center;gap:10px;
font-size:12px;letter-spacing:.15em;text-transform:uppercase;
color:var(--text-dim);
}
.scroll-cue .stick{
width:1px;height:36px;background:var(--line);position:relative;overflow:hidden;
}
.scroll-cue .stick::after{
content:"";position:absolute;top:0;left:0;width:100%;height:30%;
background:var(--yellow);
animation:scrollcue 1.8s ease-in-out infinite;
}
@keyframes scrollcue{0%{transform:translateY(-100%);}100%{transform:translateY(330%);}}
/* ---------- Section heading ---------- */
.section-head{
padding:120px 48px 40px;
display:flex;justify-content:space-between;align-items:baseline;
flex-wrap:wrap;gap:16px;
}
.section-head h2{
font-family:'Archivo Black',sans-serif;
font-size:clamp(28px,4vw,44px);
text-transform:uppercase;
}
.section-head .count{
font-size:13px;color:var(--text-dim);letter-spacing:.1em;
}
/* ---------- Filter bar ---------- */
.filters{
display:flex;gap:10px;padding:0 48px 56px;flex-wrap:wrap;
}
.filter-btn{
font-family:'Archivo',sans-serif;
font-size:13px;letter-spacing:.06em;text-transform:uppercase;
padding:9px 18px;border:1px solid var(--line);
background:transparent;color:var(--text-dim);
cursor:pointer;transition:border-color .25s ease, color .25s ease, background .25s ease;
}
.filter-btn:hover{border-color:var(--text-dim);color:var(--text);}
.filter-btn.active{
background:var(--text);color:var(--bg);border-color:var(--text);
}
/* ---------- Project grid ---------- */
.grid{
display:grid;
grid-template-columns:repeat(6,1fr);
gap:2px;
padding:0 48px 120px;
}
.cell{grid-column:span 3;}
.cell.wide{grid-column:span 4;}
.cell.narrow{grid-column:span 2;}
.card{
position:relative;
aspect-ratio:4/3;
background:var(--surface);
overflow:hidden;
cursor:pointer;
border:1px solid var(--line);
}
.card.hidden-by-filter{display:none;}
.swatch{
position:absolute;inset:0;
display:flex;align-items:center;justify-content:center;
font-family:'Archivo Black',sans-serif;
font-size:15vw;
color:rgba(242,240,236,.05);
user-select:none;
transition:transform .6s cubic-bezier(.16,1,.3,1);
}
.card:hover .swatch{transform:scale(1.08);}
.tag{
position:absolute;top:14px;left:14px;
font-family:'Archivo Black',sans-serif;
font-size:11px;letter-spacing:.08em;
color:var(--bg);
background:var(--text-dim);
padding:5px 9px;
z-index:2;
}
.card[data-accent="red"] .tag{background:var(--red);}
.card[data-accent="yellow"] .tag{background:var(--yellow);}
.stamp{
position:absolute;top:14px;right:14px;
font-family:'Archivo',sans-serif;
font-size:11px;color:var(--text-dim);
border:1px solid var(--line);
padding:4px 8px;
transform:rotate(0deg);
transition:transform .4s ease, border-color .4s ease, color .4s ease;
z-index:2;
}
.card:hover .stamp{
transform:rotate(-6deg);
border-color:var(--text-dim);
color:var(--text);
}
.overlay{
position:absolute;left:0;right:0;bottom:0;
background:var(--bg);
border-top:3px solid var(--text-dim);
padding:18px 18px 16px;
transform:translateY(100%);
transition:transform .45s cubic-bezier(.16,1,.3,1);
z-index:3;
}
.card[data-accent="red"] .overlay{border-top-color:var(--red);}
.card[data-accent="yellow"] .overlay{border-top-color:var(--yellow);}
.card:hover .overlay{transform:translateY(0);}
.overlay-name{
font-family:'Archivo Black',sans-serif;
font-size:18px;text-transform:uppercase;line-height:1.15;
margin-bottom:6px;
opacity:0;transform:translateY(8px);
transition:opacity .4s ease .08s, transform .4s ease .08s;
}
.card:hover .overlay-name{opacity:1;transform:translateY(0);}
.overlay-meta{
display:flex;justify-content:space-between;
font-size:12px;color:var(--text-dim);letter-spacing:.04em;
opacity:0;transform:translateY(8px);
transition:opacity .4s ease .14s, transform .4s ease .14s;
}
.card:hover .overlay-meta{opacity:1;transform:translateY(0);}
.corner-arrow{
position:absolute;bottom:14px;right:14px;
width:30px;height:30px;border:1px solid var(--line);
display:flex;align-items:center;justify-content:center;
font-size:14px;color:var(--text-dim);
transition:transform .4s cubic-bezier(.16,1,.3,1), border-color .3s ease, color .3s ease;
z-index:3;
}
.card:hover .corner-arrow{
transform:rotate(45deg) scale(1.1);
border-color:var(--text);color:var(--text);
}
/* ---------- About strip ---------- */
.strip{
padding:120px 48px;
border-top:1px solid var(--line);
display:grid;grid-template-columns:1fr 1fr;gap:64px;
}
.strip h2{
font-family:'Archivo Black',sans-serif;
font-size:clamp(32px,5vw,56px);
text-transform:uppercase;line-height:1.05;
}
.strip p{
font-size:16px;line-height:1.7;color:var(--text-dim);max-width:480px;
}
.strip p strong{color:var(--text);font-weight:600;}
.strip .marks{display:flex;gap:10px;margin-top:28px;}
.mark{width:10px;height:10px;}
.mark.r{background:var(--red);}
.mark.y{background:var(--yellow);}
.mark.g{background:var(--text-dim);}
/* ---------- Footer ---------- */
footer{
padding:64px 48px 40px;
border-top:1px solid var(--line);
display:flex;justify-content:space-between;align-items:center;
flex-wrap:wrap;gap:24px;
}
.foot-big{
font-family:'Archivo Black',sans-serif;
font-size:clamp(28px,6vw,72px);
text-transform:uppercase;
}
.foot-big a{position:relative;}
.foot-big a::after{
content:"";position:absolute;left:0;bottom:6px;width:100%;height:6px;
background:var(--yellow);z-index:-1;
transform:scaleX(0);transform-origin:left;
transition:transform .4s cubic-bezier(.16,1,.3,1);
}
.foot-big a:hover::after{transform:scaleX(1);}
.foot-links{display:flex;gap:24px;flex-wrap:wrap;}
.foot-links a{font-size:13px;color:var(--text-dim);letter-spacing:.06em;text-transform:uppercase;}
.foot-links a:hover{color:var(--text);}
.foot-copy{width:100%;font-size:12px;color:var(--text-dim);margin-top:40px;}
/* ---------- Reveal on scroll ---------- */
.reveal{opacity:0;transform:translateY(32px);transition:opacity .7s cubic-bezier(.16,1,.3,1), transform .7s cubic-bezier(.16,1,.3,1);}
.reveal.in{opacity:1;transform:translateY(0);}
/* ---------- Responsive ---------- */
@media (max-width:900px){
header{padding:20px 24px;}
nav{gap:18px;}
nav a{font-size:11px;}
.hero,.section-head,.filters,.grid,.strip,footer{padding-left:24px;padding-right:24px;}
.strip{grid-template-columns:1fr;gap:32px;}
.grid{grid-template-columns:repeat(2,1fr);}
.cell,.cell.wide,.cell.narrow{grid-column:span 2;}
}
@media (prefers-reduced-motion:reduce){
*{animation:none !important;transition:none !important;}
}
</style>
<div class="loader" id="loader">
<div class="loader-mark">
ARCHIVO
<div class="loader-bar"><span></span></div>
</div>
</div>
<header>
<div class="logo">ARCH<span>I</span>VO</div>
<nav>
<a href="#trabajo" class="is-active">Trabajo</a>
<a href="#sobre">Sobre mí</a>
<a href="#contacto">Contacto</a>
</nav>
</header>
<section class="hero">
<p class="hero-eyebrow">Diseño & ilustración — disponible para proyectos 2026</p>
<h1 class="hero-title">
<span class="line"><span>Hago cosas</span></span>
<span class="line"><span>que se ven</span></span>
<span class="line"><span>y se sienten</span></span>
</h1>
<div class="hero-foot">
<p class="hero-desc">Soy <Leónidas Gonzalez</strong>, diseñador/a e ilustrador/a. Esta es una selección curada de proyectos propios y para clientes, ordenados como un archivo de trabajo.</p>
<div class="scroll-cue">Scroll<div class="stick"></div></div>
</div>
</section>
<section id="trabajo">
<div class="section-head reveal">
<h2>Trabajo seleccionado</h2>
<span class="count" id="visible-count">12 proyectos</span>
</div>
<div class="filters reveal">
<button class="filter-btn active" data-filter="all">Todo</button>
<button class="filter-btn" data-filter="diseno">Diseño</button>
<button class="filter-btn" data-filter="ilustracion">Ilustración</button>
<button class="filter-btn" data-filter="branding">Branding</button>
</div>
<div class="grid" id="grid"></div>
</section>
<section class="strip reveal" id="sobre">
<h2>Sobre el archivo</h2>
<div>
<p>Cada proyecto en esta página queda catalogado como una ficha: nombre, categoría y año, igual que un expediente. La idea es simple — <strong>mostrar el trabajo sin relleno</strong>, dejar que cada pieza hable por sí misma.</p>
<div class="marks"><span class="mark r"></span><span class="mark y"></span><span class="mark g"></span></div>
</div>
</section>
<footer id="contacto">
<div class="foot-big"><a href="mailto:hola@tuweb.com">Hablemos →</a></div>
<div class="foot-links">
<a href="#">Instagram</a>
<a href="#">LinkedIn</a>
<a href="#">Dribbble</a>
</div>
<div class="foot-copy">© 2026 [Tu nombre]. Catálogo de proyectos.</div>
</footer>
<script>
// ---------- Loader ----------
window.addEventListener('load', () => {
setTimeout(() => {
document.getElementById('loader').classList.add('done');
}, 500);
});
// ---------- Project data (placeholders — reemplazar con proyectos reales) ----------
const projects = [
{ name: "Atlas", category: "branding", label: "Branding", year: "2026", accent: "red", size: "wide" },
{ name: "Niebla", category: "ilustracion", label: "Ilustración", year: "2025", accent: "yellow", size: "narrow" },
{ name: "Cursiva", category: "diseno", label: "Diseño web", year: "2025", accent: "red", size: "" },
{ name: "Forma", category: "diseno", label: "Editorial", year: "2024", accent: "yellow", size: "" },
{ name: "Rotor", category: "ilustracion", label: "Personaje", year: "2024", accent: "red", size: "narrow" },
{ name: "Lince", category: "branding", label: "Identidad", year: "2024", accent: "yellow", size: "wide" },
{ name: "Cuaderno", category: "ilustracion", label: "Editorial", year: "2023", accent: "red", size: "" },
{ name: "Sereno", category: "diseno", label: "App", year: "2023", accent: "yellow", size: "" },
{ name: "Vértigo", category: "branding", label: "Packaging", year: "2023", accent: "red", size: "narrow" },
{ name: "Marejada", category: "ilustracion", label: "Mural", year: "2022", accent: "yellow", size: "wide" },
{ name: "Cifra", category: "diseno", label: "Sistema", year: "2022", accent: "red", size: "" },
{ name: "Maqueta", category: "branding", label: "Identidad", year: "2021", accent: "yellow", size: "" },
];
const grid = document.getElementById('grid');
function initials(name){
return name.slice(0,2).toUpperCase();
}
projects.forEach((p, i) => {
const cell = document.createElement('div');
cell.className = 'cell' + (p.size ? ' ' + p.size : '');
cell.innerHTML = `
<div class="card" data-category="${p.category}" data-accent="${p.accent}">
<div class="swatch">${initials(p.name)}</div>
<span class="tag">${p.label}</span>
<span class="stamp">No. ${String(i + 1).padStart(2, '0')}</span>
<div class="corner-arrow">↗</div>
<div class="overlay">
<div class="overlay-name">${p.name}</div>
<div class="overlay-meta"><span>${p.label}</span><span>${p.year}</span></div>
</div>
</div>
`;
grid.appendChild(cell);
});
// ---------- Filtering ----------
const filterBtns = document.querySelectorAll('.filter-btn');
const visibleCount = document.getElementById('visible-count');
function applyFilter(filter){
const cards = document.querySelectorAll('.card');
let visible = 0;
cards.forEach(card => {
const match = filter === 'all' || card.dataset.category === filter;
card.closest('.cell').style.display = match ? '' : 'none';
if (match) visible++;
});
visibleCount.textContent = visible + (visible === 1 ? ' proyecto' : ' proyectos');
}
filterBtns.forEach(btn => {
btn.addEventListener('click', () => {
filterBtns.forEach(b => b.classList.remove('active'));
btn.classList.add('active');
applyFilter(btn.dataset.filter);
});
});
// ---------- Scroll reveal ----------
const revealEls = document.querySelectorAll('.reveal');
const observer = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting){
entry.target.classList.add('in');
observer.unobserve(entry.target);
}
});
}, { threshold: 0.15 });
revealEls.forEach(el => observer.observe(el));
// ---------- Active nav link on scroll ----------
const sections = ['trabajo','sobre','contacto'].map(id => document.getElementById(id));
const navLinks = document.querySelectorAll('nav a');
const navObserver = new IntersectionObserver((entries) => {
entries.forEach(entry => {
if (entry.isIntersecting){
const id = entry.target.id;
navLinks.forEach(link => {
link.classList.toggle('is-active', link.getAttribute('href') === '#' + id);
});
}
});
}, { threshold: 0.4 });
sections.forEach(sec => sec && navObserver.observe(sec));
</script>