/* ============================================================
   WOLF / Legal Boost — Design System
   Fluent 2 + Acrylic + Glassmorphism
   3 temas: mid (default) · dark · light
   Reglas: NUNCA concatenar var() con strings. Tokens predefinidos.
   ============================================================ */

/* ---------- TEMA MID (default) — light suave con acento cyan ---------- */
:root,
:root[data-theme="mid"] {
  /* Mid = un light ATENUADO. El techo de la escala es #EBEEF0: ninguna
     superficie llega al blanco. Los tres fondos comparten hue 204° y ~14% de
     saturación (los de #EBEEF0), así la rampa se siente de una sola familia,
     y bajan en pasos parejos de luminosidad para no perder profundidad. */
  --bg-elevated:  #ebeef0;  /* el más claro de todo el tema */
  --bg-surface:   #e1e5e8;
  --bg-base:      #d5dbdf;
  --bg-acrylic:   rgba(235, 238, 240, 0.86);
  --bg-overlay:   rgba(17, 30, 38, 0.44);
  --bg-hover:     rgba(8, 145, 178, 0.10);

  /* Con los fondos más oscuros, secundario y muted bajan otro escalón para
     mantener el contraste sobre las tarjetas. */
  --text-primary:   #14212a;
  --text-secondary: #3d4a53;
  --text-muted:     #64727c;
  --text-on-accent: #ffffff;

  /* Un escalón más oscuro que el cyan anterior (#0891b2): sobre los fondos
     nuevos, aquel dejaba el texto blanco de los botones en 3.7:1, bajo el
     4.5:1 que pide WCAG AA. Este llega a 4.9:1. */
  --accent:       #0e7490;
  --accent-hover: #0b5c73;
  --accent-soft:  rgba(14, 116, 144, 0.13);
  --accent-line:  rgba(14, 116, 144, 0.40);

  /* Bordes más marcados: con el fondo más oscuro, los de antes desaparecían. */
  --stroke-default: rgba(15, 45, 58, 0.16);
  --stroke-strong:  rgba(15, 45, 58, 0.28);

  --success: #059669;  --success-soft: rgba(5, 150, 105, 0.12);
  --warning: #d97706;  --warning-soft: rgba(217, 119, 6, 0.13);
  --danger:  #dc2626;  --danger-soft:  rgba(220, 38, 38, 0.12);
  --info:    #0284c7;  --info-soft:    rgba(2, 132, 199, 0.12);

  --shadow-sm:  0 1px 2px rgba(16,40,55,0.07), inset 0 0 0 0.5px rgba(15,45,58,0.03);
  --shadow-md:  0 4px 16px rgba(16,40,55,0.10), inset 0 0 0 0.5px rgba(15,45,58,0.04);
  --shadow-lg:  0 12px 36px rgba(16,40,55,0.16), inset 0 0 0 1px rgba(15,45,58,0.05);
  --glow-subtle: 0 2px 8px rgba(8,145,178,0.28);
  --glow-strong: 0 4px 16px rgba(8,145,178,0.40), 0 2px 30px rgba(8,145,178,0.20);
}

/* ---------- TEMA DARK (grises neutros + acentos de color) ----------
   Los fondos y los textos son grises casi neutros (apenas fríos, para que no
   se vean sepia). Todo el color vive en el acento y en los estados, así lo
   que tiene color es siempre lo que significa algo. */
:root[data-theme="dark"] {
  --bg-base:      #0f1011;
  --bg-surface:   #17181a;
  --bg-elevated:  #202124;
  --bg-acrylic:   rgba(23, 24, 26, 0.78);
  --bg-overlay:   rgba(0, 0, 0, 0.62);
  --bg-hover:     rgba(255, 255, 255, 0.06);

  --text-primary:   #f0f0f2;
  --text-secondary: #a6a6ac;
  --text-muted:     #75757d;
  --text-on-accent: #06272e;

  /* Cyan, el mismo acento del tema mid, subido de brillo para leerse sobre
     fondo oscuro. Es el único color de la interfaz que no es un estado. */
  --accent:       #22d3ee;
  --accent-hover: #67e8f9;
  --accent-soft:  rgba(34, 211, 238, 0.15);
  --accent-line:  rgba(34, 211, 238, 0.42);

  --stroke-default: rgba(255, 255, 255, 0.09);
  --stroke-strong:  rgba(255, 255, 255, 0.18);

  --success: #34d399;  --success-soft: rgba(52, 211, 153, 0.15);
  --warning: #fbbf24;  --warning-soft: rgba(251, 191, 36, 0.15);
  --danger:  #f87171;  --danger-soft:  rgba(248, 113, 113, 0.15);
  --info:    #60a5fa;  --info-soft:    rgba(96, 165, 250, 0.15);

  --shadow-sm:  0 1px 2px rgba(0,0,0,0.40), inset 0 0 0 0.5px rgba(255,255,255,0.05);
  --shadow-md:  0 4px 14px rgba(0,0,0,0.50), inset 0 0 0 0.5px rgba(255,255,255,0.06);
  --shadow-lg:  0 10px 34px rgba(0,0,0,0.60), inset 0 0 0 1px rgba(255,255,255,0.08);
  --glow-subtle: 0 0 10px rgba(34,211,238,0.26);
  --glow-strong: 0 0 22px rgba(34,211,238,0.44), 0 0 52px rgba(34,211,238,0.18);
}

/* ---------- TEMA LIGHT ---------- */
:root[data-theme="light"] {
  --bg-base:      #f5f5f8;
  --bg-surface:   #ffffff;
  --bg-elevated:  #ffffff;
  --bg-acrylic:   rgba(255, 255, 255, 0.78);
  --bg-overlay:   rgba(20, 20, 30, 0.35);
  --bg-hover:     rgba(0, 0, 0, 0.04);

  --text-primary:   #1a1a24;
  --text-secondary: #55555f;
  --text-muted:     #8a8a95;
  --text-on-accent: #ffffff;

  --accent:       #7c3aed;
  --accent-hover: #6d28d9;
  --accent-soft:  rgba(124, 58, 237, 0.12);
  --accent-line:  rgba(124, 58, 237, 0.40);

  --stroke-default: rgba(0, 0, 0, 0.09);
  --stroke-strong:  rgba(0, 0, 0, 0.16);

  --success: #059669;  --success-soft: rgba(5, 150, 105, 0.12);
  --warning: #d97706;  --warning-soft: rgba(217, 119, 6, 0.12);
  --danger:  #dc2626;  --danger-soft:  rgba(220, 38, 38, 0.12);
  --info:    #2563eb;  --info-soft:    rgba(37, 99, 235, 0.12);

  --shadow-sm:  0 1px 2px rgba(20,20,40,0.08), inset 0 0 0 0.5px rgba(0,0,0,0.03);
  --shadow-md:  0 4px 14px rgba(20,20,40,0.10), inset 0 0 0 0.5px rgba(0,0,0,0.03);
  --shadow-lg:  0 10px 34px rgba(20,20,40,0.16), inset 0 0 0 1px rgba(0,0,0,0.04);
  --glow-subtle: 0 0 10px rgba(124,58,237,0.22);
  --glow-strong: 0 0 22px rgba(124,58,237,0.35), 0 0 48px rgba(124,58,237,0.15);
}

/* ---------- TOKENS COMPARTIDOS ---------- */
:root {
  --font: "Segoe UI", -apple-system, system-ui, "Inter", "Helvetica Neue", Arial, sans-serif;
  --radius-sm: 8px;
  --radius:    14px;
  --radius-lg: 20px;
  --radius-xl: 28px;
  --radius-pill: 999px;

  --sp-2: 2px;  --sp-4: 4px;  --sp-6: 6px;  --sp-8: 8px;
  --sp-12: 12px; --sp-16: 16px; --sp-20: 20px; --sp-24: 24px;
  --sp-32: 32px; --sp-40: 40px; --sp-48: 48px;

  --sidebar-w: 264px;
  --header-h: 64px;
  --ease: cubic-bezier(0.33, 0, 0.1, 1);
}

