/* Estilos del sitio público.
   Los valores salen del tema de Flutter (lib/shared/theme/), para que el
   rediseño sea invisible: mismos colores, mismas medidas, mismas curvas.
   Las fuentes están subseteadas; ver docs/herramientas/subset_fuentes.js. */

@font-face {
  font-family: 'RobotoFlex';
  src: url('/fonts/robotoflex.woff2') format('woff2-variations');
  font-weight: 300 700;
  font-display: swap;
}

@font-face {
  font-family: 'BebasNeue';
  src: url('/fonts/bebasneue.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}

/* Las dos que siguen las usa solo el banner de la portada. Declararlas acá
   no cuesta nada en las demás páginas: un navegador descarga el archivo de
   una fuente recién cuando algo en la página la usa. Van subseteadas al juego
   «titulares» —letras, cifras y poca puntuación—, que es todo lo que puede
   aparecer en un apodo o en la etiqueta de un botón.

   El título del banner no usa ninguna: es un trazo, porque su tipografía es
   de Adobe Fonts y no se puede alojar acá. */

@font-face {
  font-family: 'Anton';
  src: url('/fonts/anton.woff2') format('woff2');
  font-weight: 400;
  font-display: swap;
}

@font-face {
  font-family: 'DarkerGrotesque';
  src: url('/fonts/darkergrotesque.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-display: swap;
}

:root {
  --bg: #0D0D0D;
  --surface: #1A1A1A;
  --elevated: #242424;
  --border: #2E2E2E;
  --text: #F0F0F0;
  --text-2: #8A8A8A;
  --muted: #4A4A4A;
  --accent: #E8E0D0;
  --accent-dim: #6B6358;
  /* El único color de «algo salió mal» del sitio público. Mismo valor que
     `AppColors.error` del panel, así el sitio y el panel no se contradicen. */
  --danger: #CF6679;

  --r-sm: 2px;
  --r-md: 4px;
  --wrap: 768px;
  --gutter: 24px;
  --ease: cubic-bezier(0, 0, 0.58, 1);
}

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--text);
  font-family: 'RobotoFlex', system-ui, sans-serif;
  font-size: 16px;
  line-height: 1.6;
  /* Deja lugar a la barra del reproductor cuando está visible. */
  padding-bottom: var(--player-space, 0);
}

img { max-width: 100%; }

a { color: var(--accent); }

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

.skip {
  position: absolute;
  left: -9999px;
}
.skip:focus {
  left: var(--gutter);
  top: 8px;
  z-index: 10;
  background: var(--elevated);
  padding: 8px 12px;
  border-radius: var(--r-md);
}

/* ── Encabezado ───────────────────────────────────────────────────────── */

.nav {
  display: flex;
  align-items: center;
  gap: 16px;
  height: 64px;
  padding: 0 48px;
  border-bottom: 1px solid var(--border);
}

.nav-logo {
  font-family: 'BebasNeue', sans-serif;
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 1px;
  color: var(--text);
  text-decoration: none;
  margin-right: auto;
}

.nav-links {
  display: flex;
  align-items: center;
  gap: 32px;
}

.nav-links a {
  color: var(--text-2);
  text-decoration: none;
  font-size: 14px;
  letter-spacing: 0.2px;
  transition: color 200ms var(--ease);
}
.nav-links a:hover { color: var(--text); }
.nav-links a.on { color: var(--accent); font-weight: 500; }

.lang { display: flex; align-items: center; font-size: 12px; }
.lang a {
  color: var(--muted);
  letter-spacing: 1px;
  text-decoration: none;
  font-size: 12px;
}
.lang a.on { color: var(--accent); font-weight: 600; }
.lang-sep { color: var(--muted); padding: 0 4px; }

.nav-toggle {
  display: none;
  background: none;
  border: 0;
  color: var(--text);
  padding: 8px;
  cursor: pointer;
}

@media (max-width: 1023px) {
  .nav { padding: 0 var(--gutter); height: 56px; }
  .nav-toggle { display: block; order: 3; }
  .nav-links {
    display: none;
    position: absolute;
    top: 56px;
    left: 0;
    right: 0;
    flex-direction: column;
    align-items: flex-start;
    gap: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 16px var(--gutter) 24px;
    z-index: 5;
  }
  .nav-links.open { display: flex; }
  .nav-links a { font-size: 20px; padding: 10px 0; color: var(--text); }
  .lang { padding-top: 12px; }
}

/* ── Portada ──────────────────────────────────────────────────────────── */

/* Dos mitades en escritorio: a la izquierda el nombre sobre la foto de la sala,
   a la derecha la foto. En teléfono se apila, texto arriba y foto abajo.

   La altura es la mitad de la ventana útil, no la ventana entera: así lo que
   sigue asoma por debajo y se ve que la página continúa. El recorte de la foto
   acompaña esa proporción, 1,62:1 en lugar del retrato que había. */
/* El alto sale del ancho, no de la ventana: cada mitad del banner mide
   960×592 en una pantalla de 1920, y esa proporción se mantiene en cualquier
   ancho. Es la medida que la foto ya trae, así que `cover` casi no recorta.
   El piso de 380 px es para ventanas angostas, donde la proporción sola deja
   el banner más bajo que el título y el botón.

   La cuenta va en el alto y NO como `aspect-ratio` con `min-height`. Esa
   combinación hace la cuenta al revés: cuando el mínimo gana, el navegador le
   deriva el ANCHO a partir del alto —380 × 1920/592 = 1232 px— y el banner
   sale más ancho que la ventana. En una tablet de 1024 eso era 208 px de
   barrido horizontal.

   Tampoco se deja que la decida la foto: `min-height` sobre un grid deja que
   la fila crezca con la imagen, y entonces manda la proporción del archivo
   sobre la hoja de estilos. */
.hero {
  position: relative;
  /* El 710 era 592 cuando la foto ocupaba media pantalla. A sangre completa la
     misma altura repartida sobre el doble de ancho se veía como una franja, así
     que el banner pasa del 30,8% al 37% del ancho de la ventana. */
  height: max(380px, calc(100vw * 710 / 1920));
  background-color: #000;
  overflow: hidden;
}

/* El ancho de la columna lo decide el botón, y el título se ajusta a él.

   Lo consigue el `width: 0` con `min-width: 100%` de abajo: así el título no
   cuenta para calcular el ancho de la columna —si contara, el dibujo, que es
   más ancho, mandaría— pero después ocupa todo lo que esa columna terminó
   midiendo. */
/* El bloque de texto se apoya sobre la foto, ocupando la mitad izquierda: es
   donde estaba cuando el banner eran dos columnas, y es la zona que las fotos
   dejan vacía a propósito. */
.hero-text {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  text-align: center;
  padding: 32px var(--gutter);
}

/* El nombre va dibujado: un trazo en PF Fuel Grime, que es de Adobe Fonts y
   no se puede servir como fuente web. El h1 lleva igual el texto real, oculto
   a la vista pero no a los buscadores ni a un lector de pantalla. Si el
   nombre del panel no coincide con el del dibujo, el texto se muestra y acá
   caen las reglas tipográficas de abajo. */
.hero-title {
  width: 0;
  min-width: 100%;
  font-family: 'BebasNeue', sans-serif;
  font-weight: 400;
  font-size: clamp(42px, 4.6vw, 78px);
  line-height: 0.92;
  letter-spacing: 1px;
  color: var(--text);
  margin: 0;
  /* El plano de fondo tiene zonas claras; sin esto el título pierde borde
     justo donde pasa una línea. */
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.75);
}

