/* Control de asistencia. Dos pestañas, nada más.
   Se usa en notebook, tablet y teléfono: todo se apila bajo 760px y los blancos
   de toque no bajan de 44px, que es el mínimo con el que se acierta de pie. */

body { background: var(--paper); }
.mono { font-family: var(--font-mono); }
.hint { font-size: 0.78rem; color: var(--text-mute); }
.sub { color: var(--text-soft); margin: 0.5rem 0 1.4rem; font-size: 0.92rem; line-height: 1.5; }

/* El eyebrow en mono y versalitas es lo que marca el tono del sistema: cada
   bloque se anuncia con una etiqueta técnica antes del titular. */
.eyebrow {
  font: 500 0.68rem/1 var(--font-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--text-mute);
  margin: 0 0 0.55rem;
}
.msg { font-size: 0.85rem; min-height: 1.3rem; margin: 0.8rem 0 0; font-weight: 500; }

/* Punto vivo. Se usa en la barra superior y en la cabecera del lector. */
.dot { width: 7px; height: 7px; border-radius: 50%; background: var(--live); display: inline-block; flex: none; }
.pulse { animation: pulse 1.6s ease-in-out infinite; }
@keyframes pulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50% { opacity: 0.55; transform: scale(1.15); }
}

/* ---------- puerta ---------- */

.gate {
  position: fixed; inset: 0; z-index: 80;
  display: grid; place-items: center;
  padding: 1.5rem;
  background: rgba(15, 13, 24, 0.94);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
}
.gate-card {
  width: min(460px, 100%);
  background: var(--paper-2);
  border-radius: var(--r-lg);
  padding: clamp(1.8rem, 5vw, 2.4rem);
  box-shadow: var(--shadow-modal);
  animation: modal-in 0.28s cubic-bezier(0.2, 0.9, 0.3, 1.1) both;
}
.gate-logo { height: 26px; width: auto; display: block; margin-bottom: 1.4rem; }
.gate-card h1 { font-size: clamp(1.7rem, 5vw, 2.1rem); margin-bottom: 0.2rem; }
.gate-card .btn { width: 100%; }
.check {
  display: flex; align-items: center; gap: 0.55rem;
  font-size: 0.85rem; color: var(--text-soft); margin: 0 0 1.2rem;
}
.check input { width: auto; accent-color: var(--brand); }

/* ---------- barra superior ---------- */

