/* ===========================================================
   Olimpo Láser — Panel administrativo

   Esta hoja es la del panel anterior (frontend/src/index.css del
   proyecto React), traída entera y sin retoques de gusto: el encargo
   era que el panel PHP se viera EXACTAMENTE igual que aquel, así que
   los valores no se «mejoran» al copiarlos. Si algo aquí parece raro,
   miralo dos veces antes de tocarlo: probablemente lo esté sujetando
   una pantalla que todavía no has abierto.

   Está en dos mitades:

     1. El tema original — variables, armazón y navegación móvil, con
        los nombres de clase de aquel panel (.sidebar, .menu-item,
        .content-header, .bottom-nav…). _cabecera.php y _pie.php los
        usan tal cual, así que renombrar uno aquí deja media pantalla
        sin pintar.
     2. El PUENTE del final — las clases propias del panel PHP
        (.card, .tabla, .btn, .campo…) apoyadas sobre esos mismos
        materiales. Existe porque reescribir treinta vistas para
        renombrar clases habría sido mucho más frágil que escribir
        una regla por clase aquí.

   Lo que NO se trajo: el CSS de lo que ya no existe (modales y toast
   de SweetAlert, pestañas). Ninguna vista puede provocarlos y dejarlos
   solo obligaría al siguiente a comprobarlos uno por uno. Están en
   old/panel/frontend/src/index.css si algún día hacen falta.

   La tipografía (Outfit) la carga cada plantilla con <link>, no con
   @import: un @import dentro del CSS obliga al navegador a descargar
   la hoja entera antes de enterarse de que hay otra petición que hacer.
   =========================================================== */

:root {
  --bg-base: #060708;             /* negro base (detrás del fondo animado) */
  --bg-primary: transparent;      /* fondo de la app (deja ver el fondo animado) */
  --bg-surface: rgba(12, 15, 20, 0.66);   /* sidebar / topbar / superficies (glass) */
  --bg-surface-solid: #0c0f14;    /* modales */
  --bg-card: rgba(14, 18, 24, 0.58);       /* tarjetas (glass) */

  --border-color: rgba(255, 255, 255, 0.10);
  --border-color-light: rgba(255, 255, 255, 0.06);

  --accent: #ff3d2e;              /* rojo láser Olimpo */
  --accent-hover: #ff5342;
  --accent-soft: rgba(255, 61, 46, 0.14);
  --grad: linear-gradient(100deg, #ff3d2e, #ff9d00);

  --text-main: #f5f6f8;
  --text-muted: #a2a8b4;
  --text-dark: #727884;

  --success: #3ad07e;
  --danger: #ff5b52;
  --info: #35e0ff;
  --warning: #ff9d00;

  /* --- Alias para las plantillas PHP ---
     Las vistas escriben var(--muted2) o var(--line) en atributos style. Son los
     MISMOS colores con otro nombre, definidos aquí para que exista una sola
     paleta: si mañana cambia el rojo, cambia arriba y basta. */
  --surface: var(--bg-surface);
  --surface-solid: var(--bg-surface-solid);
  --card: var(--bg-card);
  --line: var(--border-color);
  --line-soft: var(--border-color-light);
  --txt: var(--text-main);
  --muted: var(--text-muted);
  --muted2: var(--text-dark);
  --ok: var(--success);
  --warn: var(--warning);

  --radius: 16px;
  --radius-sm: 10px;
}

* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
  font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
  -webkit-font-smoothing: antialiased;
}

body {
  background: var(--bg-base);
  color: var(--text-main);
  overflow: hidden;
  height: 100vh;
  height: 100dvh;
}

a { color: inherit; text-decoration: none; }

/* ===========================================================
   Fondo de esporas: el canvas con las brasas subiendo, idéntico al del
   sitio olimpolaser.com. Fijo al viewport, detrás de todo el contenido.

   OJO CON LAS CAPAS: va en z-index POSITIVO, no negativo como en el
   panel de React. Aquel funcionaba porque solo <body> tenía fondo y el
   navegador lo propaga a la raíz, dejando el propio body transparente;
   en cuanto alguien le ponga un fondo a <html>, los hijos con z-index
   negativo desaparecen detrás de él y el canvas se vuelve invisible sin
   un solo error en consola. Ya pasó una vez. El escalonado es el mismo
   que usa el sitio (styles.css):
     0 = brasas    2 = interfaz
   =========================================================== */
.scene-bg {
  position: fixed;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 0;
  display: block;
  pointer-events: none;
  transition: opacity 0.25s ease, visibility 0.25s;
}

/* El canvas se apaga con la hoja abierta: en varias GPU de teléfono, un canvas
   bajo una capa translúcida deja fantasmas al desplazarla. */
body:has(.sheet-overlay:not([hidden])) .scene-bg {
  visibility: hidden !important;
  opacity: 0 !important;
}

/* Scrollbars oscuros y finos */
* { scrollbar-width: thin; scrollbar-color: rgba(255,255,255,.20) transparent; }
::-webkit-scrollbar { width: 8px; height: 8px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: rgba(255,255,255,.18); border-radius: 8px; }
::-webkit-scrollbar-thumb:hover { background: rgba(255,255,255,.30); }

/* ===================== Layout ===================== */
/* z-index 2: por encima del fondo y del scrim. Ver el bloque de capas. */
.app-shell { display: flex; height: 100vh; width: 100vw; position: relative; z-index: 2; }