.hero-title svg {
  display: block;
  /* La mitad del ancho del bloque de texto, centrado. Ocupaba el ancho entero
     cuando el banner eran dos columnas y el trazo competía con la foto de al
     lado; sobre la foto a sangre completa quedaba desmedido. */
  width: 50%;
  margin-inline: auto;
  height: auto;
  /* La misma sombra que llevaba el texto, ahora sobre el dibujo. */
  filter: drop-shadow(0 2px 24px rgba(0, 0, 0, 0.75));
}

/* Oculto a la vista, presente para los buscadores y los lectores de
   pantalla. No se usa `display:none` ni `visibility:hidden`, que lo sacarían
   también de ahí. */
.vh {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

.hero-nick {
  font-family: 'Anton', sans-serif;
  font-size: clamp(18px, 1.5vw, 24px);
  letter-spacing: 0.5px;
  color: var(--text);
  margin: 8px 0 0;
  text-shadow: 0 2px 16px rgba(0, 0, 0, 0.75);
}

.hero-cta {
  display: inline-block;
  margin-top: 24px;
  padding: 11px 26px;
  font-family: 'DarkerGrotesque', sans-serif;
  font-size: 20px;
  font-weight: 500;
  letter-spacing: 0.3px;
  line-height: 1;
  color: var(--bg);
  background: var(--accent);
  border-radius: var(--r-sm);
  text-decoration: none;
  transition: background 200ms var(--ease), transform 200ms var(--ease);
}
.hero-cta:hover { background: #fff; }
.hero-cta:active { transform: translateY(1px); }

/* La foto es el fondo del banner: ocupa todo y el texto va encima. */
.hero-figure { display: block; position: absolute; inset: 0; }

.hero-photo {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* El recorte entra en marcos de proporciones distintas según la pantalla.
     Favorecer la parte de arriba deja siempre la cara dentro. */
  object-position: 50% 18%;
}

/* El banner arranca pegado al encabezado: la línea divisoria lo cortaría.
   Se consulta por el contenido y no por una clase en el body porque la
   navegación blanda reemplaza el <main> sin tocar el <body>; así la regla se
   enciende y se apaga sola al entrar y salir de la portada. */
body:has(.hero) .nav { border-bottom: 0; }

/* Lo último publicado, debajo del banner.

   El margen de arriba es amplio a propósito: pegado a la foto, el texto se
   leía como un pie de imagen en vez de como una sección aparte.

   Declaran su relleno entero en lugar de apoyarse en `.block`, porque esa
   clase lo define en forma corta más abajo en esta misma hoja y, con la misma
   especificidad, le dejaba el borde superior en cero. */
.home-intro { padding: 88px var(--gutter) 24px; }
.home-intro h2 { margin-bottom: 14px; }
.home-intro p { color: var(--text-2); margin: 0 0 14px; }

.home-video { padding: 24px var(--gutter); }
.home-video h2 { margin-bottom: 14px; }
.home-video-text { margin-top: 18px; }
.home-video-text p { color: var(--text-2); margin: 0 0 14px; }

.home-latest { padding: 24px var(--gutter) 64px; }

.home-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  margin-bottom: 20px;
}
.home-intro h2,
.home-video h2,
.home-head h2 {
  font-size: 15px;
  font-weight: 500;
  letter-spacing: 1.5px;
  text-transform: uppercase;
  color: var(--text-2);
  margin: 0;
}

.home-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 20px;
}