.top {
  position: sticky; top: 0; z-index: 20;
  background: var(--paper);
  border-bottom: 1px solid var(--line);
  display: flex; align-items: center; gap: 1rem;
  padding: 0.85rem clamp(0.9rem, 3vw, 2.5rem);
  flex-wrap: wrap;
}
.brand { display: flex; align-items: center; gap: 0.85rem; margin-right: auto; min-width: 0; }
.brand-logo { height: 28px; width: auto; display: block; flex: none; }
.brand-div { width: 1px; height: 22px; background: rgba(26, 26, 26, 0.15); flex: none; }
.brand-txt { min-width: 0; }
.brand-name {
  display: block; font-family: var(--font-display); font-weight: 700;
  font-size: 0.92rem; letter-spacing: -0.01em; color: var(--text-soft);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
/* El punto magenta del logotipo de producto: el único adorno de la barra. */
.brand-name::after { content: '.'; color: var(--accent); }
.brand-sub {
  display: block; font: 500 0.66rem/1.4 var(--font-mono);
  color: var(--text-mute); letter-spacing: 0.04em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.top-acc { display: flex; align-items: center; gap: 0.7rem; }
.live {
  display: inline-flex; align-items: center; gap: 0.5rem;
  padding: 0.5rem 0.9rem; border: 1px solid var(--ink-900); border-radius: var(--r-pill);
  font: 700 0.7rem/1 var(--font-mono); letter-spacing: 0.04em; white-space: nowrap;
}

.tabs { display: flex; gap: 0.2rem; }
.tab {
  appearance: none; border: 0; background: none; cursor: pointer;
  padding: 0.6rem 1.1rem; color: var(--text-soft); font-weight: 700; font-size: 0.9rem;
  border-bottom: 2px solid transparent; margin-bottom: -0.9rem;
}
.tab:hover { color: var(--text); }
.tab[aria-selected="true"] { color: var(--text); border-bottom-color: var(--brand); }

.mini {
  appearance: none; cursor: pointer; font-size: 0.82rem; font-weight: 600;
  padding: 0.55rem 1rem; min-height: 44px;
  border: 1.5px solid var(--line-2); border-radius: 12px;
  background: var(--paper-2); color: var(--text-soft);
}
.mini:hover { background: var(--ink-900); color: var(--paper); border-color: var(--ink-900); }
.mini[aria-pressed="true"] { background: var(--ink-900); color: var(--paper); border-color: var(--ink-900); }

.panel { width: min(1280px, 100% - clamp(1.6rem, 6vw, 5rem)); margin: 0 auto; padding: 1.6rem 0 4rem; }
.notice { margin: 1rem auto; width: min(1280px, 100% - 2rem); }

/* ---------- encabezado de sección ---------- */

/* El halo morado detrás del titular. Es el mismo recurso en las dos pestañas y
   lo que evita que el papel se lea plano. */
.hero { position: relative; margin-bottom: 1.4rem; }
.hero::before {
  content: ''; position: absolute; top: -160px; left: -180px;
  width: 420px; height: 420px; pointer-events: none; filter: blur(20px); opacity: 0.07;
  background: radial-gradient(circle at 30% 30%, var(--brand) 0%, var(--brand) 35%, rgba(76, 31, 181, 0) 70%);
}
.hero-row {
  position: relative; display: flex; justify-content: space-between;
  align-items: flex-end; gap: 1.2rem; flex-wrap: wrap;
}
.hero h1 { font-size: clamp(1.7rem, 4vw, 2.15rem); }
.hero-note {
  font-size: 0.8rem; line-height: 1.45; color: var(--text-soft);
  max-width: 22rem; text-align: right;
}

.sec-head {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; margin: 1.8rem 0 0.8rem; flex-wrap: wrap;
}
.sec-head h2 { font-size: 1.05rem; letter-spacing: -0.02em; }
.sec-acc { display: flex; align-items: center; gap: 0.8rem; }

/* ---------- dashboard ---------- */

.kpis { display: grid; gap: 0.7rem; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); }
.kpi {
  background: var(--paper-2); border: 1px solid var(--line);
  border-radius: var(--r-md); padding: 1.1rem 1.2rem; box-shadow: var(--shadow-card);
}
.kpi b {
  display: block; font-family: var(--font-display);
  font-size: clamp(1.9rem, 5vw, 2.3rem); font-weight: 800;
  letter-spacing: -0.02em; line-height: 1;
}
.kpi span {
  display: block; margin-top: 0.45rem;
  font: 500 0.64rem/1.3 var(--font-mono);
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-mute);
}
.kpi.ok b { color: var(--sage); }
.kpi.warn b { color: var(--brand); }

/* ---------- filtros del dashboard ---------- */

.filtros { display: flex; gap: 0.4rem; flex-wrap: wrap; margin-bottom: 0.9rem; }
.filtro {
  appearance: none; cursor: pointer; font-size: 0.82rem; font-weight: 600;
  padding: 0.5rem 1.1rem; min-height: 44px; border-radius: var(--r-pill);
  border: 1.5px solid var(--line-2); background: var(--paper-2); color: var(--text-soft);
}
.filtro:hover { background: var(--paper-4); color: var(--text); }
.filtro[aria-pressed="true"] { background: var(--ink-900); color: var(--paper); border-color: var(--ink-900); }