.sidebar {
  width: 260px;
  flex-shrink: 0;
  background: var(--bg-surface);
  backdrop-filter: blur(16px) saturate(1.3);
  -webkit-backdrop-filter: blur(16px) saturate(1.3);
  border-right: 1px solid var(--border-color);
  display: flex;
  flex-direction: column;
  padding: 20px 16px;
  gap: 6px;
}
.sidebar-brand {
  display: flex; align-items: center; justify-content: center;
  padding: 6px 4px 16px; margin-bottom: 6px;
  border-bottom: 1px solid var(--border-color-light);
}

/* Avatar (usado en el menú de perfil del topbar) */
.user-avatar {
  border-radius: 50%; flex-shrink: 0; overflow: hidden;
  display: grid; place-items: center; font-weight: 800;
  background: var(--accent); color: #fff;
}
.user-avatar img { width: 100%; height: 100%; object-fit: cover; display: block; }
.user-avatar.sm { width: 32px; height: 32px; font-size: 14px; }
.user-avatar.lg { width: 48px; height: 48px; font-size: 20px; }

/* ===================== Menú de perfil (topbar) ===================== */
.user-menu { position: relative; }
.user-menu-trigger {
  display: flex; align-items: center; gap: 9px;
  background: rgba(255,255,255,.04); border: 1px solid var(--border-color);
  border-radius: 999px; padding: 4px 10px 4px 4px; cursor: pointer;
  color: var(--text-main); font-family: inherit; transition: border-color .18s, background .18s;
}
.user-menu-trigger:hover, .user-menu-trigger.open { border-color: var(--accent); background: var(--accent-soft); }
.user-menu-name { font-size: 13.5px; font-weight: 600; }
.user-menu-trigger .chev { color: var(--text-muted); display: flex; transition: transform .18s ease; }
.user-menu-trigger.open .chev { transform: rotate(180deg); }

.user-dropdown {
  position: absolute; top: calc(100% + 10px); right: 0; width: 250px; z-index: 1100;
  background: var(--bg-surface-solid); border: 1px solid var(--border-color);
  border-radius: 14px; padding: 8px; overflow: hidden;
  box-shadow: 0 18px 44px rgba(0,0,0,.5);
  animation: fadeIn .15s ease-out;
}
.user-dropdown-head { display: flex; align-items: center; gap: 12px; padding: 10px 10px 12px; }
.user-dropdown-head .ud-info { min-width: 0; }
.user-dropdown-head .name { font-size: 14px; font-weight: 700; color: var(--text-main); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-dropdown-head .role { font-size: 11px; font-weight: 700; color: var(--accent); text-transform: uppercase; letter-spacing: .04em; }
.ud-item {
  width: 100%; display: flex; align-items: center; gap: 10px;
  padding: 10px 10px; border-radius: 9px; border: none; background: transparent;
  color: var(--text-main); font-family: inherit; font-size: 13.5px; font-weight: 500;
  cursor: pointer; text-align: left; transition: background .15s;
}
.ud-item:hover { background: var(--accent-soft); }
.ud-item.danger { color: var(--danger); }
.ud-item.danger:hover { background: rgba(217,45,32,.10); }
.ud-divider { height: 1px; background: var(--border-color-light); margin: 6px 4px; }

.sidebar-menu { display: flex; flex-direction: column; gap: 4px; flex-grow: 1; overflow-y: auto; padding-top: 6px; }
.menu-item {
  display: flex; align-items: center; gap: 12px;
  padding: 11px 14px; border-radius: 11px;
  color: var(--text-muted); font-size: 14px; font-weight: 500;
  border: none; background: transparent; cursor: pointer; text-align: left; width: 100%;
  border-left: 3px solid transparent;
  transition: all .18s cubic-bezier(.4,0,.2,1);
}
.menu-item:hover { color: var(--text-main); background: var(--accent-soft); }
.menu-item.active { color: var(--text-main); background: var(--accent-soft); border-left-color: var(--accent); font-weight: 600; }
.menu-item.active .ic { color: var(--accent); }
.menu-item .ic { display: flex; align-items: center; }

.sidebar-footer { border-top: 1px solid var(--border-color-light); padding-top: 12px; display: flex; flex-direction: column; gap: 8px; }
.version-label { display: block; text-align: center; font-size: 11px; color: var(--text-muted); margin-top: 4px; letter-spacing: .3px; opacity: .7; }

.main-content {
  position: relative;
  flex-grow: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  background: var(--bg-primary);
}
.content-header {
  height: 66px; flex-shrink: 0; padding: 0 30px;
  background: var(--bg-surface); border-bottom: 1px solid var(--border-color);
  display: flex; align-items: center; justify-content: space-between; gap: 16px;
}
@media (min-width: 861px) {
  .content-header {
    backdrop-filter: blur(16px) saturate(1.3); -webkit-backdrop-filter: blur(16px) saturate(1.3);
  }
}
.content-header h1 { font-size: 19px; font-weight: 700; letter-spacing: -.01em; }
.content-body { flex-grow: 1; overflow-y: auto; padding: 26px 30px; }

/* ---- Orden de pintado de la cabecera sobre el contenido ----
   El z-index: 1100 del desplegable de perfil NO basta por sí solo, y esto cuesta
   una tarde si no está escrito: `backdrop-filter` crea un contexto de
   apilamiento, así que .content-header es una caja cerrada y el 1100 del
   desplegable solo compite con sus hermanos DENTRO de la cabecera. Fuera, la
   cabecera valía z-index auto y .content-body va después en el DOM: sus tarjetas
   —que también llevan backdrop-filter— se pintaban por encima del menú abierto.

   Se arregla ordenando los dos hermanos explícitamente. La barra inferior de
   móvil (900) y la hoja «Más» (1100) siguen por encima de la cabecera a
   propósito: son de otro nivel y tapan la pantalla entera. */
.content-header { position: relative; z-index: 20; }
.content-body   { position: relative; z-index: 1; }

.header-title { display: flex; align-items: center; min-width: 0; }
.header-status { display: flex; align-items: center; gap: 18px; }

/* Marca (logo) que reemplaza el título en móvil */
.header-brand { align-items: center; gap: 8px; color: var(--accent); font-weight: 800; font-size: 16px; letter-spacing: .04em; }

/* Indicador de conexión */
.status-indicator { display: flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-muted); }
.status-indicator .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--success); box-shadow: 0 0 10px var(--success); }
.status-indicator.offline .dot { background: var(--danger); box-shadow: 0 0 10px var(--danger); }

