/* Tokens alineados al Trycore Design System (capa de producto: navy =
   autoridad, teal = acción — nunca al revés; radios con tope de 6px salvo
   la píldora reservada a CTAs/chips/badges). Mismos nombres de variable de
   siempre para no tocar el resto del CSS ni las vistas — solo cambian los
   valores. */
@import url('https://fonts.googleapis.com/css2?family=Poppins:wght@400;500;600;700&family=Karla:wght@400;500;600;700&display=swap');

:root {
  --bg: #F9F9F9;
  --surface: #FFFFFF;
  --ink: #1D2751;
  --ink-2: #4A5568;
  --line: #E5E7EB;
  --brand: #00A19A;
  --brand-2: #06C8BE;
  --brand-ink: #FFFFFF;
  --ok: #16A34A;
  --ok-bg: #DFF0D8;
  --warn: #D97706;
  --warn-bg: #FCF8E3;
  --danger: #DC2626;
  --danger-bg: #F2DEDE;
  --radius: 6px;
  --radius-btn: 999px;
  --sans: 'Karla', system-ui, -apple-system, "Segoe UI", Roboto, Arial, sans-serif;
  --display: 'Poppins', var(--sans);
  --shadow-card: 0 1px 2px rgba(29, 39, 81, .04), 0 8px 24px -12px rgba(29, 39, 81, .12);
}

/* Tokens oscuros del design system: el teal de marca (--brand/--brand-2) NO
   cambia entre temas — el sistema fuente tampoco lo redefine para oscuro,
   se lee bien sobre ambos fondos sin desaturar. Solo cambian superficies,
   texto y los colores de estado (los del sistema fuente para dark). */
:root[data-theme="dark"] {
  --bg: #0D1428;
  --surface: #1A2247;
  --ink: #F5F7FF;
  --ink-2: #9BA4C7;
  --line: #243068;
  --ok: #86D45F;
  --ok-bg: rgba(92, 163, 64, .18);
  --warn: #F2D24A;
  --warn-bg: rgba(217, 185, 23, .18);
  --danger: #F08585;
  --danger-bg: rgba(166, 66, 66, .22);
  /* Una sombra teñida de navy a baja opacidad se pierde contra un fondo ya
     oscuro — pasa a negra y sube la opacidad, mismo criterio que docfly. */
  --shadow-card: 0 1px 3px rgba(0, 0, 0, .35), 0 8px 24px -12px rgba(0, 0, 0, .5);
}

@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0D1428;
    --surface: #1A2247;
    --ink: #F5F7FF;
    --ink-2: #9BA4C7;
    --line: #243068;
    --ok: #86D45F;
    --ok-bg: rgba(92, 163, 64, .18);
    --warn: #F2D24A;
    --warn-bg: rgba(217, 185, 23, .18);
    --danger: #F08585;
    --danger-bg: rgba(166, 66, 66, .22);
    --shadow-card: 0 1px 3px rgba(0, 0, 0, .35), 0 8px 24px -12px rgba(0, 0, 0, .5);
  }
}

.theme-toggle {
  width: 34px;
  height: 34px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  cursor: pointer;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  margin: 0;
  padding: 0;
  flex: none;
}
.theme-toggle:hover { color: var(--ink); background: var(--surface); }
/* En páginas sin topbar (login/expirado/etc.) flota fijo en la esquina; en
   el shell con sidebar vive dentro del topbar, junto al menú de cuenta —
   si no, ambos se pisan encima del mismo rincón superior derecho. */
.theme-toggle-fixed { position: fixed; top: 16px; right: 16px; z-index: 40; }

* { box-sizing: border-box; }
/* overflow-x en el <body> por sí solo no basta para frenar el scroll
   horizontal del viewport — el navegador mira el <html> para eso (probado
   en vivo: con overflow-x:hidden solo en body, la página igual se dejaba
   arrastrar 150px a la derecha por los anillos decorativos de .center-page,
   aunque no hubiera barra de scroll visible). */
html { overflow-x: hidden; }
html, body { margin: 0; padding: 0; }
body {
  background: var(--bg);
  color: var(--ink-2);
  font-family: var(--sans);
  line-height: 1.55;
}