.estado {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font: 700 0.66rem/1 var(--font-mono); letter-spacing: 0.05em;
  padding: 0.35rem 0.65rem; border-radius: var(--r-pill); white-space: nowrap;
  text-transform: uppercase;
}
.estado::before { content: ''; width: 6px; height: 6px; border-radius: 50%; background: currentColor; }
.estado.dentro { background: var(--sage-soft); color: var(--sage); }
.estado.falta { background: var(--paper); color: var(--text-mute); }

/* ---------- tablas ---------- */

.tablewrap {
  overflow-x: auto; border: 1px solid var(--line);
  border-radius: var(--r-md); background: var(--paper-2); box-shadow: var(--shadow-card);
}
table { border-collapse: collapse; width: 100%; font-size: 0.88rem; }

/* Reparto de columnas fijo, no decidido por el contenido.
 *
 * Con el reparto automático manda la celda más ancha, y aquí esa celda es el
 * nombre con su acompañante pegado al lado: «Kathia Orellana +1 María Eugenia
 * Salinas (Subgerente de RRHH) / Luis Ovalles (Analista de capacitación)». Una
 * sola fila así estira la primera columna, empuja las demás y la HORA se sale
 * por el borde derecho — justo el dato que se mira de lejos en la pantalla
 * proyectada, y justo el que no se puede ir a buscar con scroll cuando la
 * tabla está en un proyector.
 *
 * Las dos últimas columnas llevan ancho fijo porque su contenido lo tiene
 * («ingresó», «10:34», el botón); las de texto se reparten lo que queda. */
#tIngresados, #tRegistros { table-layout: fixed; }
/* Con reparto fijo el texto ya no ensancha la celda: si no cabe, se parte.
   Sin esto un correo largo se desborda por encima de la columna siguiente.
   `break-word` y no `anywhere`: el segundo parte también las palabras que sí
   caben —«Subgere/nte»— y deja el texto ilegible en una columna estrecha. */
#tIngresados td, #tRegistros td { overflow-wrap: break-word; }

/* Anchos de las columnas de contenido fijo. En rem y no en px para que encojan
   con la tipografía, y aquí y no en el HTML para que las media queries del
   teléfono puedan reducirlos. */
#tIngresados .c-estado { width: 8rem; }
#tIngresados .c-hora   { width: 6rem; }
#tRegistros  .c-acomp  { width: 5.5rem; }
#tRegistros  .c-accion { width: 11rem; }
th, td { text-align: left; padding: 0.9rem 1.1rem; border-bottom: 1px solid rgba(26, 26, 26, 0.06); }
th {
  font: 600 0.64rem/1 var(--font-mono); letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--text-mute); background: var(--paper-3);
  border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 1;
}
td { font-weight: 500; color: var(--ink-700); }
/* El nombre es lo que el operador busca de un vistazo: va en negrita y tinta. */
td:first-child { font-weight: 700; color: var(--text); }
tbody tr { transition: background 0.12s ease; }
tbody tr:hover { background: rgba(76, 31, 181, 0.04); }
tr:last-child td { border-bottom: 0; }
tbody tr.dentro td { background: rgba(26, 122, 26, 0.035); }
tbody tr.dentro:hover td { background: rgba(26, 122, 26, 0.06); }
td.num, th.num { text-align: right; font-family: var(--font-mono); font-size: 0.78rem; white-space: nowrap; }
td.acc, th.acc { text-align: right; white-space: nowrap; }
.empty { color: var(--text-mute); font-style: normal; padding: 2.4rem 1.1rem; text-align: center; font-weight: 500; }
.correo { color: var(--text-soft); font-size: 0.82rem; font-weight: 500; }
/* El RUT no se parte: un «15.234.567-\n8» es ilegible de un vistazo, que es la
   única forma en que se lee esta columna. */
td .hint { font-family: var(--font-mono); font-size: 0.7rem; font-weight: 500; white-space: nowrap; }

/* Botón de marcar: morado mientras falta, verde cuando ya entró — y ahí sirve
   para deshacer. El ancho fijo evita que la columna salte al cambiar el texto. */
