/* ==========================================================================
   ziflo.es - fundamentos
   Tokens, tipografia, reset y primitivas compartidas por todas las paginas.
   Tema unico: oscuro. Acento unico: --accent.
   ========================================================================== */

/* --- Tipografia autoalojada (sin peticiones a terceros) ------------------ */

@font-face {
  font-family: "Geist";
  src: url("../fonts/Geist-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

@font-face {
  font-family: "Geist Mono";
  src: url("../fonts/GeistMono-Variable.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}

/* --- Tokens -------------------------------------------------------------- */

:root {
  /* Blanco y negro puro. Grises neutros, sin tinte de color.
     Escala unica, de mas oscura a mas clara. */
  --ink: #0d0d0d;
  --surface: #151515;
  --surface-2: #1c1c1c;
  /* --line separa bloques y puede ser tenue.
     --line-strong dibuja el contorno de controles (campos, botones fantasma,
     iconos enmarcados) y por eso llega a 3:1 contra el fondo, que es lo que
     pide la WCAG 1.4.11 para elementos de interfaz. El relleno de un campo
     casi no se distingue de la pagina, asi que el borde es lo unico que le
     dice al usuario donde puede escribir. */
  --line: #262626;
  --line-strong: #666666;

  /* Texto */
  --text: #f2f2f2;
  --text-dim: #a8a8a8;
  --text-faint: #8a8a8a;

  /* Rojo: el unico color del sitio. Se reserva para lo que hay que destacar
     (marca, acciones, enlaces, foco y estados de error) y no se usa para
     decorar. Dos tonos porque el contraste que exige AA no es el mismo
     sobre fondo oscuro que debajo de texto blanco:
       --accent        texto e iconos sobre el fondo   4.9:1
       --accent-strong fondo de boton con texto blanco 5.1:1 */
  --accent: #e5484d;
  --accent-strong: #cf2f36;
  --accent-hover: #b9242c;
  --accent-wash: rgba(229, 72, 77, 0.09);
  --signal: var(--accent);

  /* Radio unico: todo lo rectangular usa --r, los controles usan --r-sm. */
  --r: 14px;
  --r-sm: 8px;

  /* Ritmo vertical */
  --gap: clamp(1rem, 2vw, 1.5rem);
  --section-y: clamp(5rem, 11vh, 8.5rem);
  --shell: 1320px;
  --pad-x: clamp(1.25rem, 5vw, 4.5rem);

  /* Curva de movimiento compartida */
  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  --font-sans: "Geist", ui-sans-serif, system-ui, -apple-system,
    "Segoe UI Variable Display", "Segoe UI", Roboto, Arial, sans-serif;
  --font-mono: "Geist Mono", ui-monospace, "Cascadia Code", "SF Mono",
    "JetBrains Mono", Menlo, Consolas, monospace;

  color-scheme: dark;
}

/* --- Reset --------------------------------------------------------------- */

*,
*::before,
*::after {
  box-sizing: border-box;
}

* {
  margin: 0;
}

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
}

body {
  background: var(--ink);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: 1rem;
  line-height: 1.6;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img,
svg,
video {
  display: block;
  max-width: 100%;
}

img {
  height: auto;
}

input,
button,
textarea,
select {
  font: inherit;
  color: inherit;
}

button {
  background: none;
  border: none;
  cursor: pointer;
}

ul,
ol {
  list-style: none;
  padding: 0;
}

a {
  color: inherit;
  text-decoration: none;
}

h1,
h2,
h3,
h4 {
  font-weight: 560;
  letter-spacing: -0.025em;
  line-height: 1.08;
  text-wrap: balance;
}

p {
  text-wrap: pretty;
}

/* Foco visible y consistente en todo el sitio. */
:focus-visible {
  outline: 2px solid var(--signal);
  outline-offset: 3px;
  border-radius: 3px;
}

::selection {
  background: var(--accent-strong);
  color: #ffffff;
}

/* --- Utilidades ---------------------------------------------------------- */

.shell {
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--pad-x);
}

.section {
  padding-block: var(--section-y);
}

/* Ritmo vertical desigual a proposito.
   Cuando todas las secciones respiran exactamente igual, la pagina se lee
   como una plantilla rellenada. En una web compuesta a mano unos bloques
   aprietan y otros se abren, segun lo que pesa cada uno. */
.section--apretada {
  padding-block: calc(var(--section-y) * 0.62);
}

.section--amplia {
  padding-block: calc(var(--section-y) * 1.3);
}

.mono {
  font-family: var(--font-mono);
  font-size: 0.78rem;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--text-faint);
}

.lede {
  font-size: clamp(1.05rem, 1.6vw, 1.25rem);
  color: var(--text-dim);
  max-width: 62ch;
  line-height: 1.65;
}

.rule {
  border: 0;
  border-top: 1px solid var(--line);
}

.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
}

.skip-link {
  position: absolute;
  top: 0;
  left: 50%;
  translate: -50% -110%;
  z-index: 100;
  background: var(--accent-strong);
  color: #ffffff;
  font-weight: 600;
  padding: 0.7rem 1.25rem;
  border-radius: 0 0 var(--r-sm) var(--r-sm);
  transition: translate 0.2s var(--ease);
}

.skip-link:focus-visible {
  translate: -50% 0;
}

/* --- Botones ------------------------------------------------------------- */

.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.55rem;
  white-space: nowrap; /* una CTA nunca parte en dos lineas */
  padding: 0.85rem 1.5rem;
  border-radius: var(--r-sm);
  font-size: 0.94rem;
  font-weight: 560;
  letter-spacing: -0.01em;
  border: 1px solid transparent;
  transition: background-color 0.2s var(--ease), border-color 0.2s var(--ease),
    color 0.2s var(--ease), translate 0.12s var(--ease);
}

