/* =========================================================
   BASE — reset, typography, links, buttons, reveal utilities.
   ========================================================= */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  /* The JS smooth-scroll turns this off; it is the no-JS fallback. */
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--fg);
  font-family: var(--font-sans);
  font-size: var(--t-body);
  line-height: var(--lh-body);
  font-variation-settings: "wght" 400, "wdth" 100;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;
  transition: background var(--dur-m) var(--ease), color var(--dur-m) var(--ease);
}

/* Locks the page while the menu or the preloader is up */
body.is-locked { overflow: hidden; }

img, svg, video, canvas { display: block; max-width: 100%; height: auto; }
img { background: var(--bg-raised); }

ul, ol { list-style: none; margin: 0; padding: 0; }
figure, blockquote { margin: 0; }
p { margin: 0 0 1em; text-wrap: pretty; }
p:last-child { margin-bottom: 0; }

h1, h2, h3, h4 {
  margin: 0;
  font-weight: 500;
  line-height: var(--lh-tight);
  letter-spacing: var(--tr-tight);
  text-wrap: balance;
}

a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }
button { background: none; border: 0; padding: 0; cursor: pointer; }

::selection { background: var(--selection); color: var(--selection-fg); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: 2px;
}

hr { border: 0; border-top: 1px solid var(--line); margin: 0; }

/* ---------- Layout helpers ---------- */
.wrap {
  width: 100%;
  max-width: var(--maxw);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.section { padding-block: var(--section); position: relative; }
.grid {
  display: grid;
  grid-template-columns: repeat(12, minmax(0, 1fr));
  gap: var(--gutter);
}

/* ---------- Type helpers ---------- */
.mono {
  font-family: var(--font-mono);
  font-size: var(--t-mono);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  color: var(--fg-dim);
  font-weight: 400;
}
/* Emphasis, everywhere. Never a slant: the italic axis of Archivo is
   not even loaded, so <em> used to be faked by the browser leaning the
   roman over. The width axis is real type, and it is unmistakably a
   decision rather than a default. Each context sets --em-wght to match
   the weight it is sitting in, because font-variation-settings is
   inherited and names every axis it touches. */
em, .em, .hero__em {
  font-style: normal;
  font-variation-settings: "wght" var(--em-wght, 400), "wdth" var(--em-wdth);
  color: var(--accent);
}

/* Solid, not hatched. The ruled version cut the letterforms into pieces
   and long words stopped reading as whole words, so the accent fills the
   glyph and the width axis carries the emphasis on its own. */
}
.lead { font-size: var(--t-lead); line-height: 1.32; letter-spacing: -0.02em; }
.dim { color: var(--fg-dim); }
.accent { color: var(--accent); }
.h1 { font-size: var(--t-h1); }
.h2 { font-size: var(--t-h2); }
.h3 { font-size: var(--t-h3); }
.giant { font-size: var(--t-giant); line-height: 0.8; letter-spacing: -0.05em; }

/* Section label: 01 / What I do */
.eyebrow {
  display: flex;
  align-items: center;
  gap: 0.9rem;
  margin-bottom: clamp(2rem, 1rem + 3vw, 4.5rem);
}
.eyebrow::before {
  content: "";
  width: clamp(28px, 4vw, 72px);
  height: 1px;
  background: currentColor;
  opacity: 0.45;
  transform-origin: left;
  transform: scaleX(0);
  transition: transform var(--dur-l) var(--ease) 0.1s;
}
.is-inview .eyebrow::before, .eyebrow.is-inview::before { transform: scaleX(1); }

.skip {
  position: fixed;
  top: 0; left: 50%;
  transform: translate(-50%, -140%);
  z-index: 999;
  background: var(--accent);
  color: var(--selection-fg);
  padding: 0.7rem 1.3rem;
  border-radius: 0 0 12px 12px;
  font-family: var(--font-mono);
  font-size: var(--t-mono);
  text-transform: uppercase;
  letter-spacing: var(--tr-wide);
  transition: transform var(--dur-s) var(--ease);
}
.skip:focus-visible { transform: translate(-50%, 0); }

.sr-only {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}

/* =========================================================
   BUTTONS
   ========================================================= */

.btn {
  --btn-bg: var(--fg);
  --btn-fg: var(--bg);
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.75em;
  padding: 1.05em 1.9em;
  border-radius: 100px;
  background: var(--btn-bg);
  color: var(--btn-fg);
  font-family: var(--font-mono);
  font-size: var(--t-mono);
  letter-spacing: var(--tr-wide);
  text-transform: uppercase;
  overflow: hidden;
  isolation: isolate;
  will-change: transform;
}
/* The fill that swipes up from the bottom on hover */
.btn::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: var(--accent);
  transform: translateY(101%);
  transition: transform var(--dur-m) var(--ease);
}
.btn:hover::before, .btn:focus-visible::before { transform: translateY(0); }
.btn:hover, .btn:focus-visible { color: var(--selection-fg); }