/* ---------- RESET ---------- */
*, *::before, *::after { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0;
  font-family: var(--font);
  font-size: 14px;
  line-height: 1.55;
  color: var(--text-primary);
  background: var(--bg-base);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
  /* Un título o un número sin espacios no puede ensanchar la página entera.
     Tiene que ser `anywhere` y no `break-word`: solo `anywhere` reduce el
     ancho mínimo del contenido, que es lo que deja encogerse a las celdas de
     grid y flex. Con `break-word` la cadena se parte pero el contenedor ya
     creció y la página sigue con barra horizontal. */
  overflow-wrap: anywhere;
}
h1,h2,h3,h4,h5,h6 { margin: 0 0 var(--sp-8); font-weight: 600; line-height: 1.25; letter-spacing: -0.01em; }
h1 { font-size: 26px; } h2 { font-size: 20px; } h3 { font-size: 16px; }
p { margin: 0 0 var(--sp-12); }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; display: block; }
button, input, select, textarea { font-family: inherit; font-size: inherit; color: inherit; }
ul { margin: 0; padding: 0; list-style: none; }
::selection { background: var(--accent-soft); }

/* Scrollbar */
*::-webkit-scrollbar { width: 10px; height: 10px; }
*::-webkit-scrollbar-thumb { background: var(--stroke-strong); border-radius: var(--radius-pill); border: 2px solid transparent; background-clip: padding-box; }
*::-webkit-scrollbar-track { background: transparent; }

/* ---------- UTILIDADES ---------- */
.font-medium   { font-weight: 500; }
.font-semibold { font-weight: 600; }
.font-bold     { font-weight: 700; }
.text-sm  { font-size: 12.5px; }
.text-xs  { font-size: 11.5px; }
.text-lg  { font-size: 16px; }
.text-secondary { color: var(--text-secondary); }
.text-muted     { color: var(--text-muted); }
.text-accent    { color: var(--accent); }
.text-success { color: var(--success); }
.text-warning { color: var(--warning); }
.text-danger  { color: var(--danger); }
.uppercase { text-transform: uppercase; letter-spacing: 0.06em; }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }
.mt-xs { margin-top: var(--sp-4); }   .mb-xs { margin-bottom: var(--sp-4); }
.mt-sm { margin-top: var(--sp-8); }   .mb-sm { margin-bottom: var(--sp-8); }
.mt-md { margin-top: var(--sp-16); }  .mb-md { margin-bottom: var(--sp-16); }
.mt-lg { margin-top: var(--sp-24); }  .mb-lg { margin-bottom: var(--sp-24); }
.flex { display: flex; }
.flex-col { flex-direction: column; }
.items-center { align-items: center; }
.justify-between { justify-content: space-between; }
.gap-4 { gap: var(--sp-4); } .gap-8 { gap: var(--sp-8); }
.gap-12 { gap: var(--sp-12); } .gap-16 { gap: var(--sp-16); } .gap-24 { gap: var(--sp-24); }
.flex-1 { flex: 1; }
/* Para etiquetas junto a un .select: el select pide width:100% y aplasta a la
   etiqueta hasta partirle la palabra ("Client / e"). */
.shrink-0 { flex-shrink: 0; }
.w-full { width: 100%; }
.hidden { display: none !important; }

/* ============================================================
   LAYOUT
   ============================================================ */
.app { display: grid; grid-template-columns: var(--sidebar-w) 1fr; min-height: 100vh; }

.sidebar {
  display: flex; flex-direction: column;
  background: var(--bg-surface);
  border-right: 1px solid var(--stroke-default);
  padding: var(--sp-20) var(--sp-12);
  position: sticky; top: 0; height: 100vh;
}
/* Lockup vertical: ícono arriba, wordmark abajo. Es lo que mejor aprovecha
   la columna angosta del sidebar. */
.brand {
  display: flex; flex-direction: column; align-items: center; gap: var(--sp-6);
  padding: var(--sp-16) var(--sp-12) var(--sp-20);
  text-decoration: none; color: var(--text-primary);
  border-bottom: 1px solid var(--stroke-default);
  margin-bottom: var(--sp-8);
}
/* fill: currentColor es lo que hace que el mismo SVG sirva en los 3 temas. */
.logo-mark { height: 40px; width: auto; fill: currentColor; }
.logo-word { height: 17px; width: auto; fill: currentColor; margin-top: var(--sp-2, 2px); }
.brand-sub { font-size: 10px; color: var(--text-muted); letter-spacing: .06em; text-transform: uppercase; margin-top: var(--sp-4); }

.nav { display: flex; flex-direction: column; gap: 2px; flex: 1; overflow-y: auto; overflow-x: hidden; }
.nav-label { font-size: 10.5px; text-transform: uppercase; letter-spacing: 0.08em; color: var(--text-muted); padding: var(--sp-16) var(--sp-12) var(--sp-6); }
.nav-item {
  display: flex; align-items: center; gap: var(--sp-12);
  padding: var(--sp-8) var(--sp-12); border-radius: var(--radius-sm);
  color: var(--text-secondary); font-weight: 500; font-size: 13.5px;
  transition: background .16s var(--ease), transform .16s var(--ease), color .16s var(--ease);
  cursor: pointer;
}
.nav-item .ico { width: 18px; text-align: center; opacity: .9; }
.nav-item:hover { background: var(--bg-hover); color: var(--text-primary); }
.nav-item.active { background: var(--accent-soft); color: var(--accent); box-shadow: inset 0 0 0 1px var(--accent-line); }
.nav-item .badge-dot { margin-left: auto; }

/* Grupos plegables del menú de administración. Diez enlaces seguidos no tienen
   jerarquía; en cuatro cajones sí. <details> nativo, sin JS.
   El encabezado se lee como un ítem más pero atenuado, para que no compita con
   el enlace activo. */
.nav-group > summary {
  display: flex; align-items: center; gap: var(--sp-8);
  padding: var(--sp-8) var(--sp-12); border-radius: var(--radius-sm);
  font-size: 12.5px; font-weight: 600; color: var(--text-secondary);
  cursor: pointer; list-style: none; user-select: none;
}
.nav-group > summary::-webkit-details-marker { display: none; }
.nav-group > summary::marker { content: ""; }
.nav-group > summary:hover { background: var(--bg-hover); color: var(--text-primary); }
.nav-group > summary .ico { width: 18px; text-align: center; opacity: .9; }
.nav-group > summary .sec-chev { margin-left: auto; }
.nav-group > summary .nav-badge + .sec-chev { margin-left: var(--sp-6); }
.nav-group[open] > summary .sec-chev { transform: rotate(180deg); }
/* Los enlaces de dentro van sangrados: dicen a qué cajón pertenecen aunque se
   esté mirando sólo el borde izquierdo. */
.nav-group > .nav-item { padding-left: var(--sp-24); }
.nav-radiografia:not(.active) { background: color-mix(in srgb, var(--accent) 7%, transparent); }
.nav-radiografia:not(.active):hover { background: color-mix(in srgb, var(--accent) 12%, var(--bg-hover)); }
/* Radiografia en una tarjeta de tarea: el mismo lenguaje que el item de
   navegacion, en version borde. Sutil a proposito: distingue de un vistazo sin
   competir con la insignia de estado, que es la que de verdad hay que leer.
   --accent-line esta definida en los tres temas, asi que no hace falta nada mas.

   Borde completo y no solo lateral: el lateral se leia como un adorno cortado.
   Se cambia solo el color, conservando el grosor de .card, para que distinga sin
   competir con la insignia de estado, que es la que hay que leer.

   Va con las dos clases y no con una sola: `.card` define su propio borde mas
   abajo en la hoja, y con la misma especificidad ganaba por orden. La tarjeta se
   veia identica a una normal. */
