/* Reglas de layout — las variables de color las inyecta base.html desde theme.json. */

* {
  box-sizing: border-box;
}

/* Estilo "tipo Claude" (pedido explícitamente): nada de scroll a nivel de
   página -- la cabecera es fija, y cada panel (sidebar, conversación del
   chat) gestiona su propio scroll dentro de una altura de viewport fija.
   Sin esto, position:sticky del sidebar y el formulario "siempre abajo" del
   chat no tienen contra qué anclarse. */
html, body {
  height: 100%;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--text-1);
  font-family: var(--font-body);
  font-size: 13.5px;
  line-height: 1.5;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.topbar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 11px 20px;
  background: var(--header-bg);
  border-bottom: 1px solid var(--border);
  flex-shrink: 0;
}

.topbar .brand {
  display: flex;
  align-items: center;
  flex-shrink: 0;
}

.topbar .brand-logo {
  height: 28px;
  width: auto;
  display: block;
}

.topbar .brand-tagline {
  flex: 1;
  text-align: center;
  color: var(--header-text);
  font-size: 19px;
  font-weight: 600;
  opacity: 1;
  letter-spacing: 0.01em;
}

.layout {
  display: flex;
  align-items: stretch;
  flex: 1;
  min-height: 0; /* permite que sidebar/main hagan scroll propio en vez de estirar la página */
}

.sidebar {
  flex-shrink: 0;
  width: 200px;
  padding: 14px 10px;
  border-right: 1px solid var(--border);
  /* "Congelada": nunca se desplaza con la conversación -- tiene su propia
     altura fija (100% del layout) y su propio scroll si su contenido no
     cabe, en vez de compartir el scroll de la página. */
  height: 100%;
  overflow-y: auto;
}

.sidebar nav {
  display: flex;
  flex-direction: column;
  gap: 1px;
}

.sidebar nav a {
  display: flex;
  align-items: center;
  gap: 10px;
  color: var(--text-2);
  text-decoration: none;
  font-size: 13.5px;
  font-weight: 500;
  padding: 7px 10px;
  border-radius: 7px;
}

.sidebar nav a svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  opacity: 0.85;
}

.sidebar nav a:hover {
  color: var(--text-1);
  background: var(--bg-card);
}

.sidebar-sessions {
  display: flex;
  flex-direction: column;
  gap: 1px;
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--border);
}

.sidebar-sessions-heading {
  padding: 4px 10px 6px;
  font-size: 10.5px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--text-2);
  opacity: 0.85;
}

.sidebar-session-row {
  display: flex;
  align-items: center;
  gap: 2px;
}

