/* ===========================================================================
   IDC Studios · web — sistema IDC «Nocturno»
   Los mismos tokens del launcher de las apps, de los vídeos
   (Video App Francos/videos/francos-9x16/frame.md) y de la maqueta de
   Grupos Padel (Trabajos Externos/Grupos Padel Web/assets/css/idc.css).

   Ley del color: dice ESTADO, no decora.
     azul  (accent) → lo que el ojo tiene que encontrar primero / lo tuyo
     verde (ok)     → sólo «confirmado / está hecho / cabe»
     ámbar (warn)   → sólo «atención / pendiente / suspendida»
   Un cuarto color rompe el sistema.

   Fondo plano, tipografía grande, mucho aire y un solo acento: el peso lo
   lleva el texto, no las cajas. El movimiento va con una sola curva y una
   sola duración, y siempre sobre `transform` y `opacity` — nunca sobre
   propiedades que obliguen a recalcular el diseño.

   Este archivo son los TOKENS y las piezas comunes. Lo propio de las
   secciones de la web está en sitio.css.
   =========================================================================== */

:root {
  --bg-deep: #04060a;
  --bg: #070a0f;
  --bg-lift: #0a0e16;
  --panel: #121822;
  --panel-2: #1b222c;
  --chassis: #2c3542;
  --ink: #f2f6fd;
  --ink-2: #e7eefb;
  --muted: #93a3bd;
  --muted-2: #7b8ca6;
  --line: rgba(140, 170, 215, 0.22);
  --line-faint: rgba(140, 170, 215, 0.13);
  --accent: #4f8cff;
  --accent-deep: #3c74e8;
  --accent-soft: rgba(79, 140, 255, 0.14);
  --ok: #22d3a6;
  --ok-soft: rgba(34, 211, 166, 0.13);
  --warn: #f5a524;
  --warn-soft: rgba(245, 165, 36, 0.13);

  /* La piel de la versión 2 de la marca (Iván, 6-oct-2026: «la 1, casi tal
     cual, con el relieve de la 2 y el juego de colores»). Se SUMA a Nocturno:
     los colores de estado no cambian. El champán nunca es un estado: es un
     filete, un punto final, la palabra clave. Mismos valores que
     `tokens/idc-v2.css` del manual de marca. */
  --noche: #0b1a33;
  --vidrio: #3b7bff;
  --vidrio-claro: #9cc0ff;
  --champan: #c8a977;
  --champan-claro: #e6d3ad;

  --f-display: "Outfit", "Segoe UI", system-ui, sans-serif;
  --f-body: "Inter", "Segoe UI", system-ui, sans-serif;
  --f-mono: "JetBrains Mono", ui-monospace, "Cascadia Mono", Consolas, monospace;
  /* Newsreader: lo que se lee con calma (la palabra clave, la cita, las
     cifras grandes). Outfit sigue en el logotipo y los títulos de pantalla. */
  --f-editorial: "Newsreader", Georgia, "Times New Roman", serif;

  /* Un radio grande y constante en todo: 20 px. */
  --r: 20px;
  --r-chico: 12px;
  --r-chip: 999px;

  /* El aire. A 320 px, 40 px de margen a cada lado dejan la línea sin sitio,
     así que el mínimo baja a 22 y el máximo sube a 56 en pantalla grande. */
  --edge: clamp(22px, 5vw, 56px);
  --aire: clamp(64px, 9vw, 136px);
  --ancho: 1240px;
  --barra-h: 64px;

  /* Una sola curva y una sola duración para todo lo que se toca. */
  --ease: cubic-bezier(.4, 0, .1, 1);
  --ease-out: cubic-bezier(.35, 0, 0, 1);
  --dur: .3s;
  --dur-corta: .18s;

  color-scheme: dark;
}

*, *::before, *::after { box-sizing: border-box; }
/* El ancla queda bajo la barra. Cada sección además lleva un
   `scroll-margin-top` NEGATIVO (sitio.css) que se come su propio aire, así
   el título queda justo debajo de la barra y no a media pantalla. */