/* Una obra del avance es un botón de reproducir, no un enlace: el objeto de
   la portada es que suene. La ficha se alcanza desde Obras.

   Columna anclada arriba: la fila de la grilla mide lo que la tarjeta más
   alta, y un botón centra su contenido en vertical por omisión. Con un
   título de dos líneas en una sola tarjeta, las otras tres bajaban su tapa
   media línea y la grilla quedaba desprolija. */
.home-card {
  display: flex;
  flex-direction: column;
  justify-content: flex-start;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  color: inherit;
  font: inherit;
  text-align: left;
  cursor: pointer;
}

.home-card-art { display: block; position: relative; }

.home-card-play {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--text);
  background: rgba(0, 0, 0, 0.35);
  border-radius: var(--r-md);
  opacity: 0;
  transition: opacity 200ms var(--ease);
}
/* Visible al pasar por encima, con el teclado, y siempre en la que suena.
   En pantalla táctil no hay hover, así que también se muestra apenas se
   puede tocar. */
.home-card:hover .home-card-play,
.home-card:focus-visible .home-card-play,
.is-current .home-card-play { opacity: 1; }
@media (hover: none) {
  .home-card-play { opacity: 1; background: rgba(0, 0, 0, 0.2); }
}
.home-card-play .ico-pause { display: none; }
.is-playing .home-card-play .ico-play { display: none; }
.is-playing .home-card-play .ico-pause { display: inline; }

.home-card-cover {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--r-md);
  background: var(--surface);
  display: block;
}
/* Dos líneas reservadas aunque el título ocupe una: así el género de las
   cuatro tarjetas arranca a la misma altura. */
