/* =============================================================================
   CAPTA · componentes compartidos (capa compartida)
   =============================================================================
   Repaso de interfaz, etapa 0 (Felipe, 2026-09-11). El CSS de los componentes que
   viven en shared/ vive también en shared/: estados (states.js), modal (modal.js),
   banda del consultorio (tenant_band.js) y resultados del buscador de contactos
   (patient_search.js). Movido tal cual desde las apps: no cambia nada de lo que
   se ve. Regla que vigila scripts/lint_shared_clases.py: ninguna clase que use un
   archivo de shared/ puede estar definida solo fuera de shared/.
   ============================================================================= */

/* ---------- Estados: cargando, vacío, error — las cinco apps ----------
   Repaso de interfaz, etapa 1 (Felipe, 2026-09-11): los de la shell de fichas.
   states.js y mobile_shell.js pintan las mismas clases. Vacío es gris y no
   alarma; error es rojo, dice qué pasó y qué hacer, y muestra el código. Los
   nombres .m-* quedan como alias de la shell. */
.c-ico { flex: none; }
.c-cargando, .m-loading { display: flex; align-items: center; justify-content: center; gap: 10px; padding: 20px; color: var(--muted); font-size: 14px; }
.c-spinner { width: 18px; height: 18px; flex: none; border: 2px solid var(--border); border-top-color: var(--teal); border-radius: 50%; animation: spin .8s linear infinite; }
.c-vacio, .m-empty {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 14px; border-radius: var(--radius);
  background: var(--surface); border: 1px dashed var(--border-strong);
  color: var(--sub); font-size: 14px; line-height: 1.45;
}
.c-vacio .c-ico { color: var(--muted); }
.c-error, .m-error {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 14px; border-radius: var(--radius);
  background: var(--danger-bg); border: 1px solid var(--danger-border);
  color: var(--danger); font-size: 14px; line-height: 1.45;
}
.c-error .c-ico { color: var(--danger); }
.c-estado-cuerpo { min-width: 0; }
.c-estado-titulo, .m-error-title { font-weight: 700; }
.c-estado-ayuda { margin-top: 4px; color: var(--muted); }
/* El código técnico se muestra, no se esconde: es lo que hace que un problema se
   pueda reportar y arreglar en vez de quedar como "no anda". */
.c-error-codigo, .m-error-code {
  display: inline-block; margin-top: 6px;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
  font-size: 12px; color: var(--danger);
  background: rgba(192,57,43,.08); border-radius: 4px; padding: 2px 6px;
}
.c-estado-accion { margin-top: 10px; }

@keyframes spin {
  to { transform: rotate(360deg); }
}

/* ---------- Modal (modal.js) ---------- */
.modal.modal-wide {
  max-width: 760px;
}

.modal-overlay {
  position: fixed;
  inset: 0;
  background: rgba(14, 31, 61, 0.55);
  display: flex;
  align-items: flex-start;
  justify-content: center;
  z-index: 1000;
  padding: 64px 16px 16px;
  animation: fadeIn 0.15s ease-out;
}

.modal {
  background: var(--surface);
  border-radius: var(--radius);
  width: 100%;
  max-width: 560px;
  max-height: calc(100vh - 80px);
  display: flex;
  flex-direction: column;
  box-shadow: 0 12px 32px rgba(14, 31, 61, 0.25);
  animation: slideIn 0.18s ease-out;
  overflow: hidden;
}

.modal-header {
  padding: 18px 24px;
  border-bottom: 1px solid var(--border);
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-shrink: 0;
}

.modal-header h2 {
  font-size: 20px;
  color: var(--navy);
}

.modal-close {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--muted);
  font-size: 22px;
  line-height: 1;
}

.modal-close:hover {
  background: var(--border);
  color: var(--text);
}

.modal-body {
  padding: 24px;
  overflow-y: auto;
  flex: 1;
}

.modal-footer {
  padding: 14px 24px;
  border-top: 1px solid var(--border);
  display: flex;
  justify-content: flex-end;
  gap: 12px;
  flex-shrink: 0;
  background: var(--bg);
}

@media (max-width: 900px) {
  .modal-overlay {
    padding: 16px;
    align-items: center;
  }
}

.modal.modal-wide {
  max-width: 760px;
}

/* ---------- Banda del consultorio (tenant_band.js) ---------- */
#tenant-band[hidden] { display: none !important; }

#tenant-band {
  grid-area: tenant-band;
  display: flex;
  align-items: center;
  gap: .55rem;
  width: 100%;
  box-sizing: border-box;
  padding: .5rem 1rem;
  background: linear-gradient(135deg, #122a61 0%, #112550 60%, #0e1d42 100%);
  font-size: .95rem;
  letter-spacing: .01em;
}