.btn svg {
  width: 1.05em;
  height: 1.05em;
  flex: none;
}

/* Rojo solido con texto blanco. Al pasar por encima oscurece, que sube el
   contraste en lugar de bajarlo. */
.btn--primary {
  background: var(--accent-strong);
  color: #ffffff;
}

.btn--primary:hover {
  background: var(--accent-hover);
}

.btn--ghost {
  border-color: var(--line-strong);
  color: var(--text);
}

.btn--ghost:hover {
  border-color: var(--text-dim);
  background: rgba(255, 255, 255, 0.035);
}

.btn:active {
  translate: 0 1px;
}

/* Enlace de texto con subrayado que crece al pasar por encima. */
.link {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  color: var(--signal);
  font-weight: 500;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0% 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size 0.3s var(--ease);
}

.link:hover {
  background-size: 100% 1px;
}

.link svg {
  width: 1em;
  height: 1em;
  flex: none;
}

/* --- Cabecera ------------------------------------------------------------ */

.masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  height: 68px;
  display: flex;
  align-items: center;
  background: color-mix(in srgb, var(--ink) 82%, transparent);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid transparent;
  transition: border-color 0.3s var(--ease);
}

.masthead[data-scrolled="true"] {
  border-bottom-color: var(--line);
}

@media (prefers-reduced-transparency: reduce) {
  .masthead {
    background: var(--ink);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
  }
}

.masthead__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2rem;
  width: 100%;
  max-width: var(--shell);
  margin-inline: auto;
  padding-inline: var(--pad-x);
}

.wordmark {
  font-size: 1.32rem;
  font-weight: 650;
  letter-spacing: -0.04em;
  flex: none;
}

/* El punto va algo despegado de la "o": es una marca, no un signo de
   puntuacion, y pegado se lee como el final de una frase. */
.wordmark b {
  color: var(--accent);
  font-weight: inherit;
  margin-left: 0.11em;
}

.nav {
  display: flex;
  align-items: center;
  gap: clamp(1.1rem, 2.4vw, 2.1rem);
}

/* :not(.btn) es obligatorio. Sin el, ".nav a" gana por especificidad a
   ".btn--primary" y el boton de la barra se queda con el gris de los
   enlaces sobre el rojo: 2.15:1, muy por debajo de AA. */
.nav a:not(.btn) {
  font-size: 0.93rem;
  color: var(--text-dim);
  white-space: nowrap;
  transition: color 0.2s var(--ease);
}

.nav a:not(.btn):hover,
.nav a:not(.btn)[aria-current="page"] {
  color: var(--text);
}

.nav .btn {
  padding: 0.6rem 1.1rem;
  font-size: 0.88rem;
}

/* Debajo de 860px la navegacion pasa a un panel desplegable. */
.nav-toggle {
  display: none;
  width: 40px;
  height: 40px;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  color: var(--text);
}

.nav-toggle span {
  position: relative;
  display: block;
  width: 17px;
  height: 1.5px;
  background: currentColor;
  transition: background-color 0.2s var(--ease);
}

.nav-toggle span::before,
.nav-toggle span::after {
  content: "";
  position: absolute;
  left: 0;
  width: 17px;
  height: 1.5px;
  background: currentColor;
  transition: translate 0.25s var(--ease), rotate 0.25s var(--ease);
}

.nav-toggle span::before {
  translate: 0 -5.5px;
}

.nav-toggle span::after {
  translate: 0 5.5px;
}

.nav-toggle[aria-expanded="true"] span {
  background: transparent;
}

.nav-toggle[aria-expanded="true"] span::before {
  translate: 0 0;
  rotate: 45deg;
}

.nav-toggle[aria-expanded="true"] span::after {
  translate: 0 0;
  rotate: -45deg;
}

@media (max-width: 860px) {
  .nav-toggle {
    display: flex;
  }

  .nav {
    position: fixed;
    inset: 68px 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--line);
    padding: 0.5rem var(--pad-x) 1.5rem;
    display: none;
  }

  .nav[data-open="true"] {
    display: flex;
  }

  .nav a {
    padding-block: 0.95rem;
    border-bottom: 1px solid var(--line);
    font-size: 1.02rem;
  }

  .nav .btn {
    margin-top: 1.15rem;
    justify-content: center;
    padding-block: 0.85rem;
    font-size: 0.95rem;
    border-bottom: none;
  }
}

/* --- Pie ----------------------------------------------------------------- */