.home-card-title {
  display: block;
  margin-top: 10px;
  font-size: 14px;
  color: var(--text);
  line-height: 1.3;
  min-height: 2.6em;
}
.home-card-meta { display: block; font-size: 12px; color: var(--muted); }
.home-card:hover .home-card-title { color: var(--accent); }
.home-card.is-current .home-card-title { color: var(--accent); }
.home-card-cover.cover-empty { aspect-ratio: 1; }

.home-posts { list-style: none; margin: 0; padding: 0; }
.home-posts li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 16px;
  padding: 12px 0;
  border-top: 1px solid var(--border);
}
.home-posts a { color: var(--text); text-decoration: none; font-size: 15px; }
.home-posts a:hover { color: var(--accent); }
.home-posts time { white-space: nowrap; }

@media (max-width: 1023px) {
  /* El banner toma la forma de la foto vertical, así no se recorta nada: la
     altura sale de la proporción del archivo y no de una cuenta sobre el ancho
     de la ventana, que acá daría una franja. */
  .hero {
    height: auto;
    aspect-ratio: 1080 / 1440;
  }
  /* El texto pasa a la banda de arriba, a todo el ancho. */
  .hero-text {
    width: 100%;
    bottom: auto;
    justify-content: flex-start;
    padding: 40px var(--gutter) 0;
  }
  .hero-photo { object-position: 50% 30%; }

  /* El único lugar donde la foto se oscurece, y con un motivo medido.
     En escritorio el texto entra en la zona vacía de la foto y no hace falta
     nada. Acá no entra: el trazo del nombre ocupa todo el ancho, y con el apodo
     y el botón el bloque llega al 60% de la altura, mientras que la parte
     limpia de la foto vertical termina al 41% —ahí arranca el pelo iluminado,
     con picos de 244/255—.

     El degradado va de arriba hacia abajo y se desvanece antes de la cara, así
     que oscurece donde hay texto y deja la foto intacta donde se la mira. */
  .hero::before {
    content: '';
    position: absolute;
    inset: 0 0 40% 0;
    background: linear-gradient(
      to bottom,
      rgba(0, 0, 0, 0.72),
      rgba(0, 0, 0, 0.45) 55%,
      transparent
    );
    pointer-events: none;
    /* Un `::before` se pinta antes que los hijos, así que sin esto el degradado
       quedaría debajo de la foto y no se vería. Las tres capas quedan
       explícitas: foto (sin z-index), degradado, texto. */
    z-index: 1;
  }
  .hero-text { z-index: 2; }
  .home-intro { padding-top: 56px; }
  .home-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 599px) {
  .hero-cta { font-size: 21px; padding: 12px 26px; }
  .home-head h2 { font-size: 13px; }
}

/* ── Estructura de página ─────────────────────────────────────────────── */

/* El ancho máximo incluye el margen lateral, así la columna de contenido sigue
   midiendo `--wrap` pero el margen no se suma dos veces.

   Sin esto, entre 768 y 816 px de ventana el contenido quedaba con el margen
   del centrado más el de la sección —50 px en una tablet— mientras el
   encabezado seguía a 24. */
.wrap {
  max-width: calc(var(--wrap) + var(--gutter) * 2);
  margin: 0 auto;
}

.block { padding: 0 var(--gutter) 64px; }

.page-header { padding: 40px var(--gutter) 32px; }

.page-header h1 {
  font-size: 40px;
  font-weight: 600;
  letter-spacing: -1px;
  line-height: 1.15;
  margin: 0;
}

.page-header .subtitle {
  font-size: 14px;
  color: var(--text-2);
  margin: 8px 0 0;
}

.back {
  display: inline-flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: var(--muted);
  text-decoration: none;
  margin-bottom: 24px;
  transition: color 200ms var(--ease);
}
.back:hover { color: var(--text-2); }

.label {
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.2px;
  color: var(--muted);
  margin: 0 0 16px;
}

.prose p { font-size: 16px; line-height: 1.6; margin: 0 0 16px; }

.button {
  display: inline-block;
  background: var(--accent);
  color: var(--bg);
  text-decoration: none;
  font-size: 14px;
  font-weight: 600;
  letter-spacing: 0.3px;
  padding: 14px 24px;
  border-radius: var(--r-md);
}