.task-card.task-360 { border-color: var(--accent-line); }

/* Tour guiado: el portal muestra un solo bloque a la vez, sin construir una
   segunda interfaz ni dejar una cuenta demo llena de datos. */
.lb-tour-hidden { visibility: hidden !important; pointer-events: none !important; }
/* Cubre el intervalo entre dos páginas del tour; la clase se aplica en el
   head, antes del primer paint de la página siguiente. */
html.tour-transition::after { content:""; position:fixed; inset:0; z-index:9999; background:#0b1014; opacity:.70; pointer-events:auto; }
.lb-tour-popover.driver-popover { max-width: 330px; padding: var(--sp-20); border: 1px solid var(--stroke-strong); border-radius: var(--radius-lg); background: var(--bg-elevated); color: var(--text-primary); box-shadow: var(--shadow-lg); }
.lb-tour-popover .driver-popover-title { color: var(--text-primary); font: inherit; font-size: 18px; font-weight: 700; }
.lb-tour-popover .driver-popover-description { color: var(--text-secondary); font: inherit; font-size: 14px; line-height: 1.5; }
.lb-tour-popover .driver-popover-progress-text { color: var(--text-muted); font-size: 11px; }
.lb-tour-popover .driver-popover-footer button { border-radius: var(--radius-sm); font: inherit; font-size: 12px; text-shadow: none !important; }
.lb-tour-popover .driver-popover-next-btn { background: var(--accent) !important; border-color: var(--accent) !important; color: #fff !important; }
.lb-tour-popover .driver-popover-prev-btn { background: transparent !important; border-color: var(--stroke-strong) !important; color: var(--text-primary) !important; }

.sidebar-footer { padding-top: var(--sp-16); border-top: 1px solid var(--stroke-default); }

.theme-switch { display: flex; gap: var(--sp-4); background: var(--bg-base); padding: var(--sp-4); border-radius: var(--radius-pill); border: 1px solid var(--stroke-default); }
.theme-btn { flex: 1; padding: var(--sp-6); border-radius: var(--radius-pill); border: none; background: transparent; color: var(--text-secondary); cursor: pointer; font-size: 11.5px; font-weight: 600; transition: all .16s var(--ease); }
.theme-btn:hover { color: var(--text-primary); }
.theme-btn.active { background: var(--bg-elevated); color: var(--accent); box-shadow: var(--shadow-sm); }

.user-chip { display: flex; align-items: center; gap: var(--sp-12); padding: var(--sp-12) var(--sp-8) var(--sp-4); }
.avatar { width: 34px; height: 34px; border-radius: 50%; background: var(--accent); color: var(--text-on-accent); display: grid; place-items: center; font-weight: 700; font-size: 13px; flex-shrink: 0; }
.user-chip .meta { min-width: 0; }
.user-chip .name { font-weight: 600; font-size: 13px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.user-chip .role { font-size: 11px; color: var(--text-muted); text-transform: capitalize; }
/* Sirve para <a> y para <button>: el logout es un form POST, y un button sin
   resetear trae fondo, borde y padding del navegador (el cuadrado gris). */
.user-action { width: 44px; height: 44px; flex-shrink: 0; display: grid; place-items: center; color: var(--text-secondary);
  background: none; border: 0; padding: 0; font: inherit; cursor: pointer; border-radius: var(--radius-sm); }
.user-action:hover { color: var(--text-primary); background: var(--bg-hover); }
.user-action:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.user-action svg { width: 18px; height: 18px; fill: none; stroke: currentColor; stroke-width: 2; stroke-linecap: round; }

/* Main */
.main { display: flex; flex-direction: column; min-width: 0; }
.topbar {
  height: var(--header-h); display: flex; align-items: center; justify-content: space-between;
  padding: 0 var(--sp-32); border-bottom: 1px solid var(--stroke-default);
  background: var(--bg-acrylic); backdrop-filter: blur(20px) saturate(1.8);
  position: sticky; top: 0; z-index: 20;
}
/* La barra tiene alto fijo, así que aquí el título se recorta con puntos
   suspensivos en vez de crecer hacia abajo. Completo se lee en la página.
   min-width:0 es imprescindible: sin él un hijo de flex nunca baja de su
   ancho de contenido y el recorte no llega a aplicarse. */
.topbar-title { min-width: 0; }
/* El lado del selector no cede: .client-picker lleva min-width:0 para poder
   encoger el desplegable en móvil, y eso le quita también el mínimo del
   texto, así que con un título largo "Cliente:" se partía letra a letra.
   Quien absorbe el recorte es el título, que para eso tiene los puntos
   suspensivos. En móvil .topbar-actions es display:contents y esto no aplica. */
.topbar-actions { flex-shrink: 0; }
.topbar h1, .topbar .sub { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.topbar h1 { margin: 0; font-size: 19px; }
/* Solo aparece bajo 860px (ver el bloque MOBILE al final). */
#burger { display: none; }
.topbar .sub { font-size: 12.5px; color: var(--text-muted); }
.content { padding: var(--sp-32); max-width: 1180px; width: 100%; }

/* ============================================================
   COMPONENTES
   ============================================================ */
.card {
  background: var(--bg-elevated);
  border: 1px solid var(--stroke-default);
  border-radius: var(--radius);
  padding: var(--sp-20);
  box-shadow: var(--shadow-sm);
  transition: box-shadow .18s var(--ease), border-color .18s var(--ease), transform .18s var(--ease);
}
.card.hover:hover, a.card:hover { box-shadow: var(--shadow-md); border-color: var(--stroke-strong); transform: translateY(-2px); }
.card-title { font-size: 13px; font-weight: 600; color: var(--text-secondary); margin-bottom: var(--sp-12); }

.grid { display: grid; gap: var(--sp-16); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-4 { grid-template-columns: repeat(4, 1fr); }
@media (max-width: 960px) { .grid-3, .grid-4 { grid-template-columns: repeat(2, 1fr); } }
/* grid-3 y grid-4 se quedan en 2 columnas: llevan tarjetas cortas (métricas,
   carpetas). Apilarlas de a una gastaba 570px de alto para mostrar 4 cifras.
   grid-2 sí colapsa: ahí van bloques de contenido, no fichas. */
@media (max-width: 640px) { .grid-2 { grid-template-columns: 1fr; } }

/* Contenido principal + columna lateral. Era un style inline en 3 plantillas,
   y por eso ninguna media query podía apilarlo: en móvil la lateral quedaba de
   148px y su contenido se desarmaba en 10 líneas por item. */
.grid-main-side { grid-template-columns: 1.4fr 1fr; }
/* Sin esto, `1fr` es minmax(auto, 1fr) y la columna NO puede encogerse por
   debajo del contenido mínimo: bastó una línea sin cortes en la actividad para
   que esa columna reclamara el ancho de la frase entera, aplastara la de tareas
   y sacara scroll horizontal a toda la página. */
.grid-main-side > * { min-width: 0; }
@media (max-width: 860px) { .grid-main-side { grid-template-columns: 1fr; } }

/* Metric card */
.metric { display: flex; flex-direction: column; gap: var(--sp-6); }
.metric .value { font-size: 30px; font-weight: 700; letter-spacing: -0.02em; line-height: 1; }
.metric .label { font-size: 12.5px; color: var(--text-muted); }
.metric .ico-box { width: 40px; height: 40px; border-radius: var(--radius-sm); display: grid; place-items: center; font-size: 18px; margin-bottom: var(--sp-4); }
.ico-accent  { background: var(--accent-soft); color: var(--accent); }
.ico-success { background: var(--success-soft); color: var(--success); }
.ico-warning { background: var(--warning-soft); color: var(--warning); }
.ico-info    { background: var(--info-soft); color: var(--info); }
.ico-muted   { background: var(--bg-hover); color: var(--text-muted); }
/* Métrica de contexto (histórico), no accionable: pesa menos que las demás. */
.metric-muted .value { font-weight: 600; color: var(--text-secondary); }

/* Buttons */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-8);
  padding: var(--sp-8) var(--sp-16); border-radius: var(--radius-sm);
  font-weight: 600; font-size: 13.5px; cursor: pointer; border: 1px solid transparent;
  transition: all .16s var(--ease); white-space: nowrap;
}
.btn-primary { background: var(--accent); color: var(--text-on-accent); box-shadow: var(--glow-subtle); }
.btn-primary:hover { background: var(--accent-hover); box-shadow: var(--glow-strong); transform: translateY(-1px); }
.btn-ghost { background: var(--bg-surface); color: var(--text-primary); border-color: var(--stroke-default); }
.btn-ghost:hover { border-color: var(--stroke-strong); background: var(--bg-hover); }
/* btn-danger se usaba desde hace tiempo en restaurar respaldo y no existía: el
   boton mas destructivo del portal se pintaba como uno neutro. */
.btn-danger { background: var(--danger); color: #fff; border-color: var(--danger); }
.btn-danger:hover { filter: brightness(1.08); transform: translateY(-1px); }
.btn-block { width: 100%; padding: var(--sp-12); }
.btn-sm { padding: var(--sp-6) var(--sp-12); font-size: 12.5px; }

/* Inputs */
.field { margin-bottom: var(--sp-16); }
.field label { display: block; font-size: 12.5px; font-weight: 600; color: var(--text-secondary); margin-bottom: var(--sp-6); }
/* Lista de casillas (responsables de una tarea). Se limita la altura porque el
   modal ya trae seis campos: con veinte fichas, el botón Guardar quedaba fuera
   de la pantalla. */
.check-list { display: flex; flex-direction: column; gap: var(--sp-8); max-height: 180px; overflow-y: auto; padding: var(--sp-8) var(--sp-12); border: 1px solid var(--stroke-default); border-radius: var(--radius-sm); }
.check-list label { font-weight: 500; color: var(--text-default); margin-bottom: 0; }
.input, .select, textarea.input {
  width: 100%; padding: var(--sp-12) var(--sp-16);
  background: var(--bg-surface); border: 1px solid var(--stroke-default);
  border-radius: var(--radius-sm); color: var(--text-primary);
  transition: border-color .16s var(--ease), box-shadow .16s var(--ease); outline: none;
}
.input:focus, .select:focus, textarea.input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-soft); }
textarea.input { resize: vertical; min-height: 90px; }

/* Badges */
.badge { display: inline-flex; align-items: center; gap: var(--sp-6); padding: 3px var(--sp-8); border-radius: var(--radius-pill); font-size: 11.5px; font-weight: 600; }
.badge-accent  { background: var(--accent-soft); color: var(--accent); }
.badge-success { background: var(--success-soft); color: var(--success); }
.badge-warning { background: var(--warning-soft); color: var(--warning); }
.badge-danger  { background: var(--danger-soft); color: var(--danger); }
.badge-info    { background: var(--info-soft); color: var(--info); }
.badge-muted   { background: var(--bg-hover); color: var(--text-secondary); }
/* Los hitos de la Radiografía van todos en acento: el plan es una sola pieza y
   pintar cada hito de un color distinto lo convertía en un semáforo. El estado
   sigue estando, escrito en la etiqueta. Por eso ya no hay .badge-pending,
   .badge-in_progress, .badge-completed ni .badge-blocked. */
.badge-dot { width: 8px; height: 8px; border-radius: 50%; padding: 0; }
.badge-dot.badge-warning { background: var(--warning); }
.badge-dot.badge-accent  { background: var(--accent); }

/* Tabs */
.tabs { display: inline-flex; gap: var(--sp-4); padding: var(--sp-4); background: var(--bg-surface); border: 1px solid var(--stroke-default); border-radius: var(--radius-pill); margin-bottom: var(--sp-24); }
.tab { padding: var(--sp-8) var(--sp-16); border-radius: var(--radius-pill); font-weight: 600; font-size: 13px; color: var(--text-secondary); cursor: pointer; border: none; background: transparent; transition: all .16s var(--ease); }
.tab:hover { color: var(--text-primary); }
/* Las pestañas de los listados son <label> con un radio dentro: el navegador
   lleva el estado y lo manda con el formulario, sin una URL por pestaña.
   El radio se esconde con opacidad y no con display:none para que siga siendo
   navegable con teclado y lo anuncie el lector de pantalla. */
.tab input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.tab:has(input:focus-visible) { outline: 2px solid var(--accent); outline-offset: 2px; }
/* La pestaña marcada la pinta el radio, no una clase del servidor: el
   formulario no se reemplaza nunca, así que una clase se quedaría vieja. Y de
   paso el resaltado es instantáneo, sin esperar la respuesta. */
.tab:has(input:checked) { background: var(--accent); color: var(--text-on-accent); box-shadow: var(--glow-subtle); }

/* Filtro de listado: pestañas y buscador en la misma línea; en móvil, apilados. */
.filtros { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sp-12); margin-bottom: var(--sp-24); }
.filtros .tabs { margin-bottom: 0; }
.buscador { flex: 1; min-width: 200px; max-width: 320px; }

/* Casilla de edición en línea dentro de una tabla: no debe pesar más que el
   dato que acompaña. */
.input-inline { padding: var(--sp-4) var(--sp-8); font-size: 13px; }

/* Progress */
.progress { height: 8px; background: var(--bg-surface); border-radius: var(--radius-pill); overflow: hidden; border: 1px solid var(--stroke-default); }
.progress > span { display: block; height: 100%; background: var(--accent); border-radius: var(--radius-pill); box-shadow: var(--glow-subtle); transition: width .4s var(--ease); }

/* Timeline */
.timeline { position: relative; padding-left: var(--sp-24); }
.timeline::before { content: ""; position: absolute; left: 7px; top: 6px; bottom: 6px; width: 2px; background: var(--stroke-default); }
.tl-item { position: relative; padding-bottom: var(--sp-24); }
.tl-item:last-child { padding-bottom: 0; }
.tl-dot { position: absolute; left: calc(-1 * var(--sp-24) + 1px); top: 4px; width: 14px; height: 14px; border-radius: 50%; background: var(--bg-elevated); border: 2px solid var(--accent); box-shadow: var(--glow-subtle); }
.tl-dot.success { border-color: var(--success); } .tl-dot.warning { border-color: var(--warning); } .tl-dot.info { border-color: var(--info); }
.tl-time { font-size: 11.5px; color: var(--text-muted); margin-bottom: var(--sp-4); }
.tl-body { background: var(--bg-surface); border: 1px solid var(--stroke-default); border-radius: var(--radius-sm); padding: var(--sp-12) var(--sp-16); }
.tl-body .author { font-size: 11.5px; color: var(--accent); font-weight: 600; }
/* En la actividad reciente la entrada entera es un enlace a su tarea. */
a.tl-body { display: block; transition: border-color .18s var(--ease); }
a.tl-body:hover { border-color: var(--accent-line); }

/* Chat (emails) */
/* El chat scrollea solo: con hilos largos (20+ mensajes) la página entera se
   volvía de 4 pantallas y la lista de tareas se iba con el scroll. */
.chat {
  display: flex; flex-direction: column; gap: var(--sp-12);
  max-height: 62vh; overflow-y: auto; overscroll-behavior: contain;
  padding-right: var(--sp-8);
}
.bubble { max-width: 74%; padding: var(--sp-12) var(--sp-16); border-radius: var(--radius); box-shadow: var(--shadow-sm); }
.bubble .from { font-size: 11px; opacity: .8; margin-bottom: var(--sp-4); }
.bubble.inbound  { align-self: flex-start; background: var(--bg-surface); border: 1px solid var(--stroke-default); border-bottom-left-radius: var(--sp-4); }
.bubble.outbound { align-self: flex-end; background: var(--accent); color: var(--text-on-accent); border-bottom-right-radius: var(--sp-4); }
.bubble .time { font-size: 10.5px; opacity: .7; margin-top: var(--sp-4); text-align: right; }

/* Table */
.tbl { width: 100%; border-collapse: collapse; }
.tbl th { text-align: left; font-size: 11px; text-transform: uppercase; letter-spacing: 0.05em; color: var(--text-muted); padding: var(--sp-8) var(--sp-12); border-bottom: 1px solid var(--stroke-default); }
.tbl td { padding: var(--sp-12); border-bottom: 1px solid var(--stroke-default); }
.tbl tr:last-child td { border-bottom: none; }
/* Ficha de cuenta. Era una tabla de cuatro columnas con cinco botones en la
   última: la columna de acciones le robaba el ancho al nombre y, al encogerla,
   los botones desbordaban sobre la columna de al lado. Una ficha apila bloques
   y no tiene anchos que negociar. */
.cuenta { display: flex; flex-direction: column; gap: var(--sp-8); }
.cuenta-top { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-12); }
.cuenta-badges { display: flex; flex-wrap: wrap; gap: var(--sp-6); }
/* Notas de apoyo (tareas, MFA, sesión): en línea y en gris. Antes ocupaban un
   renglón cada una y pesaban más que el nombre de la cuenta. */