.btn--ghost {
  --btn-bg: transparent;
  --btn-fg: var(--fg);
  border: 1px solid var(--line);
}
.btn--lg { padding: 1.3em 2.4em; font-size: clamp(0.7rem, 0.6rem + 0.3vw, 0.85rem); }

.btn__ico {
  display: inline-block;
  transition: transform var(--dur-s) var(--ease);
}
.btn:hover .btn__ico { transform: translate(4px, -4px); }

/* Text link with a line that wipes left→right */
.link {
  position: relative;
  display: inline-block;
  padding-bottom: 2px;
}
.link::after {
  content: "";
  position: absolute;
  left: 0; bottom: 0;
  width: 100%; height: 1px;
  background: currentColor;
  transform: scaleX(0);
  transform-origin: right;
  transition: transform var(--dur-m) var(--ease);
}
.link:hover::after, .link:focus-visible::after { transform: scaleX(1); transform-origin: left; }

/* Label that swaps for a copy of itself sliding in from below */
.swap {
  position: relative;
  display: inline-block;
  overflow: hidden;
  vertical-align: bottom;
}
.swap span {
  display: block;
  transition: transform var(--dur-m) var(--ease);
}
.swap span:last-child {
  position: absolute;
  inset: 0;
  transform: translateY(105%);
}
.swap:hover span, a:hover .swap span, button:hover .swap span { transform: translateY(-105%); }
.swap:hover span:last-child, a:hover .swap span:last-child, button:hover .swap span:last-child { transform: translateY(0); }

/* =========================================================
   REVEAL PRIMITIVES — driven by IntersectionObserver (.is-inview)
   ========================================================= */

/* JS wraps every word in .word (the clipping box) with the word
   itself inside. The padding/margin pairs keep descenders AND the
   Spanish accents (á é í ó ú ñ) visible, while leaving the baseline
   where the browser expects it. */
.split .word {
  display: inline-block;
  overflow: hidden;
  padding-top: 0.2em;
  margin-top: -0.2em;
  padding-bottom: 0.16em;
  margin-bottom: -0.16em;
}
.split .word > span {
  display: inline-block;
  transform: translateY(115%) rotate(3deg);
  opacity: 0;
  transform-origin: left top;
  transition:
    transform var(--dur-l) var(--ease),
    opacity var(--dur-m) linear;
  transition-delay: calc(var(--i, 0) * 42ms);
}
.is-inview.split .word > span,
.is-inview .split .word > span { transform: none; opacity: 1; }

[data-reveal] {
  opacity: 0;
  transform: translateY(38px);
  transition:
    opacity var(--dur-l) var(--ease),
    transform var(--dur-l) var(--ease);
  transition-delay: var(--d, 0ms);
}
[data-reveal="fade"] { transform: none; }
[data-reveal="left"]  { transform: translateX(-38px); }
[data-reveal="right"] { transform: translateX(38px); }
[data-reveal="scale"] { transform: scale(0.94); }
[data-reveal].is-inview { opacity: 1; transform: none; }

/* Image that uncovers itself while the inner picture un-zooms */
.mask { overflow: hidden; position: relative; }
.mask > img, .mask > video {
  width: 100%;
  transform: scale(1.28);
  transition: transform var(--dur-xl) var(--ease);
}
.mask::after {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--bg);
  transform-origin: bottom;
  transition: transform var(--dur-xl) var(--ease);
}
.mask.is-inview > img, .mask.is-inview > video { transform: scale(1); }
.mask.is-inview::after { transform: scaleY(0); }

/* Hairline that draws itself */
.rule {
  height: 1px;
  background: var(--line);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform var(--dur-xl) var(--ease);
}
.rule.is-inview { transform: scaleX(1); }

/* =========================================================
   FILM GRAIN + SCROLL PROGRESS
   ========================================================= */

.grain {
  position: fixed;
  inset: -150%;
  z-index: 900;
  pointer-events: none;
  opacity: 0.032;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='300' height='300'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  animation: grain 6s steps(6) infinite;
}
@keyframes grain {
  0%   { transform: translate(0, 0); }
  20%  { transform: translate(-3%, 4%); }
  40%  { transform: translate(2%, -5%); }
  60%  { transform: translate(-4%, -2%); }
  80%  { transform: translate(5%, 3%); }
  100% { transform: translate(0, 0); }
}

.progress {
  position: fixed;
  top: 0; left: 0;
  width: 100%;
  height: 2px;
  z-index: 850;
  pointer-events: none;
}
.progress span {
  display: block;
  height: 100%;
  width: 100%;
  background: var(--accent);
  transform: scaleX(0);
  transform-origin: left;
}

/* =========================================================
   REDUCED MOTION — everything above becomes a plain page.
   ========================================================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  [data-reveal], .split .word > span { opacity: 1 !important; transform: none !important; }
  .mask::after { display: none; }
  .mask > img { transform: none; }
  .rule { transform: scaleX(1); }
  .grain { display: none; }
}