.wrap { max-width: 720px; margin: 0 auto; padding: 48px 24px; }
.wrap.narrow { max-width: 420px; }

/* Sin esto, un <a> sin clase (ej. el slug en la columna URL de la tabla de
   proyectos) cae al azul puro por defecto del navegador — se lee como una
   fuente/estilo distinto al resto de la fila (reporte real de QA). */
a { color: var(--brand); }

h1 { font-family: var(--display); font-weight: 700; font-size: 22px; color: var(--ink); margin: 0 0 8px; letter-spacing: -.01em; }
p.sub { color: var(--ink-2); margin: 0 0 24px; }

.brand-lockup { display: flex; align-items: center; justify-content: center; margin-bottom: 18px; }
.brand-lockup img { height: 28px; width: auto; background: transparent; border-radius: 5px; padding: 0; transition: background .15s ease; }
/* El logo trae tinta oscura fija en el PNG: en modo oscuro necesita un fondo claro para seguir siendo legible. */
:root[data-theme="dark"] .brand-lockup img { background: #fff; padding: 5px 8px; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .brand-lockup img { background: #fff; padding: 5px 8px; }
}

.card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
  box-shadow: var(--shadow-card);
}

label { display: block; font-size: 14px; font-weight: 700; color: var(--ink); margin: 16px 0 6px; }
/* NO "label:first-child" — esa regla también disparaba sobre una label que
   es la primera hija de un <div> envolvente A MITAD del formulario (ej.
   "Nombre del proyecto" dentro de #nuevo-proyecto-fields), no solo la
   primera del form, y le comía el margen — quedaba pegada al campo
   anterior (bug real: 0px de separación entre el <select> "Proyecto" y
   esa label, medido en vivo, contra 16px en el resto). El primer campo
   visible de un formulario casi siempre va justo después del input oculto
   del CSRF — es ESE patrón el que necesita margin:0, no "soy el primer
   hijo de cualquier contenedor". */
input[type="hidden"] + label { margin-top: 0; }
input[type="text"], input[type="password"], input[type="date"], input[type="file"], input[type="email"], input[type="tel"], select {
  width: 100%;
  padding: 10px 12px;
  border: 1px solid var(--line);
  border-radius: 6px;
  font: inherit;
  color: var(--ink);
  background: var(--bg);
}

/* ── Zona de subir archivo con borde punteado ── el input nativo ya acepta
   drag-and-drop solo (ver script en cada vista), esto es la envoltura
   visual + el hover de "algo va a caer acá" mientras se arrastra encima. */
.dropzone {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 16px 18px;
  margin-top: 6px;
  border: 1px dashed var(--line);
  border-radius: 6px;
  background: var(--bg);
  transition: border-color .15s ease, background .15s ease;
}
.dropzone.is-dragover { border-color: var(--brand); background: color-mix(in srgb, var(--brand) 6%, var(--bg)); }
.dropzone > svg { color: var(--brand); flex: none; }
.dropzone-text { font-size: 13px; color: var(--ink-2); flex: none; white-space: nowrap; }
/* El input queda dentro de la zona en vez de ser la zona entera — se le
   quita el aspecto de campo de texto (borde/fondo propios) para que no se
   vea como un input suelto pegado al ícono y al texto. */
.dropzone input[type="file"] {
  width: auto;
  flex: 1;
  min-width: 0;
  padding: 0;
  border: 0;
  background: none;
  font-size: 13px;
  color: var(--ink-2);
}

.radio-row { display: flex; gap: 16px; margin: 6px 0 0; }
.radio-row label { display: flex; align-items: center; gap: 6px; font-weight: 500; margin: 0; }
/* El azul nativo del navegador no combinaba con la paleta navy de la
   plataforma (reporte real de QA) — un solo accent-color, mismo tono que
   el resto de los controles interactivos. */
input[type="radio"], input[type="checkbox"] { accent-color: var(--brand); }

