/* mibarra — panel de administración (estilo Revolut: gris frío, blanco, azul)
   Dinero: efectivo=verde · tarjeta=azul · NFC=violeta */
:root {
  --bg: #f5f6f8;
  --card: #ffffff;
  --ink: #14181d;
  --ink-2: #23292f;
  --muted: #69717f;
  --line: #e6e9ee;
  --line-soft: #eef1f4;
  --brand: #0666eb;
  --brand-deep: #0554c4;
  --brand-ink: #0554c4;
  --brand-soft: #edf4ff;
  --ok: #0e7f3e;
  --ok-bg: #e6f6ec;
  --warn: #916900;
  --warn-bg: #fff4d6;
  --bad: #d41e24;
  --bad-bg: #fdebec;
  --nfc: #6749ff;
  --nfc-bg: #efebff;
  --radius: 14px;
  --shadow-sm: 0 1px 2px rgba(20, 24, 29, .05);
  --shadow-md: 0 6px 16px rgba(20, 24, 29, .07), 0 1px 2px rgba(20, 24, 29, .05);
  --shadow-lg: 0 28px 70px rgba(20, 24, 29, .16), 0 6px 16px rgba(20, 24, 29, .07);
}
* { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-font-smoothing: antialiased; }
body {
  font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
  background: var(--bg); color: var(--ink); font-size: 14px; line-height: 1.45;
}
/* El panel usa la pantalla que hay.
   Estaba topado a 1180 px, medida pensada para leer texto; aquí lo que hay son
   tablas de siete y ocho columnas, y ese tope las obligaba a cortarse —el
   botón de borrar se quedaba a medias— mientras sobraba pantalla a los lados.
   Sigue habiendo un tope: a partir de cierto ancho, las filas se vuelven tan
   largas que se pierde de vista de qué fila era el importe que estás mirando. */
#app { max-width: 1560px; margin: 0 auto; padding: 24px 24px 60px; }
h1, h2, h3, .brand { font-family: "Outfit", "Inter", sans-serif; }
h1 { font-size: 21px; font-weight: 700; letter-spacing: -.02em; }
h2 { font-size: 15px; font-weight: 600; letter-spacing: -.01em; margin-bottom: 12px; }
h3 { font-size: 15px; font-weight: 600; letter-spacing: -.01em; }
a { color: var(--brand-ink); text-decoration: none; font-weight: 600; }
a:hover { color: var(--brand-deep); }

.brand {
  font-weight: 700; font-size: 19px; letter-spacing: -.03em; color: var(--ink);
  display: inline-flex; align-items: center; gap: 9px;
}
/* La marca es Entradon: la Ǝ del rótulo como sello y el rótulo como nombre. */
.brand::before {
  content: ""; display: inline-flex;
  width: 27px; height: 27px; border-radius: 9px;
  background: url(/marca/entradon-icono.png) center / cover;
  box-shadow: 0 1px 4px rgba(20, 24, 29, .18);
}
.brand img { height: 15px; display: block; }
.brand span { color: var(--muted); font-weight: 500; font-size: 13px; margin-left: 2px; }

button {
  font: inherit; font-weight: 500; cursor: pointer;
  border: 1px solid var(--line); background: var(--card); color: var(--ink);
  border-radius: 9px; padding: 8px 14px; box-shadow: var(--shadow-sm);
  transition: box-shadow .15s, transform .1s, background .15s, border-color .15s;
}
button:hover { border-color: #d3d9e0; box-shadow: var(--shadow-md); }
button:active { transform: translateY(1px); box-shadow: none; }
button.primary {
  background: linear-gradient(180deg, var(--ink-2), var(--ink));
  color: #fff; border-color: transparent; font-weight: 600;
  box-shadow: 0 2px 8px rgba(20, 24, 29, .3), inset 0 1px 0 rgba(255, 255, 255, .08);
}
button.primary:hover { background: var(--ink-2); }
button.danger { color: var(--bad); }
button.danger:hover { border-color: #efb9c1; background: var(--bad-bg); }
button.small { padding: 5px 11px; font-size: 13px; border-radius: 8px; }
button:disabled { opacity: .5; cursor: default; }
button:focus-visible, input:focus-visible, select:focus-visible {
  outline: 2px solid var(--brand); outline-offset: 1px;
}

input, select {
  font: inherit; padding: 8px 11px; border: 1px solid #dbe0e7;
  border-radius: 9px; background: var(--card); color: var(--ink); width: 100%;
  transition: border-color .15s, box-shadow .15s;
}
input:focus, select:focus {
  outline: none; border-color: var(--brand-deep);
  box-shadow: 0 0 0 3px rgba(6, 102, 235, .16);
}
label { display: block; font-size: 12px; font-weight: 500; color: var(--muted); margin: 12px 0 5px; }

.topbar {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 22px; gap: 12px; flex-wrap: wrap;
}
.topbar .who { color: var(--muted); font-size: 13px; }

.card {
  background: var(--card); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 18px; margin-bottom: 16px;
  box-shadow: var(--shadow-sm);
}

.grid-cards { display: grid; grid-template-columns: repeat(auto-fill, minmax(270px, 1fr)); gap: 16px; }
.event-card {
  cursor: pointer; position: relative; overflow: hidden;
  transition: box-shadow .2s, transform .2s, border-color .2s;
}
.event-card::before {
  content: ""; position: absolute; inset: 0 0 auto 0; height: 3px;
  background: linear-gradient(90deg, #338af5, var(--brand) 55%, var(--brand-deep));
  opacity: 0; transition: opacity .2s;
}
.event-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); border-color: #d3d9e0; }
.event-card:hover::before { opacity: 1; }
.event-card .total {
  font-size: 28px; font-weight: 700; letter-spacing: -.03em; margin-top: 12px;
  font-variant-numeric: tabular-nums;
}

.badge {
  display: inline-block; font-size: 11px; font-weight: 600; letter-spacing: .02em;
  padding: 2px 9px; border-radius: 99px; background: var(--line-soft); color: var(--muted);
}
.badge.activo, .badge.completada, .badge.abierto { background: var(--ok-bg); color: var(--ok); }
.badge.borrador { background: var(--warn-bg); color: var(--warn); }
.badge.finalizado, .badge.cerrado { background: var(--line-soft); color: var(--muted); }
.badge.anulada { background: var(--bad-bg); color: var(--bad); }
.badge.mal { background: var(--bad-bg); color: var(--bad); }
.badge.avisa { background: var(--warn-bg); color: var(--warn); }

/* --- existencias ---
   Lo que se mira aquí es qué está a punto de acabarse, así que esas filas se
   tiñen enteras: una etiqueta pequeña en una tabla de veinte líneas no la ve
   nadie con el evento en marcha. */
.fila-mal   { background: var(--bad-bg); }
.fila-avisa { background: var(--warn-bg); }
.fila-mal td, .fila-avisa td { border-bottom-color: transparent; }
.rojo { color: var(--bad); }
.aviso-stock {
  border-left: 4px solid var(--bad); font-size: 15px;
}
.aviso-stock b { color: var(--bad); }

.tabs {
  display: inline-flex; gap: 3px; background: var(--line-soft);
  border: 1px solid var(--line); border-radius: 12px; padding: 3px;
  margin-bottom: 20px; flex-wrap: wrap;
}
.tabs button {
  border: none; background: none; box-shadow: none;
  padding: 7px 14px; color: var(--muted); font-weight: 500; font-size: 13.5px;
  border-radius: 9px;
}
.tabs button:hover { color: var(--ink); }
.tabs button.active {
  color: var(--ink); background: var(--card); font-weight: 600;
  box-shadow: var(--shadow-sm);
}

table { width: 100%; border-collapse: collapse; font-size: 13.5px; }
th {
  text-align: left; color: var(--muted); font-weight: 600; font-size: 11px;
  text-transform: uppercase; letter-spacing: .05em; padding: 6px 10px 8px;
  border-bottom: 1px solid var(--line);
}
td { padding: 9px 10px; border-bottom: 1px solid var(--line-soft); vertical-align: top; }
tbody tr { transition: background .12s; }
tbody tr:hover { background: #f8fafc; }
tr:last-child td { border-bottom: none; }
/* Las cifras nunca se parten. "10 %" cortado en dos líneas se lee como si
   fueran dos datos distintos, y un importe partido cuesta de leer. */
td.num, th.num {
  text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap;
}

/* Los botones de una fila van en línea. Al apilarse verticalmente la fila
   crece al doble y la tabla se vuelve una escalera. */
td:last-child { white-space: nowrap; }
td:last-child button { display: inline-block; }

/* Las celdas se alinean al centro vertical: con "vertical-align: top", una
   fila con el nombre en dos líneas dejaba los botones despegados arriba. */
td { vertical-align: middle; }

/* El nombre puede ocupar dos líneas, pero sin romper palabras a mitad.
   Con nombres cortos (los habituales) cabe en una. */
td:first-child { overflow-wrap: break-word; min-width: 7em; }

.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(160px, 1fr)); gap: 14px; margin-bottom: 16px; }
.stat {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 15px 16px; box-shadow: var(--shadow-sm);
}
.stat .label { font-size: 12px; font-weight: 500; color: var(--muted); }
.stat .value {
  font-size: 24px; font-weight: 700; letter-spacing: -.03em; margin-top: 5px;
  font-variant-numeric: tabular-nums;
}

/* Dos columnas solo si ambas caben con holgura. Con un reparto fijo, unas
   tablas quedaban apretadas y otras medio vacías según cuántas columnas
   tuvieran; con un mínimo por columna, se pasa a una sola cuando no hay
   sitio y ninguna se desborda. */
.cols-2 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(430px, 1fr));
  gap: 16px; align-items: start;
}

