/* ==========================================================================
     ESTILOS DEL PANEL
     ==========================================================================
     Los colores, las tipografías y los espaciados están en oper1-theme.css,
     en variables (--fondo, --panel, --texto...). Aquí solo se usan: no hay
     ningún color escrito a mano. pruebas/contraste.js comprueba el tema. */

  * { box-sizing: border-box; }

  html, body {
    margin: 0;
    padding: 0;
    background: var(--fondo);
    color: var(--texto);
  }

  body {
    /* Space Grotesk para todo: titulares, texto, cifras y rótulos. IBM Plex
       Mono solo para la línea de cliente, los ejes y leyendas de los gráficos
       y el pie. Nunca otra familia. Si Google Fonts no responde, caen a Arial
       y a Courier New. */
    font-family: var(--fuente-principal);
    font-size: var(--cuerpo);
    line-height: var(--interlineado);
    -webkit-font-smoothing: antialiased;
  }

  /* Rótulos: Space Grotesk en mayúsculas, espaciada, en gris texto. Los de
     tarjeta, sección, KPI y tabla, a 700; los apuntes pequeños (tramos,
     rango, días de la semana, fecha del recuadro), a 500. */
  h2, th, .rotulo, .dato-rotulo, .rango-grafico, .tramos button, .cifra-dia-rotulo,
  tr.familia td, tr.subtotal td:first-child, .recuadro-fecha, .mejor-etiqueta,
  .tramo-escalera {
    font-family: var(--fuente-principal);
    text-transform: uppercase;
    letter-spacing: var(--rotulo-espaciado);
  }

  /* La mono, solo aquí: línea de cliente, ejes y leyendas de los gráficos y
     pie. */
  .mono, .cliente, .eje-texto, .hito-texto, .leyenda, .pie-oper1 {
    font-family: var(--fuente-mono);
    text-transform: uppercase;
    letter-spacing: var(--mono-espaciado);
  }

  /* Todas las cifras en tabular para que las columnas no bailen. */
  .num, table, .cifra, .sub-cifra, .dato, .desglose { font-variant-numeric: tabular-nums; }

  .envoltorio {
    max-width: 1232px;   /* 1.200 px de contenido más el margen lateral */
    margin: 0 auto;
    padding: 24px 16px 64px;
  }

  /* --- Cabecera --- */

  /* Tres filas: (1) logo OPER1, cliente y "Actualizar"; (2) "Dashboard de
     ventas"; (3) una línea pequeña con fecha, actualización y serie. A la
     derecha de las filas 2 y 3, la próxima edición, el tema y salir, con el
     mismo estilo discreto. En el móvil, todo en columna. Una banda blanca, sin
     color del cliente. */
  header {
    background: var(--cabecera-1);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    box-shadow: var(--sombra-tarjeta);
    padding: 22px 24px;
    margin-bottom: var(--hueco);
  }

  .cab-fila {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 12px 24px;
  }
  .cab-cuerpo { align-items: flex-end; margin-top: 14px; }
  .cab-titulo { min-width: 0; }

  /* Línea de datos: fecha · actualizado a las HH:MM · serie diaria. */
  .cab-meta {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 0;
    margin-top: 4px;
    font-size: 13px;
    color: var(--sobre-marca-suave);
  }
  .cab-meta > span + span::before { content: '·'; margin: 0 8px; color: var(--sobre-marca-tenue); }
  .cab-meta .pastilla { margin-left: 8px; }

  /* Próxima edición, tema y salir: alineados a la derecha, mismo estilo. */
  .cab-enlaces {
    display: flex;
    flex-direction: column;
    align-items: flex-end;
    gap: 4px;
    font-size: 13px;
    color: var(--sobre-marca-suave);
  }
  .cab-enlaces b { color: var(--sobre-marca); font-weight: 700; }

  /* Logo OPER1 y cliente en una línea. El margen libre alrededor del logo es
     la altura de su "O" (0.72em del cuerpo del logo, ~20px). */
  .marca-linea {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 6px 20px;
  }
  .logo-oper1 {
    display: inline-block;
    min-width: 90px;
    font-family: var(--fuente-principal);
    font-size: 28px;
    font-weight: 700;
    line-height: 1;
    letter-spacing: -0.03em;
    color: var(--sobre-marca);
    margin-right: 0.72em;
  }
  /* El "1" con fader (SVG): alto = altura de las mayúsculas de Space Grotesk
     (0.7em), apoyado en la línea base y separado de la R como en el manual. */
  .logo-oper1 .uno {
    display: inline-block;
    width: 0.396em;
    height: 0.7em;
    margin-left: 0.1em;
    vertical-align: baseline;
    overflow: visible;
  }
  .logo-oper1 .uno-trazo  { stroke: var(--senal); }
  .logo-oper1 .uno-cursor { fill: var(--sobre-marca); }
  .logo-oper1 .uno-raya   { fill: var(--cabecera-1); }
  /* "CLIENTE" en gris etiqueta; el nombre del evento, en negro y a 500. */
  .cliente {
    display: inline-flex;
    flex-wrap: wrap;
    align-items: center;
    gap: 4px 10px;
    font-size: var(--mono-pequena);
    font-weight: 500;
    color: var(--sobre-marca);
  }
  .cliente .rotulo-cliente { color: var(--etiqueta); }
  .cliente .nombre-cliente { color: var(--sobre-marca); font-weight: 500; }
  .cliente img { display: block; max-height: 18px; width: auto; }

  h1 {
    margin: 0;
    font-size: 24px;
    font-weight: 700;
    letter-spacing: -0.01em;
    line-height: 1.25;
    color: var(--sobre-marca);
  }

  header .descuadre   { color: var(--ambar); }

  header .pastilla {
    color: var(--sobre-marca-suave);
    border-color: var(--sobre-marca-linea);
  }

  /* AJUSTE (avisos técnicos en ámbar): datos atrasados, sin caché, serie no
     disponible, regeneración, fallo de la API o de una lectura. Atención, no
     alerta: el panel sigue funcionando. Para volver al gris:
     --aviso-tecnico: var(--suave) en oper1-theme.css. */
  .aviso-tecnico { color: var(--aviso-tecnico); }
  header .pastilla.aviso-tecnico { color: var(--aviso-tecnico); border-color: var(--ambar-bd); }

  /* Enlaces de la cabecera (tema, salir): discretos y todos iguales, en
     Space Grotesk, como "Próxima edición". */
  header .salir,
  .cambiar-tema {
    background: none;
    border: none;
    border-bottom: 1px solid var(--sobre-marca-linea);
    padding: 0;
    font: inherit;
    font-size: 13px;
    color: var(--sobre-marca-suave);
    text-decoration: none;
    cursor: pointer;
  }
  header .salir:hover,
  .cambiar-tema:hover { color: var(--sobre-marca); }

  /* Botón principal: negro con texto hueso (en el oscuro, al revés). */
  .boton {
    padding: 9px 18px;
    background: var(--boton-fondo);
    border: none;
    border-radius: var(--radio);
    color: var(--sobre-boton);
    font: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
  }
  .boton:hover:not(:disabled) { opacity: 0.88; }
  .boton:disabled { opacity: 0.6; cursor: default; }

  /* AJUSTE (avisos técnicos en ámbar): un refresco que falla es atención, no
     alerta: siguen a la vista los datos anteriores. Antes, en rojo. */
  .error-refresco { margin-top: 8px; font-size: 13px; color: var(--aviso-tecnico); text-align: right; }

  /* Aviso de cambio de precio: atención, en ámbar (nunca el naranja de
     marca, para no confundir "destacado" con "problema"). */
  .aviso-precio {
    display: flex;
    align-items: center;
    gap: 10px;
    background: var(--ambar-bg);
    border: 1px solid var(--ambar-bd);
    border-radius: var(--radio);
    padding: 12px 16px;
    margin-bottom: var(--hueco);
    font-size: 14px;
    color: var(--texto);
  }
  .aviso-precio b { color: var(--ambar); font-weight: 700; }
  .aviso-precio .estado-marca { background: var(--ambar-grafico); transform: none; }

  /* Datos fijos de la campaña (lanzamiento, días, aforo): una línea discreta
     dentro de la cabecera, sin cajas. Rótulo en gris y cifra en negrita. */
  .datos-rapidos {
    display: flex;
    flex-wrap: wrap;
    gap: 4px 18px;
    margin-top: 10px;
    font-variant-numeric: tabular-nums;
  }
  .dato { font-size: 13px; line-height: 1.4; color: var(--sobre-marca-suave); white-space: nowrap; }
  .dato b { font-weight: 700; color: var(--sobre-marca); }
  .dato-rotulo {
    font-size: var(--mono-pequena);
    font-weight: 700;
    color: var(--rotulo);
  }

  /* Resumen por jornada: una tarjeta por día. */
  .jornadas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
    gap: var(--hueco);
  }
  .desglose {
    list-style: none;
    margin: 14px 0 0;
    padding: 10px 0 0;
    border-top: 1px solid var(--borde);
    font-variant-numeric: tabular-nums;
  }
  .desglose li {
    display: flex;
    justify-content: space-between;
    gap: 12px;
    padding: 3px 0;
    font-size: 14px;
    color: var(--lectura);
  }
  .desglose li b { color: var(--texto); font-weight: 700; }
  .desglose li.de-pago { margin-top: 4px; padding-top: 7px; border-top: 1px dashed var(--borde); }
  .desglose li.de-pago b { color: var(--cifra-dinero); }
  .desglose li.sold-out b { color: var(--cifra-aviso); }
  .desglose li.informativo, .desglose li.informativo b { color: var(--tenue); font-weight: 400; }
  .sub-cifra .desglose { margin-top: 10px; padding-top: 8px; }
  .sub-cifra .desglose li { font-size: 13px; }

  .ocupacion { margin-top: 14px; }
  .ocupacion-pista { height: 8px; border-radius: 4px; background: var(--pista); overflow: hidden; }
  /* AJUSTE (barras de aforo): naranja de progreso; desde el umbral
     (--umbral-aforo-lleno), verde. El 80 % en ámbar ya no aplica aquí. */
  .ocupacion-relleno { display: block; height: 100%; border-radius: 4px; background: var(--barra-progreso); }
  .ocupacion-relleno.casi-lleno { background: var(--barra-aforo-lleno); }
  .etiqueta-sold-out {
    margin-left: 6px;
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--rotulo-espaciado);
    color: var(--positivo);
  }
  .ocupacion-texto {
    display: flex;
    justify-content: space-between;
    margin-top: 6px;
    font-size: 12px;
    color: var(--tenue);
    font-variant-numeric: tabular-nums;
  }

  .pastilla {
    display: inline-block;
    padding: 1px 8px;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    font-size: 12px;
    color: var(--tenue);
  }

  .descuadre { color: var(--ambar); }

  h2 {
    font-size: var(--rotulo-tamano);
    font-weight: 700;
    color: var(--rotulo);
    margin: 0 0 12px;
  }
  /* AJUSTE (marca de sección): barra naranja de 3px a la izquierda de cada
     título de sección. El texto no cambia de color. Para quitarla, en
     oper1-theme.css: --marca-seccion: transparent. */
  section h2 {
    border-left: 3px solid var(--marca-seccion);
    padding-left: 8px;
    line-height: 1.15;
  }

  section { margin-top: 30px; }
  .datos-rapidos + section { margin-top: 24px; }

  /* --- Avisos --- */

  .aviso {
    border: 1px solid var(--ambar-bd);
    background: var(--ambar-bg);
    color: var(--ambar);
    border-radius: var(--radio);
    padding: 10px 14px;
    margin-bottom: 12px;
    font-size: 14px;
  }

  /* --- Tarjetas de cifras --- */

  .tarjetas {
    display: grid;
    grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
    gap: var(--hueco);
  }

  /* --- Nivel 1 · Venta reciente: ayer, 7 días y total ---
     Tres tarjetas en fila; en el móvil, una debajo de otra y apretadas para
     que quepan tras la cabecera. Debajo de la cifra grande, dos cifras
     secundarias; la variación, en su color de estado. */
  /* Cuatro tarjetas en fila (hoy, ayer, 7 días, total); dos por fila en
     pantallas medianas. */
  .venta-reciente { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  @media (max-width: 1100px) {
    .venta-reciente { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  }
  .reciente-unidad { display: block; margin-top: 2px; font-size: 13px; color: var(--suave); }
  /* Reparto por tipo: "Abono 13 · Sáb 64 · Dom 57". Si no cabe en una
     línea, salta entre elementos, nunca entre etiqueta y cifra. */
  .reparto { display: flex; flex-wrap: wrap; gap: 2px 0; margin-top: 6px; font-size: 13px; font-variant-numeric: tabular-nums; }
  .reparto-item { white-space: nowrap; }
  .reparto-item + .reparto-item::before { content: '·'; margin: 0 7px; color: var(--tenue); }
  .reparto-etiqueta { color: var(--suave); }
  .reparto b { font-weight: 700; color: var(--texto); }

  /* "Ver qué entradas": la línea del reparto abre la lista de productos. */
  .ver-entradas > summary { list-style: none; cursor: pointer; }
  .ver-entradas > summary::-webkit-details-marker { display: none; }
  .ver-texto {
    display: inline-block;
    margin-top: 4px;
    font-size: 12px;
    font-weight: 500;
    color: var(--suave);
    border-bottom: 1px solid var(--borde);
  }
  .ver-texto::before { content: '▸ '; }
  .ver-entradas[open] .ver-texto::before { content: '▾ '; }
  .ver-entradas > summary:hover .ver-texto { color: var(--texto); }
  .ver-lista {
    list-style: none;
    margin: 8px 0 0;
    padding: 8px 0 0;
    border-top: 1px solid var(--borde);
    font-size: 12px;
    font-variant-numeric: tabular-nums;
  }
  .ver-lista li { display: flex; justify-content: space-between; gap: 10px; padding: 2px 0; color: var(--lectura); }
  .ver-lista li b { font-weight: 700; color: var(--texto); white-space: nowrap; }
  .ver-lista li.ver-grupo { margin-top: 6px; font-weight: 700; color: var(--rotulo); text-transform: uppercase; letter-spacing: var(--rotulo-espaciado); font-size: 11px; }
  .ver-lista li.ver-grupo:first-child { margin-top: 0; }
  .reciente-filas { list-style: none; margin: 12px 0 0; padding: 10px 0 0; border-top: 1px solid var(--borde); }
  .reciente-filas li {
    display: flex;
    justify-content: space-between;
    align-items: baseline;
    gap: 12px;
    padding: 3px 0;
  }
  .reciente-etiqueta { font-size: 13px; color: var(--lectura); }
  .reciente-valor {
    font-size: 20px;
    font-weight: 700;
    letter-spacing: var(--cifra-espaciado);
    color: var(--texto);
    white-space: nowrap;
    font-variant-numeric: tabular-nums;
  }
  /* La unidad de una cifra secundaria, más pequeña pero en el color de la
     cifra: a este tamaño (15px; 13px en el móvil) el naranja no llega al
     contraste del texto normal. El naranja, solo en las cifras grandes. */
  .reciente-valor .unidad { color: inherit; font-size: var(--unidad-tamano); margin-left: -0.1em; }
  .venta-reciente .nota-discreta { margin-top: 8px; font-size: 12px; }
  .venta-reciente .sub-cifra { margin-top: 0; }
  /* El desglose del total es texto y una lista: a doble ancho donde caben dos
     columnas (en una sola, span 2 crearía una columna de más). */
  @media (min-width: 700px) {
    .tarjeta-desglose { grid-column: span 2; }
  }

  /* Segunda fila, para lo que se consulta pero no se mira cada mañana. */
  .tarjetas.secundarias {
    grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  }


  /* Una caja suelta no debe estirarse a todo el ancho de la página. */
  .tarjetas.solo-una {
    grid-template-columns: minmax(260px, 400px);
  }

  .tarjeta .sub-cifra br { content: ''; display: block; margin-top: 2px; }

  /* Resumen general y cambio de precio: en filas flexibles, no en rejilla, para
     que la última fila no deje huecos (6 tarjetas en 4 columnas, 3 en 4). Las
     tarjetas de una fila se reparten el ancho; el desglose, que es texto,
     pide el doble, y la lista de tramos ocupa siempre una fila entera. */
  .tarjetas.resumen-general { display: flex; flex-wrap: wrap; }
  .tarjetas.resumen-general > .tarjeta { flex: 1 1 240px; min-width: 0; }
  .tarjetas.resumen-general > .tarjeta-desglose { flex: 2 1 480px; }
  .tarjetas.resumen-general > .tramos-lista { flex: 1 1 100%; }

  /* Una cifra por jornada en una tarjeta (VIE, SÁB, DOM): una fila por día,
     rótulos en una columna y cifras alineadas a la derecha en la otra. */
  .cifra-dias { display: inline-grid; grid-template-columns: auto auto; column-gap: 10px; align-items: baseline; }
  .cifra-dia { display: contents; }
  .cifra-dia-num { text-align: right; font-variant-numeric: tabular-nums; }
  .cifra-dia-rotulo {
    font-size: var(--mono-pequena);
    font-weight: 700;
    color: var(--rotulo);
  }

  /* AJUSTE (día de la semana con barras): una fila por día, con su nombre
     corto, una barra proporcional a su media (la mayor llena la pista) y la
     cifra al lado. Barras en gris neutro; la del mejor día, en naranja, el
     único naranja del bloque. */
  .semana-rotulo {
    display: block;
    margin-top: 14px;
    font-size: var(--mono-pequena);
    font-weight: 700;
    text-transform: uppercase;
    letter-spacing: var(--rotulo-espaciado);
    color: var(--rotulo);
  }
  .semana {
    display: grid;
    gap: 6px;
    margin-top: 8px;
    font-variant-numeric: tabular-nums;
  }
  .semana-fila {
    display: grid;
    grid-template-columns: 40px 1fr minmax(120px, auto);
    align-items: center;
    gap: 12px;
  }
  .semana-dia { font-size: 13px; font-weight: 500; color: var(--rotulo); }
  .semana-pista { height: 10px; border-radius: 5px; background: var(--pista); overflow: hidden; }
  .semana-barra { display: block; height: 100%; border-radius: 5px; background: var(--barra-semana-dia); }
  .semana-fila.mejor .semana-barra { background: var(--barra-semana-mejor); }
  .semana-cifra { display: flex; align-items: baseline; gap: 8px; }
  .semana b { font-size: 14px; font-weight: 500; color: var(--texto); }
  .semana .mejor b { font-weight: 700; }
  .semana .mejor .semana-dia { color: var(--texto); font-weight: 700; }
  .tarjeta.ancho-completo { grid-column: 1 / -1; }

  /* Lista plegable de tramos activos, a todo el ancho bajo las tarjetas. */
  .tramos-lista {
    grid-column: 1 / -1;
    background: var(--panel);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    overflow: hidden;
  }
  .tramos-lista summary {
    padding: 12px 18px;
    font-size: 13px;
    font-weight: 500;
    color: var(--suave);
    cursor: pointer;
  }
  .tramos-lista summary:hover { color: var(--texto); }
  .tramos-lista[open] summary { border-bottom: 1px solid var(--borde); }
  .tramos-lista > .nota-discreta { margin: 0; padding: 10px 18px 0; }
  .tramos-lista > .nota-discreta:last-child { padding-bottom: 14px; }

  /* --- Nivel 3 · Detalle: cada sección, en un desplegable ---
     El mismo estilo que "Ver los N tramos activos". Cerrado: título y, si hay,
     una cifra clave en pequeño. Abierto: la sección dentro, sobre el fondo,
     con su relleno (--relleno-plegable; lo descuenta ajustarLienzo para que
     los gráficos midan lo que su sitio). */
  /* minmax(0, 1fr) y min-width 0: sin ello, la rejilla se estiraría hasta el
     ancho de la tabla más ancha y movería la página entera en el móvil, en
     vez de desplazar la tabla dentro de su recuadro. */
  .plegables { display: grid; grid-template-columns: minmax(0, 1fr); gap: 10px; }
  .plegable-seccion, .plegable-cuerpo { min-width: 0; }
  /* El resumen, en línea (con display flex se perdería el triángulo). */
  .plegable-titulo { font-size: 14px; font-weight: 700; color: var(--texto); }
  .plegable-cifra { margin-left: 8px; font-size: 13px; font-weight: 500; color: var(--suave); font-variant-numeric: tabular-nums; }
  .plegable-cifra::before { content: '·'; margin-right: 8px; color: var(--tenue); }
  .plegable-cuerpo { padding: 4px var(--relleno-plegable) var(--relleno-plegable); background: var(--fondo); }
  .plegable-cuerpo > section { margin-top: 12px; }
  .plegable-seccion.sin-titulo .plegable-cuerpo > section > h2:first-child { display: none; }
  .tramo-escalera {
    display: block;
    font-size: var(--mono-pequena);
    font-weight: 500;
    color: var(--rotulo);
  }
  .tarjeta.ancho-completo .semana { max-width: 620px; }
  /* El mejor día: su media en 700 (las demás, en 500) y una etiqueta pequeña
     en mayúsculas, en negro, junto a la cifra. */
  .mejor-etiqueta {
    font-size: var(--mono-pequena);
    font-weight: 700;
    color: var(--texto);
  }

  .tarjeta {
    background: var(--panel);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    box-shadow: var(--sombra-tarjeta);
    padding: var(--relleno-tarjeta);
  }

  .tarjeta .rotulo {
    font-size: var(--rotulo-tamano);
    font-weight: 700;
    line-height: 1.3;
    color: var(--rotulo);
    margin-bottom: 8px;
  }

  /* Cifra destacada: grande y apretada, en negro salvo que exprese un estado. */
  .cifra {
    font-size: var(--cifra-grande);
    font-weight: 700;
    letter-spacing: var(--cifra-grande-espaciado);
    line-height: 1.05;
    color: var(--texto);
  }

  /* AJUSTE (valores de texto a 32px): el valor destacado que es texto y no
     cifra ("Tras el evento"), un punto más pequeño, para que quepa en una
     línea y no alargue la fila. Lo pone tarjeta() en el JS. */
  .cifra.cifra-texto { font-size: var(--cifra-texto); }

  /* AJUSTE (unidad en naranja): "€" y "%" de la cifra grande, en naranja a
     0.75em, mismo peso, en la línea base. El espacio de delante, que va dentro
     del span, se encoge con él y un margen negativo lo deja fino. Si la cifra lleva color de
     estado (.sube, .baja), la unidad toma ese mismo color, nunca el naranja.
     Para quitarlo: --unidad-color: inherit y --unidad-tamano: 1em. */
  .cifra .unidad { color: var(--unidad-color); font-size: var(--unidad-tamano); margin-left: -0.1em; }
  .cifra .sube .unidad, .cifra .baja .unidad { color: inherit; }

  /* Color de la cifra según lo que cuenta. */
  .cifra.cifra-entradas { color: var(--cifra-entradas); }
  .cifra.cifra-dinero   { color: var(--cifra-dinero); }
  .cifra.cifra-aviso    { color: var(--cifra-aviso); }

  /* Lo que explica la cifra: texto de lectura, casi negro. */
  .sub-cifra {
    margin-top: 8px;
    font-size: 14px;
    line-height: var(--interlineado-lectura);
    color: var(--lectura);
  }

  /* --- Gráfico --- */

  /* El mismo relleno que las tarjetas. Si cambia, hay que cambiar también el
     margen que resta ajustarLienzo() (relleno lateral × 2 + bordes). */
  .grafico {
    background: var(--panel);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    box-shadow: var(--sombra-tarjeta);
    padding: var(--relleno-tarjeta);
  }

  .grafico svg { display: block; width: 100%; height: auto; }

  .titulo-grafico {
    font-size: 15px;
    font-weight: 700;
    color: var(--texto);
    margin: 4px 0 2px;
  }

  .cabecera-grafico {
    display: flex;
    flex-wrap: wrap;
    align-items: center;
    justify-content: space-between;
    gap: 8px 16px;
  }

  /* Botones de tramo: un grupo, uno marcado. Ninguno si se ha acercado a mano. */
  .tramos {
    display: inline-flex;
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    overflow: hidden;
  }
  .tramos button {
    background: none;
    border: none;
    border-right: 1px solid var(--borde);
    padding: 6px 12px;
    font-size: var(--mono-pequena);
    font-weight: 500;
    color: var(--rotulo);
    cursor: pointer;
  }
  .tramos button:last-child { border-right: none; }
  .tramos button:hover { color: var(--texto); }
  .tramos button[aria-pressed="true"] { background: var(--boton-fondo); color: var(--sobre-boton); }

  .rango-grafico { display: block; font-size: var(--mono-pequena); font-weight: 500; color: var(--rotulo); margin: 4px 0 2px; }

  /* Lo que explica el gráfico: texto de lectura. */
  .cabecera-grafico + .nota {
    display: block;
    margin: 4px 0 6px;
    font-size: 14px;
    line-height: var(--interlineado-lectura);
    color: var(--lectura);
  }

  /* El segundo gráfico va pegado al primero pero con una separación clara. */
  .grafico .titulo-grafico.segundo {
    margin-top: 22px;
    padding-top: 18px;
    border-top: 1px solid var(--borde);
  }

  /* Gráficos: esta edición en negro (hueso en el oscuro), la anterior en
     gris etiqueta y discontinua, las dos a 2 px. Rejilla muy tenue; ejes y
     leyendas en la mono. El punto actual, en naranja: el único del gráfico. */
  .rejilla { stroke: var(--rejilla); stroke-width: 1; }
  .eje-texto { fill: var(--etiqueta); font-size: var(--mono-pequena); font-weight: 500; }
  .eje-ingresos { fill: var(--eje-ingresos); }

  .linea-entradas,
  .linea-ingresos {
    fill: none;
    stroke-width: 2;
    stroke-linejoin: round;
    stroke-linecap: round;
  }
  .linea-entradas { stroke: var(--serie-actual); }
  .linea-ingresos { stroke: var(--ingresos); }

  .linea-anterior { stroke: var(--serie-anterior); stroke-dasharray: 6 4; }
  .barra-2027 { fill: var(--serie-actual); }
  .barra-2026 { fill: var(--serie-anterior); }
  /* AJUSTE (semana en curso en naranja): el único naranja del gráfico. */
  .barra-2027.barra-actual { fill: var(--barra-semana-actual); }
  .semanas-lista { margin-top: 12px; }
  .sin-ventas { margin-top: 12px; }
  .punto-anterior { fill: var(--serie-anterior); stroke: var(--panel); stroke-width: 1.5; }
  .punta-anterior { fill: var(--serie-anterior); }
  .lienzo.sin-anterior .grupo-anterior { display: none; }

  .punto { fill: var(--serie-actual); stroke: var(--panel); stroke-width: 1.5; }
  .punto-ingresos { fill: var(--ingresos); stroke: var(--panel); stroke-width: 1.5; }
  /* El punto actual (el último día de esta edición): el naranja señal. */
  .punto.punto-actual { fill: var(--senal); }

  /* Hitos (cambios de precio): línea vertical fina y discontinua, con su
     etiqueta en la mono. Preparado; hoy no hay datos de hitos que pintar. */
  .hito-linea { stroke: var(--hito); stroke-width: 1; stroke-dasharray: 3 3; }
  .hito-texto { fill: var(--hito); font-family: var(--fuente-mono); font-size: var(--mono-pequena); font-weight: 500; text-transform: uppercase; letter-spacing: var(--mono-espaciado); }

  /* El punto del primer día no cabe en la escala: se dibuja pegado al borde
     superior con un triángulo que avisa de que sigue hacia arriba. */
  .punta { stroke: none; }
  .punta-entradas { fill: var(--serie-actual); }
  .punta-ingresos { fill: var(--ingresos); }
  .cifra-corte { fill: var(--texto); font-size: 12px; font-weight: 700; }

  /* Columna invisible por día: da una zona de acierto ancha, que es lo que
     hace que esto se pueda usar con el dedo y no solo con el ratón. */
  .toque {
    fill: transparent;
    pointer-events: all;
    cursor: pointer;
  }

  /* --- Leyenda y recuadro del gráfico --- */

  .leyenda {
    display: flex;
    flex-wrap: wrap;
    gap: 16px;
    align-items: center;
    margin: 10px 0 2px;
    font-size: var(--mono-pequena);
    font-weight: 500;
    color: var(--rotulo);
  }

  .clave {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    color: inherit;
    /* Un botón no hereda estos dos del navegador: sin ellos, la clave
       pulsable salía en minúsculas y distinta del resto de la leyenda. */
    text-transform: inherit;
    letter-spacing: inherit;
  }

  button.clave { cursor: pointer; }
  button.clave:hover { color: var(--texto); }
  .clave.apagada { opacity: 0.45; text-decoration: line-through; }

  .marca {
    width: 14px;
    height: 3px;
    border-radius: 2px;
    display: inline-block;
  }

  .marca-entradas { background: var(--serie-actual); }
  .marca-ingresos { background: var(--ingresos); }
  /* Discontinua también en la leyenda: se distingue sin color. */
  .marca-anterior {
    height: 0;
    background: none;
    border-top: 2px dashed var(--serie-anterior);
    border-radius: 0;
  }

  .sube { color: var(--positivo); }
  /* Variación de la tabla de comparativa: con signo, en tono suave. */
  .variacion-neutra { color: var(--suave); }
  /* Estado de campaña: una lista en un solo bloque, una frase por fila,
     separadas por una línea fina, con un punto de color a la izquierda. El
     color del punto sale del tono que manda el servidor: verde si es
     positiva, ámbar si pide atención, gris si es neutra. Las cifras de la
     frase, en negrita. */
  .estado-campana { list-style: none; margin: 0; padding: 4px 22px; }
  .estado-campana li {
    display: flex;
    align-items: baseline;
    gap: 12px;
    padding: 12px 0;
    border-bottom: 1px solid var(--borde);
  }
  .estado-campana li:last-child { border-bottom: none; }
  .estado-texto {
    font-size: var(--texto-lectura);
    line-height: var(--interlineado-lectura);
    font-weight: 400;
    color: var(--texto);
  }
  .estado-texto .cifra-frase { font-weight: 700; }
  /* El punto. También lo usa el aviso de precio. */
  .estado-marca {
    flex: none;
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--neutro-grafico);
    transform: translateY(-1px);
  }
  .estado-positivo .estado-marca { background: var(--verde-grafico); }
  .estado-atencion .estado-marca { background: var(--ambar-grafico); }

  /* Comparativa: el total, un punto más marcado; las dos líneas aparte, en
     letra normal; tarjetas y curva, separadas de la tabla. */
  .tabla-comparativa .fila-total td,
  .tabla-afters .fila-total td,
  .tabla-ventas .fila-total td { font-weight: 700; }
  .tabla-afters .fila-total td { border-bottom: 2px solid var(--borde); }
  .tabla-afters tr.sin-sala td { color: var(--suave); }
  .tabla-afters tr.grupo-columnas th {
    background: var(--panel);
    text-align: center;
    color: var(--rotulo);
    border-bottom: none;
    padding-bottom: 0;
  }
  .linea-aparte { margin: 10px 2px 0; font-size: var(--texto-lectura); line-height: var(--interlineado-lectura); color: var(--lectura); }
  .tarjetas-comparativa { margin-top: 16px; }
  .grafico-curva { margin-top: 16px; }

  /* Rótulo de cada bloque de la tabla de comparativa. */
  .cabecera-bloque td {
    background: var(--panel-3);
    color: var(--texto);
    font-weight: 700;
    font-size: 13px;
    text-align: left;
  }
  .baja { color: var(--negativo); }

  /* Aviso dentro del subtítulo de una tarjeta: cuando la cifra es correcta
     pero se puede leer mal. */
  .ojo {
    display: block;
    margin-top: 6px;
    padding-left: 9px;
    border-left: 2px solid var(--ambar-grafico);
    color: var(--ambar);
  }

  /* Separador entre las dos lecturas de la comparativa. */
  .otra-lectura {
    display: block;
    margin-top: 7px;
    padding-top: 7px;
    border-top: 1px solid var(--borde);
  }

  /* Nota al pie dentro de una tarjeta o bajo una tabla: contexto que conviene
     saber pero que no es un aviso. Más discreta que .ojo, que sí lo es. */
  .nota-discreta {
    display: block;
    margin-top: 6px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--tenue);
  }
  .pie-tabla { margin: 8px 2px 0; }
  /* Incidencia (producto sin día o sin familia confirmados): atención, en
     ámbar. Nunca el naranja de marca. */
  .nota-discreta.incidencia { color: var(--ambar); padding-left: 9px; border-left: 2px solid var(--ambar-grafico); }

  /* --- Plegables --- */

  .plegar {
    display: inline-block;
    margin-bottom: 12px;
    background: none;
    border: none;
    padding: 0;
    font: inherit;
    font-size: 13px;
    color: var(--suave);
    cursor: pointer;
    border-bottom: 1px solid var(--borde);
  }

  .plegar:hover { color: var(--texto); }
  .plegable[hidden] { display: none; }


  /* --- Familias de producto --- */

  /* Cada familia tiene que leerse como un bloque, no como una fila más. De ahí
     la banda hueso, las mayúsculas y el espaciado: el ojo salta de encabezado
     a encabezado sin tener que leer. El margen de arriba es mayor que el de
     abajo a propósito, para que el título quede pegado a SU grupo y separado
     del anterior. */
  tr.familia td {
    background: var(--panel-3);
    font-size: var(--mono-pequena);
    font-weight: 700;
    color: var(--texto);
    padding-top: 22px;
    padding-bottom: 8px;
    border-top: 1px solid var(--borde);
  }

  /* La primera no necesita separarse de nada: va justo bajo la cabecera. */
  tbody tr.familia:first-child td {
    padding-top: 12px;
    border-top: none;
  }

  /* Ni producto ni encabezado: cierra el grupo. Línea de arriba marcada, fondo
     apenas distinto, y el peso en las cifras y no en la etiqueta, que es lo que
     se quiere leer de un vistazo. El hueco de abajo es el respiro antes de la
     familia siguiente. */
  tr.subtotal td {
    background: var(--subtotal);
    border-top: 2px solid var(--borde);
    border-bottom: none;
    font-weight: 700;
    color: var(--texto);
    padding-top: 9px;
    padding-bottom: 14px;
  }

  tr.subtotal td:first-child {
    color: var(--rotulo);
    font-weight: 500;
    font-size: var(--mono-pequena);
  }

  /* --- Avance sobre el cupo --- */

  /* Pegada al número parecía un subrayado. Ahora va separada, con una pista de
     fondo que representa el cupo entero: sin pista, una barra al 30% y otra al
     90% se distinguen mal porque no hay contra qué compararlas. */
  .con-cupo { line-height: 1.25; }

  .cifra-cupo { display: block; }

  .cupo {
    display: block;
    width: 72px;
    height: 6px;
    margin: 7px 0 1px auto;
    border-radius: 3px;
    background: var(--pista);
    overflow: hidden;
  }

  .cupo-relleno {
    display: block;
    height: 100%;
    border-radius: 3px;
    background: var(--barra-progreso);   /* AJUSTE (barras de cupo): naranja de progreso */
  }

  /* AJUSTE (barras de cupo): desde el umbral (--umbral-cupo-aviso), ámbar;
     al 100 %, verde. */
  .cupo-relleno.media-llena { background: var(--barra-cupo-aviso); }
  .cupo-relleno.cupo-completo { background: var(--barra-cupo-completo); }

  /* --- Barras horizontales (procedencia y edad) --- */

  .barras {
    background: var(--panel);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    padding: 16px 18px;
  }

  /* Nombre, barra y cifra. La barra se lleva el espacio que sobra, así que las
     tres columnas quedan alineadas entre filas sin tener que medir nada. */
  .fila-barra {
    display: grid;
    grid-template-columns: minmax(96px, 168px) 1fr minmax(104px, auto);
    align-items: center;
    gap: 12px;
    padding: 5px 0;
    font-size: 14px;
  }

  .barra-nombre {
    color: var(--texto);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
  }

  .barra-pista {
    height: 10px;
    border-radius: 5px;
    background: var(--pista);
    overflow: hidden;
  }

  .barra-valor {
    display: block;
    height: 100%;
    border-radius: 5px;
    background: var(--procedencia);
  }

  .barras.de-edad .barra-valor { background: var(--edad); }

  .barra-cifra {
    text-align: right;
    color: var(--suave);
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  .barra-cifra b {
    color: var(--texto);
    font-weight: 700;
  }

  /* Fila de cierre de la lista: es un total, no una provincia más. Por eso
     lleva línea de separación arriba y NO lleva barra. Con barra, sus 562
     compradores dibujaban la raya más larga del final de la lista y parecía
     que el orden estaba roto. */
  .fila-resumen {
    display: grid;
    grid-template-columns: minmax(96px, 168px) 1fr minmax(104px, auto);
    align-items: center;
    gap: 12px;
    width: 100%;
    margin-top: 8px;
    padding: 11px 0 3px;
    border: none;
    border-top: 1px solid var(--borde);
    background: none;
    font: inherit;
    font-size: 14px;
    color: var(--suave);
    text-align: left;
    cursor: pointer;
  }

  .fila-resumen:hover { color: var(--texto); }
  .fila-resumen.fila-fija { cursor: default; }
  .fila-resumen.fila-fija:hover { color: var(--suave); }
  .fila-resumen.fila-fija .resumen-texto { border-bottom: none; }

  .resumen-texto {
    grid-column: 1 / 3;
    border-bottom: 1px solid var(--borde);
    justify-self: start;
  }

  .resumen-cifra {
    text-align: right;
    font-variant-numeric: tabular-nums;
    white-space: nowrap;
  }

  .resumen-cifra b { color: var(--texto); font-weight: 700; }

  /* Desplegable de los agrupados (provincias, países), dentro del bloque de
     barras: el de los tramos, con sus filas dentro. */
  .barras .desplegable-barras { margin-top: 12px; }
  .barras-desplegadas { padding: 8px 18px 12px; }

  /* La base sobre la que está calculado un reparto. Nunca debe faltar cuando
     el reparto no cubre el total. */
  .base-calculo {
    margin: 12px 0 0;
    font-size: 12px;
    color: var(--tenue);
  }

  .dos-bloques {
    display: grid;
    /* min(): dentro del desplegable de público, en el móvil, quedan menos de
       340 px; sin él, la columna se saldría de su recuadro. */
    grid-template-columns: repeat(auto-fit, minmax(min(340px, 100%), 1fr));
    gap: 24px;
  }
  /* Bloques de la misma fila, con la misma altura: el marco se estira. */
  .dos-bloques > div { display: flex; flex-direction: column; }
  .dos-bloques > div > .barras { flex: 1; }
  .seccion-pais { margin-top: 24px; }

  /* pan-y: el desplazamiento vertical es de la página; el horizontal y el
     pellizco los recoge el gráfico para moverse y acercar. */
  .lienzo { position: relative; touch-action: pan-y; }
  .lienzo svg { touch-action: pan-y; user-select: none; -webkit-user-select: none; }
  .lienzo.acercado { cursor: grab; }
  .lienzo.arrastrando { cursor: grabbing; }
  /* La leyenda, según lo que enseña el gráfico de evolución. */
  .modo-entradas .solo-ingresos, .modo-ingresos .solo-entradas { display: none; }
  .controles-grafico { display: flex; flex-wrap: wrap; gap: 8px; }

  .recuadro {
    display: none;
    position: absolute;
    z-index: 5;
    transform: translateX(-50%);
    background: var(--panel-2);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    padding: 8px 11px;
    font-size: 13px;
    line-height: 1.45;
    white-space: nowrap;
    pointer-events: none;
    /* Casi imperceptible: solo para separarlo del gráfico que tapa. */
    box-shadow: 0 1px 3px var(--sombra);
  }

  .recuadro.arriba { transform: translate(-50%, -100%); }
  .recuadro-fecha { color: var(--rotulo); font-size: var(--mono-pequena); font-weight: 500; margin-bottom: 3px; }
  .recuadro-linea { display: flex; align-items: center; gap: 7px; }
  .recuadro-linea .marca { width: 10px; height: 10px; border-radius: 50%; }

  /* --- Tablas --- */

  .marco {
    background: var(--panel);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    overflow: hidden;
  }

  .marco.separado { margin-top: 20px; }

  .scroll { overflow-x: auto; }

  table {
    width: 100%;
    border-collapse: collapse;
    font-size: 14px;
  }

  th, td {
    padding: 9px 14px;
    text-align: right;
    white-space: nowrap;
    border-bottom: 1px solid var(--borde);
  }

  th {
    font-size: var(--mono-pequena);
    color: var(--rotulo);
    font-weight: 700;
    background: var(--panel-2);
  }

  th:first-child, td:first-child {
    text-align: left;
    white-space: normal;
    min-width: 170px;
  }

  tbody tr:last-child td { border-bottom: none; }

  /* Celda sin dato: ni cero ni guion grande, solo un hueco marcado. */
  .vacio { color: var(--tenue); }

  tr.atenuada td { opacity: 0.45; }

  /* --- Estados --- */

  .cargando, .vacio-seccion {
    color: var(--suave);
    padding: 28px 0;
  }

  /* --- Acceso --- */

  .acceso {
    max-width: 380px;
    margin: 48px auto;
    background: var(--panel);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    padding: 26px 26px 28px;
  }

  .acceso h2 { margin-bottom: 18px; }

  .acceso label {
    display: block;
    font-size: 13px;
    color: var(--suave);
    margin: 14px 0 5px;
  }

  .acceso input {
    width: 100%;
    padding: 9px 11px;
    background: var(--fondo);
    border: 1px solid var(--borde);
    border-radius: var(--radio);
    color: var(--texto);
    font-size: 15px;
    font-family: inherit;
  }

  .acceso input:focus {
    outline: none;
    border-color: var(--texto);
  }

  .acceso button {
    width: 100%;
    margin-top: 22px;
    padding: 10px;
    background: var(--boton-fondo);
    border: none;
    border-radius: var(--radio);
    /* El mismo botón que "Actualizar": negro con texto hueso. */
    color: var(--sobre-boton);
    font-size: 15px;
    font-weight: 500;
    font-family: inherit;
    cursor: pointer;
  }

  .acceso button:hover:not(:disabled) { opacity: 0.88; }
  .acceso button:disabled { opacity: 0.55; cursor: default; }

  .acceso-error {
    margin: 0;
    padding: 9px 12px;
    border: 1px solid var(--rojo-bd);
    background: var(--rojo-bg);
    border-radius: var(--radio);
    color: var(--rojo);
    font-size: 14px;
  }

  .salir {
    color: var(--tenue);
    font-size: 12px;
    text-decoration: none;
    border-bottom: 1px solid var(--borde);
  }

  .salir:hover { color: var(--texto); }

  .error {
    border: 1px solid var(--rojo-bd);
    background: var(--rojo-bg);
    border-radius: var(--radio);
    padding: 18px 20px;
  }

  .error h2 { color: var(--rojo); }
  /* AJUSTE (avisos técnicos en ámbar): un fallo parcial (una sola lectura),
     en ámbar. El rojo queda para cuando no se puede cargar nada. */
  .error.tecnico { border-color: var(--ambar-bd); background: var(--ambar-bg); }

  .error pre {
    margin: 0;
    white-space: pre-wrap;
    word-break: break-word;
    font-family: var(--fuente-mono);
    font-size: 13px;
    color: var(--texto);
  }

  /* Pie: OPER1, discreto, en la mono. */
  .pie-oper1 {
    margin-top: 48px;
    padding-top: 16px;
    border-top: 1px solid var(--borde);
    font-size: var(--mono-pequena);
    font-weight: 500;
    color: var(--etiqueta);
  }

  /* Etiqueta de OPER1, fija abajo a la derecha: una pastilla pequeña con el
     fondo de las tarjetas, como en Brunch, con el isotipo del manual (por
     debajo de 90 px de ancho, isotipo). Sin animación ni botón de cerrar. El
     final de la página le deja hueco (padding de .envoltorio) para que no
     tape el pie. En el móvil no flota: va al final, bajo el pie. */
  .etiqueta-oper1 {
    position: fixed;
    right: 16px;
    bottom: calc(16px + env(safe-area-inset-bottom, 0px));
    z-index: 20;
    display: inline-flex;
    align-items: center;
    gap: 7px;
    padding: 5px 12px 5px 6px;
    background: var(--panel);
    border: 1px solid var(--borde);
    border-radius: 999px;
    box-shadow: var(--sombra-tarjeta);
    font-family: var(--fuente-principal);
    font-size: 13px;
    line-height: 1.2;
    color: var(--suave);
    text-decoration: none;
  }
  .etiqueta-oper1:hover { color: var(--texto); border-color: var(--suave); }
  .etiqueta-isotipo { display: block; width: 20px; height: 20px; flex: none; }
  .envoltorio { padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px)); }

  /* Venta reciente: una tarjeta debajo de otra cuando no caben dos. */
  @media (max-width: 700px) {
    .venta-reciente { grid-template-columns: minmax(0, 1fr); }
  }

  /* En el móvil, Hoy y Ayer en una fila, a media anchura; los 7 días y el
     total, debajo, a todo el ancho. En las de media anchura, cada cifra
     secundaria va debajo de su etiqueta, y el reparto puede ir en dos
     líneas. Como en Brunch. */
  @media (max-width: 480px) {
    /* El título "Venta reciente" no se enseña en el móvil: así caben las
       cuatro tarjetas tras la cabecera. En escritorio se queda. */
    .seccion-venta-reciente { margin-top: 12px; }
    .seccion-venta-reciente > h2 { display: none; }
    .venta-reciente { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; }
    .venta-reciente > .tarjeta:nth-child(n + 3) { grid-column: 1 / -1; }
    .venta-reciente .tarjeta { padding: 9px 12px; }
    .venta-reciente .rotulo { font-size: 11px; }
    .venta-reciente .cifra { font-size: 26px; line-height: 1; }
    .venta-reciente .reciente-unidad { font-size: 11px; margin-top: 1px; }
    .venta-reciente .reparto { font-size: 12px; margin-top: 3px; }
    /* En el móvil, "Ver qué entradas" se queda en una flecha al final de la
       línea del reparto: así no añade altura. */
    .venta-reciente .ver-entradas > summary { position: relative; padding-right: 12px; }
    .venta-reciente .ver-texto { position: absolute; right: 0; top: 3px; margin: 0; border: 0; font-size: 0; }
    .venta-reciente .ver-texto::before { font-size: 11px; }
    .venta-reciente > .tarjeta:nth-child(-n + 2) .ver-entradas > summary { padding-right: 9px; }
    .venta-reciente .reciente-filas { margin-top: 5px; padding-top: 4px; }
    .venta-reciente .reciente-filas li { padding: 0; }
    .venta-reciente .reciente-etiqueta { font-size: 11px; }
    .venta-reciente .reciente-valor { font-size: 15px; }
    /* Las de media anchura: cada cifra secundaria bajo su etiqueta. */
    .venta-reciente > .tarjeta:nth-child(-n + 2) .reciente-filas li { flex-direction: column; align-items: flex-start; gap: 0; line-height: 1.25; }
    .venta-reciente > .tarjeta:nth-child(-n + 2) .reciente-filas li + li { margin-top: 3px; }
    .venta-reciente > .tarjeta:nth-child(-n + 2) .reparto { font-size: 11px; gap: 0 7px; }
    /* Sin el punto separador: el hueco basta y así cabe en una línea. */
    .venta-reciente > .tarjeta:nth-child(-n + 2) .reparto-item + .reparto-item::before { content: none; }
  }

  @media (max-width: 560px) {
    :root { --relleno-plegable: 8px; }
    /* En el móvil la etiqueta no flota: va al final de la página, bajo el
       pie, así que el panel ya no necesita dejarle hueco. */
    .envoltorio { padding: 12px 12px 16px; }
    .etiqueta-oper1 {
      position: static;
      display: flex;
      width: fit-content;
      margin: 0 12px calc(24px + env(safe-area-inset-bottom, 0px));
      padding: 3px 10px 3px 4px;
      gap: 6px;
      font-size: 11px;
    }
    .etiqueta-isotipo { width: 18px; height: 18px; }
    section { margin-top: 22px; }
    /* Cabecera compacta: el logo y "Actualizar" en la primera línea; debajo,
       el cliente, el título, la línea de datos, los datos fijos y los
       enlaces, todo en letra pequeña y sin huecos de más. */
    header { padding: 14px 14px; }
    header > .cab-fila:first-child { display: grid; grid-template-columns: minmax(0, 1fr) auto; align-items: start; gap: 8px; }
    header .boton { padding: 7px 12px; font-size: 13px; }
    .marca-linea { gap: 4px 12px; }
    h1 { font-size: 19px; }
    .logo-oper1 { font-size: 22px; }
    .cab-cuerpo { margin-top: 8px; }
    /* Cabecera en columna: los enlaces, debajo y a la izquierda, en una línea. */
    .cab-cuerpo { flex-direction: column; align-items: flex-start; gap: 6px; }
    .cab-enlaces { flex-direction: row; flex-wrap: wrap; align-items: baseline; gap: 2px 14px; font-size: 12px; }
    header .salir, .cambiar-tema { font-size: 12px; }
    /* La línea de datos, una cosa por línea y sin los puntos de separación. */
    .cab-meta { flex-direction: column; align-items: flex-start; gap: 0; margin-top: 2px; font-size: 12px; }
    .cab-meta > span + span::before { content: none; }
    .datos-rapidos { gap: 0 12px; margin-top: 4px; }
    .dato { font-size: 12px; }
    /* Venta reciente, apretada para verla entera tras la cabecera. */
    .venta-reciente { gap: 10px; }
    .venta-reciente .tarjeta { padding: 12px 16px; }
    .venta-reciente .rotulo { margin-bottom: 2px; }
    .venta-reciente .cifra { font-size: 30px; }
    .reciente-unidad { font-size: 12px; }
    .reciente-filas { margin-top: 8px; padding-top: 6px; }
    .reciente-filas li { padding: 1px 0; }
    .reciente-valor { font-size: 17px; }
    .reciente-etiqueta { font-size: 12px; }
    .error-refresco { text-align: left; }
    .cifra { font-size: 34px; }
    .cifra.cifra-texto { font-size: 28px; }
    .estado-campana { padding: 2px 16px; }
    /* Los gráficos se dibujan al ancho real (ver ajustarLienzo), así que esto
       son píxeles de verdad. */
    .eje-texto, .cifra-corte { font-size: var(--mono-pequena); }
    th, td { padding: 8px 10px; }
    th:first-child, td:first-child { min-width: 140px; }
  }


  /* Estado del evento y servicios opcionales: mismo tema OPER1. */
  .modo-demo { margin: 8px 0 0; color: var(--ambar); font-size: 13px; }
  .modo-demo b { text-transform: uppercase; letter-spacing: var(--rotulo-espaciado); }
  .camping-aclaracion { margin: 0 0 14px; max-width: 850px; }
  .estado-vacio { margin: 0; padding: 16px 20px; }
  .entrada-demo { display: block; width: 100%; margin-top: 10px; padding: 10px 14px; border: 1px solid var(--borde); border-radius: var(--radio); background: var(--panel-2); color: var(--texto); font: inherit; cursor: pointer; }
  .entrada-demo:hover { border-color: var(--acento); }
  .aviso-pendientes ul { margin: 8px 0 0; padding-left: 20px; }
  .aviso-pendientes p { margin: 8px 0 0; }