.btn-marcar {
  appearance: none; cursor: pointer; min-height: 40px; min-width: 150px;
  display: inline-flex; align-items: center; justify-content: center; gap: 0.4rem;
  padding: 0.45rem 1rem; border-radius: var(--r-pill);
  border: none; background: var(--brand); color: #fff;
  font-size: 0.8rem; font-weight: 700; white-space: nowrap;
}
.btn-marcar:hover:not(:disabled) { background: var(--brand-deep); transform: translateY(-1px); }
.btn-marcar:disabled { opacity: 0.5; cursor: wait; transform: none; }
.btn-marcar.dentro {
  background: var(--sage-soft); color: var(--sage-ink);
  border: 1px solid var(--sage); font-family: var(--font-ui);
}
.btn-marcar.dentro:hover { background: #d3edd3; transform: none; }

.pill {
  font: 700 0.64rem/1 var(--font-mono); padding: 0.3rem 0.6rem;
  border-radius: var(--r-pill); background: var(--paper); color: var(--text-soft);
  letter-spacing: 0.04em; white-space: nowrap;
}
.pill.si { background: rgba(231, 60, 230, 0.12); color: var(--accent-deep); }
/* El «+1 Nombre» baja a su propia línea bajo el invitado en vez de ir pegado a
   su derecha. Al lado competía por el ancho de la columna con el nombre, y era
   lo que empujaba la tabla entera. Debajo cabe entero y se lee igual de bien. */
.pill.acomp {
  display: inline-block; margin-top: 0.3rem;
  white-space: normal; line-height: 1.35; text-align: left;
}
/* El nombre va en su propia etiqueta solo para poder esconderlo en el teléfono;
   no es una cursiva. */
.pill.acomp i { font-style: normal; }

/* ---------- buscador y lector ---------- */

/* Registros: buscador arriba, tabla abajo y a la derecha una columna fija con
   el resumen y el lector. La columna queda pegada al hacer scroll y mide lo que
   sobra de alto de pantalla, así el visor crece hasta abajo en vez de quedar un
   recuadro suelto en la esquina. */
.reg-grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  grid-template-areas:
    "toolbar cam"
    "list    cam";
  align-items: start;
}
.reg-grid .toolbar { grid-area: toolbar; }
.reg-grid .reg-list { grid-area: list; min-width: 0; }

.reg-side {
  grid-area: cam;
  width: 340px; margin-left: 1.6rem;
  position: sticky; top: 5.5rem; height: calc(100vh - 7rem);
  display: flex; flex-direction: column; gap: 0.7rem;
}
.reg-side .eyebrow { margin: 0; }

/* La columna entera —resumen, progreso y lector— existe solo mientras la cámara
   está encendida: con el lector apagado no hay nada que mirar ahí y la tabla se
   queda con todo el ancho. El único estado que se consulta es el `hidden` que
   el JS ya le pone al lector; no hace falta ninguna clase nueva. */
.reg-side:has(#scanner[hidden]) { display: none; }

.resumen { display: grid; grid-template-columns: 1fr 1fr; gap: 0.6rem; }
.caja {
  background: var(--paper-2); border: 1px solid var(--line);
  border-radius: 12px; padding: 0.9rem 1rem; box-shadow: var(--shadow-card);
}
.caja b {
  display: block; font-size: 1.75rem; font-weight: 800;
  letter-spacing: -0.02em; line-height: 1;
}
.caja span {
  display: block; margin-top: 0.4rem;
  font: 500 0.62rem/1.2 var(--font-mono);
  letter-spacing: 0.05em; text-transform: uppercase; color: var(--text-mute);
}
.caja.ok b { color: var(--sage); }
.caja.warn b { color: var(--brand); }

.progreso {
  background: var(--paper-2); border: 1px solid var(--line);
  border-radius: 12px; padding: 0.8rem 1rem; box-shadow: var(--shadow-card);
}
.progreso-head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 0.5rem; }
.progreso-head span { font-size: 0.78rem; font-weight: 700; }
.progreso-head b { font-family: var(--font-mono); font-size: 0.75rem; font-weight: 700; }
.progreso-riel { height: 8px; background: var(--paper); border-radius: 99px; overflow: hidden; }
.progreso-riel i {
  display: block; height: 100%; width: 0;
  background: var(--grad-bar); border-radius: 99px; transition: width 0.3s ease;
}