/* Una tabla larga con una lista corta al lado.
   Con dos columnas iguales, la tabla de productos —siete columnas— se cortaba
   por la mitad mientras "Categorías", que son tres filas de tres campos, se
   quedaba media pantalla vacía. La lista corta se lleva lo justo. */
.cols-principal-lateral {
  display: grid; grid-template-columns: minmax(0, 1fr) 340px;
  gap: 16px; align-items: start;
}
@media (max-width: 1080px) {
  .cols-principal-lateral { grid-template-columns: 1fr; }
}

/* Una tabla ancha dentro de una tarjeta estrecha se desborda; que la tarjeta
   haga scroll horizontal en vez de romper la página.
   El scroll va en la TARJETA y no en la tabla: poniendo display:block sobre
   la tabla se pierde el reparto de columnas y se queda encogida a la mitad
   del espacio disponible. */
.card { overflow-x: auto; }

.filters { display: flex; gap: 10px; flex-wrap: wrap; align-items: flex-end; margin-bottom: 14px; }
.filters > div { min-width: 150px; }
.filters label { margin-top: 0; }

.chart { display: flex; align-items: flex-end; gap: 8px; height: 170px; padding-top: 10px; overflow-x: auto; }
.chart .bar-wrap { display: flex; flex-direction: column; align-items: center; gap: 5px; min-width: 56px; height: 100%; justify-content: flex-end; }
.chart .bar {
  width: 30px; min-height: 3px; border-radius: 6px 6px 2px 2px;
  background: linear-gradient(180deg, #338af5, var(--brand));
  box-shadow: 0 2px 6px rgba(6, 102, 235, .25);
}
.chart .bar-label { font-size: 10px; color: var(--muted); white-space: nowrap; }
.chart .bar-value { font-size: 10px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }

.modal-bg {
  position: fixed; inset: 0; background: rgba(20, 24, 29, .4);
  backdrop-filter: blur(3px); -webkit-backdrop-filter: blur(3px);
  display: flex; align-items: center; justify-content: center; z-index: 50; padding: 16px;
  animation: fade .15s ease-out;
}
@keyframes fade { from { opacity: 0; } }
.modal {
  background: var(--card); border-radius: 16px; padding: 22px;
  width: 100%; max-width: 460px; max-height: 90vh; overflow-y: auto;
  box-shadow: var(--shadow-lg); animation: pop .18s ease-out;
}
@keyframes pop { from { opacity: 0; transform: translateY(8px) scale(.98); } }
.modal h2 { margin-bottom: 4px; font-size: 17px; }
.modal .actions { display: flex; gap: 10px; justify-content: flex-end; margin-top: 20px; }

.login-box { max-width: 380px; margin: 12vh auto 0; padding: 28px; box-shadow: var(--shadow-md); }
.login-box h1 { font-size: 22px; margin-top: 14px; }

.error { color: var(--bad); font-size: 13px; margin-top: 8px; }
.muted { color: var(--muted); font-size: 13px; }
.inline-price {
  width: 78px; text-align: right; font-variant-numeric: tabular-nums;
  padding: 7px 9px; font-size: 13.5px;
}
.row-inactive { opacity: .45; }
.pill-dot { display: inline-block; width: 10px; height: 10px; border-radius: 4px; margin-right: 6px; vertical-align: baseline; }
.mono { font-family: "SF Mono", ui-monospace, Menlo, monospace; font-size: 12px; letter-spacing: .04em; }
.sale-lines { font-size: 12.5px; color: var(--muted); }
.pos-diff { color: var(--ok); font-weight: 600; } .neg-diff { color: var(--bad); font-weight: 600; }
.section-head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 10px; gap: 10px; flex-wrap: wrap; }
.refresh-note { font-size: 12px; color: var(--muted); display: inline-flex; align-items: center; gap: 6px; }
.refresh-note::before {
  content: ""; width: 7px; height: 7px; border-radius: 50%; background: #23b673;
  box-shadow: 0 0 0 3px rgba(35, 182, 115, .18); animation: pulse 2.4s infinite;
}
@keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: .4; } }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { animation: none !important; transition: none !important; }
}

.dec { font-size: .62em; font-weight: 600; opacity: .8; }
.chip { display:inline-block; font-size:11px; font-weight:700; border-radius:99px; padding:2px 9px; margin-right:4px; }
.chip.efectivo { background: var(--ok-bg); color: var(--ok); }
.chip.tarjeta { background: var(--brand-soft); color: var(--brand); }
.chip.nfc { background: var(--nfc-bg); color: var(--nfc); }

/* galería de imágenes de producto */
.img-picker { display: grid; grid-template-columns: repeat(auto-fill, minmax(64px, 1fr)); gap: 8px; margin-top: 4px; }
.img-opt {
  padding: 0; border-radius: 12px; overflow: hidden; aspect-ratio: 1;
  border: 2px solid var(--line); background: var(--line-soft); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-size: 10px; color: var(--muted); text-align: center; line-height: 1.2;
}
.img-opt img { width: 100%; height: 100%; object-fit: cover; display: block; }
.img-opt.sel { border-color: var(--brand); box-shadow: 0 0 0 3px rgba(6, 102, 235, .18); }
/* Los dibujos de producto son ilustraciones con márgenes: "contain" los
   deja enteros, mientras que "cover" recortaba los bordes. */
.prod-thumb {
  width: 32px; height: 32px; border-radius: 8px; object-fit: contain;
  display: block; background: var(--bg); padding: 2px;
}
.chip.ft { background: var(--warn-bg); color: var(--warn); margin-right: 6px; }
.kv-row { display: flex; justify-content: space-between; padding: 7px 0; font-size: 13.5px; color: var(--muted); border-bottom: 1px solid var(--line-soft); }
.kv-row b { color: var(--ink); font-variant-numeric: tabular-nums; }
.kv-row.total { border-bottom: none; padding-top: 10px; font-weight: 600; color: var(--ink); }
.kv-row.total b { font-size: 17px; }

/* reordenación por arrastre */
.drag-cell { width: 28px; }
.drag-handle {
  display: inline-flex; align-items: center; justify-content: center;
  width: 24px; height: 24px; border-radius: 6px; color: #b6bcc6; cursor: grab;
}
.drag-handle:hover { background: var(--line-soft); color: var(--muted); }
tr.dragging { opacity: .45; background: var(--brand-soft); }

/* ==========================================================================
   Pantallas nuevas: seguimiento en vivo, plataforma y usuarios
   ========================================================================== */

/* --- chip de la organización activa en la barra superior --- */
.org-chip {
  background: var(--brand-soft);
  color: var(--brand-deep);
  border: 1px solid var(--line);
  border-radius: 999px;
  padding: 5px 14px;
  font-weight: 600;
  font-size: 14px;
  cursor: pointer;
}
.org-chip:hover { background: var(--brand); color: var(--brand-ink); }

.org-pick { border: 1px solid var(--line); border-radius: var(--radius); background: var(--card); }
.org-pick:hover { border-color: var(--brand); box-shadow: var(--shadow-sm); }

/* --- cifras de cabecera del directo --- */
.vivo-cabecera {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr 1fr;
  gap: 14px;
  margin-bottom: 20px;
}
.vivo-cabecera .card { padding: 16px 18px; }
.vivo-cabecera .total { font-size: 26px; font-weight: 800; letter-spacing: -0.5px; margin: 2px 0; }
.vivo-total .total { font-size: 34px; color: var(--brand-deep); }
.vivo-cabecera .total .dec { font-size: 0.62em; opacity: 0.65; font-weight: 700; }

.vivo-cols { display: grid; grid-template-columns: 1.5fr 1fr; gap: 22px; align-items: start; }
.vivo-cols h3 { font-size: 15px; margin: 0 0 10px; display: flex; align-items: center; gap: 8px; }