button, .btn {
  display: inline-block;
  margin-top: 20px;
  background: var(--brand);
  color: var(--brand-ink);
  border: 0;
  border-radius: var(--radius-btn);
  padding: 11px 22px;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .01em;
  /* <button> trae line-height:normal del navegador — <a>/<summary> con
     .btn no, heredan el 1.55 del body y quedan visiblemente más altos que
     el resto (reporte real de QA: "Archivos"/"Compartir" más altos que
     Inactivar/Guardar en la misma fila). Un solo valor, en la base, para
     cualquier elemento que use .btn sin importar su tag. */
  line-height: normal;
  cursor: pointer;
  text-decoration: none;
  transition: background .15s ease;
}
/* Oscurece el color de marca ACTUAL en vez de un hex fijo — con un hex fijo
   (#061542) el hover en modo oscuro se iba casi a negro sobre un fondo ya
   oscuro, perdiendo todo contraste. */
button:hover, .btn:hover { background: color-mix(in srgb, var(--brand) 82%, black); }
button.secondary, .btn.secondary { background: var(--surface); color: var(--ink-2); border: 1px solid var(--line); }
button.secondary:hover, .btn.secondary:hover { background: var(--bg); }
button.danger, .btn.danger { background: var(--danger); color: #fff; }
button.danger:hover, .btn.danger:hover { background: color-mix(in srgb, var(--danger) 82%, black); }

/* Sin esto, el foco por teclado cae al azul/violeta del navegador — que
   sobre un botón rojo (Inactivar) choca y se ve "distinto a los demás"
   (reporte real). Un solo anillo, mismo color de marca, en todos. */
button:focus-visible, .btn:focus-visible {
  outline: 2px solid var(--brand);
  outline-offset: 2px;
}

/* ── Botones/links chicos de fila (tablas, listas de archivos) — un solo
   componente reusado en vez de inline styles repetidos con leves
   variaciones cada vez (esa inconsistencia era justo lo que se veía
   "cambiante" entre una fila y otra). ── */
.btn-sm { margin: 0; padding: 6px 10px; font-size: 12px; border-radius: 6px; }
.link-sm {
  font-size: 12px;
  color: var(--ink-2);
  text-decoration: none;
  white-space: nowrap;
  cursor: pointer;
}
.link-sm:hover { color: var(--brand); }

.error { color: var(--danger); font-size: 13px; margin-top: 12px; }
.success { color: var(--ok); font-size: 13px; margin-top: 12px; }

table { width: 100%; border-collapse: collapse; margin-top: 16px; font-size: 14px; }

/* ── Tabla de Proyectos: CSS grid en vez de <table> ── mismas reglas de
   fondo que tenía la tabla (ancho mínimo propio en vez de table-layout,
   columna Estado centrada, sin overflow-x propio para que sea la página
   completa la que scrollee horizontal en ventanas angostas, no una caja
   aparte adentro — confirmado en vivo que un scroll anidado se sentía peor
   que uno de página completa). grid-template-columns reemplaza los % por
   columna: Nombre/URL absorben lo que sobra, el resto tiene un mínimo fijo
   para que badges y botones nunca se salgan de su columna. */
.proj-grid { width: 100%; margin-top: 16px; font-size: 14px; min-width: 860px; }
/* El header y cada fila son grids INDEPENDIENTES (no un único <table> con
   filas que comparten columnas automáticamente) — "1fr" a secas es en
   realidad "minmax(auto,1fr)": la columna no puede achicarse por debajo
   del contenido que tenga DENTRO. Bug real visto en producción: la columna
   Acceso de una fila (con badges largos + botón "Compartir") empuja su
   propio ancho mínimo más allá de su reparto de 1fr, robándole espacio a
   Nombre/URL en ESA fila — pero el header, que solo tiene la palabra
   "Acceso", no tiene ese mínimo y sí reparte parejo. Resultado: columnas
   que no calzan entre el header y las filas. minmax(0,Nfr) fuerza a que el
   reparto sea siempre el mismo sin importar qué tan largo sea el contenido
   de adentro (el contenido se envuelve con overflow-wrap en vez de forzar
   la columna a crecer). */
.proj-grid-head,
.proj-row {
  display: grid;
  grid-template-columns: minmax(0, 1.5fr) minmax(0, 1.1fr) 150px 96px minmax(0, 1fr) 128px;
  gap: 14px;
}
.proj-grid-head > div { padding: 12px 8px; border-bottom: 1px solid var(--line); overflow-wrap: break-word; min-width: 0; }
/* Un borde por FILA completa, no uno por celda — con un borde por celda,
   la columna Acceso (mucho más alta que Nombre/Estado) hacía que cada
   columna cortara su línea a una altura distinta, viéndose como varias
   rayas quebradas en vez de un separador limpio por proyecto (reporte real
   de QA). align-items:center en vez de align-self:start en cada celda:
   así cada columna corta queda centrada respecto al alto real de la fila
   (el que marca la columna más alta), no pegada arriba con aire vacío
   debajo. */
.proj-row {
  border-bottom: 1px solid var(--line);
  align-items: center;
}
.proj-row > div { padding: 12px 8px; overflow-wrap: break-word; min-width: 0; }
.proj-grid-head > div {
  color: var(--ink-2);
  font-weight: 600;
  font-size: 11px;
  text-transform: uppercase;
  letter-spacing: .05em;
  background: var(--bg);
}
/* Estado, centrado — badge y botón alineados igual que el resto de
   columnas de estado/acción, en vez de pegados al borde izquierdo
   (reporte real de QA). */
.proj-grid-head > div:nth-child(4),
.proj-row > div:nth-child(4) { text-align: center; }

/* El <input type=date> nativo tiene un ancho mínimo que no cede (~124px) —
   en línea con el botón Guardar, en una columna angosta, el botón se salía
   de la celda y se montaba sobre la columna Estado (reporte real de QA,
   confirmado midiendo en vivo: 89px de solape a 1024px de ancho). Apilados
   en vez de en línea, nunca dependen del ancho disponible. */
.expiracion-form { display: flex; flex-direction: column; gap: 6px; align-items: stretch; }
.expiracion-form input[type="date"] { width: 100%; min-width: 0; padding: 4px 6px; font-size: 12px; }
th, td { text-align: left; padding: 12px 8px; border-bottom: 1px solid var(--line); vertical-align: top; }
th { color: var(--ink-2); font-weight: 600; font-size: 11px; text-transform: uppercase; letter-spacing: .05em; background: var(--bg); }
/* Sin zebra striping — los bordes ya separan las filas; el hover basta
   para marcar la fila sobre la que está el mouse. */
tbody tr:hover > td { background: var(--bg); }

.badge { display: inline-block; padding: 2px 8px; border-radius: 99px; font-size: 12px; font-weight: 600; }
.badge + .badge { margin-left: 4px; }
.badge.public { background: var(--ok-bg); color: var(--ok); }
/* --brand (teal) es solo para acción/interacción, nunca para señalar un
   estado — estos badges son informativos (qué tipo de acceso tiene el
   enlace), así que usan --ink (navy = autoridad/neutro), no --brand. */
.badge.password, .badge.email { background: rgba(1, 14, 77, .08); color: var(--ink); }
.badge.expired { background: var(--danger-bg); color: var(--danger); }
.badge.revoked { background: rgba(29, 39, 81, .08); color: var(--ink-2); }

.topbar { display: flex; align-items: center; justify-content: space-between; margin-bottom: 24px; }
.topbar .who { font-size: 13px; color: var(--ink-2); }
.topbar a { color: var(--ink-2); font-size: 13px; }
.topbar .brand-lockup { margin: 0; }
.topbar .brand-lockup img { height: 20px; }

/* Anillos orbitales de fondo — motivo de marca de Trycore ("Frecuencia
   Orbitacional"), puramente decorativo. Con pseudo-elementos en vez de
   markup nuevo: aplica igual a las 6 páginas que ya comparten esta clase
   (login, login-email, magic-sent, expired, not-found, admin-login) sin
   tocar cada vista. La tarjeta va con z-index encima; los anillos nunca
   deben interceptar clics (pointer-events:none). */
.center-page { min-height: 100vh; display: flex; align-items: center; justify-content: center; position: relative; overflow-x: hidden; }
.center-page::before,
.center-page::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  pointer-events: none;
  z-index: 0;
}
.center-page::before { top: -190px; right: -150px; width: 620px; height: 620px; border: 1px solid var(--line); }
.center-page::after { bottom: -230px; left: -170px; width: 560px; height: 560px; border: 1px solid var(--line); }
/* pointer-events:none de arriba ya evita que los anillos intercepten
   clics — no hace falta subir el z-index del contenido encima, y hacerlo
   con un selector ">*" pisaría el position:fixed de .theme-toggle-fixed
   (misma especificidad, definida antes en este archivo). */

