/* ==========================================================================
   Victory's Live — sala de conciertos y eventos en alquiler
   Peri Digital · peridigital.es

   El sistema es el mismo que el de victorysdance.com (misma casa, misma
   tipografía, mismo negro, mismos componentes) con una sola diferencia: el
   acento. Allí es el magenta del logotipo de la escuela; aquí es el morado
   del logotipo de Victory's Live, muestreado del propio archivo. Son marcas
   hermanas, no la misma marca, y el color es lo único que las separa a
   primera vista.

   Contraste verificado (WCAG AA) sobre el fondo --vl-bg:
     blanco sobre --vl-primary   6.72:1  → texto de botón, válido en cualquier tamaño
     --vl-accent sobre el fondo  5.90:1  → válido para texto pequeño
     --vl-primary sobre el fondo 2.98:1  → NUNCA como texto, solo relleno y filos
   ========================================================================== */

/* --------------------------------------------------------------------------
   1. TOKENS
   -------------------------------------------------------------------------- */
:root {
  /* Marca. Muestreados del logotipo: el trazo del contorno da #803080, y de
     ahí salen el relleno, el estado sobre y el tono claro accesible. */
  --vl-primary: #8f2fa6;
  --vl-primary-hover: #a63fbe;
  --vl-accent: #c266d9;
  --vl-arena: #c8a887;           /* el beige de la púa del logotipo */

  /* Superficies. Negro de sala a oscuras con un matiz mínimo de azul, para que
     no sea el #000 plano de una pantalla apagada. Tres peldaños porque las
     tarjetas necesitan despegarse del fondo. */
  --vl-bg: #08080b;
  --vl-bg-2: #101015;
  --vl-bg-3: #17171f;
  --vl-line: #26262f;
  --vl-line-soft: rgba(255, 255, 255, 0.08);

  --vl-text: #e9ecf3;
  --vl-text-2: #a8b0c2;
  --vl-text-3: #737d93;
  --vl-on-primary: #ffffff;

  --vl-font: 'Instrument Sans', system-ui, -apple-system, 'Segoe UI', Arial, sans-serif;
  --vl-font-display: 'Bricolage Grotesque', 'Instrument Sans', system-ui, sans-serif;

  --vl-fs-sm: clamp(0.875rem, 0.85rem + 0.12vw, 0.9375rem);
  --vl-fs-base: clamp(1rem, 0.97rem + 0.18vw, 1.0938rem);
  --vl-fs-lg: clamp(1.125rem, 1.06rem + 0.32vw, 1.3125rem);
  --vl-fs-xl: clamp(1.375rem, 1.2rem + 0.75vw, 1.75rem);
  --vl-fs-2xl: clamp(1.75rem, 1.42rem + 1.45vw, 2.625rem);
  --vl-fs-3xl: clamp(2.25rem, 1.75rem + 2.3vw, 3.5rem);
  --vl-fs-4xl: clamp(2.75rem, 1.9rem + 3.6vw, 4.75rem);

  --vl-gutter: clamp(1.15rem, 0.6rem + 2.2vw, 2.25rem);
  --vl-container: 1240px;
  --vl-narrow: 760px;
  --vl-section: clamp(3.5rem, 2.2rem + 5vw, 6rem);

  --vl-gap-sm: 1.2rem;
  --vl-gap-md: clamp(1.6rem, 1.2rem + 1.4vw, 2.2rem);
  --vl-gap-lg: clamp(2.2rem, 1.6rem + 2.4vw, 3.2rem);

  --vl-radius: 14px;
  --vl-radius-sm: 8px;
  --vl-radius-pill: 999px;

  --vl-shadow: 0 1px 2px rgba(0, 0, 0, 0.4), 0 10px 30px rgba(0, 0, 0, 0.55);
  --vl-shadow-lg: 0 2px 6px rgba(0, 0, 0, 0.45), 0 28px 70px rgba(0, 0, 0, 0.7);

  --vl-superficie: linear-gradient(180deg, rgba(255, 255, 255, 0.04), rgba(255, 255, 255, 0) 140px);
  --vl-filo: inset 0 1px 0 rgba(255, 255, 255, 0.06);

  --vl-ease: cubic-bezier(0.22, 1, 0.36, 1);
  --vl-dur: 420ms;

  /* Más alta que la de victorysdance.com (78 px) por una razón concreta: allí
     el logotipo es un wordmark apaisado y a 62 px de alto se lee de sobra.
     El de Victory's Live es la púa, casi cuadrada, así que a esa altura el
     nombre dentro sale a un tercio del tamaño y no hay quien lo lea. */
  --vl-header-h: 94px;

  /* Dónde acaba de verdad la cabecera pegajosa. Todo lo que se ancla al hacer
     scroll —los bloques sticky y el margen de los saltos a #ancla— se mide
     desde aquí y no desde --vl-header-h a pelo, porque con la barra de
     administración de WordPress la cabecera baja y se comía por arriba lo que
     hubiera quedado justo debajo. */
  --vl-tope: calc(var(--vl-header-h) + 1.5rem);
}

body.admin-bar { --vl-tope: calc(var(--vl-header-h) + 1.5rem + 32px); }
@media screen and (max-width: 782px) {
  body.admin-bar { --vl-tope: calc(var(--vl-header-h) + 1.5rem + 46px); }
}