/* ── Artista ──────────────────────────────────────────────────────────── */

.artist-photo {
  width: 160px;
  height: 160px;
  object-fit: cover;
  border-radius: var(--r-sm);
  display: block;
}

.artist-name {
  font-size: 32px;
  font-weight: 600;
  letter-spacing: -0.5px;
  margin: 32px 0 24px;
}

.cover-empty {
  background: var(--surface);
  border: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
}
.cover-empty svg { width: 64px; height: 64px; }

.link-buttons { display: flex; flex-wrap: wrap; gap: 12px 12px; }
.link-buttons a {
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-size: 13px;
  padding: 8px 16px;
  text-decoration: none;
  transition: border-color 200ms var(--ease), color 200ms var(--ease);
}
.link-buttons a:hover { border-color: var(--accent-dim); color: var(--text); }

/* ── Contacto ─────────────────────────────────────────────────────────── */

.social-row {
  display: flex;
  gap: 12px;
  margin-bottom: 12px;
  font-size: 13px;
}
.social-row > span { width: 100px; flex: none; color: var(--muted); }
.social-row a {
  color: var(--accent);
  text-decoration: underline;
  text-decoration-color: var(--accent-dim);
  overflow-wrap: anywhere;
}

.form label { display: block; margin-bottom: 16px; }
.form label > span {
  display: block;
  font-size: 12px;
  color: var(--text-2);
  margin-bottom: 6px;
}
.form input, .form textarea {
  width: 100%;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--r-md);
  color: var(--text);
  font: inherit;
  font-size: 14px;
  padding: 12px 16px;
}
.form button {
  width: 100%;
  background: var(--accent);
  border: 0;
  border-radius: var(--r-md);
  color: var(--bg);
  font: inherit;
  font-weight: 600;
  padding: 14px 24px;
  margin-top: 8px;
}
.form .note {
  font-size: 12px;
  font-style: italic;
  color: var(--muted);
  margin: 12px 0 0;
}

.form textarea { resize: vertical; min-height: 120px; }
.form input::placeholder, .form textarea::placeholder { color: var(--muted); }

/* El anillo de foco es la única señal de dónde está el teclado, y el `outline`
   por omisión casi no se ve sobre este fondo. `:focus-visible` y no `:focus`:
   con el mouse no aparece. */
.form input:focus-visible,
.form textarea:focus-visible,
.form button:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-color: var(--accent-dim);
}

/* Dos fuentes para el mismo estado. `aria-invalid` lo pone el script, con el
   campo que nombró el error del servidor; `:user-invalid` cubre la validación
   del navegador, que corre antes y —al contrario de `:invalid`— no pinta en
   rojo un campo que todavía se está escribiendo. */
.form input[aria-invalid="true"],
.form textarea[aria-invalid="true"],
.form input:user-invalid,
.form textarea:user-invalid {
  border-color: var(--danger);
}

.form button {
  cursor: pointer;
  transition: opacity 200ms var(--ease);
}
.form button:hover:not(:disabled) { opacity: 0.88; }
/* El mismo hundido de 1px que `.hero-cta:active`. */
.form button:active:not(:disabled) { transform: translateY(1px); }
.form button:disabled { opacity: 0.45; cursor: default; }

/* Mientras la petición viaja. El atributo lo pone y lo saca el script. */
.form[data-busy] { cursor: progress; }

/* La trampa para robots. `display:none` la saca del orden de tabulación y del
   árbol de accesibilidad: ningún visitante la ve ni la puede llenar. */
.form .hp { display: none; }

/* El resultado del envío. Vacío no ocupa lugar: sin `:empty` reservaría una
   línea en blanco debajo del botón desde el primer dibujado, para nada. */
.form-result {
  font-size: 13px;
  line-height: 1.5;
  margin: 12px 0 0;
  color: var(--text-2);
}
.form-result:empty { display: none; }
/* Éxito en el acento y no en verde: el sitio no tiene verde en ninguna parte,
   y agregarlo por un mensaje de confirmación rompería la paleta. */
.form-result.is-ok { color: var(--accent); }
.form-result.is-error { color: var(--danger); }

/* ── Piezas compartidas ───────────────────────────────────────────────── */