html { scroll-behavior: smooth; scroll-padding-top: calc(var(--barra-h) + 8px); }
html, body { margin: 0; }
body {
  font-family: var(--f-body);
  font-size: 16px;
  line-height: 1.6;
  color: var(--ink-2);
  /* Plano. El único brillo es un velo muy tenue arriba, que no se mueve con
     el scroll (nada de `background-attachment: fixed`, que en un móvil
     cuesta un repintado por marco). */
  background: var(--bg);
  min-height: 100vh;
  overflow-x: hidden;
  -webkit-font-smoothing: antialiased;
}
/* El velo tenue de arriba va en `main` y no en `body`: `main` lleva fondo
   propio para poder deslizarse por encima del pie (ver `.pie` en sitio.css). */
main {
  background:
    radial-gradient(900px 480px at 18% -10%, rgba(79, 140, 255, .13), transparent 68%) no-repeat,
    var(--bg);
  /* Lo que vuela de lado (la tela de /trabajos) no ensancha el documento.
     `clip` y no `hidden`: no crea un contenedor de scroll, así que los
     `sticky` y los pines de ScrollTrigger siguen pegados a la ventana. */
  overflow-x: clip;
}

img { max-width: 100%; height: auto; }
a { color: var(--accent); text-underline-offset: 3px; }
a:hover { color: #85afff; }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; border-radius: 6px; }
[hidden] { display: none !important; }
::selection { background: rgba(79, 140, 255, .28); color: var(--ink); }

/* sólo para lectores de pantalla */
.solo-lectores {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip: rect(0 0 0 0); white-space: nowrap;
}
/* el salto al contenido: invisible hasta que se le da el foco con el tabulador */
.saltar {
  position: absolute; left: 12px; top: -100px; z-index: 100;
  background: var(--panel-2); color: var(--ink); border: 1px solid var(--accent);
  border-radius: var(--r-chico); padding: 10px 16px; font-weight: 600; text-decoration: none;
  transition: transform var(--dur-corta) var(--ease);
}
.saltar:focus { top: 12px; }

/* ---------------------------------------------------------------- tipografía */
.eyebrow {
  font-family: var(--f-mono); font-weight: 500; font-size: 12px;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--accent);
  margin: 0 0 18px;
}
.eyebrow--muted { color: var(--muted); }
h1, h2, h3 { font-family: var(--f-display); color: var(--ink); text-wrap: balance; }
/* El titular de la portada es la pieza principal de la página: grande de
   verdad, y con muy poco alrededor. */
h1 {
  font-weight: 600; font-size: clamp(38px, 8.2vw, 104px); line-height: 0.98;
  letter-spacing: -0.035em; margin: 0 0 24px;
}
h2 {
  font-weight: 600; font-size: clamp(27px, 4.6vw, 52px); line-height: 1.04;
  letter-spacing: -0.03em; margin: 0 0 16px;
}
h3 {
  font-weight: 600; font-size: clamp(17px, 1.5vw, 20px); line-height: 1.25;
  margin: 0 0 8px; letter-spacing: -0.015em;
}
/* La palabra clave de un titular (`*así*` en contenido.js, ver app.js): en
   Newsreader cursiva y en champán. Una por titular. */
h1 em, h2 em, h3 em {
  font-family: var(--f-editorial); font-style: italic; font-weight: 400;
  color: var(--champan); letter-spacing: -0.01em;
}
/* El punto final en champán (app.js `puntos()` lo envuelve en los h2). */
.punto { color: var(--champan); }
/* El filete champán bajo el título de cada sección. Va en ::after para no
   tocar el HTML; el alto entra en la caja del título, así que nada que
   mida la sección después se descuadra. */