.sidebar-session-link {
  flex: 1;
  min-width: 0;
  color: var(--text-2);
  text-decoration: none;
  padding: 6px 10px;
  border-radius: 7px;
  font-size: 12.5px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.sidebar-session-link:hover {
  color: var(--text-1);
  background: var(--bg-card);
}

.sidebar-session-link.active {
  color: var(--text-1);
  background: var(--bg-card);
  font-weight: 600;
}

/* Icono de borrar de cada conversación -- discreto a propósito (ver
   feedback real: "no un botón"): invisible hasta que se pasa el ratón por
   esa fila, para no llenar el sidebar de iconos rojos permanentes. Ya es un
   .icon-btn.danger (ver esas reglas más arriba); aquí solo se ajusta tamaño
   y el propio ocultamiento/aparición. */
.sidebar-session-delete {
  width: 22px;
  height: 22px;
  flex-shrink: 0;
  opacity: 0;
  transition: opacity 0.12s ease;
}

.sidebar-session-delete svg {
  width: 13px;
  height: 13px;
}

.sidebar-session-row:hover .sidebar-session-delete {
  opacity: 1;
}

/* Confirmación en línea ("¿Eliminar? Sí / No") -- sustituye el contenido de
   la fila mientras se confirma, en vez de un confirm() nativo del navegador
   (que siempre antepone el origen/puerto y no se puede personalizar). */
.sidebar-session-row.confirming {
  gap: 6px;
}

.sidebar-session-confirm-text {
  flex: 1;
  min-width: 0;
  font-size: 11.5px;
  color: var(--text-2);
  line-height: 1.3;
}

.sidebar-session-confirm-yes,
.sidebar-session-confirm-no {
  flex-shrink: 0;
  background: none;
  border: none;
  padding: 2px 4px;
  font-size: 11.5px;
  font-weight: 600;
  cursor: pointer;
}

.sidebar-session-confirm-yes {
  color: #c65b5b;
}

.sidebar-session-confirm-yes:hover {
  color: #a83f3f;
}

.sidebar-session-confirm-no {
  color: var(--text-2);
}

.sidebar-session-confirm-no:hover {
  color: var(--text-1);
}

.use-case-switcher {
  display: flex;
  flex-wrap: wrap;
  gap: 4px;
  margin-bottom: 18px;
  border-bottom: 1px solid var(--border);
  padding-bottom: 14px;
}

.use-case-switcher a {
  color: var(--text-2);
  text-decoration: none;
  padding: 5px 12px;
  border-radius: 999px;
  font-size: 12.5px;
  font-weight: 500;
}

.use-case-switcher a:hover {
  background: var(--bg-card);
  color: var(--text-1);
}

.use-case-switcher a.active {
  background: var(--accent);
  color: var(--accent-text);
  font-weight: 600;
}

main {
  flex: 1;
  min-width: 0;
  min-height: 0;
  max-width: 1200px;
  margin: 0 auto;
  padding: 20px 24px;
  width: 100%;
  /* Por defecto (páginas normales, p.ej. Fuentes de Datos): si el contenido
     no cabe, este panel hace scroll -- ya no la página entera. El chat
     sustituye este scroll por el suyo propio, ver .chat-shell más abajo. */
  display: flex;
  flex-direction: column;
  overflow-y: auto;
}

/* El chat es el único caso con "formulario siempre abajo" -- el resto de
   contenido de main (p.ej. Fuentes de Datos) no necesita este split, así
   que .chat-shell ocupa el 100% de main y desactiva SU scroll (main ya no
   necesita moverse: quien se desplaza es .chat-scroll-area de dentro). */
.chat-shell {
  display: flex;
  flex-direction: column;
  height: 100%;
  min-height: 0;
}

.chat-scroll-area {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  padding-bottom: 8px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

form {
  display: flex;
  flex-direction: column;
  gap: 10px;
  background: var(--bg-card);
  border: none;
  border-radius: 14px;
  padding: 10px 12px;
  box-shadow: 0 1px 3px rgba(20, 20, 15, 0.06);
}

/* El formulario del chat se queda siempre visible al fondo de .chat-shell
   -- flex-shrink:0 evita que .chat-scroll-area (flex:1, ver arriba) lo
   empuje o lo comprima al crecer la conversación o la lista de avance. */
#chat-form {
  flex-shrink: 0;
  margin-top: 8px;
  /* Sin la tarjeta blanca de antes -- mismo fondo que la página, solo el
     borde exterior marca la caja. El textarea de dentro pierde su propio
     fondo/borde (ver más abajo) para que no queden dos cajas anidadas. */
  background: transparent;
  border: 1px solid var(--border);
  box-shadow: none;
}

#chat-form:focus-within {
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

#chat-form textarea {
  background: transparent;
  border: none;
  padding: 4px 2px;
}

#chat-form textarea:focus {
  box-shadow: none;
}

/* Fila con el adjunto (si el caso de uso lo admite) a la izquierda y el
   botón de enviar siempre pegado a la derecha, con o sin adjunto -- mismo
   patrón que la barra de un chat moderno, en vez de dos botones apilados. */
.chat-input-toolbar {
  display: flex;
  align-items: center;
  gap: 10px;
}

#chat-send-btn {
  margin-left: auto;
}

/* Lista de avance mientras se espera la respuesta (ver chat.html) -- texto
   discreto sin caja ni fondo propio, mismo peso visual que un placeholder,
   no un elemento que compita por atención. Los puntos suspensivos del paso
   activo (ver chat.html) son la única señal de que sigue habiendo actividad,
   incluso mucho después de mostrarse el último paso. */
.chat-progress {
  display: flex;
  flex-direction: column;
  gap: 3px;
}

.chat-progress-step {
  font-size: 12.5px;
  color: var(--text-2);
}

.image-attach {
  display: flex;
  align-items: center;
  gap: 10px;
}

#chat-image-preview {
  max-width: 48px;
  max-height: 48px;
  border-radius: 6px;
  border: 1px solid var(--border);
  object-fit: cover;
}