#tenant-band .tb-label {
  text-transform: uppercase;
  font-size: .72rem;
  font-weight: 700;
  letter-spacing: .09em;
  color: var(--teal, #2aa8a0);
}

#tenant-band .tb-name {
  font-size: 1.05rem;
  font-weight: 800;
  color: #ffffff;
}

/* ---------- Resultados del buscador de contactos (patient_search.js) ---------- */
.contact-search-wrap { position: relative; }
.contact-results { display: none; position: absolute; top: 100%; left: 0; right: 0; background: var(--surface); border: 1px solid var(--border-strong); border-radius: 6px; box-shadow: 0 4px 12px rgba(14,31,61,.1); z-index: 100; max-height: 220px; overflow-y: auto; }
.contact-result-item { padding: 10px 14px; cursor: pointer; font-size: 13px; border-bottom: 1px solid var(--border); }
.contact-result-item:hover { background: rgba(56,205,196,.08); }
.contact-result-item .contact-name { font-weight: 600; color: var(--navy); }
.contact-result-item .contact-detail { font-size: 11px; color: var(--muted); margin-top: 2px; }
.contact-loading { padding: 10px 14px; font-size: 12px; color: var(--muted); font-style: italic; }

/* =============================================================================
   BASE DE COMPONENTES — una sola, con dos densidades (repaso de interfaz, etapa 2)
   =============================================================================
   Decisión de Felipe (2026-09-11): los mismos botones, campos, tarjetas, insignias
   y avisos en las cinco apps, compactos en la compu y grandes en el celular. La
   densidad la decide el CONTEXTO (html[data-densidad], lo pone embebido.js), no la
   app: tokens.css define --control-h, --texto, --relleno-x y --titulo para cada
   una. Nombres canónicos: .c-*. Los viejos (.btn*, .m-btn*, .input, .m-input,
   .badge*, .m-card, .m-warn) son ALIAS mientras dura la migración: las apps
   cambian de aspecto sin tocar su HTML.
   ============================================================================= */

/* ---------- Botones ----------
   Los variantes van también en la base porque presupuestos usa .btn-primary
   sin .btn. */
.c-btn, .btn, .m-btn,
.c-btn-primario, .btn-primary, .c-btn-secundario, .btn-secondary {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: var(--control-h); padding: 0 var(--relleno-x);
  border: 1px solid transparent; border-radius: var(--radius-sm);
  font-family: var(--font-sans); font-size: var(--texto); font-weight: 500; line-height: 1.2;
  cursor: pointer; white-space: nowrap; text-decoration: none;
  transition: background .15s, color .15s, border-color .15s, transform .05s;
  -webkit-tap-highlight-color: transparent;
}
.c-btn:active, .btn:active, .m-btn:active { transform: translateY(1px); }
.c-btn:disabled, .btn:disabled, .m-btn:disabled, .btn-primary:disabled, .btn-secondary:disabled { opacity: .5; cursor: default; transform: none; }
.c-btn-primario, .btn-primary, .m-btn-primary { background: var(--teal); color: var(--white); }
.c-btn-primario:hover, .btn-primary:hover, .m-btn-primary:hover { background: var(--dark); }
.c-btn-secundario, .btn-secondary, .m-btn-secondary { background: var(--surface); color: var(--text); border-color: var(--border-strong); }
.c-btn-secundario:hover, .btn-secondary:hover, .m-btn-secondary:hover { border-color: var(--teal); color: var(--teal); }
.c-btn-fantasma, .btn-ghost, .m-btn-ghost { background: transparent; color: var(--sub); }
.c-btn-fantasma:hover, .btn-ghost:hover, .m-btn-ghost:hover { background: var(--border); color: var(--text); }
.c-btn-peligro, .btn-danger { background: var(--surface); color: var(--danger); border-color: var(--border-strong); }
.c-btn-peligro:hover, .btn-danger:hover { background: var(--danger-bg); border-color: var(--danger); }
.c-btn-chico, .btn-sm { min-height: 30px; padding: 0 10px; font-size: 13px; }

/* ---------- Campos ----------
   El <select> sin clase de las apps de escritorio sigue en la hoja de cada app,
   con estos mismos tokens: una regla de elemento acá pisaría los de presupuestos. */
.c-campo, .input, .m-input {
  height: var(--control-h); padding: 0 12px;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  font-family: var(--font-sans); font-size: var(--texto); color: var(--text);
  transition: border-color .15s, box-shadow .15s;
}
.c-campo:focus, .input:focus, .m-input:focus { outline: none; border-color: var(--teal); box-shadow: 0 0 0 3px rgba(42,168,160,.15); }

/* ---------- Tarjetas ---------- */
.c-tarjeta, .m-card { background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius); padding: 14px; box-shadow: var(--shadow-sm); }