.chips { display: flex; flex-wrap: wrap; gap: 8px; }
.chip {
  --chip: var(--accent-dim);
  border: 1px solid color-mix(in srgb, var(--chip) 50%, transparent);
  border-radius: var(--r-sm);
  color: var(--chip);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.8px;
  padding: 4px 10px;
}

.video {
  position: relative;
  aspect-ratio: 16 / 9;
  background: var(--surface);
}
.video iframe { position: absolute; inset: 0; width: 100%; height: 100%; border: 0; }

/* ── Reproductor ──────────────────────────────────────────────────────── */

.player {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  background: var(--elevated);
  border-top: 1px solid var(--border);
  z-index: 20;
}
.player[hidden] { display: none; }

.player-seek {
  -webkit-appearance: none;
  appearance: none;
  display: block;
  width: 100%;
  height: 2px;
  margin: 0;
  background: var(--border);
  cursor: pointer;
}
.player-seek::-webkit-slider-thumb {
  -webkit-appearance: none;
  width: 10px;
  height: 10px;
  border-radius: 50%;
  background: var(--accent);
}
.player-seek::-moz-range-thumb {
  width: 10px;
  height: 10px;
  border: 0;
  border-radius: 50%;
  background: var(--accent);
}

.player-row {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 6px 16px 10px;
}