#chat-document-preview {
  font-size: 13px;
  color: var(--text-2);
  padding: 4px 10px;
  border: 1px solid var(--border);
  border-radius: 6px;
  background: var(--bg);
}

label {
  display: flex;
  flex-direction: column;
  gap: 6px;
  font-size: 12.5px;
  font-weight: 500;
  color: var(--text-2);
}

input,
textarea {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 8px 10px;
  color: var(--text-1);
  font-size: 14px;
  font-family: inherit;
}

textarea {
  /* Empieza en una sola línea (rows="1" en chat.html) y crece con el texto
     vía JS (ver chat.html) hasta este máximo -- a partir de ahí hace scroll
     interno en vez de seguir creciendo. Nada de resize manual: choca con el
     auto-crecimiento (el usuario podría dejarlo más pequeño que su propio
     contenido). */
  min-height: 20px;
  max-height: 200px;
  resize: none;
  overflow-y: auto;
}

/* Sin esto, el navegador aplica su propio anillo de foco por defecto (a
   veces un borde negro grueso, según navegador/SO) que no tiene nada que ver
   con la paleta del tema -- se sustituye por un resplandor suave en el color
   de acento, mismo lenguaje visual que el resto de estados interactivos. */
input:focus,
textarea:focus {
  outline: none;
  border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}

button {
  align-self: flex-start;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 8px;
  padding: 8px 16px;
  font-size: 13.5px;
  font-weight: 600;
  cursor: pointer;
  transition: opacity 0.12s ease;
}

button:hover {
  opacity: 0.88;
}

.reply {
  margin-top: 20px;
  padding: 16px;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  white-space: pre-wrap;
}

.conversation {
  display: flex;
  flex-direction: column;
  gap: 16px;
  margin-bottom: 24px;
}

.turn {
  padding: 12px 16px;
  border-radius: 12px;
  border: none;
  box-shadow: 0 1px 3px rgba(20, 20, 15, 0.05);
}

.turn strong {
  display: block;
  font-size: 11px;
  font-weight: 600;
  color: var(--text-2);
  margin-bottom: 6px;
  text-transform: uppercase;
  letter-spacing: 0.05em;
}

.turn-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
}

.turn-header strong {
  margin-bottom: 0;
}

/* Botón de solo icono, base compartida -- el tooltip nativo del atributo
   title dice qué hace al pasar el ratón, como en cualquier chat. Lo usan
   tanto "Copiar" como "Adjuntar imagen". */
.icon-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 26px;
  height: 26px;
  padding: 0;
  background: none;
  border: 1px solid transparent;
  border-radius: 6px;
  color: var(--text-2);
  cursor: pointer;
  flex-shrink: 0;
}

.icon-btn:hover {
  color: var(--text-1);
  background: var(--bg);
  border-color: var(--border);
}

.icon-btn:disabled {
  opacity: 0.7;
  cursor: default;
}

.icon-btn svg {
  width: 15px;
  height: 15px;
  display: block;
}

.icon-btn.danger {
  color: #c65b5b;
}

.icon-btn.danger:hover {
  color: #a83f3f;
  background: rgba(224, 92, 92, 0.1);
  border-color: rgba(224, 92, 92, 0.3);
}

/* Acción primaria en formato icono-solo (Enviar, Subir) -- mismo lenguaje
   visual que .icon-btn (mismo tamaño de icono, mismo radio) pero con relleno
   de acento en vez de transparente, para las pocas acciones que sí necesitan
   leerse como la principal del formulario sin volver a ser un bloque de
   color con texto. */
.icon-action-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 32px;
  height: 32px;
  padding: 0;
  background: var(--accent);
  color: var(--accent-text);
  border: none;
  border-radius: 8px;
  cursor: pointer;
  flex-shrink: 0;
  transition: opacity 0.12s ease;
}

.icon-action-btn:hover {
  opacity: 0.88;
}

.icon-action-btn:disabled {
  background: var(--border);
  color: var(--text-2);
  cursor: not-allowed;
  opacity: 1;
}

.icon-action-btn svg {
  width: 16px;
  height: 16px;
  display: block;
}

.copy-btn .icon-check {
  display: none;
}

.copy-btn.copied .icon-copy {
  display: none;
}

.copy-btn.copied .icon-check {
  display: block;
  color: var(--accent);
}

.turn-content {
  white-space: pre-wrap;
  line-height: 1.5;
}