.toolbar { display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center; }
.search-wrap { flex: 1 1 280px; position: relative; display: flex; }
.search-ico {
  position: absolute; left: 1.1rem; top: 50%; transform: translateY(-50%);
  color: var(--text-mute); pointer-events: none;
}
.search {
  width: 100%; min-height: 52px;
  padding: 0.9rem 2.9rem 0.9rem 3rem;
  border: 1.5px solid var(--line-2); border-radius: var(--r-md);
  background: var(--paper-2); font-weight: 500; outline: none;
}
.search::placeholder { color: var(--text-mute); }
.search:focus { border-color: var(--ink-900); }

.search-clear {
  position: absolute; right: 0.85rem; top: 50%; transform: translateY(-50%);
  width: 28px; height: 28px; border: none; border-radius: 50%;
  background: var(--paper); color: var(--text-soft);
  display: flex; align-items: center; justify-content: center; cursor: pointer;
}
.search-clear:hover { background: var(--ink-900); color: var(--paper); }
/* Con el campo vacío no hay nada que borrar, así que la X no aparece. Lo
   resuelve `:placeholder-shown`: el JS no tiene que mostrarla ni ocultarla. */
.search:placeholder-shown + .search-clear { display: none; }

/* Encender la cámara es verde; apagarla, roja. El color hace de estado: el
   operador no lee el botón, lo reconoce. */