.cuenta-notas { display: flex; flex-wrap: wrap; gap: var(--sp-4) var(--sp-12); font-size: 12px; color: var(--text-muted); }
.cuenta-acciones { display: flex; flex-wrap: wrap; gap: var(--sp-6); padding-top: var(--sp-8); border-top: 1px solid var(--stroke-default); }
/* Los botones de gestión son secundarios: no deben pesar como el contenido. */
.cuenta-acciones .btn { padding: var(--sp-4) var(--sp-8); font-size: 12px; min-height: 0; }
.alias-form { display: flex; align-items: center; gap: var(--sp-8); }
.alias-form .input { flex: 1; min-width: 0; }
.tbl tr:hover td { background: var(--bg-hover); }

/* Task row */
.task-row { display: flex; align-items: center; gap: var(--sp-16); padding: var(--sp-16); }
.task-row .t-title { font-weight: 600; }
.task-row .t-meta { font-size: 12px; color: var(--text-muted); }

/* Login */
.login-wrap { min-height: 100vh; display: grid; place-items: center; padding: var(--sp-24); position: relative; overflow: hidden; }
.login-wrap::before { content: ""; position: absolute; width: 520px; height: 520px; border-radius: 50%; background: var(--accent); opacity: .10; filter: blur(120px); top: -120px; right: -80px; }
.login-card { width: 100%; max-width: 400px; background: var(--bg-acrylic); backdrop-filter: blur(24px) saturate(1.8); border: 1px solid var(--stroke-strong); border-radius: var(--radius-xl); padding: var(--sp-40) var(--sp-32); box-shadow: var(--shadow-lg); position: relative; }
.login-card .brand { padding: 0 0 var(--sp-24); border-bottom: none; margin-bottom: 0; }
.login-card .logo-mark { height: 56px; }
.login-card .logo-word { height: 24px; }
.mfa-card { max-width: 480px; }
.mfa-qr {
  display: block;
  width: min(256px, 100%);
  height: auto;
  margin: 18px auto;
  padding: 10px;
  border-radius: 16px;
  background: #fff;
}
.mfa-secret {
  display: block;
  padding: 12px;
  overflow-wrap: anywhere;
  text-align: center;
  letter-spacing: .08em;
  border: 1px solid var(--stroke);
  border-radius: 10px;
}
.recovery-grid {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 8px;
}
.recovery-grid code {
  padding: 10px;
  text-align: center;
  border: 1px solid var(--stroke);
  border-radius: 8px;
}
/* Cuentas demo: un toque rellena correo y contraseña. */
  display: flex; align-items: center; justify-content: space-between; gap: var(--sp-8);
  width: 100%; margin-top: var(--sp-6); padding: var(--sp-8) var(--sp-10);
  background: var(--bg-surface); border: 1px solid var(--stroke-default);
  border-radius: var(--radius-sm); cursor: pointer; text-align: left;
  font-size: 11.5px; color: var(--text-secondary);
  transition: all .16s var(--ease);
}
.alert-danger { background: var(--danger-soft); color: var(--danger); border: 1px solid var(--danger); border-radius: var(--radius-sm); padding: var(--sp-12); font-size: 13px; margin-bottom: var(--sp-16); }
/* Un mantenimiento no es un error: no debe pintarse en rojo de fallo. */
.alert-warning { background: var(--warning-soft); color: var(--warning); border: 1px solid var(--warning); border-radius: var(--radius-sm); padding: var(--sp-12); font-size: 13px; margin-bottom: var(--sp-16); }
.alert-warning a { color: inherit; }