/* Píldora de tasa en el topbar */
.rate-pill {
  display: inline-flex; align-items: center; gap: 8px;
  background: var(--accent); color: #fff; font-weight: 700; font-size: 13.5px;
  padding: 7px 14px; border-radius: 10px;
  box-shadow: 0 4px 14px rgba(255,61,46,.32);
  white-space: nowrap;
}
.rate-pill .sep { opacity: .5; }
.rate-pill a, .rate-pill button {
  background: rgba(255,255,255,.22); color: #fff; border: none;
  width: 26px; height: 26px; border-radius: 7px; cursor: pointer;
  display: grid; place-items: center; transition: .15s; flex-shrink: 0;
}
.rate-pill a:hover, .rate-pill button:hover { background: rgba(255,255,255,.36); }

/* ===================== Componentes ===================== */
/* La tarjeta de vidrio no vive aquí sino en el puente, como `.card`: es el
   nombre que usan las vistas. Los valores son los de `.glass-card`. */

/* Inputs */
input, select, textarea {
  width: 100%;
  background: rgba(255,255,255,.04);
  border: 1px solid var(--border-color);
  border-radius: 10px;
  padding: 10px 13px;
  color: var(--text-main);
  font-size: 14px;
  transition: border-color .18s, box-shadow .18s;
  outline: none;
}
select option { background: var(--bg-surface-solid); color: var(--text-main); }
input::placeholder, textarea::placeholder { color: var(--text-dark); }
input:focus, select:focus, textarea:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
input[type="checkbox"], input[type="radio"] { width: auto; accent-color: var(--accent); }
input[type="file"] { padding: 8px 10px; font-size: 13px; }
label { display: block; font-size: 12px; font-weight: 600; color: var(--text-muted); margin-bottom: 6px; }

/* Tablas */
table { width: 100%; border-collapse: separate; border-spacing: 0; border: 1px solid var(--border-color); border-radius: 12px; overflow: hidden; }
th {
  background: #171b22; color: var(--text-muted); text-transform: uppercase;
  font-size: 11px; font-weight: 700; letter-spacing: .04em; text-align: left;
  padding: 12px 16px; border-bottom: 1px solid var(--border-color); position: sticky; top: 0; z-index: 1;
  white-space: nowrap;
}
td { padding: 13px 16px; border-bottom: 1px solid var(--border-color-light); font-size: 13.5px; color: var(--text-main); white-space: nowrap; }
tbody tr:last-child td { border-bottom: none; }
tbody tr:hover td { background: rgba(255,255,255,.04); }

/* Botones (base; los componentes definen colores) */
button { cursor: pointer; font-family: inherit; transition: filter .15s ease, transform .1s ease, background .18s ease; }
button:not(:disabled):hover { filter: brightness(0.97); }
button:not(:disabled):active { transform: scale(0.98); }
button:disabled { cursor: default; opacity: .55; }

/* Los modales (.mo/.md), los toast de SweetAlert y las tarjetas de entidad del
   panel anterior NO se portaron: aquí no hay ninguno. Cada formulario es su
   propia página y cada confirmación, un POST. Traer su CSS «por si acaso» solo
   dejaría reglas que nadie puede provocar y que el siguiente que lea esto
   tendría que ir a comprobar una por una. Están en old/ si hacen falta. */

@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

input[type="number"] { font-variant-numeric: tabular-nums; }

/* ===========================================================
   Listados en tarjetas

   La forma en que este panel enseña una lista, y no es una preferencia
   estética: una fila de tabla obliga a decidir qué columna se sacrifica
   en un teléfono, y el panel se consulta desde el taller con el móvil en
   la mano. La tarjeta apila los mismos datos y no pierde ninguno.

   Las tablas se reservan para lo que de verdad es tabular y se lee
   comparando filas: el histórico de tasas, la bitácora, los movimientos
   de un insumo. Ese era también el reparto del panel anterior.
   =========================================================== */

.card-header-flex {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 16px;
}
.card-header-flex h2 {
  font-size: 18px;
  font-weight: 700;
  color: #fff;
  display: flex;
  align-items: center;
  gap: 8px;
}
.card-header-flex h2 svg { color: var(--accent); flex-shrink: 0; }
.card-header-actions { display: flex; gap: 10px; flex-wrap: wrap; align-items: center; }