/* --------------------------------------------------------------------------
   2. TIPOGRAFÍAS
   Autoalojadas: la visita no genera ninguna petición a servidores de terceros.
   -------------------------------------------------------------------------- */
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal; font-weight: 600 800; font-stretch: 100%; font-display: swap;
  src: url(../fonts/bricolage-grotesque-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Bricolage Grotesque';
  font-style: normal; font-weight: 600 800; font-stretch: 100%; font-display: swap;
  src: url(../fonts/bricolage-grotesque-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal; font-weight: 400 700; font-stretch: 100%; font-display: swap;
  src: url(../fonts/instrument-sans-normal-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Instrument Sans';
  font-style: normal; font-weight: 400 700; font-stretch: 100%; font-display: swap;
  src: url(../fonts/instrument-sans-normal-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

/* --------------------------------------------------------------------------
   3. RESET
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  color-scheme: dark;
  scrollbar-color: var(--vl-line) var(--vl-bg);
}

/* La cabecera es pegajosa: sin este margen, saltar a una sección desde el menú
   dejaba su titular escondido detrás de la barra. */
:target, [id] { scroll-margin-top: var(--vl-tope); }

::selection { background: var(--vl-primary); color: #fff; }

body {
  margin: 0;
  background: var(--vl-bg);
  color: var(--vl-text);
  font-family: var(--vl-font);
  font-size: var(--vl-fs-base);
  line-height: 1.68;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}

/* Grano de película. Capa fija, sin eventos y sin repintar al hacer scroll:
   rompe el degradado digital perfecto y da textura de fotografía analógica. */
body::after {
  content: "";
  position: fixed; inset: 0; z-index: 9998;
  pointer-events: none; opacity: 0.05; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}
@media (prefers-reduced-motion: reduce) { body::after { display: none; } }

h1, h2, h3, h4 {
  margin: 0 0 0.6em;
  font-family: var(--vl-font-display);
  font-weight: 800; line-height: 1.07; letter-spacing: -0.021em;
  color: #fff; text-wrap: balance;
}
h3, h4 { letter-spacing: -0.012em; }
h1 { font-size: var(--vl-fs-3xl); }
h2 { font-size: var(--vl-fs-2xl); }
h3 { font-size: var(--vl-fs-xl); font-weight: 700; }

p { margin: 0 0 1.15em; text-wrap: pretty; color: var(--vl-text-2); }
p:last-child { margin-bottom: 0; }

a { color: var(--vl-accent); text-underline-offset: 0.2em; }
a:hover { color: #fff; }

img, picture, svg { max-width: 100%; height: auto; display: block; }
ul, ol { margin: 0 0 1.15em; padding-left: 1.2rem; }
button, input, select, textarea { font: inherit; color: inherit; }

:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: 3px; border-radius: 4px; }

/* Cifras de ancho fijo donde se comparan en columna: precios y horarios. */
.vl-cifra__n, .vl-precio__cifra span, .vl-concierto__fecha { font-variant-numeric: tabular-nums; }

.vl-oculto {
  position: absolute; width: 1px; height: 1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap;
}
.skip-link {
  position: absolute; left: -9999px; z-index: 999;
  padding: 0.8rem 1.2rem; background: var(--vl-primary); color: #fff;
  border-radius: 0 0 var(--vl-radius-sm) 0; text-decoration: none;
}
.skip-link:focus { left: 0; top: 0; }

/* --------------------------------------------------------------------------
   4. LAYOUT
   -------------------------------------------------------------------------- */
.vl-container { width: 100%; max-width: var(--vl-container); margin-inline: auto; padding-inline: var(--vl-gutter); }
.vl-section { padding-block: var(--vl-section); position: relative; }
.vl-section--tint { background: var(--vl-bg-2); }
.vl-main { min-height: 50vh; position: relative; z-index: 1; }

.vl-encabezado { max-width: 54ch; margin-bottom: var(--vl-gap-lg); }
.vl-encabezado > :last-child { margin-bottom: 0; }
.vl-encabezado h2 { margin-bottom: 0.45em; }

/* --------------------------------------------------------------------------
   5. PRIMITIVAS
   -------------------------------------------------------------------------- */
.vl-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.55em;
  padding: 0.95em 1.9em;
  font-size: var(--vl-fs-sm); font-weight: 700;
  letter-spacing: 0.045em; text-transform: uppercase; text-decoration: none;
  white-space: nowrap;
  border: 2px solid transparent; border-radius: var(--vl-radius-pill);
  cursor: pointer;
  transition: background var(--vl-dur) var(--vl-ease),
              color var(--vl-dur) var(--vl-ease),
              border-color var(--vl-dur) var(--vl-ease),
              transform 180ms var(--vl-ease);
}
.vl-btn:active { transform: translateY(1px); }
.vl-btn--primary { background: var(--vl-primary); color: var(--vl-on-primary); }
.vl-btn--primary:hover { background: var(--vl-primary-hover); color: #fff; }
.vl-btn--outline { border-color: rgba(255, 255, 255, 0.32); color: #fff; }
.vl-btn--outline:hover { background: #fff; color: var(--vl-bg); border-color: #fff; }
.vl-btn--grande { padding: 1.05em 2.3em; font-size: var(--vl-fs-base); }

.vl-eyebrow {
  display: block; margin-bottom: 1rem;
  font-size: 0.8125rem; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  color: var(--vl-accent);
}
.vl-lead { font-size: var(--vl-fs-lg); color: var(--vl-text-2); max-width: 58ch; }

/* --------------------------------------------------------------------------
   6. CABECERA
   -------------------------------------------------------------------------- */
.vl-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(8, 8, 11, 0.8);
  backdrop-filter: blur(16px) saturate(140%);
  border-bottom: 1px solid transparent;
  transition: background var(--vl-dur) var(--vl-ease),
              border-color var(--vl-dur) var(--vl-ease),
              box-shadow var(--vl-dur) var(--vl-ease);
}
/* Arriba del todo la barra se funde con el hero; en cuanto pasa contenido por
   debajo se separa con línea y sombra. Sin esto, el borde permanente parece un
   corte del diseño. */
.vl-header.is-scrolled {
  background: rgba(8, 8, 11, 0.94);
  border-bottom-color: var(--vl-line-soft);
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.5);
}
.vl-header__inner {
  display: flex; align-items: center;
  gap: clamp(1rem, 0.4rem + 2vw, 2.4rem); min-height: var(--vl-header-h);
}
.vl-header .vl-nav { margin-left: auto; }
.vl-logo { display: inline-flex; align-items: center; text-decoration: none; flex-shrink: 0; }
/* Altura explícita: el reset pone height:auto y la imagen necesita una medida
   concreta para no decidirla por su cuenta dentro de la barra. */
.vl-logo img { height: 78px; width: auto; }
@media (max-width: 1180px) { .vl-logo img { height: 68px; } }
@media (max-width: 600px) { .vl-logo img { height: 58px; } }

.vl-nav ul { display: flex; align-items: center; gap: 1.6rem; list-style: none; margin: 0; padding: 0; }
.vl-nav a {
  color: var(--vl-text); text-decoration: none;
  font-size: 0.9375rem; font-weight: 500; white-space: nowrap;
  transition: color 220ms var(--vl-ease);
}
.vl-nav a:hover, .vl-nav a.is-actual { color: var(--vl-accent); }

.vl-header__cta { flex-shrink: 0; }
.vl-header__cta .vl-btn { padding: 0.72em 1.35em; font-size: 0.8125rem; }

.vl-nav-toggle {
  /* Sin `flex-shrink: 0` el navegador aplasta el botón cuando el logotipo y el
     CTA no dejan sitio: sigue ahí, pero es imposible acertarle. */
  display: none; flex-shrink: 0;
  width: 44px; height: 44px;
  align-items: center; justify-content: center;
  background: transparent; border: 0; color: #fff; padding: 0; cursor: pointer;
}
.vl-nav-toggle svg { flex-shrink: 0; }

/* En pantallas estrechas el CTA se queda solo con el icono: con el texto no
   caben logotipo, botón y menú a la vez. El nombre lo lee el lector de
   pantalla desde el aria-label. */
@media (max-width: 620px) {
  .vl-header__cta .vl-btn { padding: 0.72em 0.95em; }
  .vl-header__cta .vl-btn span { position: absolute; width: 1px; height: 1px; overflow: hidden; clip: rect(0 0 0 0); }
}

@media (max-width: 1180px) {
  .vl-nav-toggle { display: inline-flex; order: 3; }
  .vl-header__cta { margin-left: auto; }
  .vl-nav {
    display: none; position: absolute; inset-inline: 0; top: 100%;
    max-height: calc(100vh - var(--vl-header-h)); overflow-y: auto;
    background: var(--vl-bg-2); border-bottom: 1px solid var(--vl-line);
    padding: 1.6rem var(--vl-gutter); box-shadow: var(--vl-shadow-lg);
  }
  .vl-nav.is-open { display: block; }
  .vl-nav ul { flex-direction: column; align-items: stretch; gap: 0.2rem; }
  .vl-nav a { display: inline-flex; padding-block: 0.55rem; font-size: 1.05rem; }
}

/* --------------------------------------------------------------------------
   7. HERO
   Fotografía de la sala llena a sangre, con el titular apoyado abajo. Es el
   argumento de venta entero en una imagen: esto es lo que se alquila.
   -------------------------------------------------------------------------- */
.vl-hero {
  position: relative; isolation: isolate; overflow: hidden;
  display: grid; align-items: end;
  min-height: min(92vh, 800px);
  margin-top: calc(var(--vl-header-h) * -1);
  padding-block: calc(var(--vl-header-h) + 4rem) clamp(3rem, 2rem + 4vw, 5.5rem);
}
/* `dvh` descuenta la barra del navegador móvil, que aparece y desaparece al
   hacer scroll. Con `vh` el hero da un salto de 60 px en cuanto se desliza. */
@supports (height: 100dvh) { .vl-hero { min-height: min(92dvh, 800px); } }

.vl-hero__foto { position: absolute; inset: 0; z-index: 0; }
.vl-hero__foto img { width: 100%; height: 100%; object-fit: cover; object-position: center 42%; }
/* Velo: carga arriba, donde está la barra, y abajo, donde está el titular, y
   deja el centro de la fotografía limpio. */
.vl-hero__foto::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(180deg,
              rgba(8, 8, 11, 0.95) 0%,
              rgba(8, 8, 11, 0.58) 16%,
              rgba(8, 8, 11, 0.34) 44%,
              rgba(8, 8, 11, 0.94) 100%);
}
/* Cierre inferior a color de fondo, para que la foto no acabe en corte recto
   contra la franja de cifras. */
.vl-hero::after {
  content: ""; position: absolute; z-index: 1; pointer-events: none;
  left: 0; right: 0; bottom: 0; height: 30%;
  background: linear-gradient(180deg, rgba(8, 8, 11, 0), var(--vl-bg));
}
.vl-hero__copy { position: relative; z-index: 2; max-width: 46rem; }
.vl-hero h1 {
  font-size: var(--vl-fs-4xl); margin-bottom: 0.4em; max-width: 15ch;
  text-shadow: 0 2px 24px rgba(0, 0, 0, 0.55);
}
.vl-hero h1 em { font-style: normal; color: var(--vl-accent); }
.vl-hero__lead { font-size: var(--vl-fs-lg); color: var(--vl-text); max-width: 44ch; }
.vl-hero__actions { display: flex; flex-wrap: wrap; gap: 0.9rem; margin-top: 2rem; }

/* --------------------------------------------------------------------------
   8. FRANJA DE CIFRAS
   -------------------------------------------------------------------------- */
.vl-cifras { border-block: 1px solid var(--vl-line); background: var(--vl-bg-2); position: relative; isolation: isolate; }
.vl-cifras__grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1px; background: var(--vl-line); }
@media (min-width: 780px) { .vl-cifras__grid { grid-template-columns: repeat(4, 1fr); } }
.vl-cifra { background: var(--vl-bg-2); padding: clamp(1.6rem, 1rem + 2vw, 2.6rem) 1.2rem; text-align: center; }
.vl-cifra__n {
  display: block; font-family: var(--vl-font-display);
  font-size: clamp(1.9rem, 1.3rem + 2.2vw, 2.9rem);
  font-weight: 800; line-height: 1; letter-spacing: -0.04em; color: #fff;
}
.vl-cifra__l { display: block; margin-top: 0.55rem; font-size: var(--vl-fs-sm); color: var(--vl-text-3); }

/* --------------------------------------------------------------------------
   9. LA SALA  (texto + mosaico de fotografías)
   -------------------------------------------------------------------------- */
.vl-sala { display: grid; gap: var(--vl-gap-lg); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 940px) { .vl-sala { grid-template-columns: 0.95fr 1.05fr; } }

/* Mosaico de tres: una alta a la izquierda y dos apiladas a la derecha. Una
   rejilla de tres iguales convertía la sala en un catálogo; así se lee como
   una composición. */
.vl-mosaico { display: grid; gap: clamp(0.6rem, 0.4rem + 0.8vw, 1rem); grid-template-columns: 1fr 1fr; grid-template-rows: repeat(2, minmax(0, 1fr)); }
.vl-mosaico img { width: 100%; height: 100%; object-fit: cover; border-radius: var(--vl-radius); box-shadow: var(--vl-shadow); }
.vl-mosaico > :first-child { grid-row: span 2; }
.vl-mosaico > * { min-height: 165px; }
@media (min-width: 940px) { .vl-mosaico > * { min-height: 200px; } }

.vl-lista-check { list-style: none; padding: 0; margin: 1.6rem 0 0; display: grid; gap: 0.85rem; }
.vl-lista-check li {
  display: grid; grid-template-columns: 1.4rem 1fr; gap: 0.75rem;
  align-items: start; color: var(--vl-text-2); font-size: var(--vl-fs-sm);
}
.vl-lista-check li::before {
  content: ""; margin-top: 0.42em;
  width: 1.4rem; height: 1.4rem; margin-left: -0.05rem;
  background: var(--vl-accent);
  /* La marca se dibuja con máscara y no con un SVG de fondo: así hereda el
     color del token y basta cambiar una variable para repintarlas todas. */
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 1.05rem no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center / 1.05rem no-repeat;
  flex-shrink: 0;
}
.vl-lista-check strong { color: #fff; }

/* --------------------------------------------------------------------------
   10. EQUIPAMIENTO
   Cada bloque es una partida del dossier técnico. La marca y el modelo van en
   el titular a propósito: un promotor busca exactamente eso.
   -------------------------------------------------------------------------- */
.vl-equipo { display: grid; gap: clamp(0.9rem, 0.5rem + 1.4vw, 1.4rem); grid-template-columns: 1fr; }
@media (min-width: 700px) { .vl-equipo { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1040px) { .vl-equipo { grid-template-columns: repeat(3, 1fr); } }

.vl-eq {
  display: flex; flex-direction: column;
  padding: clamp(1.4rem, 1.1rem + 1.2vw, 1.9rem);
  background: var(--vl-bg-3); background-image: var(--vl-superficie);
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
  box-shadow: var(--vl-filo);
  transition: border-color var(--vl-dur) var(--vl-ease), transform var(--vl-dur) var(--vl-ease);
}
.vl-eq:hover { border-color: var(--vl-primary); transform: translateY(-3px); }
@media (prefers-reduced-motion: reduce) { .vl-eq:hover { transform: none; } }
.vl-eq__icono {
  width: 44px; height: 44px; margin-bottom: 1.1rem;
  display: grid; place-items: center;
  color: var(--vl-accent); background: rgba(194, 102, 217, 0.12);
  border-radius: var(--vl-radius-sm);
}
.vl-eq__icono svg { width: 22px; height: 22px; }
.vl-eq h3 { font-size: var(--vl-fs-lg); margin-bottom: 0.35em; }
.vl-eq__cant {
  display: block; margin-bottom: 0.55rem;
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--vl-accent);
}
.vl-eq p { font-size: var(--vl-fs-sm); }

/* Plano del escenario. Dibujado en CSS: dos rectángulos anidados y sus
   medidas, que es exactamente lo que dice el dossier. Un SVG aquí sería más
   peso para decir lo mismo. */
.vl-escenario { display: grid; gap: var(--vl-gap-lg); grid-template-columns: 1fr; align-items: center; margin-top: var(--vl-gap-lg); }
@media (min-width: 860px) { .vl-escenario { grid-template-columns: 0.85fr 1.15fr; } }
/* Las dos zonas van APILADAS, no una dentro de otra: la batería al fondo del
   escenario y la banda por delante, que es como está distribuido de verdad.
   Anidadas —que fue el primer intento— la caja de batería caía justo encima
   del rótulo de la zona de banda y se leían las dos superpuestas. */
.vl-plano {
  position: relative; aspect-ratio: 4 / 3;
  display: grid; grid-template-rows: 34% 1fr; gap: 0.7rem;
  justify-items: center;
  padding: 1.5rem 1.5rem 2.6rem;
  background: var(--vl-bg-2); background-image: var(--vl-superficie);
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
}
.vl-plano__banda, .vl-plano__bateria {
  display: grid; place-content: center; text-align: center;
  border-radius: var(--vl-radius-sm);
  font-size: 0.72rem; line-height: 1.35; color: var(--vl-text-2);
}
/* Rellena y con borde continuo: es la zona reservada, y se distingue de la
   otra a primera vista sin necesidad de leer nada. */
.vl-plano__bateria {
  width: 38%; height: 100%;
  border: 1.5px solid var(--vl-primary);
  background: rgba(143, 47, 166, 0.16);
}
.vl-plano__banda {
  width: 100%; height: 100%;
  border: 1.5px dashed rgba(194, 102, 217, 0.55);
}
.vl-plano strong { display: block; color: #fff; font-size: 0.82rem; }
.vl-plano__pie {
  position: absolute; left: 0; right: 0; bottom: 0.7rem;
  text-align: center; font-size: 0.7rem; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--vl-text-3);
}

/* --------------------------------------------------------------------------
   11. QUÉ INCLUYE / DE QUÉ SE ENCARGA EL PROMOTOR
   Dos columnas enfrentadas. El reparto de tareas es la duda número uno de
   quien alquila, así que se responde en una sola pantalla.
   -------------------------------------------------------------------------- */
.vl-reparto { display: grid; gap: var(--vl-gap-md); grid-template-columns: 1fr; }
@media (min-width: 860px) { .vl-reparto { grid-template-columns: repeat(2, 1fr); } }
.vl-caja {
  padding: clamp(1.5rem, 1.1rem + 1.6vw, 2.2rem);
  background: var(--vl-bg-3); background-image: var(--vl-superficie);
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
  box-shadow: var(--vl-filo);
}
/* La columna de lo incluido lleva el filo de color: es la que vende. */
.vl-caja--destacada { border-color: rgba(194, 102, 217, 0.4); }
.vl-caja h3 { font-size: var(--vl-fs-lg); margin-bottom: 0.2em; }
.vl-caja__sub { font-size: var(--vl-fs-sm); color: var(--vl-text-3); margin-bottom: 1.4rem; }
.vl-caja .vl-lista-check { margin-top: 0; }
.vl-caja--promotor .vl-lista-check li::before { background: var(--vl-text-3); }

/* --------------------------------------------------------------------------
   12. PRECIO
   -------------------------------------------------------------------------- */
.vl-precio {
  display: grid; gap: var(--vl-gap-md); grid-template-columns: 1fr; align-items: center;
  padding: clamp(1.6rem, 1.1rem + 1.8vw, 2.6rem);
  background: var(--vl-bg-3); background-image: var(--vl-superficie);
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
  box-shadow: var(--vl-filo);
}
@media (min-width: 760px) { .vl-precio { grid-template-columns: auto 1fr; gap: clamp(2rem, 1rem + 3vw, 3.4rem); } }
.vl-precio__cifra { display: flex; align-items: baseline; gap: 0.5rem; }
.vl-precio__cifra span {
  font-family: var(--vl-font-display); font-weight: 800; line-height: 1;
  font-size: clamp(2.8rem, 2rem + 3.4vw, 4.4rem); color: #fff;
}
.vl-precio__cifra small { font-size: var(--vl-fs-base); color: var(--vl-text-3); }
.vl-precio__texto h3 { font-size: var(--vl-fs-xl); margin-bottom: 0.4em; }

/* Franja del 100 % de la taquilla. Deliberadamente distinta del resto: es el
   argumento que separa esta oferta de la de cualquier otra sala. */
.vl-taquilla {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.6rem;
  margin: 0 0 var(--vl-gap-md); padding: 1rem 1.3rem;
  background: linear-gradient(100deg, rgba(143, 47, 166, 0.28), rgba(143, 47, 166, 0.07));
  border: 1px solid rgba(194, 102, 217, 0.38); border-radius: var(--vl-radius);
}
.vl-taquilla strong {
  font-family: var(--vl-font-display); font-size: var(--vl-fs-xl);
  font-weight: 800; color: #fff; letter-spacing: -0.01em;
}
.vl-taquilla span { font-size: var(--vl-fs-base); color: var(--vl-text-2); }

.vl-notas { list-style: none; padding: 0; margin: var(--vl-gap-md) 0 0; display: grid; gap: 0.6rem; }
.vl-notas li { font-size: var(--vl-fs-sm); color: var(--vl-text-3); display: flex; gap: 0.6rem; }
.vl-notas li::before { content: "·"; color: var(--vl-accent); font-weight: 700; }

/* --------------------------------------------------------------------------
   13. PRÓXIMOS CONCIERTOS
   -------------------------------------------------------------------------- */
/* Rejilla mientras haya pocos carteles. En cuanto pasan de cuatro, el guion
   añade `is-carrusel` y esta rejilla deja de aplicarse. */
.vl-conciertos { display: grid; gap: clamp(1rem, 0.6rem + 1.4vw, 1.6rem); grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); }

/* --- Carrusel continuo ----------------------------------------------------
   Dos copias idénticas de la lista, una detrás de otra, desplazándose hacia la
   izquierda. Cuando la primera copia termina de salir, la animación vuelve a
   cero y en pantalla está la segunda exactamente en la misma posición: el corte
   no se ve y el bucle es infinito sin tocar nada desde JS en cada fotograma.

   La clave del truco es que el hueco entre tarjetas viva DENTRO de cada copia
   (gap + padding derecho) y no en la pista. Si el hueco lo pusiera la pista,
   el 50 % del desplazamiento no coincidiría con el ancho de una copia y el
   salto se notaría en cada vuelta. */
.vl-conciertos.is-carrusel {
  /* En móvil el cartel ocupa casi todo el ancho pero deja ver el siguiente
     asomando: es lo que dice, sin escribirlo, que la fila sigue. */
  --vl-carrusel-ancho: 320px;
  --vl-carrusel-gap: clamp(1rem, 0.6rem + 1.4vw, 1.6rem);
  display: block;
  overflow: hidden;
  /* Los carteles se desvanecen contra los bordes en vez de cortarse en seco,
     que es lo que delata que hay más fuera de la pantalla. */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 4%, #000 96%, transparent);
}
.vl-carrusel__pista {
  display: flex;
  width: max-content;
  animation: vl-desfile var(--vl-carrusel-dur, 60s) linear infinite;
}
.vl-carrusel__grupo {
  display: flex;
  gap: var(--vl-carrusel-gap);
  padding-right: var(--vl-carrusel-gap);
}
.is-carrusel .vl-concierto { flex: 0 0 var(--vl-carrusel-ancho); width: var(--vl-carrusel-ancho); }
@media (max-width: 620px) { .vl-conciertos.is-carrusel { --vl-carrusel-ancho: 76vw; } }

@keyframes vl-desfile {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}

/* Se para al pasar por encima y al llegar el foco por teclado: dentro de cada
   tarjeta hay un enlace de entradas, y perseguir un enlace en movimiento no
   hay quien lo haga. En pantallas táctiles el primer toque cuenta como hover,
   así que también se detiene al tocarlo. */
.vl-conciertos.is-carrusel:hover .vl-carrusel__pista,
.vl-conciertos.is-carrusel:focus-within .vl-carrusel__pista { animation-play-state: paused; }

/* Con movimiento reducido no hay desfile: se queda en un carrusel que se
   arrastra a mano, con parada en cada cartel. El guion no llega a duplicar la
   lista en este caso, así que aquí solo hay una copia. */
@media (prefers-reduced-motion: reduce) {
  .vl-conciertos.is-carrusel {
    overflow-x: auto;
    scroll-snap-type: x mandatory;
    -webkit-overflow-scrolling: touch;
    padding-bottom: 0.6rem;
  }
  .vl-carrusel__pista { animation: none; }
  .is-carrusel .vl-concierto { scroll-snap-align: start; }
}
/* El `display:flex` de abajo pisa el `[hidden] { display:none }` que trae el
   navegador de serie, porque una regla del tema gana a la del navegador. Sin
   esto, el filtro del calendario marcaba las tarjetas como ocultas y se
   seguían viendo todas. */
.vl-concierto[hidden] { display: none; }

.vl-concierto {
  display: flex; flex-direction: column;
  background: var(--vl-bg-3); border: 1px solid var(--vl-line);
  border-radius: var(--vl-radius); overflow: hidden;
  transition: border-color var(--vl-dur) var(--vl-ease), transform var(--vl-dur) var(--vl-ease);
}
.vl-concierto:hover { border-color: var(--vl-primary); transform: translateY(-4px); }
@media (prefers-reduced-motion: reduce) { .vl-concierto:hover { transform: none; } }
/* El cartel se ve entero, sin recortar: es una pieza de diseño ajena y
   recortarla por la mitad la estropea. */
.vl-concierto__cartel { display: block; background: #000; }
.vl-concierto__cartel img { width: 100%; height: auto; }
.vl-concierto__cuerpo { padding: 1.1rem 1.2rem 1.3rem; display: flex; flex-direction: column; flex: 1; }
.vl-concierto__fecha {
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--vl-accent); margin-bottom: 0.45rem;
}
.vl-concierto h3 { font-size: var(--vl-fs-lg); margin-bottom: 0.3em; }
.vl-concierto p { font-size: var(--vl-fs-sm); margin-bottom: 1rem; }
.vl-concierto__pie { margin-top: auto; font-size: var(--vl-fs-sm); }
.vl-concierto__pie a { font-weight: 700; text-decoration: none; }
.vl-concierto__pie a:hover { text-decoration: underline; }

/* Botón bajo la rejilla de carteles. Solo posiciona: el botón en sí es un
   `.vl-btn .vl-btn--outline` como todos los demás del sitio. Antes tenía
   borde, radio y tamaño propios y se parecía a los otros botones solo un poco,
   que es peor que no parecerse nada. */
.vl-conciertos__todos { margin-top: clamp(1.4rem, 1rem + 1.4vw, 2.2rem); text-align: center; }

/* --------------------------------------------------------------------------
   14. CONTACTO
   -------------------------------------------------------------------------- */
.vl-contacto {
  position: relative; overflow: hidden;
  background: var(--vl-bg-3);
}
.vl-contacto::before {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(70% 120% at 15% 0%, rgba(143, 47, 166, 0.3), transparent 62%);
}
.vl-contacto__grid { position: relative; display: grid; gap: var(--vl-gap-lg); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 940px) { .vl-contacto__grid { grid-template-columns: 1.1fr 0.9fr; } }

/* La columna de datos es mucho más corta que el formulario. Pegada al hacer
   scroll acompaña toda la lectura en vez de dejar medio metro de vacío. */
@media (min-width: 940px) { .vl-contacto__datos { position: sticky; top: var(--vl-tope); } }

.vl-datos { list-style: none; padding: 0; margin: 0 0 1.8rem; display: grid; gap: 1.2rem; }
.vl-datos dt { font-size: 0.8125rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--vl-text-3); margin-bottom: 0.25rem; }
.vl-datos dd { margin: 0; font-size: var(--vl-fs-lg); font-weight: 700; color: #fff; }
.vl-datos a { color: #fff; text-decoration: none; }
.vl-datos a:hover { color: var(--vl-accent); }

.vl-mapa {
  display: flex; align-items: center; gap: 1rem;
  padding: 1.3rem 1.4rem; text-decoration: none;
  background: var(--vl-bg-2); border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
  transition: border-color var(--vl-dur) var(--vl-ease);
}
.vl-mapa:hover { border-color: var(--vl-primary); }
.vl-mapa svg { flex-shrink: 0; color: var(--vl-accent); }
.vl-mapa__texto { display: grid; gap: 0.15rem; font-size: var(--vl-fs-sm); color: var(--vl-text-2); }
.vl-mapa__texto strong { color: #fff; font-size: var(--vl-fs-base); }

/* --------------------------------------------------------------------------
   15. FORMULARIO
   Etiqueta arriba, error debajo. Contraste AA sobre fondo oscuro.
   -------------------------------------------------------------------------- */
.vl-form { display: grid; gap: 1.1rem; }
.vl-form__fila { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 620px) { .vl-form__fila { grid-template-columns: 1fr 1fr; } }

.vl-form label { display: block; font-size: var(--vl-fs-sm); font-weight: 700; color: #fff; }
.vl-form label .vl-opt { font-weight: 400; color: var(--vl-text-3); }
.vl-form input[type="text"], .vl-form input[type="email"],
.vl-form input[type="tel"], .vl-form input[type="date"], .vl-form textarea {
  display: block; width: 100%; margin-top: 0.45rem;
  padding: 0.85rem 1rem;
  background: var(--vl-bg); color: #fff;
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius-sm);
  font-weight: 400;
  transition: border-color 220ms var(--vl-ease), box-shadow 220ms var(--vl-ease);
}
.vl-form input::placeholder, .vl-form textarea::placeholder { color: var(--vl-text-3); }
.vl-form input:focus, .vl-form textarea:focus {
  border-color: var(--vl-accent); outline: none;
  box-shadow: 0 0 0 3px rgba(194, 102, 217, 0.22);
}
.vl-form input[aria-invalid="true"], .vl-form textarea[aria-invalid="true"] { border-color: #ff8a8a; }
.vl-form textarea { height: 150px; min-height: 110px; resize: vertical; }

/* El selector de fecha nativo pinta su icono en negro sobre fondo negro. */
.vl-form input[type="date"]::-webkit-calendar-picker-indicator {
  filter: invert(58%) sepia(38%) saturate(1200%) hue-rotate(250deg);
  cursor: pointer;
}

/* El hueco del aviso existe siempre en el HTML para que el guion pueda
   escribir dentro sin recolocar nada, pero mientras está vacío no debe ocupar
   ni un píxel: si no, el formulario nace con seis huecos de aire repartidos. */
.vl-form__error { display: block; margin-top: 0.4rem; font-size: 0.8125rem; font-weight: 400; color: #ff8a8a; }
.vl-form__error:empty { display: none; }

/* La casilla y su texto se alinean por la PRIMERA línea del texto, no por el
   bloque entero (el texto ocupa dos o tres líneas). La medida va en `em` y con
   la misma altura de línea que el texto: así la casilla mide exactamente lo
   que mide una línea y las dos empiezan a la vez, sin márgenes a ojo que se
   descuadran en cuanto cambia el tamaño de letra. */
.vl-form__rgpd {
  display: flex; align-items: flex-start; gap: 0.75rem;
  font-weight: 400; color: var(--vl-text-2); font-size: var(--vl-fs-sm);
  line-height: 1.5; cursor: pointer;
}
.vl-form__rgpd > span { display: block; }

.vl-form__rgpd input[type="checkbox"] {
  appearance: none; flex-shrink: 0;
  width: 1.5em; height: 1.5em; margin: 0;
  background: var(--vl-bg);
  /* Borde en color de marca y de 2px: con el gris de las líneas la casilla
     desaparecía sobre el fondo oscuro y no se veía que hubiera nada que
     marcar. */
  border: 2px solid var(--vl-primary);
  border-radius: var(--vl-radius-sm); cursor: pointer;
  background-repeat: no-repeat; background-position: center;
  background-size: 76% 76%;
  transition: background-color var(--vl-dur) var(--vl-ease), border-color var(--vl-dur) var(--vl-ease);
}
.vl-form__rgpd input[type="checkbox"]:hover { border-color: var(--vl-accent); }

/* Marcada: morado entero con el tic blanco dentro. El tic va como imagen de
   fondo en SVG y no como ::after, porque los pseudoelementos sobre un <input>
   no funcionan en todos los navegadores. */
.vl-form__rgpd input[type="checkbox"]:checked {
  background-color: var(--vl-primary);
  border-color: var(--vl-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23ffffff' stroke-width='3.2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M4 12.5l5.5 5.5L20 6.5'/%3E%3C/svg%3E");
}
.vl-form__rgpd input[type="checkbox"]:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: 2px; }
.vl-form__rgpd input[type="checkbox"]:checked {
  background: var(--vl-primary); border-color: var(--vl-primary);
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='14' viewBox='0 0 24 24' fill='none' stroke='white' stroke-width='3.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: center;
}
.vl-form button[type="submit"] { justify-self: start; margin-top: 0.5rem; border: 0; }

/* Trampa para robots: un campo que ningún humano ve y que ninguno rellena.
   `display:none` lo saltan algunos rellenadores automáticos, así que además
   sale del flujo y se esconde a los lectores de pantalla con aria-hidden. */
.vl-trampa { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.vl-aviso {
  margin-bottom: 1.6rem;
  padding: 1rem 1.3rem; border-radius: var(--vl-radius);
  font-size: var(--vl-fs-sm);
  background: rgba(255, 138, 138, 0.1); border: 1px solid rgba(255, 138, 138, 0.4);
  color: #ffc9c9;
}
.vl-aviso p { color: inherit; margin-bottom: 0.5rem; }
.vl-aviso p:last-child { margin-bottom: 0; }
.vl-aviso ul { margin: 0; padding-left: 1.1rem; display: grid; gap: 0.3rem; }
.vl-aviso a { color: inherit; text-decoration: underline; }
.vl-aviso a:hover { color: #fff; }
.vl-aviso strong { color: #fff; }
/* Recibe el foco desde el guion al fallar la validación, pero no es un control:
   no debe dibujar el anillo de foco como si se pudiera pulsar. */
.vl-aviso:focus { outline: none; }

/* --------------------------------------------------------------------------
   16. PIE
   -------------------------------------------------------------------------- */
.vl-footer {
  background: var(--vl-bg-2); border-top: 1px solid var(--vl-line);
  padding-block: clamp(2.6rem, 2rem + 2.4vw, 3.6rem) 2rem;
  font-size: var(--vl-fs-sm); position: relative; z-index: 1;
}
.vl-footer__grid { display: grid; gap: 2.2rem; grid-template-columns: 1fr; }
@media (min-width: 760px) { .vl-footer__grid { grid-template-columns: 1.4fr 1fr 1fr; } }
.vl-footer p, .vl-footer li { color: var(--vl-text-2); }
.vl-footer a { color: var(--vl-text-2); text-decoration: none; }
.vl-footer a:hover { color: #fff; }
.vl-footer strong { color: #fff; }
.vl-footer h2 { font-size: var(--vl-fs-sm); letter-spacing: 0.14em; text-transform: uppercase; color: var(--vl-text-3); font-family: var(--vl-font); font-weight: 700; margin-bottom: 1rem; }
.vl-footer ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.5rem; }
.vl-footer__logo img { height: 104px; width: auto; margin-bottom: 1.1rem; }
.vl-footer__bottom {
  margin-top: 2.6rem; padding-top: 1.5rem; border-top: 1px solid var(--vl-line);
  display: flex; flex-wrap: wrap; gap: 1rem; justify-content: space-between;
  align-items: center; font-size: 0.8125rem; color: var(--vl-text-3);
}
.vl-footer__credit a { color: var(--vl-accent); }

/* --------------------------------------------------------------------------
   17. PÁGINAS DE ESTADO  (gracias y 404)
   -------------------------------------------------------------------------- */
.vl-estado {
  position: relative; isolation: isolate;
  display: grid; place-items: center; text-align: center;
  min-height: calc(100vh - var(--vl-header-h));
  padding-block: clamp(3rem, 2rem + 5vw, 6rem);
}
.vl-estado::before {
  content: ""; position: absolute; z-index: -1; inset: 0; pointer-events: none;
  background: radial-gradient(60% 60% at 50% 30%, rgba(143, 47, 166, 0.28), transparent 70%);
}
.vl-estado__inner { max-width: 56ch; }
.vl-estado h1 { margin-bottom: 0.4em; }
.vl-estado .vl-lead { margin-inline: auto; }
.vl-estado__actions { display: flex; flex-wrap: wrap; gap: 0.9rem; justify-content: center; margin-top: 2.2rem; }
.vl-estado__cifra {
  display: block; font-family: var(--vl-font-display);
  font-size: clamp(5rem, 3rem + 14vw, 11rem); font-weight: 800; line-height: 0.9;
  letter-spacing: -0.05em; color: transparent;
  -webkit-text-stroke: 2px rgba(194, 102, 217, 0.5);
  margin-bottom: 0.15em;
}
.vl-estado__marca { width: clamp(180px, 34vw, 260px); margin: 0 auto 2rem; }

/* Atajos de la 404: en una web de una sola página, lo que hay que ofrecer son
   sus secciones. */
.vl-atajos { display: grid; gap: 1rem; grid-template-columns: 1fr; margin-top: 2.6rem; text-align: left; }
@media (min-width: 700px) { .vl-atajos { grid-template-columns: repeat(2, 1fr); } }
.vl-atajo {
  display: grid; gap: 0.2rem;
  padding: 1.2rem 1.4rem; text-decoration: none;
  background: var(--vl-bg-3); border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
  transition: border-color var(--vl-dur) var(--vl-ease);
}
.vl-atajo:hover { border-color: var(--vl-primary); }
.vl-atajo strong { color: #fff; font-family: var(--vl-font-display); font-size: var(--vl-fs-lg); }
.vl-atajo span { color: var(--vl-text-2); font-size: var(--vl-fs-sm); }

/* Las tres puertas de la portada reutilizan el componente de atajos del 404.
   Dos diferencias por el sitio donde van: son TRES —a dos columnas la última se
   quedaba sola a media fila— y llevan encima un .vl-encabezado que ya separa,
   así que el margen superior del componente sobra. */
.vl-atajos--perfiles { margin-top: 0; }
@media (min-width: 940px) { .vl-atajos--perfiles { grid-template-columns: repeat(3, 1fr); } }

/* --------------------------------------------------------------------------
   18. ENTRADA DE LOS BLOQUES
   Solo se activa si hay JS (la clase `js` la pone la propia página antes de
   pintar). Sin ella, todo se ve desde el primer momento: un fallo del guion no
   puede dejar la página en blanco.
   -------------------------------------------------------------------------- */
.js .vl-reveal { opacity: 0; transform: translateY(18px); }
.js .vl-reveal.is-visible {
  opacity: 1; transform: none;
  transition: opacity 700ms var(--vl-ease) var(--vl-delay, 0ms),
              transform 700ms var(--vl-ease) var(--vl-delay, 0ms);
}
@media (prefers-reduced-motion: reduce) {
  .js .vl-reveal { opacity: 1; transform: none; }
}

@media print {
  .vl-header, .vl-hero__foto, .vl-nav-toggle { display: none; }
  body { background: #fff; color: #000; }
}

/* --------------------------------------------------------------------------
   20. WORDPRESS
   Reglas que en el sitio estático iban como atributo style= en el HTML. Al
   pasar a plantillas hay un solo header y un solo footer para varias páginas,
   así que lo que cambia entre ellas tiene que ser una clase y no un estilo
   pegado a mano.
   -------------------------------------------------------------------------- */

/* Medida de lectura para los textos legales. A todo el ancho del contenedor
   salen líneas de 140 caracteres y el ojo pierde el renglón al volver. */
.vl-container--texto { max-width: 760px; }

/* Los enlaces legales van en fila. Hay que decirlo explícitamente porque
   `.vl-footer ul` los pone en rejilla vertical. */
.vl-footer__legal { display: flex; flex-wrap: wrap; gap: 1.2rem; list-style: none; margin: 0; padding: 0; }

/* Contenido que escribe el editor de WordPress. Los textos legales son la
   única parte de la web donde el HTML no lo controla la plantilla, así que
   aquí sí hacen falta reglas de tipografía corrida. */
.vl-texto > h2 { margin-top: 2.2em; }
.vl-texto > h3 { margin-top: 1.8em; }
.vl-texto > :first-child { margin-top: 0; }
.vl-texto ul, .vl-texto ol { color: var(--vl-text-2); }
.vl-texto li { margin-bottom: 0.5em; }
.vl-texto a { color: var(--vl-accent); }

/* Barra de administración: sin esto se come 32 px de la cabecera fija y el
   logo queda por debajo del borde de la pantalla. Solo la ve quien ha
   iniciado sesión. */
body.admin-bar .vl-header { top: 32px; }
@media screen and (max-width: 782px) {
  body.admin-bar .vl-header { top: 46px; }
}

/* --------------------------------------------------------------------------
   21. RESERVAS
   -------------------------------------------------------------------------- */

/* El calendario a la izquierda y el formulario a la derecha. En vertical el
   calendario va primero: la primera pregunta de quien entra es «¿está libre
   el 14?», y hacerle bajar quince campos para averiguarlo lo pierde. */
.vl-reservas { display: grid; gap: var(--vl-gap-lg); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 1000px) { .vl-reservas { grid-template-columns: minmax(320px, 0.85fr) 1.15fr; } }

/* El calendario acompaña al formulario mientras se rellena: sin esto, al bajar
   a los últimos campos ya no se ve qué días estaban libres. */
@media (min-width: 1000px) {
  .vl-reservas__cal { position: sticky; top: var(--vl-tope); }
}

.vl-reservas h2 { font-size: var(--vl-fs-xl); margin-bottom: 1.2rem; }

/* --- Calendario ----------------------------------------------------------- */
.vl-cal {
  background: var(--vl-bg-3); border: 1px solid var(--vl-line);
  border-radius: var(--vl-radius); padding: 1.2rem;
}
.vl-cal__barra { display: flex; align-items: center; justify-content: space-between; gap: 0.6rem; margin-bottom: 1rem; }
.vl-cal__mes { font-size: var(--vl-fs-lg); margin: 0; text-transform: capitalize; text-align: center; flex: 1; }
.vl-cal__nav {
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; flex-shrink: 0;
  border: 1px solid var(--vl-line); border-radius: 50%;
  color: var(--vl-text-2); text-decoration: none;
  transition: border-color var(--vl-dur) var(--vl-ease), color var(--vl-dur) var(--vl-ease);
}
.vl-cal__nav:hover { border-color: var(--vl-primary); color: var(--vl-accent); }
.vl-cal__nav.is-off { visibility: hidden; }

.vl-cal__cabecera, .vl-cal__dias { display: grid; grid-template-columns: repeat(7, 1fr); gap: 4px; }
.vl-cal__cabecera {
  margin-bottom: 6px; font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--vl-text-3); text-align: center;
}

/* Cada día es un cuadrado. `aspect-ratio` en vez de altura fija para que la
   rejilla siga siendo cuadrada a cualquier ancho. */
.vl-cal__dia {
  display: flex; align-items: center; justify-content: center;
  aspect-ratio: 1; width: 100%;
  border: 1px solid transparent; border-radius: var(--vl-radius-sm);
  font-size: 0.875rem; font-weight: 600; font-variant-numeric: tabular-nums;
  background: transparent; color: var(--vl-text-3); padding: 0;
}
.vl-cal__hueco { aspect-ratio: 1; }

/* LIBRE: relleno de morado suave con borde de marca, como estaba al principio.
   Aquel calendario se veía más vivo, y el problema que tenía —confundirse con
   los días ocupados— ya no existe: entonces el concierto también iba en
   morado claro, y ahora todo lo ocupado es un gris apagado. El color vuelve a
   señalar lo único que importa, que es dónde se puede pulsar. */
button.vl-cal__dia.is-libre {
  background: color-mix(in srgb, var(--vl-primary) 16%, transparent);
  border-color: color-mix(in srgb, var(--vl-primary) 42%, transparent);
  color: #fff; cursor: pointer;
  transition: background var(--vl-dur) var(--vl-ease),
              border-color var(--vl-dur) var(--vl-ease),
              transform var(--vl-dur) var(--vl-ease);
}
button.vl-cal__dia.is-libre:hover {
  background: var(--vl-primary); border-color: var(--vl-primary); transform: translateY(-2px);
}
button.vl-cal__dia.is-libre:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: 2px; }

/* El día ELEGIDO sí va en color de marca: es el único que está "puesto". */
button.vl-cal__dia.is-libre.is-elegido {
  background: var(--vl-primary); border-color: var(--vl-primary);
  box-shadow: 0 0 0 2px var(--vl-accent);
}

/* RESERVADO: relleno y apagado. Da igual si es un concierto, una reserva
   confirmada o un cierre: desde fuera es lo mismo, un día que no se puede
   pedir. */
.vl-cal__dia.is-reservado {
  background: var(--vl-bg-2); color: var(--vl-text-3);
  border-color: var(--vl-bg-2);
}

/* Los días de la semana en que la sala no alquila, y los ya pasados, se
   difuminan en vez de marcarse: no son una respuesta («ocupado»), son días que
   no entran en la conversación. */
.vl-cal__dia.is-semana { opacity: 0.3; }
.vl-cal__dia.is-pasado { opacity: 0.18; }

@media (prefers-reduced-motion: reduce) {
  button.vl-cal__dia.is-libre:hover { transform: none; }
}

.vl-cal__leyenda {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.1rem;
  list-style: none; padding: 0; margin: 1.1rem 0 0;
  font-size: 0.78rem; color: var(--vl-text-3);
}
.vl-cal__leyenda li { display: flex; align-items: center; gap: 0.4rem; }
/* Los puntos de la leyenda imitan al día real: el libre, vacío con borde; el
   reservado, relleno. Si no coincidieran, la leyenda explicaría un calendario
   distinto del que hay encima. */
.vl-cal__punto { width: 12px; height: 12px; border-radius: 3px; flex-shrink: 0; }
.vl-cal__punto.is-libre     { background: color-mix(in srgb, var(--vl-primary) 55%, transparent); }
.vl-cal__punto.is-reservado { background: var(--vl-bg-2); border: 1px solid var(--vl-line); }

.vl-cal__pie { font-size: 0.78rem; color: var(--vl-text-3); margin: 0.9rem 0 0; }

/* --- Formulario largo ------------------------------------------------------ */
/* Un formulario de quince campos seguidos se abandona. Agrupado en tres
   bloques cortos con su título se lee como tres preguntas, no como un trámite. */
.vl-campos { border: 0; padding: 0; margin: 0 0 var(--vl-gap-md); }
.vl-campos legend {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--vl-accent);
  padding: 0; margin-bottom: 1rem;
}
.vl-form select {
  width: 100%; font: inherit; color: var(--vl-text);
  background: var(--vl-bg-2); border: 1px solid var(--vl-line);
  border-radius: var(--vl-radius-sm); padding: 0.85em 1em;
}
.vl-form select:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: 1px; }
.vl-form__nota { font-size: 0.78rem; color: var(--vl-text-3); margin: 1rem 0 0; }

/* --- Formulario de reservas ------------------------------------------------
   Quince preguntas. En vez de filas fijas de dos en dos, una rejilla de dos
   columnas donde cada campo dice si ocupa media fila o la fila entera: las
   preguntas largas (nombre del evento, conformidad, comentarios) necesitan el
   ancho completo y las cortas se emparejan solas. */
.vl-form__rejilla { display: grid; gap: 1.1rem; grid-template-columns: 1fr; }
@media (min-width: 620px) { .vl-form__rejilla { grid-template-columns: 1fr 1fr; } }
.vl-form__campo { min-width: 0; }
.vl-form__campo--ancho { grid-column: 1 / -1; }

/* --- Alineación de las preguntas de una misma fila ------------------------ */
/* Dos preguntas que comparten fila no miden lo mismo: unas llevan aclaración y
   otras no, y unas etiquetas ocupan una línea y otras dos. Con la maquetación
   normal cada campo empieza justo debajo de SU etiqueta, así que el de la
   izquierda quedaba más arriba que el de la derecha y la fila se veía torcida.

   Se arregla empujando el campo al fondo de su celda: el título y la aclaración
   crecen hacia arriba y los campos de la fila acaban todos a la misma altura,
   que es la línea que sigue el ojo al rellenar. Los títulos siguen empezando
   arriba, que es donde se leen.

   Solo a partir de 620 px: por debajo hay una sola columna y no hay nada que
   alinear. */
@media (min-width: 620px) {
  .vl-form__rejilla > .vl-form__campo { display: flex; }

  .vl-form__rejilla > .vl-form__campo > label,
  .vl-form__rejilla > .vl-form__campo > fieldset {
    display: flex; flex-direction: column;
    /* El hueco entre piezas lo pone `gap` y no los márgenes de cada una: con
       márgenes, el `margin-top: auto` de abajo los anularía y el campo quedaría
       pegado a su aclaración en la pregunta más alta de la fila. */
    gap: 0.45rem;
    flex: 1 1 auto; min-width: 0;
  }

  .vl-form__rejilla > .vl-form__campo .vl-form__ayuda,
  .vl-form__rejilla > .vl-form__campo .vl-form__error,
  .vl-form__rejilla > .vl-form__campo .vl-opciones__lista,
  .vl-form__rejilla > .vl-form__campo input,
  .vl-form__rejilla > .vl-form__campo textarea { margin-top: 0; }

  .vl-form__rejilla > .vl-form__campo > label > input,
  .vl-form__rejilla > .vl-form__campo > label > textarea,
  .vl-form__rejilla > .vl-form__campo > fieldset > .vl-opciones__lista { margin-top: auto; }
}

/* Envuelve el título de la pregunta y su «(opcional)». Existe para que en la
   columna flexible sigan siendo una sola pieza y no dos líneas. */
.vl-form__etiqueta { display: block; }

.vl-reserva-form__titulo { font-size: var(--vl-fs-xl); margin-bottom: 0.4em; }
.vl-reserva-form__intro { color: var(--vl-text-2); margin-bottom: var(--vl-gap-md); }

/* La aclaración de cada pregunta va bajo la etiqueta y antes del campo, que es
   donde se lee antes de contestar y no después. */
.vl-form__ayuda {
  display: block; margin-top: 0.25rem;
  font-size: 0.8125rem; font-weight: 400; line-height: 1.4;
  color: var(--vl-text-3);
}

.vl-form input[type="time"] {
  display: block; width: 100%; margin-top: 0.45rem;
  padding: 0.85rem 1rem;
  background: var(--vl-bg); color: #fff;
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius-sm);
  font-weight: 400; font-family: inherit;
  transition: border-color 220ms var(--vl-ease), box-shadow 220ms var(--vl-ease);
}
.vl-form input[type="time"]::-webkit-calendar-picker-indicator {
  filter: invert(58%) sepia(38%) saturate(1200%) hue-rotate(250deg);
  cursor: pointer;
}
.vl-form input[type="time"][aria-invalid="true"] { border-color: #ff8a8a; }

/* --- Grupos de opciones (Sí / No) ----------------------------------------- */
.vl-opciones { border: 0; padding: 0; margin: 0; min-width: 0; }
.vl-opciones legend {
  padding: 0; font-size: var(--vl-fs-sm); font-weight: 700; color: #fff;
}
.vl-opciones legend .vl-opt { font-weight: 400; color: var(--vl-text-3); }
.vl-opciones__lista { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0.6rem; }

/* Cada opción es una pastilla pulsable entera, no un puntito de 13 px con una
   palabra al lado: en móvil el objetivo pasa de ser casi inalcanzable a ocupar
   media pantalla. */
.vl-opcion {
  display: inline-flex; align-items: center; gap: 0.55rem;
  padding: 0.7rem 1.1rem;
  background: var(--vl-bg); border: 1px solid var(--vl-line);
  border-radius: var(--vl-radius-pill);
  font-size: var(--vl-fs-sm); font-weight: 400; color: var(--vl-text-2);
  cursor: pointer;
  transition: border-color var(--vl-dur) var(--vl-ease), color var(--vl-dur) var(--vl-ease);
}
.vl-opcion:hover { border-color: var(--vl-accent); color: #fff; }
/* Mismo criterio que la casilla de la política: borde en color de marca y de
   2px, porque con el gris de las líneas no se veía que hubiera nada que
   pulsar. */
.vl-opcion input[type="radio"] {
  appearance: none; flex-shrink: 0;
  width: 18px; height: 18px; margin: 0;
  background: var(--vl-bg);
  border: 2px solid var(--vl-primary); border-radius: 50%;
  cursor: pointer;
  transition: border-color var(--vl-dur) var(--vl-ease), box-shadow var(--vl-ease);
}
.vl-opcion input[type="radio"]:checked {
  border-color: var(--vl-primary);
  box-shadow: inset 0 0 0 4px var(--vl-primary);
}
.vl-opcion:has(input:checked) { border-color: var(--vl-primary); color: #fff; }
.vl-opcion input[type="radio"]:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: 2px; }

/* --------------------------------------------------------------------------
   22. AVISOS DE ENVIADO
   -------------------------------------------------------------------------- */

/* Banner que sustituye al formulario de contacto de la portada al enviarlo.
   Ocupa su hueco en vez de aparecer encima: dejar el formulario vacío debajo
   del «gracias» invita a rellenarlo otra vez y llegan dos consultas iguales. */
.vl-gracias {
  display: flex; align-items: flex-start; gap: 1rem;
  padding: 1.5rem 1.6rem;
  background: color-mix(in srgb, var(--vl-primary) 12%, var(--vl-bg-3));
  border: 1px solid color-mix(in srgb, var(--vl-primary) 45%, transparent);
  border-radius: var(--vl-radius);
}
.vl-gracias__icono {
  display: grid; place-items: center; flex-shrink: 0;
  width: 44px; height: 44px; border-radius: 50%;
  background: var(--vl-primary); color: #fff;
}
.vl-gracias strong { display: block; color: #fff; font-size: var(--vl-fs-lg); margin-bottom: 0.35em; }
.vl-gracias p { margin: 0; }
.vl-gracias:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: 3px; }

/* Pantalla de gracias tras pedir una fecha. */
.vl-estado__tic {
  display: grid; place-items: center;
  width: 68px; height: 68px; margin: 0 auto 1.6rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--vl-primary) 18%, transparent);
  border: 2px solid var(--vl-primary);
  color: var(--vl-accent);
}

/* El aviso de «todavía no hay nada reservado» tiene que leerse aunque se pase
   la vista por encima: es lo que evita que alguien dé la fecha por suya.
   Misma forma que `.vl-aviso` del formulario —caja cerrada, borde fino
   alrededor y fondo tintado— para que el sitio tenga UNA manera de avisar y no
   dos. */
.vl-estado__aviso {
  max-width: 60ch; margin-inline: auto;
  padding: 1rem 1.3rem;
  background: color-mix(in srgb, var(--vl-primary) 10%, var(--vl-bg-2));
  border: 1px solid color-mix(in srgb, var(--vl-primary) 38%, transparent);
  border-radius: var(--vl-radius);
  text-align: left; font-size: var(--vl-fs-sm); color: var(--vl-text-2);
}
.vl-estado__pie { margin-top: 2rem; font-size: var(--vl-fs-sm); color: var(--vl-text-3); }
.vl-estado__pie a { color: var(--vl-accent); }

/* --------------------------------------------------------------------------
   23. AGENDA DE CONCIERTOS
   -------------------------------------------------------------------------- */

/* Encabezado con el botón a la derecha en escritorio. En móvil el botón no
   cabe al lado del texto sin encogerlo hasta lo ilegible, así que se esconde
   aquí y sale otro debajo del carrusel: allí cae justo cuando has terminado de
   ver los carteles y quieres más. */
.vl-encabezado-fila { display: grid; gap: 1.4rem; align-items: end; margin-bottom: var(--vl-gap-lg); }
.vl-encabezado-fila .vl-encabezado { margin-bottom: 0; }
.vl-encabezado-fila__btn { display: none; }

@media (min-width: 860px) {
  .vl-encabezado-fila { grid-template-columns: 1fr auto; gap: 2rem; }
  .vl-encabezado-fila__btn { display: inline-flex; white-space: nowrap; }
}

.vl-conciertos__todos--movil { display: block; }
@media (min-width: 860px) { .vl-conciertos__todos--movil { display: none; } }

/* Calendario a la izquierda, lista a la derecha.
   El calendario va a ancho FIJO y estrecho, no a fracción: con una fracción se
   llevaba 450 px y en la lista solo cabían dos carteles. A 280 px la rejilla de
   días sigue siendo cómoda de pulsar y quedan ~800 px para las tarjetas, que es
   justo lo que piden tres. */
.vl-agenda { display: grid; gap: var(--vl-gap-lg); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 1000px) { .vl-agenda { grid-template-columns: 280px minmax(0, 1fr); } }
@media (min-width: 1180px) { .vl-agenda { grid-template-columns: 300px minmax(0, 1fr); } }
@media (min-width: 1000px) { .vl-agenda__cal { position: sticky; top: var(--vl-tope); } }
.vl-agenda h2 { font-size: var(--vl-fs-xl); margin-bottom: 1.2rem; }

/* Tres por fila fijas en escritorio, no `auto-fill`: con auto-fill el número de
   columnas dependía del ancho sobrante y saltaba de tres a dos sin avisar. */
.vl-conciertos--lista { grid-template-columns: repeat(auto-fill, minmax(220px, 1fr)); }
@media (min-width: 1000px) { .vl-conciertos--lista { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* El calendario de la agenda es más estrecho que el de reservas, así que sus
   números y su barra se ajustan para no quedar apretados. */
.vl-cal--conciertos { padding: 1rem; }
.vl-cal--conciertos .vl-cal__mes { font-size: var(--vl-fs-base); }
.vl-cal--conciertos .vl-cal__dia { font-size: 0.8125rem; }
.vl-cal--conciertos .vl-cal__nav { width: 34px; height: 34px; }

/* Mismo lenguaje de aviso que el resto del sitio: caja cerrada, borde fino y
   fondo tintado. */
.vl-agenda__vacio {
  padding: 1rem 1.3rem; text-align: center;
  background: var(--vl-bg-2);
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
  font-size: var(--vl-fs-sm); color: var(--vl-text-3);
}

/* --- Calendario en modo conciertos ---------------------------------------
   Aquí lo pulsable es justo lo contrario que en reservas: los días CON algo. */
.vl-cal__dia.is-vacio { opacity: 0.32; }
.vl-cal__dia.is-ido { opacity: 0.3; }

button.vl-cal__dia.is-concierto {
  background: color-mix(in srgb, var(--vl-primary) 16%, transparent);
  border-color: color-mix(in srgb, var(--vl-primary) 42%, transparent);
  color: #fff; cursor: pointer;
  transition: background var(--vl-dur) var(--vl-ease), transform var(--vl-dur) var(--vl-ease);
}
button.vl-cal__dia.is-concierto:hover { background: var(--vl-primary); transform: translateY(-2px); }
button.vl-cal__dia.is-concierto.is-elegido { background: var(--vl-primary); box-shadow: 0 0 0 2px var(--vl-accent); }
button.vl-cal__dia.is-concierto.is-ido { opacity: 0.55; }
button.vl-cal__dia:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  button.vl-cal__dia.is-concierto:hover { transform: none; }
}

/* El botón se comporta como todos los del sitio: en línea y del ancho de su
   texto. Antes lo estiraba al 100 % y era el único botón ancho de la web. */
.vl-cal__limpiar { margin: 1rem 0 0; text-align: center; }
.vl-cal__limpiar .vl-btn { padding: 0.72em 1.35em; font-size: 0.8125rem; }

/* Un cartel ya celebrado se apaga un poco y recupera el color al pasar por
   encima: sigue siendo material de venta —enseña lo que ha pasado por la
   sala—, pero no compite con lo que todavía tiene entradas. */
.vl-concierto.is-pasado { opacity: 0.62; transition: opacity var(--vl-dur) var(--vl-ease); }
.vl-concierto.is-pasado:hover { opacity: 1; }
.vl-concierto__celebrado {
  font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--vl-text-3);
}

/* --------------------------------------------------------------------------
   24. REDES SOCIALES
   -------------------------------------------------------------------------- */
.vl-redes { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; margin: 1.2rem 0 0; padding: 0; }
.vl-redes a {
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border: 1px solid var(--vl-line); border-radius: 50%;
  color: var(--vl-text-2);
  transition: border-color var(--vl-dur) var(--vl-ease), color var(--vl-dur) var(--vl-ease),
              transform var(--vl-dur) var(--vl-ease);
}
.vl-redes a:hover { border-color: var(--vl-primary); color: #fff; transform: translateY(-2px); }
.vl-redes a:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: 2px; }

@media (prefers-reduced-motion: reduce) {
  .vl-redes a:hover { transform: none; }
}

/* En el menú de móvil las redes van al final, separadas del listado. */
.vl-nav .vl-redes { margin-top: 1.4rem; padding-top: 1.4rem; border-top: 1px solid var(--vl-line); }
@media (min-width: 1181px) { .vl-nav .vl-redes { display: none; } }

/* --------------------------------------------------------------------------
   25. AVISO DE COOKIES
   Mismos componentes que el resto: los botones son .vl-btn, la caja usa los
   mismos fondo, borde y radio que las tarjetas, y los colores salen de los
   tokens. No hay ni un valor suelto.
   -------------------------------------------------------------------------- */
.vl-cookies {
  position: fixed; z-index: 200;
  inset-inline: 0; bottom: 0;
  padding: var(--vl-gutter);
  /* Empieza abajo del todo y sube: aparecer de golpe delante de la cara es
     agresivo, y este aviso ya interrumpe bastante por sí solo. */
  transform: translateY(110%);
  transition: transform 320ms var(--vl-ease);
}
.vl-cookies.is-visible { transform: translateY(0); }

@media (prefers-reduced-motion: reduce) {
  .vl-cookies { transition: none; }
}

.vl-cookies__caja {
  max-width: var(--vl-container); margin-inline: auto;
  display: grid; gap: 1.2rem; align-items: center;
  padding: 1.3rem 1.5rem;
  background: var(--vl-bg-3);
  border: 1px solid var(--vl-line);
  border-radius: var(--vl-radius);
  box-shadow: var(--vl-shadow-lg);
}
@media (min-width: 860px) {
  .vl-cookies__caja { grid-template-columns: 1fr auto; gap: 2rem; }
}

.vl-cookies__texto strong {
  display: block; margin-bottom: 0.3em;
  font-size: 0.75rem; font-weight: 700; letter-spacing: 0.14em;
  text-transform: uppercase; color: var(--vl-accent);
}
.vl-cookies__texto p { margin: 0; font-size: var(--vl-fs-sm); max-width: 68ch; }
.vl-cookies__texto a { color: var(--vl-accent); text-decoration: underline; }
.vl-cookies__texto a:hover { color: #fff; }

/* Los dos botones, del mismo tamaño y uno al lado del otro. Rechazar tiene que
   costar exactamente lo mismo que aceptar. */
.vl-cookies__botones { display: flex; flex-wrap: wrap; gap: 0.7rem; }
.vl-cookies__botones .vl-btn { flex: 1 1 auto; justify-content: center; padding: 0.8em 1.6em; }
@media (min-width: 860px) {
  .vl-cookies__botones .vl-btn { flex: 0 0 auto; }
}

/* Un botón que se lee como un enlace: para «Preferencias de cookies» en el
   pie, que tiene que ser un <button> porque no lleva a ninguna página. */
.vl-enlace-boton {
  padding: 0; border: 0; background: none;
  font: inherit; color: inherit; cursor: pointer;
  text-decoration: none;
}
.vl-enlace-boton:hover { color: var(--vl-accent); text-decoration: underline; }
.vl-enlace-boton:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: 2px; }


/* --------------------------------------------------------------------------
   26. PÁGINAS DE CONTENIDO
   La sala, la ficha técnica, los precios, grupos, DJs. Son documentos que se
   leen buscando un dato, no folletos que se miran: de ahí la banda de cabecera,
   la franja de cifras y el índice al margen.

   No estrenan ni un color ni una superficie. La cabecera se mete bajo la barra
   fija igual que el hero de la portada, las cifras son el mismo componente, las
   tablas usan el fondo, borde, radio y filo de .vl-eq, y los botones son los
   .vl-btn de siempre.
   -------------------------------------------------------------------------- */

/* --- Cabecera de página --------------------------------------------------- */
/* El tirón hacia arriba es lo que separa una página compuesta de un titular
   suelto sobre el fondo: la banda pasa por DEBAJO de la barra, que arriba del
   todo es traslúcida, y la página empieza en un sitio evidente. */
/* La franja de cifras trae su propio filo superior. Pegada a la cabecera, que
   también lo lleva, salían dos líneas de 1 px seguidas: se ve. */
.vl-cabecera + .vl-cifras { border-top: 0; }

.vl-cabecera {
  margin-top: calc(var(--vl-header-h) * -1);
  padding-block: calc(var(--vl-header-h) + clamp(2.6rem, 1.6rem + 3.4vw, 4.6rem)) clamp(2.6rem, 1.6rem + 3.4vw, 4.6rem);
  background: var(--vl-bg-2); background-image: var(--vl-superficie);
  border-bottom: 1px solid var(--vl-line);
}

.vl-cabecera__grid { display: grid; gap: var(--vl-gap-lg); align-items: center; }
@media (min-width: 1000px) {
  .vl-cabecera--foto .vl-cabecera__grid { grid-template-columns: 1fr 0.85fr; gap: clamp(2.4rem, 1rem + 4vw, 4rem); }
}

.vl-cabecera h1 { font-size: var(--vl-fs-3xl); max-width: 20ch; margin-bottom: 0.35em; }
.vl-cabecera .vl-lead { max-width: 54ch; }
.vl-cabecera__copy > :last-child { margin-bottom: 0; }

.vl-cabecera__meta {
  margin: 1.6rem 0 0;
  font-size: 0.75rem; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--vl-text-3);
}

.vl-cabecera__foto { margin: 0; }
.vl-cabecera__foto img {
  width: 100%; aspect-ratio: 4 / 3; object-fit: cover;
  border-radius: var(--vl-radius); box-shadow: var(--vl-shadow-lg);
}

/* --- Documento: índice al margen + cuerpo --------------------------------- */
.vl-doc { display: grid; gap: var(--vl-gap-lg); grid-template-columns: 1fr; }
@media (min-width: 1000px) {
  .vl-doc { grid-template-columns: 224px minmax(0, 1fr); gap: clamp(2.5rem, 0.5rem + 4.5vw, 4.5rem); align-items: start; }
}
/* Páginas cortas: una sola columna. Se probó a mantener la sangría del índice
   para que no hubiera salto lateral entre páginas, pero 270 px de vacío a la
   izquierda sin nada dentro no se lee como una decisión, se lee como un fallo. */
@media (min-width: 1000px) {
  .vl-doc--solo { grid-template-columns: minmax(0, 1fr); }
}

/* En móvil no hay dónde ponerlo sin robarle la pantalla al texto. */
.vl-indice { display: none; }
@media (min-width: 1000px) {
  .vl-indice {
    display: block;
    position: sticky; top: var(--vl-tope); align-self: start;
    max-height: calc(100vh - var(--vl-tope) - 2rem); overflow-y: auto;
    scrollbar-width: thin;
  }
}
.vl-indice__titulo {
  margin: 0 0 0.9rem;
  font-size: 0.72rem; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--vl-text-3);
}
/* Un <ol> sin números a la vista: el orden de los apartados es real y por eso es
   una lista ordenada, pero numerarlos sugeriría unos pasos que hay que seguir en
   orden, y no lo son. */
.vl-indice ol {
  list-style: none; margin: 0; padding: 0;
  border-left: 1px solid var(--vl-line);
}
.vl-indice a {
  display: block; margin-left: -1px;
  padding: 0.42rem 0 0.42rem 1.05rem;
  border-left: 1px solid transparent;
  font-size: var(--vl-fs-sm); line-height: 1.35;
  color: var(--vl-text-3); text-decoration: none;
  transition: color var(--vl-dur) var(--vl-ease), border-color var(--vl-dur) var(--vl-ease);
}
.vl-indice a:hover { color: var(--vl-text); }
.vl-indice a.is-actual { color: #fff; border-left-color: var(--vl-accent); }

/* --- Cuerpo del documento ------------------------------------------------- */
/* La medida de lectura se le pone al TEXTO, no a la columna. Por encima de 75
   caracteres el ojo pierde el renglón al volver a la izquierda, así que los
   párrafos se quedan en 68; las tablas, en cambio, ocupan la columna entera. Una
   ficha técnica de dos columnas metida en la medida de un párrafo obliga a
   partir los modelos en dos líneas, y un modelo partido deja de leerse como un
   modelo. */
.vl-doc__cuerpo > p,
.vl-doc__cuerpo > h2,
.vl-doc__cuerpo > h3,
.vl-doc__cuerpo > ul,
.vl-doc__cuerpo > ol { max-width: 68ch; }

.vl-doc__cuerpo > h2 {
  position: relative;
  margin-top: 3.2rem; padding-top: 2.1rem;
  border-top: 1px solid var(--vl-line);
  font-size: var(--vl-fs-xl);
}
.vl-doc__cuerpo > :first-child { margin-top: 0; }
.vl-doc__cuerpo > h2:first-child { padding-top: 0; border-top: 0; }
.vl-doc__cuerpo > h3 { margin-top: 2.2rem; }

/* Enlace al apartado. Aparece al pasar por encima del titular y se queda si se
   llega con el teclado: sirve para mandar «la parte de microfonía» sin mandar la
   página entera. Donde no hay ratón no se pinta: no habría forma de descubrirlo
   y ocuparía sitio para nada. */
.vl-ancla {
  position: absolute; left: -1.5rem; top: 2.1rem;
  width: 1.1rem; height: 1.6em;
  opacity: 0;
  transition: opacity 180ms var(--vl-ease);
}
.vl-ancla::before {
  content: "#";
  font-family: var(--vl-font); font-size: 1rem; font-weight: 700;
  color: var(--vl-accent);
}
.vl-doc__cuerpo > h2:hover .vl-ancla, .vl-ancla:focus-visible { opacity: 1; }
@media (hover: none), (max-width: 1099px) { .vl-ancla { display: none; } }

/* Párrafo clave. Misma piel que la franja del 100 % de la taquilla de la
   portada: es el sitio donde se dice el argumento que decide la venta, y no
   tiene por qué parecer otra cosa por estar en otra página. */
.vl-texto .vl-clave {
  margin: 2.2rem 0; padding: 1.15rem 1.4rem;
  background: linear-gradient(100deg, rgba(143, 47, 166, 0.28), rgba(143, 47, 166, 0.07));
  border: 1px solid rgba(194, 102, 217, 0.38); border-radius: var(--vl-radius);
  color: var(--vl-text);
}
.vl-texto .vl-clave strong { color: #fff; }

/* Listas de comprobación dentro del texto del editor: algo más de aire que en la
   portada, donde van dentro de una tarjeta que ya las encuadra. */
.vl-texto .vl-lista-check { margin-block: 1.8rem; gap: 0.95rem; }
.vl-texto .vl-lista-check li { font-size: var(--vl-fs-base); }

/* --- Tablas --------------------------------------------------------------- */
/* La ficha técnica es media página de tablas. Sin tratarlas salían con los filos
   por defecto del navegador y arrastraban la página entera al aspecto de
   documento. Van como tarjeta —el mismo fondo, borde, radio y filo que .vl-eq— y
   con desplazamiento propio: en un móvil de 360 px no cabe ninguna tabla de dos
   columnas con modelos de equipo, y lo que no puede pasar es que sea la página
   la que se desplace de lado. */
/* `.vl-tabla` es lo que pinta vl_tabla() desde los campos; `.wp-block-table`
   sigue contemplado porque los textos legales se escriben en el editor y ahí sí
   puede aparecer una tabla suya. */
.vl-texto .vl-tabla,
.vl-texto .wp-block-table {
  margin: 2.2rem 0; overflow-x: auto;
  background: var(--vl-bg-3); background-image: var(--vl-superficie);
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
  box-shadow: var(--vl-filo);
}
.vl-texto table {
  width: 100%; border-collapse: collapse;
  font-size: var(--vl-fs-sm); color: var(--vl-text-2);
}
.vl-texto table caption {
  padding: 1rem clamp(0.9rem, 0.7rem + 0.5vw, 1.3rem) 0;
  text-align: left;
  font-family: var(--vl-font-display); font-weight: 700;
  font-size: var(--vl-fs-base); color: #fff;
}
.vl-texto table th, .vl-texto table td {
  padding: 0.9rem clamp(0.9rem, 0.7rem + 0.5vw, 1.3rem);
  text-align: left; vertical-align: top;
  border-bottom: 1px solid var(--vl-line);
}
.vl-texto table tbody tr:last-child th, .vl-texto table tbody tr:last-child td { border-bottom: 0; }
.vl-texto table tbody tr:hover th, .vl-texto table tbody tr:hover td { background: rgba(255, 255, 255, 0.022); }

/* La primera columna es siempre el concepto —el modelo del equipo, la partida
   del presupuesto— y la segunda lo que es. Va como `th scope="row"`, que es lo
   que de verdad es: el encabezado de su fila, no un dato más. Un lector de
   pantalla lo anuncia antes de cada valor y así se sabe qué se está oyendo.

   En la tipografía de titulares para poder leer la tabla en diagonal, que es
   como se lee una ficha técnica. */
.vl-texto table th[scope="row"],
.vl-texto table td:first-child {
  color: #fff; font-family: var(--vl-font-display);
  font-weight: 700; letter-spacing: -0.005em;
  white-space: nowrap;
}
/* En pantalla estrecha el concepto puede partir: obligarlo a una línea ahí
   convertía la tabla en un desplazamiento de tres pantallas. */
@media (max-width: 599px) {
  .vl-texto table th[scope="row"],
  .vl-texto table td:first-child { white-space: normal; }
}

/* --- Preguntas frecuentes ------------------------------------------------- */
.vl-faq { display: grid; gap: 0.7rem; max-width: 74ch; }
.vl-faq__item {
  background: var(--vl-bg-3); background-image: var(--vl-superficie);
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
  box-shadow: var(--vl-filo);
  transition: border-color var(--vl-dur) var(--vl-ease);
}
.vl-faq__item[open], .vl-faq__item:hover { border-color: var(--vl-primary); }

.vl-faq__item summary {
  display: flex; align-items: flex-start; gap: 1rem;
  padding: 1.15rem clamp(1.1rem, 0.9rem + 0.8vw, 1.6rem);
  font-family: var(--vl-font-display); font-weight: 700;
  font-size: var(--vl-fs-base); line-height: 1.35; color: #fff;
  cursor: pointer; list-style: none;
}
.vl-faq__item summary::-webkit-details-marker { display: none; }
.vl-faq__item summary:focus-visible { outline: 2px solid var(--vl-accent); outline-offset: -2px; }

/* El signo se dibuja con máscara y gira al abrir. Un carácter de texto («+»,
   «▾») cambia de forma y de peso con cada tipografía de respaldo. */
.vl-faq__item summary::after {
  content: ""; flex-shrink: 0;
  width: 0.9rem; height: 0.9rem; margin-left: auto; margin-top: 0.3em;
  background: var(--vl-accent);
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='3' stroke-linecap='round'%3E%3Cpath d='M6 9l6 6 6-6'/%3E%3C/svg%3E") center / contain no-repeat;
  transition: transform var(--vl-dur) var(--vl-ease);
}
.vl-faq__item[open] summary::after { transform: rotate(180deg); }
@media (prefers-reduced-motion: reduce) { .vl-faq__item summary::after { transition: none; } }

.vl-faq__resp { padding: 0 clamp(1.1rem, 0.9rem + 0.8vw, 1.6rem) 1.35rem; font-size: var(--vl-fs-sm); }
.vl-faq__resp p { margin-bottom: 0.8em; }

/* --- Cierre --------------------------------------------------------------- */
/* Misma caja que .vl-precio, que es el otro sitio donde el remate de una sección
   es «esto cuesta esto, pídelo». Cambia el reparto, no la piel. */
.vl-cierre {
  display: grid; gap: var(--vl-gap-md); align-items: center;
  grid-template-columns: 1fr;
  padding: clamp(1.6rem, 1.1rem + 1.8vw, 2.6rem);
  background: var(--vl-bg-3); background-image: var(--vl-superficie);
  border: 1px solid var(--vl-line); border-radius: var(--vl-radius);
  box-shadow: var(--vl-filo);
}
@media (min-width: 860px) { .vl-cierre { grid-template-columns: 1.35fr auto; } }
.vl-cierre h2 { font-size: var(--vl-fs-xl); margin-bottom: 0.4em; }
.vl-cierre p { max-width: 52ch; }
.vl-cierre__acciones { display: flex; flex-wrap: wrap; gap: 0.8rem; }

/* Sección seguida de otra: sin esto, el texto de /contacto/ y el formulario de
   debajo suman dos espaciados completos y quedan a media pantalla uno de otro. */
.vl-section--corta { padding-bottom: 0; }

/* Enlace al pie de cada sección de la portada hacia su página en detalle. Solo
   separación: el botón ya es un .vl-btn de los de siempre. */
.vl-mas { margin: var(--vl-gap-md) 0 0; }