/* ---------- Insignias ---------- */
.c-insignia, .badge { display: inline-block; padding: 2px 8px; border-radius: 12px; font-size: 12px; font-weight: 500; line-height: 1.4; white-space: nowrap; }
.c-insignia-exito, .badge-success {
  background: var(--success-bg);
  color: var(--success);
  border: 1px solid var(--success-border);
}
.c-insignia-aviso, .badge-warning, .badge-warn {
  background: var(--warning-bg);
  color: var(--warning);
  border: 1px solid var(--warning-border);
}
.c-insignia-peligro, .badge-danger {
  background: var(--danger-bg);
  color: var(--danger);
  border: 1px solid var(--danger-border);
}
.c-insignia-neutra, .badge-muted {
  background: var(--border);
  color: var(--sub);
}
.c-insignia-marca, .badge-teal {
  background: rgba(42, 168, 160, 0.15);
  color: var(--dark);
}
.c-insignia-pendiente, .badge-pending {
  background: var(--border);
  color: var(--sub);
}

/* ---------- Aviso en la página (advertencia) ---------- */
.c-aviso, .m-warn {
  display: flex; align-items: flex-start; gap: 10px;
  padding: 14px; border-radius: var(--radius);
  background: var(--warning-bg); border: 1px solid var(--warning-border);
  color: var(--warning); font-size: 14px; line-height: 1.45;
}

/* ---------- Título de pantalla: 28px en la compu, 24px en el celular ---------- */
h1, .c-titulo { font-size: var(--titulo); }

/* ---------- En el celular, 44px como mínimo en todo lo que se toca (Felipe) ----------
   Es un PISO, no un valor: max() no achica lo que ya es más grande (un botón
   táctil sigue en 48px). Va sobre los elementos, no solo sobre las clases de la
   base, porque cada app tiene controles propios que también se tocan (filtros,
   pestañas, íconos): la primera versión listaba clases y los filtros de pacientes
   quedaban en 28px. */
html[data-densidad="tactil"] :is(button, select, textarea, [role="button"], a.btn, a.c-btn,
  input:not([type="checkbox"], [type="radio"], [type="hidden"], [type="range"]),
  .m-nav-tab, .m-list-row, .m-result, .iframe-tab, .nav-btn) { min-height: max(44px, var(--control-h)); }
html[data-densidad="tactil"] :is(.modal-close, .c-aviso-cerrar) { min-width: 44px; }

/* ---------- Orden de columnas y arrastre (column_sort.js, sortable.js) ---------- */
.drag-handle {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  cursor: grab;
  color: var(--muted);
  border-radius: 4px;
  transition: color 0.12s, background 0.12s;
  user-select: none;
}

.drag-handle svg {
  fill: currentColor;
}

.drag-handle:hover {
  color: var(--text);
  background: var(--border);
}

.sort-arrow {
  display: inline-block;
  margin-left: 4px;
  font-size: 11px;
  font-weight: 700;
  line-height: 1;
}

.sort-arrow-active {
  color: var(--teal);
  opacity: 1;
}

.sort-arrow-idle {
  color: var(--muted);
  opacity: 0.45;
}

/* Encabezado de columna ordenable (column_sort.js: th.sortable-col + .sort-label). */
table.data th.sortable-col {
  cursor: pointer;
  user-select: none;
  transition: color 0.12s;
}

table.data th.sortable-col .sort-label {
  display: inline-block;
}

table.data th.sortable-col:hover {
  color: var(--text);
}

/* ---------- Avisos flotantes (aviso.js) — reemplazan a alert() ----------
   Un error no se cierra solo; "listo" sí. */
.c-avisos { position: fixed; right: 16px; bottom: 16px; z-index: 60; display: flex; flex-direction: column; gap: 8px; width: min(420px, calc(100vw - 32px)); }
.c-aviso-flotante { display: flex; align-items: flex-start; gap: 10px; padding: 12px 14px; border-radius: var(--radius); font-size: 14px; line-height: 1.45; box-shadow: var(--shadow-md); }
.c-aviso-error { background: var(--danger-bg); border: 1px solid var(--danger-border); color: var(--danger); }
.c-aviso-warn { background: var(--warning-bg); border: 1px solid var(--warning); color: var(--warning); }
.c-aviso-ok { background: var(--success-bg); border: 1px solid var(--success); color: var(--success); }
.c-aviso-cuerpo { flex: 1; min-width: 0; }
.c-aviso-cerrar { flex: none; min-width: 28px; min-height: 28px; margin: -4px -6px 0 0; border: 0; border-radius: var(--radius-sm); background: none; color: inherit; font-size: 20px; line-height: 1; cursor: pointer; }
.c-aviso-cerrar:hover { background: rgba(14,31,61,.06); }
