:root{
  --bg:#EEF0F3; --card:#FFFFFF; --ink:#0F2340; --ink-soft:#5B6472; --muted:#5B6472; --line:#E4E7EE;
  --green:#5f8b1f; --green-press:#4a6a17; --green-ink:#3f5a1e; --green-soft:#eef5df;
  --lime:#7ab929; --soft:#8b929c;      /* --nav vive con el resto del armazon, mas abajo */
  --blue:#2e78b7; --blue-soft:#E7F0F8; --gold:#C98A12; --gold-soft:#faf0d6; --gold-ink:#7a5600;
  --link:#2e78b7; --danger:#B42318; --red:#c0392b; --ok:#5f8b1f; --radius:14px; --field-h:52px;
  /* El anillo de foco era un color translucido fijo, calculado para el armazon navy: sobre fondo
     claro se compone y se apaga (2.0 en el encabezado, 1.7 en el menu, cuando el minimo para un
     elemento grafico es 3). Opaco y por token: no depende del fondo y el tema si lo puede cambiar. */
  --foco:#2E78B7;                    /* 4.68 sobre blanco */
  /* Texto de ejemplo de los campos. Ni el gris del navegador (no es token) ni --soft, que mide
     3.14 sobre la tarjeta: por debajo del 4.5 que pide AA para el texto normal. */
  --ph:#6B7484;                      /* 4.71 sobre --card */
  /* Rejilla de informes: el renglon alterno y la columna de domingo/festivo. Medidos sobre
     --card; "aqui hay dato" reusa --tab-on, que este archivo ya midio en 1.20. */
  --rej-cebra:#EAEEF5;               /* 1.16 sobre --card */
  --rej-fest:#FFF6DC;                /* 1.08 sobre --card; el numero encima, 14.59 */
  /* Domingo/festivo como FONDO DE CELDA en el calendario del mes. No se reusa --rej-fest: mide
     1.08 contra la tarjeta y este archivo ya fijo 1.20 como minimo para un tinte de fondo (en la
     rejilla de informes funciona porque la columna entera va tenida y el numero encima da 14.59;
     como celda suelta se pierde). MEDIDO: 1.21 en claro, tinta --ink encima 13.03. */
  --cal-fest:#F8E9BE;
  /* ---- BANDA de novedad en el calendario del mes (hr-v82) -------------------------------------
     El TIPO de novedad ya no es un relleno palido: es una banda vertical en tinta SATURADA. Por
     que: los seis rellenos median 1.12-1.22 contra la tarjeta y ENTRE SI no llegaban a 1.10, asi
     que solo los separaba el tono... y el tono de un lavado al 1.2 casi no se ve. Saturados, cada
     banda mide 5.00 o mas contra CUALQUIER relleno de estado, en los dos temas.
     Los tonos se eligieron por distancia perceptual (CIEDE2000), no a ojo: con las tintas que ya
     existian, `licencia` y `compensatorio` median dE 6.3 en claro y 4.2 en oscuro -- por debajo de
     11, o sea la misma banda. Y `ausentismo` con --ink-soft chocaba con `vacaciones` en oscuro
     (dE 9.5). Con estos valores la PEOR pareja de las seis mide dE 18.0 en claro y 16.6 en oscuro.
     `compensatorio` estrena un tono que la app no usaba (teal): los otros cinco ya estaban
     ocupados por azul, rojo, dorado, verde y gris. */
  --nov-vacaciones:#1C5D9B;      /* 5.59 min · dE 18.0 al mas cercano */
  --nov-incapacidad:#B42318;     /* 5.40 min */
  --nov-permiso:#7a5600;         /* 5.46 min */
  --nov-licencia:#3f5a1e;        /* 6.41 min */
  --nov-ausentismo:#5E6167;      /* 5.10 min · gris NEUTRO: con --ink-soft (#5B6472) chocaba */
  --nov-compensatorio:#0F6E68;   /* 5.00 min · teal, el sexto tono */
  /* Tinta sobre dorado. Blanco sobre --gold da 2.95 y AA pide 4.5; el propio archivo ya lo resolvia
     bien en .btn.gold con este mismo color, pero escrito a pelo en tres sitios. */
  --gold-tinta:#3a2c00;              /* 4.63 sobre --gold */
  --navy:#0f2340; --red-soft:#FDE9E9;
  /* Fondo de la pestana donde estas. Elegido MIDIENDO contraste, no a ojo: el primer valor que
     probe (#f6faee) daba 1.06 contra la barra blanca, o sea invisible -- la linea verde hacia todo
     el trabajo. Este da 1.20, que se nota sin gritar, y el texto encima queda en 6.5 (AA pide 4.5). */
  --tab-on:#e4efcc;
  /* ---- Tinte de ESTADO para celdas y filas de los informes ---------------------------------
     Son los mismos tonos de `.pill.*`, un punto mas profundos. Por que no se reusan tal cual:
     MEDIDO, los de pastilla dan 1.10-1.19 contra la tarjeta y el minimo para un tinte de fondo es
     1.20 — como pastilla funcionan (tienen forma y borde), como fondo de celda se pierden contra
     el blanco. Estos miden 1.20-1.22 en claro y 1.34-1.43 en oscuro, con la tinta encima por
     encima de 4.9 en los dos temas. */
  --st-borrador:#E5EAF3; --sti-borrador:#0F2340;   /* 1.21 · texto 13.03 */
  --st-enviado:#F6E8D2;  --sti-enviado:#8A5A00;    /* 1.21 · texto  4.91 */
  --st-aprobado:#DFEEE2; --sti-aprobado:#3f5a1e;   /* 1.20 · texto  6.49 */
  --st-recibido:#DDECF8; --sti-recibido:#1C5D9B;   /* 1.21 · texto  5.64 */
  --st-devuelto:#FAE4E2; --sti-devuelto:#B42318;   /* 1.22 · texto  5.40 */
  /* ---- Armazon CLARO (propuesta A, elegida por el usuario) --------------------------------
     El menu lateral y el encabezado dejan de ser una banda navy y pasan a ser OTRA SUPERFICIE:
     la misma tarjeta del contenido, separada con lineas de un pixel. El color se reserva para
     una sola cosa: donde estas.

     Por que: en el celular la barra de abajo SIEMPRE fue clara, asi que el marco estaba a
     medias (encabezado oscuro y barra clara en la misma pantalla). Y desde que hay tema
     claro/oscuro de verdad, un armazon navy en LOS DOS temas ya no tenia defensa.

     Todo el color del armazon vive aqui: si un color no es token, el tema no lo puede cambiar.
     Los numeros son contraste MEDIDO, no estimado. */
  --nav:#FFFFFF;                     /* el menu es la misma superficie que las tarjetas */
  --nav-hdr:#FFFFFF;                 /* y el encabezado tambien */
  --nav-linea:#E4E7EE;               /* separa la LINEA, no el color de fondo */
  --nav-ink:#0F2340;                 /* 15.7 */
  --nav-ink-soft:#5B6472;            /* 6.0 */
  --nav-hover:rgba(15,35,64,.055);   /* el hover ya no puede ser blanco translucido */
  /* El mismo tinte EXACTO que la barra inferior (--tab-on): asi no pueden volver a separarse.
     Con #EEF5DF el bloque del activo media 1.13 contra el menu blanco, y este archivo ya habia
     medido que por debajo de 1.20 el estado no se ve y la linea de acento hace todo el trabajo. */
  --nav-on-bg:var(--tab-on);
  --nav-on-ink:#3F5A1E;              /* 7.0 sobre --nav-on-bg */
  --nav-on-bar:#5F8B1F;              /* el filo de acento */
  --hdr-ink:#0F2340;                 /* 15.7 - antes era #fff a pelo, en tres sitios */
  --hdr-ink-soft:#5B6472;            /* 6.0 */
  --hdr-btn:#F1F3F6;                 /* botones redondos del encabezado (tema, campana, salir) */
  --hdr-btn-bd:#E4E7EE;
  --hdr-btn-hover:#E4E9F0;
  --nav-sombra:0 1px 3px rgba(15,35,64,.07);
  /* Escala de iconos del armazon: tres tamanos con nombre y ninguno mas (habia cinco) */
  --ico-nav:20px; --ico-hdr:18px; --ico-tab:22px;
  --shadow:0 1px 2px rgba(15,35,64,.05),0 4px 14px rgba(15,35,64,.07);
  --shadow-lg:0 8px 26px rgba(15,35,64,.13);
}
*{box-sizing:border-box;-webkit-tap-highlight-color:transparent}
html,body{margin:0;min-height:100%}
body{background:var(--bg);color:var(--ink);
  font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
  padding-bottom:env(safe-area-inset-bottom)}
a{color:var(--link);text-decoration:none}
.wrap{width:100%;max-width:460px;margin:0 auto;padding:14px}
.wrap.wide{max-width:1200px}

/* Header */
/* Sobre fondo claro una sombra fuerte se ve sucia: separa la LINEA, y la sombra solo insinua
   que el encabezado esta por encima del contenido cuando se hace scroll. */