/* Latido que indica que la pantalla se está actualizando sola. */
.pulso {
  width: 8px; height: 8px; border-radius: 50%;
  background: var(--ok);
  animation: latido 2s ease-in-out infinite;
}
@keyframes latido {
  0%, 100% { opacity: 1; box-shadow: 0 0 0 0 color-mix(in srgb, var(--ok) 60%, transparent); }
  50%      { opacity: .55; box-shadow: 0 0 0 5px transparent; }
}
@media (prefers-reduced-motion: reduce) { .pulso { animation: none; } }

/* --- listado de ventas en directo --- */
.feed {
  background: var(--card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  max-height: 62vh;
  overflow-y: auto;
}
.feed-row {
  display: grid;
  grid-template-columns: 54px 1fr auto;
  gap: 12px;
  align-items: center;
  padding: 11px 16px;
  border-bottom: 1px solid var(--line-soft);
}
.feed-row:last-child { border-bottom: 0; }
/* La venta más reciente entra con un destello para que se note. */
.feed-row:first-child { animation: entra .5s ease-out; }
@keyframes entra { from { background: var(--brand-soft); } to { background: transparent; } }
@media (prefers-reduced-motion: reduce) { .feed-row:first-child { animation: none; } }

.feed-hora { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.feed-que b { display: block; font-weight: 600; font-size: 14px; }
.feed-que span { font-size: 12px; color: var(--muted); }
.feed-imp {
  text-align: right; font-weight: 700; font-variant-numeric: tabular-nums;
  display: flex; align-items: center; gap: 8px;
}
.feed-row.anulada { opacity: .5; }
.feed-row.anulada .feed-que b { text-decoration: line-through; }

/* --- pares dato/valor de las tarjetas laterales --- */
.kv {
  display: flex; justify-content: space-between; gap: 12px;
  padding: 7px 0; border-bottom: 1px solid var(--line-soft);
  font-size: 14px;
}
.kv:last-child { border-bottom: 0; }
.kv span { color: var(--muted); }
.kv b { font-variant-numeric: tabular-nums; white-space: nowrap; }

/* --- credenciales recién creadas --- */
.cred-box {
  background: var(--brand-soft);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 14px 16px;
  margin-top: 12px;
}

.row-2 { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 18px; }

/* --- distintivos de rol --- */
.badge.propietario { background: var(--brand-soft); color: var(--brand-deep); }
.badge.admin       { background: var(--ok-bg); color: var(--ok); }
.badge.supervisor  { background: var(--warn-bg); color: var(--warn); }
.badge.promotor    { background: var(--nfc-bg); color: var(--nfc); }

/* En pantallas estrechas todo pasa a una columna: el panel se consulta
   mucho desde el móvil durante el evento. */
@media (max-width: 900px) {
  .vivo-cabecera { grid-template-columns: 1fr 1fr; }
  .vivo-cols, .row-2 { grid-template-columns: 1fr; }
  .feed { max-height: none; }
}
@media (max-width: 560px) {
  /* El facturado ocupa toda la fila y el desglose va de dos en dos: de una en
     una había que hacer scroll para ver el total y el efectivo a la vez, que
     es justo la comparación que se hace de un vistazo. */
  .vivo-cabecera { grid-template-columns: 1fr 1fr; }
  .vivo-cabecera .vivo-total { grid-column: 1 / -1; }
  .feed-row { grid-template-columns: 46px 1fr; }
  .feed-imp { grid-column: 2; justify-content: flex-start; }
}

/* --- logo del evento ---------------------------------------------------
   Reconocer el evento por su marca es más rápido que leer el nombre, y
   evita que alguien abra turno en el evento equivocado cuando la
   organización lleva dos a la vez. */
.logo-ev {
  border-radius: 50%; object-fit: cover; flex-shrink: 0;
  background: #fff; border: 1px solid rgba(20, 24, 29, .08);
}
.logo-ini {
  display: inline-flex; align-items: center; justify-content: center;
  font-weight: 800; letter-spacing: -.02em; font-size: 15px;
  background: var(--panel-2); color: var(--muted);
}
/* subida de logo en el formulario de evento */
.logo-campo { display: flex; gap: 14px; align-items: flex-start; margin-bottom: 6px; }
.logo-prev {
  width: 76px; height: 76px; border-radius: 50%; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg); border: 1px dashed var(--line);
  font-size: 11px; overflow: hidden;
}
.logo-prev img { width: 100%; height: 100%; object-fit: cover; }

/* Celdas que nunca deben partirse: fechas, importes y códigos. */
.nowrap { white-space: nowrap; }

/* Aviso de que la tabla continúa a la derecha. Sin esto, con doce columnas
   no hay forma de saber que falta información por ver. */
.card { position: relative; }
.card::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; width: 26px;
  background: linear-gradient(to right, transparent, var(--card));
  pointer-events: none; opacity: 0; transition: opacity .2s;
}
.card.desborda::after { opacity: 1; }

/* ---------------------------------------------------------------------------
   Cobros con tarjeta

   La jerarquía es la del cierre de caja: primero lo que impide cerrar,
   después los totales, al final el detalle. Los avisos usan el número grande
   a la izquierda porque lo primero que se quiere saber es cuántos son.
--------------------------------------------------------------------------- */
.avisos { display: grid; gap: 10px; margin-bottom: 18px; }

.aviso {
  display: flex; align-items: center; gap: 16px;
  padding: 14px 18px; border-radius: var(--radius);
  border: 1px solid var(--line); background: var(--card);
  box-shadow: var(--shadow-sm);
}
.aviso.solo { margin-bottom: 18px; }
.aviso-n {
  flex: none; min-width: 44px; height: 44px; padding: 0 10px;
  border-radius: 12px; display: grid; place-items: center;
  font-size: 20px; font-weight: 800; font-variant-numeric: tabular-nums;
}
.aviso-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.aviso-txt b { font-size: 15px; }
.aviso-txt span { color: var(--muted); font-size: 13.5px; line-height: 1.45; }
.aviso button { flex: none; }