/* Section header */
.section-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: var(--sp-16); }

/* Empty state */
.empty { text-align: center; padding: var(--sp-48) var(--sp-24); color: var(--text-muted); }
.empty .ico { font-size: 40px; opacity: .5; margin-bottom: var(--sp-12); }

/* Banner "vista cliente" (abogado/admin) */
.client-banner { background: var(--accent-soft); color: var(--accent); border-bottom: 1px solid var(--accent-line); padding: var(--sp-8) var(--sp-32); font-size: 12.5px; font-weight: 500; }
.activation-banner { background: var(--warning-soft); color: var(--warning); border-bottom: 1px solid var(--warning); padding: var(--sp-8) var(--sp-32); font-size: 12.5px; font-weight: 600; }
.client-picker { display: flex; align-items: center; gap: var(--sp-8); min-width: 0; }
/* Un <option> no envuelve nunca —el overflow-wrap global no lo alcanza— y el
   <select> se dimensiona según su opción más ancha. Sin tope, un nombre de
   cliente largo ensancha la barra y con ella la página entera. El min-width:0
   es imprescindible: sin él un hijo de flex no baja de su ancho de contenido.
   La regla de móvil (bloque @media del final) lo deja ocupar toda su fila. */
.client-picker .select { min-width: 0; max-width: 240px; }

/* Radiografía 360° */
.radio-hero { display: flex; align-items: center; gap: var(--sp-20); }
.radio-hero h2 { margin: 0 0 var(--sp-4); }
.radio-hero .btn { margin-left: auto; flex-shrink: 0; }
.radio-progress-empty { min-height: 55vh; display: flex; flex-direction: column; align-items: center; justify-content: center; text-align: center; gap: var(--sp-12); max-width: 620px; margin: 0 auto; }
.radio-progress-empty h2 { margin: 0; }
.radio-progress-empty p { max-width: 540px; }
.radio-progress-mark { font-size: 36px; line-height: 1; opacity: .85; }
.radio-light { display: flex; flex-direction: column; align-items: center; gap: var(--sp-4); min-width: 70px; font-size: 12px; }
.radio-light span { width: 38px; height: 38px; border-radius: 50%; background: var(--danger); box-shadow: 0 0 0 7px var(--danger-soft); }
.radio-light.yellow span { background: var(--warning); box-shadow: 0 0 0 7px var(--warning-soft); }
.radio-light.green span { background: var(--success); box-shadow: 0 0 0 7px var(--success-soft); }
.milestone { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12); padding: var(--sp-12) 0; border-bottom: 1px solid var(--stroke-default); }
.milestone .badge { flex: 0 0 auto; text-align: center; }
.milestone:last-child { border-bottom: none; }
.homologation-action { display: grid; grid-template-columns: 120px minmax(0, 1fr) auto auto; align-items: end; gap: var(--sp-8); }
.homologation-action label { display: block; margin-bottom: var(--sp-6); }
.plan-timeline { position: relative; display: flex; justify-content: space-between; margin: var(--sp-32) var(--sp-20) var(--sp-8); padding-top: var(--sp-4); }
.plan-timeline-line { position: absolute; top: 12px; left: 0; right: 0; height: 3px; background: var(--stroke-default); border-radius: var(--radius-pill); }
.plan-timeline-line span { display: block; height: 100%; background: var(--accent); border-radius: inherit; transition: width .3s var(--ease); }
.plan-timeline-step { position: relative; z-index: 1; display: flex; flex-direction: column; align-items: center; gap: var(--sp-6); color: var(--text-muted); font-size: 11.5px; }
.plan-timeline-step > span { width: 18px; height: 18px; border-radius: 50%; background: var(--bg-elevated); border: 3px solid var(--stroke-strong); }
.plan-timeline-step.done { color: var(--accent); }.plan-timeline-step.done > span { background: var(--accent); border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.plan-timeline-step.current > span { border-color: var(--accent); box-shadow: 0 0 0 4px var(--accent-soft); }
.plan-timeline-caption { position: absolute; top: calc(var(--sp-32) + var(--sp-8)); left: 0; right: 0; text-align: center; font-size: 11.5px; color: var(--text-muted); }
.plan-await { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-16); margin: var(--sp-24) 0; padding: var(--sp-16) 0; border-top: 1px solid var(--stroke-default); border-bottom: 1px solid var(--stroke-default); }