.footer {
  border-top: 1px solid var(--line);
  padding-block: 3.5rem 2.5rem;
  margin-top: auto;
}

.footer__grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr;
  gap: 3rem;
  align-items: start;
}

.footer__blurb {
  color: var(--text-faint);
  font-size: 0.9rem;
  max-width: 34ch;
  margin-top: 1rem;
}

.footer__col h3 {
  font-size: 0.78rem;
  font-family: var(--font-mono);
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--text-faint);
  font-weight: 500;
  margin-bottom: 1.1rem;
}

.footer__col li + li {
  margin-top: 0.6rem;
}

.footer__col a {
  font-size: 0.93rem;
  color: var(--text-dim);
  transition: color 0.2s var(--ease);
}

.footer__col a:hover {
  color: var(--text);
}

.footer__base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  margin-top: 3.5rem;
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
  font-size: 0.83rem;
  color: var(--text-faint);
}

@media (max-width: 760px) {
  .footer__grid {
    grid-template-columns: 1fr;
    gap: 2.25rem;
  }
}

/* --- Transiciones entre paginas ------------------------------------------- */
/*
   API nativa de transiciones de vista. Al pasar de una pagina a otra el
   navegador funde ambas en lugar del parpadeo en blanco de siempre.

   Son doce lineas de CSS, sin una sola libreria. Los navegadores que todavia
   no la soportan ignoran el bloque entero y navegan como siempre: no hay nada
   que degradar a mano ni que detectar por JavaScript.

   La cabecera y el logotipo llevan view-transition-name propio, asi que se
   mantienen fijos mientras el resto de la pagina cambia. Ese detalle es el
   que hace que parezca una aplicacion y no una web recargando.
*/

@view-transition {
  navigation: auto;
}

@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root) {
    animation: vt-salir 0.22s cubic-bezier(0.4, 0, 1, 1) both;
  }

  ::view-transition-new(root) {
    animation: vt-entrar 0.32s var(--ease) both;
  }
}

@keyframes vt-salir {
  to {
    opacity: 0;
    translate: 0 -8px;
  }
}

@keyframes vt-entrar {
  from {
    opacity: 0;
    translate: 0 12px;
  }
}

/* La barra superior no participa: se queda quieta mientras cambia el resto. */
.masthead {
  view-transition-name: masthead;
}

/* --- Barra de progreso de lectura ----------------------------------------- */
/*
   Una linea roja arriba que avanza segun bajas por la pagina.

   No lleva una sola linea de JavaScript: animation-timeline: scroll() ata la
   animacion a la barra de desplazamiento del documento. El navegador la
   ejecuta fuera del hilo principal, asi que no compite con nada y no puede
   provocar tirones aunque la pagina este ocupada.

   El elemento lo crea site.js, de modo que si no hay JavaScript sencillamente
   no aparece y no estorba.
*/

.progreso {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 60;
  height: 2px;
  width: 100%;
  transform-origin: 0 50%;
  scale: 0 1;
  background: linear-gradient(90deg, var(--accent-strong), var(--accent));
  pointer-events: none;
}

@supports (animation-timeline: scroll()) {
  @media (prefers-reduced-motion: no-preference) {
    .progreso {
      animation: avanzar linear both;
      animation-timeline: scroll(root block);
    }
  }
}

@keyframes avanzar {
  to {
    scale: 1 1;
  }
}

/* --- Revelado al hacer scroll -------------------------------------------- */
/* Comunica jerarquia: el contenido entra en el orden en que se debe leer. */

/* El estado oculto depende de la clase "js", que solo anade el propio script.
   Si el JavaScript no llega a ejecutarse, esta regla no se aplica nunca y el
   contenido se ve sin mas. Ocultar por defecto y confiar en que algo lo
   muestre despues es la forma habitual de dejar una pagina en blanco. */
@media (prefers-reduced-motion: no-preference) {
  .js [data-reveal] {
    opacity: 0;
    translate: 0 18px;
    transition: opacity 0.7s var(--ease), translate 0.7s var(--ease);
    transition-delay: var(--reveal-delay, 0ms);
  }

  .js [data-reveal][data-shown="true"] {
    opacity: 1;
    translate: 0 0;
  }
}

/*
   Version moderna del mismo revelado.

   Donde el navegador soporta animation-timeline: view(), la aparicion deja de
   depender del observador de JavaScript y pasa a ir atada a la posicion del
   elemento en la pantalla. La diferencia se nota: en lugar de dispararse de
   golpe al cruzar un umbral, el bloque acompana al scroll, y la animacion se
   ejecuta fuera del hilo principal.

   El observador de site.js sigue ahi para los navegadores que no lo soportan.
   Aqui se anula su transicion para que no compitan por las mismas propiedades.
*/
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .js [data-reveal] {
      opacity: 1;
      translate: none;
      transition: none;
      animation: revelar linear both;
      animation-timeline: view();
      animation-range: entry 4% cover 26%;
    }
  }
}

@keyframes revelar {
  from {
    opacity: 0;
    translate: 0 26px;
  }
  to {
    opacity: 1;
    translate: 0 0;
  }
}