/* Botón de crear compacto en la cabecera del listado */
.btn-create-header {
  background: var(--accent);
  color: #fff;
  border: none;
  padding: 8px 16px;
  border-radius: 6px;
  font-family: inherit;
  font-weight: 600;
  font-size: 13.5px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background 0.15s, transform 0.1s ease;
}
.btn-create-header:hover { background: var(--accent-hover); color: #fff; }
.btn-create-header:active { transform: scale(0.96); }

.search-bar-container { position: relative; width: 100%; margin: 14px 0 8px; }
.search-bar-container input {
  width: 100%;
  padding: 10px 14px;
  font-size: 13.5px;
  background: rgba(255, 255, 255, 0.02);
  border: 1px solid var(--border-color);
  border-radius: 10px;
  color: var(--text-main);
  outline: none;
  transition: border-color 0.2s, box-shadow 0.2s;
}
.search-bar-container input:focus {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

.cards-list-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(290px, 1fr));
  gap: 16px;
  margin-top: 18px;
  margin-bottom: 24px;
}

.entity-card {
  background: rgba(14, 18, 24, 0.45);
  border: 1px solid var(--border-color-light);
  border-radius: 14px;
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 12px;
  transition: transform 0.15s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
.entity-card:hover {
  transform: translateY(-2px);
  border-color: var(--border-color);
  box-shadow: 0 6px 20px rgba(0, 0, 0, 0.3);
}

.entity-card-header { display: flex; justify-content: space-between; align-items: flex-start; gap: 10px; }
/* Variante en dos filas (ID + acciones arriba, título debajo). La usan los
   listados cuyo título es largo y no cabe al lado de las acciones. */
.entity-card-header--apilada { flex-direction: column; align-items: stretch; gap: 6px; }
.entity-card-header--apilada .entity-card-fila { display: flex; justify-content: space-between; align-items: center; gap: 8px; }

.entity-card-title { font-size: 15px; font-weight: 700; color: var(--text-main); line-height: 1.25; word-break: break-word; }
.entity-card-id { font-size: 11px; color: var(--text-dark); font-family: monospace; }

.entity-card-body { display: flex; flex-direction: column; gap: 6px; flex-grow: 1; }
.entity-card-info-item {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 12.5px;
  color: var(--text-muted);
  min-width: 0;
}
.entity-card-info-item svg { color: var(--text-dark); flex-shrink: 0; }
/* El valor se recorta antes que desbordar la tarjeta: un correo largo
   ensanchaba la columna entera de la rejilla. */
.entity-card-info-item > span:last-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.entity-card-info-item .rotulo { font-weight: 600; color: var(--text-dark); font-size: 11px; flex-shrink: 0; }
.entity-card-info-item .valor { color: var(--text-main); }

/* La fila de la esquina: etiqueta de estado + grupo de botones. Son dos
   contenedores y no uno porque la separación entre la etiqueta y los botones
   (6px) no es la misma que entre los dos botones (4px). */
.entity-card-acciones { display: flex; align-items: center; gap: 6px; flex-shrink: 0; }
.entity-card-botones { display: flex; gap: 4px; flex-shrink: 0; }
.entity-card-etiquetas { display: flex; gap: 6px; flex-wrap: wrap; margin-top: -4px; }

.entity-card-actions {
  display: flex;
  gap: 8px;
  justify-content: flex-end;
  border-top: 1px solid var(--border-color-light);
  padding-top: 12px;
  margin-top: auto;
}

/* Quién creó y quién tocó por última vez el registro. En la tabla era una
   columna; aquí va al pie de la tarjeta, en letra pequeña: se consulta cuando
   hay una duda, no en cada vistazo. */
.entity-card-firma {
  border-top: 1px solid var(--border-color-light);
  padding-top: 10px;
  margin-top: auto;
  color: var(--text-dark);
  font-size: 10.5px;
  line-height: 1.45;
}

/* Botones de acción mini (en la esquina de la tarjeta) */
.btn-action-edit-mini, .btn-action-delete-mini {
  background: transparent;
  padding: 5px;
  border-radius: 6px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.btn-action-edit-mini { color: var(--accent); border: 1px solid var(--border-color); }
.btn-action-edit-mini:hover { background: var(--accent-soft); border-color: var(--accent); }
.btn-action-delete-mini { color: var(--danger); border: 1px solid rgba(255, 91, 82, 0.15); }
.btn-action-delete-mini:hover { background: rgba(255, 91, 82, 0.08); border-color: var(--danger); }

/* Badges de las tarjetas */
.badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 700;
  white-space: nowrap;
}
.badge--estado { text-transform: uppercase; font-size: 10px; }
.badge--ok    { background: rgba(58, 208, 126, .12); color: var(--success); }
.badge--warn  { background: rgba(255, 157, 0, .12);  color: var(--warning); }
.badge--info  { background: rgba(53, 224, 255, .10); color: var(--info); }
.badge--error { background: rgba(255, 91, 82, .12);  color: var(--danger); }
.badge--neutro { background: rgba(255, 255, 255, .05); color: var(--text-muted); }
.badge--acento { background: rgba(255, 61, 46, .08); color: var(--accent); border: 1px solid rgba(255, 61, 46, .15); font-size: 9px; padding: 2px 6px; text-transform: uppercase; }

/* Sin resultados de búsqueda */
.lista-sin-resultados { text-align: center; padding: 40px 20px; color: var(--text-muted); font-size: 13.5px; }

.pagination-bar {
  display: flex;
  justify-content: center;
  align-items: center;
  gap: 16px;
  margin-top: 20px;
  padding-top: 12px;
  border-top: 1px solid var(--border-color-light);
}
.pagination-bar button {
  background: rgba(255, 255, 255, 0.03);
  border: 1px solid var(--border-color);
  color: var(--text-muted);
  padding: 6px 14px;
  border-radius: 8px;
  font-family: inherit;
  font-size: 12.5px;
  font-weight: 600;
  transition: background 0.15s, color 0.15s;
}
.pagination-bar button:not(:disabled):hover {
  background: var(--accent-soft);
  color: var(--text-main);
  border-color: var(--accent);
}
.pagination-bar span { font-size: 13px; color: var(--text-muted); }

/* Utilidades de visibilidad (las usa el rótulo de la paginación) */
.show-xs { display: none !important; }
@media (max-width: 480px) {
  .hide-xs { display: none !important; }
  .show-xs { display: inline !important; }
}

/* Tarjetas compactas en el teléfono */
@media (max-width: 860px) {
  .cards-list-grid {
    grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
    gap: 12px;
    margin-top: 12px;
    margin-bottom: 16px;
  }
  .entity-card { padding: 12px; gap: 8px; border-radius: 12px; }
  .entity-card-header { gap: 6px; }
  .entity-card-title { font-size: 14px; }
  .entity-card-body { gap: 4px; }
  .entity-card-info-item { font-size: 12px; gap: 6px; }
  .entity-card-actions { padding-top: 8px; margin-top: 4px; }
  .btn-create-header { padding: 5px 10px; font-size: 12px; border-radius: 5px; }
  .card-header-flex h2 { font-size: 16px; }
}

/* ===========================================================
   Navegación móvil (estilo app nativa Android): barra inferior fija +
   bottom sheet con el resto de módulos. Ocultas en escritorio.
   =========================================================== */
.mobile-only { display: none !important; }

.bottom-nav { display: none; }
.bottom-nav-btn {
  flex: 1; min-width: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  background: transparent; border: none; color: var(--text-muted);
  font-family: inherit; font-size: 10.5px; font-weight: 600;
  padding: 6px 2px; border-radius: 14px; cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  transition: color .18s ease, transform .12s ease;
  position: relative;
}
.bottom-nav-btn span { max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; line-height: 1; }
.bottom-nav-btn svg { transition: transform .18s ease; }
.bottom-nav-btn.active { color: var(--accent); }
.bottom-nav-btn.active svg { transform: translateY(-2px); }
.bottom-nav-btn.active::before {
  content: ''; position: absolute; top: 3px; width: 40px; height: 30px;
  border-radius: 12px; background: var(--accent-soft); z-index: -1;
}
.bottom-nav-btn:active { transform: scale(.92); }

/* Bottom sheet ("Más") */
.sheet-overlay {
  position: fixed; inset: 0; z-index: 1100;
  background: rgba(0,0,0,.68);
  display: flex; align-items: flex-end; animation: fadeIn .2s ease-out;
  transform: translate3d(0, 0, 0);
  backface-visibility: hidden;
}
/* En React la hoja se montaba y desmontaba; aquí está siempre en el HTML y se
   alterna con [hidden]. Lo apaga la regla global [hidden] del final. */
.sheet {
  position: relative;
  z-index: 5;
  transform: translate3d(0, 0, 0);
  backface-visibility: hidden;
  width: 100%; background: var(--bg-surface-solid);
  border-top-left-radius: 22px; border-top-right-radius: 22px;
  border-top: 1px solid var(--border-color);
  padding: 10px 18px calc(22px + env(safe-area-inset-bottom, 0px));
  box-shadow: 0 -12px 40px rgba(0,0,0,.5);
}
.sheet-handle { width: 40px; height: 4px; border-radius: 4px; background: var(--border-color); margin: 4px auto 12px; }
.sheet-header { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.sheet-header span { font-size: 15px; font-weight: 700; }
.sheet-header button { background: transparent; border: none; color: var(--text-muted); display: grid; place-items: center; padding: 6px; border-radius: 8px; cursor: pointer; }
.sheet-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 10px; }
.sheet-item {
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 7px;
  padding: 14px 6px; border-radius: 14px; cursor: pointer;
  background: rgba(255,255,255,.03); border: 1px solid var(--border-color-light);
  color: var(--text-muted); font-size: 11px; font-weight: 600; text-align: center;
  transition: background .15s, color .15s;
}
.sheet-item span { line-height: 1.1; }
.sheet-item:active { transform: scale(.95); }
.sheet-item.active { color: var(--accent); background: var(--accent-soft); border-color: transparent; }

/* Escritorio angosto: sidebar comprimida (solo iconos) */
@media (max-width: 1200px) and (min-width: 861px) {
  .sidebar { width: 72px; padding: 16px 8px; }
  .sidebar .hide-sm { display: none; }
  .menu-item { justify-content: center; padding: 12px 0; }
  .sidebar-brand svg { width: 44px !important; }
}

/* Tablet / móvil: la barra inferior toma el mando (estilo app nativa) */
@media (max-width: 860px) {
  .sidebar { display: none; }
  .mobile-only { display: flex !important; }
  .header-title h1 { display: none; }

  .app-shell { height: 100dvh; }
  .content-header {
    height: calc(60px + env(safe-area-inset-top, 0px));
    padding-top: env(safe-area-inset-top, 0px);
    padding-left: 14px;
    padding-right: 14px;
    gap: 8px;
  }
  .content-body { padding: 18px 16px; }
  .header-status .hide-sm { display: none !important; }

  .bottom-nav {
    display: flex; position: fixed; left: 0; right: 0; bottom: 0;
    height: 62px; padding: 4px 6px calc(4px + env(safe-area-inset-bottom, 0px));
    background: var(--bg-surface-solid); border-top: 1px solid var(--border-color);
    box-shadow: 0 -4px 22px rgba(0,0,0,.4); z-index: 900; gap: 2px;
  }
  .main-content { padding-bottom: calc(62px + env(safe-area-inset-bottom, 0px)); }

  /* Sin blur ni capas compuestas en móvil: en varios teléfonos el velo con
     backdrop-filter sobre el canvas producía estática. Se sustituye por un
     fondo casi opaco, que se ve igual y no le pide nada a la GPU. */
  .sheet-overlay {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    transform: none !important;
    backface-visibility: visible !important;
    background: rgba(6, 7, 8, 0.94) !important;
  }
  .sheet {
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
    transform: none !important;
    backface-visibility: visible !important;
  }

  /* Cabecera: el título de sección se oculta; damos aire a los controles */
  .header-status { gap: 8px; }
  .user-menu-trigger { padding: 3px; border-radius: 50%; }
  .rate-pill {
    font-size: 11px;
    padding: 5px 8px;
    gap: 6px;
    border-radius: 8px;
  }
  .rate-pill a, .rate-pill button {
    width: 22px;
    height: 22px;
    border-radius: 5px;
  }
}

@media (max-width: 480px) {
  .header-brand span { display: none; }
}

@media (max-width: 380px) {
  .bottom-nav-btn { font-size: 9.5px; }
  .sheet-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ===========================================================
   PUENTE — clases del panel PHP sobre los materiales de arriba

   Las vistas de este panel no usan .glass-card ni .badge: usan .card,
   .tabla, .btn, .campo, .etiqueta… Cada regla de aquí abajo viste una
   de esas clases con exactamente los mismos valores que tenía su
   equivalente en el panel anterior. Es una capa de traducción, no un
   segundo diseño: si cambias algo arriba, mira si tiene pareja aquí.
   =========================================================== */

/* ---------- Cabecera de sección ----------
   El título del módulo ya lo dice la barra superior, así que este <h1>
   funciona como el <h3> que encabezaba cada tarjeta en el panel viejo:
   más pequeño que el de arriba a propósito, para que no compitan. */
.cabecera {
  display: flex;
  justify-content: space-between;
  align-items: center;
  flex-wrap: wrap;
  gap: 12px;
  margin-bottom: 18px;
}
.cabecera h1 { font-size: 17px; font-weight: 700; color: var(--text-main); letter-spacing: -.01em; }
.cabecera__sub { color: var(--text-muted); font-size: 12.5px; margin-top: 3px; }

h1, h2, h3 { font-weight: 700; letter-spacing: -.01em; }

/* ---------- Tarjetas ---------- */
.card {
  position: relative;
  background: var(--bg-card);
  border: 1px solid var(--border-color);
  border-radius: 16px;
  padding: 22px;
  box-shadow: 0 1px 2px rgba(0,0,0,.30), 0 8px 26px rgba(0,0,0,.35);
  transition: border-color .2s, box-shadow .25s;
}
@media (min-width: 861px) {
  .card { backdrop-filter: blur(12px) saturate(1.2); -webkit-backdrop-filter: blur(12px) saturate(1.2); }
}
.card:hover { box-shadow: 0 2px 4px rgba(0,0,0,.35), 0 14px 40px rgba(0,0,0,.45); }
/* Solo las tarjetas que son un enlace marcan el borde: una tarjeta que
   reacciona al ratón pero no lleva a ningún sitio promete algo que no cumple. */
a.card:hover { border-color: rgba(255, 61, 46, .34); }

.rejilla { display: grid; gap: 20px; }
.rejilla--4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }

/* En el teléfono las tarjetas de resumen van 2x2, no en una columna de cuatro
   filas: cuatro cifras que hay que mirar de un vistazo no pueden ocupar dos
   pantallas de alto. Es lo que hacía .dashboard-summary-grid. */
@media (max-width: 860px) {
  .card { padding: 14px 12px; }
  .rejilla { gap: 12px; }
  .rejilla--4 { grid-template-columns: repeat(2, 1fr); }
  .rejilla--4 .card { padding: 14px 10px; }
  .kpi__valor { font-size: clamp(16px, 4.6vw, 20px); }
}

.kpi__label { color: var(--text-muted); font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .5px; }
.kpi__valor { font-size: 24px; font-weight: 800; color: var(--text-main); margin-top: 6px; letter-spacing: -.01em; font-variant-numeric: tabular-nums; }
.kpi__pie { color: var(--text-dark); font-size: 11.5px; margin-top: 4px; }

/* ---------- Barras de proporción ---------- */
/* El ancho lo pone el PHP en un style inline, y es lo correcto: un porcentaje
   calculado es un dato, no un estilo. Sacarlo aquí exigiría una clase por cada
   valor posible. */
.barra {
  display: flex;
  height: 8px;
  border-radius: 999px;
  overflow: hidden;
  background: rgba(255, 255, 255, .05);
}
.barra__parte { height: 100%; }
.barra__parte--ingreso { background: var(--success); }
.barra__parte--egreso  { background: var(--danger); }
.barra__leyenda {
  display: flex;
  justify-content: space-between;
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-dark);
}