.aviso.bad  { border-color: #f3c9cb; background: var(--bad-bg); }
.aviso.bad  .aviso-n { background: var(--bad); color: #fff; }
.aviso.bad  .aviso-txt b { color: var(--bad); }
.aviso.warn { border-color: #ecd9a0; background: var(--warn-bg); }
.aviso.warn .aviso-n { background: var(--warn); color: #fff; }
.aviso.warn .aviso-txt b { color: var(--warn); }
.aviso.ok   { border-color: #bfe3cd; background: var(--ok-bg); }
.aviso.ok   .aviso-txt b { color: var(--ok); }

.card.problema { border-color: #f3c9cb; }
.card.problema .section-head h2 { color: var(--bad); }

.stat .sub { color: var(--muted); font-size: 12.5px; margin-top: 4px; }
.acciones { white-space: nowrap; text-align: right; }
.acciones button + button { margin-left: 6px; }

.hint {
  color: var(--muted); font-size: 13px; line-height: 1.5;
  margin: 10px 16px 14px;
}
label.check {
  display: flex; align-items: center; gap: 9px;
  font-weight: 500; margin-top: 12px; cursor: pointer;
}
label.check input { width: auto; margin: 0; }
.modal label small {
  display: block; color: var(--muted); font-weight: 400;
  font-size: 12.5px; margin-top: 4px; line-height: 1.45;
}

/* Aviso breve: aparece abajo a la derecha y se va solo. */
#toast {
  position: fixed; right: 20px; bottom: 20px; z-index: 300;
  max-width: min(420px, calc(100vw - 40px));
  padding: 13px 18px; border-radius: 12px;
  background: var(--ink); color: #fff;
  font-size: 14px; font-weight: 600; line-height: 1.45;
  box-shadow: var(--shadow-lg, 0 12px 32px rgba(20, 24, 29, .22));
  opacity: 0; transform: translateY(10px); pointer-events: none;
  transition: opacity .18s ease, transform .18s ease;
}
#toast.visible { opacity: 1; transform: none; }
#toast.malo { background: var(--bad); }
@media (prefers-reduced-motion: reduce) {
  #toast { transition: none; }
}

/* ---------------------------------------------------------------------------
   NAVEGACIÓN DEL EVENTO

   Antes eran seis pestañas en fila donde todo pesaba lo mismo. Ahora las
   secciones van agrupadas por cómo se trabaja —los dos primeros grupos son los
   mismos por los que se entra en el móvil—, y cada una lleva debajo una línea
   que dice para qué sirve: quien monta un evento por primera vez no tiene por
   qué adivinar dónde se ponen los precios de las entradas.
--------------------------------------------------------------------------- */
/* El menú del evento, arriba y en una sola fila.
   Estaba en un lateral de 196 px que se llevaba ese ancho de forma permanente,
   y debajo hay tablas de siete y ocho columnas: ese ancho era justo el que les
   faltaba para no cortarse. Arriba gasta una fila de alto y devuelve la
   pantalla entera al contenido.
   Si algún día no cabe —más secciones, pantalla estrecha— se desliza en
   horizontal en vez de partirse en dos filas. */
.menu-ev {
  display: flex; align-items: center; gap: 2px;
  background: var(--card); border: 1px solid var(--line);
  border-radius: 14px; box-shadow: var(--shadow-sm);
  padding: 5px; margin-bottom: 18px;
  overflow-x: auto; scrollbar-width: none;
}
.menu-ev::-webkit-scrollbar { display: none; }
.menu-sep {
  flex: none; width: 1px; height: 22px; background: var(--line); margin: 0 6px;
}
.menu-item {
  display: inline-flex; align-items: center; gap: 7px; flex: none;
  background: none; border: 0; box-shadow: none; border-radius: 10px;
  padding: 8px 12px; cursor: pointer; color: var(--muted); white-space: nowrap;
}
.menu-item svg { width: 17px; height: 17px; flex: none; }
.menu-item b { font-size: 13.5px; font-weight: 550; letter-spacing: -.01em; }
.menu-item:hover { background: var(--line-soft); color: var(--ink); border-color: transparent; box-shadow: none; }
.menu-item.activa { background: var(--brand-soft); color: var(--brand-ink); }
.menu-item.activa b { font-weight: 650; }
.menu-item:focus-visible { outline: 2px solid var(--brand); outline-offset: -2px; }
.ev-cuerpo { min-width: 0; }

/* Volver a la lista de eventos: un botón, no un enlace pegado al título. */
.volver {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 6px 12px 6px 9px; font-size: 13px; font-weight: 600;
  color: var(--muted); background: var(--card);
  border: 1px solid var(--line); border-radius: 99px;
}
.volver svg { width: 15px; height: 15px; }
.volver:hover { color: var(--ink); border-color: var(--ink); background: var(--card); }

.topbar .tb-izq { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.topbar .tb-der { display: flex; gap: 10px; align-items: center; }
.topbar .codigo-tpv { font-size: 12.5px; }

/* En pantalla estrecha el menú pasa arriba y se desliza en horizontal: en una
   tablet en la puerta no hay 232 px que regalar a un lateral. */
@media (max-width: 860px) {
  /* El menú ya es horizontal en todas las pantallas; aquí solo se aprieta un
     poco para que quepan más secciones antes de tener que deslizar. */
  .menu-item { padding: 8px 10px; }
  .menu-item b { font-size: 13px; }
  .menu-sep { margin: 0 3px; }
}

/* ---------------------------------------------------------------------------
   CIFRAS DE CABECERA

   Lo que hay que poder leer sin acercarse a la pantalla. En accesos, la gente
   que hay dentro va destacada porque el aforo es responsabilidad legal y llega
   un momento de la noche en que es lo único que importa.
--------------------------------------------------------------------------- */
.cifras { display: grid; grid-template-columns: repeat(auto-fit, minmax(190px, 1fr)); gap: 14px; margin-bottom: 18px; }
.cifra {
  background: var(--card); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); padding: 14px 16px;
}
/* Hijo directo, no cualquier descendiente: los decimales de un importe van en
   un <span> DENTRO del <b>, y con el selector abierto se les aplicaba también
   este `display: block`. Resultado: un "784" enorme con un ",00 €" en la
   línea de abajo, que ni se lee como una cantidad. */
.cifra > span { display: block; color: var(--muted); font-size: 12.5px; }
.cifra b {
  display: block; margin-top: 4px;
  font-family: "Outfit", "Inter", sans-serif; font-size: 27px; font-weight: 700;
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
}
.cifra.destacada { border-color: var(--brand); background: var(--brand-soft); }
.cifra.destacada b, .cifra.destacada span { color: var(--brand-ink); }

/* Chips de sí/no y de módulos del TPV. */
.chip.ok { background: var(--ok-bg); color: var(--ok); }
.chip.no { background: var(--bad-bg); color: var(--bad); }
.chip.mod-sell { background: var(--brand-soft); color: var(--brand-ink); }
.chip.mod-cashless { background: var(--nfc-bg); color: var(--nfc); }
.chip.mod-tickets { background: var(--warn-bg); color: var(--warn); }
.chip.mod-access { background: var(--ok-bg); color: var(--ok); }
.muted.sub { font-weight: 400; font-size: 13px; }

/* Opciones marcables con su explicación: se usa para elegir a qué módulos del
   TPV entra cada persona, que es lo que decide qué ve al entrar. */
.opciones { display: grid; gap: 8px; margin: 6px 0 10px; }
.opcion {
  display: flex; gap: 10px; align-items: flex-start; font-weight: 400;
  border: 1px solid var(--line); border-radius: 10px; padding: 10px 12px; cursor: pointer;
}
.opcion:hover { border-color: var(--brand); background: var(--brand-soft); }
/* Marcada se ve marcada, sin tener que mirar el cuadradito.
   Antes lo único que cambiaba era una casilla de trece píxeles, y en una lista
   de cinco opciones había que repasarlas una a una para saber qué estaba
   puesto. */
.opcion.marcada { border-color: var(--brand); background: var(--brand-soft); }
.opcion.marcada b { color: var(--brand); }
.opcion input { width: auto; margin-top: 2px; }
.opcion b { display: block; font-size: 13.5px; }
.opcion small { display: block; color: var(--muted); font-size: 12px; }

/* El acceso al TPV: en rojo cuando se le está dejando fuera.
   Es lo que más cuesta descubrir tarde —un camarero que no puede abrir turno
   con la cola puesta—, así que no puede parecerse a las demás opciones cuando
   está apagado. */
.opcion-acceso { margin-top: 4px; }
.opcion-acceso.fuera {
  border-color: var(--bad); background: var(--bad-bg);
}
.opcion-acceso.fuera b { color: var(--bad); }
.opcion-acceso.fuera small { color: var(--bad); opacity: .85; }
.chip { white-space: nowrap; }

/* ---------------------------------------------------------------------------
   AVISO DE SESIÓN

   "Tu sesión se ha cerrado por inactividad" iba en gris pequeño, del mismo
   color que el texto de apoyo, así que quien volvía a la pantalla de entrar
   no se enteraba de por qué le habían echado y creía que la aplicación había
   fallado. Lleva color de aviso porque es una explicación, no un adorno.
--------------------------------------------------------------------------- */
.aviso-sesion {
  margin-top: 14px; padding: 11px 14px; border-radius: 10px;
  background: var(--warn-bg); color: var(--warn);
  font-size: 13.5px; font-weight: 600; line-height: 1.45;
}

/* ---------------------------------------------------------------------------
   EL PANEL EN UN MÓVIL

   Durante el evento el panel se abre desde el móvil, de pie y con una mano:
   se mira el directo, se comprueba un arqueo o se da de alta a alguien que
   acaba de llegar. Antes salía en tamaño de escritorio encogido, con las
   tablas desbordadas y los diálogos sin sitio para el teclado.
--------------------------------------------------------------------------- */
@media (max-width: 640px) {
  #app { padding: 14px 12px 48px; }

  /* La cabecera se apila y deja el nombre del evento arriba, entero. */
  .topbar { gap: 8px; margin-bottom: 16px; }
  .topbar .tb-izq { gap: 8px; }
  .topbar .tb-izq h1 { font-size: 18px; width: 100%; order: -1; }
  .topbar .tb-der { width: 100%; justify-content: flex-end; }
  /* Quién ha entrado importa poco cuando falta sitio: el botón de salir, no. */
  .topbar .who { display: none; }
  .topbar .codigo-tpv { font-size: 12px; }

  h1 { font-size: 19px; }
  .card { padding: 14px; border-radius: 12px; }

  /* Dos cifras por fila: de una en una obligaba a hacer scroll para ver el
     total y el desglose a la vez, que es justo la comparación que se hace. */
  .cifras { grid-template-columns: 1fr 1fr; gap: 10px; }
  .cifra { padding: 11px 12px; }
  .cifra b { font-size: 22px; }
  .cifra span { font-size: 11.5px; }
  .stats { grid-template-columns: 1fr 1fr; gap: 10px; }

  /* Las tablas siguen haciendo scroll dentro de su tarjeta, pero con menos
     aire por celda caben dos columnas más antes de tener que arrastrar. */
  table { font-size: 13px; }
  th { padding: 6px 7px 7px; }
  td { padding: 8px 7px; }
  td:first-child { min-width: 6em; }
  .card { -webkit-overflow-scrolling: touch; }

  /* El diálogo sube y se pega abajo, como una hoja: así el teclado del móvil
     no tapa los botones de guardar. */
  .modal-bg { align-items: flex-end; }
  .modal {
    width: 100%; max-width: none; max-height: 92dvh; overflow-y: auto;
    border-radius: 18px 18px 0 0; padding: 18px 16px calc(16px + env(safe-area-inset-bottom));
  }
  .modal .actions, .modal-actions { position: sticky; bottom: 0; background: var(--card); padding-top: 12px; }
  .modal .actions button, .modal-actions button { flex: 1; padding: 13px; }

  /* Los controles se tocan con el dedo: 44 px es el mínimo que se acierta. */
  button, .btn { min-height: 40px; }
  button.small { min-height: 36px; }
  input, select, textarea { font-size: 16px; min-height: 42px; }  /* 16px evita el zoom de iOS */

  .login-box { margin: 6vh auto 0; padding: 22px 18px; }
  .filters { gap: 8px; }
  .filters > div { min-width: 130px; flex: 1; }
}
@media (max-width: 640px) {
  /* Sin el margen del fondo, la hoja llega de verdad hasta el borde. */
  .modal-bg { padding: 0; }
}

@media (max-width: 640px) {
  /* El título y su botón, uno debajo del otro. En una fila, el botón se
     montaba encima del texto en cuanto el título llevaba explicación. */
  .section-head { flex-direction: column; align-items: stretch; gap: 8px; }
  .section-head h2 { margin-bottom: 0; }
  .section-head button { width: 100%; }

  /* La tabla conserva un ancho mínimo y se desliza dentro de su tarjeta.
     Comprimiéndola para que "quepa", cada celda con dos etiquetas se partía
     en tres líneas y la fila crecía hasta hacerse ilegible: se lee mejor
     arrastrando de lado que leyendo una escalera. */
  .card > table, .card table { min-width: 620px; }
  /* Las que son de dos o tres columnas no necesitan ese mínimo. */
  .card table.estrecha { min-width: 0; }
}
/* Las etiquetas de una celda van en línea. Apiladas, una fila con tres
   etiquetas ocupa lo mismo que tres filas y la tabla se vuelve una escalera:
   se lee mejor deslizando de lado. */
td.chips { white-space: nowrap; }

/* ---------------------------------------------------------------------------
   LECTURA RÁPIDA EN EL DIRECTO

   Durante el evento esta pantalla se mira de reojo y desde lejos. Un importe
   suelto obliga a compararlo mentalmente con los demás; con el reparto y la
   barra detrás, se ve de un vistazo si esta noche se está cobrando con tarjeta
   o en efectivo, y qué barra va destacada.
--------------------------------------------------------------------------- */
.reparto { font-size: 12px; font-weight: 600; color: var(--muted); margin-top: 2px; }
.reparto.efectivo { color: var(--ok); }
.reparto.tarjeta { color: var(--brand-ink); }

/* Mientras llega el repintado de un toque (cambiar de día, de pestaña): la
   pantalla se atenúa y no acepta más toques. La respuesta inmediata es lo
   que evita el triple toque de quien cree que el panel no le hace caso. */
.cargando-suave { opacity: .55; pointer-events: none; transition: opacity .15s; }
.reparto.nfc { color: var(--nfc); }

.barra-fila { padding: 9px 0; border-bottom: 1px solid var(--line-soft); }
.barra-fila:last-child { border-bottom: none; }
.barra-texto { display: flex; justify-content: space-between; align-items: baseline; gap: 12px; font-size: 13.5px; }
.barra-texto b { font-variant-numeric: tabular-nums; white-space: nowrap; }
.barra-riel { height: 5px; border-radius: 99px; background: var(--line-soft); margin-top: 6px; overflow: hidden; }
.barra-valor { height: 100%; border-radius: 99px; background: var(--brand); }

/* El botón de una cabecera se queda a la derecha aunque el título haga dos
   líneas. Con `flex-wrap` a secas caía al principio de la línea siguiente y
   parecía suelto en medio de la pantalla, sin relación con nada. */
.section-head { align-items: flex-start; }
.section-head h2 { flex: 1 1 auto; min-width: 0; }
.section-head > :last-child:not(h1):not(h2):not(h3) { margin-left: auto; flex: none; }

/* Bloques uno debajo de otro, cada uno con todo el ancho.
   Es lo que necesita cualquier tabla que lleve botones al final: en dos
   columnas la fila se parte y lo primero que se pierde es justo la acción. */
.apiladas { display: grid; grid-template-columns: 1fr; gap: 16px; }

/* Y para el resto: dos columnas solo cuando de verdad caben dos tablas.
   Con 430 px de mínimo se partían en cuanto había seis columnas y un par de
   botones; el resultado era peor que una sola columna, porque las dos mitades
   quedaban cortadas a la vez. */
.cols-2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 620px), 1fr)); }

/* Cabecera de una ficha: de dónde vienes y dónde estás, en la misma línea. */
.cabecera-ficha {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-bottom: 16px;
}
.cabecera-ficha h1 { font-size: 20px; }
.cabecera-ficha .chip { margin-right: 0; }

/* Varios botones en la cabecera de una tarjeta, sin que se separen. */
.acciones-cab { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; }

@media (max-width: 640px) {
  /* Los botones de la cabecera comparten fila en vez de ocupar una cada uno:
     dos botones a ancho completo empujan la tabla fuera de la primera pantalla
     y obligan a hacer scroll para ver el primer dato. */
  .section-head .acciones-cab { display: flex; gap: 8px; }
  .section-head .acciones-cab button { width: auto; flex: 1; }
}

/* Listas largas con scroll propio y cabecera fija.
   Cien filas seguidas son casi seis mil píxeles: para volver a los filtros o
   al total había que recorrer la lista entera hacia arriba. Así la pantalla
   cabe de una vez y se recorre solo lo que hay que recorrer. */
.tabla-larga { max-height: 62dvh; overflow-y: auto; }
.tabla-larga thead th {
  position: sticky; top: 0; z-index: 1;
  background: var(--card); box-shadow: 0 1px 0 var(--line);
}

/* Un poco menos de aire lateral en las celdas: son veinte píxeles por tabla,
   y son justo los que separaban a "Arqueos por turno" de caber sin cortarse. */
td, th { padding-left: 8px; padding-right: 8px; }

/* ---------------------------------------------------------------------------
   NINGÚN IMPORTE SE PARTE

   Los importes grandes se pintan como "1154" + un <span> con ",00 €" más
   pequeño. Ese span es un elemento aparte, así que en cuanto la caja se
   estrecha —una columna cerrada, el navegador con zoom— el navegador lo baja
   a la línea siguiente y queda un "0" enorme con un ",00 €" suelto debajo,
   que ni siquiera se lee como una cantidad.

   Se marcan como intocables los contenedores de cifra, no solo el span: si
   solo se protege el span, lo que se parte es el hueco anterior.
--------------------------------------------------------------------------- */
.dec { white-space: nowrap; }
.cifra b,
.stat .value,
.event-card .total,
.vivo-cabecera .total,
.total,
.kv b,
.barra-texto b,
td.num, th.num {
  white-space: nowrap;
}
/* Y si aun así no cabe, que encoja la letra antes que partirse en dos filas. */
.cifra b, .stat .value, .vivo-cabecera .total { font-size: clamp(20px, 4.6vw, 27px); }

/* ---------- entradas y accesos ---------- */
/*
 * El buscador manda y por eso ocupa el sitio que le sobra a los desplegables:
 * con seis mil entradas nadie navega, se busca por el nombre que le están
 * diciendo en la puerta.
 */
.filtros {
  display: flex; gap: 10px; margin-bottom: 16px; flex-wrap: wrap;
}
.filtros .buscador { flex: 1 1 260px; min-width: 200px; }
/* Los campos del panel son `width: 100%` por defecto, que es lo que se quiere
   dentro de un formulario. Aquí no: si el desplegable se lleva el ancho entero,
   los tres filtros caen uno debajo de otro y se comen media pantalla antes de
   llegar a la primera entrada. */
.filtros select { flex: 0 1 auto; width: auto; min-width: 170px; }

.paginacion {
  display: flex; align-items: center; justify-content: center; gap: 16px;
  padding-top: 14px; margin-top: 4px; border-top: 1px solid var(--line-soft);
}

/* Elegir varios de una lista corta. Un desplegable múltiple es incómodo con el
   ratón y directamente inservible con el dedo. */
.chips-edit {
  display: flex; flex-wrap: wrap; gap: 8px; margin-top: 6px;
}
.chip-check {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 7px 12px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--card); font-size: 13px; cursor: pointer;
  user-select: none;
}
.chip-check:has(input:checked) {
  border-color: var(--ink); background: var(--line-soft); font-weight: 600;
}
.chip-check input { margin: 0; accent-color: var(--ink); }