/* Botón "Editar" de un mensaje propio (ticket bonus "permitir al usuario
   definir el prompt anterior") -- texto discreto, no un botón de acción
   primaria como "Enviar"/"Subir". */
.edit-prompt-btn {
  align-self: auto;
  background: none;
  border: none;
  padding: 2px 6px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-2);
}

.edit-prompt-btn:hover {
  color: var(--accent);
  opacity: 1;
}

.turn-user {
  background: var(--bg);
  align-self: flex-end;
  max-width: 70%;
  /* scrollIntoView (ver chat.html: aterriza en la última pregunta, no al
     final de la respuesta) respeta este margen -- sin él, la pregunta queda
     pegada al borde superior del panel, sin aire. */
  scroll-margin-top: 10px;
}

.turn-assistant {
  background: var(--bg-card);
  align-self: flex-start;
  max-width: 100%;
}

.metric-cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(140px, 1fr));
  gap: 12px;
  margin-top: 14px;
}

.metric-card {
  background: var(--metric-card-bg);
  border: 1px solid var(--metric-card-border);
  border-radius: 8px;
  padding: 12px 14px;
}

.metric-card-value {
  font-size: 22px;
  font-weight: 700;
  color: var(--text-1);
}

.metric-card-percent {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-2);
  margin-left: 4px;
}

.metric-card-label {
  font-size: 12px;
  color: var(--text-2);
  margin-top: 4px;
}

.turn-charts {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 16px;
  margin-top: 14px;
}

/* Un gráfico con muchas categorías/puntos necesita más ancho para que las
   etiquetas no se amontonen -- ocupa toda la fila en vez de encajarse en la
   misma celda estrecha que uno pequeño. La altura se fija aparte, en línea,
   por gráfico (ver chat.html) según cuántas filas tenga. */
.chart-card--wide {
  grid-column: 1 / -1;
}

.chart-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px;
}

.chart-card-title-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 8px;
  margin: 0 0 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}

.chart-card-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-1);
}

.chart-card-image-downloads {
  display: flex;
  gap: 8px;
  flex-shrink: 0;
}

.chart-card-image-downloads button {
  background: none;
  border: none;
  padding: 0;
  font-size: 12px;
  color: var(--text-2);
  cursor: pointer;
}

.chart-card-image-downloads button:hover {
  color: var(--accent);
  text-decoration: underline;
}

.chart-card-canvas {
  position: relative;
}

/* "Ver como tabla" y las descargas PNG/JPG en la misma línea -- antes las
   descargas vivían junto al título del gráfico, donde estorbaban; ahora
   comparten fila con el otro enlace de utilidad de la tarjeta, misma
   tipografía discreta para las dos cosas. */
.chart-card-footer {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 8px;
  margin-top: 10px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
}

.chart-table-toggle summary {
  cursor: pointer;
  color: var(--text-2);
  font-size: 12px;
}

.chart-table-toggle summary:hover {
  color: var(--accent);
}

.chart-table-toggle table {
  width: 100%;
  border-collapse: collapse;
  margin-top: 8px;
  font-size: 12px;
}

.chart-table-toggle th,
.chart-table-toggle td {
  text-align: left;
  padding: 4px 8px;
  border-bottom: 1px solid var(--border);
  color: var(--text-1);
}

.chart-table-toggle th {
  color: var(--text-2);
  font-weight: 600;
}

.turn-tables {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin-top: 14px;
}

.data-table-card {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 14px;
}

.data-table-card-title {
  font-size: 13px;
  font-weight: 600;
  color: var(--text-1);
  margin: 0 0 10px;
  padding-bottom: 8px;
  border-bottom: 1px solid var(--border);
}

.data-table-card-count {
  font-weight: 400;
  color: var(--text-2);
}

/* La tabla en sí no se recorta ni se pagina -- solo se envuelve en un
   contenedor con scroll propio (horizontal Y vertical) para que un listado
   largo no obligue a desplazar toda la página, sin dejar de mostrar el
   listado completo, por grande que sea. */
.data-table-scroll {
  max-height: 480px;
  overflow: auto;
}

.data-table-scroll table {
  width: 100%;
  border-collapse: collapse;
  font-size: 12px;
}

.data-table-scroll th,
.data-table-scroll td {
  text-align: left;
  padding: 6px 10px;
  border-bottom: 1px solid var(--border);
  color: var(--text-1);
  white-space: nowrap;
}