/* Meta rows (detalle tarea, etc.) */
.meta-row { display: flex; flex-wrap: wrap; gap: var(--sp-24); align-items: center; }
.meta-row .k { color: var(--text-muted); font-size: 12px; margin-right: var(--sp-6); }
.meta-row .v { font-weight: 600; }

/* Backlink chip a tarea */
.task-link { display: inline-flex; align-items: center; gap: var(--sp-6); font-size: 12px; color: var(--accent); font-weight: 600; }
.task-link:hover { text-decoration: underline; }

/* «Ver más» de una descripción larga: <details> nativo, sin JS. Al abrirse, el
   texto completo SUSTITUYE al fragmento en vez de repetirlo debajo, y el
   enlace cambia a «Ver menos» para que se pueda cerrar: un desplegable de ida
   y sin vuelta deja la lista rota hasta recargar. */
.ver-mas > summary { display: block; list-style: none; cursor: pointer; }
.ver-mas > summary::-webkit-details-marker { display: none; }
.ver-mas > summary::marker { content: ""; }
.ver-mas[open] .ver-mas-corto { display: none; }
.ver-mas .v-menos, .ver-mas[open] .v-mas { display: none; }
.ver-mas[open] .v-menos { display: inline; }
.ver-mas-link { color: var(--accent); font-weight: 600; font-size: 12px; white-space: nowrap; }
.ver-mas-link:hover { text-decoration: underline; }

/* Folder card rediseñada (#9): banner con ícono centrado, sin ícono a la izquierda */
.folder-card { background: var(--bg-elevated); border: 1px solid var(--stroke-default); border-radius: var(--radius); box-shadow: var(--shadow-sm); overflow: hidden; transition: transform .18s var(--ease), box-shadow .18s var(--ease), border-color .18s var(--ease); }
.folder-card:hover { transform: translateY(-3px); box-shadow: var(--shadow-md); border-color: var(--accent-line); }
.folder-card .fc-top { position: relative; background: var(--accent-soft); padding: var(--sp-24) var(--sp-16); display: grid; place-items: center; font-size: 40px; }
.folder-card .fc-top::before { content: ""; position: absolute; top: 0; left: var(--sp-16); width: 46px; height: 8px; background: var(--accent); border-radius: 0 0 6px 6px; }
.folder-card .fc-body { padding: var(--sp-16); display: flex; align-items: center; justify-content: space-between; gap: var(--sp-12); }
.folder-card .fc-name { font-weight: 600; }
/* Las acciones van fuera del <a> de la tarjeta: no se pueden anidar botones
   dentro de un enlace. Aparecen al pasar el mouse sobre la tarjeta. */
.folder-wrap { position: relative; }
.folder-wrap .folder-actions {
  position: absolute; top: var(--sp-8); right: var(--sp-8);
  display: flex; gap: var(--sp-4); opacity: 0; transition: opacity .16s var(--ease);
}
.folder-wrap:hover .folder-actions, .folder-wrap:focus-within .folder-actions { opacity: 1; }

/* ---------- DENSIDAD ----------
   Regla única para toda lista larga: 6 items visibles, el resto tras "Ver más".
   Es CSS + un listener, sin paginación en el servidor: los volúmenes reales son
   de decenas de items, no de miles.
   ponytail: paginar en el backend resolvería un problema que no tenemos. */
.list-capped > *:nth-child(n+7) { display: none; }
.list-capped.expanded > * { display: revert; }
.list-more { width: 100%; margin-top: var(--sp-12); }
/* Listas con scroll propio dentro de una tarjeta (chat, listas laterales). */
.list-scroll { max-height: 420px; overflow-y: auto; overscroll-behavior: contain; }
.activity-scroll { max-height: 420px; padding-right: var(--sp-8); overflow-y: auto; overscroll-behavior: contain; }

/* Filas de tabla que abren su propio detalle al hacer click. */
.row-clickable { cursor: pointer; }
.row-clickable:hover { background: var(--bg-hover); }

/* ---------- SECCIONES COLAPSABLES ----------
   <details> nativo: el estado abierto/cerrado lo lleva el propio HTML, así que
   no hace falta una línea de JS. El servidor manda los avisos cerrados (con su
   contador a la vista) y las listas abiertas; en escritorio el CSS reabre todo
   y el encabezado deja de ser un control, para que se vea como siempre. */
.seccion > summary { display: flex; align-items: center; gap: var(--sp-12); list-style: none; }
.seccion > summary::-webkit-details-marker { display: none; }
.seccion > summary::marker { content: ""; }
.seccion > summary .nav-badge { margin-left: 0; }
.seccion[open] > summary { margin-bottom: var(--sp-12); }
.sec-chev { color: var(--text-muted); font-size: 11px; transition: transform .18s var(--ease); }
.seccion[open] > summary .sec-chev { transform: rotate(180deg); }
/* Los enlaces del encabezado (p. ej. "Ver todas") navegan, no colapsan. */
.seccion > summary .btn { pointer-events: auto; }

/* Fila de aviso: texto a la izquierda, acciones a la derecha. */
.sec-row { display: flex; align-items: center; gap: var(--sp-16); }

/* Fila desplegable dentro de una tarjeta (resumen semanal): de la cifra al
   detalle sin cambiar de página.
   NO usa .seccion a propósito: aquélla se reabre sola en escritorio, y aquí el
   punto es justo que empiece cerrada aunque haya sitio de sobra. */
.seccion-fila { border-top: 1px solid var(--stroke-default); }
.seccion-fila:first-of-type { border-top: none; }
.seccion-fila > summary {
  display: flex; align-items: center; gap: var(--sp-12);
  padding: var(--sp-12) 0; cursor: pointer; list-style: none;
}
.seccion-fila > summary::-webkit-details-marker { display: none; }
.seccion-fila > summary::marker { content: ""; }
.seccion-fila > summary:hover { color: var(--accent); }
.seccion-fila[open] > summary .sec-chev { transform: rotate(180deg); }
/* El detalle va sangrado para que se lea como hijo de la fila y no como otra. */
.seccion-fila > .dl-row, .seccion-fila > .text-sm { padding-left: var(--sp-16); }

@media (min-width: 861px) {
  /* `revert` volvía al display:none nativo de <details> cerrado en Chrome.
     Cada hijo se reabre con su display real para escritorio. */
  .seccion:not([open]) > .dl-row, .seccion:not([open]) > .sec-row { display: flex !important; }
  .seccion:not([open]) > .card { display: block !important; }
  .seccion > summary { pointer-events: none; margin-bottom: var(--sp-12); }
  .sec-chev, .seccion > summary .nav-badge { display: none; }
}
@media (max-width: 860px) {
  .seccion > summary { cursor: pointer; min-height: 44px; }
  /* Apilada, la actividad va primero: cerrada ocupa una línea y deja las
     tareas —lo accionable— arriba del pliegue. En escritorio sigue siendo la
     columna derecha, así que el orden del DOM no se toca. */
  .sec-actividad { order: -1; }
  .activity-scroll { max-height: none; padding-right: 0; overflow: visible; }
  /* El texto no puede competir por el ancho con botones que no se encogen:
     bajo 640px se lleva la primera línea entera y las acciones caen abajo. */
  .sec-row { flex-wrap: wrap; }
  .sec-row > .flex-1 { flex-basis: 100%; }
  .sec-row > .btn { flex: 1; }
}