.player-info { flex: 1; min-width: 0; }
.player-title {
  display: block;
  font-size: 13px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.player-meta { font-size: 11px; color: var(--text-2); }

.player-controls { display: flex; align-items: center; gap: 2px; }

.player-btn {
  background: none;
  border: 0;
  color: var(--text-2);
  cursor: pointer;
  display: flex;
  padding: 8px;
}
.player-btn:hover { color: var(--text); }
.player-btn:disabled { color: var(--muted); cursor: default; }
.player-main { color: var(--accent); }
.player-main:hover { color: var(--accent); }

/* El icono que se muestra depende de si está sonando. */
.player-main .ico-pause { display: none; }
.player.playing .player-main .ico-play { display: none; }
.player.playing .player-main .ico-pause { display: inline; }

.player-time {
  font-size: 11px;
  color: var(--text-2);
  font-variant-numeric: tabular-nums;
  flex: none;
}

@media (max-width: 599px) {
  .player-time { display: none; }
  .player-row { gap: 8px; }
}

/* ── Transición entre páginas ─────────────────────────────────────────── */

/* La firma del sitio: entra desplazándose un 4% con un fundido, 300ms. */
@keyframes page-in {
  from { opacity: 0; transform: translateX(4%); }
  to { opacity: 1; transform: none; }
}

main.entering { animation: page-in 300ms var(--ease); }

@media (prefers-reduced-motion: reduce) {
  main.entering { animation: none; }
  * { transition-duration: 0.01ms !important; }
}

/* ── Listado de obras ─────────────────────────────────────────────────── */

.filters {
  display: flex;
  gap: 8px;
  overflow-x: auto;
  /* Pegado al listado: con más aire parece un bloque suelto. */
  padding: 0 var(--gutter) 8px;
  scrollbar-width: none;
}
.filters::-webkit-scrollbar { display: none; }

.filter {
  flex: none;
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  color: var(--text-2);
  font-size: 13px;
  font-weight: 500;
  padding: 8px 16px;
  text-decoration: none;
  white-space: nowrap;
  transition: background-color 200ms var(--ease), border-color 200ms var(--ease),
    color 200ms var(--ease);
}
.filter:hover { border-color: var(--accent-dim); color: var(--text); }
.filter.on { background: var(--accent); border-color: var(--accent); color: var(--bg); }

.track {
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  transition: background-color 300ms ease-in-out;
}
.track[open] { background: var(--elevated); }

.track-head {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 20px var(--gutter);
  cursor: pointer;
  list-style: none;
}
.track-head::-webkit-details-marker { display: none; }

.track-thumb {
  width: 52px;
  height: 52px;
  flex: none;
  object-fit: cover;
  border-radius: var(--r-sm);
}
.track-thumb.cover-empty { background: var(--elevated); border: 0; }
.track-thumb.cover-empty svg { width: 24px; height: 24px; }

.track-title { flex: 1; min-width: 0; }
.track-name {
  display: block;
  font-size: 18px;
  font-weight: 500;
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.track-meta {
  display: block;
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 1.2px;
  color: var(--muted);
  margin-top: 4px;
}

.track-play {
  flex: none;
  background: none;
  border: 0;
  color: var(--accent);
  cursor: pointer;
  display: flex;
  padding: 3px;
}
.track-play .ico-pause { display: none; }
.is-playing .track-play .ico-play { display: none; }
.is-playing .track-play .ico-pause { display: inline; }

.track-chevron {
  flex: none;
  color: var(--muted);
  display: flex;
  transition: transform 300ms linear;
}
.track[open] .track-chevron { transform: rotate(180deg); }

.track-body { padding: 0 var(--gutter) 28px; }
.track-body > *:first-child { margin-top: 0; }
.track-body p { font-size: 14px; color: var(--text-2); margin: 0 0 16px; }

.meta-row { font-size: 13px; }
.meta-row > span { color: var(--muted); }

.track-body .chips, .track-body .link-buttons { margin-bottom: 16px; }
.track-body .label { margin-top: 20px; }

.read-more {
  display: inline-block;
  font-size: 13px;
  color: var(--accent);
  text-decoration: none;
  margin-top: 8px;
}
.read-more:hover { text-decoration: underline; }

.empty { color: var(--text-2); text-align: center; padding: 48px 0; }

/* ── Detalle de obra y de entrada ─────────────────────────────────────── */

/* La tapa de una entrada: cuadrada, y del mismo tamaño que la de una obra para
   que las dos páginas la muestren igual. Antes era una franja de 280 px de
   alto, que de una imagen cuadrada recortaba al centro y le comía arriba y
   abajo.

   El ancho sale del mismo reparto que `.track-intro`: al ancho del `.wrap` se
   le descuentan sus dos márgenes laterales y el espacio entre columnas, y de
   lo que queda se toma un tercio. Con los 768 px de `--wrap` son 248 px, los
   mismos que mide la tapa de una obra.

   Lleva `margin-left` porque esta imagen es hija directa de `.wrap`, no de
   `.block`: sin él arrancaría 24 px antes que la primera letra del artículo. */
.wide-cover {
  width: calc((100% - var(--gutter) * 2 - 24px) / 3);
  aspect-ratio: 1;
  object-fit: cover;
  display: block;
  margin-left: var(--gutter);
  background: var(--surface);
}
.wide-cover.cover-empty { border: 0; aspect-ratio: 1; }

/* La portada de una obra y su descripción, lado a lado: un tercio y dos
   tercios.

   La portada va en 1:1 y recortada, el mismo mecanismo que `.home-card-cover`
   en la portada del sitio. La caja de 280 px de alto de `.wide-cover` —que
   sigue arriba porque la usa el detalle de una entrada— le comía arriba y
   abajo: la foto que sube el cliente es cuadrada, y perdía el encuadre justo
   al abrir la obra, que es donde se la mira con atención.

   Es `grid` y no `flex`, contra la costumbre del archivo, porque un tercio y
   dos tercios exactos es lo que `1fr 2fr` da sin cuentas: con `flex-basis` el
   `gap` se descuenta del porcentaje y la proporción deja de ser la pedida.

   `align-items: start` es lo que deja que la descripción siga bajando sola
   cuando es más larga que la foto, en lugar de estirarla. */
.track-intro {
  display: grid;
  /* `minmax(0, …)` y no `1fr 2fr` pelado: un elemento de cuadrícula no baja de
     su contenido mínimo, así que una palabra larga en la descripción —una URL
     pegada, el nombre de un archivo— ensancharía su columna y correría la
     página al costado. Es el mismo motivo del `min-width: 0` que acompaña a
     cada `flex: 1` de este archivo. */
  grid-template-columns: minmax(0, 1fr) minmax(0, 2fr);
  gap: 24px;
  align-items: start;
  padding: 0 var(--gutter);
}

.track-cover {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  background: var(--surface);
  display: block;
}

/* Sin archivo, `cover()` devuelve un `div`, no un `img`: sin esto hereda solo
   el flex centrado de `.cover-empty` y la caja colapsa. El mismo parche que
   lleva `.home-card-cover.cover-empty`. */
.track-cover.cover-empty { aspect-ratio: 1; }

/* El margen inferior lo pone ahora el `gap`. Y una palabra que no entra se
   corta en lugar de asomarse fuera de su columna. */
.track-intro .lead { margin: 0; overflow-wrap: break-word; }

.block-video { padding: 32px var(--gutter) 0; }

.lead { font-size: 16px; line-height: 1.6; color: var(--text); margin: 0 0 24px; }

.track-detail .block .label { margin-top: 24px; }
.track-detail .chips { margin: 16px 0; }

/* ── Blog ─────────────────────────────────────────────────────────────── */

.post-card {
  display: flex;
  gap: 24px;
  padding: 28px 0;
  border-bottom: 1px solid var(--border);
}
.post-card:last-child { border-bottom: 0; }

.post-cover {
  width: 100px;
  height: 100px;
  flex: none;
  object-fit: cover;
  border-radius: var(--r-sm);
}
.post-cover.cover-empty svg { width: 32px; height: 32px; }

.post-body { min-width: 0; }
.post-body h2 { font-size: 18px; font-weight: 500; margin: 8px 0; }
.post-body h2 a { color: var(--text); text-decoration: none; }
.post-body h2 a:hover { color: var(--accent); }
.post-body .label { margin: 0; }

.excerpt {
  font-size: 14px;
  color: var(--text-2);
  margin: 0 0 16px;
  display: -webkit-box;
  -webkit-line-clamp: 3;
  -webkit-box-orient: vertical;
  overflow: hidden;
}

.tags { font-size: 11px; color: var(--muted); margin: 12px 0 0; }

/* ── Cuerpo de una entrada ────────────────────────────────────────────── */

.prose { max-width: 720px; }
.prose h2 { font-size: 24px; font-weight: 500; margin: 40px 0 16px; }
.prose h3 { font-size: 18px; font-weight: 500; margin: 32px 0 12px; }
.prose img { border-radius: var(--r-sm); display: block; margin: 24px 0; }
.prose ul, .prose ol { padding-left: 20px; }
.prose li { margin-bottom: 8px; }
.prose blockquote {
  border-left: 3px solid var(--accent);
  color: var(--text-2);
  margin: 24px 0;
  padding-left: 16px;
}
.prose code {
  background: var(--surface);
  border-radius: var(--r-sm);
  font-size: 14px;
  padding: 2px 6px;
}
.prose pre {
  background: var(--surface);
  border-radius: var(--r-md);
  overflow-x: auto;
  padding: 16px;
}
.prose pre code { background: none; padding: 0; }
.prose .video { margin: 24px 0; }

@media (max-width: 599px) {
  .page-header h1 { font-size: 32px; }
  .post-card { gap: 16px; }
  .post-cover { width: 72px; height: 72px; }
  .track-head { gap: 14px; }
  /* En el teléfono, a todo el ancho del texto: un tercio de 312 px de
     contenido quedaría en 96 px. Igual que la tapa de una obra. */
  .wide-cover { width: calc(100% - var(--gutter) * 2); }
  /* Apiladas: la foto arriba, en 1:1 y a todo el ancho, como en la portada.
     A un tercio de 312 px de contenido quedaría en 96 px. */
  .track-intro { grid-template-columns: 1fr; gap: 20px; }
}

/* ── Botón de reproducir en el encabezado de una obra ─────────────────── */

/* Va al lado del título y no debajo de la portada: ahí ocupaba el ancho
   entero y pesaba más que el contenido de la página. */
.title-row {
  display: flex;
  align-items: center;
  gap: 16px;
}
.title-row h1 { flex: 1; min-width: 0; }

.title-play {
  flex: none;
  background: none;
  border: 0;
  color: var(--accent);
  cursor: pointer;
  display: flex;
  padding: 4px;
  transition: opacity 200ms var(--ease);
}
.title-play:hover { opacity: 0.8; }
.title-play svg { width: 40px; height: 40px; }
.title-play .ico-pause { display: none; }
.is-playing .title-play .ico-play { display: none; }
.is-playing .title-play .ico-pause { display: inline; }

@media (max-width: 599px) {
  .title-play svg { width: 34px; height: 34px; }
  .title-row { gap: 12px; }
}