.chip.muted { background: var(--line-soft); color: var(--muted); }

.aviso-error {
  padding: 10px 14px; border-radius: 10px; margin: 12px 0;
  background: var(--bad-bg); color: var(--bad); font-size: 13.5px;
}
.previa { margin-top: 16px; }
.previa table { margin-top: 8px; }
.cifras.compactas { margin-bottom: 14px; }
.cifras.compactas .cifra { padding: 12px 14px; }
.cifras.compactas .cifra b { font-size: 26px; }

td.num.neg, b.neg { color: var(--bad); }
.muted.sub { font-size: 12px; font-weight: 400; }

/* Una sección sin nada dentro no enseña tablas vacías: enseña cómo llenarla.
   Es el estado en el que empieza todo evento nuevo, así que es tan parte del
   diseño como la pantalla llena. */
.card.vacio { text-align: center; padding: 46px 28px; }
.card.vacio h2 { margin-bottom: 10px; }
.card.vacio p { max-width: 560px; margin: 0 auto 10px; }
.acciones-vacio {
  display: flex; gap: 10px; justify-content: center; flex-wrap: wrap; margin-top: 22px;
}
.pie-nota {
  margin-top: 14px; padding: 12px 16px; border-radius: var(--radius);
  background: var(--line-soft); color: var(--muted); font-size: 13px;
}
.cifra .sub { display: block; color: var(--muted); font-size: 11.5px; margin-top: 2px; }

