/* ═══ SIDEBAR COMPARTIDO — fuente única para todas las páginas del portal ═══
   No copiar/pegar este bloque en páginas nuevas — enlazar este archivo:
   <link rel="stylesheet" href="/portal/portal-sidebar.css">
   <script src="/portal/portal-sidebar.js"></script>
   Ver [[project_portal_sidebar_unificado]] en el vault para el porqué. */
.usb-sidebar{position:fixed;top:0;left:0;bottom:0;width:15rem;transition:width .18s ease,padding .18s ease;background:var(--superficie);border-right:1px solid var(--linea);display:flex;flex-direction:column;padding:1.5rem 1rem;z-index:50;font-family:Inter,sans-serif}
.usb-item{display:flex;align-items:center;gap: var(--e-3);padding: var(--e-3) var(--e-4);border-radius:10px;color:var(--txt-2);font-size:.875rem;font-weight:500;transition:all .2s;cursor:pointer;text-decoration:none;border:1px solid transparent}
.usb-item:hover{background:var(--acento-tinte);color:var(--acento)}
.usb-active{background:var(--acento-tinte)!important;color:var(--acento)!important;border:1px solid var(--acento-borde)!important}
.usb-imp{display:none;height:44px;background:var(--tinte-alerta);border-bottom:1px solid var(--alerta);backdrop-filter:blur(12px);-webkit-backdrop-filter:blur(12px);padding:0 24px;align-items:center;gap: var(--e-3);font-size:13px;color:var(--alerta);position:fixed;top:0;left:15rem;right:0;z-index:49;font-family:Inter,sans-serif}
.usb-imp.visible{display:flex}
.usb-imp-label{display:flex;align-items:center;gap: var(--e-2);min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.usb-imp-label .material-icons-outlined{font-size:18px;color:var(--alerta);flex-shrink:0}
.usb-imp-label strong{color:var(--acento-txt, #fff);font-weight:600}
.usb-imp-fullword{display:inline}
.usb-back{margin-left:auto;flex-shrink:0;display:inline-flex;align-items:center;gap: var(--e-2);padding: var(--e-2) var(--e-3);background:var(--tinte-alerta);border:1px solid var(--alerta);color:var(--alerta);border-radius:8px;font-size:12px;font-weight:600;cursor:pointer;white-space:nowrap}
.usb-back:hover{background:var(--tinte-alerta)}
/* Reserva el espacio de la barra para que no tape títulos ni el sidebar/header.
   `--usb-imp-h` expone ese offset a las páginas: cualquier layout de alto completo
   debe usar `calc(100vh - var(--usb-imp-h))` en vez de `100vh` pelado, porque el
   padding del body desplaza el contenido y un 100vh se sale por abajo justo esos
   44px (le pasaba a la barra de escribir de la bandeja, quedaba fuera de pantalla). */
:root{--usb-imp-h:0px}
body.usb-imp-on{padding-top: 44px;--usb-imp-h:44px}
/* El sidebar es position:fixed de alto completo. Sin esto, cuando hay más items que
   alto de pantalla, los de abajo (ej. Admin) quedan inalcanzables: el scroll de la
   página no mueve un elemento fixed. Scrollea el <nav>, dejando logo arriba y
   usuario/sesión abajo siempre visibles. `min-height:0` es obligatorio para que un
   hijo flex con flex:1 pueda encogerse y activar su propio scroll. */
.usb-sidebar > nav{flex:1 1 auto;min-height:0;overflow-y:auto;overflow-x:hidden;overscroll-behavior:contain;scrollbar-width:thin;scrollbar-color:var(--linea-fuerte) transparent}
.usb-sidebar > nav::-webkit-scrollbar{width:4px}
.usb-sidebar > nav::-webkit-scrollbar-track{background:transparent}
.usb-sidebar > nav::-webkit-scrollbar-thumb{background:var(--linea-fuerte);border-radius:99px}
.usb-sidebar > nav:hover::-webkit-scrollbar-thumb{background:var(--txt-3)}
@media(max-width:768px){.usb-sidebar{display:none}}
/* Suprime cualquier sidebar legado que quede en alguna página vieja */
aside.sidebar, aside.w-64 { display: none !important; }

/* Evita el "zoom" inicial en móvil: si algún elemento se pasa del ancho del viewport,
   el navegador reduce la escala inicial para que quepa. Bloqueamos ese desborde acá. */
html, body { overflow-x: hidden; max-width: 100vw; }

/* ── Header + menú móvil (< 768px) ── */
.usb-mobile-header{display:none}
.usb-mobile-menu{display:none}
@media(max-width:768px){
  /* El <body> de casi todas las páginas es `class="... flex"` (fila horizontal).
     En escritorio no importa porque .usb-sidebar es position:fixed (fuera del flujo)
     y queda un solo hijo en el flex. Pero el header/menú móvil SÍ son hijos normales,
     así que sin esto quedan en fila junto al contenido en vez de apilarse arriba. */
  body{flex-direction:column !important}
  .usb-mobile-header{display:flex;align-items:center;justify-content:space-between;padding: var(--e-3) var(--e-4);position:sticky;top:0;z-index:50;background:var(--superficie);backdrop-filter:blur(12px);border-bottom:1px solid var(--linea);width:100%}
  .usb-mobile-menu{display:block;width:100%;max-height:0;overflow:hidden;transition:max-height .25s ease;background:var(--superficie);border-bottom:1px solid var(--linea)}
  .usb-mobile-menu.open{max-height:80vh;overflow-y:auto}
  .usb-imp{left:0 !important;padding:0 12px}
  .usb-imp .usb-imp-fullword{display:none}
  .usb-imp .usb-back span.usb-back-label{display:none}
  /* Con la barra de «vista de cliente» arriba (fixed, 44px) el header móvil no
     puede seguir siendo sticky: son dos elementos apilados y el segundo, con
     top:44 igual a su posición natural, se «pega» desde el reposo, se sale del
     flujo y deja que el título de la página suba detrás de él y quede cortado.
     Pasa a estático: ocupa su espacio y el contenido nunca se tapa. Al scrollear
     se va con la página, que en la vista de cliente —una revisión, no la
     operación diaria— es aceptable. Sin imp, el header sigue sticky. */
  body.usb-imp-on .usb-mobile-header{position:static}
}

/* ── Sidebar retráctil (modo íconos) ─────────────────────────────────────
   Lo activa el usuario con el botón del pie del sidebar y la preferencia queda en
   localStorage (`portal_sidebar_compacto`). La clase `.usb-compact` la escribe un
   script del <head> sobre <html> antes de pintar, para que al recargar no se vea el
   sidebar ancho un instante y luego salte a 64px.
   Todo queda gateado bajo `.usb-sidebar` (el nodo desktop, oculto <768px por la regla
   de arriba) para no filtrarse al `.usb-mobile-menu`, que reusa `.usb-item` con las
   mismas clases pero debe seguir mostrando el label completo en el hamburger móvil. */
.usb-compact .usb-sidebar { width:64px; padding:1.5rem 0.5rem; }
.usb-compact .usb-sidebar .usb-item { justify-content:center; gap:0; padding: var(--e-3) var(--e-2); }
.usb-compact .usb-sidebar .usb-item .usb-item-label { display:none; }
/* El botón "Personalizar" es un <button class="usb-item"> con texto suelto (sin span
   .usb-item-label, porque no pasa por buildNavHtml) — se oculta aparte para no dejar
   texto descentrado en 64px. Su título ("Personalizar") ya se explica por el ícono `tune`. */
/* El `font-size:0` era el parche para un rótulo que iba suelto en el HTML. Ahora
   va envuelto en `.usb-item-label` como el de cualquier otra entrada, así que lo
   pliega la misma regla que a las demás y el parche sobra. */
/* Logo / identidad de cliente impersonado arriba del todo: a 64px solo cabe el avatar.
   `padding` necesita !important por el mismo motivo que el pie: buildSidebarInnerHtml
   pone `padding:0 8px` inline en estos dos contenedores para su layout normal. */
.usb-compact .usb-sidebar .usb-brand-logo { justify-content:center; padding:0 !important; }
/* `max-height`+`max-width` (en vez de `height` fijo) porque no se conoce la proporción real
   del PNG acá; con `width:auto;height:auto` el navegador escala manteniendo el aspect ratio
   y nunca desborda los ~48px útiles del sidebar en 64px (64px - 2×0.5rem de padding). */
.usb-compact .usb-sidebar .usb-brand-logo img { max-height:28px; max-width:100%; width:auto; height:auto; }
/* Plegado solo cabe el símbolo; el nombre vuelve al desplegar. */
.usb-compact .usb-sidebar .usb-brand-nombre { display:none; }
.usb-compact .usb-sidebar .usb-brand-imp { justify-content:center; padding:0 !important; }
.usb-compact .usb-sidebar .usb-brand-imp-text { display:none; }
/* Pie (timer de sesión, avatar + nombre/email, cerrar sesión): colapsa a solo avatar +
   botón de logout apilados y centrados. No toca `.usb-sidebar > nav`, así que el
   scroll obligatorio del <nav> (ver arriba) sigue intacto.
   `!important` en las tres reglas: buildSidebarInnerHtml (portal-sidebar.js) pone
   `display/gap/padding` de estos nodos como estilo inline (por su layout normal, sin
   pensar en el modo compacto), y un inline style sin !important le gana a cualquier
   regla de hoja de estilos aunque no sea important — así que sin !important acá esto
   queda invisible en pantalla pero sin efecto real. */
.usb-compact .usb-sidebar .usb-perfil-fila { justify-content:center; }
.usb-compact .usb-sidebar .usb-perfil-nombre { display:none; }
/* Barra de impersonación: normalmente empieza en `left:15rem` (ancho del sidebar normal);
   en modo compacto el sidebar mide 64px, así que hay que correrla para no dejar un hueco. */
.usb-compact .usb-imp { left:64px; }
@media(max-width:768px){
  /* A este ancho el sidebar desktop ya está oculto (regla de arriba) y el menú móvil
     manda; el modo compacto no debe tocar la barra de impersonación en mobile, que ya
     tiene su propio `left:0 !important` bajo este breakpoint. */
  .usb-compact .usb-imp { left:0; }
}
/* Offset del contenido: las páginas normales usan la utilidad de Tailwind `md:ml-60`
   (240px, ancho del sidebar normal) sobre su contenedor raíz. En modo compacto el
   sidebar mide 64px, así que ese contenedor necesita 64px en vez de 240px. Se resuelve
   acá (no editando el markup de inbox.html) para que quede autocontenido en la clase
   de opt-in. `!important` porque compite con la utilidad `md:ml-60` inyectada por el
   CDN de Tailwind, cuya regla también vive bajo `min-width:768px`. `.inbox-wrap` es
   específico de inbox.html — hoy la única página con `.usb-compact` — así que no
   hace falta un nombre de clase más genérico. */
@media (min-width:768px){
  .usb-compact .inbox-wrap { margin-left: var(--e-8) !important; }
  /* `.md\:ml-60` es la clase escapada de Tailwind que llevan los contenedores raíz
     del resto de las páginas. Con esto el modo compacto funciona en todas sin tocar
     el markup de ninguna. */
  .usb-compact .md\:ml-60 { margin-left: var(--e-8) !important; }
  .md\:ml-60 { transition:margin-left .18s ease; }
}

/* Botón de plegar / desplegar, al pie del sidebar. */
.usb-toggle{display:flex;align-items:center;gap: var(--e-3);width:100%;background:none;border:none;cursor:pointer;color:var(--txt-3);font-family:inherit;font-size:12px;padding: var(--e-2) var(--e-2);border-radius:8px;transition:color .15s,background .15s}
.usb-toggle:hover{color:var(--txt-2);background:var(--superficie-2)}
.usb-toggle .material-icons-outlined{font-size:18px;transition:transform .18s ease}
.usb-compact .usb-toggle{justify-content:center;padding: var(--e-2) 0}
.usb-compact .usb-toggle .usb-toggle-label{display:none}
.usb-compact .usb-toggle .material-icons-outlined{transform:rotate(180deg)}
@media(max-width:768px){.usb-toggle{display:none}}

/* ── Fix inputs ilegibles (Fase 0.1) ──
   El CDN de Tailwind carga el plugin `forms` DESPUÉS de nuestros estilos
   inline/de página, así que sus reglas (fondo blanco, texto oscuro) ganan
   sobre `.input-field` aunque estén definidas antes en el HTML. Resultado:
   inputs blancos con texto claro → ilegibles. Se arregla una sola vez acá
   porque las 8 páginas del portal ya cargan este archivo, en vez de
   parchar calendario.html, reservas.html, cabanas.html y login.html por
   separado (y volver a olvidarlo en la próxima página nueva). */
.input-field, input.input-field, select.input-field, textarea.input-field {
  background: var(--superficie-2) !important;
  border: 1px solid var(--linea-fuerte) !important;
  color: var(--txt) !important;
}
.input-field::placeholder { color: var(--txt-3) !important; }
.input-field:focus {
  border-color: var(--acento) !important;
  box-shadow: 0 0 0 3px var(--acento-tinte) !important;
  outline: none !important;
}

/* ── El foco del teclado dentro de la barra ──────────────────────────────────
   El anillo global de `portal-theme.css` no llegaba acá y los ítems del menú
   se quedaban con el anillo por defecto del navegador: 1.5px del color del
   texto, casi invisible sobre el hover. Se declara acá, en la hoja de la
   barra, con la especificidad suficiente para ganar en su propio terreno. */
.usb-sidebar a:focus-visible,
.usb-sidebar button:focus-visible,
.usb-mobile-menu a:focus-visible,
.usb-mobile-menu button:focus-visible,
.usb-mobile-header button:focus-visible {
  outline: 2px solid var(--acento) !important;
  outline-offset: -2px !important;
  border-radius: var(--r-sm);
}

/* El plugin `forms` también deja el ícono nativo del datepicker/selector
   en negro sobre nuestro fondo oscuro, invisible. `color-scheme: dark`
   le pide al navegador que dibuje esos controles nativos (ícono de
   calendario, panel del datepicker, flecha del select) en su variante
   clara-sobre-oscura. Selector amplio para cubrir tanto `.input-field`
   como cualquier input de fecha suelto que aparezca en el portal. */
.input-field[type="date"],
.input-field[type="datetime-local"],
input[type="date"],
input[type="datetime-local"],
select.input-field,
select {
  color-scheme: dark;
}

/* Red de seguridad: todo el portal es tema oscuro, así que cualquier campo de
   texto que se haya olvidado de llevar `.input-field` (pasó con #resSearch en
   reservas.html: fondo blanco + texto claro = escribías y no se veía nada)
   también tiene que ser legible. Se excluyen checkbox/radio/botones/file porque
   tienen su propio tratamiento (ej. `.vp-check-item` en admin.html). */
input:not([type="checkbox"]):not([type="radio"]):not([type="submit"]):not([type="button"]):not([type="file"]):not([type="range"]):not([type="color"]),
select,
textarea {
  background: var(--superficie-2) !important;
  border: 1px solid var(--linea-fuerte) !important;
  color: var(--txt) !important;
}
input::placeholder, textarea::placeholder { color: var(--txt-3) !important; }


/* ── Pie del sidebar: perfil en un menú emergente ─────────────────────────
   Antes el pie eran tres filas (reloj de sesión, avatar con nombre y correo, y
   botón de salir) y se comía unos 90px de alto en todas las páginas. Ahora es
   una sola fila con el avatar; el resto aparece al tocarlo. Funciona igual con
   el sidebar plegado, donde solo cabe el avatar. */
.usb-foot{margin-top:auto;padding-top:.75rem;border-top:1px solid var(--superficie-2)}
.usb-perfil-fila{display:flex;align-items:center;gap: var(--e-3);padding: var(--e-1) 0}
.usb-avatar{width:32px;height:32px;border-radius:50%;background:var(--acento-borde);display:flex;align-items:center;justify-content:center;color:var(--acento);font-size:14px;font-weight:700;flex-shrink:0;border:none;cursor:pointer;font-family:inherit;transition:background .15s,box-shadow .15s}
.usb-avatar:hover{background:var(--acento-borde);box-shadow:0 0 0 3px var(--acento-tinte)}
.usb-perfil-nombre{font-size:13px;color:var(--txt-2);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;min-width:0}

.usb-perfil-menu{position:fixed;z-index:9999;min-width:210px;background:var(--superficie-2);border:1px solid var(--superficie-3);border-radius:12px;padding: var(--e-4);box-shadow:0 16px 44px rgba(0,0,0,.34);font-family:Inter,sans-serif}
.usb-perfil-menu[hidden]{display:none}
.usb-perfil-n{margin:0;font-size:14px;font-weight:600;color:var(--txt);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.usb-perfil-e{margin: var(--e-1) 0 0;font-size:12px;color:var(--txt-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis}
.usb-perfil-t{margin: var(--e-3) 0 0;display:flex;align-items:center;gap: var(--e-2);font-size:11px;color:var(--txt-3)}
.usb-perfil-salir{margin-top: var(--e-3);width:100%;display:flex;align-items:center;justify-content:center;gap: var(--e-2);background:var(--superficie-2);border:none;border-radius:8px;padding: var(--e-2);color:var(--txt-2);font-size:13px;font-weight:600;font-family:inherit;cursor:pointer;transition:background .15s,color .15s}
.usb-perfil-salir:hover{background:var(--tinte-critico);color:var(--critico)}
/* ── Nova: la barra lateral es una lista, no una torre de cajas ──────────── */
.usb-sidebar{
  background:var(--superficie)!important;
  border-right:1px solid var(--linea)!important;
  padding:24px 12px!important;
}
.usb-item{
  height:34px!important;padding:0 12px!important;border-radius:8px!important;
  font-size:14px!important;font-weight:500!important;color:var(--txt-2)!important;
  gap:8px!important;
}
.usb-item:hover{background:var(--superficie-2)!important;color:var(--txt)!important}
.usb-item.active, .usb-item[aria-current]{
  background:var(--superficie-2)!important;color:var(--txt)!important;font-weight:600!important;
}
.usb-item .material-icons-outlined,.usb-item .material-icons{font-size:18px!important}

/* El grupo del cliente se separa con una etiqueta, no con una caja. */
.usb-grupo,.usb-section{
  font-size:10.5px!important;font-weight:600!important;letter-spacing:.12em!important;
  text-transform:uppercase!important;color:var(--txt-3)!important;
  padding:20px 12px 8px!important;
}

.usb-foot{border-top:1px solid var(--linea)!important;padding-top:16px!important;margin-top:auto}
.usb-toggle,.usb-perfil-fila{border-radius:8px!important}
.usb-toggle:hover,.usb-perfil-fila:hover{background:var(--superficie-2)!important}
.usb-avatar{
  background:var(--superficie-2)!important;border:1px solid var(--linea)!important;
  color:var(--txt-2)!important;font-weight:600!important;
}
.usb-perfil-menu{
  background:var(--superficie)!important;border:1px solid var(--linea)!important;
  border-radius:12px!important;box-shadow:0 12px 32px rgba(26,25,23,.10)!important;
}
.usb-perfil-salir{color:var(--critico)!important}
.usb-perfil-salir:hover{background:var(--tinte-critico)!important}

/* ── Arreglos del 21-08, vistos en el iPad de Juan ───────────────────────

   1. El contenido ya no ensancha la página. Los body del portal son flex, y
      un item flex sin min-width usa su min-content como piso: el gantt de
      Ocupación (160px + 31 columnas fijas) empujaba TODO el contenedor a
      1152px+ y la página entera scrolleaba de lado, cortando la cabecera.
      Con min-width:0 el ancho lo manda el viewport y lo ancho scrollea
      dentro de su propio contenedor, que es donde tiene overflow-x:auto. */
body > .flex-1 { min-width: 0; }

/* 2. El selector de negocio no tenía versión compacta: quedaba a ancho
      completo aplastado dentro de los 64px. Plegado queda solo el avatar,
      y el menú se abre en fixed al costado para no quedar preso del ancho
      del sidebar. Los !important compiten con estilos inline que pone
      buildSidebarInnerHtml para el layout normal. */
.usb-compact .usb-sidebar .usb-neg-toggle { justify-content:center; padding:6px !important; }
.usb-compact .usb-sidebar .usb-neg-toggle > span:nth-child(2),
.usb-compact .usb-sidebar .usb-neg-toggle > .material-icons-outlined { display:none; }
.usb-compact .usb-sidebar .usb-neg-menu {
  position:fixed !important; left:70px !important; right:auto !important;
  top:72px !important; width:232px;
}

/* 3. dashboard.html no usa md:ml-60: tiene su propio .lienzo con margen
      fijo de 240px, así que al plegar el sidebar quedaba un hueco de
      176px (la foto del iPad de Juan). Mismo trato que las demás. */
@media (min-width:768px){
  .usb-compact .lienzo { margin-left: var(--e-8) !important; }
  .lienzo { transition:margin-left .18s ease; }
}