.seccion__cab h1::after, main h2[id^="t-"]:not(.solo-lectores)::after {
  content: ""; display: block; width: 64px; height: 1.5px; margin-top: .42em;
  background: var(--champan); border-radius: 1px;
}
p { margin: 0 0 16px; }
.lead { color: var(--muted); font-size: clamp(16.5px, 1.5vw, 20px); line-height: 1.55; max-width: 54ch; }
.chica { font-size: 13.5px; }
.muted { color: var(--muted); }
.mono { font-family: var(--f-mono); font-variant-numeric: tabular-nums; }

/* ---------------------------------------------------------------- marca */
.marca { display: inline-flex; align-items: center; gap: 12px; text-decoration: none; color: var(--ink); }
.marca__idc {
  font-family: var(--f-display); font-weight: 600; letter-spacing: 0.42em;
  font-size: 14px; color: var(--ink);
}
.marca__studios { margin-left: 0.1em; letter-spacing: 0.06em; font-weight: 500; color: var(--ink-2); }
/* el logotipo de celdas: el mismo de la maqueta de Grupos Padel */
.celdas { display: grid; grid-template-columns: repeat(4, 7px); gap: 3px; flex: none; }
.celdas i { width: 7px; height: 5px; border-radius: 1.5px; background: #202b3c; display: block; }
.celdas i.a { background: #3f74d8; }
.celdas i.o { background: #1c9a80; }

/* ---------------------------------------------------------------- superficies */
.ventana {
  background: var(--panel);
  border: 1px solid var(--line-faint);
  border-radius: var(--r);
}
.caja { padding: clamp(20px, 3vw, 30px); }
.sep { height: 1px; background: var(--line-faint); border: 0; margin: 0; }

/* ---------------------------------------------------------------- botones */
/* `--imx`/`--imy` los escribe el imán de efectos.js; `--lift` es el hover.
   Van juntos en un solo `transform` para que no se pisen. */
.btn {
  --imx: 0px; --imy: 0px; --lift: 0px;
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 50px; padding: 0 24px; border-radius: var(--r-chip);
  border: 1px solid var(--line); background: transparent; color: var(--ink); cursor: pointer;
  font-family: var(--f-body); font-weight: 500; font-size: 15px;
  text-decoration: none;
  transform: translate3d(var(--imx), calc(var(--imy) + var(--lift)), 0);
  transition: transform var(--dur) var(--ease), border-color var(--dur) var(--ease),
              background-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.btn:hover { border-color: rgba(140, 170, 215, .5); color: var(--ink); --lift: -3px; }
.btn:active { --lift: 0px; }
/* El botón principal es de VIDRIO, como las celdas del logo de la v2: la
   cara en degradé, un brillo arriba y el canto abajo. El degradé va de
   #8db4ff a #4f8cff para que el texto oscuro mida más de 6:1 en toda la
   cara (con el azul hondo del logo bajaba a 3,2:1). */
.btn--cta {
  background: linear-gradient(180deg, #8db4ff 0%, #6a9dff 45%, #4f8cff 100%);
  border-color: #4f8cff; color: #04060a; font-weight: 600;
  box-shadow: inset 0 1px 0 rgba(255, 255, 255, .45), 0 2px 0 #2d5bae,
              0 10px 22px -12px rgba(59, 123, 255, .7);
}
.btn--cta:hover {
  background: linear-gradient(180deg, #a6c4ff 0%, #7eaaff 45%, #5f97ff 100%);
  border-color: #5f97ff; color: #04060a;
}
.btn--chico { min-height: 42px; padding: 0 17px; font-size: 14px; }
.btn svg { width: 17px; height: 17px; flex: none; }
.acciones { display: flex; gap: 12px; flex-wrap: wrap; align-items: center; }

/* ---------------------------------------------------------------- chips de estado */
.chip {
  display: inline-flex; align-items: center; gap: 7px; padding: 4px 12px; border-radius: var(--r-chip);
  font-family: var(--f-mono); font-size: 11.5px; letter-spacing: .04em; font-weight: 500;
  border: 1px solid var(--line); color: var(--muted); white-space: nowrap;
}
.chip::before { content: ""; width: 6px; height: 6px; border-radius: 50%; background: currentColor; flex: none; }
.chip--ok { color: var(--ok); border-color: rgba(34, 211, 166, .3); background: var(--ok-soft); }
.chip--warn { color: var(--warn); border-color: rgba(245, 165, 36, .3); background: var(--warn-soft); }
.chip--accent { color: var(--accent); border-color: rgba(79, 140, 255, .35); background: var(--accent-soft); }
/* el sello de «esto son datos inventados» */
.ejemplo {
  display: inline-block; font-family: var(--f-mono); font-size: 11.5px; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted); border: 1px dashed var(--line);
  border-radius: var(--r-chip); padding: 4px 11px;
}

/* ---------------------------------------------------------------- campos */
.campo { display: grid; gap: 8px; }
.campo > span { font-size: 14px; color: var(--muted); font-weight: 500; }
.campo input, .campo textarea {
  background: var(--bg-lift); border: 1px solid var(--line); border-radius: var(--r-chico);
  padding: 12px 15px; min-height: 50px; color: var(--ink);
  font-family: var(--f-body); font-size: 16px; width: 100%;
  transition: border-color var(--dur-corta) var(--ease);
}
.campo textarea { min-height: 130px; resize: vertical; line-height: 1.55; }
.campo input::placeholder, .campo textarea::placeholder { color: var(--muted-2); }
.campo input:focus, .campo textarea:focus {
  border-color: var(--accent); outline: none; box-shadow: 0 0 0 3px var(--accent-soft);
}

/* ============================================================== movimiento
   Las entradas al hacer scroll.

   El estado de partida «escondido» SÓLO existe bajo `.anima`, que pone un
   script en el <head> y únicamente si hay JavaScript y no hay
   `prefers-reduced-motion`. Sin JavaScript, con el script roto o con el
   movimiento apagado, el suelo es lo visible: el contenido está ahí, entero
   y sin esperar nada. */
[data-reveal] { opacity: 1; transform: none; }
/* `quieta` la pone efectos.js cuando una red salta (el reloj de las
   animaciones no avanza: captura, vista previa, pestaña dormida). Quitar
   `anima` a secas no alcanzaba: disparaba OTRA transición de invisible a
   visible que, con el reloj parado, tampoco terminaba nunca. Medido en
   /trabajos: filas a opacidad 0,001 con `anima` ya quitada. Con `quieta`,
   todo salta a su estado final en el acto. */
html.quieta *, html.quieta *::before, html.quieta *::after {
  transition-duration: 0s !important; transition-delay: 0s !important;
  animation-duration: 0s !important; animation-delay: 0s !important;
}
.anima [data-reveal] {
  opacity: 0.001;
  transform: translate3d(0, 18px, 0);
  transition: opacity .4s var(--ease-out), transform .4s var(--ease-out);
}
.anima [data-reveal].es-visible { opacity: 1; transform: none; }
/* En una lista, cada elemento entra un pelo después que el anterior. Tres
   escalones y basta: más es una cortina. */
.anima [data-reveal]:nth-child(2) { transition-delay: .06s; }
.anima [data-reveal]:nth-child(3) { transition-delay: .12s; }
.anima [data-reveal]:nth-child(n+4) { transition-delay: .18s; }

/* ------------------------------------------------ el titular, por palabras
   Cada palabra sube desde debajo de su propia línea. El HTML lo parte
   efectos.js; el texto no cambia, así que un lector de pantalla oye lo
   mismo. Sin JavaScript nada de esto existe y el titular está entero. */
/* La caja que recorta NO puede tocar el diseño: sin relleno y sin márgenes,
   cada palabra ocupa exactamente lo que ocuparía sin partir. Para que los
   rabos de las letras no se corten, el recorte se agranda con
   `overflow-clip-margin`, que amplía la zona recortada SIN mover nada.

   (Antes esto era `overflow:hidden` + relleno + margen negativo. Con la
   tipografía de la marca medía bien, pero basta con que Google Fonts tarde
   y entre la de respaldo para que la caja deje de medir lo que mide la
   tinta y el titular se escriba encima del párrafo de abajo. Un margen
   negativo no puede ser lo que sostiene un titular.) */
.partido .pal {
  display: inline-block; vertical-align: bottom;
  overflow: clip; overflow-clip-margin: .24em;
}
/* Respaldo para quien no tenga `overflow-clip-margin` (Safari): recorta al
   borde, que como mucho come un rabo de letra, nunca el diseño. */
@supports not (overflow-clip-margin: .24em) {
  .partido .pal { overflow: hidden; }
}
.partido .pal > span { display: block; }
/* El titular está VISIBLE por defecto y la animación es lo que se agrega:
   una palabra sin animar se lee igual. Lo contrario —esconderla y esperar a
   que algo la revele— deja el titular en blanco cada vez que la animación no
   llega a correr (una captura, una pestaña en segundo plano, un navegador
   que se salta la transición). Por eso va con `animation … both` y no con
   una transición desde un estado escondido. */
.anima .partido.es-visible .pal > span {
  animation: idc-sube-palabra .72s var(--ease-out) both;
  animation-delay: var(--retraso, 0ms);
}
@keyframes idc-sube-palabra {
  from { transform: translate3d(0, 140%, 0); }
  to { transform: none; }
}

/* ------------------------------------------------------- el aro del cursor
   Un aro con inercia y un punto exacto. REEMPLAZAN al cursor del sistema,
   pero sólo mientras efectos.js tiene puesto `html[data-cursor="propio"]`:
   lo pone con el aro ya colocado bajo el puntero y lo quita en cuanto el
   puntero sale de la ventana, la pestaña pierde el foco, llega un dedo o
   hay `prefers-reduced-motion`. Sobre un campo de texto se ve el cursor de
   escribir del sistema y el aro se esconde. */
.aro, .aro-punto {
  position: fixed; left: 0; top: 0; z-index: 90;
  pointer-events: none; opacity: 0; will-change: transform;
}
.aro {
  width: 36px; height: 36px;
  border: 1px solid rgba(79, 140, 255, .6); border-radius: 50%;
  transition: opacity .3s var(--ease), width .3s var(--ease), height .3s var(--ease),
              border-color .3s var(--ease), background-color .3s var(--ease);
}
.aro-punto { width: 6px; height: 6px; border-radius: 50%; background: var(--ink); transition: opacity .3s var(--ease); }
.aro.es-visible, .aro-punto.es-visible { opacity: 1; }
.aro.es-grande { background: rgba(79, 140, 255, .1); border-color: rgba(79, 140, 255, .9); }
html[data-cursor="propio"], html[data-cursor="propio"] * { cursor: none !important; }
html[data-cursor="propio"] :is(input, textarea, select) { cursor: auto !important; }
.aro[data-modo="campo"] { opacity: 0; }

/* ------------------------------------------------- el brillo de lo que se toca
   Un punto de luz que sigue al puntero por dentro del borde. Las variables
   las escribe efectos.js; sin JavaScript el elemento sigue teniendo su
   cambio de borde al pasar por encima, que es lo que hace falta. */
[data-brillo] { position: relative; isolation: isolate; }
[data-brillo]::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; z-index: -1;
  pointer-events: none; opacity: 0; transition: opacity var(--dur) var(--ease);
  background: radial-gradient(220px 180px at var(--bx, 50%) var(--by, 50%),
              rgba(79, 140, 255, .16), transparent 70%);
}
[data-brillo]:hover::after, [data-brillo]:focus-within::after { opacity: 1; }

/* ------------------------------------------------- el halo que sigue al ratón
   UNA capa fija que cubre el viewport entero, con un degradado radial
   centrado en el puntero (`--x`/`--y` los escribe efectos.js en un solo
   sitio). Antes era un foco por sección y moría en el borde de cada una.

   Va POR ENCIMA de todo y no por debajo, a propósito: las secciones
   apiladas llevan fondo opaco (si no, la de abajo se vería a través de la
   que entra), y una capa por debajo quedaría tapada por ellas. Con
   `mix-blend-mode: screen` y esta intensidad el resultado es el mismo que
   una luz por debajo sobre un fondo oscuro: sobre el texto blanco no
   cambia nada (blanco con screen sigue siendo blanco) y ningún
   `overflow: hidden`, `isolation` ni `contain` puede recortarla. */
.halo {
  position: fixed; inset: 0; z-index: 80; pointer-events: none;
  mix-blend-mode: screen; opacity: 0; transition: opacity .5s var(--ease);
  background: radial-gradient(560px 460px at var(--x, 50%) var(--y, 50%),
              rgba(79, 140, 255, .11), transparent 70%);
}
.halo.es-visible { opacity: 1; }

/* ---------------------------------------------------- el grano del fondo
   Una capa finísima de ruido sobre el fondo plano. Es CSS puro, no cuesta
   un solo cuadro y no depende de JavaScript. */
body::after {
  content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
  opacity: .035; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml;utf8,\
<svg xmlns='http://www.w3.org/2000/svg' width='140' height='140'>\
<filter id='r'><feTurbulence type='fractalNoise' baseFrequency='.85' numOctaves='3'/></filter>\
<rect width='140' height='140' filter='url(%23r)'/></svg>");
}
body > * { position: relative; z-index: 1; }

/* ------------------------------------------------- el paso entre páginas
   Portada ↔ /trabajos. Es la View Transitions API entre documentos: donde
   no existe, el navegador navega como siempre y no se pierde nada. */
@view-transition { navigation: auto; }
::view-transition-old(root) { animation: idc-sale .26s var(--ease) both; }
::view-transition-new(root) { animation: idc-entra .34s var(--ease-out) both; }
@keyframes idc-sale { to { opacity: 0; transform: translate3d(0, -14px, 0); } }
@keyframes idc-entra { from { opacity: 0; transform: translate3d(0, 18px, 0); } }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important; animation-iteration-count: 1 !important;
    transition-duration: .001ms !important; scroll-behavior: auto !important;
  }
  [data-reveal], .anima [data-reveal] { opacity: 1 !important; transform: none !important; }
  .partido .pal > span { transform: none !important; animation: none !important; }
  .aro, .aro-punto, .halo { display: none !important; }
  html[data-cursor="propio"], html[data-cursor="propio"] * { cursor: auto !important; }
  ::view-transition-old(root), ::view-transition-new(root) { animation: none !important; }
}

/* ------------------------------------------------ el cursor, según qué hay
   El aro dice QUÉ tiene debajo: sobre una demo se agranda y se etiqueta,
   sobre una fila de proyecto dice «Ver», sobre la rejilla se hace un punto y
   sobre un texto se vuelve una barra fina, como un cursor de escritura.
   Cambia de forma y de tamaño; nada de iconos. */
.aro__texto {
  font-family: var(--f-mono); font-size: 11px; letter-spacing: .06em;
  color: #04060a; white-space: nowrap; opacity: 0;
  transition: opacity .2s var(--ease);
}
.aro[data-modo="ver"], .aro[data-modo="abrir"] {
  width: auto; height: 34px; min-width: 34px; padding: 0 16px; border-radius: 999px;
  background: var(--accent); border-color: var(--accent);
  display: grid; place-items: center;
}
.aro[data-modo="ver"] .aro__texto, .aro[data-modo="abrir"] .aro__texto { opacity: 1; }
.aro[data-modo="rejilla"] {
  width: 10px; height: 10px; background: var(--accent); border-color: transparent;
}
.aro[data-modo="texto"] {
  width: 3px; height: 28px; border-radius: 2px;
  background: rgba(79, 140, 255, .75); border-color: transparent;
}