.tour-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 22px;
  height: 22px;
  border-radius: 99px;
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  font-size: 12px;
  font-weight: 700;
  font-family: var(--sans);
  cursor: pointer;
  margin: 0;
  padding: 0;
  vertical-align: middle;
  flex: none;
}
.tour-btn:hover { color: var(--ink); }

/* ── driver.js: alineado al design system, no al estilo por defecto de la librería ── */
.driver-popover {
  font-family: var(--sans);
  background: var(--surface);
  color: var(--ink-2);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  box-shadow: 0 1px 2px rgba(29, 39, 81, .04), 0 8px 24px -12px rgba(29, 39, 81, .18);
  max-width: 340px;
}
.driver-popover-title {
  font-family: var(--display);
  color: var(--ink);
  font-size: 15px;
  font-weight: 700;
}
.driver-popover-description { color: var(--ink-2); font-size: 13px; line-height: 1.55; }
.driver-popover-progress-text { color: var(--ink-2); font-size: 11px; }
.driver-popover-navigation-btns button {
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 600;
  border-radius: var(--radius-btn);
  border: 1px solid var(--line);
  background: var(--surface);
  color: var(--ink-2);
  text-shadow: none;
  padding: 6px 12px;
}
.driver-popover-navigation-btns button:last-child {
  background: var(--brand);
  color: var(--brand-ink);
  border-color: var(--brand);
}
.driver-popover-close-btn { color: var(--ink-2); }
.driver-popover-arrow-side-top.driver-popover-arrow { border-top-color: var(--surface); }
.driver-popover-arrow-side-bottom.driver-popover-arrow { border-bottom-color: var(--surface); }
.driver-popover-arrow-side-left.driver-popover-arrow { border-left-color: var(--surface); }
.driver-popover-arrow-side-right.driver-popover-arrow { border-right-color: var(--surface); }