/* ---------- Tablas ---------- */
/* La envoltura hace de tarjeta y la tabla va sin borde propio: si los llevaran
   los dos se ve una línea doble en las esquinas redondeadas. */
.tabla-envoltura {
  border: 1px solid var(--border-color);
  border-radius: 12px;
  overflow: hidden;
  background: var(--bg-card);
  box-shadow: 0 1px 2px rgba(0,0,0,.30), 0 8px 26px rgba(0,0,0,.35);
}
@media (min-width: 861px) {
  .tabla-envoltura { backdrop-filter: blur(12px) saturate(1.2); -webkit-backdrop-filter: blur(12px) saturate(1.2); }
}
.tabla { border: 0; border-radius: 0; }

/* Una tabla dentro de una tarjeta (la bitácora) no repite el vidrio: dos
   superficies translúcidas apiladas se ven turbias y el borde interior dibuja
   una segunda caja dentro de la primera. */
.card .tabla-envoltura {
  background: transparent;
  box-shadow: none;
  backdrop-filter: none;
  -webkit-backdrop-filter: none;
}
.tabla__acciones { text-align: right; white-space: nowrap; }
.tabla__acciones .btn + form,
.tabla__acciones .btn + .btn { margin-left: 6px; }

.firma { color: var(--text-dark); font-size: 11.5px; white-space: normal; }