.data-table-scroll th {
  color: var(--text-2);
  font-weight: 600;
  background: var(--table-header-bg);
  position: sticky;
  top: 0;
}

/* Mismo rojo que .icon-btn.danger -- un valor negativo (p.ej. una
   devolución) se distingue de un vistazo sin tener que leer el signo. */
.data-table-scroll td.value-negative {
  color: #c65b5b;
  font-weight: 600;
}

.dashboard-downloads {
  display: flex;
  gap: 12px;
  margin-top: 12px;
  padding-top: 8px;
  border-top: 1px solid var(--border);
  font-size: 11px;
}

.dashboard-downloads a {
  color: var(--text-2);
  text-decoration: none;
}

.dashboard-downloads a:hover {
  color: var(--accent);
  text-decoration: underline;
}

.dashboard-downloads button {
  background: none;
  border: none;
  padding: 0;
  font: inherit;
  font-size: 11px;
  color: var(--text-2);
  cursor: pointer;
}

.dashboard-downloads button:hover {
  color: var(--accent);
  text-decoration: underline;
}

/* Markdown renderizado (respuestas del asistente) — el HTML ya trae su
   propio espaciado, así que aquí se anula el pre-wrap de .turn-content. */
.turn-content.markdown {
  white-space: normal;
}

.turn-content.markdown > *:first-child {
  margin-top: 0;
}

.turn-content.markdown > *:last-child {
  margin-bottom: 0;
}

.turn-content.markdown h1,
.turn-content.markdown h2,
.turn-content.markdown h3,
.turn-content.markdown h4 {
  margin: 18px 0 8px;
  line-height: 1.3;
  color: var(--text-1);
}

.turn-content.markdown h1 { font-size: 17px; }
.turn-content.markdown h2 { font-size: 15px; }
.turn-content.markdown h3 { font-size: 14px; }
.turn-content.markdown h4 { font-size: 13.5px; }

.turn-content.markdown p {
  margin: 8px 0;
}

.turn-content.markdown b {
  color: inherit;
  font-weight: 700;
}

.turn-content.markdown ul,
.turn-content.markdown ol {
  margin: 8px 0;
  padding-left: 22px;
}

.turn-content.markdown ul {
  list-style-type: disc;
}

.turn-content.markdown ul ul {
  list-style-type: circle;
}

.turn-content.markdown li {
  margin: 4px 0;
}

.turn-content.markdown blockquote {
  margin: 8px 0;
  padding: 4px 14px;
  border-left: 3px solid var(--accent);
  color: var(--text-2);
}

.turn-content.markdown code {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 4px;
  padding: 1px 5px;
  font-size: 0.9em;
  font-family: "SFMono-Regular", Consolas, "Liberation Mono", Menlo, monospace;
}

.turn-content.markdown pre {
  background: var(--bg);
  border: 1px solid var(--border);
  border-radius: 8px;
  padding: 12px 14px;
  overflow-x: auto;
}

.turn-content.markdown pre code {
  background: none;
  border: none;
  padding: 0;
}

.turn-content.markdown table {
  width: 100%;
  margin: 10px 0;
  border-collapse: collapse;
  font-size: 0.92em;
}

.turn-content.markdown th,
.turn-content.markdown td {
  border: 1px solid var(--border);
  padding: 6px 10px;
  text-align: left;
}

.turn-content.markdown th {
  background: var(--table-header-bg);
  color: var(--text-2);
  font-weight: 600;
}

.turn-content.markdown a {
  color: var(--accent);
}

.new-conversation {
  margin: 2px 0 10px;
  padding: 0;
  background: transparent;
  border: none;
}

.new-conversation button {
  display: flex;
  align-items: center;
  gap: 10px;
  width: 100%;
  background: transparent;
  border: 1px solid var(--border);
  border-radius: 7px;
  color: var(--text-1);
  font-size: 13.5px;
  font-weight: 500;
  padding: 7px 10px;
  cursor: pointer;
}

.new-conversation button svg {
  width: 15px;
  height: 15px;
  flex-shrink: 0;
  color: var(--accent);
}

.new-conversation button:hover {
  background: var(--bg-card);
  border-color: var(--accent);
}

.error-banner {
  margin-bottom: 16px;
  padding: 12px 16px;
  border-radius: 8px;
  background: rgba(224, 92, 92, 0.12);
  border: 1px solid #e05c5c;
  color: #e05c5c;
}