/* ── Shell: sidebar + topbar (referencia: docfly-saas) ── */
.app-shell { display: flex; min-height: 100vh; }

/* El sidebar es navy siempre, en claro y en oscuro — "el ancla corporativa"
   del design system de Trycore, la única superficie que no invierte con el
   tema (mismo criterio que el logo mono-blanco de acá adentro: no depende
   de qué tema esté activo). Colores hardcodeados a propósito, no tokens
   --ink/--bg (esos sí cambian con el tema; el sidebar no). */
.app-sidebar {
  width: 220px;
  flex: none;
  background: linear-gradient(175deg, #243066 0%, #1D2751 62%, #131C3E 100%);
  display: flex;
  flex-direction: column;
}
/* Mismo alto que .app-topbar (56px) — antes .app-sidebar-top se dimensionaba
   por su padding+contenido, que no daba exactamente 56px, así que el borde
   de abajo quedaba a una altura distinta del borde del topbar: un "corte"
   visible justo donde se tocan sidebar y topbar (reporte real de QA). */
.app-sidebar-top { height: 56px; padding: 0 20px; display: flex; align-items: center; border-bottom: 1px solid rgba(255,255,255,.10); }
.app-sidebar-logo-wrap { display: inline-flex; align-items: center; }
.app-sidebar-logo { height: 22px; width: auto; display: block; }
.app-sidebar-nav { padding: 12px; display: flex; flex-direction: column; gap: 2px; }
.app-sidebar-link {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 9px 12px;
  border-radius: 6px;
  color: rgba(255,255,255,.74);
  font-size: 14px;
  font-weight: 500;
  text-decoration: none;
  transition: background .16s var(--tc-ease, cubic-bezier(.4,0,.2,1)), color .16s var(--tc-ease, cubic-bezier(.4,0,.2,1));
}
.app-sidebar-link svg { width: 18px; height: 18px; flex: none; }
.app-sidebar-link:hover { background: rgba(255,255,255,.09); color: #fff; }
.app-sidebar-link.is-active {
  background: rgba(0,161,154,.22);
  box-shadow: inset 0 0 0 1px rgba(6,200,190,.42);
  color: #7FE6DF;
  font-weight: 600;
}

.app-main { flex: 1; min-width: 0; display: flex; flex-direction: column; }
.app-topbar {
  height: 56px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  padding: 0 24px;
  border-bottom: 1px solid var(--line);
  background: var(--surface);
}
.app-content { flex: 1; padding: 32px 24px 64px; }
/* El max-width real lo pone cada página inline (720/960px) — acá solo se
   centra dentro del espacio disponible. Sin esto, en una ventana ancha el
   contenido queda pegado al borde del sidebar con un vacío enorme a la
   derecha (bug real reportado). */
.app-content .wrap { padding: 0; margin: 0 auto; max-width: 100%; }

@media (max-width: 860px) {
  .app-shell { flex-direction: column; }
  .app-sidebar { width: 100%; flex-direction: row; align-items: center; border-bottom: 1px solid rgba(255,255,255,.10); }
  .app-sidebar-top { padding: 12px 16px; border-bottom: 0; }
  .app-sidebar-nav { flex-direction: row; padding: 8px; overflow-x: auto; }
  .app-content { padding: 20px 16px 48px; }
  table, .proj-grid { display: block; overflow-x: auto; }
}

/* ── Account menu ── */
.account-menu { position: relative; }
.account-trigger { background: none; border: 0; padding: 0; margin: 0; cursor: pointer; display: flex; }
.avatar {
  width: 32px;
  height: 32px;
  border-radius: 50%;
  background: var(--brand);
  color: var(--brand-ink);
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  font-weight: 700;
  font-family: var(--sans);
  flex: none;
}
.account-dropdown {
  position: absolute;
  top: calc(100% + 10px);
  right: 0;
  width: 240px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: 0 8px 24px -8px rgba(29, 39, 81, .25);
  padding: 8px;
  z-index: 50;
}
.account-user { display: flex; align-items: center; gap: 10px; padding: 8px; }
.account-user-txt { display: flex; flex-direction: column; overflow: hidden; }
.account-user-txt .nm { font-size: 13px; font-weight: 600; color: var(--ink); white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.account-user-txt .rl { font-size: 12px; color: var(--ink-2); }
.account-sep { height: 1px; background: var(--line); margin: 6px 4px; }
.account-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px;
  border-radius: 6px;
  font-size: 13px;
  color: var(--ink-2);
  text-decoration: none;
}
.account-item svg { width: 16px; height: 16px; flex: none; }
.account-item:hover { background: var(--bg); color: var(--ink); }
.account-item.danger { color: var(--danger); }
.account-item.danger:hover { background: var(--danger-bg); }

/* ── Badges de privacidad de proyecto — a propósito NO reusan .badge.public
   (verde): esa clase ya es "Pública" del acceso al enlace, un eje distinto
   (quién ve el ENLACE vs. quién ve el PROYECTO en este panel). Compartir el
   mismo verde para ambas hacía que se leyeran como el mismo dato repetido
   (reporte real: "se duplicó el estado"). ── */
.badge.privado { background: rgba(29, 39, 81, .08); color: var(--ink-2); }
.badge.publico { background: rgba(1, 14, 77, .08); color: var(--ink); }

/* ── Botón "Archivos" de la tabla de proyectos — ancho fijo en vez de
   auto-sizing, para que mida lo mismo fila tras fila. Inactivar/Reactivar
   viven en la columna Estado, junto al badge que describen. ── */
.actions-col { display: block; width: 110px; text-align: center; }

/* ── Dashboard: tarjetas de resumen + barra de filtros ── */
.stat-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(140px, 1fr)); gap: 12px; margin-bottom: 16px; }
.stat-card {
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 16px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  box-shadow: var(--shadow-card);
}
.stat-value { font-family: var(--display); font-size: 26px; font-weight: 700; color: var(--ink); line-height: 1.1; }
.stat-label { font-size: 12px; color: var(--ink-2); }
.filter-bar { display: flex; gap: 16px; align-items: center; flex-wrap: wrap; }
.filter-bar input[type="text"] { flex: 1; min-width: 200px; margin: 0; }
.filter-bar select { width: auto; margin: 0; }