/* Definition list (datos de transferencia) */
.dl { display: flex; flex-direction: column; }
.dl-row { display: flex; justify-content: space-between; gap: var(--sp-16); padding: var(--sp-8) 0; border-top: 1px solid var(--stroke-default); font-size: 13px; }
.dl-row:first-child { border-top: none; }
.dl-row .k { color: var(--text-muted); }
.dl-row .v { font-weight: 600; text-align: right; word-break: break-word; }

/* Modal (HTMX fragment) */
.modal-overlay { position: fixed; inset: 0; background: var(--bg-overlay); backdrop-filter: blur(4px); display: grid; place-items: center; z-index: 200; padding: var(--sp-24); animation: fadeIn .15s var(--ease); }
/* max-height + scroll interno: los formularios largos (firma, tarea) se salían
   de la pantalla y no había forma de llegar al botón Guardar. */
.modal-frame { position: relative; width: min(460px, 100%); max-height: calc(100dvh - 48px); }
.modal { background: var(--bg-acrylic); backdrop-filter: blur(24px) saturate(1.8); border: 1px solid var(--stroke-strong); border-radius: var(--radius-xl); box-shadow: var(--shadow-lg); padding: var(--sp-32); width: 100%; max-height: inherit; overflow-y: auto; overscroll-behavior: contain; scrollbar-gutter: stable; animation: slideUp .25s var(--ease); }
.modal .modal-head { display: flex; align-items: flex-start; justify-content: space-between; gap: var(--sp-16); margin-bottom: var(--sp-16); }
.modal-x { position: absolute; z-index: 1; top: -14px; right: -14px; display: grid; place-items: center; width: 36px; height: 36px; padding: 0; border: 1px solid var(--stroke-strong); border-radius: 50%; background: var(--bg-elevated); box-shadow: var(--shadow-sm); font-size: 20px; cursor: pointer; color: var(--text-muted); line-height: 1; }
.modal-x:hover { color: var(--text-primary); border-color: var(--accent); }

/* Progreso de exceso (rojo) */
.progress.danger > span { background: var(--danger); box-shadow: none; }
.progress.success > span { background: var(--success); box-shadow: none; }

/* Badge numérico en nav */
.nav-badge { margin-left: auto; background: var(--danger); color: #fff; font-size: 10px; font-weight: 700; min-width: 18px; height: 18px; padding: 0 5px; border-radius: var(--radius-pill); display: inline-grid; place-items: center; }

/* Mensajes: layout con selector de tareas */
.msg-layout { display: grid; grid-template-columns: 260px 1fr; gap: var(--sp-16); align-items: start; }
.msg-tasklist { display: flex; flex-direction: column; gap: var(--sp-6); }
.msg-task { display: flex; flex-direction: column; gap: 2px; text-align: left; padding: var(--sp-12); border-radius: var(--radius-sm); border: 1px solid var(--stroke-default); background: var(--bg-surface); cursor: pointer; font-size: 13px; font-weight: 500; color: var(--text-secondary); transition: all .16s var(--ease); }
.msg-task:hover { color: var(--text-primary); border-color: var(--stroke-strong); }
.msg-task.active { border-color: var(--accent-line); background: var(--accent-soft); color: var(--accent); }
@media (max-width: 760px) { .msg-layout { grid-template-columns: 1fr; } }

/* Recursos: portada e iframe */
.res-cover { aspect-ratio: 16 / 9; width: 100%; object-fit: cover; background: var(--bg-surface); border-bottom: 1px solid var(--stroke-default); }
.res-embed { aspect-ratio: 16 / 9; width: 100%; border: 0; display: block; }
.res-card { padding: 0; overflow: hidden; }
.res-card .res-body { padding: var(--sp-16); }

/* Toast (boost, etc.) */
.toast { position: fixed; bottom: var(--sp-24); left: 50%; transform: translateX(-50%); background: var(--bg-elevated); border: 1px solid var(--accent-line); color: var(--text-primary); padding: var(--sp-12) var(--sp-20); border-radius: var(--radius-pill); box-shadow: var(--shadow-lg); z-index: 300; font-weight: 600; font-size: 13px; animation: slideUp .2s var(--ease); }

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

/* Animations */
@keyframes slideUp { from { opacity: 0; transform: translateY(10px); } to { opacity: 1; transform: translateY(0); } }
.content > * { animation: slideUp .3s var(--ease) both; }
.htmx-swapping { opacity: 0; transition: opacity .1s; }

/* ---------- MOBILE ----------
   El transform sobre .sidebar es seguro: #modal-slot vive a nivel <body>,
   fuera del sidebar, así que no rompe el position:fixed de los modales. */
@media (max-width: 860px) {
  .app { grid-template-columns: 1fr; }

  .sidebar {
    position: fixed; top: 0; left: 0; bottom: auto; height: 100dvh;
    width: 272px; max-width: 86vw; z-index: 100;
    overflow-y: auto; overscroll-behavior: contain;
    padding-bottom: calc(var(--sp-20) + env(safe-area-inset-bottom));
    transform: translateX(-100%); transition: transform .22s var(--ease);
    box-shadow: var(--shadow-lg);
  }
  .sidebar.open { transform: translateX(0); }

  .sidebar-backdrop {
    position: fixed; inset: 0; z-index: 90;
    background: var(--bg-overlay); backdrop-filter: blur(5px);
    -webkit-backdrop-filter: blur(5px); opacity: 0;
    pointer-events: none; transition: opacity .22s var(--ease);
  }
  .sidebar-backdrop.open { opacity: 1; pointer-events: auto; }

  /* el display lo controla el CSS, no un style inline en el HTML */
  #burger { display: inline-flex !important; align-items: center; }

  .topbar {
    display: grid; grid-template-columns: minmax(0, 1fr) 44px;
    grid-template-areas: "title burger" "picker picker";
    gap: var(--sp-4) var(--sp-12);
    padding: var(--sp-8) var(--sp-16); height: auto;
  }
  .topbar-title { grid-area: title; min-width: 0; }
  .topbar-actions { display: contents; }
  .topbar h1 { font-size: 17px; }
  .topbar .sub { font-size: 11.5px; }
  .client-picker { grid-area: picker; width: 100%; display: flex; align-items: center; gap: var(--sp-8); }
  /* El flex:1 no llega a surtir efecto: el hijo flex de .client-picker es el
     <form> que envuelve al select, no el select. Se conserva porque el
     min-width:0 sí lo necesita, y el tope de 240px de arriba es lo que de
     verdad impide que un nombre largo ensanche la fila. */
  .client-picker .select { flex: 1; min-width: 0; width: auto !important; }
  #burger { grid-area: burger; justify-self: end; }

  .content { padding: var(--sp-16); }
  .card { padding: var(--sp-16); }

  /* Tablas: scrollean dentro de su tarjeta en vez de desbordar la página. */
  .card:has(> .tbl) { overflow-x: auto; }
  .tbl { min-width: 560px; }

  /* Objetivos táctiles: 44px es el mínimo con el que un dedo no falla.
     Los ítems del menú y los íconos del pie estaban en 37px y 25px. */
  .nav-item { padding: var(--sp-12); min-height: 44px; }
  .user-chip .ico { min-width: 44px; min-height: 44px; display: grid; place-items: center; }
  .user-action { flex: 0 0 44px; }
  #burger { min-width: 44px; min-height: 44px; }
  .btn-sm { min-height: 40px; }

  /* El banner de la carpeta era medio alto de tarjeta para un emoji solo. */
  .folder-card .fc-top { padding: var(--sp-12); font-size: 30px; }
	.radio-hero { align-items: flex-start; flex-wrap: wrap; }
	.radio-hero .btn { margin-left: 0; }
	.plan-timeline { margin-left: var(--sp-8); margin-right: var(--sp-8); }
	.plan-await { align-items: flex-start; flex-direction: column; }
	.homologation-action { grid-template-columns: 1fr 1fr; }
	.homologation-action .btn { width: 100%; }

  .dl-row, .meta-row { flex-wrap: wrap; gap: var(--sp-6); }
  /* Las pestañas eran inline-flex con width:100%: el ancho no lo usaba nadie y
     quedaban pegadas a la izquierda. Y al apretarse, «Todos» y «Activos» se
     partían en dos líneas y la píldora los cortaba.
     display:flex reparte el sobrante entre las pestañas (Todas/Clientes/
     Abogados llenan la fila), y flex-shrink:0 + nowrap impide que se aplasten:
     cuando no caben —«Pendientes de activación»— la fila se desliza. */
  .tabs { display: flex; width: 100%; overflow-x: auto; }
  .tab { flex: 1 0 auto; white-space: nowrap; text-align: center; }
  .list-scroll { max-height: 320px; }
}

/* Métrica compacta: ícono y cifra en la misma línea, etiqueta debajo. En
   vertical cada tarjeta medía 131px de alto para un número de dos dígitos. */
@media (max-width: 640px) {
  .topbar .sub, .client-picker .text-xs { display: none; }
  .metric { flex-direction: row; align-items: center; flex-wrap: wrap; gap: var(--sp-8); }
  .metric .ico-box { width: 30px; height: 30px; font-size: 15px; margin: 0; }
  .metric .value { font-size: 24px; }
  .metric .label { width: 100%; font-size: 11.5px; line-height: 1.3; }
}

/* Tarjeta de tarea compacta: el título a 16px se partía en dos líneas de 25px
   y con el padding de 16 la tarjeta llegaba a 134px de alto. */
@media (max-width: 640px) {
  .task-card { padding: var(--sp-12); }
  .task-card .text-lg { font-size: 14.5px; line-height: 1.3; }
  .task-card .flex.gap-16 { gap: var(--sp-12); }
}

@media (max-width: 480px) {
  .content { padding: var(--sp-12); }
  .btn { padding: var(--sp-8) var(--sp-12); font-size: 13px; }
  .metric .value { font-size: 22px; }
  .modal { padding: var(--sp-20); }
  .modal-x { top: -10px; right: -8px; }
  .login-wrap { min-height: 100dvh; padding-bottom: calc(var(--sp-24) + env(safe-area-inset-bottom)); }
}

/* ---- Tablero kanban ----
   Tres columnas EN FILA y cada una con su propio scroll. Apiladas se robarían
   el gesto de desplazar —la regla de «una sola caja con scroll por pantalla»—;
   una al lado de otra, cada columna gobierna la suya y la página no crece.
   La altura sale del alto de ventana menos la cabecera, para que las tres
   acaben a la misma línea sin depender de cuántas tarjetas tenga cada una. */
.kanban {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--sp-12);
  align-items: start;
}
.kan-col {
  display: flex;
  flex-direction: column;
  min-width: 0;
  max-height: calc(100vh - 260px);
  background: var(--bg-surface);
  border: 1px solid var(--stroke-default);
  border-radius: var(--radius);
}
.kan-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-8);
  padding: var(--sp-12);
  font-weight: 600;
  font-size: 13px;
  border-bottom: 1px solid var(--stroke-default);
}
.kan-body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-8);
  padding: var(--sp-12);
  overflow-y: auto;
  /* Con la columna vacía sigue habiendo dónde soltar: sin altura mínima el
     área de drop mide cero y la tarjeta no se puede mover a una columna vacía. */
  min-height: 96px;
}
.kan-card {
  padding: var(--sp-12);
  background: var(--bg-elevated);
  border: 1px solid var(--stroke-default);
  border-radius: var(--radius-sm);
  cursor: grab;
}
.kan-card:active { cursor: grabbing; }
.kan-dragging { opacity: 0.4; }
.kan-over { border-color: var(--accent); box-shadow: var(--shadow-md); }
.kan-client {
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--text-muted);
  margin-bottom: var(--sp-4);
}
.kan-title { display: block; font-size: 14px; font-weight: 500; }
.kan-meta {
  display: flex;
  align-items: center;
  gap: var(--sp-8);
  flex-wrap: wrap;
  margin-top: var(--sp-8);
}
/* En pantalla estrecha las tres columnas no caben: se apilan y cada una
   recupera su altura natural, porque ya no compiten por el scroll. */