.btn-scan {
  appearance: none; cursor: pointer; min-height: 52px;
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  padding: 0.9rem 1.3rem; border: none; border-radius: var(--r-md);
  background: var(--sage); color: #fff; font-size: 0.88rem; font-weight: 700; white-space: nowrap;
}
.btn-scan:hover:not(:disabled) { background: #16651a; }
.btn-scan:disabled { opacity: 0.55; cursor: wait; }
.btn-scan[aria-pressed="true"] { background: var(--alert); }
.btn-scan[aria-pressed="true"]:hover { background: var(--alert-deep); }

/* El lector se come todo el alto que sobra en la columna. */
.scanner {
  flex: 1; min-height: 220px;
  display: flex; flex-direction: column;
  background: var(--ink-900); border-radius: var(--r-md); overflow: hidden;
}
.scanner-head {
  flex: none; display: flex; justify-content: space-between; align-items: center;
  padding: 0.8rem 1rem; color: var(--paper);
}
.cam-state { display: inline-flex; align-items: center; gap: 0.5rem; font: 600 0.66rem/1 var(--font-mono); letter-spacing: 0.06em; }
.cam-state .dot { background: var(--accent); }
.cam-tag { font: 500 0.63rem/1 var(--font-mono); color: var(--text-mute); letter-spacing: 0.06em; }

/* En la columna lateral el visor se estira hasta el fondo; apilado (tablet y
   teléfono) vuelve a una proporción fija, que es lo que cabe ahí. */
.scanner-stage { position: relative; width: 100%; flex: 1; min-height: 0; overflow: hidden; background: var(--ink-800); }
.scanner-stage video { width: 100%; height: 100%; object-fit: cover; display: block; }

/* La guía es lo que hace que la gente acerque el código al centro. Sin ella
   apuntan a cualquier parte del recuadro y el lector no engancha. */
.scanner-frame {
  position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: min(58%, 220px); aspect-ratio: 1;
  box-shadow: 0 0 0 100vmax rgba(15, 13, 24, 0.55);
}
.scanner-frame .c { position: absolute; width: 34px; height: 34px; border: 0 solid var(--accent); }
.scanner-frame .tl { top: 0; left: 0; border-top-width: 3px; border-left-width: 3px; border-top-left-radius: 8px; }
.scanner-frame .tr { top: 0; right: 0; border-top-width: 3px; border-right-width: 3px; border-top-right-radius: 8px; }
.scanner-frame .bl { bottom: 0; left: 0; border-bottom-width: 3px; border-left-width: 3px; border-bottom-left-radius: 8px; }
.scanner-frame .br { bottom: 0; right: 0; border-bottom-width: 3px; border-right-width: 3px; border-bottom-right-radius: 8px; }
/* Recorre la guía de lado a lado. Se anima `top` y no `transform` porque la
   guía es cuadrada y de tamaño variable: un desplazamiento en píxeles se sale
   del recuadro en pantallas chicas. */
.scanline {
  position: absolute; left: 8px; right: 8px; height: 2px;
  background: linear-gradient(90deg, transparent 0%, var(--accent) 50%, transparent 100%);
  box-shadow: 0 0 12px var(--accent);
  animation: scan 2.2s ease-in-out infinite;
}
@keyframes scan {
  0%, 100% { top: 8px; opacity: 0.9; }
  50% { top: calc(100% - 10px); opacity: 0.4; }
}

.scanner-stat {
  flex: none;
  font: 500 0.66rem/1 var(--font-mono); color: var(--text-mute);
  letter-spacing: 0.06em; margin: 0; padding: 0.85rem 1rem;
  background: var(--ink-800); border-top: 1px solid rgba(255, 255, 255, 0.06);
}

/* ---------- preview del escaneo ---------- */

/* A pantalla completa y con su propio color por resultado. El operador mira a
   la persona, no al monitor: si el resultado fuera una línea de texto en una
   esquina, no se ve. */
.flash {
  position: fixed; inset: 0; z-index: 70; display: grid; place-items: center;
  padding: 1.5rem; background: rgba(15, 13, 24, 0.72);
  backdrop-filter: blur(6px); -webkit-backdrop-filter: blur(6px);
  animation: flash-in 0.18s ease-out;
}
.flash-card {
  width: min(520px, 100%); background: var(--paper-2); border-radius: 24px;
  padding: clamp(2rem, 5vw, 2.75rem) clamp(1.5rem, 4vw, 2.5rem) 2rem;
  text-align: center; box-shadow: var(--shadow-modal);
  animation: modal-in 0.28s cubic-bezier(0.2, 0.9, 0.3, 1.1);
}

/* El icono va dentro de un disco del color del resultado: es lo primero que se
   lee a dos metros del monitor. */
.flash-icon {
  width: 88px; height: 88px; margin: 0 auto 1.25rem;
  display: flex; align-items: center; justify-content: center;
  border-radius: 50%; background: var(--sage-soft); color: var(--sage);
  font-size: 2.6rem; font-weight: 800; line-height: 1;
}
.flash-card.repetido .flash-icon { background: rgba(231, 60, 230, 0.12); color: var(--accent-deep); }
.flash-card.error .flash-icon { background: var(--alert-soft); color: var(--alert); }

.flash-estado {
  font: 500 0.7rem/1 var(--font-mono); letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--sage); margin: 0 0 0.9rem;
}
.flash-card.repetido .flash-estado { color: var(--accent-deep); }
.flash-card.error .flash-estado { color: var(--alert); }

/* El nombre en degradado: es el único texto de la aplicación que la persona que
   acaba de entrar va a mirar. */
.flash-nombre {
  font-family: var(--font-display); font-size: clamp(1.8rem, 6vw, 2.5rem);
  font-weight: 800; letter-spacing: -0.025em; margin: 0; line-height: 1.05;
  background: var(--grad-bar); -webkit-background-clip: text; background-clip: text;
  -webkit-text-fill-color: transparent; color: var(--brand);
}
.flash-card.error .flash-nombre { background: none; -webkit-text-fill-color: var(--ink-900); color: var(--ink-900); }
.flash-empresa { font-size: 0.98rem; color: var(--ink-700); margin: 0.5rem 0 0; }