/* ── Tabs (Activos/Inactivos en Proyectos) ── */
.tab-row { display: flex; gap: 4px; }
.tab-btn {
  margin: 0;
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 600;
  border-radius: 6px;
  background: transparent;
  color: var(--ink-2);
  border: 0;
}
.tab-btn:hover { background: var(--bg); color: var(--ink); }
.tab-btn.is-active { background: color-mix(in srgb, var(--brand) 10%, transparent); color: var(--brand); }

/* ── Icono de estado en páginas públicas (login/expirado/no-encontrado) ── */
.status-icon {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: color-mix(in srgb, var(--brand) 8%, transparent);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto 18px;
}
.status-icon svg { width: 22px; height: 22px; color: var(--brand); }
.status-icon.danger { background: var(--danger-bg); }
.status-icon.danger svg { color: var(--danger); }

/* ── Popover inline (Compartir / + Archivos en la tabla de proyectos) ──
   <details> normal empuja el layout de la celda/tabla al abrirse (el bug
   real reportado: todo se amontona). Se posiciona el contenido en absoluto,
   flotando sobre la tabla en vez de reflowarla. */
.inline-popover { position: relative; display: inline-block; margin-top: 4px; }
.inline-popover > summary {
  cursor: pointer;
  color: var(--ink-2);
  font-size: 12px;
  list-style: none;
}
.inline-popover > summary::-webkit-details-marker { display: none; }
.inline-popover > summary:hover { color: var(--ink); }
.inline-popover[open] > summary { color: var(--brand); font-weight: 600; }
/* Cuando el trigger es un botón real (.btn) en vez del link de texto por
   defecto — "Compartir" debía verse como botón, igual que "Archivos", no
   como un hipervínculo (reporte real de QA). El margin-top:20px de .btn es
   para separarlo de un campo de formulario; acá va pegado a los badges de
   arriba, así que se recorta a algo chico. */