@media (max-width: 860px) {
  .kanban { grid-template-columns: 1fr; }
  .kan-col { max-height: none; }
  .kan-body { overflow-y: visible; }
}

/* ============================================================
   UTILIDADES — van al FINAL a propósito: reemplazan los style=""
   inline y deben ganarle a las reglas de componente (.card, .btn).
   Si se declaran antes, .card pisa a .border-danger y el estilo se
   pierde en silencio. Todo estilo nuevo va acá, nunca en el atributo.
   ============================================================ */
.p-0 { padding: 0; }
.m-0 { margin: 0; }
.w-auto { width: auto; }
.w-120 { width: 120px; }
.min-w-0 { min-width: 0; }
.max-w-120 { max-width: 120px; }
.max-w-520 { max-width: 520px; }
.max-w-620 { max-width: 620px; }
.max-w-860 { max-width: 860px; }
.ml-auto { margin-left: auto; }
.text-right { text-align: right; }
.text-left { text-align: left; }
.inline-block { display: inline-block; }
.d-inline { display: inline; }
.justify-end { justify-content: flex-end; }
.items-center-flex { display: flex; align-items: center; }
.capitalize { text-transform: capitalize; }
.italic { font-style: italic; }
.pointer { cursor: pointer; }
.fs-16 { font-size: 16px; }
.fs-24-bold { font-size: 24px; font-weight: 700; }
.fs-16-normal { font-size: 16px; font-weight: 400; }
.btn-compact { width: auto; padding: 6px 10px; }
.chip-xs { padding: 2px 8px; font-size: 11px; }
.border-danger { border-color: var(--danger); }
.border-warning { border-color: var(--warning); }
.border-success { border-color: var(--success); }
.border-bottom { border-bottom: 1px solid var(--stroke-default); }
.border-top-pad { border-top: 1px solid var(--stroke-default); padding-top: var(--sp-16); }
.alert-danger-soft { margin: 0; background: var(--danger-soft); color: var(--danger); }
.link-plain { color: inherit; text-decoration: none; }
.no-underline { text-decoration: none; }
.link-row { min-width: 0; flex: 1; color: inherit; text-decoration: none; }

/* Recorte con puntos suspensivos. Va en CSS y no cortando el texto en Go
   porque el punto de corte depende del ancho real de la caja —no es lo mismo
   la columna estrecha del inicio que la ficha entera— y porque el texto
   completo sigue en el HTML: se lee al abrir la tarea y lo encuentra el
   buscador del navegador. -webkit-line-clamp lo entienden todos los
   navegadores actuales, incluido Firefox. */
.recorte-1 { overflow: hidden; white-space: nowrap; text-overflow: ellipsis; }
.recorte-2 { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; line-clamp: 2; overflow: hidden; }

.card-credential { border-color: var(--accent); margin-bottom: var(--sp-16); }
.card-error { border-color: var(--danger); color: var(--danger); margin-bottom: var(--sp-16); }

/* El aviso de rechazo viaja con HTTP 200; el color es su único indicador. */
.toast-danger { border-color: var(--danger); color: var(--danger); }
.m-0 { margin: 0; }
