:root { --brand: #1f6f5c; --brand-dark: #185a4a; }
.bg-brand { background: var(--brand); }
.btn-brand { background: var(--brand); border-color: var(--brand); color: #fff; }
.btn-brand:hover, .btn-brand:focus { background: var(--brand-dark); border-color: var(--brand-dark); color: #fff; }
.table td, .table th { vertical-align: middle; }
.table-nowrap td, .table-nowrap th { white-space: nowrap; }
.voided td { text-decoration: line-through; color: var(--bs-secondary-color); }
.stat { font-size: 1.75rem; font-weight: 600; line-height: 1.1; }

/* Logo */
.nav-logo { height: 36px; width: 36px; border-radius: 50%; object-fit: cover; background: #fff; }
.login-logo { width: 140px; height: 140px; border-radius: 50%; object-fit: cover; }

/* Kiosco */
.kiosk-logo { position: fixed; top: .75rem; left: .75rem; width: 64px; height: 64px; border-radius: 50%;
              object-fit: cover; background: #fff; z-index: 5; }
.kiosk-btn { font-size: 2rem; font-weight: 700; padding: 1.5rem; border-radius: 1rem; color: #fff; border: 0; }
.kiosk-btn-in { background: #198754; }
.kiosk-btn-out { background: #0d6efd; }
.kiosk-btn:disabled { background: #3a4a45; color: #8a9a95; opacity: 1; }
.kiosk-btn:disabled::before { content: "🔒 "; }
.kiosk { background: #0f1f1a; color: #fff; min-height: 100vh; min-height: 100dvh; overflow: hidden; }
.kiosk-wrap { min-height: 100vh; min-height: 100dvh; display: flex; flex-direction: column; align-items: center;
              justify-content: center; padding: 1rem; gap: 1rem; text-align: center; }
.kiosk-clock { font-size: 3rem; font-weight: 600; font-variant-numeric: tabular-nums; line-height: 1; }
#reader { width: min(92vw, 420px); border-radius: 1rem; overflow: hidden; background: #000; }
#reader video { object-fit: cover; }
.kiosk-result { position: fixed; inset: 0; display: none; flex-direction: column; align-items: center;
                justify-content: center; padding: 2rem; text-align: center; font-size: 2rem; font-weight: 600; z-index: 10; }
.kiosk-result.show { display: flex; }
.kiosk-result.in { background: #198754; }
.kiosk-result.out { background: #0d6efd; }
.kiosk-result.error { background: #b02a37; }
.kiosk-result .icon { font-size: 5rem; line-height: 1; margin-bottom: 1rem; }
.pin-pad { display: grid; grid-template-columns: repeat(3, 5rem); gap: .75rem; justify-content: center; }
.pin-pad button { height: 5rem; font-size: 2rem; border-radius: 1rem; }
.pin-dots { font-size: 2.5rem; letter-spacing: 1rem; min-height: 3rem; }

@media print {
  .no-print { display: none !important; }
  body { background: #fff !important; }
}

/* ------------------------------------------------------------------ Resumen */
.stat-card { transition: transform .15s ease, box-shadow .15s ease; color: inherit; }
a.stat-card:hover { transform: translateY(-2px); box-shadow: 0 .5rem 1rem rgba(0,0,0,.08); }
.stat-alert { border-color: #f0ad4e; background: #fff8ec; }
.hours-bar { height: .6rem; border-radius: 1rem; background: var(--bs-secondary-bg); overflow: hidden; }
.hours-bar-fill { height: 100%; border-radius: 1rem; background: var(--brand); display: flex; justify-content: flex-end; }
.hours-bar-extra { height: 100%; background: #f0ad4e; }
.legend-extra { display: inline-block; width: .8rem; height: .5rem; border-radius: 1rem; background: #f0ad4e; }
.live-dot { display: inline-block; width: .55rem; height: .55rem; border-radius: 50%; background: #20c997;
            margin-right: .5rem; box-shadow: 0 0 0 0 rgba(32,201,151,.6); animation: live 2s infinite; }
@keyframes live { 70% { box-shadow: 0 0 0 .45rem rgba(32,201,151,0); } 100% { box-shadow: 0 0 0 0 rgba(32,201,151,0); } }

/* ------------------------------------------------------------------ Scroll nativo (sin JS)
 * animation-timeline: view() / scroll(). Solo en navegadores que lo soportan y sin
 * «reducir movimiento»; en el resto todo se ve igual pero sin animar. */
.scroll-progress { position: fixed; top: 0; left: 0; right: 0; height: 3px; z-index: 1080;
                   background: var(--brand); transform-origin: 0 50%; transform: scaleX(0); pointer-events: none;
                   display: none; }
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: scroll()) {
    .scroll-progress { display: block; animation: grow-x linear both; animation-timeline: scroll(root); }
    @keyframes grow-x { to { transform: scaleX(1); } }
  }
  @supports (animation-timeline: view()) {
    .reveal { animation: reveal-up linear both; animation-timeline: view(); animation-range: entry 0% cover 22%; }
    @keyframes reveal-up { from { opacity: 0; transform: translateY(1.5rem) scale(.98); } }
  }
  .live-dot { animation: live 2s infinite; }
}
@media (prefers-reduced-motion: reduce) {
  .live-dot { animation: none; }
  .stat-card { transition: none; }
}

/* Portal en móvil: tabla compacta que cabe en 360px */
.portal-table td, .portal-table th { padding: .5rem .4rem; }
.portal-table td:first-child, .portal-table th:first-child { padding-left: .75rem; }
.portal-table td:last-child, .portal-table th:last-child { padding-right: .75rem; }
@media (max-width: 400px) {
  .portal-table { font-size: .875rem; }
  .portal-table .badge { font-size: .65em; }
  .portal-table td, .portal-table th { padding: .45rem .3rem; }
  .portal-table .btn-sm { padding: .2rem .45rem; }
}

/* ------------------------------------------------------------------ Calendario de turnos */
.cal { display: grid; grid-template-columns: repeat(7, minmax(0, 1fr)); gap: 1px;
       background: var(--bs-border-color); border: 1px solid var(--bs-border-color); border-radius: .5rem; overflow: hidden; }
.cal-head { display: contents; }
.cal-head > div { background: var(--bs-tertiary-bg); padding: .4rem; text-align: center; font-size: .8rem;
                  font-weight: 600; text-transform: capitalize; color: var(--bs-secondary-color); }
.cal-day { background: var(--bs-body-bg); min-height: 7rem; padding: .35rem; display: flex; flex-direction: column; gap: .25rem;
           scroll-margin-top: 5rem; }
.cal-day.is-out { background: var(--bs-tertiary-bg); }
.cal-day.is-out .cal-num { color: var(--bs-secondary-color); }
.cal-date { display: flex; align-items: center; gap: .35rem; }
.cal-dow { display: none; text-transform: capitalize; }
.cal-num { font-weight: 600; font-size: .9rem; width: 1.7rem; height: 1.7rem; display: inline-grid; place-items: center; border-radius: 50%; }
.is-today .cal-num { background: var(--brand); color: #fff; }
.cal-add { margin-left: auto; border: 0; background: transparent; color: var(--bs-secondary-color); width: 1.7rem; height: 1.7rem;
           border-radius: 50%; font-size: 1.1rem; line-height: 1; opacity: 0; transition: opacity .15s, background .15s; }
.cal-day:hover .cal-add, .cal-add:focus-visible { opacity: 1; }
.cal-add:hover { background: var(--bs-secondary-bg); color: var(--bs-body-color); }
.chip { display: block; width: 100%; text-align: left; border: 0; border-radius: .35rem; padding: .2rem .4rem;
        background: var(--c); color: var(--ink); font-size: .78rem; line-height: 1.25; overflow: hidden; text-overflow: ellipsis;
        white-space: nowrap; }
button.chip { cursor: pointer; transition: transform .1s, box-shadow .1s; }
button.chip:hover { transform: translateY(-1px); box-shadow: 0 .15rem .4rem rgba(0,0,0,.2); }
.cal-legend { display: flex; flex-wrap: wrap; gap: .4rem; }
.legend-item { border: 1px solid var(--bs-border-color); background: var(--bs-body-bg); border-radius: 2rem; padding: .25rem .7rem;
               font-size: .875rem; display: inline-flex; align-items: center; gap: .4rem; }
.legend-item.is-on { border-color: var(--c, var(--brand)); box-shadow: inset 0 0 0 1px var(--c, var(--brand)); font-weight: 600; }
.legend-dot { width: .7rem; height: .7rem; border-radius: 50%; background: var(--c); }
.emp-picker { display: flex; flex-wrap: wrap; gap: .4rem; }
.emp-pick { border: 2px solid var(--c); color: var(--bs-body-color); border-radius: 2rem; padding: .3rem .8rem; }
.btn-check:checked + .emp-pick { background: var(--c); color: var(--ink); }
.btn-check:focus-visible + .emp-pick { box-shadow: 0 0 0 .2rem rgba(31,111,92,.35); }

/* Móvil: lista de días en vez de cuadrícula */
@media (max-width: 767.98px) {
  .cal { display: block; border: 0; background: transparent; }
  .cal-head { display: none; }
  .cal-day { min-height: 0; border: 1px solid var(--bs-border-color); border-radius: .5rem; margin-bottom: .4rem; padding: .5rem .6rem; }
  .cal-day.is-out.is-empty { display: none; }
  .cal-day.is-out .cal-add { display: none; }
  .cal:not(.cal-edit) .cal-day.is-empty { display: none; }
  .cal-edit .cal-day.is-empty { padding: .25rem .6rem; }
  .cal-dow { display: inline; font-size: .85rem; color: var(--bs-secondary-color); }
  .cal-date { order: -1; }
  .cal-add { opacity: 1; }
  .chip { font-size: .9rem; padding: .35rem .6rem; white-space: normal; }
}
.next-shift { border-left: .35rem solid var(--c); color: inherit; }

/* Estado del turno frente a los fichajes */
.chip-status { display: inline-grid; place-items: center; min-width: 1.15rem; height: 1.15rem; border-radius: 50%;
               font-size: .7rem; font-weight: 700; margin-right: .3rem; background: #fff; color: #333; vertical-align: -.1rem; }
.st-ok { color: #198754; } .st-late, .st-late_early { color: #b35c00; } .st-early { color: #6f42c1; }
.st-working { color: #20c997; } .st-missing { background: #ffc107; color: #000; }
.st-absent { background: #dc3545; color: #fff; } .st-no_out { color: #dc3545; }

/* Kiosco: aviso de conexión */
.kiosk-net { position: fixed; top: .9rem; right: .9rem; left: 5.5rem; z-index: 6; text-align: center;
             border-radius: 2rem; padding: .45rem .9rem; font-size: .95rem; font-weight: 600; }
.kiosk-net.is-offline { background: #ffc107; color: #000; }
.kiosk-net.is-sending { background: #0dcaf0; color: #000; }

/* ================================================================== FX: interacciones */

/* ---- Barra superior: se esconde al bajar, se ve al subir */
.navbar { position: sticky; top: 0; z-index: 1030; transition: transform .3s ease, box-shadow .3s ease; }
.navbar.is-hidden { transform: translateY(-100%); }
.navbar.is-scrolled { box-shadow: 0 .4rem 1.2rem rgba(0,0,0,.18); }

/* ---- Onda al pulsar */
.btn, .legend-item, .fx-ripple { position: relative; overflow: hidden; }
.ripple { position: absolute; border-radius: 50%; pointer-events: none; background: currentColor; opacity: .25;
          transform: scale(0); animation: ripple .55s ease-out forwards; }
@keyframes ripple { to { transform: scale(1); opacity: 0; } }
.btn-brand:not(.btn-sm), .fx-magnetic { transition: transform .25s cubic-bezier(.2,.8,.2,1), background .15s; }

/* ---- Tarjetas 3D con foco de luz que sigue al cursor */
.fx-tilt { transition: transform .35s cubic-bezier(.2,.8,.2,1), box-shadow .2s; transform-style: preserve-3d; will-change: transform; }
.fx-tilt:hover { box-shadow: 0 1rem 2rem rgba(0,0,0,.1); }
.fx-tilt, .fx-spot { position: relative; isolation: isolate; }
.fx-tilt::after, .fx-spot::after { content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none;
  background: radial-gradient(260px circle at var(--mx, 50%) var(--my, 50%), rgba(31,111,92,.13), transparent 60%);
  opacity: 0; transition: opacity .25s; z-index: -1; }
.fx-tilt:hover::after, .fx-spot:hover::after { opacity: 1; }

/* ---- Avisos flotantes */
.toast-stack { position: fixed; top: 4.5rem; right: 1rem; z-index: 1090; display: flex; flex-direction: column; gap: .5rem;
               width: min(24rem, calc(100vw - 2rem)); pointer-events: none; }
.fx-toast { pointer-events: auto; position: relative; overflow: hidden; display: flex; align-items: flex-start; gap: .5rem;
  padding: .8rem 2.2rem .9rem 1rem; border-radius: .75rem; background: var(--bs-body-bg); color: var(--bs-body-color);
  box-shadow: 0 .8rem 2rem rgba(0,0,0,.16); border-left: .35rem solid var(--tc, var(--brand));
  transform: translateX(110%); opacity: 0; transition: transform .35s cubic-bezier(.2,.9,.2,1.1), opacity .3s; touch-action: pan-y; }
.fx-toast.is-in { transform: none; opacity: 1; }
.fx-toast.is-out { transform: translateX(110%); opacity: 0; }
.fx-toast.is-drag { transition: none; cursor: grabbing; }
.fx-toast.is-success { --tc: #198754; } .fx-toast.is-danger { --tc: #dc3545; }
.fx-toast.is-warning { --tc: #f0ad4e; } .fx-toast.is-info { --tc: #0dcaf0; }
.fx-toast-x { position: absolute; top: .35rem; right: .5rem; border: 0; background: none; font-size: 1.3rem; line-height: 1;
              color: var(--bs-secondary-color); }
.fx-toast-bar { position: absolute; left: 0; bottom: 0; height: 3px; width: 100%; background: var(--tc, var(--brand));
                transform-origin: left; animation: toast-bar var(--ms) linear forwards; }
.fx-toast.is-paused .fx-toast-bar { animation-play-state: paused; }
@keyframes toast-bar { to { transform: scaleX(0); } }

/* ---- Volver arriba con anillo de progreso */
.fx-top { position: fixed; right: 1rem; bottom: 1rem; z-index: 1040; width: 44px; height: 44px; border: 0; border-radius: 50%;
          background: var(--bs-body-bg); box-shadow: 0 .4rem 1rem rgba(0,0,0,.18); display: grid; place-items: center;
          opacity: 0; transform: translateY(1rem) scale(.8); pointer-events: none; transition: opacity .25s, transform .25s; }
.fx-top.is-visible { opacity: 1; transform: none; pointer-events: auto; }
.fx-top svg { position: absolute; inset: 0; transform: rotate(-90deg); }
.fx-top circle { fill: none; stroke-width: 3; }
.fx-top .trk { stroke: var(--bs-secondary-bg); }
.fx-top .val { stroke: var(--brand); stroke-linecap: round; transition: stroke-dashoffset .1s linear; }
.fx-top span { font-weight: 700; color: var(--brand); }

/* ---- Login: fondo vivo con los colores del logo */
.login-scene { position: fixed; inset: 0; z-index: -1; overflow: hidden; background: #fff7f3; }
.login-scene .blob { position: absolute; border-radius: 50%; filter: blur(60px); opacity: .55; transition: translate .6s cubic-bezier(.2,.8,.2,1); }
.login-scene .b1 { width: 46vmax; height: 46vmax; left: -12vmax; top: -14vmax; background: #f08a6c; animation: drift 18s ease-in-out infinite alternate; }
.login-scene .b2 { width: 38vmax; height: 38vmax; right: -10vmax; bottom: -12vmax; background: #1f6f5c; opacity: .35; animation: drift 22s ease-in-out infinite alternate-reverse; }
.login-scene .b3 { width: 24vmax; height: 24vmax; right: 18vw; top: 8vh; background: #f3a712; opacity: .3; animation: drift 15s ease-in-out infinite alternate; }
@keyframes drift { to { transform: translate(6vmax, 4vmax) scale(1.12) rotate(20deg); } }
.login-card { background: rgba(255,255,255,.78); backdrop-filter: blur(14px) saturate(1.2); -webkit-backdrop-filter: blur(14px) saturate(1.2);
              border: 1px solid rgba(255,255,255,.6); border-radius: 1.25rem; }
.login-logo { transition: transform .4s cubic-bezier(.2,.8,.2,1); box-shadow: 0 1rem 2.5rem rgba(240,138,108,.35); }
@media (prefers-reduced-motion: reduce) { .login-scene .blob { animation: none; } }

/* ---- Portal: anillo de horas */
.hours-ring { --p: 0; width: 7.5rem; height: 7.5rem; position: relative; flex: none; }
.hours-ring svg { width: 100%; height: 100%; transform: rotate(-90deg); }
.hours-ring circle { fill: none; stroke-width: 10; }
.hours-ring .trk { stroke: var(--bs-secondary-bg); }
.hours-ring .val { stroke: var(--ring, var(--brand)); stroke-linecap: round; stroke-dasharray: 327; stroke-dashoffset: 327;
                   transition: stroke-dashoffset 1.2s cubic-bezier(.2,.8,.2,1); }
.hours-ring.is-drawn .val { stroke-dashoffset: calc(327 * (1 - var(--p))); }
.hours-ring .ring-text { position: absolute; inset: 0; display: grid; place-content: center; text-align: center; line-height: 1.1; }
.hours-ring .ring-text strong { font-size: 1.4rem; }
.countdown { font-variant-numeric: tabular-nums; }

/* ---- Calendario: resaltar a una persona y arrastrar turnos */
.cal.is-hl .chip { opacity: .28; filter: saturate(.4); transition: opacity .15s, filter .15s; }
.cal.is-hl .chip.is-hl { opacity: 1; filter: none; box-shadow: 0 0 0 2px var(--bs-body-bg), 0 0 0 4px var(--c); }
.chip[draggable="true"] { cursor: grab; }
.chip.is-dragging { opacity: .35; }
.cal-day.is-drop { background: color-mix(in srgb, var(--brand) 10%, var(--bs-body-bg)); box-shadow: inset 0 0 0 2px var(--brand); }
.cal-day.is-drop.is-copy { box-shadow: inset 0 0 0 2px #f3a712; }
.chip.is-new { animation: chip-pop .45s cubic-bezier(.2,1.4,.4,1); }
@keyframes chip-pop { from { transform: scale(.6); opacity: 0; } }
.chip.is-shake { animation: shake .4s; }
@keyframes shake { 20%, 60% { transform: translateX(-4px); } 40%, 80% { transform: translateX(4px); } }
.cal-hint { font-size: .8rem; }

/* ---- Kiosco: tick que se dibuja y error que tiembla (rápido, no retrasa el fichaje) */
.kiosk-check { width: 6rem; height: 6rem; margin-bottom: 1rem; }
.kiosk-check circle { fill: none; stroke: #fff; stroke-width: 4; stroke-dasharray: 166; stroke-dashoffset: 166; }
.kiosk-check path { fill: none; stroke: #fff; stroke-width: 6; stroke-linecap: round; stroke-linejoin: round;
                    stroke-dasharray: 48; stroke-dashoffset: 48; }
.kiosk-result.show .kiosk-check circle { animation: draw .45s ease-out forwards; }
.kiosk-result.show .kiosk-check path { animation: draw .3s .35s ease-out forwards; }
@keyframes draw { to { stroke-dashoffset: 0; } }
.kiosk-result.show.error .icon { animation: shake .45s; }
.kiosk-result.show #result-text { animation: pop-in .35s cubic-bezier(.2,1.3,.4,1) both; }
@keyframes pop-in { from { transform: scale(.85); opacity: 0; } }
@media (prefers-reduced-motion: reduce) {
  .kiosk-check circle, .kiosk-check path { stroke-dashoffset: 0; animation: none !important; }
  .kiosk-result.show #result-text, .kiosk-result.show.error .icon { animation: none; }
}