.inline-popover > summary.btn { margin-top: 8px; color: var(--ink-2); }
.inline-popover[open] > summary.btn { color: var(--ink-2); }

/* Acceso: dos líneas con etiqueta chica ("Enlace"/"Panel") — antes eran
   dos badges sueltos sin decir cuál era cuál, y con el mismo verde en
   algunos casos se leían como el mismo dato repetido (reporte real de
   QA: "no me queda clara la información"). */
.acceso-line { display: flex; align-items: center; gap: 6px; margin-bottom: 3px; }
.acceso-label { font-size: 10px; font-weight: 700; color: var(--ink-2); text-transform: uppercase; letter-spacing: .04em; width: 70px; flex: none; white-space: nowrap; }
.inline-popover-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  z-index: 30;
  width: 300px;
  max-width: calc(100vw - 48px);
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: 6px;
  box-shadow: 0 8px 24px -8px rgba(29, 39, 81, .25);
  padding: 12px;
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.inline-popover-panel.align-right { left: auto; right: 0; }
.inline-popover-panel form { display: flex; flex-wrap: wrap; gap: 6px; align-items: center; }
.inline-popover-panel select,
.inline-popover-panel input[type="text"],
.inline-popover-panel input[type="file"] {
  font: inherit;
  font-size: 12px;
  padding: 5px 7px;
  border-radius: 6px;
  border: 1px solid var(--line);
  background: var(--bg);
  color: var(--ink);
  flex: 1;
  min-width: 0;
}
/* border-radius:6px a propósito — sin esto heredaban el 3px de --radius-btn
   por defecto, distinto del 6px de .btn-sm que usa el resto de botones
   chicos de esta misma pantalla (reporte real de QA: "diferencias en los
   botones"). */