.hdr{position:sticky;top:0;z-index:10;background:var(--nav-hdr);color:var(--hdr-ink);display:flex;
  align-items:center;gap:8px;padding:10px 14px;padding-top:max(10px,env(safe-area-inset-top));
  border-bottom:1px solid var(--nav-linea);box-shadow:var(--nav-sombra)}
.hdr .htitle{flex:1 1 auto;min-width:10ch;display:flex;flex-direction:column;justify-content:center;line-height:1.15}
.hdr h1{font-size:16px;font-weight:700;margin:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hdr .sub{font-size:11px;color:var(--hdr-ink-soft);font-weight:500;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.hbtn{display:inline-flex;align-items:center;gap:6px;height:38px;padding:0 13px;border-radius:999px;
  background:var(--hdr-btn);border:1px solid var(--hdr-btn-bd);color:var(--hdr-ink);font-size:13px;
  font-weight:600;cursor:pointer;text-decoration:none;white-space:nowrap;line-height:1;flex:none;transition:background .15s}
.hbtn:hover{background:var(--hdr-btn-hover)}
/* Mientras se cambia de tema, NADA se anima. Las transiciones de fondo existen para el hover, y en
   un cambio de tema hacen que el control se quede un momento con el color del tema anterior: medido
   con el propio sol/luna, la campana seguia en #F1F3F6 sobre el encabezado ya oscuro. `js/prefs.js`
   pone esta clase, repinta, y la quita al frame siguiente. */
html.cambiando-tema, html.cambiando-tema *, html.cambiando-tema *::before, html.cambiando-tema *::after{
  transition:none !important; animation:none !important;
}
/* ---- «Ver como»: el chip del encabezado y la banda -----------------------------------------
   Solo existen cuando el modo esta encendido (se enciende en Administración → Sistema), asi que
   con el modo apagado el armazon no lleva ni un control mas. Van en la familia AZUL, que en esta
   app significa "informativo", con la tinta normal encima y no `--blue`: ese par medido da 4.05 y
   AA pide 4.5 para texto normal, que es lo que hay en la banda. */
.hbtn-vc{background:var(--blue-soft);border-color:var(--blue);color:var(--ink)}
.hbtn-vc:hover{background:var(--blue-soft);filter:brightness(1.06)}
.vcbanda{display:flex;align-items:center;gap:9px;flex-wrap:wrap;
  background:var(--blue-soft);border-bottom:1px solid var(--blue);color:var(--ink);
  padding:8px 14px;font-size:12.5px;line-height:1.4}
.vcbanda svg{color:var(--blue);flex:none}
.vcbanda span{flex:1;min-width:12ch}
/* La pastilla mide 36px de alto a proposito: la banda es una franja delgada y un boton de 44
   la partiria en dos renglones en el telefono. Lo que crece es el AREA TOCABLE, no el boton
   (misma solucion que el resto de la app): 4px arriba y abajo dejan 44 justos, y con letra grande
   (--tap 48) sigue faltando, asi que el pseudo-elemento se estira con el token. Medido: sin esto
   el unico camino para salir del espejo desde el cuerpo de la pagina era un blanco de 36px. */
.vcbanda button{appearance:none;font:inherit;font-size:12px;font-weight:700;cursor:pointer;
  min-height:36px;padding:0 12px;border-radius:999px;border:1px solid var(--blue);
  background:var(--card);color:var(--ink);flex:none;position:relative}
.vcbanda button::after{content:"";position:absolute;left:0;right:0;
  top:calc((36px - var(--tap)) / 2);bottom:calc((36px - var(--tap)) / 2)}
.hbtn .hi{font-size:15px;line-height:1}
/* "Salir" ya no grita: es un boton igual a los demas y el rojo solo aparece al apuntarlo.
   Solo se ve en escritorio con el menu lateral recogido (en el resto lo esconde el CSS del
   armazon y Salir vive en el menu o en la hoja "Mas"). */
.hbtn-danger:hover{background:var(--red-soft);border-color:var(--danger);color:var(--danger)}
.hbtn .ht{max-width:180px;overflow:hidden;text-overflow:ellipsis}
.badge{background:var(--gold);color:var(--gold-tinta);font-size:11px;font-weight:800;border-radius:20px;padding:3px 8px;min-width:22px;text-align:center;flex:none}
@media(max-width:600px){ .hdr .hbtn:not(.hbtn-back) .ht{display:none} }

/* Cards */
.card{background:var(--card);border:1px solid var(--line);border-radius:var(--radius);
  padding:14px;margin-bottom:12px;box-shadow:var(--shadow)}
.card h3{margin:0 0 4px;font-size:16px;color:var(--green-ink)}
.muted{color:var(--ink-soft);font-size:13px}
.row{display:flex;gap:10px;align-items:center}
/* OJO con el nombre: aqui `wrap` significa "que los hijos salten de renglon", pero `.wrap` a
   secas es el CONTENEDOR de la pagina (460 px centrados y 14 px de relleno, mas arriba en este
   archivo). Un `class="row wrap"` se llevaba las DOS cosas: la fila quedaba con tope de 460 px y
   con relleno propio DENTRO de una tarjeta, por mas pantalla que hubiera. Medido en el panel de
   la campana a 700 px: la fila media 460 en una caja de 640, y por eso el tercer boton saltaba
   de renglon. Son 7 filas en 5 pantallas (perfil, novedades, biblioteca, la tarjeta de la
   planilla y el panel de notificaciones), asi que se apaga aqui y no en cada sitio. */
.row.wrap{flex-wrap:wrap;max-width:none;margin:0;padding:0}
.spread{justify-content:space-between}

/* Botones */
.btn{height:var(--field-h);border:none;border-radius:var(--radius);background:var(--green);
  color:#fff;font-size:16px;font-weight:700;cursor:pointer;display:flex;align-items:center;
  justify-content:center;gap:8px;width:100%;transition:background .15s,transform .04s}
.btn:active{background:var(--green-press);transform:translateY(1px)}
.btn.ghost{background:#fff;color:var(--ink);border:1px solid var(--line)}
.btn.gold{background:var(--gold);color:var(--gold-tinta)}
.btn.blue{background:var(--blue)}
.btn.danger{background:var(--danger);color:#fff}
/* "Devolver" secundario: contorno rojo, texto rojo, fondo blanco (evita el rojo+texto navy roto de .ghost.danger) */
.btn.ghost.danger,.btn.ghost-danger{background:#fff;color:var(--danger);border:1px solid var(--danger)}
.btn.sm{height:44px;font-size:14px;width:auto;padding:0 16px}
.btn[disabled]{opacity:.6;cursor:progress}
.btn:focus-visible,.chip:focus-visible,.hbtn:focus-visible,.segbar button:focus-visible{
  outline:3px solid var(--foco);outline-offset:2px}
.spin{width:16px;height:16px;border:2.5px solid rgba(255,255,255,.45);border-top-color:#fff;
  border-radius:50%;animation:sp .7s linear infinite}
@keyframes sp{to{transform:rotate(360deg)}}

/* Reloj checador (nucleo ultraintuitivo) */
.punch{display:flex;flex-direction:column;gap:12px;margin:8px 0 4px}
.punch .pbtn{height:96px;border:none;border-radius:20px;font-size:22px;font-weight:800;color:#fff;
  cursor:pointer;display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;
  box-shadow:var(--shadow-lg);transition:transform .05s}
.punch .pbtn:active{transform:scale(.99)}
.punch .pbtn small{font-size:13px;font-weight:600;opacity:.9}
.punch .entrada{background:linear-gradient(120deg,#6c9a2e,#3f5a1e)}
.punch .salida{background:linear-gradient(120deg,#c98a12,#7a5600)}
.punch .pbtn[disabled]{filter:grayscale(.5);opacity:.55;cursor:not-allowed}
.reloj{font-size:44px;font-weight:800;text-align:center;font-variant-numeric:tabular-nums;letter-spacing:1px}
.reloj-f{text-align:center;color:var(--ink-soft);font-size:14px;margin-top:-4px;text-transform:capitalize}

/* Segmented bar (dia/semana/mes) */
.segbar{display:flex;background:#e7eaf0;border-radius:12px;padding:4px;gap:4px;margin-bottom:12px}
.segbar button{flex:1;border:none;background:none;padding:9px 0;border-radius:9px;font-size:14px;
  font-weight:700;color:var(--ink-soft);cursor:pointer}
.segbar button.on{background:#fff;color:var(--ink);box-shadow:var(--shadow)}
/* Segmentado PEQUENO (Dias en la planilla, accion en pendientes, "que le das" en accesos).
   El estilo base vivia SOLO en los <style> de planilla.html y pendientes.html, mientras que aqui
   estaban ya sus variantes de tema oscuro: un componente compartido a medias. En tema claro, que es
   el de por defecto, el administrador lo pintaba con los botones grises del navegador y NO se veia
   cual estaba elegido. Las dos pantallas que traen su propia copia la declaran despues de este
   archivo, asi que siguen mandando ellas y no cambia nada de lo que ya funcionaba. */
.segmini{display:inline-flex;background:var(--bg);border-radius:9px;padding:3px;gap:3px;flex:0 0 auto}
.segmini button{border:none;background:none;padding:0 11px;height:28px;border-radius:7px;
  font-size:12.5px;font-weight:700;color:var(--ink-soft);cursor:pointer;white-space:nowrap}
.segmini button.on{background:var(--card);color:var(--ink);box-shadow:var(--shadow)}

/* Campos */
label{display:block;font-size:13px;font-weight:600;margin:10px 0 4px;color:var(--ink)}
input,select,textarea{width:100%;min-height:var(--field-h);background:var(--card);
  border:1px solid var(--line);border-radius:var(--radius);padding:12px 14px;font-size:16px;
  color:var(--ink);outline:none;font-family:inherit}
textarea{min-height:76px;resize:vertical}
input:focus,select:focus,textarea:focus{border-color:var(--ink);box-shadow:0 0 0 3px rgba(10,34,71,.10)}
.grid2{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.grid3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:8px}

/* Chips y pills */
.chips{display:flex;gap:8px;flex-wrap:wrap}
/* ---- Barra de "como lo quiero ver": agrupar y resumir -------------------------------
   Vivia SOLO en informes.html. Mi planilla necesita los mismos chips y copiarlos habria
   sido crear el segundo sitio donde arreglar lo mismo -- es lo que ya paso con `.tchip`,
   que estaba copiado en dos pantallas y YA habia divergido. Los numeros medidos siguen en
   los comentarios de cada regla. */
  /* Barra de "cómo lo quiero ver": agrupar y resumir. Son los mismos chips de la barra de arriba. */
  .verops{display:flex;gap:14px;flex-wrap:wrap;align-items:center;padding:9px 12px;
    border-bottom:1px solid var(--line)}
  .verops .grp{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
  .verops .grp .chips{display:flex;gap:6px;align-items:center;flex-wrap:wrap}
  .verops .et{font-size:var(--f-xs);color:var(--ink-soft);font-weight:600}
  .opt{border:1px solid var(--line);background:var(--card);color:var(--ink-soft);border-radius:999px;
    padding:5px 11px;font-size:var(--f-xs);font-weight:600;cursor:pointer;height:30px}
  .opt:hover{background:var(--blue-soft);color:var(--ink)}
  /* El elegido usa el MISMO tinte de "aquí estás" que la barra de pestañas y el menú (`--tab-on`),
     que esta hoja ya midió: 1.20 contra la tarjeta en claro y 1.33 en oscuro, con la tinta verde
     encima en 6.5. Antes iba en `--navy`: el texto blanco encima medía 15.96, pero **el relleno
     medía 1.09 contra la tarjeta en oscuro** —por debajo del piso de 1.33 de esta app—, así que el
     chip elegido se distinguía solo por el color de la letra. El borde verde lo remata. */
  .opt.on{background:var(--tab-on);border-color:var(--green);color:var(--green-ink)}
  /* En el celular estos chips se tocan con el dedo: 30px de alto es la mitad de un pulgar. Suben a
     40, como los chips de la barra (`.pchip2`, 36) más el aire de estar dentro de una tarjeta.
     600px es un corte que esta hoja de estilos ya usa; no se inventa uno nuevo. */
  @media(max-width:760px){
    /* Medido a 390px: los chips se partian en escalera —"Sin agrupar" solo en un renglon, el rotulo
       "Detalle" pegado al chip siguiente— porque `flex-wrap` reparte sin saber a que grupo pertenece
       cada uno. Aqui cada grupo es un BLOQUE: su rotulo arriba y sus chips en una sola linea que se
       desliza, igual que la barra de filtros de la planilla. */
    .verops{flex-direction:column;align-items:stretch;gap:12px}
    .verops .grp{display:grid;grid-template-columns:1fr;gap:6px}
    .verops .grp .et{padding-left:2px}
    /* `nowrap` explicito: la regla ancha los deja envolver, y sin esto seguian partiendose en dos
       renglones en vez de deslizarse (medido a 375px: el grupo "Agrupar por" ocupaba 2 filas). */
    .verops .grp .chips{display:flex;gap:6px;flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;
      padding-bottom:2px;-webkit-overflow-scrolling:touch}
    .verops .grp .chips::-webkit-scrollbar{display:none}
    .opt{min-height:40px;padding:8px 13px;flex:none}
  }

.chip{border:1px solid var(--line);background:#fff;border-radius:20px;padding:8px 14px;font-size:14px;cursor:pointer;user-select:none}
.chip.on{background:var(--ink);color:#fff;border-color:var(--ink)}
/* ---------------------------------------------------------------- CHIPS DE TURNO (.turnos/.tpl)
   «Con que turno se registra este dia»: Diurno / Nocturno / los que haya. Vivian copiados en
   calendario.html; desde hr-v83 los usa tambien hoy.html, asi que estan aqui una sola vez — es la
   misma razon por la que la barra de arriba dejo de estar en cuatro sitios.
   Los chips van en UN renglon, mitad y mitad: el nombre arriba y la hora debajo. Con el chip de una
   linea ("Diurno 07:00-16:30") no cabian dos en 340px y se partian en dos renglones. */
.turnos{display:flex;gap:8px}
.tpl{flex:1 1 0;min-width:0;min-height:var(--tap);border-radius:12px;border:1px solid var(--line);
  background:var(--card);color:var(--ink);font-family:inherit;cursor:pointer;padding:6px 10px;
  display:inline-flex;align-items:center;justify-content:center;gap:7px;text-align:left}
/* El nombre y la hora, uno debajo del otro y SIN cruzarse: con line-height heredado sus cajas se
   montaban 2px (lo caza el auditor, aunque a ojo no se note). */
.tpl .tx{display:flex;flex-direction:column;gap:1px;min-width:0}
.tpl .tx b{font-size:13px;font-weight:700;line-height:1.25}
.tpl .tx small{font-size:11px;line-height:1.3;color:var(--muted);font-variant-numeric:tabular-nums}
/* Activo = el tinte de «aqui estas» con borde verde, no verde solido. Con fondo --green la hora
   pequena quedaba en blanco translucido (3.40 en claro, 2.75 en oscuro: por debajo del 4.5 que pide
   un texto), y encima era un color escrito a mano. Medido: tinte 1.20/1.33 sobre la tarjeta, tinta
   --green-ink encima 6.51/6.46, borde --green 4.04/4.59. */
.tpl[aria-pressed="true"]{background:var(--tab-on);color:var(--green-ink);border-color:var(--green)}
.tpl[aria-pressed="true"] .tx small{color:var(--green-ink)}
.tpl:focus-visible{outline:3px solid var(--foco);outline-offset:2px}

.pill{display:inline-block;font-size:11px;font-weight:700;border-radius:10px;padding:3px 9px}
.pill.borrador{background:#E7ECF5;color:var(--ink)}
.pill.enviado{background:#FEF3E2;color:#8A5A00}
.pill.aprobado{background:#E6F4EA;color:var(--green)}
.pill.recibido{background:#E3F0FB;color:#1C5D9B}
/* DEVUELTO: el estado tenia nombre en los filtros, color de celda (--st-devuelto, hr-v60) y
   estilo de fila en Informes, pero NO tenia pastilla, asi que en Mi planilla salia sin fondo.
   Va con los TOKENS y no con literales como sus cuatro hermanos —que son anteriores a los
   tokens— para que el tema oscuro le llegue solo. Contraste del texto MEDIDO: 5.40 en claro
   y 5.70 en oscuro; AA pide 4.5 y una pastilla de 11px en negrita NO es texto grande. */
.pill.devuelto{background:var(--st-devuelto);color:var(--sti-devuelto)}
.pill.fuera{background:#FDECEA;color:var(--danger)}
/* "el mismo": marca la opcion en la que ya estas dentro de una lista (el centro de la 2a jornada).
   No reusa .pill.aprobado porque ese par MIDE 3.56 en claro (AA pide 4.5 y 11px en negrita no es
   texto grande); con los tokens del verde da 6.97 en claro y 7.99 en oscuro, y ademas el tema los
   cambia solo. */
.pill.mismo{background:var(--green-soft);color:var(--green-ink)}
/* Estados de NOVEDAD (femeninos, del modulo de novedades). Vivian copiados en planilla.html y
   novedades.html, y en biblioteca.html NO estaban: la pastilla salia sin color ninguno. Los tokens
   ya cambian con el tema, asi que no hacen falta variantes de oscuro. */
.pill.pendiente{background:var(--gold-soft);color:var(--gold-ink)}
.pill.aprobada{background:var(--green-soft);color:var(--green)}
.pill.rechazada{background:var(--red-soft);color:var(--danger)}
.pill.recibida{background:var(--blue-soft);color:var(--blue)}
.pill.anulada{background:var(--bg);color:var(--muted)}

/* Tipo de novedad, vigencia y la marca de "medico". Los usan novedades.html y biblioteca.html;
   estaban copiados en las dos y YA habian divergido (el chip media 11px alli y 11.5px aca). Misma
   razon por la que la hoja de filtros vive solo aqui: una copia es un sitio donde volver a arreglar. */
.tchip{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:700;border-radius:999px;
  padding:3px 9px;border:1px solid transparent;width:fit-content}
/* La TINTA de cada tipo sale de --nov-* (hr-v82), el mismo token que pinta la banda del calendario:
   asi un tipo de novedad tiene UN tono en toda la app. Antes cada pantalla elegia el suyo y
   `compensatorio` y `licencia` compartian --green-ink con fondos a 1.06 entre si — o sea la MISMA
   pastilla, distinguidas solo por el borde y el icono (lo decia el comentario que habia aqui).
   Medida perceptual (CIEDE2000) de esa pareja: 6.3 en claro y 4.2 en oscuro, cuando por debajo de
   11 dos colores se confunden. Con --nov-* la peor pareja de los seis mide 18.0 y 16.6.
   El fondo palido se queda: en una PASTILLA funciona (tiene forma y borde), y era como FONDO DE
   CELDA donde se perdia. Tinta sobre su fondo, medido: peor caso 5.08 en claro y 6.12 en oscuro
   (AA pide 4.5 y 11.5px en negrita no es texto grande). */
.t-vacaciones{background:var(--blue-soft);color:var(--nov-vacaciones);border-color:var(--line)}
.t-incapacidad{background:var(--red-soft);color:var(--nov-incapacidad);border-color:var(--nov-incapacidad)}
.t-ausentismo{background:var(--bg);color:var(--nov-ausentismo);border-color:var(--line)}
.t-permiso{background:var(--gold-soft);color:var(--nov-permiso);border-color:var(--gold)}
.t-licencia{background:var(--green-soft);color:var(--nov-licencia);border-color:var(--line)}
.t-compensatorio{background:var(--tab-on);color:var(--nov-compensatorio);border-color:var(--nov-compensatorio)}
.vig{display:inline-flex;align-items:center;gap:5px;font-size:11.5px;font-weight:700;border-radius:8px;
  padding:3px 8px;width:fit-content}
.vig-vigente{background:var(--green-soft);color:var(--green-ink)}
.vig-por_vencer{background:var(--gold-soft);color:var(--gold-ink)}
.vig-terminada{background:var(--red-soft);color:var(--danger)}
.vig-na{background:var(--bg);color:var(--muted)}
.med{font-size:10.5px;color:var(--gold-ink);background:var(--gold-soft);border-radius:6px;padding:1px 6px;font-weight:700}

/* KPIs */
.kpis{display:grid;grid-template-columns:repeat(auto-fit,minmax(120px,1fr));gap:10px;margin-bottom:12px}
.kpi{background:var(--card);border:1px solid var(--line);border-radius:12px;padding:12px 14px}
.kpi b{font-size:26px;font-weight:800;display:block;font-variant-numeric:tabular-nums}
.kpi span{font-size:12px;color:var(--ink-soft)}

/* Tabla */
.tabla-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
table.data{width:100%;border-collapse:collapse;font-size:13.5px}
table.data th,table.data td{text-align:left;padding:9px 10px;border-bottom:1px solid var(--line);white-space:nowrap}
/* La cabecera se recorta con puntos suspensivos en vez de derramarse encima de la de al lado.
   Con `table-layout:fixed` y `nowrap`, "CENTROS ASIGNADOS (CON SU JEFE...)" pedia 301px en una
   celda de 253 a 1280px y los 48 que sobraban se pintaban sobre "TIPO DE HORARIO": se leia
   "PARA QUITABE HORARIO". El texto completo va en el `title` de cada cabecera larga. */
table.data th{font-size:11px;text-transform:uppercase;letter-spacing:.04em;color:var(--ink-soft);font-weight:700;
  overflow:hidden;text-overflow:ellipsis}
table.data td.num{text-align:right;font-variant-numeric:tabular-nums}
table.data tr:last-child td{border-bottom:none}

/* Listas */
.item{padding:12px 0;border-bottom:1px solid var(--line)}
.item:last-child{border-bottom:none}
.empty{text-align:center;color:var(--ink-soft);padding:40px 16px;font-size:15px}

/* Evidencia: hora de registro + ubicacion, UNA LINEA POR MARCA (entrada, salida y la 2a jornada).
   Estaba escrita a mano en un `style=` dentro de js/ui.js, asi que el tema no la podia tocar. */
.evid{font-size:11.5px;color:var(--muted);margin-top:6px;padding-top:6px;
  border-top:1px dashed var(--line);line-height:1.45;display:flex;flex-direction:column;gap:3px}
.evid-f{display:flex;align-items:baseline;gap:5px;flex-wrap:wrap}
.evid-f b{color:var(--ink-soft)}
.evid-m{font-size:11px;color:var(--muted);margin:2px 0 0 22px;line-height:1.35}

/* Toast */
.toast{position:fixed;left:50%;bottom:24px;transform:translateX(-50%);background:var(--ink);
  color:#fff;padding:12px 18px;border-radius:12px;font-size:14px;font-weight:600;z-index:100;
  box-shadow:0 8px 24px rgba(0,0,0,.25);opacity:0;transition:opacity .2s;max-width:90%}
.toast.show{opacity:1}.toast.ok{background:var(--green)}.toast.err{background:var(--danger)}.toast.warn{background:var(--gold);color:var(--gold-tinta)}

/* Modal */
.modal{position:fixed;inset:0;background:rgba(10,34,71,.42);display:none;align-items:flex-end;z-index:90}
.modal.show{display:flex}
.modal .box{position:relative;background:#fff;width:100%;max-width:460px;margin:0 auto;
  border-radius:20px 20px 0 0;padding:20px 18px 18px;max-height:90vh;overflow:auto;box-shadow:0 -10px 40px rgba(10,34,71,.22)}
.modal .box h3{margin:0 0 12px;padding-right:34px;font-size:17px;color:var(--green-ink)}
.modal-x{position:absolute;top:12px;right:12px;width:32px;height:32px;border:none;border-radius:50%;
  background:#eef1f6;color:var(--ink-soft);font-size:14px;cursor:pointer;line-height:1;z-index:2}
@media(min-width:600px){ .modal{align-items:center} .modal .box{border-radius:18px} }

/* ================= Responsive / auto-ajuste (cualquier zoom + movil) ================= */
html{-webkit-text-size-adjust:100%;text-size-adjust:100%}
body{overflow-x:hidden}                     /* nada desborda la pantalla horizontalmente */
img,canvas,svg,video{max-width:100%}
.wrap,.wrap.wide{padding-left:clamp(10px,3vw,14px);padding-right:clamp(10px,3vw,14px)}
.tabla-wrap{max-width:100%}                  /* el scroll horizontal vive dentro de la tabla, no en la pagina */
.row.wrap{row-gap:8px}

/* Barra segmentada / tabs: si no caben, se acomodan en filas parejas en vez de cortarse */
@media(max-width:560px){
  .segbar{flex-wrap:wrap}
  .segbar button{flex:1 1 30%;min-width:86px}
}

/* Tablas: un punto mas compactas en pantallas chicas (el ancho extra scrollea adentro) */
@media(max-width:600px){
  table.data{font-size:12.5px}
  table.data th,table.data td{padding:7px 8px}
  .kpi b{font-size:22px}
}

/* Escritorio: las pantallas de columna unica (hoy/perfil) no deben quedar como un hilo
   perdido junto al sidebar de 248px; se ensanchan a un panel comodo y centrado. */
@media(min-width:900px){
  .wrap:not(.wide){max-width:660px}
}

/* Foco visible tambien en la navegacion lateral (accesibilidad por teclado) */
.as-link:focus-visible{outline:3px solid var(--foco);outline-offset:-2px}

/* Spinner reutilizable dentro de un boton mientras carga */
.btn.loading{pointer-events:none}
.btn .spin{display:none}
.btn.loading .spin{display:inline-block}

/* Skeleton / estado de carga y de error para listas y tablas */
.loadbox{display:flex;flex-direction:column;gap:10px;padding:6px 0}
.skel{height:56px;border-radius:12px;background:linear-gradient(90deg,#eef1f6 25%,#e3e8f0 37%,#eef1f6 63%);
  background-size:400% 100%;animation:sk 1.2s ease infinite}
@keyframes sk{0%{background-position:100% 0}100%{background-position:0 0}}
/* CHIP DEL PERMISO POR HORAS dentro de una celda de la planilla. Va en BLOQUE y no en linea:
   un dia puede llevar varios permisos, y en fila la columna «Trab.» pasaba de 141 a 556px y
   doblaba el desborde horizontal de la tabla (medido a 1180px). Apilados, la columna la marca el
   chip mas largo y no la suma de todos. */
.novchip.permh{display:block;margin-top:2px;font-weight:600;font-size:11px;white-space:nowrap}

/* AVISO AZUL, compartido. Vivia solo en calendario.html y desde hr-v90 lo usa tambien la planilla
   para explicar un permiso por horas: una regla copiada en dos pantallas es como se desincronizan.
   NO usa --blue sobre --blue-soft. Medido el 1-sep-2026 sobre los valores reales: el texto daba
   4.06 en claro y AA pide 4.5 (12px en negrita 600 NO es texto grande), y el fondo 1.15 sobre la
   tarjeta, por debajo del 1.20 que esta app se fijo. Se reusan los tokens de la pastilla
   «recibido»: texto 5.64/5.95 y fondo 1.20/1.36. Sin tokens nuevos. */
.avisoazul{background:var(--st-recibido);color:var(--sti-recibido);border-radius:10px;padding:8px 10px;
  font-size:12px;font-weight:600;display:flex;gap:7px;align-items:flex-start}
.errbox{text-align:center;color:var(--danger);padding:22px 16px}
.errbox .btn{max-width:220px;margin:12px auto 0}
@media(prefers-reduced-motion:reduce){ .skel,.spin{animation:none} }

/* ============================================================================================
   REDISEÑO 2026-08 · tokens de texto, tema oscuro y barra inferior de pestañas.
   Va al final a proposito: estas reglas ganan sobre las de arriba sin tener que reescribirlas.
   - Tamaño de letra: html[data-letra="grande"] (Mi perfil > Apariencia).
   - Tema: html[data-tema="oscuro"] | "claro" | ausente = sigue al sistema.
   - Barra inferior: solo <=900px; en escritorio manda la barra lateral de ui.js.
   ============================================================================================ */
:root{
  --f-xs:11px; --f-sm:12px; --f-md:13px; --f-base:14px; --f-lg:16px; --f-xl:20px; --f-2xl:26px;
  --tap:44px;                       /* alto minimo de cualquier cosa que se toca */
  --tabbar-h:58px;
}
html[data-letra="grande"]{
  --f-xs:12px; --f-sm:13px; --f-md:14.5px; --f-base:15.5px; --f-lg:17.5px; --f-xl:22px; --f-2xl:29px;
  --tap:48px;
}
html[data-letra="grande"] body{font-size:var(--f-base)}
html[data-letra="grande"] .muted,
html[data-letra="grande"] table.data{font-size:var(--f-md)}
html[data-letra="grande"] .card h3{font-size:var(--f-lg)}

/* ---- Iconos (js/icons.js): heredan color y se alinean con el texto ---- */
.ico{display:inline-block;vertical-align:-.18em;flex:none}
/* Los tres tamanos del armazon salen de aqui, no de cada llamada a _ic(): un solo sitio para
   cambiarlos. El trazo sigue siendo 1.7 (js/icons.js). */
.appside .as-link .ico{width:var(--ico-nav);height:var(--ico-nav)}
.hdr .ico{width:var(--ico-hdr);height:var(--ico-hdr)}
.tabbar a .ico{width:var(--ico-tab);height:var(--ico-tab)}
.ico-btn{display:inline-flex;align-items:center;justify-content:center;min-width:var(--tap);
  min-height:var(--tap);border:none;background:none;color:inherit;cursor:pointer;padding:0}

/* ---- Tema oscuro: se redefinen SOLO las variables; los componentes no cambian ---- */
html[data-tema="oscuro"]{
  --bg:#0B1420; --card:#152A3D; --ink:#EAF1F8; --ink-soft:#9FB3C8; --muted:#9FB3C8; --line:#24435E;
  --green:#6D9E27; --green-press:#5B8420; --green-ink:#A9D46B; --green-soft:#1B3320;
  --lime:#97C459; --soft:#7F95AD;
  --blue:#4E9BDE; --blue-soft:#152F45; --gold:#D89A1E; --gold-soft:#33270D; --gold-ink:#FAC775;
  --link:#7FBCEF; --danger:#E86A62; --red:#E86A62; --ok:#A9D46B;
  --foco:#7FBCEF;                    /* 7.2 sobre la superficie del armazon en oscuro */
  --gold-tinta:#2B1F00;              /* 6.59 sobre --gold en oscuro */
  --navy:#122334; --red-soft:#3A1A1A;
  --tab-on:#22432c;          /* en oscuro hace falta mas separacion: 1.33 contra la barra */
  --st-borrador:#24435E; --sti-borrador:#EAF1F8;   /* 1.43 · texto 9.04 */
  --st-enviado:#4B3A14;  --sti-enviado:#FAC775;    /* 1.34 · texto 7.05 */
  --st-aprobado:#294328; --sti-aprobado:#A9D46B;   /* 1.35 · texto 6.39 */
  --st-recibido:#224058; --sti-recibido:#8FC6F5;   /* 1.35 · texto 5.95 */
  --st-devuelto:#593231; --sti-devuelto:#F2A9A3;   /* 1.35 · texto 5.70 */
  --ph:#7F95AD;              /* 4.76 sobre --card */
  --rej-cebra:#10202F;       /* 1.13 sobre --card */
  /* En oscuro el dorado de siempre (#33270D) medía 1.00 contra la tarjeta: invisible. 1.33. */
  --rej-fest:#4A3A10;        /* 1.33 sobre --card; el numero encima, 9.68 */
  --cal-fest:#4A3A10;        /* en oscuro el de siempre ya llega: 1.33 sobre --card */
  /* Banda de novedad en oscuro. Mismos criterios y mismas mediciones que en claro (ver el bloque
     de :root): 5.38 el peor contraste sobre un relleno, dE 16.6 la peor pareja entre bandas. */
  --nov-vacaciones:#8FC6F5;      /* 5.67 min */
  --nov-incapacidad:#F2A9A3;     /* 5.38 min */
  --nov-permiso:#FAC775;         /* 6.61 min */
  --nov-licencia:#A9D46B;        /* 6.04 min */
  --nov-ausentismo:#BCBEC2;      /* 5.53 min · gris neutro (con #9FB3C8 daba dE 9.5 vs vacaciones) */
  --nov-compensatorio:#5FD3CB;   /* 5.72 min · teal */
  /* En oscuro el armazon claro es la superficie de TARJETA, no el fondo: mismo criterio que en
     claro, un escalon por encima del contenido y separado por linea. */
  --nav:#152A3D; --nav-hdr:#152A3D;
  --nav-linea:#24435E;
  --nav-ink:#EAF1F8;                 /* 12.9 */
  --nav-ink-soft:#9FB3C8;            /* 6.8 */
  --nav-hover:rgba(255,255,255,.07);
  --nav-on-bg:var(--tab-on); --nav-on-ink:#A9D46B;          /* 8.0 sobre el tinte */
  --nav-on-bar:#97C459;
  --hdr-ink:#EAF1F8; --hdr-ink-soft:#9FB3C8;                /* 12.9 / 6.8 */
  --hdr-btn:#0F2233; --hdr-btn-bd:#24435E; --hdr-btn-hover:#1B3A52;
  --nav-sombra:0 1px 3px rgba(0,0,0,.35);
  --shadow:0 1px 2px rgba(0,0,0,.35),0 4px 14px rgba(0,0,0,.30);
  --shadow-lg:0 8px 26px rgba(0,0,0,.45);
  color-scheme:dark;
}
/* Superficies internas que estaban en gris claro fijo dentro de los componentes */
html[data-tema="oscuro"] .segbar,
html[data-tema="oscuro"] .segmini{background:#0F2233}
html[data-tema="oscuro"] .segbar button.on,
html[data-tema="oscuro"] .segmini button.on{background:#24435E;color:var(--ink)}
html[data-tema="oscuro"] .chip{background:var(--card);border-color:var(--line);color:var(--ink)}
html[data-tema="oscuro"] .chip.on{background:var(--lime);border-color:var(--lime);color:#0B1420}
html[data-tema="oscuro"] .modal .box{background:var(--card);color:var(--ink)}
html[data-tema="oscuro"] .modal-x{background:#24435E;color:var(--ink)}
html[data-tema="oscuro"] .btn.ghost{background:var(--card);color:var(--ink);border-color:var(--line)}
html[data-tema="oscuro"] .pill.borrador{background:#24435E;color:var(--ink)}
html[data-tema="oscuro"] .pill.enviado{background:#3A2C0A;color:#FAC775}
html[data-tema="oscuro"] .pill.aprobado{background:#1B3320;color:#A9D46B}
html[data-tema="oscuro"] .pill.recibido{background:#152F45;color:#8FC6F5}
html[data-tema="oscuro"] .pill.fuera{background:#3A1A1A;color:#F2A9A3}
html[data-tema="oscuro"] .skel{background:linear-gradient(90deg,#152A3D 25%,#1D3A52 37%,#152A3D 63%)}
html[data-tema="oscuro"] input,html[data-tema="oscuro"] select,html[data-tema="oscuro"] textarea{
  background:#0F2233;color:var(--ink);border-color:var(--line)}
/* El texto de ejemplo solo tenia color en el tema OSCURO: en claro se quedaba con el gris del
   navegador (#757575), que no es token y por tanto ningun tema puede cambiarlo. Ahora sale de --ph
   en los dos: 4.71 en claro y 4.76 en oscuro sobre la tarjeta, medidos en el DOM. */
input::placeholder,textarea::placeholder{color:var(--ph)}

/* ---- Toques minimos (accesibilidad en obra, con guantes) ---- */
.chip{min-height:calc(var(--tap) - 4px);display:inline-flex;align-items:center}
.hbtn{min-height:40px}
.segbar button{min-height:38px}
.segmini button{min-height:32px}

/* ---- Barra inferior de pestanas (solo movil/tablet angosta) ---- */
.tabbar{position:fixed;left:0;right:0;bottom:0;z-index:45;display:none;
  background:var(--card);border-top:1px solid var(--line);
  padding-bottom:env(safe-area-inset-bottom);box-shadow:0 -2px 14px rgba(15,35,64,.10)}
.tabbar a{flex:1;min-width:0;display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:3px;min-height:var(--tabbar-h);padding:6px 2px 5px;color:var(--ink-soft);text-decoration:none;
  font-size:var(--f-xs);font-weight:600;position:relative;-webkit-tap-highlight-color:transparent}
.tabbar a .tlbl{max-width:100%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;line-height:1.1}
/* DONDE ESTAS: linea de color en el borde de arriba + fondo apenas tintado. Marca la columna
   completa, asi que se ve de reojo y con la pantalla al sol. Ni un pixel cambia de tamano: el
   `inset` del box-shadow no ocupa espacio (y meter algo que crezca dentro de la barra fue justo lo
   que rompio el scroll en hr-v22). Antes solo cambiaba el color del texto y no se distinguia. */
.tabbar a.on{color:var(--green-ink);background:var(--tab-on);box-shadow:inset 0 3px 0 var(--green)}
.tabbar a:active{background:var(--bg)}
.tabbar a.on:active{background:var(--green-soft)}
.tabbar .tbadge{position:absolute;top:5px;left:50%;margin-left:4px;background:var(--gold);color:var(--gold-tinta);
  font-size:10.5px;font-weight:800;line-height:16px;min-width:16px;padding:0 4px;border-radius:999px;text-align:center}
@media(max-width:899.98px){
  .tabbar{display:flex}
  body.app-shell{padding-bottom:calc(var(--tabbar-h) + env(safe-area-inset-bottom))}
  .hamb{display:none}                       /* el cajon lateral ya no hace falta: manda la barra */
  .hdr .hbtn-danger{display:none}           /* Salir vive en la hoja "Mas", no junto a la campana */
  .toast{bottom:calc(var(--tabbar-h) + 16px + env(safe-area-inset-bottom))}
}
@media(min-width:900px){ .tabbar{display:none} }

/* ---- Hoja "Mas" y listas de opciones dentro de un modal ---- */
.sheet-grp{font-size:var(--f-xs);font-weight:800;letter-spacing:.06em;text-transform:uppercase;
  color:var(--ink-soft);margin:14px 2px 4px}
.sheet-link{display:flex;align-items:center;gap:12px;padding:12px 4px;min-height:var(--tap);
  border-bottom:1px solid var(--line);color:var(--ink);text-decoration:none;font-size:var(--f-base);font-weight:600}
.sheet-link:last-of-type{border-bottom:none}
.sheet-link .ico{color:var(--ink-soft)}
.sheet-link .sarr{margin-left:auto;color:var(--soft)}
.sheet-link:active{background:var(--bg)}

/* Puntos de estado: reemplazan los emojis de color (vigente / por vencer / terminada). */
.dot{display:inline-block;width:9px;height:9px;border-radius:50%;flex:none;margin-right:3px;vertical-align:baseline}
.dot-ok{background:var(--green)}
.dot-warn{background:var(--gold)}
.dot-bad{background:var(--danger)}
.dot-off{background:var(--soft)}
/* El punto de ubicacion va PEGADO a la hora que califica (entrada o salida), no delante. Es un
   BOTON porque en el telefono no hay hover: al tocarlo dice lo mismo que el `title`. Objetivo
   tactil de 30px de alto (control secundario, igual criterio que las acciones de fila) sin que el
   punto crezca ni separe la hora de lo que sigue: el area vive en el padding. */
.ubic{display:inline-flex;align-items:center;justify-content:center;border:none;background:none;
  padding:0 7px;margin:0 0 0 1px;min-width:28px;min-height:22px;cursor:pointer;vertical-align:middle;
  line-height:0;flex:none;position:relative}
/* El AREA TACTIL se estira con un pseudo-elemento, no con el tamano del boton: asi el dedo tiene
   38x34 y la tarjeta NO crece ni un pixel (subir el boton a 30px de alto le costaba 9px a cada
   tarjeta). Los 5px laterales caben de sobra en el `gap:14px` de la fila de horas: no se pisan
   entre si. */
.ubic::after{content:"";position:absolute;inset:-6px -5px}
.ubic .dot{margin:0}
.ubic:focus-visible{outline:2px solid var(--link);outline-offset:1px;border-radius:6px}
@media(hover:hover){ .ubic:hover .dot{box-shadow:0 0 0 3px var(--line)} }
/* En la TABLA el punto se queda compacto (estirar la celda apretaria una tabla que ya va justa),
   pero el area tactil se estira igual: hay tablets que ven la tabla. */
table.data .ubic{min-height:20px;min-width:0;padding:0 3px}
table.data .ubic::after{inset:-7px -8px}

/* ---- Densidad compacta (Mi perfil > Apariencia; solo tiene efecto en pantallas anchas) ----
   Lleva !important a proposito: es una preferencia de la persona y tiene que ganarle al padding
   propio de cada pantalla (la planilla y pendientes definen el suyo). */
@media(min-width:900px){
  html[data-densidad="compacta"] .card{padding:9px 11px!important;margin-bottom:8px!important}
  html[data-densidad="compacta"] table.data th,
  html[data-densidad="compacta"] table.data td{padding:5px 8px!important}
  html[data-densidad="compacta"] table.data{font-size:12.5px}
  html[data-densidad="compacta"] .kpi{padding:8px 10px!important}
  html[data-densidad="compacta"] .kpi b{font-size:20px}
  html[data-densidad="compacta"] .item{padding:8px 0!important}
}

/* ---- Resumen dentro del header (periodo y totales de la pantalla). Nunca compite con el título:
        desaparece por debajo de 1100px y ahí lo muestra la barra de la propia pantalla. ---- */
.hstats{display:none;gap:14px;align-items:baseline;white-space:nowrap;font-size:var(--f-sm);
  color:var(--hdr-ink-soft);overflow:hidden;flex:0 1 auto;min-width:0}
.hstats b{color:var(--hdr-ink);font-weight:700;font-size:var(--f-base)}
.hstats span{display:inline-flex;gap:5px;align-items:baseline}
@media(min-width:1101px){ .hstats{display:flex} }
/* La regla de arriba mide la VENTANA, y el encabezado no vive en la ventana: con el menú lateral
   desplegado le faltan 248px. A 1280px el título de la planilla se quedaba en la letra "P" con los
   totales al lado, que es justo lo que el comentario dice que no debe pasar. El umbral se corre
   1101 + 248 = 1349px mientras el menú esté desplegado. */
@media(min-width:900px) and (max-width:1348px){
  body.app-shell:not(.nav-colapsado) .hstats{display:none}
  /* Y la barra lo RECOGE justo cuando el encabezado lo suelta. Sin esta gemela habia una franja
     (1101-1348px con el menu desplegado, o sea una ventana de 1280 en su estado por defecto) donde
     el resumen no se veia en NINGUNO de los dos sitios: el encabezado ya lo habia soltado y la
     barra creia que sobraba. Gana por especificidad al .barmini{display:none} de mas abajo. */
  body.app-shell:not(.nav-colapsado) .barmini{display:flex}
}

/* La X de las hojas y modales: 40px para que se pueda tocar con el pulgar (antes 32). */
.modal-x{width:40px;height:40px;top:10px;right:10px}

/* ============================================================================================
   BARRA DE FILTROS COMPARTIDA (planilla, pendientes, novedades) - rediseño 2026-08-19
   Una sola fila: buscador que crece + chips deslizables + "Filtros (n)" + acciones en iconos.
   En <=700px la fila se parte y los iconos se recogen en el botón "⋯".
   Y las hojas de filtros de móvil: lista con lo que tiene puesto cada filtro + subpantallas.
   ============================================================================================ */
/* `top:0`, no `top:var(--hdr-h)`. El header NO se queda pegado: `.hdr` es sticky pero vive dentro
   del envoltorio `<div id="hdr">`, que mide exactamente lo que mide el header, asi que sticky no
   tiene ni un pixel de recorrido y se va con el scroll (medido: al bajar 800px el header esta en
   -586). Con `top:60px` la barra quedaba flotando 60px por debajo del borde y por esa franja pasaba
   el contenido por detras. Pegada arriba no cuesta espacio y no deja franja. --hdr-h se sigue
   midiendo en ui.js; si algun dia se decide que el header SI se quede, se vuelve a usar aqui. */
.barra{position:sticky;top:0;z-index:8;background:var(--bg);padding:7px 0 6px;margin:0 0 6px}
.barfila{display:flex;align-items:center;gap:6px;min-width:0}
.barbusca{flex:1 1 170px;min-width:104px;display:flex;align-items:center;gap:6px;background:var(--card);
  border:1px solid var(--line);border-radius:999px;height:36px;padding:0 6px 0 11px;color:var(--ink-soft)}
.barbusca input{flex:1;min-width:0;border:none;background:none;height:34px;min-height:0;padding:0;
  font-size:var(--f-sm);color:var(--ink)}
.barbusca input:focus{outline:none;box-shadow:none;border:none}
.barbusca input::-webkit-search-cancel-button{display:none}
.qx{border:none;background:none;color:var(--ink-soft);cursor:pointer;width:26px;height:26px;border-radius:50%;
  display:flex;align-items:center;justify-content:center;flex:none}
/* La fila de chips se DESLIZA cuando no caben (pasa en el celular en cuanto hay 5). Sin la
   sombra del borde derecho no se notaba que hubiera mas: "Con extras" simplemente no existia.
   `mask` se degrada solo: donde no esta soportado se ve la fila entera, como antes. */
.barchips{display:flex;gap:5px;flex:0 1 auto;min-width:0;overflow-x:auto;scrollbar-width:none;
  -webkit-overflow-scrolling:touch;scroll-snap-type:x proximity;
  -webkit-mask-image:linear-gradient(to right,#000 calc(100% - 22px),transparent);
  mask-image:linear-gradient(to right,#000 calc(100% - 22px),transparent)}
.barchips::-webkit-scrollbar{display:none}
.barchips .pchip2{scroll-snap-align:start}
/* Sin desbordamiento no hay nada que insinuar: la mascara se quita cuando todo cabe. */
.barchips:not(.hay-mas){-webkit-mask-image:none;mask-image:none}
.pchip2{flex:none;display:inline-flex;align-items:center;gap:5px;border:1px solid var(--line);background:var(--card);
  color:var(--ink);border-radius:999px;padding:7px 12px;font-size:var(--f-xs);white-space:nowrap;cursor:pointer;min-height:36px}
.pchip2.on{background:var(--navy);color:#fff;border-color:var(--navy)}
.pchip2.apl{background:#E7ECF5;border-color:#C7D0E0;cursor:default}
html[data-tema="oscuro"] .pchip2.apl{background:#1B3A52;border-color:#24435E}
.pchip2 b{font-weight:700}
.xchip{border:none;background:none;color:inherit;cursor:pointer;padding:0 0 0 2px;display:inline-flex;align-items:center}
/* El boton de accion principal DENTRO de la barra (p.ej. "Novedad"): .btn nace a lo ancho y con
   52px de alto, y aqui tiene que ser de su tamano. Iba en un style= en linea, que le gana a
   cualquier regla y ya habia mordido cuatro veces en admin.html. */
.barfila .btn.sm{width:auto;flex:none;height:36px}
.btnfil{flex:none;display:inline-flex;align-items:center;gap:5px;height:36px;padding:0 12px;border-radius:999px;
  border:1px solid var(--ink);background:var(--card);color:var(--ink);font-size:var(--f-sm);font-weight:600;cursor:pointer;white-space:nowrap}
.btnfil b{background:var(--green);color:#fff;border-radius:999px;padding:0 6px;font-size:var(--f-xs)}
.icbtn{flex:none;width:36px;height:36px;border:1px solid var(--line);background:var(--card);color:var(--ink);
  border-radius:999px;display:flex;align-items:center;justify-content:center;cursor:pointer}
.segvista{flex:none;display:inline-flex;background:#e7eaf0;border-radius:999px;padding:2px;gap:2px}
html[data-tema="oscuro"] .segvista{background:#0F2233}
.segvista button{border:none;background:none;color:var(--ink-soft);padding:0 9px;min-height:32px;border-radius:999px;
  cursor:pointer;display:inline-flex;align-items:center}
.segvista button.on{background:var(--card);color:var(--ink);box-shadow:var(--shadow)}
.barmini{display:flex;gap:12px;flex-wrap:wrap;align-items:baseline;margin-top:6px;font-size:var(--f-xs);color:var(--ink-soft)}
.barmini b{color:var(--ink);font-size:var(--f-sm)}
.barmini .mper{color:var(--ink)}
.barmini .mq{color:var(--gold-ink)}
.masacc{display:none}
@media(max-width:899.98px){                       /* con barra de pestañas abajo se toca con el dedo */
  .segvista button{min-height:38px;padding:0 12px}
  .chip2[role=button]{padding:7px 11px}        /* los atajos "ver solo esto" también se tocan */
}
@media(max-width:700px){
  .barfila{flex-wrap:wrap}
  .barfila .icbtn{display:none}
  .barfila .icbtn.masacc{display:flex}
  .segvista{display:none}
  /* El buscador se REPARTE lo que sobra, no reclama la fila entera.
     Con `flex-basis:auto` su tamano base es el del <input>, que es ancho por defecto, y flexbox
     corta las lineas ANTES de repartir: en Novedades (buscador + Filtros + "Novedad" + "...")
     eso mandaba el "..." solo a un renglon y la barra ocupaba CUATRO. Con una base chica los
     cuatro controles caben en uno y el buscador se queda con el resto. El `min-width` es el
     suelo: por debajo de eso si vale mas la pena que baje de linea. */
  .barbusca{flex:1 1 88px;min-width:88px}
  .barchips{order:3;flex:1 0 100%;margin-top:6px}
}
@media(max-width:390px){
  .barfila{gap:5px}
  .btnfil .ft{display:none}
  .btnfil{padding:0 10px}
}
@media(min-width:1101px){ .barmini{display:none} }

/* ---- Hojas de filtros en móvil: lista + subpantallas ---- */
.flt-lista{margin:2px -2px 0}
.flt-row{display:flex;align-items:center;gap:11px;padding:13px 4px;min-height:52px;
  border-bottom:1px solid var(--line);color:var(--ink);text-decoration:none;font-size:var(--f-base)}
.flt-row:last-child{border-bottom:none}
.flt-row:active{background:var(--bg)}
.flt-row .ico{color:var(--ink-soft);flex:none}
.flt-t{flex:none}
.flt-v{margin-left:auto;color:var(--ink-soft);font-size:var(--f-sm);text-align:right;
  max-width:52%;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.flt-v.set{color:var(--green-ink);font-weight:700}
.flt-sw{display:flex;align-items:center;gap:10px;padding:13px 4px;min-height:52px;
  border-top:1px solid var(--line);font-size:var(--f-base);font-weight:600}
.flt-sw input{width:24px;height:24px;min-height:0;flex:none}
.flt-cab{display:flex;align-items:center;gap:10px;margin:0 0 10px}
.flt-cab b{font-size:var(--f-lg)}
.flt-atras{width:38px;height:38px;border:1px solid var(--line);background:var(--card);color:var(--ink);
  border-radius:11px;display:flex;align-items:center;justify-content:center;cursor:pointer;flex:none}
.flt-ops{display:grid;grid-template-columns:1fr 1fr;gap:8px}
.flt-ops.col{display:flex;flex-direction:column;gap:6px}
.flt-op{display:flex;align-items:center;gap:9px;text-align:left;min-height:48px;padding:9px 12px;
  border:1px solid var(--line);background:var(--card);color:var(--ink);border-radius:12px;
  font-size:var(--f-base);cursor:pointer;width:100%}
.flt-op.on{border-color:var(--green);background:var(--green-soft);color:var(--green-ink);font-weight:700}
.flt-op .flt-sub{color:var(--ink-soft);font-size:var(--f-xs);font-weight:400}
.flt-grp{font-size:var(--f-xs);color:var(--ink-soft);letter-spacing:.05em;text-transform:uppercase;margin:14px 0 6px}
#fltQ{margin-bottom:8px}
/* ---- Pie de la hoja: la accion principal manda ----
   Iba con `.row` y un `flex:1.5` suelto en el boton de aplicar. En un flex, `.btn` trae
   `width:100%`, asi que "Limpiar" arrancaba con una base del ancho ENTERO y solo encogia, mientras
   que `flex:1.5` (= `1.5 1 0%`) le daba a "Aplicar filtros" base CERO: el boton importante quedaba
   estrujado y con el nombre partido en dos renglones. Con base 0 en los dos y el reparto por
   `flex-grow`, aplicar ocupa el doble que limpiar y ninguno se parte. */
.flt-pie{display:flex;gap:10px;margin-top:14px}
.flt-pie .btn{flex:1 1 0;width:auto;min-width:0;white-space:nowrap;padding:0 10px}
.flt-pie .btn.principal{flex:2 1 0}
@media(max-width:359.98px){ .flt-pie .btn{font-size:var(--f-base)} }
.flt-aviso{color:var(--danger);font-size:var(--f-sm);margin:8px 0 0;min-height:18px}

/* ---- Hoja de filtros en dos columnas (pantallas anchas): lista a la izquierda, opciones del
        filtro elegido a la derecha. Aprovecha el ancho y nada queda flotando encima. ---- */
/* El panel de la campana. La caja por defecto (460) deja 424 px de interior y los tres botones
   de accion piden 434 medidos: "Borrar todas" se iba a un segundo renglon en CUALQUIER pantalla,
   por grande que fuera, y los asuntos (433 px el mas largo, a 14 px) se partian en dos. Con este
   ancho el interior es 604 en escritorio: una sola fila de botones y el asunto en un renglon.
   Crece con la ventana hasta el tope y por debajo de ~680 px manda el 94vw, asi que en el movil
   sigue siendo la hoja de siempre. */
.modal .box.notis{max-width:min(94vw,640px)}
.modal .box.hoja-filtros.ancha{max-width:780px}
.modal .box.hoja-filtros.angosta{max-width:520px}
.flt-2col{display:grid;grid-template-columns:minmax(0,268px) minmax(0,1fr);gap:14px;align-items:start}
.flt-izq{min-width:0}
.flt-der{min-width:0;border-left:1px solid var(--line);padding-left:14px;min-height:280px}
.flt-2col .flt-row{padding:11px 4px;min-height:46px;font-size:var(--f-sm)}
.flt-2col .flt-row.act{background:var(--bg);border-radius:9px}
.flt-2col .flt-v{max-width:46%}
.flt-der .flt-ops{max-height:46vh;overflow:auto}
.flt-der .flt-op{min-height:42px;font-size:var(--f-sm);padding:7px 11px}
.flt-der .flt-cab{align-items:center}
@media(max-width:879px){ .flt-2col{display:block} .flt-der{display:none} }
.flt-ops{max-height:52vh;overflow:auto}

/* ---------- Tirador de ancho ------------------------------------------------------------------
   La manija que se arrastra para ensanchar una columna o un panel (Informes y Administrador).
   Medido: a 55% de opacidad daba 2.34 de contraste en el tema claro, por debajo del 3.0 que
   necesita un control para verse; va a color pleno y delgado para no gritar. */
.grip{position:absolute;top:0;right:0;width:8px;height:100%;cursor:col-resize;touch-action:none;
  display:flex;align-items:center;justify-content:center;z-index:5}
.grip::before{content:"";width:2px;height:56%;background:var(--ink-soft);border-radius:2px}
.grip:hover::before,.grip.on::before{background:var(--green);width:3px}

/* ---------------------------------------------------------------- RUEDA DE HORA (.ruedas/.rueda)
   Elegir la hora sin escribirla: dos columnas con scroll-snap, hora 00-23 y minuto de 5 en 5.
   Vive aqui y no en hoy.html porque el panel del calendario es el siguiente que la necesita --ahi
   estan las 503 marcas que se registran dias despues-- y copiarla es como acabo la barra superior.

   Por que ES NUESTRA y no `<input type="time">`: el nativo se pinta con el idioma del NAVEGADOR, asi
   que el campo que guarda 19:30 se lee "07:30 p. m." (medido en Chromium; `lang` no lo cambia). Con
   20:00 como la entrada MAS frecuente de la app --101 marcas-- eso es una puerta a equivocarse en 12
   horas. Misma razon por la que existe `campoHora()` en ui.js.

   Medido sobre las 727 marcas de produccion: `:00` y `:30` son el 87%, los cuartos el 92%, y de 5 en
   5 se cubren 725 de 727 (solo dos, a las :49, quedan fuera; para esas esta el modo de escribir).

   Cada valor mide --tap de alto, asi que tocar uno que ya se ve es un blanco legitimo. TRES a la
   vista y no cinco: 44*3 = 132 de columna, 150 el bloque, en vez de 213. */
[hidden]{display:none!important}      /* `.stepper` es display:flex y le ganaba al atributo */
.ruedas{display:flex;gap:10px;align-items:stretch;justify-content:center;position:relative;
  border:1px solid var(--line);border-radius:14px;background:var(--card);padding:8px 10px}
/* La banda del centro dice DONDE se elige y NO se mueve con el arrastre. Va detras de los numeros
   (`pointer-events:none`) para no robarles el toque. Es --tab-on, el mismo "aqui estas" del resto de
   la app: 1.20 sobre la tarjeta en claro y 1.33 en oscuro, ya medidos. */
.ruedas::before{content:"";position:absolute;left:8px;right:8px;top:50%;height:var(--tap);
  transform:translateY(-50%);background:var(--tab-on);border-radius:10px;pointer-events:none}
.rueda{flex:1 1 0;max-width:130px;height:calc(var(--tap) * 3);overflow-y:auto;position:relative;
  z-index:1;scroll-snap-type:y mandatory;padding:var(--tap) 0;cursor:grab;touch-action:pan-y;
  scrollbar-width:none;-ms-overflow-style:none}
.rueda::-webkit-scrollbar{display:none}
.rueda:focus-visible{outline:3px solid var(--foco);outline-offset:2px;border-radius:10px}
.rueda .v{height:var(--tap);display:flex;align-items:center;justify-content:center;
  scroll-snap-align:center;font-size:20px;font-weight:700;font-variant-numeric:tabular-nums;
  color:var(--ink-soft);line-height:1;cursor:pointer;user-select:none}
/* El elegido a 30px: el numero grande de esta pantalla media 34 y se lee con sol y de lejos; bajarlo
   a 20 seria perder eso a cambio de la rueda. Sobre --tab-on, --green-ink mide 6.51/6.46. */
.rueda .v.on{font-size:30px;font-weight:800;color:var(--green-ink)}
.ruedas .sep{align-self:center;font-size:26px;font-weight:800;color:var(--ink-soft);
  position:relative;z-index:1}
.rlabs{display:flex;gap:10px;margin-bottom:5px}
.rlabs span{flex:1;text-align:center;font-size:var(--f-xs);font-weight:800;color:var(--muted);
  text-transform:uppercase;letter-spacing:.05em}
/* El enlace que cambia de rueda a escribir. Es un <button>, no un <a href="#">: no navega a ningun
   sitio, y un enlace que no lleva a una direccion es mentira para quien usa lector de pantalla.
   Area tocable de --tap con `::after` para no engordar la linea de texto (regla de la app). */
.lnkhora{background:none;border:0;padding:0;font:inherit;font-weight:700;color:var(--link);
  cursor:pointer;position:relative;text-decoration:underline}
.lnkhora::after{content:"";position:absolute;left:-8px;right:-8px;top:50%;height:var(--tap);
  transform:translateY(-50%)}
.lnkhora:focus-visible{outline:3px solid var(--foco);outline-offset:3px;border-radius:4px}

/* ------------------------------------------------------------------- CUADRO DE FIRMA (.firmapad)
   Lo pintan DOS pantallas con el mismo `firmaHTML()` de js/firma.js: el primer ingreso, donde la
   firma es obligatoria, y Mi perfil, donde se reemplaza. Estaba escrito a mano dentro de
   perfil.html con estilos en linea, que es como se desincronizan las cosas en este proyecto.

   El lienzo es BLANCO en los dos temas y no sale de un token: no es color de interfaz, es el papel.
   Esta firma se estampa en la hoja de firmas IMPRESA (planilla_pdf.html), asi que se dibuja sobre
   lo mismo sobre lo que va a salir; y la tinta es fija por lo mismo (una firma clara en tema oscuro
   se imprimiria en blanco sobre blanco). El borde SI es token, que es interfaz. */
/* El borde NO va con --line: el papel es blanco y en tema claro la tarjeta tambien, asi que el
   recuadro medido daba 1.00 de relleno y 1.24 de borde -o sea, no se veia donde hay que firmar-.
   Con --ink-soft mide 5.98 en claro y 4.32 contra el papel en oscuro, por encima del 3.0 que esta
   app le exige a un elemento grafico. Es el unico borde discontinuo grueso de la app, y dice lo
   que tiene que decir: firma DENTRO de aqui. */
.firmapad .lienzo{border:2px dashed var(--ink-soft);border-radius:12px;background:#fff}
.firmapad canvas{width:100%;display:block;border-radius:12px;
  touch-action:none;                /* sin esto el dedo hace scroll en vez de firmar */
  cursor:crosshair;
  /* Alto FIJO, no una proporcion. Con `width:100%` sobre un lienzo de 440x150, a 320 px quedaban 87
     px de alto para firmar con el dedo; y en escritorio se iba a 203. 150 es el alto con el que se
     diseno, y js/firma.js iguala el lienzo interno al tamano en pantalla, asi que no deforma. */
  height:150px}
.firmaacc{display:flex;gap:8px;flex-wrap:wrap;margin-top:8px}
/* "Subir imagen" es un <label> que envuelve un <input type=file> escondido: sin esto hereda el
   `width:100%` de .btn y se lleva el renglon entero (la trampa de .row wrap de hr-v84). */
.firmaacc .btn{width:auto;flex:0 0 auto}
.firmasubir{cursor:pointer;margin:0}
.firmasubir input[type=file]{display:none}
.firmaprev{margin-top:10px}
.firmaprev img{max-width:220px;border:1px solid var(--line);border-radius:8px;background:#fff}