/* ---------------------------------------------------------------------------
   INCIDENCIAS
   Lo vivo llama y lo atendido descansa: la tarjeta pendiente lleva su borde
   ámbar (o rojo si es un corte de red), y la resuelta se apaga sin borrarse,
   que la noche se reconstruye leyendo también lo que ya pasó.
--------------------------------------------------------------------------- */
.cards-col { display: grid; gap: 10px; max-width: 720px; }
.incidencia { border-left: 4px solid var(--warn); }
.incidencia.corte { border-left-color: var(--bad); }
.incidencia.resuelta { border-left-color: var(--line); opacity: .65; }
.inc-cab { display: flex; justify-content: space-between; gap: 10px; flex-wrap: wrap; align-items: baseline; }
.inc-texto { margin: 8px 0; font-size: 15px; }
.chip.warn { background: var(--bad-bg); color: var(--bad); font-weight: 700; }
.inc-resolver {
  background: var(--ok-bg); color: var(--ok); border: 1px solid transparent;
  padding: 8px 14px; border-radius: 9px; font-weight: 600;
}
.inc-resolver:hover { border-color: var(--ok); }
/* Parece un enlace pero se toca como un botón: 36 px de zona, que esto se usa
   también desde una tablet con el evento en marcha. */
.linklike {
  background: none; border: none; color: var(--brand-ink); font-weight: 600;
  min-height: 36px; padding: 0 10px; display: inline-flex; align-items: center;
}