.inline-popover-panel button { margin: 0; padding: 5px 10px; font-size: 12px; border-radius: 6px; flex: none; }
.inline-popover-label { font-size: 11px; font-weight: 600; color: var(--ink-2); text-transform: uppercase; letter-spacing: .02em; }
/* Un solo texto de ayuda, corto, justo debajo del título del grupo — antes
   estaba al final del todo, mezclando dos ideas en una frase larga con
   guión (reporte real de QA: "el mensaje de abajo no es claro"). */
.inline-popover-hint { display: block; font-size: 11px; color: var(--ink-2); margin-top: -4px; line-height: 1.4; }

/* ── Breadcrumb (página de archivos de un proyecto) ── */
.breadcrumb { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--ink-2); margin-bottom: 12px; }
.breadcrumb a { color: var(--ink-2); text-decoration: none; }
.breadcrumb a:hover { color: var(--brand); }
.breadcrumb-sep { color: var(--line); }
.breadcrumb-current { color: var(--ink); font-weight: 600; }

/* ── Lista de archivos de un proyecto (página dedicada) ──
   El nombre es texto estático — renombrar es una acción explícita
   ("Renombrar" abre un modal) en vez de un campo editable siempre
   presente en la fila (pedido real: los nombres de archivo no se editan
   sueltos en la lista). */
.file-list { display: flex; flex-direction: column; }
.file-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 12px 0;
  border-bottom: 1px solid var(--line);
  font-size: 13px;
  flex-wrap: wrap;
}
.file-row:last-child { border-bottom: 0; }
.file-row > svg { width: 16px; height: 16px; color: var(--ink-2); flex: none; }
.file-name-static { flex: 1; min-width: 120px; overflow-wrap: break-word; }
.file-row > a, .file-row > button, .file-row > form { flex: none; }
.file-row-note { font-size: 11px; color: var(--ink-2); margin: -6px 0 8px 26px; }
.file-list-empty { font-size: 13px; color: var(--ink-2); padding: 8px 0; }

/* ── Campo "estático + Actualizar" (Nombre/URL del proyecto) — mismo
   patrón que el nombre de archivo: no se edita nunca inline, un botón
   abre el modal correspondiente. ── */
.static-field { display: flex; align-items: center; justify-content: space-between; gap: 12px; margin-top: 6px; }
.static-field span { overflow-wrap: break-word; min-width: 0; }

/* ── Modal (<dialog> nativo) — Actualizar nombre/URL, renombrar archivo.
   El botón Guardar arranca deshabilitado (pedido real: "no se activa con
   cambio de color si hay cambios") y un script chico lo habilita solo
   cuando el valor difiere del original. ── */
dialog.tc-modal {
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 24px;
  background: var(--surface);
  color: var(--ink);
  box-shadow: var(--shadow-card);
  max-width: 420px;
  width: 90vw;
}
dialog.tc-modal::backdrop { background: rgba(10, 14, 26, .55); }
dialog.tc-modal h3 { margin: 0 0 12px; font-family: var(--display); font-size: 17px; color: var(--ink); }
dialog.tc-modal input[type="text"] { margin: 0; }
dialog.tc-modal .modal-actions { display: flex; gap: 8px; justify-content: flex-end; margin-top: 18px; }
dialog.tc-modal .modal-actions button { margin: 0; }
dialog.tc-modal button:disabled { opacity: .45; cursor: not-allowed; }

/* ── Historial de usuario (panel Usuarios) ── */
.history-list { display: flex; flex-direction: column; gap: 8px; max-height: 180px; overflow-y: auto; margin-top: 8px; }
.history-item {
  padding: 8px 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: var(--bg);
  font-size: 12px;
  color: var(--ink-2);
}
.history-item strong { color: var(--ink); }
.history-item time { display: block; margin-top: 3px; font-size: 11px; color: var(--ink-2); }