/* Las tablas anchas se desplazan en vez de romper el diseño. */
@media (max-width: 860px) {
  .tabla-envoltura {
    overflow-x: auto;
    -webkit-overflow-scrolling: touch;
    scrollbar-color: rgba(255, 61, 46, .3) rgba(255, 255, 255, .03);
  }
  .tabla-envoltura::-webkit-scrollbar { height: 6px; }
  .tabla-envoltura::-webkit-scrollbar-thumb { background: rgba(255, 61, 46, .3); border-radius: 10px; }
  .tabla { min-width: 680px; }
}

/* ---------- Botones ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 7px;
  padding: 8px 16px;
  border-radius: 8px;
  border: 1px solid var(--border-color);
  background: rgba(255, 255, 255, .03);
  color: var(--text-muted);
  font-family: inherit;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  transition: background .15s, color .15s, border-color .15s, transform .1s ease;
}
.btn:hover { background: var(--accent-soft); color: var(--text-main); border-color: var(--accent); }
.btn:active { transform: scale(0.96); }

/* El botón primario es el rojo plano del panel viejo (.btn-create-header), no un
   degradado: el degradado se reservaba para el logotipo. */
.btn--pri { background: var(--accent); border-color: var(--accent); color: #fff; }
.btn--pri:hover { background: var(--accent-hover); border-color: var(--accent-hover); color: #fff; }

.btn--peligro { color: var(--danger); border-color: rgba(255, 91, 82, .15); background: transparent; }
.btn--peligro:hover { background: rgba(255, 91, 82, .08); border-color: var(--danger); color: var(--danger); }

.btn--sm { padding: 6px 10px; font-size: 12.5px; border-radius: 6px; }

/* ---------- Formularios ---------- */
.campo { margin-bottom: 15px; }
.campo label { display: block; font-size: 12px; font-weight: 600; color: var(--text-muted); margin-bottom: 6px; }
.campo__ayuda { font-size: 11.5px; color: var(--text-dark); margin-top: 5px; }

.fila { display: grid; gap: 14px; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); }

.interruptor {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 0;
  font-size: 13.5px;
  color: var(--text-muted);
  cursor: pointer;
  margin-bottom: 0;
}
.interruptor input { width: 17px; height: 17px; accent-color: var(--accent); }

/* Campo dentro de una tabla editable (las líneas de un presupuesto). */
.celda {
  width: 100%;
  padding: 7px 10px;
  border-radius: 8px;
  border: 1px solid var(--border-color);
  background: rgba(255, 255, 255, .04);
  color: var(--text-main);
  font-family: inherit;
  font-size: 13px;
}
.celda:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }

/* ---------- Avisos y etiquetas ---------- */
/* Ocupan el sitio de los toast del panel viejo (SweetAlert). Aquí llegan
   renderizados desde el servidor, así que no pueden desaparecer solos: se leen
   arriba del contenido y se van al recargar. */
.aviso {
  padding: 12px 16px;
  border-radius: 10px;
  margin-bottom: 16px;
  font-size: 13.5px;
  font-weight: 500;
  border: 1px solid;
}
.aviso--ok    { background: rgba(58, 208, 126, .10); border-color: rgba(58, 208, 126, .30); color: #a9edc8; }
.aviso--error { background: rgba(255, 91, 82, .10);  border-color: rgba(255, 91, 82, .30);  color: #ffc0bc; }
.aviso--info  { background: rgba(53, 224, 255, .08); border-color: rgba(53, 224, 255, .25); color: #b6effb; }

.etiqueta {
  display: inline-block;
  padding: 3px 10px;
  border-radius: 20px;
  font-size: 11px;
  font-weight: 700;
  border: 1px solid var(--border-color);
  color: var(--text-muted);
  white-space: nowrap;
}
.etiqueta--ok    { background: rgba(58, 208, 126, .12); color: #7fe0ac; border-color: rgba(58, 208, 126, .30); }
.etiqueta--warn  { background: rgba(255, 157, 0, .12);  color: #ffc670; border-color: rgba(255, 157, 0, .30); }
.etiqueta--info  { background: rgba(53, 224, 255, .10); color: #8fe6fa; border-color: rgba(53, 224, 255, .28); }
.etiqueta--error { background: rgba(255, 91, 82, .12);  color: #ffb3ae; border-color: rgba(255, 91, 82, .30); }

/* ---------- Avatar de la ficha de perfil ---------- */
.avatar {
  width: 96px;
  height: 96px;
  border-radius: 50%;
  object-fit: cover;
  border: 1px solid var(--border-color);
  display: block;
}
.avatar--vacio {
  display: grid;
  place-items: center;
  background: var(--accent);
  color: #fff;
  font-size: 2rem;
  font-weight: 800;
}

/* ---------- Estado vacío ---------- */
.vacio { text-align: center; padding: 48px 20px; color: var(--text-dark); font-size: 13px; white-space: normal; }
.vacio strong { display: block; color: var(--text-muted); font-size: 15px; font-weight: 700; margin-bottom: 6px; }

/* ---------- Login ----------
   Calcado del Login.jsx anterior: logotipo centrado, rótulo espaciado en
   versales y el botón rojo a todo el ancho. */
.login-pantalla {
  min-height: 100vh;
  min-height: 100dvh;
  display: grid;
  place-items: center;
  padding: 20px;
  /* Misma capa que .app-shell: sin esto el login queda bajo las brasas. */
  position: relative;
  z-index: 2;
  overflow-y: auto;
}
.login-caja {
  width: 100%;
  max-width: 390px;
  background: var(--bg-surface);
  border: 1px solid var(--border-color);
  border-radius: 18px;
  padding: 34px 30px;
  backdrop-filter: blur(16px) saturate(1.3);
  -webkit-backdrop-filter: blur(16px) saturate(1.3);
  box-shadow: 0 30px 80px rgba(0, 0, 0, .55);
}
.login-caja__marca { display: flex; flex-direction: column; align-items: center; gap: 8px; margin-bottom: 22px; }
.login-caja__sub {
  font-size: 12px;
  color: var(--text-muted);
  letter-spacing: .16em;
  text-transform: uppercase;
  font-weight: 600;
}
.login-caja .campo { margin-bottom: 18px; }
/* El icono va dentro del input: el hueco de la izquierda lo abre el
   padding del propio campo, no un margen del icono. */
.login-campo { position: relative; }
.login-campo svg { position: absolute; left: 12px; top: 50%; transform: translateY(-50%); color: var(--text-dark); pointer-events: none; }
.login-campo input { padding-left: 34px; }
.login-caja .btn {
  width: 100%;
  padding: 12px;
  border-radius: 11px;
  font-size: 15px;
  font-weight: 700;
  margin-top: 4px;
  box-shadow: 0 6px 18px rgba(255, 61, 46, .3);
}

/* ---------- Movimiento reducido ---------- */
@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
}

/* ===========================================================
   El atributo [hidden] gana SIEMPRE

   Va al final del archivo y con !important a propósito. El navegador trae
   `[hidden] { display: none }` de fábrica, pero es una regla de su hoja por
   defecto: la pisa cualquier selector de clase del sitio. Y como aquí casi todo
   declara su display —.entity-card es flex, .pagination-bar es flex,
   .mobile-only es flex !important—, marcar un elemento como oculto no lo ocultaba.

   Se manifestó en la paginación de las tarjetas: la barra calculaba bien «1 / 2»
   y ponía hidden a las tarjetas de la página siguiente, pero seguían viéndose
   las doce. Parecía que no paginaba; en realidad paginaba y nadie le hacía caso.

   Estar al final es parte del arreglo: contra otro !important de la misma
   especificidad gana el que se declara después.
   =========================================================== */
[hidden] { display: none !important; }

/* ===========================================================
   Impresión
   Se imprimen presupuestos para entregárselos al cliente. En papel el
   tema oscuro es un cartucho de tinta entero, así que se invierte.
   =========================================================== */
@media print {
  @page { size: auto; margin: 12mm; }

  .sidebar, .bottom-nav, .sheet-overlay, .content-header,
  .no-print, .no-imprimir, .aviso { display: none !important; }
  .scene-bg { display: none !important; }

  body { background: #fff !important; color: #111 !important; overflow: visible !important; height: auto !important; }
  .app-shell { display: block; height: auto; width: auto; }
  .main-content { padding: 0 !important; }
  .content-body { overflow: visible !important; padding: 0 !important; }

  .card, .tabla-envoltura {
    background: #fff !important;
    border-color: #ccc !important;
    box-shadow: none !important;
    backdrop-filter: none !important;
    -webkit-backdrop-filter: none !important;
  }
  .cabecera h1, .kpi__valor, .vacio strong { color: #111 !important; }
  th { background: #f4f4f4 !important; color: #555 !important; }
  td { color: #111 !important; border-color: #e4e4e4 !important; }
  .kpi__label, .kpi__pie, .firma, .cabecera__sub, .barra__leyenda { color: #555 !important; }
  .etiqueta { color: #333 !important; border-color: #bbb !important; background: #f4f4f4 !important; }

  /* Un informe impreso sin sus barras es una columna en blanco: el navegador
     descarta los fondos al imprimir salvo que se le diga que ahí está el dato. */
  .barra { border: 1px solid #ccc; }
  .barra, .barra__parte { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
}