.flash-datos {
  display: grid; grid-template-columns: auto 1fr; gap: 0.45rem 1.2rem;
  margin: 1.4rem 0 0; text-align: left; font-size: 0.85rem;
  background: var(--paper-3); border-radius: var(--r-md); padding: 1rem 1.2rem;
}
/* Un QR ilegible no trae datos que mostrar: sin esto quedaría una caja beige
   vacía bajo el nombre. */
.flash-datos:empty, .flash-empresa:empty { display: none; }
.flash-datos dt {
  font: 500 0.63rem/1.6 var(--font-mono); letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--text-mute);
}
.flash-datos dd { margin: 0; font: 700 0.8rem/1.6 var(--font-mono); color: var(--ink-900); }

/* El acompañante va destacado: es la única línea que cambia lo que el operador
   tiene que hacer a continuación (entregar dos credenciales, no una). */
.flash-acomp {
  margin: 0.9rem 0 0; padding: 0.85rem 1.1rem; border-radius: var(--r-sm);
  background: rgba(231, 60, 230, 0.1); color: var(--accent-deep);
  font-weight: 700; font-size: 0.88rem;
}

@keyframes flash-in { from { opacity: 0; } to { opacity: 1; } }
@keyframes modal-in {
  from { opacity: 0; transform: scale(0.9); }
  to { opacity: 1; transform: scale(1); }
}

/* ---------- pie con marquesina ---------- */

.marquee {
  background: var(--ink-900); color: var(--paper);
  height: 38px; display: flex; align-items: center; overflow: hidden;
}
.marquee-track { display: flex; gap: 3rem; white-space: nowrap; padding-left: 1.5rem; animation: marquee 30s linear infinite; }
.marquee-track span { font: 600 0.68rem/1 var(--font-mono); letter-spacing: 0.1em; }
.marquee-track .em { color: var(--accent); }
@keyframes marquee {
  0% { transform: translateX(0); }
  100% { transform: translateX(-50%); }
}

/* Bajo este ancho no caben tabla y cámara lado a lado: la columna se convierte
   en una fila entre el buscador y la tabla. La cámara empuja la tabla hacia
   abajo, que en un teléfono es lo único que deja ver las dos. */
@media (max-width: 1000px) {
  .reg-grid { grid-template-columns: minmax(0, 1fr); grid-template-areas: "toolbar" "cam" "list"; }
  .reg-side { position: static; width: auto; height: auto; margin: 1.2rem 0 0; }
  .resumen, .progreso, .reg-side .scanner { max-width: 460px; }
  .reg-side .scanner { flex: none; min-height: 0; margin-top: 0.5rem; }
  .reg-side .scanner-stage { flex: none; aspect-ratio: 4/3; }
}