.dropzone {
  border: 1.5px dashed var(--border);
  border-radius: 10px;
  padding: 22px;
  text-align: center;
  color: var(--text-2);
}

.dropzone.dragover {
  border-color: var(--accent);
  color: var(--text-1);
  background: var(--bg);
}

.dropzone-icon {
  width: 22px;
  height: 22px;
  margin-bottom: 6px;
  color: var(--text-2);
  opacity: 0.7;
}

/* Botón con pinta de enlace -- para una acción secundaria incrustada en una
   frase (p.ej. "...arrastra un fichero o Elegir archivo"), sin la caja de
   fondo de un botón normal. Dispara un <input type="file" hidden> real por
   delegación, igual que el icono de adjuntar del chat. */
.link-btn {
  display: inline;
  align-self: auto;
  background: none;
  border: none;
  padding: 0;
  color: var(--accent);
  font-weight: 600;
  font-size: inherit;
  text-decoration: underline;
  text-underline-offset: 2px;
  cursor: pointer;
}

.link-btn:hover {
  opacity: 0.8;
}

.file-name-preview {
  display: block;
  margin-top: 8px;
  font-size: 12px;
  color: var(--text-2);
}

/* Botón "Subir": gris mientras no hay fichero elegido (icon-action-btn ya
   se pone gris automáticamente vía :disabled), acento en cuanto el usuario
   selecciona uno y el atributo disabled se retira -- ver upload.html
   (evento "change" del input file). La clase "ready" ya no aporta estilo
   propio, pero el JS la sigue alternando por si algún selector futuro la
   necesita. */

/* Fila de fichero ya cargado: el input de fichero real permanece oculto
   hasta que se pulsa "Actualizar" -- ver upload.html. */
.update-file-input {
  display: none;
}

/* Barra de progreso indeterminada durante la subida/actualización de un
   fichero. El envío sigue siendo un POST clásico con recarga de página (ver
   upload.py), así que no hay un porcentaje real de bytes -- esto es
   únicamente la señal visual de "se está procesando" mientras dura la
   petición; desaparece sola al recargarse la página con el resultado. */
.upload-progress {
  display: none;
  height: 4px;
  margin-top: 10px;
  border-radius: 2px;
  background: var(--border);
  overflow: hidden;
}

.upload-progress.active {
  display: block;
}

.inline-form .upload-progress {
  width: 100%;
  margin-top: 0;
}

.upload-progress span {
  display: block;
  width: 40%;
  height: 100%;
  background: var(--accent);
  animation: upload-progress-slide 1.1s ease-in-out infinite;
}

@keyframes upload-progress-slide {
  0% { transform: translateX(-100%); }
  100% { transform: translateX(350%); }
}

h2 {
  font-size: 14.5px;
  font-weight: 600;
  margin: 28px 0 12px;
}

.muted {
  color: var(--text-2);
}

.files-table-wrap {
  overflow-x: auto;
}

.files-table {
  width: 100%;
  border-collapse: collapse;
  background: var(--bg-card);
  border: 1px solid var(--border);
  border-radius: 10px;
  overflow: hidden;
}

.files-table th,
.files-table td {
  text-align: left;
  padding: 10px 14px;
  border-bottom: 1px solid var(--border);
  font-size: 13px;
  vertical-align: top;
}

.files-table th {
  color: var(--text-2);
  font-weight: 600;
  background: var(--table-header-bg);
}

.files-table tr:last-child td {
  border-bottom: none;
}

.files-table-desc {
  max-width: 320px;
  color: var(--text-2);
}

.file-actions {
  display: flex;
  flex-direction: row;
  align-items: center;
  gap: 4px;
}

.inline-form {
  display: flex;
  flex-direction: row;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px;
  background: transparent;
  border: none;
  padding: 0;
}

.inline-form input[type="file"] {
  max-width: 140px;
  padding: 4px 6px;
  font-size: 12px;
}

/* Los botones de fila de fichero (Actualizar/Eliminar) son .icon-btn --
   :not() evita que esta regla, más específica que .icon-btn a secas, les
   pise el tamaño/padding fijos del icono. */
.inline-form button:not(.icon-btn) {
  padding: 6px 10px;
  font-size: 12px;
  white-space: nowrap;
}