/* --- Cobros: explicaciones y causas de los turnos que no cuadran --- */
.explica {
  margin: 0 0 12px; padding: 10px 14px; border-radius: 10px;
  background: var(--warn-bg); border: 1px solid #ecd9a0;
  font-size: 13.5px; line-height: 1.5; color: var(--ink, inherit);
}
.explica b { font-weight: 700; }
details.turno-desc {
  border: 1px solid var(--line); border-radius: 10px; margin-bottom: 8px; background: var(--card);
}
details.turno-desc > summary {
  cursor: pointer; padding: 10px 14px; display: flex; justify-content: space-between;
  gap: 12px; align-items: center; flex-wrap: wrap; font-size: 14px; list-style: none;
}
details.turno-desc > summary::-webkit-details-marker { display: none; }
details.turno-desc > summary::before { content: '▸'; color: var(--muted); margin-right: 6px; }
details.turno-desc[open] > summary::before { content: '▾'; }
.turno-causas { padding: 0 14px 10px; display: flex; flex-direction: column; gap: 8px; }
.causa {
  display: grid; grid-template-columns: minmax(220px, 1fr) 1.4fr; gap: 12px;
  padding: 10px 12px; border-radius: 8px; background: var(--bg, #f6f7f9); font-size: 13.5px; line-height: 1.45;
}
.causa .que-hacer { color: var(--muted); }
.causa .que-hacer b { color: inherit; }
.causa .acciones { margin-top: 6px; display: flex; gap: 6px; flex-wrap: wrap; }
@media (max-width: 720px) { .causa { grid-template-columns: 1fr; } }
.chips-dia { display: flex; gap: 6px; flex-wrap: wrap; margin: 0 0 10px; align-items: center; }
.chips-dia button.activo { background: var(--ink, #14181d); color: #fff; }

/* ---------- pulseras y tarjetas NFC ---------- */
.tramos { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin-top: 10px; }
.tramo { padding: 10px 12px; border: 1px solid var(--line-soft); border-radius: 10px; }
.tramo-n { font-size: 22px; font-weight: 700; font-variant-numeric: tabular-nums; margin: 2px 0; }
.ficha-pulsera { margin-bottom: 8px; }
.pf-datos { margin-top: 10px; }
.modal .ops-list { max-height: 45vh; overflow-y: auto; }
.chip.regalo { background: var(--warn-bg); color: var(--warn); }
.ops-list { display: flex; flex-direction: column; }
.op-row {
  display: flex; justify-content: space-between; align-items: flex-start; gap: 12px;
  padding: 8px 0; border-bottom: 1px solid var(--line-soft); font-size: 13.5px;
}
.op-row:last-child { border-bottom: none; }
.op-amt { text-align: right; font-weight: 700; font-variant-numeric: tabular-nums; white-space: nowrap; }
.op-amt.pos { color: var(--ok); }
.op-amt.neg { color: var(--bad); }
.op-amt .muted { font-weight: 400; display: block; font-size: 12px; }

/* --- ficha de una pulsera --- */
.modal.ficha-pulsera-modal { max-width: 560px; }
.pf-cab { display: flex; justify-content: space-between; align-items: flex-start; gap: 16px; padding-bottom: 14px; border-bottom: 1px solid var(--line-soft); }
.pf-cab .badge, .pf-cab .chip { vertical-align: middle; }
.pf-uid { font-size: 20px; letter-spacing: .06em; margin: 2px 0 6px; }
.pf-saldo { text-align: right; }
.pf-saldo .total { font-size: 30px; font-weight: 800; font-variant-numeric: tabular-nums; line-height: 1.1; }
.pf-saldo .total .dec { font-size: 16px; font-weight: 600; color: var(--muted); }
.pf-datos-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 10px 16px; padding: 12px 0; }
.pf-datos-grid > div { display: flex; flex-direction: column; gap: 2px; font-size: 13.5px; }
.pf-datos-grid .muted { font-size: 12px; }
.pf-bloque { padding: 12px 0; border-top: 1px solid var(--line-soft); }
.pf-bloque-cab { margin-bottom: 8px; font-size: 14px; }
.pf-bloque-cab .muted { font-size: 12.5px; }
.pf-dos { display: flex; gap: 8px; align-items: center; }
.pf-dos input { flex: 1 1 120px; min-width: 0; margin: 0; }
.pf-dos button { flex: none; white-space: nowrap; }
.pf-peligro { border-top: 1px dashed var(--line); }
.movs { max-height: 42vh; overflow-y: auto; }
.mov { display: grid; grid-template-columns: 26px 1fr auto; gap: 10px; align-items: start; padding: 9px 0; border-bottom: 1px solid var(--line-soft); }
.mov:last-child { border-bottom: none; }
.mov-ico { width: 24px; height: 24px; border-radius: 50%; display: grid; place-items: center; font-weight: 800; font-size: 14px; margin-top: 1px; }
.mov.pos .mov-ico { background: var(--ok-bg); color: var(--ok); }
.mov.neg .mov-ico { background: var(--bad-bg); color: var(--bad); }
.mov-titulo { font-weight: 600; font-size: 13.5px; display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.mov-meta { color: var(--muted); font-size: 12px; margin-top: 1px; }
.mov-nota { font-size: 12.5px; margin-top: 2px; }
.mov-imp { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.mov-imp b { display: block; font-size: 14px; }
.mov.pos .mov-imp b { color: var(--ok); }
.mov.neg .mov-imp b { color: var(--bad); }
.mov-imp span { font-size: 11.5px; color: var(--muted); }
@media (max-width: 560px) {
  .pf-cab { flex-direction: column; }
  .pf-saldo { text-align: left; }
  .pf-dos { flex-wrap: wrap; }
  .pf-dos button { flex: 1 1 100%; }
}

/* ---------- avisos: la franja de «lo que hay que mirar ahora» ---------- */
.avisos {
  margin: -8px 0 18px; border-radius: 14px; border: 1px solid var(--line);
  background: var(--card); box-shadow: var(--shadow-sm); overflow: hidden;
}
.avisos.oculto { display: none; }
.avisos.rojo  { border-color: #efb9c1; background: var(--bad-bg); }
.avisos.ambar { border-color: #f1d9a3; background: var(--warn-bg); }
.avisos.vacio { background: var(--card); }
.avisos-cab {
  display: flex; align-items: center; gap: 10px; padding: 9px 14px; font-size: 13.5px;
  cursor: pointer; user-select: none; flex-wrap: wrap;
}
.avisos.vacio .avisos-cab { cursor: default; padding: 7px 14px; }
.avisos-ok { color: var(--ok); font-weight: 700; }
.avisos-resumen { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; flex: 1 1 200px; }
.avisos-der { margin-left: auto; display: inline-flex; align-items: center; gap: 10px; white-space: nowrap; }
.avisos .chevron { color: var(--muted); font-size: 12px; }
button.enlace {
  background: none; border: none; box-shadow: none; padding: 5px 6px; min-height: 30px; font: inherit; font-size: 12.5px;
  color: var(--brand-ink, var(--brand)); cursor: pointer; text-decoration: underline; text-underline-offset: 3px;
}
button.enlace:hover { background: none; }
.pill {
  display: inline-block; min-width: 20px; text-align: center; padding: 1px 8px; border-radius: 99px;
  font-size: 11px; font-weight: 800; letter-spacing: .02em; line-height: 18px;
}
.pill.rojo  { background: var(--bad); color: #fff; }
.pill.ambar { background: var(--warn); color: #fff; }
.avisos-lista { border-top: 1px solid rgba(0,0,0,.06); background: var(--card); }
.aviso {
  display: grid; grid-template-columns: auto 1fr auto; gap: 12px; align-items: start;
  padding: 10px 14px; border-bottom: 1px solid var(--line-soft); font-size: 13.5px;
}
.aviso:last-child { border-bottom: none; }
.aviso .pill { margin-top: 2px; }
.aviso .pill.rojo  { background: var(--bad-bg); color: var(--bad); }
.aviso .pill.ambar { background: var(--warn-bg); color: var(--warn); }
.aviso-txt { min-width: 0; }
.aviso-txt b { display: block; }
.aviso-txt .muted { font-size: 12.5px; margin-top: 2px; line-height: 1.4; }
.aviso-acc { display: flex; gap: 6px; white-space: nowrap; }
@media (max-width: 720px) {
  .aviso { grid-template-columns: auto 1fr; }
  .aviso-acc { grid-column: 2; flex-wrap: wrap; }
  .avisos-resumen { display: none; }
}

/* ---------- cierre de jornada: la hoja ---------- */
.cierre { max-width: none; }
.cierre-acciones { display: flex; gap: 8px; align-items: center; flex-wrap: wrap; margin-bottom: 14px; }
.hoja { background: var(--card); border: 1px solid var(--line); border-radius: 14px; padding: 18px 20px; margin-bottom: 14px; box-shadow: var(--shadow-sm); }
.hoja h2 { font-size: 16px; margin: 0 0 12px; padding-bottom: 8px; border-bottom: 1px solid var(--line-soft); }
.hoja h3 { font-size: 13.5px; margin: 16px 0 6px; }
.hoja table { width: 100%; }
.hoja table.compacta td, .hoja table.compacta th { padding: 5px 8px; font-size: 12.5px; }
.hoja tr.total td { font-weight: 700; border-top: 2px solid var(--line); background: var(--bg, #f7f8fa); }
.hoja .nota { font-size: 12.5px; margin: 8px 0 0; line-height: 1.45; }
.hoja .nota.rojo { color: var(--bad); } .hoja .nota.verde { color: var(--ok); } .hoja .nota.ambar { color: var(--warn); }
.cabecera { display: flex; justify-content: space-between; gap: 20px; align-items: flex-start; }
.cabecera h1 { font-size: 24px; margin: 2px 0 4px; }
.cierre-sub { font-size: 13.5px; color: var(--muted); }
.cierre-meta { text-align: right; font-size: 12.5px; color: var(--muted); line-height: 1.6; }
.cierre-meta .rojo { color: var(--bad); } .cierre-meta .verde { color: var(--ok); }
.aviso-hoja { background: var(--warn-bg); border-color: #f1d9a3; font-size: 13.5px; }
.kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 10px; }
.kpis-4 { grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); }
.kpi { border: 1px solid var(--line-soft); border-radius: 10px; padding: 10px 12px; }
.kpi .k { font-size: 12px; color: var(--muted); font-weight: 500; }
.kpi .v { font-size: 22px; font-weight: 800; margin: 2px 0; font-variant-numeric: tabular-nums; }
.kpi .v .dec { font-size: 13px; font-weight: 600; color: var(--muted); }
.kpi .s { font-size: 11.5px; color: var(--muted); line-height: 1.4; }
.kpi.mal { background: var(--bad-bg); border-color: #efb9c1; } .kpi.mal .v { color: var(--bad); }
.kpi.avisa { background: var(--warn-bg); border-color: #f1d9a3; }
.delta { font-weight: 600; } .delta.pos { color: var(--ok); } .delta.neg { color: var(--bad); }
.dos-col { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; align-items: start; }
.lista-avisos { margin: 4px 0 0; padding-left: 18px; font-size: 13px; line-height: 1.6; }
.lista-avisos li.rojo b { color: var(--bad); } .lista-avisos li.ambar b { color: var(--warn); }
.firmas .obs .caja-obs { border: 1px solid var(--line); border-radius: 8px; height: 70px; margin: 4px 0 16px; }
.firmas-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; font-size: 12.5px; color: var(--muted); text-align: center; margin-bottom: 14px; }
.firmas-grid .linea { height: 48px; border-bottom: 1px solid var(--ink); margin-bottom: 6px; }
@media (max-width: 800px) { .dos-col { grid-template-columns: 1fr; } .cabecera { flex-direction: column; } .cierre-meta { text-align: left; } .firmas-grid { grid-template-columns: 1fr; } }

.solo-print { display: none; }
/* En pantalla, la tabla envolvente del cierre no es tabla: es transparente. */
.print-wrap, .print-wrap > thead, .print-wrap > tbody, .print-wrap > tfoot, .print-wrap > * > tr, .print-wrap > * > tr > td { display: block; padding: 0; border: 0; width: 100%; }
/* Es un td: sin esto hereda el `td:last-child { white-space: nowrap }` de las tablas y nada envuelve. */
.print-wrap > * > tr > td { white-space: normal !important; text-align: left; }
.print-wrap > thead, .print-wrap > tfoot { display: none; }
.cierre-marca { display: flex; align-items: center; gap: 10px; }
.cierre-marca img { height: 22px; }
@media print {
  /* Sin margen de página: así el navegador no pinta su cabecera y pie (la
     URL y la fecha). El margen lo pone el cuerpo, y la cabecera y el pie son
     nuestros: fijos, se repiten en cada hoja. */
  @page { size: A4 portrait; margin: 0; }
  html, body { background: #fff !important; font-size: 11px; }
  body { padding: 0 12mm; }
  #app { padding: 0 !important; }
  /* La tabla envolvente vuelve a ser tabla: su thead y tfoot se repiten en
     cada hoja y reservan el hueco de la cabecera y el pie fijos. */
  .print-wrap { display: table; width: 186mm; max-width: 186mm; table-layout: fixed; border-collapse: collapse; }
  .print-wrap > tbody > tr > td { width: 186mm; max-width: 186mm; }
  .cierre { width: 186mm; max-width: 186mm; }
  .hoja { max-width: 100%; }
  .dos-col > * { min-width: 0; }
  .firmas-grid { grid-template-columns: repeat(3, minmax(0, 1fr)) !important; }
  .cabecera { flex-direction: row !important; } .cierre-meta { text-align: right !important; }
  .kpis, .kpis-4 { grid-template-columns: repeat(4, minmax(0, 1fr)) !important; }
  .kpi { min-width: 0; }
  .print-wrap > thead { display: table-header-group; }
  .print-wrap > tfoot { display: table-footer-group; }
  .print-wrap > tbody { display: table-row-group; }
  .print-wrap > * > tr { display: table-row; }
  .print-wrap > * > tr > td { display: table-cell; padding: 0; }
  .print-hueco-cab { height: 16mm; }
  .print-hueco-pie { height: 12mm; }
  .solo-print { display: flex; }
  .print-cab {
    position: fixed; top: 0; left: 0; right: 0; height: 12mm; padding: 0 12mm;
    align-items: center; justify-content: space-between; gap: 12px;
    font-size: 10px; color: #555; border-bottom: 1px solid #ddd; background: #fff;
  }
  .print-cab img { height: 16px; }
  .print-pie {
    position: fixed; bottom: 0; left: 0; right: 0; height: 9mm; padding: 0 12mm;
    align-items: center; justify-content: center; font-size: 9px; color: #777;
    border-top: 1px solid #eee; background: #fff;
  }
  .topbar, .menu-ev, .avisos, .jornadas-tabs, .no-print, #toast { display: none !important; }
  .ev-cuerpo, .cierre { max-width: none; }
  .hoja { box-shadow: none; border-color: #ccc; margin-bottom: 8px; padding: 10px 12px; break-inside: auto; }
  .hoja.cabecera, .hoja.firmas, .kpi, .hoja tr, .aviso-hoja { break-inside: avoid; page-break-inside: avoid; }
  .hoja h2, .hoja h3, .hoja thead { break-after: avoid; page-break-after: avoid; }
  .hoja h3 { break-before: auto; }
  .hoja p, .hoja .nota { orphans: 3; widows: 3; }
  .hoja > table, .hoja .dos-col > table { break-before: avoid; }
  .firmas { break-before: auto; }
  .hoja h2 { font-size: 13px; }
  .hoja table { width: 100%; table-layout: auto; font-size: 9.5px; }
  .hoja table td, .hoja table th { padding: 2px 4px !important; font-size: 9.5px !important; white-space: normal !important; }
  .hoja .badge, .hoja .chip { font-size: 8.5px; padding: 0 5px; }
  .hoja thead { display: table-header-group; }
  .hoja { overflow: visible; }
  .dos-col { grid-template-columns: 1fr 1fr; }
  .kpi .v { font-size: 16px; }
  .fila-mal, .fila-avisa, .kpi.mal, .kpi.avisa, tr.total td { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  a { text-decoration: none; color: inherit; }
}

/* --- ficha de pulsera, versión con casillas --- */
.pf-cab { align-items: flex-start; }
.pf-badges { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.pf-tiles { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 10px; padding: 14px 0 6px; }
.pf-tile { border-radius: 12px; padding: 10px 12px; border: 1px solid var(--line-soft); }
.pf-tile-k { font-size: 12px; font-weight: 600; display: flex; align-items: center; gap: 6px; }
.pf-tile-k svg { width: 14px; height: 14px; }
.pf-tile-v { font-size: 22px; font-weight: 800; font-variant-numeric: tabular-nums; margin: 2px 0; }
.pf-tile-s { font-size: 11.5px; color: var(--muted); line-height: 1.5; }
.pf-tile.dinero { background: var(--ok-bg); border-color: #bfe6cc; } .pf-tile.dinero .pf-tile-k { color: var(--ok); }
.pf-tile.producto { background: var(--nfc-bg); border-color: #d6cdff; } .pf-tile.producto .pf-tile-k { color: var(--nfc); }
.pf-tile.total { background: var(--card); border-color: var(--line); } .pf-tile.total .pf-tile-k { color: var(--muted); }
.pf-prod { display: inline-block; background: rgba(255,255,255,.7); border-radius: 6px; padding: 1px 6px; margin: 2px 2px 0 0; color: var(--ink); }
.pf-leyenda { margin-left: auto; display: inline-flex; gap: 6px; }
.pf-bloque-cab { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.mov-tipo { font-size: 10px; font-weight: 700; letter-spacing: .04em; text-transform: uppercase; padding: 1px 6px; border-radius: 5px; }
.mov-tipo.dinero { background: var(--ok-bg); color: var(--ok); }
.mov-tipo.producto { background: var(--nfc-bg); color: var(--nfc); }
.mov-dia { font-size: 11.5px; font-weight: 700; color: var(--muted); text-transform: uppercase; letter-spacing: .04em; padding: 10px 0 2px; border-bottom: 1px solid var(--line-soft); }
.mov-ico svg { width: 13px; height: 13px; }
.mov.producto .mov-ico { background: var(--nfc-bg); color: var(--nfc); }
.mov.producto.pos .mov-imp b { color: var(--nfc); }
.mov.producto.neg .mov-imp b { color: var(--nfc); }
.pf-det { border-top: 1px solid var(--line-soft); padding: 10px 0; }
.pf-det summary { cursor: pointer; font-size: 13.5px; list-style: none; display: flex; gap: 6px; align-items: baseline; }
.pf-det summary::-webkit-details-marker { display: none; }
.pf-det summary::before { content: '▸'; color: var(--muted); font-size: 12px; margin-right: 2px; }
.pf-det[open] summary::before { content: '▾'; }
.pf-det .pf-dos { margin-top: 10px; }
.pf-det.peligro { border-top-style: dashed; }
@media (max-width: 560px) { .pf-tiles { grid-template-columns: 1fr; } }
.stat.stat-mal { background: var(--bad-bg); border-color: #efb9c1; } .stat.stat-mal .value { color: var(--bad); }
.stat.stat-avisa { background: var(--warn-bg); border-color: #f1d9a3; }
.inc-detalle td { background: var(--bg, #f7f8fa); }
.chip.warn { background: var(--warn-bg); color: var(--warn); }
.modal textarea { width: 100%; font: inherit; padding: 9px 11px; border: 1px solid var(--line); border-radius: 9px; resize: vertical; }
.pf-det summary b { white-space: nowrap; }

/* ---------- el panel en un móvil (iPhone y similares), segunda pasada ---------- */
@media (max-width: 640px) {
  /* Cabecera del evento en dos filas: el nombre arriba; debajo, volver,
     estado y código a la izquierda y los botones a la derecha. */
  .topbar { flex-wrap: wrap; align-items: center; gap: 8px; }
  /* El grupo de la izquierda se disuelve: así el título ocupa su fila y
     «volver», el estado y los botones de la derecha comparten la siguiente. */
  .topbar .tb-izq { display: contents; }
  .topbar .tb-izq h1 { font-size: 18px; width: 100%; order: -1; margin-bottom: 2px; }
  .topbar .tb-der { width: auto; margin-left: auto; gap: 6px; }
  .topbar .tb-der button { padding: 8px 10px; font-size: 13px; }
  .topbar .volver { padding: 7px 10px; }
  .topbar .codigo-tpv { display: none; }   /* el código ya sale en Editar evento; aquí no cabe */

  /* Las hojas del cierre se deslizan como las tarjetas. */
  .hoja { overflow-x: auto; -webkit-overflow-scrolling: touch; padding: 14px; }
  .hoja table { min-width: 560px; }
  .hoja table.estrecha { min-width: 0; }
  .kpis, .kpis-4 { grid-template-columns: 1fr 1fr; }
  .cierre-acciones button { flex: 1 1 auto; }
  .cierre-acciones .muted { display: none; }

  /* Avisos: pastillas y botones que quepan con el dedo. */
  .avisos-cab { padding: 9px 12px; }
  .aviso { grid-template-columns: auto 1fr; padding: 10px 12px; }
  .aviso-acc { grid-column: 1 / -1; flex-wrap: wrap; }
  .aviso-acc button { flex: 1 1 auto; }

  /* Pulseras: filtros en columna y ficha a pantalla completa. */
  .filtros .buscador { flex: 1 1 100%; }
  .filtros select { flex: 1 1 100%; }
  .pf-tiles { grid-template-columns: 1fr; }
  .modal.ficha-pulsera-modal { max-width: none; }
  .tramos { grid-template-columns: 1fr 1fr; }

  /* Incidencias: los chips de tipo en dos filas y el botón de apuntar debajo. */
  .filtros .tabs { flex-wrap: wrap; }
  .stats .stat .value { font-size: 22px; }

  /* Las tablas del directo y de existencias, con scroll propio. */
  .vivo-cols { grid-template-columns: 1fr; }
  .dos-col { grid-template-columns: 1fr; }
  .firmas-grid { grid-template-columns: 1fr; }
  .print-wrap > * > tr > td { display: block; }
}

/* --- aforo en Entradas --- */
.aforo-card { padding: 12px 16px; }
.aforo-card.casi { background: var(--warn-bg); border-color: #f1d9a3; }
.aforo-card.lleno { background: var(--bad-bg); border-color: #efb9c1; }
.aforo-cab { display: flex; gap: 12px; align-items: baseline; flex-wrap: wrap; font-size: 14px; margin-bottom: 8px; }
.aforo-riel { position: relative; height: 10px; border-radius: 99px; background: var(--line-soft); overflow: hidden; }
.aforo-valor { height: 100%; border-radius: 99px; background: var(--ok); transition: width .3s; }
.aforo-card.casi .aforo-valor { background: var(--warn); }
.aforo-card.lleno .aforo-valor { background: var(--bad); }
.aforo-marca { position: absolute; top: 0; bottom: 0; width: 2px; background: rgba(0,0,0,.35); }

/* La firma del recibí en miniatura: sobre blanco siempre, que el trazo se vea
   también con el tema del sistema en oscuro. */
.firma-mini { height: 28px; background: #fff; border: 1px solid var(--line); border-radius: 4px; vertical-align: middle; }