@media (max-width: 760px) {
  .top { gap: 0.6rem 0.5rem; padding: 0.7rem 1rem; }

  /* «Salir» sube a la fila del logo, arriba a la derecha, y las pestañas se
     quedan solas abajo ocupando el ancho completo. Además de seguir el patrón
     de siempre, aleja el botón que cierra la sesión de los dos que se tocan
     todo el rato: en un teléfono, a un dedo apurado, 8px de separación entre
     «Registros» y «Salir» son un cierre de sesión a media jornada. */
  /* Base cero, si no la marca reclama el ancho de su contenido, se queda con la
     fila entera y empuja «Salir» abajo. Así cede lo que haga falta y el nombre
     del evento se recorta con puntos suspensivos. */
  .brand { flex: 1 1 0; min-width: 0; margin-right: auto; }
  .top-acc { order: 1; flex: none; gap: 0.5rem; }
  .tabs { order: 2; flex: 1 1 100%; }
  .tab { flex: 1; text-align: center; }
  .live { padding: 0.45rem 0.7rem; font-size: 0.64rem; }
  .hero-note { text-align: left; max-width: none; }
  .hero::before { display: none; }
  th, td { padding: 0.75rem 0.8rem; }
  .btn-marcar { min-width: 110px; }
  /* En teléfono el correo sobra: el operador busca por nombre y marca. */
  #tRegistros th:nth-child(2), #tRegistros td:nth-child(2) { display: none; }

  /* En el teléfono se deja de repartir a la fuerza.
   *
   * El reparto fijo está pensado para una pantalla ancha, donde el problema es
   * que una fila larga empuje la hora fuera del borde. En 360px el problema es
   * el contrario: meter las columnas dentro de ese ancho a como dé lugar deja
   * «Kathia Orellana» partido en dos líneas de una palabra y todo pegado.
   *
   * Así que la tabla vuelve a medirse por su contenido, con un mínimo para que
   * ninguna columna quede en una tira, y el contenedor la desplaza en
   * horizontal — `.tablewrap` ya trae `overflow-x: auto`. Se lee deslizando,
   * que en un teléfono es el gesto natural, y no se esconde ningún dato.
   *
   * Los anchos reservados se sueltan: con reparto automático son un estorbo,
   * y además una columna oculta —el correo, aquí arriba— seguiría quedándose
   * con su parte del ancho aunque no se vea. */
  #tIngresados, #tRegistros { table-layout: auto; min-width: 32rem; }
  #tIngresados .c-estado, #tIngresados .c-hora,
  #tRegistros .c-acomp, #tRegistros .c-accion { width: auto; }
}

/* En un teléfono no caben cinco columnas sin partir el nombre y el RUT en
   varias líneas. Cae también la de acompañante: el «+1» sigue saliendo junto al
   nombre en el dashboard y a pantalla completa al escanear, que es cuando
   importa — ahí es donde el operador decide si entrega una credencial o dos. */
@media (max-width: 620px) {
  /* Cae la píldora «EN VIVO»: es decorativa —dice lo mismo pase lo que pase— y
     el ancho que ocupa es exactamente el que necesitan el nombre del evento y
     la línea de sincronización, que sí son datos. Con ella puesta, en un
     teléfono el nombre se recortaba a una letra. Si el servidor se cae, quien
     avisa es la franja roja de «sin conexión», no esta píldora. */
  .live { display: none; }

  /* El logotipo es una firma horizontal: a 28px de alto mide ~147px de ancho y
     en un teléfono no deja nada para el nombre del evento. Baja a 22px y la
     marca se junta un poco. */
  .brand { gap: 0.6rem; }
  .brand-logo { height: 22px; }

  #tRegistros th:nth-child(4), #tRegistros td:nth-child(4) { display: none; }

  /* El «+1» del dashboard pierde el nombre del acompañante: en una columna
     estrecha esa frase —«María Eugenia Salinas (Subgerente de RRHH) / Luis
     Ovalles (Analista de capacitación)»— ocupa media pantalla y entierra los
     nombres de las filas siguientes. La marca de que viene alguien se conserva,
     que es lo que se mira de un vistazo; el nombre completo sigue en Registros
     y a pantalla completa al escanear, que es cuando hay que entregar la
     segunda credencial. */
  .pill.acomp i { display: none; }

  /* Todo el bloque del lector se mide contra la pantalla real del teléfono, no
     contra un tamaño fijo: `dvh` descuenta la barra del navegador, que es la
     que hace que en un móvil «200px» se sientan la mitad de la pantalla. Entre
     las cajas, el progreso y el visor no pueden pasar de dos tercios del alto,
     o la tabla queda fuera de la vista y hay que buscarla a ciegas. */
  .reg-side .scanner-stage { aspect-ratio: auto; height: clamp(150px, 30dvh, 230px); }
  .caja { padding: 0.7rem 0.85rem; }
  .caja b { font-size: 1.5rem; }
  .progreso { padding: 0.7rem 0.85rem; }
  .reg-side { gap: 0.5rem; }

  th, td { padding: 0.7rem 0.6rem; }
  .btn-marcar { min-width: 92px; padding: 0.4rem 0.6rem; font-size: 0.74rem; }
  .sec-head { margin-top: 1.4rem; }
}
