/* ============================================================================
 * TES Edificaciones — Hoja de estilos
 * Identidad visual TES: gama neutra y sobria, contrastada con el naranja de
 * marca (#EC8656) usado como punto de atención. Tipografía IBM Plex Sans
 * (Light para texto, SemiBold para énfasis), según el manual de marca.
 * ==========================================================================*/

/* La tipografía de marca (IBM Plex Sans) se declara en assets/fonts.css */

:root {
  /* Ancho máximo del contenido. Antes eran 1120px fijos: en un portátil de
     1440px sobraban 60px, pero en un monitor de 1920 se desperdiciaban más
     de 500px de fondo vacío mientras las tablas se apretaban. Con 2200px
     el contenido llena la pantalla en cualquier monitor normal (hasta
     2560px) y el tope solo entra en pantallas ultrapanorámicas, donde una
     fila estirada a 3000px obligaría a recorrer la mirada de lado a lado
     para leer un solo registro. Si se quiere sin límite: `none`.
     Lo usan `.container` y `.main-bar`: van juntos o la campana se
     descuadra respecto al contenido. */
  --ancho-max: 2200px;

  /* Neutros cálidos derivados de Pantone 412C / 402C / 7527C */
  --bg: #f4f3ef;
  --surface: #ffffff;
  --surface-2: #faf8f5;
  --border: #e8e5de;
  --border-strong: #d8d8d0;   /* 7527 C */
  --ink: #302929;             /* 412 C */
  --ink-soft: #574c4b;
  --muted: #6f6462;
  --muted-2: #9a938a;
  --stone: #aaa89c;           /* 402 C */

  /* Marca (naranja 2024 C) */
  --brand: #ec8656;
  --brand-hover: #e06f3b;
  --brand-soft: #fdf0e9;
  --brand-softer: #fef7f3;
  --brand-ink: #a85a2e;       /* naranja legible sobre fondo claro */

  /* Alias para reutilizar reglas existentes */
  --accent: #ec8656;
  --accent-hover: #e06f3b;
  --ring: rgba(236, 134, 86, 0.26);
  --danger: #b3402f;
  --danger-bg: #faedea;
  --danger-bd: #ecd2cb;

  /* Aviso (arena tostada) */
  --warn: #c08a3e;
  --warn-ink: #8a6524;
  --warn-bg: #fbf3e6;
  --warn-bd: #efdcba;

  /* Estados de obra: neutros sobrios; el naranja marca la obra viva.
     En el orden en que se leen: en estudio → aprobada (consultoría, en
     ejecución, paralizada, finalizada) → rechazada. */
  --st-estudio: #8a8578;
  --st-aprobada: #4e7c7a;
  --st-consultoria: #5a6e80;
  --st-ejecucion: #ec8656;
  --st-paralizada: #a6493c;
  --st-finalizada: #5f7a63;
  --st-rechazada: var(--danger);

  /* Acentos de categoría (chips, avatares): paleta desaturada de marca */
  --c-indigo: #ec8656;  --c-indigo-bg: #fdf0e9;
  --c-blue: #5a6e80;    --c-blue-bg: #eaeef2;
  --c-violet: #7a6a78;  --c-violet-bg: #f1edf0;
  --c-amber: #c08a3e;   --c-amber-bg: #f9f0e2;
  --c-green: #5f7a63;   --c-green-bg: #e9f0ea;
  --c-rose: #a6493c;    --c-rose-bg: #f8ece9;
  --c-teal: #4e7c7a;    --c-teal-bg: #e6f0ef;

  /* Color de datos (gráficos) */
  --data: #ec8656;
  --data-soft: #fdf0e9;

  --sidebar-w: 258px;
  --rail-w: 88px;          /* barra lateral reducida a iconos, en tablet */
  --topbar-h: 56px;        /* cabecera del móvil */
  --tabbar-h: 60px;        /* barra de pestañas inferior del móvil */

  /* Márgenes seguros del dispositivo (notch, isla dinámica, barra de gestos).
     Fuera de iOS valen 0 y no afectan a nada. */
  --safe-t: env(safe-area-inset-top, 0px);
  --safe-b: env(safe-area-inset-bottom, 0px);
  --safe-l: env(safe-area-inset-left, 0px);
  --safe-r: env(safe-area-inset-right, 0px);

  /* Geometría rectilínea, en línea con el logotipo */
  --radius: 12px;
  --radius-sm: 8px;
  --shadow-sm: 0 1px 2px rgba(48, 41, 41, 0.04), 0 1px 3px rgba(48, 41, 41, 0.05);
  --shadow-md: 0 4px 14px rgba(48, 41, 41, 0.06), 0 2px 6px rgba(48, 41, 41, 0.04);
  --shadow-lg: 0 18px 48px rgba(48, 41, 41, 0.16);
  --font: 'IBM Plex Sans', 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* Escala tipográfica: solo dos pesos reales (Light 400 · SemiBold 600) */
  --w-normal: 400;
  --w-bold: 600;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
}

::selection { background: var(--brand-soft); color: var(--brand-ink); }

/* Foco visible y coherente en toda la app */
:focus-visible { outline: 2px solid var(--brand); outline-offset: 2px; }

/* Quien tenga desactivadas las animaciones en su sistema no ve ninguna: las
   barras de avance y los desplegables saltan directamente a su estado final. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

button { font-family: inherit; }
a { color: inherit; text-decoration: none; }

.icon { display: inline-flex; width: 16px; height: 16px; }
.icon svg { width: 100%; height: 100%; display: block; }
.icon.mini { width: 14px; height: 14px; }

/* ---- Logotipo ------------------------------------------------------------ *
 * Se usa el logotipo original de marca: no se recrea con otra tipografía ni se
 * alteran sus proporciones. Sobre naranja se emplea la versión en blanco.
 * ------------------------------------------------------------------------- */
.logo-tes { display: block; height: 22px; width: auto; }
.logo-tes.on-brand { filter: brightness(0) invert(1); }

/* ---- Shell con barra lateral -------------------------------------------- */
.app-shell { display: flex; min-height: 100vh; min-height: 100dvh; align-items: stretch; }

/* Cabecera y pestañas son exclusivas del móvil: aquí no existen. */
.topbar, .tabbar { display: none; }
/* Etiqueta corta: solo donde no cabe el nombre completo (raíl y pestañas). */
.nav-label-corto { display: none; }

.sidebar {
  width: var(--sidebar-w);
  flex: none;
  position: sticky;
  /* Por encima del contenido: el submenú que sale a la derecha se sale de la
     barra y tiene que pintarse sobre las tarjetas, no por debajo. Queda muy
     lejos del 100 de los diálogos, que siguen tapándolo todo. */
  z-index: 20;
  top: 0;
  align-self: flex-start;
  height: 100vh;
  background: var(--surface);
  border-right: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  padding: 18px 14px;
  gap: 6px;
}
/* Marca en la barra lateral: solo el logotipo, alineado a la izquierda */
.sb-brand {
  display: flex; align-items: center;
  padding: 14px 10px 20px;
  margin-bottom: 2px;
  border-bottom: 1px solid var(--border);
}
.sb-brand .logo-tes { height: 26px; }
.sb-nav { display: flex; flex-direction: column; gap: 2px; margin-top: 6px; }
.nav-group {
  font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.14em;
  color: var(--muted-2); padding: 18px 11px 8px;
}
.nav-item {
  display: flex; align-items: center; gap: 12px;
  padding: 9px 12px;
  min-height: 40px;
  border-radius: var(--radius-sm);
  color: var(--ink-soft);
  font-size: 14px; font-weight: 400;
  transition: background 0.15s, color 0.15s;
  position: relative;
}
.nav-item:hover { background: var(--surface-2); color: var(--ink); }
.nav-item.active { background: var(--brand-soft); color: var(--brand-ink); font-weight: 600; }
/* Marca de sección activa: filete naranja, el único acento de la navegación */
.nav-item.active::before {
  content: ''; position: absolute; left: 0; top: 8px; bottom: 8px;
  width: 2px; border-radius: 2px; background: var(--brand);
}
.nav-ic {
  display: inline-grid; place-items: center;
  width: 22px; height: 22px; flex: none;
  color: var(--muted-2);
  transition: color 0.15s;
}
.nav-item:hover .nav-ic { color: var(--ink-soft); }
.nav-item.active .nav-ic { color: var(--brand); }
.nav-item .nav-ic .icon { width: 18px; height: 18px; }
.nav-label { flex: 1; }
.nav-badge {
  min-width: 20px; height: 20px; padding: 0 6px;
  display: inline-grid; place-items: center;
  background: var(--brand); color: #fff;
  font-size: 11px; font-weight: 600; border-radius: 100px;
  font-variant-numeric: tabular-nums;
}
/* ---- Secciones con submenú (barra lateral) -------------------------------- *
 * El grupo se pliega y despliega sin repintar la pantalla: el chevron cambia
 * las clases a mano. Así la animación no se corta a la mitad, que es lo que
 * pasaría si cada pulsación rehiciera la barra entera.
 * -------------------------------------------------------------------------- */
.nav-bloque { display: flex; flex-direction: column; position: relative; }
.nav-fila { position: relative; }

/* Estás dentro del grupo, pero la marca fuerte es del hijo: aquí basta con
   subir el contraste para situarte sin competir con él. */
.nav-bloque.dentro > .nav-fila > .nav-item-padre { color: var(--ink); font-weight: 600; }
.nav-bloque.dentro > .nav-fila > .nav-item-padre .nav-ic { color: var(--ink-soft); }

/* --- Dentro del grupo: el submenú cuelga debajo, siempre a la vista -------- *
 * La altura se anima con `grid-template-rows` de 0fr a 1fr: crece justo lo que
 * ocupen los hijos, sin fijar una altura a mano que se quedaría corta en
 * cuanto cambien los textos o se añada una pantalla más.                     */
.nav-sub {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 0.26s cubic-bezier(0.4, 0, 0.2, 1);
}
.nav-bloque.dentro > .nav-sub { grid-template-rows: 1fr; }
.nav-sub-in {
  overflow: hidden;
  opacity: 0;
  /* `visibility` saca los enlaces plegados del recorrido del tabulador. Se
     retrasa hasta que termina de plegarse para no cortar la animación. */
  visibility: hidden;
  transition: opacity 0.16s ease, visibility 0s 0.26s;
}
.nav-bloque.dentro > .nav-sub > .nav-sub-in {
  opacity: 1; visibility: visible;
  transition: opacity 0.22s ease 0.06s, visibility 0s;
}

/* --- Fuera del grupo: al posar el cursor, sale a la derecha ---------------- *
 * Se reaprovecha el MISMO submenú en vez de duplicarlo: los dos enlaces se
 * escriben una sola vez y no hay forma de que se queden descuadrados entre sí.
 * `:focus-within` lo abre también con el tabulador, para quien no use ratón.
 * -------------------------------------------------------------------------- */
.nav-bloque:not(.dentro) > .nav-sub {
  position: absolute; left: 100%; top: -6px;
  z-index: 60;
  display: block; grid-template-rows: none;
  min-width: 216px;
  /* Franja transparente a la izquierda: hace de puente para que el cursor
     cruce del enlace al panel en diagonal sin que se cierre por el camino.
     Por eso el fondo va en `.nav-sub-in` y no aquí. */
  padding: 6px 0 6px 8px;
  opacity: 0; visibility: hidden; transform: translateX(-6px);
  pointer-events: none;
  transition: opacity 0.16s ease, transform 0.16s ease, visibility 0s 0.16s;
}
.nav-bloque:not(.dentro):hover > .nav-sub,
.nav-bloque:not(.dentro):focus-within > .nav-sub {
  opacity: 1; visibility: visible; transform: none;
  pointer-events: auto;
  transition: opacity 0.18s ease, transform 0.18s cubic-bezier(0.4, 0, 0.2, 1), visibility 0s;
}
.nav-bloque:not(.dentro) > .nav-sub > .nav-sub-in {
  overflow: visible; opacity: 1; visibility: visible; transition: none;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 6px;
}
/* En el panel flotante sobra el filete guía: ahí no hay de qué colgar */
.nav-bloque:not(.dentro) .nav-sub-lista {
  margin: 0; padding: 0; border-left: 0;
}
.nav-bloque:not(.dentro) .nav-subitem { white-space: nowrap; }
.nav-bloque:not(.dentro) .nav-subitem.active::before { left: -2px; }

/* Filete guía a la izquierda, alineado con el icono del padre: ata los hijos
   a su grupo de un vistazo, sin necesidad de más sangría. */
.nav-sub-lista {
  display: flex; flex-direction: column; gap: 2px;
  margin: 3px 0 4px 22px; padding-left: 11px;
  border-left: 1px solid var(--border);
}
.nav-subitem {
  display: block;
  padding: 8px 10px; min-height: 34px;
  border-radius: var(--radius-sm);
  color: var(--muted); font-size: 13.5px; line-height: 1.3;
  position: relative;
  transition: background 0.15s, color 0.15s;
}
.nav-subitem:hover { background: var(--surface-2); color: var(--ink); }
.nav-subitem.active { background: var(--brand-soft); color: var(--brand-ink); font-weight: 600; }
/* Mismo filete naranja que las secciones de primer nivel, sobre la guía */
.nav-subitem.active::before {
  content: ''; position: absolute; left: -12px; top: 7px; bottom: 7px;
  width: 2px; border-radius: 2px; background: var(--brand);
}

@media (prefers-reduced-motion: reduce) {
  .nav-sub, .nav-sub-in { transition-duration: 0.01ms; }
}

.sb-foot { margin-top: auto; padding: 6px; display: flex; flex-direction: column; gap: 10px; }
.sb-version { font-size: 11.5px; color: var(--muted-2); padding-left: 6px; letter-spacing: 0.04em; }

/* ---- Pie de sesión en la barra lateral ---------------------------------- */
.sb-sesion { display: flex; flex-direction: column; gap: 9px; }
.sb-sync {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 4px 9px; border-radius: 100px; align-self: flex-start;
  font-size: 11px; font-weight: 600; letter-spacing: 0.01em;
  background: var(--surface-2); color: var(--muted);
}
.sb-sync .icon { width: 12px; height: 12px; }
.sb-sync.ok { background: #e9f0ea; color: #40593f; }
.sb-sync.pendiente { background: #fdf0da; color: #b45309; }
.sb-sync.error { background: var(--danger-bg); color: var(--danger); }
.sb-sync.cargando .icon { animation: girar 0.9s linear infinite; }
@keyframes girar { to { transform: rotate(360deg); } }

.sb-usuario {
  display: flex; align-items: center; gap: 9px; min-width: 0; width: 100%;
  padding: 7px 8px; border-radius: 10px;
  transition: background 0.15s;
  /* Es un <button>: hay que desandar los estilos que trae de serie. */
  background: none; border: 0; font: inherit; text-align: left; cursor: pointer;
}
.sb-usuario:hover { background: var(--surface-2); }
.sb-usuario.active { background: var(--surface-2); }
.sb-usuario-chev {
  display: inline-grid; place-items: center; flex: none; margin-left: auto;
  color: var(--muted-2); transition: transform 0.16s, color 0.15s;
}
.sb-usuario-chev .icon { width: 15px; height: 15px; }
/* El icono base apunta hacia abajo. El menú de la barra lateral se abre hacia
   arriba, así que el chevrón apunta arriba y se da la vuelta al abrirlo. */
.menu-ancla .sb-usuario-chev { transform: rotate(180deg); }
.menu-ancla.abierto .sb-usuario-chev { transform: rotate(0deg); color: var(--ink-soft); }
.sb-usuario:hover .sb-usuario-chev { color: var(--ink-soft); }

/* ---- Menú flotante del usuario ------------------------------------------ */
.menu-ancla { position: relative; }
.menu-flot {
  position: absolute; z-index: 40; left: 0; min-width: 244px;
  display: none; flex-direction: column; gap: 2px; padding: 6px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: 12px; box-shadow: var(--shadow-lg);
}
.menu-ancla.abierto .menu-flot { display: flex; animation: pop 0.14s ease; }
/* Abajo del todo de la barra lateral: el menú sube. En la cabecera del móvil
   baja, y se ancla a la derecha para no salirse de la pantalla. */
.menu-arriba { bottom: calc(100% + 8px); }
.menu-abajo { top: calc(100% + 8px); left: auto; right: 0; }
.menu-flot-item {
  display: flex; align-items: flex-start; gap: 11px;
  padding: 9px 10px; border-radius: 9px;
  transition: background 0.14s;
}
.menu-flot-item:hover { background: var(--surface-2); }
.menu-flot-item.active { background: var(--brand-soft); }
.menu-flot-ic {
  display: inline-grid; place-items: center; flex: none;
  width: 30px; height: 30px; border-radius: 8px;
  background: var(--surface-2); color: var(--muted);
}
.menu-flot-item.active .menu-flot-ic { background: var(--surface); color: var(--brand); }
.menu-flot-ic .icon { width: 16px; height: 16px; }
.menu-flot-txt { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.menu-flot-lbl { font-size: 13.5px; font-weight: 600; color: var(--ink); }
.menu-flot-item.active .menu-flot-lbl { color: var(--brand-ink); }
.menu-flot-sub { font-size: 11.5px; color: var(--muted-2); line-height: 1.35; }

/* ---- Campana de avisos --------------------------------------------------- */
/* Franja superior del escritorio: solo la campana, pegada arriba a la derecha. */
.main-bar {
  position: sticky; top: 0; z-index: 20;
  display: flex; justify-content: flex-end; align-items: center; gap: 10px;
  max-width: var(--ancho-max); margin: 0 auto;
  padding: 16px max(40px, var(--safe-r)) 0 40px;
  background: var(--bg);
}
.campana {
  position: relative;
  display: inline-grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: 11px;
  color: var(--muted); background: transparent;
  border: 1px solid transparent;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.campana:hover { background: var(--surface); border-color: var(--border); color: var(--ink); }
.campana.active { background: var(--brand-soft); color: var(--brand-ink); border-color: transparent; }
.campana .icon { width: 19px; height: 19px; }
.campana.con-avisos { color: var(--ink-soft); }
.campana-badge {
  position: absolute; top: 2px; right: 2px;
  min-width: 17px; height: 17px; padding: 0 4px;
  display: inline-grid; place-items: center;
  background: var(--brand); color: #fff;
  font-size: 10.5px; font-weight: 600; border-radius: 100px;
  font-variant-numeric: tabular-nums;
  box-shadow: 0 0 0 2px var(--bg);
}
.campana.active .campana-badge { box-shadow: 0 0 0 2px var(--brand-soft); }
.sb-avatar {
  display: inline-grid; place-items: center; flex: none;
  width: 28px; height: 28px; border-radius: 9px;
  background: var(--brand); color: #fff; font-size: 13px; font-weight: 700;
}
.sb-email {
  font-size: 12px; color: var(--ink-soft); min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.cuenta-acciones { display: flex; gap: 12px; flex-wrap: wrap; }

/* ---- Elección del destino de los datos (Mi cuenta) ---------------------- */
.modo-cuenta {
  display: flex; align-items: center; gap: 7px;
  margin: -6px 0 16px; font-size: 12.5px; color: var(--muted);
}
.modo-cuenta .icon { width: 14px; height: 14px; }
.modo-lista { display: flex; flex-direction: column; gap: 10px; }
.modo-card {
  display: flex; align-items: flex-start; gap: 14px; width: 100%; text-align: left;
  padding: 16px 18px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface); font-family: inherit; cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s;
}
.modo-card:hover:not(:disabled) { border-color: var(--accent); box-shadow: var(--shadow-md); transform: translateY(-1px); }
.modo-card:disabled { cursor: default; background: var(--surface-2); border-color: var(--border-strong); }
.modo-ic {
  display: inline-grid; place-items: center; flex: none;
  width: 38px; height: 38px; border-radius: 11px;
  background: var(--surface-2); color: var(--muted);
}
.modo-card.actual .modo-ic { background: var(--brand); color: #fff; }
.modo-ic .icon { width: 19px; height: 19px; }
.modo-txt { flex: 1; min-width: 0; }
.modo-titulo {
  display: flex; align-items: center; gap: 9px; flex-wrap: wrap;
  font-size: 15px; font-weight: 680; color: var(--ink); letter-spacing: -0.01em;
}
.modo-actual-tag {
  padding: 2px 9px; border-radius: 100px; background: var(--brand); color: #fff;
  font-size: 11px; font-weight: 700; letter-spacing: 0.02em;
}
.modo-resumen { margin: 5px 0 0; font-size: 13px; color: var(--ink-soft); line-height: 1.5; }
.modo-detalle { margin: 4px 0 0; font-size: 12px; color: var(--muted-2); line-height: 1.5; }
.modo-chev { width: 18px; height: 18px; flex: none; color: var(--muted-2); transform: rotate(-90deg); align-self: center; }
.aviso-costes.reconectar { margin-bottom: 22px; }

/* ---- Pantallas de acceso ------------------------------------------------- */
.auth-pantalla {
  min-height: 100vh; min-height: 100dvh;
  display: grid; place-items: center;
  padding: 24px; background: var(--bg);
}
.auth-caja {
  width: 100%; max-width: 420px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); box-shadow: var(--shadow-md);
  padding: 34px 32px 28px;
}
.auth-marca { display: flex; align-items: center; margin-bottom: 26px; }
.auth-marca .logo-tes { height: 28px; }
.auth-titulo { margin: 0; font-size: 23px; font-weight: 700; letter-spacing: -0.02em; color: var(--ink); }
.auth-sub { margin: 7px 0 0; font-size: 14px; color: var(--muted); line-height: 1.5; }
.auth-form { display: flex; flex-direction: column; gap: 16px; margin-top: 24px; }
.auth-ayuda { font-size: 12px; color: var(--muted-2); line-height: 1.45; }
.auth-btn { width: 100%; justify-content: center; min-height: 44px; margin-top: 4px; }

.auth-aviso {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 11px 13px; border-radius: 10px;
  font-size: 13px; line-height: 1.45;
}
.auth-aviso .icon { width: 15px; height: 15px; flex: none; margin-top: 1px; }
.auth-aviso.error { background: var(--danger-bg); border: 1px solid #f0c9c4; color: var(--danger); }
.auth-aviso.ok { background: #e9f0ea; border: 1px solid #d5e2d6; color: #40593f; }
.auth-aviso.info { background: var(--surface-2); border: 1px solid var(--border); color: var(--ink-soft); }

.auth-nota-seguridad {
  display: flex; align-items: flex-start; gap: 9px;
  padding: 12px 13px; border-radius: 10px;
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: 12.5px; color: var(--muted); line-height: 1.5;
}
.auth-nota-seguridad .icon { width: 15px; height: 15px; flex: none; margin-top: 1px; color: var(--brand); }

.auth-pie {
  margin-top: 24px; padding-top: 20px; border-top: 1px solid var(--border);
  font-size: 13px; color: var(--muted); text-align: center; line-height: 1.9;
}
.auth-separador { height: 1px; background: var(--border); margin: 14px 0; }
.auth-enlace {
  border: none; background: none; padding: 0; cursor: pointer;
  font-family: inherit; font-size: 13px; color: var(--brand); font-weight: 560;
}
.auth-enlace:hover { text-decoration: underline; }
.auth-enlace.fuerte { font-weight: 700; }

/* Medidor de robustez de la contraseña */
.auth-fuerza { height: 4px; border-radius: 100px; background: var(--surface-2); overflow: hidden; margin-top: -8px; }
.auth-fuerza-barra { height: 100%; width: 0; border-radius: 100px; transition: width 0.25s ease, background 0.25s ease; background: var(--danger); }
.auth-fuerza.n1 .auth-fuerza-barra { background: #e11d48; }
.auth-fuerza.n2 .auth-fuerza-barra { background: #ea580c; }
.auth-fuerza.n3 .auth-fuerza-barra { background: #d97706; }
.auth-fuerza.n4 .auth-fuerza-barra { background: #40593f; }

.auth-spinner {
  display: inline-block; width: 16px; height: 16px;
  border: 2px solid rgba(255,255,255,0.4); border-top-color: #fff;
  border-radius: 50%; animation: girar 0.7s linear infinite;
}
.sb-alert {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 13px;
  background: var(--warn-bg); border: 1px solid var(--warn-bd); border-radius: var(--radius-sm);
  color: var(--warn-ink); font-size: 12.5px; font-weight: 400;
  transition: background 0.15s, border-color 0.15s;
}
.sb-alert:hover { background: #f8ecd8; border-color: #e5cc9f; }
.sb-alert .icon { width: 16px; height: 16px; flex: none; color: var(--warn); }

.main { flex: 1; min-width: 0; }

/* ---- Contenedor ---------------------------------------------------------- */
/* El padding lateral se contrae con la pantalla y respeta los márgenes seguros
   del dispositivo, de modo que nada queda bajo el notch ni fuera de la vista. */
.container {
  max-width: var(--ancho-max);
  margin: 0 auto;
  /* Poco aire arriba: encima va la franja de la campana, que ya separa. */
  padding: 22px max(40px, var(--safe-l)) 96px max(40px, var(--safe-r));
}

/* El tablero del CRM es la excepción al tope: cada columna que cabe es una
   etapa más del embudo a la vista, así que aquí el ancho no es aire de sobra
   sino información. Se le quita el límite y la barra de la campana lo
   acompaña, para que las dos sigan alineadas. */
.container-ancho, .main-bar-ancho { max-width: none; }

/* ---- Cabecera de página -------------------------------------------------- */
.page-head {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  gap: 18px;
  margin-bottom: 26px;
}
.page-title {
  margin: 0;
  min-width: 0;
  overflow-wrap: break-word;
  font-size: 27px;
  font-weight: 600;
  letter-spacing: -0.015em;
  color: var(--ink);
  line-height: 1.2;
}
.page-sub { margin: 5px 0 0; color: var(--muted); font-size: 14px; }
/* Controles de la cabecera (filtros + acción principal) */
.page-head-tools { display: flex; align-items: center; gap: 10px; flex: none; flex-wrap: wrap; justify-content: flex-end; }

/* Filtro de periodo del panel: uno solo para toda la pantalla */
.dash-periodo {
  display: inline-flex; align-items: center; gap: 8px; cursor: pointer;
  padding: 5px 10px 5px 12px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.dash-periodo:hover { border-color: var(--border-strong); }
.dash-periodo:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.dash-periodo-lbl {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 11.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--muted-2);
}
.dash-periodo-lbl .icon { width: 14px; height: 14px; }
.dash-periodo .periodo-select { max-width: none; font-size: 13px; color: var(--ink); padding: 3px 4px; }
.dash-periodo .periodo-select:hover { background: transparent; border-color: transparent; }
.dash-periodo .periodo-select:focus-visible { box-shadow: none; border-color: transparent; }

.link-back {
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--muted); font-size: 13px; font-weight: 400;
  margin-bottom: 10px;
  transition: color 0.15s;
}
.link-back:hover { color: var(--ink); }
.link-back .icon { width: 15px; height: 15px; }

/* ---- Botones ------------------------------------------------------------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  padding: 10px 18px;
  min-height: 42px;
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-size: 14px; font-weight: 600;
  letter-spacing: -0.005em;
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s, color 0.15s, transform 0.05s;
  white-space: nowrap;
}
.btn:active { transform: translateY(0.5px); }
.btn .icon { width: 16px; height: 16px; }
.btn-primary { background: var(--brand); color: #fff; }
.btn-primary:hover { background: var(--brand-hover); }
.btn-ghost { background: var(--surface); color: var(--ink-soft); border-color: var(--border-strong); }
.btn-ghost:hover { background: var(--surface-2); border-color: var(--stone); color: var(--ink); }
.btn-danger { background: var(--danger); color: #fff; }
.btn-danger:hover { filter: brightness(0.92); }
.btn-danger-ghost { background: transparent; color: var(--danger); border-color: var(--danger-bd); }
.btn-danger-ghost:hover { background: var(--danger-bg); }
/* Botón de descarga de PDF mientras genera: mismo giro que el chip de
   sincronización, para que un icono "cargando" siempre se lea igual. */
.btn-generando { cursor: default; opacity: 0.85; }
.btn-generando .icon { animation: girar 0.9s linear infinite; }
.chev-right { transform: rotate(-90deg); width: 15px !important; height: 15px !important; }

/* ---- Tabla de obras ------------------------------------------------------ */
.tabla {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
/* Columnas elásticas: ninguna impone un ancho mínimo que desborde la tabla
   cuando el contenido se estrecha (tablet en vertical). */
.row-obra {
  display: grid;
  grid-template-columns: 46px minmax(0, 1fr) minmax(88px, 108px) minmax(148px, 186px) 40px;
  align-items: center;
  gap: 14px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.12s;
}
.row-obra:last-child { border-bottom: none; }
.row-obra:not(.row-head):hover { background: var(--surface-2); }
.row-head {
  cursor: default;
  background: var(--surface-2);
  font-size: 10.5px;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  color: var(--muted-2);
  font-weight: 600;
  padding-top: 12px;
  padding-bottom: 12px;
}
.row-head:hover { background: var(--surface-2); }
.cell { min-width: 0; }
.cell-avatar { display: flex; }
.obra-avatar {
  display: inline-grid; place-items: center;
  width: 40px; height: 40px; border-radius: var(--radius-sm); flex: none;
  background: var(--chip-bg); color: var(--chip-fg);
}
.obra-avatar .icon { width: 20px; height: 20px; }
.cell-encargo { display: flex; flex-direction: column; gap: 2px; }
/* Dos líneas, no una con puntos suspensivos. Los encargos de este estudio son
   largos y lo que los distingue va al FINAL («260702 SFD RESIDENCIA
   ESTUDIANTES_FSA»): cortando en una línea quedaba «260702 SFD RESIDENCIA
   ESTU…», que no identifica nada. Con dos líneas caben enteros casi siempre,
   y el corte —cuando toca— ya cae después de lo que distingue. */
.cell-encargo-text {
  font-weight: 600; color: var(--ink); font-size: 15px;
  letter-spacing: -0.01em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; overflow-wrap: anywhere;
}
.cell-tipologia { font-size: 12.5px; color: var(--muted); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
/* La referencia no tiene columna propia: va delante de la tipología, tomada
   de `data-ref`. Es lo que de verdad identifica la obra encargo a encargo. */
.row-obra:not(.row-head) .cell-tipologia::before { content: attr(data-ref); color: var(--muted); font-variant-numeric: tabular-nums; }
.row-obra:not(.row-head) .cell-tipologia:not(:empty)::before { content: attr(data-ref) " · "; }
.cell-fecha { color: var(--ink-soft); font-size: 14px; font-variant-numeric: tabular-nums; }
.row-head .cell-fecha { font-size: inherit; letter-spacing: inherit; color: inherit; }
.cell-acciones { display: flex; justify-content: flex-end; }
.row-delete {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted-2);
  border-radius: 8px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.14s, background 0.14s, color 0.14s, border-color 0.14s;
}
.row-obra:hover .row-delete { opacity: 1; }
.row-delete:hover { background: var(--danger-bg); color: var(--danger); border-color: var(--danger-bd); }
.row-delete .icon { width: 15px; height: 15px; }
.muted { color: var(--muted-2); }

/* ---- Badge / estado ------------------------------------------------------ */
.badge {
  display: inline-flex; align-items: center; gap: 7px;
  padding: 5px 11px;
  border-radius: 6px;
  font-size: 12.5px; font-weight: 600;
  border: 1px solid transparent;
  background: var(--surface-2);
  color: var(--ink-soft);
}
.badge-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); flex: none; }
.badge-btn { cursor: pointer; transition: filter 0.15s, box-shadow 0.15s; }
.badge-btn:hover { filter: brightness(0.97); box-shadow: var(--shadow-sm); }
.badge-btn .chev { width: 14px; height: 14px; opacity: 0.6; margin-left: 1px; }

/* Pastillas tintadas por estado (tonos sobrios; el naranja = obra en marcha) */
.badge-estudio { background: #f2f1ec; color: #5f5a4f; }
.badge-aprobada { background: #e8f0ef; color: #35605d; }
.badge-consultoria { background: #eaeff3; color: #3f5566; }
.badge-ejecucion { background: #fdefe7; color: #a85a2e; }
.badge-paralizada { background: #f8ece9; color: #8a3a2e; }
.badge-finalizada { background: #eaf0ea; color: #40593f; }
.badge-rechazada { background: var(--danger-bg); color: var(--danger); }

.badge-estudio .badge-dot, .badge-dot.badge-estudio { background: var(--st-estudio); }
.badge-aprobada .badge-dot, .badge-dot.badge-aprobada { background: var(--st-aprobada); }
.badge-consultoria .badge-dot, .badge-dot.badge-consultoria { background: var(--st-consultoria); }
.badge-ejecucion .badge-dot, .badge-dot.badge-ejecucion { background: var(--st-ejecucion); }
.badge-paralizada .badge-dot, .badge-dot.badge-paralizada { background: var(--st-paralizada); }
.badge-finalizada .badge-dot, .badge-dot.badge-finalizada { background: var(--st-finalizada); }
.badge-rechazada .badge-dot, .badge-dot.badge-rechazada { background: var(--st-rechazada); }

.estado-dd { position: relative; display: inline-block; }
.estado-menu {
  position: absolute;
  top: calc(100% + 6px);
  left: 0;
  min-width: 210px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 6px;
  z-index: 50;
  display: none;
  animation: pop 0.12s ease;
}
.estado-menu.open { display: block; }
.estado-menu-item {
  display: flex; align-items: center; gap: 9px;
  width: 100%;
  padding: 8px 10px;
  border: none; background: transparent;
  border-radius: 6px;
  font-size: 14px; color: var(--ink-soft);
  cursor: pointer; text-align: left;
}
.estado-menu-item:hover { background: var(--surface-2); }
.estado-menu-item.active { color: var(--ink); font-weight: 600; }
.estado-menu-item .icon { margin-left: auto; color: var(--ink); }

/* Los matices de una obra aprobada cuelgan de ella: sangrado + un filo que
   los agrupa, para que se lea que son formas de estar aprobada y no estados
   alternativos a «Aprobada». */
.estado-menu-sub { margin-left: 18px; padding-left: 12px; border-left: 2px solid var(--border); border-radius: 0 6px 6px 0; }

/* ---- Dropdown de Fase de obra ----------------------------------------------
 * Solo aparece con la obra «En ejecución»: acento naranja de marca (el mismo
 * que ya representa «en marcha» en el badge de estado), para que se lea como
 * parte de esa misma situación y no como un control suelto. La mini barra
 * adelanta el avance sin tener que abrir el menú; dentro, un itinerario
 * numerado con la línea que conecta cada paso con el siguiente.
 * ------------------------------------------------------------------------- */
.fase-dd { position: relative; display: inline-block; }
.fase-badge {
  display: inline-flex; align-items: center; gap: 10px;
  padding: 6px 12px 6px 10px;
  border-radius: 8px;
  border: 1px solid var(--brand-soft);
  background: linear-gradient(135deg, var(--brand-softer), var(--brand-soft));
  color: var(--brand-ink);
  cursor: pointer;
  transition: filter 0.15s, box-shadow 0.15s, border-color 0.15s;
}
.fase-badge:hover { filter: brightness(0.98); box-shadow: var(--shadow-sm); border-color: var(--brand); }
.fase-badge .icon { width: 16px; height: 16px; flex: none; }
.fase-badge .chev { width: 14px; height: 14px; opacity: 0.6; flex: none; }
.fase-badge-texto { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; min-width: 0; }
.fase-badge-nombre {
  font-size: 12.5px; font-weight: 600; line-height: 1.15;
  max-width: 168px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.fase-badge.vacio .fase-badge-nombre { font-weight: 500; opacity: 0.8; }

/* Seis segmentos, tan simple como se lee: los hechos, en naranja lleno. */
.fase-mini { display: flex; gap: 2px; }
.fase-mini-seg { width: 11px; height: 4px; border-radius: 2px; background: rgba(168, 90, 46, 0.18); }
.fase-mini-seg.hecho { background: var(--brand-ink); }

.fase-menu {
  position: absolute;
  min-width: 250px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 8px;
  z-index: 50;
  display: none;
  animation: pop 0.12s ease;
}
.fase-menu.open { display: block; }
.fase-menu-item {
  position: relative; z-index: 1;
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  padding: 9px 10px;
  border: none; background: transparent;
  border-radius: 8px;
  font-size: 13.5px; color: var(--ink-soft);
  cursor: pointer; text-align: left;
}
.fase-menu-item:hover { background: var(--surface-2); }
.fase-menu-item.active { color: var(--ink); font-weight: 600; background: var(--brand-softer); }
.fase-menu-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 22px; height: 22px; flex: none;
  border-radius: 50%; font-size: 11px; font-weight: 700;
  background: var(--surface); color: var(--muted-2);
  border: 1.5px solid var(--border);
}
.fase-menu-num .icon { width: 12px; height: 12px; }
.fase-menu-item.active .fase-menu-num { background: var(--brand); border-color: var(--brand); color: #fff; }
.fase-menu-item.pasada .fase-menu-num { background: var(--brand-soft); border-color: var(--brand-soft); color: var(--brand-ink); }
.fase-menu-nombre { flex: 1; min-width: 0; }
/* El itinerario: una línea continua detrás de los círculos, de la primera
   fase a la última. Los círculos, con fondo opaco, la tapan a su paso —el
   efecto de una línea "atravesando" cada parada, como un mapa de metro. */
.fase-menu-linea {
  position: absolute; z-index: 0;
  top: calc(8px + 9px + 11px); bottom: calc(8px + 9px + 11px);
  left: calc(8px + 10px + 11px - 1px);
  width: 2px; background: var(--border);
}

@keyframes pop { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: translateY(0); } }

/* ---- Estado vacío -------------------------------------------------------- */
.empty {
  text-align: center;
  padding: 72px 24px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
}
.empty-icon { width: 44px; height: 44px; color: var(--muted-2); margin-bottom: 6px; }
.empty h2 { margin: 8px 0 4px; font-size: 19px; font-weight: 600; letter-spacing: -0.01em; }
.empty p { margin: 0 0 22px; color: var(--muted); }

/* ---- Tarjetas ------------------------------------------------------------ */
.card {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 26px 28px;
  box-shadow: var(--shadow-sm);
  margin-bottom: 20px;
}
.card-title {
  margin: 0 0 18px;
  font-size: 11px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.13em;
  color: var(--muted);
}
.card-calc { background: var(--brand-softer); border-color: #f4e0d4; }

/* ---- Formulario de creación ---------------------------------------------- */
.form-card { padding: 12px 30px 24px; }
.form-section { padding: 22px 0; border-bottom: 1px solid var(--border); }
.form-section:first-child { padding-top: 18px; }
.form-section:last-of-type { border-bottom: none; }
.form-section-head { display: flex; align-items: center; gap: 12px; margin-bottom: 20px; }
.form-section-ic {
  display: inline-grid; place-items: center;
  width: 36px; height: 36px; border-radius: var(--radius-sm); flex: none;
  background: var(--chip-bg); color: var(--chip-fg);
}
.form-section-ic .icon { width: 18px; height: 18px; }
.form-section-title { font-size: 15px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }
.form-section-sub { font-size: 12.5px; color: var(--muted); margin-top: 1px; }
.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px 26px;
}
.field { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.field-label {
  font-size: 13px; font-weight: 600; color: var(--ink-soft);
  display: flex; align-items: baseline; gap: 6px;
}
.field-unit {
  font-size: 11.5px; color: var(--muted-2); font-weight: 400;
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 1px 6px; border-radius: 5px;
}
.field-input {
  width: 100%;
  padding: 11px 13px;
  min-height: 42px;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  font-size: 14.5px;
  color: var(--ink);
  background: var(--surface);
  transition: border-color 0.15s, box-shadow 0.15s;
  outline: none;
}
.field-input::placeholder { color: var(--muted-2); }
.field-input:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.field-input.inline { padding: 7px 10px; font-size: 14px; }

.form-actions {
  display: flex; justify-content: flex-end; gap: 10px;
  margin-top: 28px;
  padding-top: 22px;
  border-top: 1px solid var(--border);
}
.form-note {
  margin: 14px 2px 0;
  color: var(--muted);
  font-size: 13px;
  line-height: 1.55;
}

/* ---- Combobox ------------------------------------------------------------ */
.combo { position: relative; }
.combo-control {
  display: flex; align-items: center;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.combo-control.focused { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.combo-input {
  flex: 1; min-width: 0;
  border: none; outline: none; background: transparent;
  padding: 10px 12px;
  font-size: 14.5px; color: var(--ink);
  font-family: inherit;
}
.combo-input::placeholder { color: var(--muted-2); }
.combo-chev { color: var(--muted-2); margin-right: 10px; width: 16px; height: 16px; cursor: pointer; flex: none; }

.combo-panel {
  position: absolute;
  top: calc(100% + 6px);
  left: 0; right: 0;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg);
  padding: 6px;
  z-index: 60;
  display: none;
  max-height: 264px;
  overflow-y: auto;
  animation: pop 0.12s ease;
}
.combo-panel.open { display: block; }
.combo-item {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 8px 10px;
  border: none; background: transparent;
  border-radius: 6px;
  font-size: 14px; color: var(--ink-soft);
  cursor: pointer; text-align: left;
}
.combo-item:hover { background: var(--surface-2); }
/* Fila con papelera: la opción ocupa todo menos el botón de quitar, que solo
   se despinta al pasar por encima para que no compita con la propia opción. */
.combo-fila { display: flex; align-items: stretch; }
.combo-fila > .combo-item { flex: 1; min-width: 0; }
.combo-fila:hover { background: var(--surface-2); }
.combo-quitar {
  flex: none; width: 34px; display: grid; place-items: center;
  border: none; background: transparent; color: transparent; cursor: pointer;
  transition: color 0.15s, background 0.15s;
}
.combo-fila:hover .combo-quitar { color: var(--muted-2); }
.combo-quitar:hover { color: var(--danger); background: var(--danger-bg); }
.combo-quitar .icon { width: 13px; height: 13px; }
/* En táctil no hay «pasar por encima»: si se deja transparente, el botón está
   ahí pero no se ve, y se pulsa sin querer. */
@media (hover: none) {
  .combo-quitar { color: var(--muted-2); }
}
.combo-item.active { color: var(--ink); font-weight: 600; }
.combo-item .icon { margin-left: auto; color: var(--ink); }
/* Ya puesto en otra fila: se enseña, no se esconde, pero se apaga para que no
   compita con las que sí están libres. */
.combo-item.usada { color: var(--muted-2); }
.combo-nota {
  margin-left: auto; padding-left: 10px; flex: none;
  font-size: 11.5px; font-weight: 600; color: var(--muted-2);
}
.combo-add {
  display: flex; align-items: center; gap: 8px;
  width: 100%;
  padding: 9px 10px;
  margin-top: 4px;
  border: none;
  border-top: 1px solid var(--border);
  background: transparent;
  border-radius: 0 0 6px 6px;
  font-size: 14px; color: var(--accent);
  cursor: pointer; text-align: left;
}
.combo-add:hover { background: var(--surface-2); }
.combo-add .icon { color: var(--accent); }
.combo-add strong { font-weight: 600; }
.combo-hint, .combo-empty {
  padding: 9px 10px; font-size: 12.5px; color: var(--muted-2);
  border-top: 1px solid var(--border); margin-top: 4px;
}
.combo-empty { border-top: none; margin-top: 0; }

/* ---- Selector de perfil (arquitecto / promotor) ------------------------- */
.perfil-picker { position: relative; }
.perfil-control {
  display: flex; align-items: center; gap: 8px; width: 100%;
  padding: 10px 12px; border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); font-size: 14.5px; color: var(--ink); font-family: inherit;
  cursor: pointer; text-align: left; transition: border-color 0.15s, box-shadow 0.15s;
}
.perfil-control.open { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.perfil-control-txt { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.perfil-control-txt.placeholder { color: var(--muted-2); }
.perfil-chev { color: var(--muted-2); width: 16px; height: 16px; flex: none; }
.perfil-panel {
  position: absolute; top: calc(100% + 6px); left: 0; right: 0;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg); padding: 6px; z-index: 60; display: none;
  max-height: 300px; overflow-y: auto; animation: pop 0.12s ease;
}
.perfil-panel.open { display: block; }
.perfil-search-wrap { display: flex; align-items: center; gap: 7px; padding: 6px 9px; margin-bottom: 4px; border: 1px solid var(--border); border-radius: 8px; background: var(--surface-2); }
.perfil-search-wrap .icon { color: var(--muted-2); width: 15px; height: 15px; flex: none; }
.perfil-search { flex: 1; min-width: 0; border: none; outline: none; background: transparent; font-family: inherit; font-size: 14px; color: var(--ink); }
.perfil-list { display: flex; flex-direction: column; }
/* Ya no es un <button> —dentro lleva otros dos, editar y borrar, y un botón
   no puede contener botones— pero se comporta igual: toda la fila selecciona
   salvo el rincón de las acciones. */
.perfil-item {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 8px 10px;
  border-radius: 6px; cursor: pointer; text-align: left;
}
.perfil-item:hover { background: var(--surface-2); }
.perfil-item.active { background: var(--brand-soft); }
.perfil-item-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; flex: 1; }
.perfil-item-name { font-size: 14px; color: var(--ink); font-weight: 400; }
.perfil-item-sub { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.perfil-item-right { margin-left: auto; display: flex; align-items: center; gap: 4px; flex: none; }
.perfil-item-check.icon { color: var(--brand-ink); }
/* Editar / borrar directamente desde el desplegable: solo se revelan al
   pasar el ratón por la fila (como el resto de la app), y en pantallas
   táctiles quedan siempre a la vista — la media query de más abajo se
   encarga, igual que con `.row-delete`. */
.perfil-item-acciones { display: flex; gap: 2px; opacity: 0; transition: opacity 0.12s; }
.perfil-item:hover .perfil-item-acciones, .perfil-item:focus-within .perfil-item-acciones { opacity: 1; }
.perfil-item-accion {
  display: inline-grid; place-items: center; width: 28px; height: 28px;
  border: none; background: transparent; border-radius: 6px;
  color: var(--muted); cursor: pointer; transition: background 0.12s, color 0.12s;
}
.perfil-item-accion:hover { background: var(--surface); color: var(--ink); }
.perfil-item-accion-danger:hover { background: var(--danger-bg); color: var(--danger); }
.perfil-empty { padding: 14px 10px; font-size: 13px; color: var(--muted-2); text-align: center; }
.perfil-add {
  display: flex; align-items: center; gap: 8px; width: 100%; padding: 10px;
  margin-top: 4px; border: none; border-top: 1px solid var(--border); background: transparent;
  font-size: 14px; font-weight: 600; color: var(--accent); cursor: pointer; text-align: left;
}
.perfil-add:hover { background: var(--surface-2); }
.perfil-add .icon { color: var(--accent); }

/* Celda de arquitecto/promotor en el detalle (nombre + ver ficha) */
.perfil-cell { display: inline-flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.perfil-goto {
  display: inline-flex; align-items: center; gap: 4px;
  padding: 3px 9px; border-radius: 6px; background: var(--brand-soft); color: var(--brand-ink);
  font-size: 12px; font-weight: 600; transition: filter 0.15s;
}
.perfil-goto:hover { filter: brightness(0.96); }
.perfil-goto .icon { width: 12px; height: 12px; }
/* Varios (otros colaboradores): un `.perfil-cell` por línea, no en fila */
.perfil-cell-multi { display: flex; flex-direction: column; gap: 8px; align-items: flex-start; }

/* ---- Selector de VARIOS perfiles (otros colaboradores) ------------------- */
.perfil-picker-multi { display: flex; flex-direction: column; gap: 8px; width: 100%; }
.perfil-picker-filas { display: flex; flex-direction: column; gap: 8px; }
.perfil-picker-fila { width: 100%; }
.soft-row > .perfil-picker { flex: 1 1 220px; min-width: 0; }

/* Modal de perfil: cabecera fija · cuerpo con scroll · pie con acciones */
/* Doble clase: gana a `.modal` (max-width 420px) sin depender del orden */
.modal.modal-perfil {
  max-width: 720px; width: 100%; padding: 0;
  display: flex; flex-direction: column; max-height: 88vh; overflow: hidden;
}

/* ---- Datos de la obra, en panel ------------------------------------------ *
 * Más ancho que el de perfil porque dentro van los mismos `.campos` de antes,
 * que a partir de 900px se ponen en dos columnas. Con 720px las dos columnas
 * salían apretadas y las etiquetas se partían en dos líneas.
 * -------------------------------------------------------------------------- */
.modal.modal-datos {
  max-width: 1000px; width: 100%; padding: 0;
  display: flex; flex-direction: column; max-height: 88vh; overflow: hidden;
}
.modal-datos > .modal-title {
  margin: 0; padding: 22px 28px 18px;
  font-size: 19px; font-weight: 600; letter-spacing: -0.015em;
  border-bottom: 1px solid var(--border);
}
.modal-datos-body { flex: 1; min-height: 0; overflow-y: auto; padding: 4px 28px 14px; }
.modal-datos > .modal-actions {
  padding: 16px 28px 20px; border-top: 1px solid var(--border); background: var(--surface-2);
}
/* La última fila de cada columna no necesita raya: ya la pone el pie. */
.modal-datos .campo:last-child { border-bottom: none; }
.modal-perfil > .modal-title {
  margin: 0; padding: 22px 28px 18px;
  font-size: 19px; font-weight: 600; letter-spacing: -0.015em;
  text-transform: capitalize;
  border-bottom: 1px solid var(--border);
}
.modal-perfil-body { flex: 1; min-height: 0; overflow-y: auto; padding: 6px 28px; }
.modal-perfil .form-section { padding: 22px 0; border-bottom: 1px solid var(--border); }
.modal-perfil .form-section:first-child { padding-top: 18px; }
.modal-perfil .form-section:last-child { border-bottom: none; padding-bottom: 6px; }
.modal-perfil .form-section-head { margin-bottom: 18px; }
.modal-perfil .form-grid { gap: 16px 22px; }
.modal-perfil .field-hint { margin: 0 0 16px; }
.modal-perfil > .modal-actions { padding: 16px 28px 20px; border-top: 1px solid var(--border); background: var(--surface-2); }
.perfil-error { display: none; margin: 0; padding: 12px 28px 0; font-size: 13px; color: var(--danger); font-weight: 600; }
.perfil-error.show { display: block; }

/* ---- Ficha de perfil (página): cabecera + tarjetas + edición en línea ---- */
.pf-header { margin-bottom: 22px; }
.pf-header-main { display: flex; align-items: center; gap: 16px; margin-top: 14px; }
.pf-avatar { display: inline-grid; place-items: center; width: 56px; height: 56px; border-radius: var(--radius); flex: none; background: var(--chip-bg); color: var(--chip-fg); font-size: 20px; font-weight: 600; letter-spacing: -0.02em; }
.pf-header-txt { flex: 1; min-width: 0; }
.pf-name { margin: 0; font-size: 26px; font-weight: 600; letter-spacing: -0.02em; color: var(--ink); line-height: 1.12; overflow-wrap: anywhere; }
.pf-tipo { display: inline-block; margin-top: 7px; padding: 3px 10px; border-radius: 6px; background: var(--surface-2); border: 1px solid var(--border); color: var(--muted); font-size: 12px; font-weight: 400; text-transform: capitalize; }
.pf-head-actions { display: flex; gap: 10px; flex: none; }
.pf-error { display: none; margin-top: 16px; padding: 11px 15px; background: var(--danger-bg); border: 1px solid var(--danger-bd); border-radius: var(--radius-sm); color: var(--danger); font-size: 13px; font-weight: 600; }
.pf-error.show { display: block; }

.pf-card { padding: 22px 26px; }
.pf-rows { display: flex; flex-direction: column; }
.pf-row { display: grid; grid-template-columns: minmax(0, 190px) minmax(0, 1fr); gap: 16px 20px; align-items: center; padding: 13px 0; border-top: 1px solid var(--border); }
.pf-row:first-child { border-top: none; padding-top: 4px; }
.pf-row.editing { align-items: start; }
.pf-label { font-size: 13px; color: var(--muted); font-weight: 400; min-width: 0; }
.pf-row.editing .pf-label { padding-top: 11px; }
/* Correos y URLs largas parten de línea en vez de estirar la fila. */
.pf-value { font-size: 14.5px; color: var(--ink); line-height: 1.5; min-width: 0; overflow-wrap: anywhere; }
.pf-value .field-input { width: 100%; }
.pf-dir div { line-height: 1.5; }

/* Campos: ancho completo, textarea, ayuda */
.field-wide { grid-column: 1 / -1; }
.field-area { resize: vertical; min-height: 44px; line-height: 1.5; font-family: inherit; }
.field-hint { margin: -8px 0 16px; font-size: 12.5px; color: var(--muted); }

/* Input de teléfono (país + número) */
.tel-input { display: flex; gap: 8px; }
.tel-pais {
  flex: none; width: 104px; padding: 10px 8px; border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm); background: var(--surface); font-family: inherit; font-size: 14px;
  color: var(--ink); outline: none; cursor: pointer;
}
.tel-pais:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.tel-num { flex: 1 1 auto; min-width: 96px; }

.perfil-web { display: inline-flex; align-items: center; gap: 5px; color: var(--brand-ink); font-weight: 400; max-width: 100%; overflow-wrap: anywhere; }
.perfil-web:hover { text-decoration: underline; }
.perfil-web .icon { width: 13px; height: 13px; }

/* Chip de contacto con menú de acciones. Nunca sobresale de su columna: el
   texto (un correo puede ser larguísimo) se recorta con puntos suspensivos. */
.cc { position: relative; display: inline-block; max-width: 100%; min-width: 0; }
.cc-chip {
  display: inline-flex; align-items: center; gap: 8px; padding: 7px 12px;
  max-width: 100%; min-height: 40px;
  border: 1px solid var(--border-strong); border-radius: 100px; background: var(--surface);
  font-family: inherit; font-size: 14px; color: var(--ink); font-weight: 400; cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.cc-chip:hover, .cc-chip.open { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.cc-chip > .icon { width: 15px; height: 15px; color: var(--brand); flex: none; }
.cc-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cc-chev { width: 14px; height: 14px; color: var(--muted-2); flex: none; }
.cc-menu {
  position: absolute; top: calc(100% + 6px); left: 0; min-width: 190px; max-width: min(280px, 88vw);
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius-sm);
  box-shadow: var(--shadow-lg); padding: 6px; z-index: 60; display: none; animation: pop 0.12s ease;
}
.cc-menu.open { display: block; }
.cc-action { display: flex; align-items: center; gap: 10px; padding: 9px 10px; border-radius: 6px; font-size: 14px; color: var(--ink-soft); }
.cc-action:hover { background: var(--surface-2); color: var(--ink); }
.cc-action .icon { width: 16px; height: 16px; color: var(--brand); }

/* ---- Detalle: campos editables ------------------------------------------- */
.detalle-estado { align-self: flex-end; }
/* Acciones de la cabecera del detalle: exportar a PDF + estado de la obra */
/* Envuelve en vez de desbordar. Con `flex: none` y sin envolver, en cuanto la
   fila juntaba cuatro cosas —datos, PDF, estado y fase— se salía de la
   pantalla en los anchos intermedios (medido: 922px de contenido en una
   ventana de 768). Ahora los botones bajan a una segunda línea, alineados a
   la derecha, y la fila nunca empuja la página a lo ancho. */
.detalle-acciones {
  display: flex; align-items: center; gap: 10px;
  align-self: flex-end;
  flex-wrap: wrap; justify-content: flex-end;
  min-width: 0;
}
/* Que el título ceda antes que los botones: un encargo largo no debe empujar
   las acciones fuera de la pantalla. */
.page-head > div:first-child { min-width: 0; }

/* Dos columnas a partir de 900px: en una sola, cada dato ocupaba una línea
   entera de ~1000px con el valor pegado a la izquierda y medio ancho vacío. */
.campos { display: grid; grid-template-columns: 1fr; column-gap: 38px; }
@media (min-width: 900px) { .campos { grid-template-columns: 1fr 1fr; } }
.campo {
  display: grid;
  grid-template-columns: minmax(0, 150px) minmax(0, 1fr) auto;
  align-items: center;
  gap: 14px;
  padding: 14px 4px;
  border-bottom: 1px solid var(--border);
  min-height: 56px;
}
/* En una columna, el último no lleva raya. En dos, la quitan los dos últimos:
   si no, queda una raya suelta bajo el único campo de la fila final. */
.campos > .campo:last-child { border-bottom: none; }
@media (min-width: 900px) {
  .campos > .campo:nth-last-child(-n+2):nth-child(odd),
  .campos > .campo:nth-last-child(-n+2):nth-child(odd) ~ .campo { border-bottom: none; }
}
.campo-label { font-size: 13.5px; color: var(--muted); font-weight: 400; }
.campo-valor {
  font-size: 15px; color: var(--ink); font-weight: 400;
  display: flex; align-items: center; gap: 10px; min-width: 0;
}
.campo-calc .campo-valor { font-variant-numeric: tabular-nums; }

.link-map {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--accent); font-weight: 600;
  border-bottom: 1px solid transparent;
  transition: border-color 0.14s;
}
.link-map:hover { border-color: var(--accent); }
.link-map .icon { color: var(--ink-soft); }

.edit-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: 1px solid transparent;
  background: transparent;
  color: var(--muted-2);
  border-radius: 8px;
  cursor: pointer;
  opacity: 0;
  transition: opacity 0.14s, background 0.14s, color 0.14s, border-color 0.14s;
}
.campo:hover .edit-btn { opacity: 1; }
.edit-btn:hover { background: var(--surface-2); color: var(--ink); border-color: var(--border); }
.edit-btn .icon { width: 15px; height: 15px; }
.edit-btn.hidden { display: none; }

.inline-editor { display: flex; align-items: center; gap: 8px; width: 100%; }
.inline-editor .field-input { max-width: 320px; }
.inline-combo { width: 320px; max-width: 100%; }
/* Editor de varios perfiles (otros colaboradores): las filas del picker no
   caben en una línea junto a Guardar/Cancelar como el resto de campos, así
   que van apiladas y los botones quedan debajo, no al lado. */
.inline-editor-column { display: flex; flex-direction: column; align-items: flex-start; gap: 10px; width: 100%; }
.inline-editor-column .perfil-picker-multi { width: 100%; }
.editor-actions { display: flex; gap: 4px; }
.icon-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 32px; height: 32px;
  border: 1px solid var(--border-strong);
  background: var(--surface);
  border-radius: 8px; cursor: pointer;
  transition: background 0.14s, border-color 0.14s, color 0.14s;
}
.icon-btn .icon { width: 16px; height: 16px; }
.icon-btn.save { background: var(--accent); color: #fff; border-color: var(--accent); }
.icon-btn.save:hover { background: var(--accent-hover); }
.icon-btn.cancel { color: var(--muted); }
.icon-btn.cancel:hover { background: var(--surface-2); color: var(--ink); border-color: var(--muted-2); }
/* Deshabilitado: se mantiene en su sitio (no desaparece) para que la fila no
   baile al mover un capítulo al primer o último puesto. */
/* Un botón bloqueado tiene que PARECERLO. Sin esto, el de «Quitar y
   reasignar» salía en rojo pleno mientras aún no se podía pulsar, y lo único
   que decía que estaba bloqueado era el texto. */
.btn:disabled { opacity: 0.45; cursor: default; box-shadow: none; }
.btn:disabled:hover { filter: none; }

.icon-btn:disabled { opacity: 0.3; cursor: default; }
.icon-btn:disabled:hover { background: var(--surface); border-color: var(--border-strong); }
/* El chevron apunta hacia abajo: girado 180° sirve de flecha para subir. */
.chev-arriba { transform: rotate(180deg); }

.tag-manual {
  font-size: 11px; font-weight: 600;
  color: var(--st-paralizada);
  background: var(--warn-bg); border: 1px solid var(--warn-bd);
  padding: 1px 7px; border-radius: 100px;
  letter-spacing: 0.01em;
}

/* ---- Zona peligrosa ------------------------------------------------------ */
.danger-zone { margin-top: 28px; display: flex; justify-content: flex-end; }

/* ---- Modal --------------------------------------------------------------- */
.modal-overlay {
  position: fixed; inset: 0;
  background: rgba(24, 24, 27, 0.32);
  backdrop-filter: blur(2px);
  display: grid; place-items: center;
  z-index: 100;
  padding: 24px;
  animation: fade 0.14s ease;
}
.modal {
  background: var(--surface);
  border-radius: var(--radius);
  box-shadow: var(--shadow-lg);
  padding: 26px;
  max-width: 420px; width: 100%;
  animation: pop 0.16s ease;
}
/* Para diálogos con una lista dentro (reasignar tipologías): con 420px las
   dos columnas de cada fila se quedan sin sitio y el nombre de la obra se
   parte en tres líneas. */
.modal-ancho { max-width: 560px; }

.modal-title { margin: 0 0 8px; font-size: 18px; font-weight: 600; letter-spacing: -0.01em; }
.modal-text { margin: 0 0 22px; color: var(--ink-soft); line-height: 1.55; }
.modal-actions { display: flex; justify-content: flex-end; gap: 10px; }

/* ---- Reasignar tipología antes de quitarla ------------------------------- */
.reasig-todas {
  display: flex; align-items: center; gap: 10px; flex-wrap: wrap;
  padding: 12px; margin-bottom: 12px;
  background: var(--surface-2); border-radius: var(--radius-sm);
}
.reasig-todas-lbl { font-size: 13px; font-weight: 600; color: var(--ink-soft); flex: none; }
.reasig-todas .reasig-select { flex: 1; min-width: 160px; }

/* Con muchas obras la lista se desplaza dentro del diálogo: sin tope, con
   quince obras los botones de abajo se irían fuera de la pantalla. */
.reasig-lista {
  display: flex; flex-direction: column; gap: 8px;
  max-height: 46vh; overflow-y: auto;
  margin-bottom: 18px;
}
.reasig-fila {
  display: flex; align-items: center; gap: 12px;
  padding: 10px 12px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.reasig-obra { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.reasig-ref {
  font-size: 12px; color: var(--muted-2);
  font-variant-numeric: tabular-nums; letter-spacing: 0.03em;
}
.reasig-nombre {
  font-size: 14px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.reasig-select { flex: none; width: 190px; min-height: 40px; }

/* En el móvil el desplegable baja bajo el nombre de la obra: al lado dejaría
   las dos columnas tan estrechas que no se leería ninguna. */
@media (max-width: 560px) {
  .reasig-fila { flex-direction: column; align-items: stretch; gap: 8px; }
  .reasig-select { width: 100%; }
  .reasig-nombre { white-space: normal; }
  .reasig-lista { max-height: 42vh; }
}
/* Campo de pedirTexto(): como hijo directo de un .modal simple (no modal-perfil,
   que ya controla su propio espaciado con flex). */
.modal > .field-wide { margin: 2px 0 16px; }
.modal-input-error { display: none; margin: -8px 0 16px; font-size: 13px; color: var(--danger); font-weight: 600; }
.modal-input-error.show { display: block; }
/* Campos de pedirFormulario(): etiqueta encima del campo, con su ayuda debajo. */
.modal-campos { display: flex; flex-direction: column; gap: 15px; margin: 2px 0 18px; }
.modal-campo { display: flex; flex-direction: column; gap: 6px; }
.modal-campo-label { font-size: 13px; font-weight: 600; color: var(--ink-soft); }
.modal-campo-ayuda { font-size: 12px; color: var(--muted-2); line-height: 1.35; }
/* En iOS el campo de fecha se queda bajo si no se le da alto de control. */
.modal-campo .field-input[type="date"] { min-height: 44px; }

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

/* ---- Dashboard: rejilla que se pliega sola ------------------------------ *
 * `auto-fit` + `minmax` reparte 3 · 2 · 1 columnas según el ancho REAL del
 * contenido, sin depender de media queries que ignoran el ancho de la barra
 * lateral. Es lo que evita que las tarjetas se estrujen en tablet.
 * ------------------------------------------------------------------------- */
/* Se usa flex, no grid: cuando en la última fila queda una sola tarjeta, ésta
   ocupa el ancho sobrante en vez de dejar un hueco a su derecha. */
.dash-grid-3 {
  display: flex;
  flex-wrap: wrap;
  gap: 18px;
  margin-bottom: 18px;
  align-items: stretch;
}
.dash-grid-3 > * { flex: 1 1 236px; min-width: 0; }
.dash-charts-3 > * { flex: 1 1 300px; }

/* KPIs de la primera fila */
.kpi {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: 20px 22px 18px;
  box-shadow: var(--shadow-sm);
  display: flex; flex-direction: column;
  min-width: 0;
  position: relative;
  overflow: hidden;
}
.kpi::before {
  content: ''; position: absolute; top: 0; left: 0; right: 0; height: 2px;
  background: var(--chip-fg, var(--brand));
}
.kpi-top { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; min-width: 0; }

/* Selector de franja temporal (discreto: no compite con el dato). El
   alineado a la derecha lo decide cada contenedor (`space-between` o un
   `margin-left: auto` propio); este componente no impone el suyo. */
.periodo-select {
  flex: 0 1 auto; min-width: 0;
  max-width: 132px;
  padding: 4px 6px;
  border: 1px solid transparent; border-radius: 8px;
  background: transparent; font-family: inherit;
  font-size: 11.5px; font-weight: 600; color: var(--muted);
  cursor: pointer; outline: none;
  transition: background 0.15s, border-color 0.15s, color 0.15s;
}
.periodo-select:hover { background: var(--surface-2); border-color: var(--border); color: var(--ink-soft); }
.periodo-select:focus-visible { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); color: var(--ink-soft); }
.kpi-chip {
  display: inline-grid; place-items: center;
  width: 36px; height: 36px; border-radius: var(--radius-sm); flex: none;
  background: var(--chip-bg); color: var(--chip-fg);
}
.kpi-chip .icon { width: 18px; height: 18px; }
.kpi-label { font-size: 12.5px; color: var(--muted); font-weight: 600; letter-spacing: 0.01em; min-width: 0; flex: 1 1 auto; }
.kpi-value {
  font-size: 30px; font-weight: 600; letter-spacing: -0.03em; color: var(--ink);
  /* 1.05 recortaba por abajo el € y el % (la caja del glifo es más alta que
     la línea, y el overflow oculto se los comía). */
  line-height: 1.18; font-variant-numeric: tabular-nums;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.kpi-meter { height: 7px; border-radius: 100px; background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border); overflow: hidden; margin-top: 13px; }
.kpi-meter-fill { height: 100%; border-radius: 100px; background: var(--chip-fg); transition: width 0.45s ease; }
.kpi-sub { font-size: 12.5px; color: var(--muted-2); margin-top: 9px; }

/* Tarjetas de gráfico (fila 2) */
.dash-charts-3 .chart-card { margin-bottom: 0; display: flex; flex-direction: column; padding: 20px 22px 22px; }
.chart-head { display: flex; align-items: center; justify-content: space-between; gap: 6px 10px; flex-wrap: wrap; padding-bottom: 14px; margin-bottom: 4px; border-bottom: 1px solid var(--border); min-height: 30px; }
.chart-head .card-title { margin-bottom: 0; min-width: 0; }
.chart-sub { font-size: 12px; color: var(--muted-2); white-space: nowrap; }
/* Las tres tarjetas de la fila comparten alto (lo marca la más alta, el
   donut). Centrando el contenido, a las cortas no les queda un vacío al pie
   que parezca que falta algo: se lee como aire deliberado. */
.chart-body { flex: 1; display: flex; flex-direction: column; justify-content: center; padding-top: 16px; }

/* €/m² medio por tipología */
.m2-list { display: flex; flex-direction: column; gap: 15px; }
.m2-row { display: flex; flex-direction: column; gap: 6px; }
.m2-top { display: flex; align-items: baseline; justify-content: space-between; gap: 10px; }
.m2-label { font-size: 13px; color: var(--ink-soft); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.m2-val { font-size: 14px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; white-space: nowrap; }
.m2-track { height: 8px; border-radius: 100px; background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border); overflow: hidden; }
.m2-fill { height: 100%; border-radius: 100px; background: var(--c-amber); transition: width 0.4s ease; }
.m2-n { font-size: 11.5px; color: var(--muted-2); }
.chart-card { margin-bottom: 0; }
.chart-empty { padding: 40px 8px; text-align: center; color: var(--muted-2); font-size: 14px; }

.donut-block { display: flex; align-items: center; gap: 26px; flex-wrap: wrap; }
.donut-wrap { position: relative; width: 146px; height: 146px; flex: none; }
.donut { width: 146px; height: 146px; transform: rotate(0deg); }
.donut-center {
  position: absolute; inset: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  pointer-events: none;
}
.donut-total { font-size: 30px; font-weight: 600; letter-spacing: -0.02em; color: var(--ink); line-height: 1; }
.donut-total-label { font-size: 11.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.06em; margin-top: 3px; }
.donut-legend { display: flex; flex-direction: column; gap: 5px; flex: 1 1 150px; min-width: 0; }
.legend-item {
  display: flex; align-items: center; gap: 10px; font-size: 13px;
  padding: 5px 8px; border-radius: 8px; transition: background 0.14s;
}
.legend-item:hover { background: var(--surface-2); }
.legend-dot { width: 10px; height: 10px; border-radius: 4px; flex: none; }
.legend-label { color: var(--ink-soft); flex: 1; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.legend-val { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Leyenda a dos niveles: una línea de grupo con el total y, colgando de ella,
   el desglose. El filo de la izquierda es lo que ata los hijos a su grupo. */
.legend-grupo { font-weight: 600; }
.legend-grupo .legend-label { color: var(--ink); }
.legend-grupo + .legend-sub { margin-top: 1px; }
.legend-sub {
  margin-left: 13px; padding-left: 13px;
  border-left: 2px solid var(--border);
  border-radius: 0 8px 8px 0;
  font-size: 12.5px;
}
.legend-sub .legend-label { color: var(--muted); }
.legend-sub .legend-dot { width: 8px; height: 8px; border-radius: 3px; }
.legend-sub .legend-val { font-weight: 400; color: var(--ink-soft); }
/* Variante apilada: anillo arriba, leyenda debajo (columna estrecha) */
.donut-block.vertical { flex-direction: column; gap: 18px; align-items: stretch; }
.donut-block.vertical .donut-wrap { align-self: center; }
/* En vertical el eje principal es la altura: sin esto, el `flex-basis` de la
   leyenda reservaría 150px de alto aunque esté vacía. */
.donut-block.vertical .donut-legend { flex: 0 0 auto; width: 100%; min-width: 0; }

/* ---- Barra segmentada de importes ------------------------------------------
 * Variante horizontal para dinero: una franja apilada por tramos con el
 * porcentaje dentro cuando cabe, y debajo una leyenda con el peso y el
 * importe de cada tramo.
 * ------------------------------------------------------------------------- */
.barseg-block { display: flex; flex-direction: column; gap: 18px; }
.barseg-track {
  display: flex; height: 44px; border-radius: 12px; overflow: hidden;
  background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border);
}
.barseg-seg {
  display: flex; align-items: center; justify-content: center;
  min-width: 3px; transition: width 0.4s ease;
}
.barseg-seg.barseg-vacio { width: 100%; }
.barseg-pct {
  font-size: 12.5px; font-weight: 700; color: #fff; letter-spacing: 0.01em;
  text-shadow: 0 1px 2px rgba(0, 0, 0, 0.2);
}
.barseg-legend { display: flex; flex-wrap: wrap; gap: 10px 22px; }
.barseg-item { display: flex; align-items: baseline; gap: 8px; font-size: 13px; min-width: 0; }
.barseg-item .legend-dot { align-self: center; }
.barseg-label { color: var(--ink-soft); white-space: nowrap; }
.barseg-cifras { display: flex; align-items: baseline; gap: 7px; font-variant-numeric: tabular-nums; white-space: nowrap; }
.barseg-item-pct { font-weight: 600; color: var(--ink); }
.barseg-eur { font-size: 12px; color: var(--muted-2); }

.barlist { display: flex; flex-direction: column; gap: 15px; padding-top: 4px; }
.bar-row { display: grid; grid-template-columns: minmax(0, 150px) minmax(0, 1fr) auto; align-items: center; gap: 12px; }
.bar-label {
  font-size: 13px; color: var(--ink-soft);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.bar-track { height: 11px; background: var(--surface-2); border: 1px solid var(--border); border-radius: 100px; overflow: hidden; }
.bar-fill { height: 100%; background: var(--brand); border-radius: 100px; transition: width 0.4s ease; min-width: 6px; }
.bar-val { font-size: 13px; color: var(--ink); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
/* Variante compacta: etiqueta arriba, barra debajo (columna estrecha) */
.barlist.compact { gap: 14px; }
.barlist.compact .bar-row {
  grid-template-columns: 1fr auto;
  grid-template-areas: 'label val' 'track track';
  gap: 6px 10px; align-items: baseline;
}
.barlist.compact .bar-label { grid-area: label; }
.barlist.compact .bar-val { grid-area: val; }
.barlist.compact .bar-track { grid-area: track; height: 8px; }

/* ---- Dashboard: mini-list (últimas obras) ------------------------------- */
.card-head-row { display: flex; align-items: center; justify-content: space-between; gap: 8px 12px; flex-wrap: wrap; margin-bottom: 14px; }
.card-head-row .card-title { margin-bottom: 0; }
.card-head-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; margin-left: auto; }
.link-mini { display: inline-flex; align-items: center; gap: 3px; font-size: 13px; color: var(--muted); font-weight: 400; }
.link-mini:hover { color: var(--ink); }
.link-mini .chev-right { width: 14px !important; height: 14px !important; }
.mini-list { display: flex; flex-direction: column; }
.mini-row {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 6px; border-top: 1px solid var(--border); cursor: pointer;
  transition: background 0.12s; border-radius: 8px;
}
.mini-row:first-child { border-top: none; }
.mini-row:hover { background: var(--surface-2); }
.mini-main { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.mini-title { font-weight: 600; color: var(--ink); font-size: 14.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mini-meta { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

/* ---- Dashboard: últimos proyectos (tarjetas) --------------------------- */
/* auto-fit (no auto-fill): con menos de tres proyectos las tarjetas se
   reparten el ancho en vez de dejar huecos vacíos a la derecha. */
.proy-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(226px, 1fr)); gap: 14px; }
.proy-card {
  display: flex; flex-direction: column; min-width: 0;
  padding: 16px 18px 14px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2); cursor: pointer;
  transition: border-color 0.15s, box-shadow 0.15s, transform 0.15s, background 0.15s;
}
.proy-card:hover { background: var(--surface); border-color: var(--border-strong); box-shadow: var(--shadow-md); transform: translateY(-2px); }
.proy-top { display: flex; align-items: center; justify-content: space-between; gap: 10px; margin-bottom: 13px; }
.proy-avatar {
  display: inline-grid; place-items: center; width: 36px; height: 36px; flex: none;
  border-radius: var(--radius-sm); background: var(--chip-bg); color: var(--chip-fg);
}
.proy-avatar .icon { width: 18px; height: 18px; }
/* Mismo criterio que en el listado: dos líneas antes que cortar por la mitad
   un nombre cuya parte útil está al final. */
.proy-name {
  font-size: 15px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em;
  display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden; overflow-wrap: anywhere;
  min-height: 2.6em;          /* las tres tarjetas, a la misma altura */
}
.proy-meta { font-size: 12.5px; color: var(--muted); margin-top: 3px; font-variant-numeric: tabular-nums; }
.proy-foot {
  display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border);
}
.proy-foot-label { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.05em; color: var(--muted-2); }
.proy-foot-val { font-size: 14.5px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }

.empty-inline { text-align: center; padding: 48px 24px; }
.empty-inline .empty-icon { width: 40px; height: 40px; color: var(--muted-2); }
.empty-inline h2 { margin: 8px 0 4px; font-size: 18px; font-weight: 600; }
.empty-inline p { margin: 0 0 20px; color: var(--muted); }

/* ---- Segmented tabs (costes) -------------------------------------------- */
.seg-tabs {
  display: inline-flex; gap: 4px;
  background: var(--surface-2); border: 1px solid var(--border);
  padding: 4px; border-radius: var(--radius-sm); margin-bottom: 24px;
}
.seg-tab {
  display: inline-flex; align-items: center; gap: 8px;
  padding: 8px 16px; border: none; background: transparent;
  border-radius: 8px; font-size: 14px; font-weight: 400; color: var(--muted);
  cursor: pointer; transition: background 0.14s, color 0.14s, box-shadow 0.14s;
}
.seg-tab .icon { width: 16px; height: 16px; }
/* El rótulo nunca se parte: la pestaña entera pasa a la línea siguiente */
.seg-tab { white-space: nowrap; }
.seg-tab:hover { color: var(--ink-soft); }
.seg-tab.active { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); font-weight: 600; }

/* ---- Costes: layout con panel de resultado ------------------------------ */
.coste-layout { display: grid; grid-template-columns: 1fr 300px; gap: 22px; align-items: start; }
.coste-main { min-width: 0; }
.coste-aside { position: sticky; top: 24px; }
.card-note { margin: -6px 0 16px; color: var(--muted); font-size: 13px; line-height: 1.5; }

.coste-fields { display: flex; flex-direction: column; }
.coste-fields.two {
  display: grid; grid-template-columns: 1fr 1fr; gap: 14px 20px;
}
/* Etiqueta e importes comparten la fila mientras quepan; si no, los importes
   bajan a la línea siguiente en vez de salirse de la tarjeta. */
.coste-field {
  display: flex; align-items: center; justify-content: space-between; gap: 10px 16px;
  flex-wrap: wrap;
  padding: 11px 2px; border-bottom: 1px solid var(--border);
}
.coste-fields.two .coste-field { border-bottom: none; padding: 0; flex-direction: column; align-items: stretch; gap: 6px; flex-wrap: nowrap; }
.coste-field:last-child { border-bottom: none; }
.coste-field-label { font-size: 13.5px; color: var(--ink-soft); font-weight: 400; flex: 1 1 180px; min-width: 0; }
/* En columna, `flex-basis` mide ALTO: hay que neutralizarlo o la etiqueta
   reserva 180px de altura y el campo se estira absurdamente. */
.coste-fields.two .coste-field-label { font-size: 13px; color: var(--muted); font-weight: 400; flex: 0 0 auto; }
.coste-fields.two .coste-field-inputs { flex: 0 0 auto; }
.coste-field-inputs { display: flex; align-items: center; gap: 10px; flex: 0 1 auto; min-width: 0; justify-content: flex-end; flex-wrap: wrap; }

/* Grupo de input: campo + sufijo en su propia caja, nunca se solapan
   sin importar cuán largo sea el sufijo (€, km, h/día, L/100km…). */
.money-wrap {
  width: 168px; max-width: 100%;
  display: flex; align-items: stretch;
  border: 1px solid var(--border-strong);
  border-radius: var(--radius-sm);
  background: var(--surface);
  overflow: hidden;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.money-wrap:focus-within { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }
.money-wrap .field-input {
  flex: 1 1 auto;
  min-width: 5ch;              /* garantiza sitio para varias cifras */
  border: none; background: transparent;
  text-align: right; font-variant-numeric: tabular-nums;
  box-shadow: none;
  padding-left: 8px; padding-right: 10px;
}
.money-wrap .field-input:focus { border: none; box-shadow: none; }
/* Campo calculado (p. ej. el tiempo de trayecto): se ve que no se escribe. */
.field-input[readonly] { background: var(--surface-2); color: var(--muted); cursor: default; }
.coste-fields.two .money-wrap { width: 100%; }
.money-suffix {
  flex: 0 0 auto; display: flex; align-items: center;
  padding: 0 10px;
  font-size: 12px; color: var(--muted-2); font-weight: 400;
  white-space: nowrap;
  background: var(--surface-2);
  border-left: 1px solid var(--border);
}
.cada-prefix { font-size: 13px; color: var(--muted); white-space: nowrap; }
/* "narrow" = campo corto (unidades, %, veces). Ancho suficiente para que el
   sufijo nunca recorte las cifras. */
.money-wrap.narrow { width: 136px; }
.coste-field-inputs.cada .money-wrap { width: 156px; }
.soft-row .money-wrap { width: 100%; }

.mini-select {
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm);
  padding: 9px 10px; font-size: 13.5px; color: var(--ink-soft); background: var(--surface);
  font-family: inherit; cursor: pointer; outline: none; min-width: 124px; max-width: 100%;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.mini-select:focus { border-color: var(--accent); box-shadow: 0 0 0 3px var(--ring); }

/* ---- Costes: subtarjetas (software / otros) ----------------------------- */
.coste-subcard { }
.coste-subcard-head { display: flex; align-items: center; justify-content: space-between; margin-bottom: 14px; }
.coste-subcard-head h3, .coste-subcard h3 { margin: 0; font-size: 15px; font-weight: 600; letter-spacing: -0.01em; }
.coste-subcard > h3 { margin-bottom: 14px; }
.btn-sm { padding: 7px 12px; min-height: 34px; font-size: 13px; }
.soft-list { display: flex; flex-direction: column; gap: 10px; }
.soft-empty { font-size: 13px; color: var(--muted-2); padding: 6px 2px; }

/* ---- Servicios ofertados (pantalla de honorarios) -----------------------
   Etiquetas, no una columna de campos: lo que se oferta se lee de golpe y solo
   hay un sitio donde escribir. Antes era un desplegable cerrado que casi nadie
   abría, porque nada invitaba a hacerlo. */
.serv-cab { display: flex; align-items: center; gap: 12px; margin-bottom: 16px; }
.serv-ic {
  display: inline-grid; place-items: center; width: 34px; height: 34px; flex: none;
  border-radius: var(--radius-sm); background: var(--brand-softer); color: var(--brand);
}
.serv-ic .icon { width: 17px; height: 17px; }
.serv-cab-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.serv-cab-txt .card-title { margin-bottom: 0; }
.serv-cab-txt .card-note { margin: 0; }

.serv-chips { display: flex; flex-wrap: wrap; gap: 8px; }
.serv-chips:empty { display: none; }
.serv-chips:not(:empty) { margin-bottom: 14px; }
/* Mismo aspecto que las etiquetas de la ficha de obra y del PDF: lo que se ve
   aquí al editarlo es lo que va a salir impreso. */
.serv-chip {
  display: inline-flex; align-items: center; gap: 2px;
  font-size: 13px; font-weight: 600; color: var(--brand-ink);
  background: var(--brand-softer); border: 1px solid var(--brand-soft);
  border-radius: 100px; padding: 6px 6px 6px 14px; max-width: 100%;
}
.serv-chip-txt { min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.serv-chip-x {
  flex: none; display: grid; place-items: center; width: 24px; height: 24px;
  border: 0; border-radius: 100px; background: transparent; color: var(--brand);
  cursor: pointer; opacity: 0.55; transition: opacity 0.15s, background 0.15s;
}
.serv-chip-x:hover { opacity: 1; background: var(--surface); }
.serv-chip-x .icon { width: 12px; height: 12px; }

.serv-add .combo-input { padding: 11px 12px; }

/* Atajos de un toque a lo que ya está guardado. Es lo que enseña que la lista
   se acuerda de la obra anterior; sin esto habría que abrir el desplegable
   para descubrirlo. */
.serv-sug { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.serv-sug:empty { display: none; }
.serv-sug:not(:empty) { margin-top: 14px; }
.serv-sug-tit {
  font-size: 11.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.06em; color: var(--muted-2); margin-right: 2px;
}
.serv-sug-btn {
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: 13px; color: var(--ink-soft);
  background: var(--surface); border: 1px dashed var(--border-strong);
  border-radius: 100px; padding: 6px 13px 6px 10px; cursor: pointer;
  transition: border-color 0.15s, color 0.15s, background 0.15s;
}
.serv-sug-btn:hover { border-style: solid; border-color: var(--brand); color: var(--brand-ink); background: var(--brand-softer); }
.serv-sug-btn .icon { width: 13px; height: 13px; color: var(--muted-2); }
.serv-sug-btn:hover .icon { color: var(--brand); }
.serv-sug-mas { font-size: 12.5px; color: var(--muted-2); }

.serv-add-btn {
  display: flex; align-items: center; justify-content: center;
  width: 100%; padding: 11px; border: 1px dashed var(--border-strong); border-radius: var(--radius-sm);
  background: transparent; color: var(--muted); cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.serv-add-btn:hover { background: var(--surface-2); color: var(--accent); border-color: var(--accent); }
.serv-add-btn .icon { width: 17px; height: 17px; }
/* Fila de concepto: tolera 3 o 4 campos y se reajusta sin recortar nada */
.soft-row { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.soft-row > .field-input { flex: 1 1 190px; min-width: 0; padding: 9px 11px; }
.soft-row .money-wrap { flex: 0 0 156px; width: auto; }
.soft-row .money-wrap.narrow { flex: 0 0 130px; width: auto; }
.soft-row .mini-select { flex: 0 0 auto; min-width: 128px; }
.soft-row .icon-btn { flex: none; margin-left: auto; }

/* ---- Costes: panel de resultado en vivo --------------------------------- */
.live-result {
  background: var(--brand); color: #fff;
  border-radius: var(--radius); padding: 24px 24px 20px;
  position: relative; overflow: hidden;
}
.live-label { font-size: 12px; color: rgba(255,255,255,0.88); text-transform: uppercase; letter-spacing: 0.06em; font-weight: 600; position: relative; }
.live-value { font-size: 40px; font-weight: 600; letter-spacing: -0.03em; margin: 8px 0 4px; line-height: 1; position: relative; }
.live-subs { display: flex; flex-direction: column; gap: 4px; margin-top: 12px; position: relative; }
.live-sub { font-size: 13px; color: rgba(255,255,255,0.85); font-variant-numeric: tabular-nums; }
.live-note { margin: 16px 0 0; font-size: 12px; color: rgba(255,255,255,0.6); line-height: 1.5; position: relative; }
/* Desglose dentro del panel en vivo (honorarios) */
.live-breakdown { margin-top: 14px; display: flex; flex-direction: column; gap: 2px; position: relative; }
.live-bd-row { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 7px 0; border-top: 1px solid rgba(255,255,255,0.16); font-size: 13.5px; }
.live-bd-label { color: rgba(255,255,255,0.85); }
.live-bd-val { color: #fff; font-weight: 600; font-variant-numeric: tabular-nums; }
.live-warn { margin: 14px 0 0; font-size: 12px; color: #fff; background: rgba(0,0,0,0.18); border-radius: 8px; padding: 8px 10px; line-height: 1.45; position: relative; }

/* ---- Honorarios: campo calculado (solo lectura) -------------------------- */
.field-input[readonly] { background: var(--surface-2); color: var(--ink-soft); cursor: default; }
.field-input[readonly]:focus { border-color: var(--border-strong); box-shadow: none; }

/* ---- Honorarios: aviso de costes sin configurar ------------------------- */
.aviso-costes {
  display: flex; gap: 13px; align-items: flex-start;
  background: var(--warn-bg); border: 1px solid var(--warn-bd); border-radius: var(--radius);
  padding: 16px 18px; margin-bottom: 20px;
}
.aviso-costes > .icon { width: 20px; height: 20px; color: var(--warn); flex: none; margin-top: 1px; }
.aviso-costes strong { font-weight: 600; color: var(--warn-ink); font-size: 14.5px; }
.aviso-costes p { margin: 3px 0 0; font-size: 13px; color: var(--warn-ink); line-height: 1.5; }
.aviso-actions { display: flex; gap: 10px; margin-top: 12px; flex-wrap: wrap; }

/* ---- Honorarios: tarjeta en el detalle de obra ------------------------- */
.hon-card {
  background: var(--brand-softer);
  border-color: #f4e0d4;
  padding: 24px 26px;
}
/* Cabecera: chip + título + botón editar */
.hon-card-header { display: flex; align-items: center; gap: 13px; padding-bottom: 20px; border-bottom: 1px solid var(--border); }
.hon-chip {
  display: inline-grid; place-items: center; width: 40px; height: 40px; flex: none;
  border-radius: var(--radius-sm); background: var(--brand); color: #fff;
}
.hon-chip .icon { width: 20px; height: 20px; }
.hon-card-heading { flex: 1; min-width: 0; }
.hon-title { margin: 0; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; color: var(--ink); }
.hon-subtitle { font-size: 12.5px; color: var(--muted); }
.hon-edit-btn { flex: none; }

/* Zona hero: dos casillas gemelas (calculados azul · propuestos verde) */
/* auto-fit en vez de un nº de columnas fijo: con dos figuras se reparten a
   mitades y con tres (al añadirse el plazo) se ajustan solas, en cualquier
   ancho, sin necesitar una regla de breakpoint por cada caso. */
.hon-hero { display: grid; grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); gap: 16px; padding: 22px 0; align-items: stretch; }
.hon-figure {
  display: flex; flex-direction: column; gap: 12px; justify-content: center;
  padding: 18px 20px; border-radius: var(--radius-sm);
  border: 1px solid var(--fig-bd); background: var(--fig-bg);
  transition: box-shadow 0.15s, border-color 0.15s;
}
.hon-figure-calc { --fig-ink: var(--brand-ink); --fig-bg: #fef7f3; --fig-bd: #f4e0d4; --fig-soft: var(--brand-soft); --fig: 236,134,86; }
.hon-figure-prop { --fig-ink: #40593f; --fig-bg: #f2f6f2; --fig-bd: #d5e2d6; --fig-soft: #e9f0ea; --fig: 95,122,99; }
/* Neutra a propósito: es un dato informativo, no una cifra calculada — no
   debe competir visualmente con calculados/propuestos. */
.hon-figure-plazo { --fig-ink: var(--ink-soft); --fig-bg: var(--surface-2); --fig-bd: var(--border); }
.hon-figure-plazo .hon-figure-value { font-size: 19px; line-height: 1.3; }
.hon-figure-plazo .hon-figure-value.placeholder { color: var(--muted-2); font-weight: 600; }
.hon-figure-prop.editing { border-color: var(--c-green); box-shadow: 0 0 0 3px rgba(95, 122, 99, 0.18); }
.hon-figure.clickable { cursor: pointer; }
.hon-figure.clickable:hover { border-color: var(--c-green); box-shadow: 0 6px 18px rgba(95, 122, 99, 0.18); }
.hon-figure.clickable:focus-visible { outline: none; border-color: var(--c-green); box-shadow: 0 0 0 3px rgba(95, 122, 99, 0.18); }
.hon-figure-label { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--fig-ink); }
.hon-figure-prop .hon-figure-label { display: flex; align-items: center; justify-content: space-between; gap: 8px; }
.hon-edit-hint { display: inline-flex; align-items: center; gap: 4px; font-size: 11px; font-weight: 600; color: var(--c-green); text-transform: none; letter-spacing: 0; opacity: 0.75; transition: opacity 0.15s; }
.hon-edit-hint .icon { width: 12px; height: 12px; }
.hon-figure.clickable:hover .hon-edit-hint { opacity: 1; }
.hon-figure-value.placeholder { color: rgba(95, 122, 99, 0.55); font-weight: 600; }
.hon-figure-value { font-size: 33px; font-weight: 600; letter-spacing: -0.035em; color: var(--fig-ink); line-height: 1; font-variant-numeric: tabular-nums; display: flex; align-items: baseline; gap: 6px; }
.hon-cur { font-size: 20px; font-weight: 600; color: var(--fig-ink); }
.hon-big-input {
  flex: 1; min-width: 0; border: none; background: transparent; padding: 0; margin: 0; outline: none;
  font-family: inherit; font-size: 33px; font-weight: 600; letter-spacing: -0.035em; line-height: 1;
  color: var(--fig-ink); font-variant-numeric: tabular-nums;
}
.hon-big-input::placeholder { color: rgba(95, 122, 99, 0.4); }
.hon-figure-pill {
  align-self: flex-start; display: inline-flex; align-items: baseline; gap: 5px;
  padding: 4px 12px; border-radius: 6px;
  background: var(--fig-soft); color: var(--fig-ink);
  font-size: 14px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.hon-figure-pill.muted { background: var(--surface-2); color: var(--muted); font-weight: 400; font-size: 12px; }
.hon-figure-pill.editable { padding-top: 3px; padding-bottom: 3px; }
.hon-pill-input {
  width: 46px; border: none; background: transparent; padding: 0; margin: 0; outline: none;
  font-family: inherit; font-size: 14px; font-weight: 600; color: var(--fig-ink); text-align: right;
  font-variant-numeric: tabular-nums;
}
.hon-pill-input::placeholder { color: rgba(95, 122, 99, 0.4); }
.hon-pill-unit { font-size: 11px; font-weight: 600; opacity: 0.78; text-transform: uppercase; letter-spacing: 0.04em; }
.hon-hero-note { display: flex; align-items: center; gap: 7px; margin: -8px 0 4px; font-size: 12.5px; color: var(--warn-ink); }
.hon-hero-note .icon { width: 15px; height: 15px; flex: none; }

/* Composición del cálculo: barra apilada + leyenda */
.hon-composition { padding-top: 20px; border-top: 1px solid var(--border); }
.hon-comp-title { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted); }
.hon-bar { display: flex; height: 12px; border-radius: 100px; overflow: hidden; margin: 12px 0 16px; background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border); }
.hon-bar-seg { height: 100%; min-width: 2px; }
.hon-bar-seg:not(:last-child) { border-right: 2px solid var(--surface); }
.hon-bar-empty { width: 100%; }
.hon-legend { display: flex; flex-wrap: wrap; gap: 8px 20px; min-width: 0; }
.hon-legend-item { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; }
.hon-legend-dot { width: 10px; height: 10px; border-radius: 4px; flex: none; }
.hon-legend-label { color: var(--ink-soft); }
.hon-legend-val { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }

/* Servicios ofertados: remarcados, mismo acento de marca que en el PDF. */
.hon-servicios { margin-top: 20px; padding: 14px 16px; background: var(--brand-softer); border-radius: var(--radius-sm); }
.hon-servicios-title { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--brand-ink); }
.hon-servicios-list { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 10px; }
.hon-servicio-chip {
  font-size: 13px; font-weight: 600; color: var(--brand-ink);
  background: var(--surface); border: 1px solid var(--brand-soft); border-radius: 100px;
  padding: 6px 14px;
}

.hon-warn { display: flex; align-items: center; gap: 7px; margin: 18px 0 0; font-size: 12.5px; color: var(--warn-ink); }
.hon-warn .icon { width: 15px; height: 15px; flex: none; }

/* ---- Cashflow de una obra ------------------------------------------------
   Al final de la ficha de cada obra aprobada. Arriba a la izquierda, lo
   previsto y lo que queda por planificar; debajo, un mes por columna. */
.cf-cab { display: flex; align-items: center; gap: 12px; margin-bottom: 18px; }
.cf-ic {
  display: inline-grid; place-items: center; width: 36px; height: 36px; flex: none;
  border-radius: var(--radius-sm); background: var(--brand-softer); color: var(--brand);
}
.cf-ic .icon { width: 18px; height: 18px; }
.cf-cab-txt { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cf-cab-txt .card-title { margin: 0; }
.cf-cab-txt .card-note { margin: 0; }

/* Las dos cifras, a la izquierda y grandes: es lo que se mira mientras se
   reparte, y cambian con cada tecla. */
.cf-resumen { margin-bottom: 18px; max-width: 520px; }
.cf-cifras { display: flex; flex-wrap: wrap; gap: 10px 36px; }
.cf-cifra { display: flex; flex-direction: column; gap: 3px; }
.cf-cifra-lbl {
  font-size: 11.5px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}
.cf-cifra-val {
  font-size: 26px; font-weight: 600; letter-spacing: -0.02em;
  color: var(--ink); font-variant-numeric: tabular-nums;
}
.cf-cifra:first-child .cf-cifra-val { color: var(--brand-ink); }
/* Planificado de más: se ve, sin gritar */
.cf-cifra.de-mas .cf-cifra-lbl, .cf-cifra.de-mas .cf-cifra-val { color: var(--warn-ink); }

.cf-barra {
  height: 6px; margin-top: 14px; border-radius: 100px;
  background: var(--surface-2); border: 1px solid var(--border); overflow: hidden;
}
.cf-barra-seg { display: block; height: 100%; width: 0; background: var(--brand); transition: width 0.18s ease; }
.cf-barra-seg.completo { background: var(--c-green); }
.cf-nota { margin: 8px 0 0; font-size: 12.5px; color: var(--muted); line-height: 1.45; }
.cf-aviso {
  margin: 10px 0 0; padding: 9px 12px; font-size: 12.5px; line-height: 1.45;
  color: var(--warn-ink); background: var(--warn-bg); border-radius: var(--radius-sm);
}

/* El primer mes: el de aprobación, a la vista y corregible. */
.cf-inicio { margin-bottom: 14px; }
.cf-inicio-fila { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cf-inicio-lbl { font-size: 12.5px; font-weight: 600; color: var(--muted); margin-right: 2px; }
.cf-sel { min-width: 0; padding: 7px 10px; font-weight: 600; color: var(--ink); }
.cf-inicio-nota {
  display: flex; align-items: flex-start; gap: 8px; max-width: 520px;
  margin: 10px 0 0; padding: 9px 12px; font-size: 12.5px; line-height: 1.45;
  color: var(--warn-ink); background: var(--warn-bg); border-radius: var(--radius-sm);
}
.cf-inicio-nota .icon { flex: none; width: 14px; height: 14px; margin-top: 2px; }

/* La tabla. Se desplaza de lado dentro de la tarjeta, nunca la página. */
/* El contenedor que se desplaza NO puede ser más ancho que su tabla.
 *
 * Con un ancho fijo del 100%, cuando la tabla es más estrecha queda un trozo
 * de contenedor vacío a la derecha por el que además se puede desplazar: una
 * franja en blanco sin nada dentro. Con `fit-content` el contenedor se ajusta
 * a la tabla, y `max-width: 100%` lo frena en el ancho de la tarjeta para que,
 * cuando la tabla sea larga, siga habiendo desplazamiento lateral.
 *
 * `margin-inline: auto` es lo que lo deja centrado cuando sobra sitio. */
.cf-scroll {
  overflow-x: auto;
  width: fit-content; max-width: 100%;
  margin: 0 auto; padding: 0 2px 6px;
  -webkit-overflow-scrolling: touch;
}
/* La tabla ocupa lo que ocupan sus meses y se CENTRA en el hueco.
 *
 * Antes llevaba `min-width: 100%`, que la estiraba hasta el ancho de la
 * tarjeta: con pocos meses las columnas llenaban 712 de 852px y los 140px
 * restantes quedaban en blanco dentro del recuadro, todo pegado a la
 * izquierda. Con `max-content` a secas el recuadro termina donde termina el
 * último mes, y `margin-inline: auto` reparte lo que sobre a los dos lados.
 *
 * Cuando los meses NO caben, `max-content` supera el hueco, el margen
 * automático se queda en cero y la tabla se desplaza de lado como siempre. */
.cf-tabla {
  display: flex; width: max-content; margin-inline: auto;
  border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden;
}
/* Ancho fijo, ni crece ni encoge: todos los meses miden lo mismo, que es lo
   que deja comparar una columna con otra de un vistazo. El hueco que sobre lo
   reparte la tabla centrándose (ver `.cf-tabla`), no estirando las casillas.

   El `max-width` NO es redundante con el `flex-basis`, y es justo lo que
   arreglaba el desplazamiento hacia la nada:

   `.cf-tabla` se dimensiona con `max-content`, que suma lo que cada columna
   pediría COMO MUCHO —«Septiembre 2026» y su casilla piden unos 195px—, no lo
   que de verdad va a medir. Las columnas se colocaban a sus 132px, así que
   con 29 meses la tabla se declaraba de 6.728px para 4.144px de columnas:
   2.584px de vacío por dentro, desplazables y sin nada. `max-width` limita
   también lo que cada columna PIDE, y así el ancho declarado coincide con el
   real. */
.cf-col {
  display: flex; flex-direction: column;
  /* `width` además de `flex-basis`: con un ancho explícito lo que cada columna
     PIDE es exactamente 132px en todos los motores. Safari no siempre recorta
     con `max-width` lo que pide un elemento flexible, y la tabla volvía a
     declararse más ancha que sus meses. */
  flex: 0 0 132px; width: 132px; max-width: 132px;
  border-left: 1px solid var(--border);
}
.cf-col:first-child { border-left: none; }
/* El nombre de la obra se queda fijo al desplazarse: con veinticuatro meses,
   al llegar al último ya no se sabe de qué obra era la fila. */
.cf-col-obra {
  /* `max-width` por el mismo motivo que en `.cf-col`: sin él, el nombre largo
     de un encargo haría que esta columna PIDIERA más de los 220px que ocupa, y
     esa diferencia acababa en vacío desplazable al final de la tabla. */
  flex: 0 0 220px; width: 220px; max-width: 220px; position: sticky; left: 0; z-index: 1;
  background: var(--surface); box-shadow: 1px 0 0 var(--border);
}
/* El alto mínimo es el de un mes con su año debajo, y lo llevan TODAS las
   cabeceras, también la de la obra y la de añadir mes, que tienen menos
   dentro. Cada columna es una pieza aparte: si una cabecera mide menos, todo
   lo de debajo en esa columna sube y deja de cuadrar con su fila. */
.cf-celda-cab {
  display: flex; flex-direction: column; justify-content: center; gap: 1px;
  min-height: 58px; padding: 8px 12px;
  background: var(--surface-2); border-bottom: 1px solid var(--border);
}
.cf-cab-lbl {
  font-size: 11px; font-weight: 600; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
/* El mes manda y el año acompaña: se lee «Septiembre», y el año solo hace
   falta mirarlo cuando la fila cruza de diciembre a enero. */
.cf-mes { font-size: 13.5px; font-weight: 600; color: var(--ink); white-space: nowrap; }
.cf-anio { font-size: 11.5px; font-weight: 500; color: var(--muted); font-variant-numeric: tabular-nums; }
.cf-celda { display: flex; align-items: center; min-height: 52px; padding: 0 12px 0 4px; }

/* ---- Meses añadidos a mano, más allá del plazo --------------------------- */
/* Se distinguen en suave: son meses de verdad y se rellenan igual, pero saber
   cuáles pasan del plazo contratado importa al leer la previsión. */
.cf-col-extra .cf-celda-cab { background: var(--brand-softer); }
.cf-col-extra .cf-anio { color: var(--brand-ink); }
/* La cabecera del mes pasa a fila para dejar sitio a la ✕ a la derecha */
.cf-col-extra .cf-celda-cab {
  flex-direction: row; align-items: center; gap: 8px;
}
.cf-col-extra .cf-celda-cab > .cf-mes { flex: 1; min-width: 0; }
.cf-col-extra .cf-celda-cab > .cf-anio { flex: none; }
.cf-mes-quitar {
  flex: none; display: grid; place-items: center;
  width: 26px; height: 26px; margin-left: 2px;
  border: 0; border-radius: 7px; background: transparent;
  color: var(--muted); cursor: pointer;
  transition: background 0.14s, color 0.14s;
}
.cf-mes-quitar:hover { background: var(--danger-bg); color: var(--danger); }
.cf-mes-quitar:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.cf-mes-quitar .icon { width: 14px; height: 14px; }

/* ---- Añadir un mes al final --------------------------------------------- */
.cf-col-mas { flex: 0 0 96px; width: 96px; max-width: 96px; background: var(--surface-2); }
.cf-celda-mas { padding: 0 10px; justify-content: center; }
.cf-mas {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 9px 12px; min-height: 40px;
  border: 1px dashed var(--border-strong); border-radius: var(--radius-sm);
  background: var(--surface); color: var(--brand-ink);
  font-size: 13px; font-weight: 600; cursor: pointer; white-space: nowrap;
  transition: border-color 0.14s, background 0.14s;
}
.cf-mas:hover { border-color: var(--brand); border-style: solid; background: var(--brand-softer); }
.cf-mas:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.cf-mas .icon { width: 14px; height: 14px; }
.cf-mas-tope { font-size: 12px; color: var(--muted-2); }
.cf-celda-obra {
  padding: 0 12px; font-size: 14px; font-weight: 600; color: var(--ink);
  line-height: 1.3; overflow-wrap: anywhere;
}
.cf-input {
  flex: 1; min-width: 0; width: 100%;
  border: 1px solid transparent; border-radius: 6px; background: transparent;
  padding: 9px 8px; font: inherit; font-size: 14px; text-align: right;
  font-variant-numeric: tabular-nums; color: var(--ink);
  transition: border-color 0.12s, background 0.12s, box-shadow 0.12s;
}
.cf-input::placeholder { color: var(--muted-2); }
.cf-input:hover { border-color: var(--border); }
.cf-input:focus { outline: none; border-color: var(--accent); background: var(--surface); box-shadow: 0 0 0 3px var(--ring); }
.cf-eur { flex: none; margin-left: 4px; font-size: 13px; color: var(--muted-2); }

/* En qué estado está la planificación: en naranja suave lo que aún se puede
   tocar (borrador o edición abierta), en gris con candado lo guardado. La
   edición, un punto más marcada: hay cambios que no cuentan hasta guardar. */
.cf-estado {
  display: inline-flex; align-items: center; gap: 6px;
  margin: 0 0 14px; padding: 5px 11px; border-radius: 999px;
  font-size: 12.5px; font-weight: 600; line-height: 1.35;
}
.cf-estado .icon { flex: none; width: 13px; height: 13px; }
.cf-estado.borrador { background: var(--brand-softer); color: var(--brand-ink); }
.cf-estado.editando { background: var(--brand-soft); color: var(--brand-ink); box-shadow: inset 0 0 0 1px var(--brand); }
.cf-estado.fija { background: var(--surface-2); color: var(--muted); }

/* Al editar, el mes que ya no es como estaba guardado: fondo naranja suave y
   una raya a la izquierda, para ver de un vistazo qué se va a cambiar. */
.cf-celda.cambiada { background: var(--brand-softer); box-shadow: inset 3px 0 0 var(--brand); }

/* Un importe guardado: la cifra sin casilla, alineada donde iría la casilla. */
.cf-fijo {
  flex: 1; min-width: 0; padding: 9px 8px; text-align: right;
  font-size: 14px; font-variant-numeric: tabular-nums; color: var(--ink);
}
.cfg-fija .cf-fijo { padding: 0 8px; }

/* ---- Lo facturado en Holded, debajo de lo previsto de cada mes -----------
   Alto FIJO y no mínimo: cada mes es una columna aparte, y la fila solo
   cuadra si todas sus casillas miden lo mismo, también la de la obra, que
   lleva dos líneas (el rótulo y el total). En verde lo que tiene factura:
   es dinero facturado de verdad, no previsto. */
.cf-celda-real {
  display: flex; align-items: center; justify-content: flex-end; gap: 6px;
  height: 46px; padding: 0 12px;
  border-top: 1px solid var(--border); background: var(--surface-2);
  font-size: 13.5px; color: var(--muted-2); font-variant-numeric: tabular-nums; white-space: nowrap;
}
.cf-celda-real.con { background: var(--c-green-bg); color: var(--c-green); font-weight: 600; }
.cf-real-lbl { display: none; }
.cf-celda-real-obra {
  flex-direction: column; align-items: flex-start; justify-content: center; gap: 1px;
}
.cf-real-total { font-size: 13.5px; font-weight: 700; color: var(--c-green); }

.cf-real-zona { display: flex; flex-direction: column; gap: 8px; margin-top: 14px; }
.cf-real-zona:empty { display: none; }
.cf-real-linea { display: flex; align-items: flex-start; gap: 8px; font-size: 13.5px; line-height: 1.45; color: var(--ink-soft); }
.cf-real-linea p { margin: 0; min-width: 0; }
.cf-real-linea strong { color: var(--ink); }
.cf-real-linea .icon { flex: none; width: 15px; height: 15px; margin-top: 2px; color: var(--muted-2); }
.cf-real-linea.file .icon { color: var(--c-green); }
.cf-real-linea.alert .icon { color: var(--warn); }
/* Lo que cuelga de la línea va alineado con su texto, no con el icono. */
.cf-real-nota, .cf-real-btns, .cf-real-lista { margin-left: 23px; }
.cf-real-nota { margin-top: 0; margin-bottom: 0; font-size: 12.5px; line-height: 1.45; color: var(--muted); }
.cf-real-nota.aviso { color: var(--warn-ink); }
.cf-real-btns { display: flex; flex-wrap: wrap; align-items: center; gap: 8px; }
.cf-real-hora { font-size: 12px; color: var(--muted-2); }
.cf-real-lista { max-width: 560px; border: 1px solid var(--border); border-radius: var(--radius-sm); }
.cf-real-fac {
  display: grid; grid-template-columns: 88px minmax(0, 1fr) auto; align-items: center; gap: 12px;
  padding: 9px 12px; border-top: 1px solid var(--border);
  font-size: 13px; font-variant-numeric: tabular-nums;
}
.cf-real-fac:first-child { border-top: none; }
.cf-real-fecha { color: var(--muted); }
.cf-real-num { display: flex; flex-wrap: wrap; align-items: center; gap: 6px; font-weight: 600; color: var(--ink); overflow-wrap: anywhere; }
.cf-real-rect { padding: 1px 7px; border-radius: 999px; background: var(--warn-bg); color: var(--warn-ink); font-size: 11px; font-weight: 600; }
.cf-real-imp { display: flex; flex-direction: column; align-items: flex-end; text-align: right; font-weight: 600; color: var(--ink); white-space: nowrap; }
/* Debajo del total cobrado, su base sin IVA, en pequeño: referencia, no cifra. */
.cf-real-base { font-size: 11.5px; font-weight: 500; color: var(--muted-2); }
.cf-real-fac.rect .cf-real-imp { color: var(--danger); }

.cf-acciones { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; margin-top: 16px; }
.cf-acciones-btns { display: flex; flex-wrap: wrap; gap: 8px; }
.cf-acciones-nota { margin: 0; font-size: 12.5px; color: var(--muted); line-height: 1.45; max-width: 560px; }

/* ---- Ingresos / Gastos ----------------------------------------------------
   Interruptor de dos posiciones a la derecha de la cabecera. En el móvil baja
   a su propia línea, a todo lo ancho y a tamaño de dedo. */
.cf-cab { flex-wrap: wrap; }
.cf-modo {
  display: flex; gap: 3px; margin-left: auto; padding: 3px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: 999px;
}
.cf-modo-op {
  padding: 7px 18px; min-height: 36px; border: 0; border-radius: 999px;
  background: transparent; color: var(--muted);
  font-family: inherit; font-size: 13.5px; font-weight: 600; cursor: pointer;
  transition: background 0.15s, color 0.15s, box-shadow 0.15s;
}
.cf-modo-op:hover { color: var(--ink); }
.cf-modo-op.activo { background: var(--surface); color: var(--ink); box-shadow: var(--shadow-sm); }
.cf-modo-op:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }

/* La tabla de gastos: la rejilla de la tabla de todas las obras, dentro de
   la tarjeta, con su borde y desplazándose de lado a cualquier ancho. */
.cf-gastos-scroll {
  overflow-x: auto; -webkit-overflow-scrolling: touch;
  width: fit-content; max-width: 100%; margin: 0 auto;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.cf-gastos-scroll .cfg-tabla { min-width: 0; }
.cf-gastos-scroll .cfg-obra-nom { -webkit-line-clamp: 2; }
/* Cada gasto: el nombre arriba, a todo el ancho; debajo, su total y la
   papelera para quitarlo de la obra. */
.cfgg-concepto-pie { display: flex; align-items: center; gap: 6px; align-self: stretch; min-height: 26px; }
.cfgg-quitar { margin-left: auto; }

/* Un gasto general mensual o anual: la periodicidad y, debajo, un importe
   único con su botón para repartirlo en las casillas del mes. Todo apilado
   en vertical porque la columna del nombre es estrecha —136 a 240px según
   la pantalla— y no hay sitio para ponerlo en fila. */
.cfgg-relleno { display: flex; flex-direction: column; gap: 5px; margin: 6px 0; }
.cfgg-periodo { min-width: 0; width: 100%; padding: 6px 8px; font-size: 12.5px; }
.cfgg-relleno-input { min-height: 32px; padding: 5px 8px; font-size: 12.5px; text-align: right; }
.cfgg-relleno-btn { width: 100%; justify-content: center; white-space: normal; text-align: center; line-height: 1.25; }

/* ---- Gastos de todas las obras -------------------------------------------
   En qué se va el dinero: cada concepto con su barra, de más a menos. */
.cfgg-conceptos {
  display: grid; grid-template-columns: minmax(140px, 190px) minmax(80px, 1fr) auto 44px;
  align-items: center; gap: 9px 14px; max-width: 640px; margin-top: 20px;
}
.cfgg-conceptos > .cf-cab-lbl { grid-column: 1 / -1; margin-bottom: 2px; }
.cfgg-concepto { display: contents; }
.cfgg-concepto-nom { font-size: 13.5px; color: var(--ink); }
.cfgg-concepto-barra { height: 8px; border-radius: 999px; background: var(--surface-2); overflow: hidden; }
.cfgg-concepto-barra > span { display: block; height: 100%; border-radius: 999px; background: var(--brand); }
.cfgg-concepto-val { font-size: 13.5px; font-weight: 600; color: var(--ink); text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cfgg-concepto-pct { font-size: 12px; color: var(--muted-2); text-align: right; font-variant-numeric: tabular-nums; }

/* Encima de la tabla: desplegar todas, y dónde se apuntan los gastos. */
.cfgg-barra { display: flex; flex-wrap: wrap; align-items: center; gap: 8px 14px; padding: 0 20px 14px; }
.cfgg-ayuda { font-size: 12.5px; color: var(--muted); }

/* La fila de cada obra manda; sus conceptos, debajo, sangrados y en gris. */
.cfgg-obra-cab { display: flex; align-items: center; gap: 6px; min-width: 0; }
.cfgg-plegar {
  flex: none; display: grid; place-items: center; width: 24px; height: 24px;
  border: 0; border-radius: 6px; background: transparent; color: var(--muted); cursor: pointer;
}
.cfgg-plegar:hover { background: var(--surface-2); color: var(--ink); }
.cfgg-plegar:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }
.cfgg-plegar .icon { width: 15px; height: 15px; transform: rotate(-90deg); transition: transform 0.15s; }
.cfgg-plegar.abierta .icon { transform: none; }
.cfgg-sangria { padding-left: 30px; }
.cfgg-fila-obra .cf-fijo { font-weight: 600; }
/* `.cfg-celda.` delante para ganar a su fondo blanco; el mes en curso, que
   va después con la misma fuerza, conserva el suyo. */
.cfg-celda.cfgg-sub { background: var(--surface-2); min-height: 44px; }
.cfgg-sub-nom { font-size: 12.5px; color: var(--ink); }
.cfgg-sub .cf-fijo { font-size: 13px; color: var(--muted); }
.cfgg-cero { color: var(--muted-2); }
.cfgg-vacio { font-size: 12px; color: var(--muted-2); font-style: italic; }

/* Gastos generales del estudio: un grupo más de la tabla, separado de las obras
   por un filete más marcado encima, con su rótulo debajo del nombre. */
.cfg-celda.cfgg-otros.cfgg-fila-obra { border-top: 2px solid var(--border-strong); }
.cfgg-otros-nota { font-size: 11px; color: var(--muted-2); }
.cfg-celda.cfgg-fila-anadir { min-height: 50px; }
.cfgg-anadir-otro { margin-left: 24px; }

/* Qué planificación de la obra sale en la tabla de todas */
.cfg-obra-pie { flex-wrap: wrap; row-gap: 2px; }
.cfg-plan { font-size: 11px; color: var(--muted-2); white-space: nowrap; font-variant-numeric: tabular-nums; }
.cfg-plan.borrador { color: var(--brand-ink); font-weight: 600; }

/* --- Cashflow de TODAS las obras (pantalla propia) -------------------------
   Una rejilla: las obras en filas, los meses del calendario en columnas y los
   totales abajo. La columna de la obra se queda fija al desplazarse de lado,
   porque con veinte meses el nombre se pierde por la izquierda. */
/* Sin `overflow: hidden` aquí a propósito: un `position: sticky` dentro de un
   antepasado con overflow no-visible se ancla a ESE antepasado en vez de a
   la ventana, y entonces el `top` del bloque fijo del gráfico (ver
   `.cfgg-sticky-top`) ya no significa «tantos píxeles desde arriba de la
   pantalla». Las esquinas redondeadas que daba este `overflow: hidden` las
   ponen ahora las dos piezas por separado: el bloque del gráfico redondea
   las de arriba y `.cfg-card .cf-scroll` las de abajo. */
.cfg-card { padding: 0; overflow: visible; }
.cfg-card .cf-scroll {
  margin: 0; padding: 0;
  overflow-y: hidden; border-radius: 0 0 var(--radius) var(--radius);
}
/* La fila de meses, aparte y dentro del bloque fijo (ver `cabeceraAparte` en
   cashflow.js). Se mueve de lado con la tabla, así que su propia barra de
   desplazamiento sobra: la de la tabla basta. */
.cfg-card .cfg-scroll-cab { border-radius: 0; scrollbar-width: none; }
.cfg-card .cfg-scroll-cab::-webkit-scrollbar { display: none; }
/* La fila de totales, aparte y fija abajo (ver `pieAparte` en cashflow.js).
   La barra de desplazamiento lateral la lleva ELLA, que siempre está a la
   vista; la del cuerpo se esconde, porque estaría al final de la tabla, que
   con muchas obras queda fuera de la pantalla. El cuerpo sigue moviéndose de
   lado con el ratón, el panel táctil o el dedo, y arrastra a las otras dos.
   El cuerpo ya no es lo último de la tarjeta: sin esquinas redondeadas, y
   con su última casilla cerrada por abajo como las demás de su fila. */
.cfg-card .cfg-scroll-cuerpo { border-radius: 0; scrollbar-width: none; }
.cfg-card .cfg-scroll-cuerpo::-webkit-scrollbar { display: none; }
.cfg-scroll-cuerpo .cfg-tabla > .cfg-celda:last-child { border-bottom: 1px solid var(--border); }
/* El filete de arriba como sombra y no como borde: cuando el pie está en su
   sitio cae justo encima del borde de la última fila (no se duplica), y
   cuando flota sobre las obras las separa de ellas. */
.cfg-scroll-pie { background: var(--surface-2); box-shadow: 0 -1px 0 var(--border); }
/* La tarjeta de todas va sin relleno por la tabla; el gráfico sí lo necesita.
   Sin `>`: el gráfico vive dentro de `.cfgg-sticky-top` (ver más abajo), no
   ya como hijo directo de la tarjeta. */
.cfg-card .cfx { margin: 22px 20px 14px 14px; }
/* Esquinas de arriba: antes las redondeaba el `overflow: hidden` de
   `.cfg-card`; ahora las pone este bloque sobre sí mismo, sticky o no —
   en el móvil no es fijo, pero sigue siendo lo primero que se ve dentro de
   la tarjeta y tiene que quedar igual de redondeado. */
.cfgg-sticky-top {
  background: var(--surface); border-bottom: 1px solid var(--border);
  border-radius: var(--radius) var(--radius) 0 0; overflow: hidden;
}
/* `--cfg-meses` lo pone la pantalla: cuántas columnas de mes hay. Va por
   variable y no por estilo en línea para que el móvil pueda estrecharlas. */
.cfg-tabla {
  display: grid; width: max-content; min-width: 100%;
  grid-template-columns: 240px repeat(var(--cfg-meses, 1), 132px);
}
.cfg-celda {
  display: flex; align-items: center; gap: 4px;
  min-height: 56px; padding: 8px 12px 8px 4px;
  border-bottom: 1px solid var(--border); border-left: 1px solid var(--border);
  background: var(--surface);
}
.cfg-obra {
  position: sticky; left: 0; z-index: 2;
  flex-direction: column; align-items: flex-start; justify-content: center; gap: 2px;
  padding: 10px 14px; border-left: none; box-shadow: 1px 0 0 var(--border);
}
.cfg-cab {
  flex-direction: column; align-items: flex-start; justify-content: center; gap: 1px;
  min-height: 48px; padding: 8px 12px; background: var(--surface-2);
  /* En la pantalla de todas las obras esta fila no vive en la tabla sino en
     el bloque fijo del gráfico (`cabeceraAparte` en cashflow.js), que es lo
     que la deja fija al bajar. */
  position: sticky; top: 0; z-index: 3;
}
.cfg-cab.cfg-obra { z-index: 4; }
/* El mes en curso, marcado en suave: es desde donde se lee la previsión. */
.cfg-celda.hoy { background: var(--brand-softer); }
.cfg-cab.hoy { background: var(--brand-soft); }
.cfg-cab.hoy .cf-mes { color: var(--brand-ink); }
.cfg-obra-nom {
  font-size: 13.5px; font-weight: 600; color: var(--ink); text-decoration: none;
  line-height: 1.3; display: -webkit-box; -webkit-line-clamp: 2; -webkit-box-orient: vertical;
  overflow: hidden;
}
.cfg-obra-nom:hover { color: var(--brand-ink); }
.cfg-obra-pie { display: flex; align-items: center; gap: 6px; }
.cfg-obra-cifra { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cfg-obra-cifra > span { white-space: nowrap; }
.cfg-est { display: inline-flex; color: var(--warn-ink); }
.cfg-est .icon { width: 13px; height: 13px; }
/* Meses en los que la obra todavía no existe o ya ha terminado. */
.cfg-fuera { background: var(--surface-2); }
.cfg-total { justify-content: flex-end; padding-right: 12px; background: var(--surface-2); }
.cfg-total-mes { font-size: 13px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.cfg-total-lbl { background: var(--surface-2); font-size: 12px; font-weight: 600; color: var(--muted); }
.cfg-total-val { font-size: 15px; font-weight: 700; color: var(--brand-ink); font-variant-numeric: tabular-nums; }
/* Debajo del total, de qué año es: sin ello se leería como la cifra de un mes. */
.cfg-total-anio { font-size: 11px; font-weight: 500; color: var(--muted-2); }
.cfg-tabla > .cfg-celda:last-child, .cfg-total { border-bottom: none; }

/* ---- Cabecera fija al desplazar (pantalla de todas las obras) -----------
 * El filtro de años y el bloque del gráfico (con, en gastos, el botón «Ver
 * los conceptos de todas», y debajo la fila de meses de la tabla) se quedan
 * a la vista mientras se recorre la tabla, y abajo, la fila de totales.
 *
 * Solo desde tablet: en el móvil esto se comería la pantalla entera y no
 * dejaría ver ni una fila de la tabla, así que ahí se desplaza todo normal
 * y `--cf-alto-filtro` ni se calcula por debajo de este ancho
 * (`fijadorCabecera()` en cashflow.js). */
@media (min-width: 761px) {
  .cf-filtro-fijo {
    position: sticky; top: 0; z-index: 12;
    background: var(--bg); padding-top: 2px;
  }
  .cfgg-sticky-top { position: sticky; top: var(--cf-alto-filtro, 0px); z-index: 11; }
  .cfg-scroll-pie { position: sticky; bottom: 0; z-index: 11; }
}

.cfg-sinplazo { margin-top: 18px; }
.cfg-sinplazo .card-note { margin: 4px 0 14px; }
.cfg-sinplazo-lista { display: flex; flex-direction: column; gap: 8px; }
.cfg-sinplazo-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 12px 14px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  font-size: 13.5px; font-weight: 600; color: var(--ink); text-decoration: none;
  transition: border-color 0.15s, background 0.15s;
}
.cfg-sinplazo-item:hover { border-color: var(--border-strong); background: var(--surface-2); }
.cfg-sinplazo-cta { display: inline-flex; align-items: center; gap: 4px; flex: none; font-size: 12.5px; font-weight: 600; color: var(--brand-ink); }
.cfg-sinplazo-cta .icon { width: 13px; height: 13px; }

.cf-vacio { display: flex; flex-direction: column; align-items: flex-start; gap: 14px; }
.cf-vacio p { margin: 0; color: var(--muted); font-size: 14px; line-height: 1.5; }

.hon-cta { display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap; background: var(--brand-softer); border-color: #f4e0d4; }
.hon-cta-title { font-size: 16px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em; }
.hon-cta-text p { margin: 4px 0 0; font-size: 13.5px; color: var(--muted); }

/* ---- Costes: hero de resultado (resumen) -------------------------------- */
.hero-card { padding: 26px 28px; }
.hero-top { display: flex; align-items: flex-start; justify-content: space-between; margin-bottom: 6px; }
.hero-icon {
  width: 46px; height: 46px; border-radius: var(--radius-sm);
  background: var(--brand); color: #fff; display: grid; place-items: center;
}
.hero-icon .icon { width: 22px; height: 22px; }
.hero-actions { display: flex; gap: 8px; }
.hero-label { font-size: 13px; color: var(--muted); font-weight: 400; margin-top: 8px; }
.hero-value { font-size: 44px; font-weight: 600; letter-spacing: -0.03em; color: var(--ink); line-height: 1.05; margin: 2px 0; }
.hero-sub { font-size: 14px; color: var(--muted); }
.hero-breakdown { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 22px; padding-top: 20px; border-top: 1px solid var(--border); }
.hero-metric {
  display: flex; flex-direction: column; gap: 3px; flex: 1; min-width: 150px;
  padding: 12px 14px; background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.hero-metric-label { font-size: 12px; color: var(--muted); font-weight: 400; }
.hero-metric-value { font-size: 18px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em; font-variant-numeric: tabular-nums; }
.hero-review {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 18px;
  font-size: 12.5px; color: var(--muted); font-weight: 400;
}
.hero-review .icon { width: 14px; height: 14px; }
.hero-review.due { color: var(--warn-ink); }

/* ---- Costes: desglose (resumen) ----------------------------------------- */
.resumen-list { display: flex; flex-direction: column; }
.resumen-row {
  display: grid; grid-template-columns: minmax(0, 1fr) auto minmax(0, 120px); gap: 14px; align-items: center;
  padding: 11px 2px; border-bottom: 1px solid var(--border);
}
.resumen-row:last-child { border-bottom: none; }
.resumen-label { font-size: 13.5px; color: var(--ink-soft); }
.resumen-pagos { font-size: 12px; color: var(--muted-2); font-variant-numeric: tabular-nums; }
.resumen-val { font-size: 14px; color: var(--ink); font-weight: 600; text-align: right; font-variant-numeric: tabular-nums; }
.resumen-hours { background: var(--surface-2); border-radius: 8px; padding-left: 10px; padding-right: 10px; margin-top: 6px; }

.sticky-actions { margin-top: 22px; }

/* ---- Notificaciones ------------------------------------------------------ */
.notif-list { display: flex; flex-direction: column; gap: 12px; }
.notif-card {
  display: flex; gap: 14px; align-items: flex-start;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 18px 20px; box-shadow: var(--shadow-sm);
}
.notif-card.unread { border-color: var(--border-strong); }
.notif-ic { width: 38px; height: 38px; border-radius: var(--radius-sm); display: grid; place-items: center; flex: none; }
.notif-ic .icon { width: 19px; height: 19px; }
.notif-ic.info { background: var(--data-soft); color: var(--data); }
.notif-ic.warn { background: var(--warn-bg); color: var(--warn); }
.notif-body { flex: 1; min-width: 0; }
.notif-title { font-size: 15px; font-weight: 600; color: var(--ink); display: flex; align-items: center; gap: 8px; }
.notif-dot { width: 7px; height: 7px; border-radius: 50%; background: var(--data); flex: none; }
.notif-msg { font-size: 13.5px; color: var(--ink-soft); margin-top: 3px; line-height: 1.5; }
.notif-meta { font-size: 12px; color: var(--muted-2); margin-top: 7px; }
.notif-actions { display: flex; align-items: center; gap: 8px; flex: none; }

.notif-modal { max-width: 440px; text-align: left; }
.notif-modal-ic { width: 46px; height: 46px; border-radius: 12px; display: grid; place-items: center; margin-bottom: 16px; }
.notif-modal-ic .icon { width: 23px; height: 23px; }
.notif-modal-ic.info { background: var(--data-soft); color: var(--data); }
.notif-modal-ic.warn { background: var(--warn-bg); color: var(--warn); }
.notif-modal-more { margin: -10px 0 20px; font-size: 12.5px; color: var(--muted); }

/* Aviso de obras renumeradas al fusionar dos dispositivos */
.renum-lista { display: flex; flex-direction: column; gap: 8px; margin: 4px 0 20px; text-align: left; }
.renum-item {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 10px 13px; border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface-2);
}
.renum-nombre { font-size: 13.5px; color: var(--ink); min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.renum-cambio {
  display: inline-flex; align-items: center; gap: 5px; flex: none;
  font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.renum-cambio .icon { width: 13px; height: 13px; transform: rotate(-90deg); }
.renum-cambio strong { color: var(--ink); font-weight: 700; }

/* ============================================================================
 * CONTROL DE CERTIFICACIONES
 * Entran las obras en ejecución. El presupuesto se reparte en capítulos
 * numerados; cada uno tiene su acento de color, que se repite en la barra de
 * reparto, en la fila y en su porcentaje: el mismo dato, siempre del mismo
 * color, para leerlo de un vistazo también en obra.
 * ==========================================================================*/

/* ---- Listado de obras en ejecución -------------------------------------- */
/* ---- Selector entre las pantallas de una sección -------------------------- *
 * En el móvil es la única forma de pasar de Certificaciones a Documentación
 * (la barra inferior no despliega submenús), así que se deja a la vista en
 * todos los tamaños y con altura de dedo. Rueda de lado si no cabe, en vez de
 * partirse en dos filas.
 * -------------------------------------------------------------------------- */
.tabs-seccion {
  display: flex; gap: 4px;
  margin: -4px 0 18px;
  padding: 4px;
  background: var(--surface-2);
  border-radius: var(--radius);
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  scrollbar-width: none;
}
.tabs-seccion::-webkit-scrollbar { display: none; }
.tab-seccion {
  flex: none;
  padding: 9px 16px; min-height: 40px;
  display: inline-flex; align-items: center;
  border-radius: calc(var(--radius) - 5px);
  color: var(--muted); font-size: 14px; white-space: nowrap;
  transition: background 0.15s, color 0.15s, box-shadow 0.15s;
}
.tab-seccion:hover { color: var(--ink); }
.tab-seccion.active {
  background: var(--surface); color: var(--ink);
  font-weight: 600; box-shadow: var(--shadow-sm);
}

/* ---- Documentación de obras: lista de comprobación por fases ------------- */
.doc-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 14px; }
.doc-card {
  display: flex; flex-direction: column; gap: 10px; text-align: left;
  padding: 16px; border: 1px solid var(--border);
  border-radius: var(--radius); background: var(--surface);
  cursor: pointer; transition: border-color 0.15s, box-shadow 0.15s;
}
.doc-card:hover { border-color: var(--border-strong); box-shadow: var(--shadow-sm); }
.doc-card-top { display: flex; align-items: center; gap: 12px; }
.doc-card-ic {
  flex: none; display: grid; place-items: center;
  width: 36px; height: 36px; border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--muted-2);
}
.doc-card-ic .icon { width: 18px; height: 18px; }
.doc-card-txt { flex: 1; min-width: 0; }
.doc-card-title {
  display: block; font-size: 14px; font-weight: 600; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.doc-card-chev { width: 16px; height: 16px; color: var(--muted-2); flex: none; }
.doc-card-datos { display: flex; align-items: baseline; justify-content: space-between; }
.doc-card-cifra { font-size: 13px; color: var(--muted); font-variant-numeric: tabular-nums; }
.doc-card-pct { font-size: 15px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.doc-card-pie { display: flex; align-items: center; gap: 6px; font-size: 12.5px; color: var(--muted-2); }
.doc-card-pie.ok { color: var(--c-green); }
.doc-mini-bar { height: 5px; border-radius: 3px; background: var(--surface-2); overflow: hidden; }
.doc-mini-seg { display: block; height: 100%; background: var(--brand); border-radius: 3px; transition: width 0.3s ease; }

/* --- Resumen de la obra --- */
.doc-resumen { display: flex; flex-direction: column; gap: 10px; margin-bottom: 16px; }
.doc-resumen-top { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.doc-resumen-lbl { font-size: 13px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; }
.doc-resumen-val { font-size: 15px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.doc-resumen-pie { display: flex; align-items: center; gap: 6px; font-size: 13px; color: var(--muted); }
.doc-resumen-pie.ok { color: var(--c-green); font-weight: 600; }
.doc-barra { height: 8px; border-radius: 4px; background: var(--surface-2); overflow: hidden; }
.doc-barra.fina { height: 5px; border-radius: 3px; margin-bottom: 4px; }
.doc-barra-seg {
  display: block; height: 100%; background: var(--brand); border-radius: 4px;
  transition: width 0.3s cubic-bezier(0.4, 0, 0.2, 1);
}

/* --- Una fase --- */
.doc-fase { display: flex; flex-direction: column; gap: 10px; margin-bottom: 14px; }
.doc-fase.completa .doc-barra-seg { background: var(--c-green); }
/* Bloqueada: se sigue viendo entera —saber qué viene después ayuda a
   prepararlo—, pero apagada y sin poder marcar nada. */
.doc-fase.bloqueada { background: var(--surface-2); border-style: dashed; }
.doc-fase.bloqueada .doc-lista { opacity: 0.55; }

.doc-fase-head { display: flex; align-items: center; gap: 12px; }
.doc-fase-num {
  flex: none; display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 50%;
  background: var(--brand-soft); color: var(--brand-ink);
  font-size: 13px; font-weight: 600;
}
.doc-fase.completa .doc-fase-num { background: var(--c-green-bg); color: var(--c-green); }
.doc-fase.bloqueada .doc-fase-num { background: var(--border); color: var(--muted-2); }
.doc-fase-num .icon { width: 15px; height: 15px; }
.doc-fase-txt { flex: 1; min-width: 0; }
.doc-fase-tit { margin: 0; font-size: 15px; font-weight: 600; color: var(--ink); }
.doc-fase-sub { font-size: 12.5px; color: var(--muted-2); }
.doc-fase-chip {
  flex: none; display: inline-flex; align-items: center; gap: 5px;
  padding: 4px 10px; border-radius: 100px;
  background: var(--surface-2); color: var(--muted);
  font-size: 12px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.doc-fase-chip.ok { background: var(--c-green-bg); color: var(--c-green); }

/* --- Filas de documento --- */
.doc-lista { display: flex; flex-direction: column; gap: 4px; }
.doc-fila-wrap { display: flex; align-items: stretch; gap: 6px; }
/* Botón, no checkbox: hay tres estados (pendiente, hecho, no aplica) y en obra
   se pulsa con el dedo, así que el área útil es la fila entera. */
.doc-fila {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 11px; text-align: left;
  padding: 11px 12px; min-height: 48px;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: transparent; cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.doc-fila:hover:not(:disabled) { background: var(--surface-2); }
.doc-fila:disabled { cursor: default; }
.doc-check {
  flex: none; display: grid; place-items: center;
  width: 22px; height: 22px; border-radius: 6px;
  border: 1.5px solid var(--border-strong); background: var(--surface);
  color: #fff;
  transition: background 0.15s, border-color 0.15s;
}
.doc-check .icon { width: 14px; height: 14px; }
.doc-fila.hecho .doc-check { background: var(--c-green); border-color: var(--c-green); }
.doc-nombre { flex: 1; min-width: 0; font-size: 14px; line-height: 1.4; color: var(--ink); }
.doc-fila.hecho .doc-nombre { color: var(--muted); }
.doc-fila.na .doc-nombre { color: var(--muted-2); text-decoration: line-through; }
.doc-fila.na .doc-check { border-style: dashed; }
.doc-etiqueta-na {
  flex: none; padding: 2px 8px; border-radius: 100px;
  background: var(--surface-2); color: var(--muted-2);
  font-size: 11.5px; font-weight: 600;
}
/* Sin recuadro: es una salida de emergencia para los documentos que no tocan,
   no una acción principal. Con borde, trece de ellos en columna pesaban más
   que la propia lista y competían con las casillas. */
.doc-na-btn {
  flex: none; align-self: center;
  padding: 7px 10px; min-height: 36px;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: transparent; color: var(--muted-2);
  font-size: 12.5px; cursor: pointer; white-space: nowrap;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.doc-na-btn:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
.doc-na-btn.activo { background: var(--surface-2); color: var(--ink); font-weight: 600; }
.doc-na-btn:disabled { cursor: default; opacity: 0.5; }

/* --- Grupo desplegable (el acta con sus LIE) --- */
.doc-grupo-wrap { display: flex; flex-direction: column; }
.doc-grupo { width: 100%; }
/* Cuadrado y no redondo: se ve de un vistazo que no es una casilla que se
   marque a mano, sino el resumen de lo que llevan sus hijos. */
.doc-check-grupo { border-style: dashed; border-radius: 4px; }
.doc-grupo.hecho .doc-check-grupo {
  background: var(--c-green); border-color: var(--c-green); border-style: solid;
}
.doc-grupo-cuenta {
  flex: none; font-size: 12.5px; color: var(--muted-2);
  font-variant-numeric: tabular-nums;
}
.doc-grupo-chev { flex: none; display: grid; place-items: center; width: 20px; height: 20px; color: var(--muted-2); }
.doc-grupo-chev .icon {
  width: 15px; height: 15px;
  transition: transform 0.22s cubic-bezier(0.4, 0, 0.2, 1);
}
.doc-grupo[aria-expanded="false"] .doc-grupo-chev .icon { transform: rotate(-90deg); }

/* Mismo truco de altura que el submenú de la barra lateral: crece lo que
   ocupen los hijos, sin una altura fija que se quede corta al añadir uno. */
.doc-sub {
  display: grid; grid-template-rows: 0fr;
  transition: grid-template-rows 0.24s cubic-bezier(0.4, 0, 0.2, 1);
}
.doc-sub.abierto { grid-template-rows: 1fr; }
.doc-sub-in {
  overflow: hidden; opacity: 0; visibility: hidden;
  transition: opacity 0.15s ease, visibility 0s 0.24s;
}
.doc-sub.abierto .doc-sub-in {
  opacity: 1; visibility: visible;
  transition: opacity 0.2s ease 0.05s, visibility 0s;
}
/* Filete guía: ata las LIE a su acta sin necesidad de más sangría */
.doc-sub-lista {
  display: flex; flex-direction: column; gap: 2px;
  margin: 2px 0 6px 22px; padding-left: 12px;
  border-left: 1px solid var(--border);
}
.doc-sub-lista .doc-nombre { font-size: 13.5px; }

@media (prefers-reduced-motion: reduce) {
  .doc-sub, .doc-sub-in, .doc-grupo-chev .icon { transition-duration: 0.01ms; }
}

/* --- «Otros documentos»: adjuntos, fuera de las fases --- */
/* Sin número de fase y con borde suave: se ve que no es la cuarta fase de la
   lista, sino un cajón aparte que no bloquea ni cuenta para el avance. */
.otros-card { border-style: dashed; }
.otros-cab {
  display: flex; align-items: center; gap: 12px; width: 100%;
  padding: 0; border: 0; background: transparent; cursor: pointer; text-align: left;
}
.otros-ic {
  flex: none; display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: var(--radius-sm);
  background: var(--surface-2); color: var(--muted-2);
}
.otros-ic .icon { width: 16px; height: 16px; }
.otros-txt { flex: 1; min-width: 0; }
.otros-cab[aria-expanded="false"] .doc-grupo-chev .icon { transform: rotate(-90deg); }

.otros-zona {
  display: flex; align-items: center; flex-wrap: wrap; gap: 10px;
  padding: 12px 0 4px;
}
/* El input real se esconde, pero NO con `display:none`: así sigue siendo
   alcanzable con el tabulador a través de su etiqueta. */
.otros-input { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.otros-btn { flex: none; }
.otros-tope { font-size: 12.5px; color: var(--muted-2); }
.otros-estado { flex-basis: 100%; font-size: 13px; }
.otros-cargando { color: var(--muted); }
.otros-error { color: var(--danger); }
.otros-aviso {
  display: flex; align-items: flex-start; gap: 8px;
  padding: 10px 12px; border-radius: var(--radius-sm);
  background: var(--warn-bg); border: 1px solid var(--warn-bd);
  color: var(--warn-ink); font-size: 13px; line-height: 1.5;
}
.otros-vacio { padding: 10px 0 2px; font-size: 13px; color: var(--muted-2); }

.otros-lista { display: flex; flex-direction: column; gap: 4px; margin-top: 8px; }
.otros-fila {
  display: flex; align-items: center; gap: 11px;
  padding: 10px 12px; min-height: 52px;
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  background: var(--surface);
}
.otros-fila-ic {
  flex: none; display: grid; place-items: center;
  width: 30px; height: 30px; border-radius: 6px;
  background: var(--surface-2); color: var(--muted-2);
}
.otros-fila-ic .icon { width: 15px; height: 15px; }
.otros-fila-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.otros-fila-nombre {
  font-size: 14px; color: var(--ink);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.otros-fila-meta { font-size: 12px; color: var(--muted-2); font-variant-numeric: tabular-nums; }
.otros-acciones { flex: none; display: flex; gap: 4px; }
.otros-accion {
  display: grid; place-items: center;
  width: 38px; height: 38px;
  border: 1px solid transparent; border-radius: var(--radius-sm);
  background: transparent; color: var(--muted-2); cursor: pointer;
  transition: background 0.15s, color 0.15s;
}
.otros-accion:hover:not(:disabled) { background: var(--surface-2); color: var(--ink); }
.otros-accion.peligro:hover:not(:disabled) { background: var(--danger-bg); color: var(--danger); }
.otros-accion:disabled { cursor: default; opacity: 0.5; }
.otros-accion .icon { width: 16px; height: 16px; }
/* Varios errores seguidos (una tanda con dos archivos demasiado grandes) se
   leen como una lista, no como un párrafo pegado. */
.otros-estado .otros-error + .otros-error { margin-top: 3px; }

/* ---- Archivos de obra: botón, ventana y selector del alta --------------- */
.archivos-btn { flex: none; gap: 7px; }
/* La cuenta no es un adorno: dice si esta obra tiene papeles sin abrir nada. */
.archivos-btn-num {
  display: inline-grid; place-items: center; min-width: 19px; height: 19px;
  padding: 0 5px; border-radius: 100px;
  background: var(--brand-softer); color: var(--brand);
  font-size: 11.5px; font-weight: 700; font-variant-numeric: tabular-nums;
}
.hon-card-acciones { flex: none; display: flex; align-items: center; gap: 8px; }
.hon-cta-acciones { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* La ventana crece con la lista pero nunca tapa la pantalla entera: con
   treinta archivos, el botón de cerrar tiene que seguir estando a la vista. */
.modal.modal-archivos { max-width: 560px; display: flex; flex-direction: column; max-height: 86vh; }
.modal-archivos-body { flex: 1; min-height: 0; overflow-y: auto; margin: 0 -4px; padding: 0 4px; }
.modal-archivos-sub { margin-bottom: 16px; }
.modal-archivos .otros-zona { padding: 0 0 12px; }
.modal-archivos .modal-actions { flex: none; padding-top: 16px; }
.modal-archivos .doc-barra { margin-top: 4px; }

.archivos-nuevos .otros-zona { padding: 0 0 10px; }

/* --- Cartel de traslado de datos (bloquea la app entera) --- */
/* z-index por encima del 100 de los diálogos normales: mientras se mueven los
   datos no puede quedar NADA por delante con lo que se pueda interactuar. */
.mig-overlay { z-index: 300; cursor: progress; }
.mig-caja {
  max-width: 420px; text-align: center;
  display: flex; flex-direction: column; align-items: center; gap: 12px;
  padding: 28px 26px;
}
.mig-spinner {
  width: 34px; height: 34px; border-radius: 50%;
  border: 3px solid var(--border); border-top-color: var(--brand);
  animation: mig-giro 0.8s linear infinite;
}
@keyframes mig-giro { to { transform: rotate(360deg); } }
.mig-titulo { margin: 0; font-size: 17px; font-weight: 600; color: var(--ink); }
.mig-detalle { margin: 0; font-size: 14px; color: var(--muted); min-height: 20px; }
.mig-barra {
  width: 100%; height: 8px; border-radius: 4px;
  background: var(--surface-2); overflow: hidden;
}
.mig-barra-seg {
  display: block; height: 100%; background: var(--brand); border-radius: 4px;
  transition: width 0.25s ease;
}
.mig-cifra { font-size: 12.5px; color: var(--muted-2); font-variant-numeric: tabular-nums; min-height: 16px; }
.mig-nota { margin: 4px 0 0; font-size: 12.5px; color: var(--muted-2); line-height: 1.5; }
@media (prefers-reduced-motion: reduce) {
  .mig-spinner { animation-duration: 2.4s; }
}

/* En el móvil el botón de «no aplica» baja debajo del nombre: al lado dejaría
   el texto del documento en una columna demasiado estrecha para leerse. */
@media (max-width: 560px) {
  .doc-fila-wrap { flex-direction: column; gap: 0; }
  .doc-na-btn { align-self: flex-start; margin: 0 0 6px 45px; }
  .doc-sub-lista { margin-left: 12px; padding-left: 10px; }
}

.cert-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(268px, 1fr)); gap: 14px; }
.cert-card {
  display: flex; flex-direction: column; gap: 14px;
  text-align: left; font-family: inherit;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius); padding: 18px;
  box-shadow: var(--shadow-sm); cursor: pointer;
  transition: border-color 0.14s, box-shadow 0.14s, transform 0.14s;
}
.cert-card:hover { border-color: var(--stone); box-shadow: var(--shadow-md); transform: translateY(-1px); }
.cert-card-top { display: flex; align-items: center; gap: 12px; }
.cert-card-ic {
  display: inline-grid; place-items: center; width: 38px; height: 38px; flex: none;
  border-radius: var(--radius-sm); background: var(--brand-soft); color: var(--brand-ink);
}
.cert-card-ic .icon { width: 19px; height: 19px; }
.cert-card-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 1px; }
/* Los encargos son largos: dos líneas antes de recortar, en vez de una. */
.cert-card-title {
  font-size: 15px; font-weight: 600; color: var(--ink); line-height: 1.35;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.cert-card-chev { flex: none; color: var(--muted-2); transform: rotate(-90deg); }
.cert-card-datos { display: flex; gap: 22px; flex-wrap: wrap; }
.cert-card-dato { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cert-card-label { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted-2); }
.cert-card-val { font-size: 16px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.cert-mini-bar {
  display: flex; height: 8px; border-radius: 100px; overflow: hidden;
  background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border);
}
.cert-mini-seg { height: 100%; min-width: 2px; }
.cert-mini-seg + .cert-mini-seg { border-left: 2px solid var(--surface); }
.cert-card-pie { display: flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.cert-card-pie .icon { flex: none; }
.cert-card-pie.aviso { color: var(--warn-ink); }

/* ---- Recuadro del total: se calcula solo, sumando los capítulos --------- */
.cert-hero { background: var(--brand-softer); border-color: #f4e0d4; padding: 22px 24px; }
.cert-hero-top { display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap; }
.cert-hero-campo { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.cert-hero-label { display: flex; align-items: center; gap: 8px; font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--brand-ink); }
.cert-hero-pem {
  font-size: 10px; font-weight: 600; letter-spacing: 0.04em; color: var(--brand-ink);
  background: var(--brand-soft); border-radius: 5px; padding: 2px 7px;
}
.cert-hero-valor { font-size: 34px; font-weight: 600; letter-spacing: -0.03em; line-height: 1.2; color: var(--ink); }
.cert-hero-valor.vacio { font-size: 20px; font-weight: 600; color: rgba(95, 122, 99, 0.55); }
.cert-hero-hint { font-size: 12.5px; color: var(--muted); max-width: 42ch; }
.cert-add-btn { flex: none; }
/* Las dos acciones de la obra, juntas a la derecha del total. */
.cert-hero-btns { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; flex: none; }
/* Sobre el crema del recuadro, el botón fantasma necesita fondo propio para
   no leerse como texto suelto. */
.cert-hero-btns .btn-ghost { background: var(--surface); }
.cert-hero-btns .btn-ghost:hover { background: var(--surface-2); }
/* Cuántos precios están en trámite: el aviso que traía la tarjeta que este
   botón sustituye. */
.cert-btn-aviso {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 19px; height: 19px; padding: 0 6px; margin-left: 2px;
  border-radius: 100px; background: var(--c-amber-bg); color: #8a6524;
  font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums;
}

/* Barra de reparto del presupuesto */
.cert-bar {
  display: flex; height: 14px; border-radius: 100px; overflow: hidden;
  background: var(--surface); box-shadow: inset 0 0 0 1px #eccdb9;
  margin-top: 18px;
}
.cert-bar-seg { height: 100%; min-width: 3px; }
.cert-bar-seg:not(:last-child) { border-right: 2px solid var(--brand-softer); }

/* ---- Lista de capítulos -------------------------------------------------- */
.cert-caps-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; }
.cert-caps-title { margin-bottom: 6px; }
.cert-caps-note { margin: 0; }
.cert-caps-cuenta { flex: none; font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cert-caps { display: flex; flex-direction: column; margin-top: 14px; }
.cert-cap {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto;
  align-items: center; gap: 14px;
  padding: 13px 4px; border-top: 1px solid var(--border);
}
.cert-cap:first-child { border-top: none; }
.cert-cap-num {
  display: inline-grid; place-items: center; width: 30px; height: 30px; flex: none;
  border-radius: 8px; background: var(--cap-bg); color: var(--cap);
  font-size: 13.5px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.cert-cap-main { min-width: 0; display: flex; flex-direction: column; gap: 7px; }
.cert-cap-desc {
  font-size: 14.5px; color: var(--ink); line-height: 1.35;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.cert-cap-track { height: 6px; border-radius: 100px; background: var(--surface-2); box-shadow: inset 0 0 0 1px var(--border); overflow: hidden; }
.cert-cap-fill { display: block; height: 100%; background: var(--cap); border-radius: 100px; }
.cert-cap-cifras { display: flex; flex-direction: column; align-items: flex-end; gap: 1px; }
.cert-cap-importe { font-size: 15px; font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums; }
.cert-cap-pct { font-size: 12.5px; font-weight: 600; color: var(--cap); font-variant-numeric: tabular-nums; }
.cert-cap-acciones { display: flex; gap: 6px; }

.cert-caps-empty { display: flex; flex-direction: column; align-items: center; text-align: center; gap: 4px; padding: 26px 16px 22px; }
.cert-caps-empty .empty-icon { margin-bottom: 2px; }
.cert-caps-empty h3 { margin: 4px 0 0; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
.cert-caps-empty p { margin: 0 0 16px; color: var(--muted); font-size: 13.5px; max-width: 44ch; }

.cert-caps-total {
  display: flex; align-items: baseline; gap: 14px; flex-wrap: wrap;
  margin-top: 16px; padding: 13px 16px;
  background: var(--surface-2); border: 1px solid var(--border); border-radius: var(--radius-sm);
}
.cert-ct-label { flex: 1; font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted); }
.cert-ct-val { font-size: 19px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.015em; }
.cert-ct-pct { font-size: 13.5px; font-weight: 600; color: var(--brand-ink); font-variant-numeric: tabular-nums; }

/* ---- Fase 1: aviso de configuración y cierre ---------------------------- */
.cert-fase {
  display: flex; align-items: flex-start; gap: 14px;
  background: var(--warn-bg); border: 1px solid var(--warn-bd);
  border-radius: var(--radius); padding: 16px 18px; margin-bottom: 18px;
}
.cert-fase-paso {
  flex: none; font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em;
  color: #fff; background: var(--warn); border-radius: 6px; padding: 5px 9px; margin-top: 1px;
}
.cert-fase strong { font-size: 14.5px; font-weight: 600; color: var(--warn-ink); }
.cert-fase p { margin: 4px 0 0; font-size: 13px; color: var(--warn-ink); line-height: 1.5; max-width: 78ch; }

.cert-cerrar {
  display: flex; align-items: center; justify-content: space-between; gap: 18px; flex-wrap: wrap;
  margin-top: 18px; padding: 18px 20px;
  background: var(--surface); border: 1px solid var(--border-strong); border-radius: var(--radius);
}
.cert-cerrar strong { font-size: 14.5px; font-weight: 600; }
.cert-cerrar p { margin: 4px 0 0; font-size: 13px; color: var(--muted); line-height: 1.5; max-width: 70ch; }
.cert-cerrar .btn[disabled] { opacity: 0.5; pointer-events: none; }

/* Capítulos ya cerrados: sin acciones, pero misma lectura */
.cert-lock { display: inline-flex; align-items: center; gap: 5px; color: var(--c-green); font-weight: 600; }
.cert-lock .icon { width: 13px; height: 13px; }
.cert-reabrir {
  display: inline-flex; align-items: center; gap: 5px; margin-left: 12px;
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: inherit; font-size: 12.5px; color: var(--muted-2); text-decoration: underline;
}
.cert-reabrir:hover { color: var(--brand-ink); }
.cert-cap-ro { grid-template-columns: auto minmax(0, 1fr) auto; }

/* ---- Fase 2: avance certificado ----------------------------------------- */
.cert-avance { margin-top: 18px; }
.cert-bar-avance { box-shadow: inset 0 0 0 1px #eccdb9; }
.cert-avance-datos { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px; margin-top: 14px; }
.cert-avance-item {
  display: flex; flex-direction: column; gap: 1px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 12px 14px;
}
.cert-avance-label { font-size: 11.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted-2); }
.cert-avance-val { font-size: 19px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.015em; }
.cert-avance-pct { font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }
/* El presupuesto actualizado es la cifra con la que se trabaja de verdad:
   se marca en naranja de marca para separarla del PEM de partida. */
.cert-avance-item.destacado { border-color: #f0d8c9; }
.cert-avance-item.destacado .cert-avance-val { color: var(--brand-ink); }

/* ---- Fase 2: las dos gráficas ------------------------------------------- */
.cert-graficas {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(330px, 1fr));
  gap: 18px; margin-bottom: 18px;
}
.cert-graficas .chart-card { display: flex; flex-direction: column; padding: 20px 22px 22px; }
.cert-graficas .chart-head { align-items: flex-start; }
.cert-graficas .cert-caps-note { margin: 4px 0 0; }
/* Los dos anillos arrancan a la misma altura: centrar el contenido de cada
   tarjeta los dejaba a distinta altura, porque una leyenda tiene más filas. */
.cert-graficas .chart-body { justify-content: flex-start; }

/* ---- Histórico de certificaciones --------------------------------------- */
.cert-hist { display: flex; flex-direction: column; margin-top: 14px; }
.cert-hist-row {
  display: grid; grid-template-columns: auto minmax(0, 1fr) auto auto auto;
  align-items: center; gap: 14px;
  padding: 14px 4px; border-top: 1px solid var(--border);
  cursor: pointer; border-radius: 8px; transition: background 0.12s;
}
.cert-hist-row:first-child { border-top: none; }
.cert-hist-row:hover { background: var(--surface-2); }
.cert-hist-num {
  display: inline-grid; place-items: center; width: 30px; height: 30px; flex: none;
  border-radius: 8px; background: var(--cap-bg, var(--brand-soft)); color: var(--cap, var(--brand-ink));
  font-size: 13.5px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.cert-hist-main { min-width: 0; display: flex; flex-direction: column; gap: 1px; }
.cert-hist-mes { font-size: 14.5px; font-weight: 600; color: var(--ink); }
.cert-hist-meta { font-size: 12.5px; color: var(--muted); }

/* Dos cifras por certificación, cada una con su rótulo encima: lo acumulado
   a origen y lo que avanzó ese mes en concreto (en verde cuando sube). */
.cert-hist-cifras { display: flex; align-items: flex-start; gap: 22px; flex: none; }
.cert-hist-stat { display: flex; flex-direction: column; align-items: flex-end; gap: 2px; min-width: 76px; }
.cert-hist-stat-lbl {
  font-size: 10px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.07em; color: var(--muted-2);
}
.cert-hist-total { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; }
.cert-hist-pct { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cert-hist-delta { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--muted-2); }
.cert-hist-delta-pct { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }
.cert-hist-stat-mes.up .cert-hist-delta,
.cert-hist-stat-mes.up .cert-hist-delta-pct { color: var(--c-green); }
.cert-hist-chev { color: var(--muted-2); transform: rotate(-90deg); flex: none; }

/* ---- Nueva certificación ------------------------------------------------- */
.cert-nc-cab { display: flex; align-items: flex-start; gap: 14px 20px; flex-wrap: wrap; }
.cert-nc-num {
  display: inline-grid; place-items: center; min-width: 52px; height: 44px; flex: none; padding: 0 12px;
  margin-top: 2px; /* alinea ópticamente con la primera línea de los campos */
  border-radius: var(--radius-sm); background: var(--brand); color: #fff;
  font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums;
}
/* Nombre (libre) y mes (fijo) uno junto al otro; en poco ancho, el nombre se
   lleva su propia línea porque es el dato que más espacio necesita. */
.cert-nc-cab-campos { display: flex; align-items: flex-end; gap: 14px 20px; flex: 1 1 320px; flex-wrap: wrap; }
.cert-nc-campo-nombre { flex: 1 1 240px; min-width: 0; }
.cert-mes-select { min-width: 190px; }
.cert-nc-nota { flex: 1 1 100%; margin: 0; font-size: 12.5px; color: var(--muted); max-width: 68ch; }

.cert-nc-tabla { display: flex; flex-direction: column; margin-top: 6px; }
.cert-nc-cabecera, .cert-nc-fila {
  display: grid; grid-template-columns: auto minmax(0, 1fr) minmax(0, 130px) minmax(0, 160px) minmax(0, 140px);
  align-items: center; gap: 14px;
}
.cert-nc-cabecera {
  padding: 0 4px 10px; border-bottom: 1px solid var(--border-strong);
  font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.1em; color: var(--muted-2);
}
.cert-nc-cabecera span:nth-child(3) { text-align: right; }
.cert-nc-fila { padding: 12px 4px; border-bottom: 1px solid var(--border); }
.cert-nc-cap { min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.cert-nc-desc {
  font-size: 14.5px; color: var(--ink); line-height: 1.35;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 2; overflow: hidden;
}
.cert-nc-anterior { font-size: 12px; color: var(--muted-2); }
/* El precio total del capítulo, bien visible: es la referencia del 100 %
   con la que se lee el campo de al lado. */
.cert-nc-pem {
  font-size: 17px; font-weight: 600; color: var(--ink);
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em; text-align: right;
}
.cert-nc-campo { min-width: 0; }
.cert-nc-campo .money-wrap { width: 100%; }
/* Un capítulo nuevo no tiene porcentaje que enlazar (su propio importe ya
   es el 100 %): el campo ocupa el ancho de las dos columnas de entrada, sin
   dejar un hueco vacío donde iría el porcentaje. */
.campo-euros-solo { grid-column: span 2; }
.cert-nc-tag { margin-bottom: 1px; }
/* La etiqueta de cada campo solo se ve en móvil, donde no hay fila de cabecera */
.cert-nc-campo-lbl { display: none; }
.cert-nc-aviso { grid-column: 1 / -1; font-size: 12px; color: var(--danger); font-weight: 600; }
.cert-nc-aviso:empty { display: none; }

.cert-nc-total {
  display: flex; align-items: center; justify-content: space-between; gap: 20px; flex-wrap: wrap;
  margin-top: 18px; padding: 16px 18px;
  background: var(--brand-softer); border: 1px solid #f4e0d4; border-radius: var(--radius-sm);
}
.cert-nc-total-izq { flex: 1 1 240px; min-width: 0; }
.cert-nc-total-izq .cert-bar { margin-top: 10px; }
.cert-nc-total-cifras { display: flex; align-items: baseline; gap: 12px; flex-wrap: wrap; }
.cert-nc-total-val { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; }
.cert-nc-total-pct { font-size: 14px; font-weight: 600; color: var(--brand-ink); font-variant-numeric: tabular-nums; }
.cert-nc-total-lbl { font-size: 11.5px; color: var(--muted); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 600; }
.cert-nc-total-delta { font-size: 15px; font-weight: 600; font-variant-numeric: tabular-nums; color: var(--muted-2); }
.cert-nc-total-delta.up { color: var(--c-green); }
.cert-nc-total-delta.down { color: var(--danger); }

/* ---- Ver una certificación guardada ------------------------------------- */
.cert-ver-mes { flex: none; display: flex; flex-direction: column; gap: 2px; align-items: flex-end; }
.cert-ver-mes-val { font-size: 22px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.02em; color: var(--muted-2); }
.cert-ver-mes-val.up { color: var(--c-green); }
.cert-ver-tabla { display: flex; flex-direction: column; margin-top: 6px; }
.cert-ver-cabecera, .cert-ver-fila {
  display: grid; grid-template-columns: auto minmax(0, 1fr) minmax(0, 100px) minmax(0, 130px) minmax(0, 96px) minmax(0, 130px);
  align-items: center; gap: 12px;
}
.cert-ver-cabecera {
  padding: 0 4px 10px; border-bottom: 1px solid var(--border-strong);
  font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.06em; color: var(--muted-2);
}
.cert-ver-cabecera span { align-self: end; line-height: 1.3; }
.cert-ver-cabecera span:nth-child(n+3) { text-align: right; }
.cert-ver-fila { padding: 12px 4px; border-bottom: 1px solid var(--border); }
.cert-ver-importe, .cert-ver-acum, .cert-ver-pct, .cert-ver-delta {
  text-align: right; font-variant-numeric: tabular-nums; font-size: 13.5px;
}
.cert-ver-importe { color: var(--muted); }
.cert-ver-acum { font-weight: 600; }
.cert-ver-pct { font-weight: 600; color: var(--cap); }
.cert-ver-delta { color: var(--muted-2); font-weight: 600; }
.cert-ver-delta.up { color: var(--c-green); }

/* Fila de totales: mismas columnas que la tabla, resaltada como resumen */
.cert-ver-fila.cert-ver-total {
  margin-top: 6px; padding: 14px 12px; border-bottom: none;
  background: var(--brand-softer); border: 1px solid #f4e0d4; border-radius: var(--radius-sm);
}
.cert-ver-total .cert-cap-num { background: #fff; color: var(--c-green); }
.cert-ver-total-label { font-size: 11.5px; font-weight: 700; text-transform: uppercase; letter-spacing: 0.09em; color: var(--muted); }
.cert-ver-total .cert-ver-importe { font-weight: 600; }
.cert-ver-total .cert-ver-acum { font-size: 18px; font-weight: 700; color: var(--ink); letter-spacing: -0.01em; }
.cert-ver-total .cert-ver-pct { color: var(--brand-ink); }

/* ---- Modal de capítulo --------------------------------------------------- */
.modal.modal-capitulo { max-width: 470px; }
/* Al añadir capítulos el modal se queda abierto y suma un recordatorio de lo
   ya guardado: necesita algo más de ancho que el de editar uno solo. */
.modal.modal-capitulo.con-lista { max-width: 560px; }
.cert-modal-head { display: flex; align-items: center; gap: 13px; margin-bottom: 20px; }
.cert-modal-num {
  display: inline-grid; place-items: center; width: 38px; height: 38px; flex: none;
  border-radius: var(--radius-sm); background: var(--brand); color: #fff;
  font-size: 16px; font-weight: 600; font-variant-numeric: tabular-nums;
}
.cert-modal-head .modal-title { margin: 0; }
.cert-modal-sub { font-size: 12.5px; color: var(--muted); }
.cert-modal-body { display: flex; flex-direction: column; gap: 16px; margin-bottom: 20px; }
.cert-imp-wrap { width: 100%; }
.cert-pct-campo {
  display: flex; flex-direction: column; gap: 9px;
  background: var(--brand-softer); border: 1px solid #f4e0d4;
  border-radius: var(--radius-sm); padding: 14px 15px;
}
.cert-pct-caja { display: flex; align-items: center; gap: 14px; }
.cert-pct-val {
  font-size: 24px; font-weight: 600; color: var(--brand-ink);
  font-variant-numeric: tabular-nums; letter-spacing: -0.025em; line-height: 1;
  flex: none; min-width: 96px;
}
.cert-pct-track { flex: 1; display: block; height: 8px; border-radius: 100px; background: var(--surface); box-shadow: inset 0 0 0 1px #f0d8c9; overflow: hidden; }
.cert-pct-fill { display: block; height: 100%; background: var(--brand); border-radius: 100px; transition: width 0.18s ease; }
.cert-pct-nota { font-size: 12px; color: var(--muted); }
.cert-error { display: none; margin: 0 0 14px; font-size: 13px; color: var(--danger); font-weight: 600; }
.cert-error.show { display: block; }

/* Recordatorio, dentro del modal de alta, de los capítulos ya guardados */
.cert-modal-lista {
  margin-bottom: 18px; padding-top: 14px; border-top: 1px solid var(--border);
  max-height: 260px; overflow-y: auto;
}
.cert-modal-lista .cert-caps { margin-top: 0; }
.cert-modal-lista-titulo {
  display: block; font-size: 10.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--muted); margin-bottom: 6px;
}

/* Tres acciones: Salir a la izquierda, guardar y terminar agrupados a la derecha */
.cert-modal-actions { justify-content: space-between; gap: 10px; flex-wrap: wrap; }
.cert-modal-actions-right { display: flex; gap: 10px; flex-wrap: wrap; justify-content: flex-end; }

/* ============================================================================
 * PRECIOS ADICIONALES
 * Registro de contradictorios y precios nuevos de una obra.
 * ==========================================================================*/

/* ---- Acceso desde la pantalla de la obra -------------------------------- */
.acceso-card {
  display: flex; align-items: center; gap: 14px;
  margin-bottom: 18px; padding: 14px 18px;
  background: var(--surface); border: 1px solid var(--border); border-radius: var(--radius);
  box-shadow: var(--shadow-sm); text-decoration: none; color: inherit;
  transition: border-color 0.14s, box-shadow 0.14s, transform 0.14s;
}
.acceso-card:hover { border-color: var(--brand); box-shadow: var(--shadow-md); }
.acceso-card-ic {
  display: inline-grid; place-items: center; width: 38px; height: 38px; flex: none;
  border-radius: var(--radius-sm); background: var(--brand-soft); color: var(--brand-ink);
}
.acceso-card-ic .icon { width: 19px; height: 19px; }
.acceso-card-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 2px; }
.acceso-card-tit { font-size: 14.5px; font-weight: 600; color: var(--ink); }
.acceso-card-sub { font-size: 12.5px; color: var(--muted); }
.acceso-card-aviso {
  flex: none; font-size: 11.5px; font-weight: 600; padding: 4px 9px; border-radius: 100px;
  background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--warn-bd);
}
.acceso-card-chev { color: var(--muted-2); flex: none; transform: rotate(-90deg); }

/* ---- Desglose por clase, junto al importe total -------------------------- *
 * Dos cifras pequeñas al lado del número grande: cuánto del incremento es de
 * precios nuevos y cuánto de contradictorios. Coloreadas como sus chips
 * (.adic-tipo), para relacionarlas de un vistazo con el resto de la pantalla.
 * ------------------------------------------------------------------------- */
.cert-hero-valor-fila {
  display: flex; align-items: baseline; gap: 22px 28px; flex-wrap: wrap;
}
.adic-split { display: flex; gap: 20px 26px; flex-wrap: wrap; }
.adic-split-item {
  display: flex; flex-direction: column; gap: 2px;
  padding-left: 12px; border-left: 2px solid var(--tipo);
}
.adic-split-lbl {
  font-size: 10.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--muted-2);
}
.adic-split-cifras { display: flex; align-items: baseline; gap: 7px; flex-wrap: wrap; }
.adic-split-val {
  font-size: 17px; font-weight: 600; color: var(--tipo);
  font-variant-numeric: tabular-nums; letter-spacing: -0.01em;
}
.adic-split-pct { font-size: 11.5px; color: var(--muted); font-variant-numeric: tabular-nums; white-space: nowrap; }

/* ---- Resumen de cabecera ------------------------------------------------- */
.adic-resumen {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(170px, 1fr)); gap: 12px;
  margin-top: 18px;
}
.adic-dato {
  display: flex; flex-direction: column; gap: 1px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 12px 14px;
}
.adic-dato.destacado { border-color: #f0d8c9; background: var(--brand-softer); }
.adic-dato.destacado .cert-avance-val { color: var(--brand-ink); }

/* ---- Filtros: pestañas por clase + buscador ----------------------------- */
/* Sin resultados tras filtrar: mismo tono que los vacíos de tarjeta */
.tabla-vacia {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 4px;
  padding: 46px 16px; background: var(--surface);
  border: 1px solid var(--border); border-radius: var(--radius); box-shadow: var(--shadow-sm);
}
.tabla-vacia h3 { margin: 6px 0 0; font-size: 16px; font-weight: 600; letter-spacing: -0.01em; }
.tabla-vacia p { margin: 0; color: var(--muted); font-size: 13.5px; }

.filtros-barra {
  display: flex; align-items: center; gap: 12px 18px; flex-wrap: wrap;
  margin: 16px 0 14px;
}
/* En el listado de obras la barra abre la pantalla: sin margen superior */
.page-head + .filtros-barra { margin-top: 0; }
/* Las dos filas de filtros (estado principal y, bajo «Aprobada», su matiz)
   se apilan y cuentan como un solo bloque dentro de la barra. */
.filtro-tabs-wrap { display: flex; flex-direction: column; align-items: flex-start; gap: 8px; flex: none; }
.filtro-tabs { margin-bottom: 0; flex: none; }
/* Subordinada a la de arriba: más pequeña y sin caja propia, para que se lea
   como un matiz del filtro elegido y no como otro juego de filtros al mismo
   nivel. */
.filtro-subtabs { background: transparent; border-color: transparent; padding: 0 0 0 4px; }
.filtro-subtabs .seg-tab { padding: 5px 11px; font-size: 13px; }
.filtro-subtabs .seg-tab.active { background: var(--surface-2); box-shadow: none; }
.filtro-tab-n {
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
  padding: 1px 6px; border-radius: 100px; background: var(--border); color: var(--muted);
}
.seg-tab.active .filtro-tab-n { background: var(--brand-soft); color: var(--brand-ink); }
.filtro-busca { flex: 1 1 240px; min-width: 0; margin-bottom: 0; }
.adic-sin-resultados {
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 28px 16px; color: var(--muted); font-size: 13.5px;
}

/* ---- Grupos por mes ------------------------------------------------------ */
.adic-lista { display: flex; flex-direction: column; gap: 26px; margin-top: 18px; }
.adic-mes { display: flex; flex-direction: column; }
.adic-mes-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 4px 16px; flex-wrap: wrap;
  padding-bottom: 9px; margin-bottom: 12px;
  border-bottom: 1px solid var(--border-strong);
}
.adic-mes-tit { font-size: 14.5px; font-weight: 600; color: var(--ink); }
.adic-mes-meta {
  display: inline-flex; align-items: baseline; gap: 7px; flex-wrap: wrap;
  font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.adic-mes-sep { color: var(--muted-2); }
.adic-mes-inc { font-weight: 600; color: var(--c-green); }
.adic-mes-tramite {
  font-size: 11.5px; font-weight: 600; padding: 2px 8px; border-radius: 100px;
  background: var(--warn-bg); color: var(--warn-ink); border: 1px solid var(--warn-bd);
}
/* En «Aprobados» el grupo ya sabe a qué certificación va: se dice ahí mismo */
.adic-mes-cert {
  font-size: 11.5px; font-weight: 600; padding: 2px 8px; border-radius: 100px;
  background: var(--brand-soft); color: var(--brand-ink); border: 1px solid #f4e0d4;
}
.adic-mes-items { display: flex; flex-direction: column; gap: 12px; }

/* ---- Una entrada del registro -------------------------------------------- */
.adic-item {
  border: 1px solid var(--border); border-left: 3px solid var(--tipo);
  border-radius: var(--radius-sm); background: var(--surface);
  padding: 15px 17px;
}
.adic-item-cab {
  display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 14px 24px;
  align-items: start;
}
.adic-item-main { min-width: 0; display: flex; flex-direction: column; gap: 5px; }
.adic-tipo {
  align-self: flex-start;
  font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.08em;
  padding: 3px 8px; border-radius: 5px; background: var(--tipo-bg); color: var(--tipo);
}
.adic-concepto { font-size: 15px; font-weight: 600; color: var(--ink); line-height: 1.35; }
.adic-obs {
  margin: 0; font-size: 13px; color: var(--muted); line-height: 1.5; max-width: 68ch;
  display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 3; overflow: hidden;
}
.adic-item-cifras { display: flex; gap: 26px; flex: none; }
.adic-cifra { display: flex; flex-direction: column; gap: 1px; align-items: flex-end; text-align: right; }
.adic-cifra-lbl {
  font-size: 10.5px; font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--muted-2);
}
.adic-cifra-val { font-size: 17px; font-weight: 600; font-variant-numeric: tabular-nums; letter-spacing: -0.015em; }
.adic-cifra-val.up { color: var(--c-green); }
.adic-cifra-pct { font-size: 12px; color: var(--muted); font-variant-numeric: tabular-nums; }

.adic-item-pie {
  display: flex; align-items: center; justify-content: space-between; gap: 12px 18px;
  flex-wrap: wrap; margin-top: 14px; padding-top: 13px; border-top: 1px solid var(--border);
}
.adic-visados { display: flex; gap: 7px; flex-wrap: wrap; }
/* Los visados se marcan con un clic desde la propia lista */
.adic-visado {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 5px 11px 5px 8px; border-radius: 100px; cursor: pointer;
  border: 1px solid var(--border-strong); background: var(--surface);
  font-family: inherit; font-size: 12.5px; font-weight: 600; color: var(--muted-2);
  transition: background 0.14s, color 0.14s, border-color 0.14s;
}
.adic-visado .icon { width: 13px; height: 13px; }
.adic-visado:hover { border-color: var(--stone); color: var(--ink-soft); }
.adic-visado.on {
  background: var(--c-green-bg); border-color: #cfdcd1; color: var(--c-green);
}
.adic-item-fin { display: flex; align-items: center; gap: 8px; }
.adic-meta { display: inline-flex; align-items: center; gap: 12px; margin-right: 4px; flex-wrap: wrap; }
.adic-fecha, .adic-plazo {
  display: inline-flex; align-items: center; gap: 5px;
  font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.adic-fecha .icon, .adic-plazo .icon { width: 14px; height: 14px; color: var(--muted-2); }
.adic-fecha.aprobado { color: var(--c-green); font-weight: 600; }
.adic-fecha.aprobado .icon { color: var(--c-green); }

/* ---- Modal: elegir la clase de precio ------------------------------------ */
.modal.modal-adic-tipo { max-width: 540px; }
.adic-opciones { display: flex; flex-direction: column; gap: 12px; margin: 20px 0 8px; }
.adic-opcion {
  display: flex; align-items: center; gap: 14px; width: 100%; text-align: left;
  padding: 16px 18px; cursor: pointer;
  border: 1px solid var(--border-strong); border-radius: var(--radius); background: var(--surface);
  font-family: inherit; color: inherit;
  transition: border-color 0.14s, box-shadow 0.14s, background 0.14s;
}
.adic-opcion:hover { border-color: var(--tipo); background: var(--tipo-bg); box-shadow: var(--shadow-sm); }
.adic-opcion-ic {
  display: inline-grid; place-items: center; width: 40px; height: 40px; flex: none;
  border-radius: var(--radius-sm); background: var(--tipo-bg); color: var(--tipo);
}
.adic-opcion-ic .icon { width: 20px; height: 20px; }
.adic-opcion-txt { flex: 1; min-width: 0; display: flex; flex-direction: column; gap: 3px; }
.adic-opcion-tit { font-size: 15px; font-weight: 600; color: var(--ink); }
.adic-opcion-sub { font-size: 12.5px; color: var(--muted); line-height: 1.5; }
.adic-opcion-chev { color: var(--muted-2); flex: none; transform: rotate(-90deg); }

/* ---- Modal: formulario del precio ---------------------------------------- */
/* Son bastantes campos: la cabecera y los botones se quedan fijos y solo
   scrollea el formulario, para no perder de vista "Guardar". */
.modal.modal-adic {
  max-width: 620px; display: flex; flex-direction: column;
  max-height: 88vh; overflow: hidden;
}
.modal-adic .cert-modal-head { flex: none; }
.modal-adic > .cert-error, .modal-adic > .modal-actions { flex: none; }
.adic-modal-ic {
  display: inline-grid; place-items: center; width: 38px; height: 38px; flex: none;
  border-radius: var(--radius-sm); background: var(--tipo-bg); color: var(--tipo);
}
.adic-modal-ic .icon { width: 19px; height: 19px; }
.adic-form {
  display: grid; grid-template-columns: 1fr 1fr; gap: 16px 20px; margin-bottom: 20px;
  align-items: start;
  flex: 1; min-height: 0; overflow-y: auto;
}
/* El porcentaje calculado acompaña a su importe: mismo alto que el campo */
.adic-form .cert-pct-campo { padding: 11px 14px; }
.adic-form .cert-pct-val { font-size: 20px; min-width: 78px; }
/* Con el rótulo a dos líneas, la etiqueta «se calcula solo» baja en vez de
   quedarse apretada contra el borde. */
.adic-form .cert-pct-campo .field-label { flex-wrap: wrap; }
.money-dias { width: 100%; }
/* El plazo ocupa su propia fila (evita una columna vacía junto a él, que
   cambia según el tipo de precio), pero el campo en sí no necesita más
   ancho que el de un número de pocas cifras. */
.field-plazo .money-wrap.money-dias { max-width: 200px; }
.adic-checks { gap: 10px; }
.adic-checks-fila { display: flex; gap: 10px; flex-wrap: wrap; }
.adic-check {
  display: inline-flex; align-items: center; gap: 9px;
  padding: 10px 15px 10px 12px; cursor: pointer;
  border: 1px solid var(--border-strong); border-radius: var(--radius-sm); background: var(--surface);
  font-family: inherit; font-size: 13.5px; color: var(--ink-soft);
  transition: border-color 0.14s, background 0.14s, color 0.14s;
}
.adic-check-caja {
  display: inline-grid; place-items: center; width: 20px; height: 20px; flex: none;
  border: 1px solid var(--border-strong); border-radius: 6px; background: var(--surface);
  color: transparent; transition: background 0.14s, border-color 0.14s, color 0.14s;
}
.adic-check-caja .icon { width: 13px; height: 13px; }
.adic-check:hover { border-color: var(--stone); }
.adic-check.on { border-color: #cfdcd1; background: var(--c-green-bg); color: var(--c-green); font-weight: 600; }
.adic-check.on .adic-check-caja { background: var(--c-green); border-color: var(--c-green); color: #fff; }

/* ============================================================================
 * ADAPTACIÓN A CADA PANTALLA
 *
 * Tres formatos, no uno «encogido»:
 *   · Escritorio (>1080px) — barra lateral completa con nombres de sección.
 *   · Tablet (761–1080px)  — la lateral se reduce a un raíl de iconos, para que
 *                            el contenido no quede estrangulado en vertical.
 *   · Móvil (≤760px)       — cabecera arriba (marca · estado · cuenta) y barra
 *                            de pestañas abajo, al alcance del pulgar.
 *
 * Las rejillas de tarjetas usan `auto-fit`, así que se pliegan según el ancho
 * REAL disponible y no según el de la ventana.
 * ==========================================================================*/

/* El panel de resultado en vivo deja de ser una columna lateral en cuanto el
   formulario se quedaría demasiado estrecho: pasa arriba, a lo ancho. */
@media (max-width: 1080px) {
  .coste-layout { grid-template-columns: minmax(0, 1fr); }
  .coste-aside { position: static; order: -1; }
}

/* ---- Legibilidad en móvil y tablet -------------------------------------- *
 * Los textos auxiliares se dimensionaron para leerse a 60 cm en un monitor.
 * En una pantalla que se mira de pie, en obra y con luz de sol, 11px no se
 * lee: se sube todo el escalón secundario.
 * ------------------------------------------------------------------------- */
@media (max-width: 1080px) {
  .card-title { font-size: 12px; letter-spacing: 0.1em; }
  .row-head { font-size: 11.5px; letter-spacing: 0.1em; }
  .kpi-label { font-size: 13px; }
  .kpi-sub, .chart-sub, .m2-n, .proy-foot-label, .donut-total-label,
  .field-unit, .notif-meta, .hero-metric-label, .form-section-sub,
  .resumen-pagos, .perfil-item-sub, .hon-figure-label, .hon-comp-title,
  .live-label, .live-note, .hon-pill-unit { font-size: 12.5px; }
  .field-label, .pf-label, .mini-meta, .proy-meta, .cell-tipologia,
  .hon-subtitle, .card-note, .form-note, .field-hint, .live-sub,
  .notif-title { font-size: 13.5px; }
  .campo-label, .coste-field-label, .m2-label, .bar-label, .legend-label,
  .resumen-label, .notif-msg, .link-mini, .hon-legend-label,
  .m2-val, .bar-val, .legend-val { font-size: 14px; }
  .campo-valor, .pf-value, .cell-encargo-text, .badge, .cell-fecha { font-size: 15px; }
  .empty p, .empty-inline p { font-size: 14.5px; }
}

/* ---- Manejo con el dedo ------------------------------------------------- *
 * Se activa por ancho (móvil y tablet) y también por tipo de puntero, para
 * cubrir tablets grandes y portátiles táctiles. En obra se toca con guantes:
 * ningún control accionable baja de ~40px.
 * ------------------------------------------------------------------------- */
@media (max-width: 1080px), (pointer: coarse) {
  /* Sin hover, las acciones que solo aparecían al pasar el ratón serían
     invisibles: aquí están siempre presentes. */
  .edit-btn, .row-delete { opacity: 1; }
  .edit-btn, .row-delete, .icon-btn { width: 42px; height: 42px; }
  .badge-btn, .fase-badge { min-height: 40px; padding: 8px 13px; }
  .fase-menu-item { min-height: 40px; }
  .filtro-op { min-height: 40px; padding: 9px 16px; }
  .row-cli .row-accion.row-delete { opacity: 1; }
  .cli-tipo-op { min-height: 56px; }
  .filtro-limpiar { min-height: 40px; }
  .btn-sm { min-height: 40px; padding: 9px 14px; font-size: 13.5px; }
  .seg-tab { min-height: 44px; }
  .link-back { min-height: 44px; font-size: 14px; }
  .link-mini, .link-map, .perfil-web { min-height: 40px; }
  .perfil-goto { min-height: 42px; padding: 9px 13px; font-size: 13px; }
  .periodo-select { min-height: 44px; padding: 9px 11px; font-size: 14px; }
  .combo-item, .perfil-item, .estado-menu-item, .cc-action { min-height: 44px; }
  .perfil-item-acciones { opacity: 1; }
  .perfil-item-accion { width: 36px; height: 36px; }
  .cc-chip { min-height: 42px; }
  .topbar-brand { min-height: 44px; }
  .mini-row, .legend-item { padding-top: 11px; padding-bottom: 11px; }
}

/* ---- Tablet: barra lateral reducida a raíl de iconos --------------------- */
@media (min-width: 761px) and (max-width: 1080px) {
  .sidebar { width: var(--rail-w); padding: 16px 8px; align-items: stretch; }
  .sb-brand { align-items: center; padding: 6px 4px 14px; }
  .sb-brand .logo-tes { height: 19px; }
  .nav-group, .sb-alert, .sb-version, .sb-email, .sb-usuario-chev { display: none; }

  .sb-nav { gap: 4px; margin-top: 12px; }
  .nav-item {
    flex-direction: column; justify-content: center; text-align: center;
    gap: 5px; padding: 10px 4px; min-height: 62px;
  }
  .nav-item .nav-ic { width: 24px; height: 24px; }
  .nav-item .nav-ic .icon { width: 21px; height: 21px; }
  .nav-label { display: none; }
  .nav-label-corto { display: block; font-size: 11.5px; line-height: 1.15; }
  .nav-item.active::before {
    left: 10px; right: 10px; top: auto; bottom: 3px; width: auto; height: 2px;
  }
  .nav-item .nav-badge { position: absolute; top: 5px; right: 12px; }

  /* En el raíl no caben submenús colgando: en 88px quedarían dos líneas de
     texto apretadas bajo un icono. Aquí el desplegable lateral es la única
     forma, así que se usa siempre, también estando dentro del grupo. */
  .nav-bloque.dentro > .nav-sub { grid-template-rows: 0fr; }
  .nav-bloque > .nav-sub {
    position: absolute; left: 100%; top: -6px;
    z-index: 60;
    display: block; grid-template-rows: none;
    min-width: 216px;
    padding: 6px 0 6px 8px;
    opacity: 0; visibility: hidden; transform: translateX(-6px);
    pointer-events: none;
    transition: opacity 0.16s ease, transform 0.16s ease, visibility 0s 0.16s;
  }
  .nav-bloque:hover > .nav-sub,
  .nav-bloque:focus-within > .nav-sub {
    opacity: 1; visibility: visible; transform: none; pointer-events: auto;
    transition: opacity 0.18s ease, transform 0.18s cubic-bezier(0.4, 0, 0.2, 1), visibility 0s;
  }
  .nav-bloque > .nav-sub > .nav-sub-in {
    overflow: visible; opacity: 1; visibility: visible; transition: none;
    background: var(--surface);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    box-shadow: var(--shadow-lg);
    padding: 6px;
  }
  .nav-sub-lista { margin: 0; padding: 0; border-left: 0; }
  .nav-subitem { white-space: nowrap; }
  .nav-subitem.active::before { left: -2px; }

  .sb-foot { padding: 6px 0; align-items: center; }
  .sb-sesion { align-items: center; gap: 8px; }
  .sb-sync { padding: 7px; align-self: center; }
  .sb-sync .sb-sync-txt { display: none; }
  .sb-usuario { justify-content: center; padding: 6px; }

  .container { padding: 18px max(24px, var(--safe-l)) 76px max(24px, var(--safe-r)); }

  .row-obra {
    grid-template-columns: 44px minmax(0, 1fr) minmax(0, 100px) minmax(0, 180px) 40px;
  }

  /* El nombre del concepto ocupa su propia línea; importes debajo */
  .soft-row > .field-input { flex: 1 1 100%; }
}

/* En pantallas medianas la tabla de clientes pierde la ubicación: es el dato
   que menos se usa para identificar a quién se busca. */
@media (max-width: 1180px) {
  .row-cli { grid-template-columns: 46px minmax(0, 1.3fr) minmax(92px, 112px) minmax(0, 1.1fr) minmax(108px, 132px) 76px; }
  .row-cli .cell-cli-ubi { display: none; }
}

/* Tablet en vertical: cabe una columna menos todavía */
@media (min-width: 761px) and (max-width: 880px) {
  .row-obra { grid-template-columns: 44px minmax(0, 1fr) minmax(0, 180px) 40px; }
  .row-obra .cell-fecha { display: none; }
}

/* Entre 1081px y 1240px la lateral completa deja poco sitio: menos aire. */
@media (min-width: 1081px) and (max-width: 1240px) {
  .container { padding: 20px 28px 84px; }
  .row-obra { padding-left: 16px; padding-right: 16px; gap: 12px; }
}

/* ---- Tablet en vertical: las tablas de certificación se apiñan ----------- *
 * Con la barra lateral reducida a raíl (761–1080px), estas dos tablas tienen
 * cuatro columnas fijas de cifras y a la de "Capítulo" apenas le queda sitio:
 * una descripción real llega a truncarse por debajo de los 980px. En vez de
 * malvivir con columnas más estrechas, se reutiliza el mismo diseño de
 * tarjeta apilada que ya usa el móvil, sin límite superior de descripción.
 * ------------------------------------------------------------------------- */
@media (min-width: 761px) and (max-width: 980px) {
  .cert-nc-cabecera { display: none; }
  .cert-nc-fila {
    grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: 'num cap cap' 'num pem pem' 'num euros pct' 'num aviso aviso';
    gap: 10px 12px; padding: 14px 4px;
  }
  .cert-nc-fila .cert-cap-num { grid-area: num; align-self: start; }
  .cert-nc-cap { grid-area: cap; }
  .cert-nc-fila .cert-nc-pem { grid-area: pem; text-align: left; font-size: 19px; }
  .cert-nc-fila .campo-euros { grid-area: euros; }
  .cert-nc-fila .campo-pct { grid-area: pct; }
  .cert-nc-campo { display: flex; flex-direction: column; gap: 5px; }
  .cert-nc-campo-lbl { display: block; font-size: 11.5px; font-weight: 600; color: var(--muted); }
  .cert-nc-aviso { grid-area: aviso; }

  .cert-ver-cabecera { display: none; }
  .cert-ver-fila {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: 'num cap cap' 'num d1 d1' 'num d2 d2';
    gap: 8px 12px;
  }
  .cert-ver-fila .cert-cap-num { grid-area: num; align-self: start; }
  .cert-ver-fila .cert-nc-cap { grid-area: cap; }
  .cert-ver-importe { grid-area: d1; text-align: left; color: var(--muted); font-size: 13px; }
  .cert-ver-acum { grid-area: d1; justify-self: end; text-align: right; font-size: 13px; }
  .cert-ver-pct { grid-area: d2; text-align: left; font-size: 13px; }
  .cert-ver-delta { grid-area: d2; justify-self: end; text-align: right; font-size: 13px; }

  /* Con el raíl no caben concepto y cifras en la misma línea sin apretar la
     descripción: las cifras bajan y se reparten a lo ancho. */
  .adic-item-cab { grid-template-columns: minmax(0, 1fr); }
  .adic-item-cifras { gap: 0; justify-content: flex-start; }
  .adic-cifra { align-items: flex-start; text-align: left; min-width: 190px; }
}

/* ============================================================================
   CRM (embudos y oportunidades de Holded)
   ========================================================================= */

/* La tarjeta de Configuración lleva botones, así que no es un enlace entero:
   no debe reaccionar al hover como si lo fuera. */
.acceso-card-est { cursor: default; }
.acceso-card-est:hover { border-color: var(--border); box-shadow: var(--shadow-sm); }
.acceso-card-acciones { display: flex; align-items: center; gap: 8px; flex: none; flex-wrap: wrap; }
.btn-sm-danger { color: var(--danger); }
.btn-sm-danger:hover { background: var(--danger-bg); color: var(--danger); }

/* --- Estados de red --- */
.crm-cargando {
  display: flex; align-items: center; justify-content: center; gap: 10px;
  padding: 44px 20px; color: var(--muted); font-size: 13.5px;
}
.crm-spinner {
  width: 16px; height: 16px; flex: none; border-radius: 50%;
  border: 2px solid var(--border); border-top-color: var(--brand);
  animation: crm-giro 0.7s linear infinite;
}
@keyframes crm-giro { to { transform: rotate(360deg); } }

.crm-error {
  display: flex; align-items: center; gap: 14px; padding: 18px;
  background: var(--danger-bg); border: 1px solid var(--danger-bd);
  border-radius: var(--radius); color: var(--danger);
}
.crm-error-ic { flex: none; width: 22px; height: 22px; }
.crm-error-txt { flex: 1; min-width: 0; }
.crm-error-txt p { margin: 2px 0 0; font-size: 13px; color: var(--ink-soft); }

/* --- Listado de embudos --- */
.row-crm {
  display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr) 118px;
  align-items: center; gap: 14px; padding: 13px 18px;
  border-bottom: 1px solid var(--border); cursor: pointer;
  transition: background 0.12s;
}
.row-crm:last-child { border-bottom: none; }
.row-crm:not(.row-head):hover { background: var(--surface-2); }
.row-crm.row-head {
  cursor: default; background: var(--surface-2);
  font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}
.row-crm.row-head:hover { background: var(--surface-2); }
.cell-embudo { display: flex; align-items: center; gap: 12px; min-width: 0; }
.crm-embudo-ic {
  display: inline-grid; place-items: center; width: 34px; height: 34px; flex: none;
  border-radius: var(--radius-sm); background: var(--brand-soft); color: var(--brand-ink);
}
.crm-embudo-ic .icon { width: 17px; height: 17px; }
.crm-embudo-txt { display: flex; flex-direction: column; gap: 1px; min-width: 0; }
.crm-embudo-nombre {
  font-size: 14.5px; font-weight: 600; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.crm-embudo-sub { font-size: 12px; color: var(--muted); }
.crm-chips { display: flex; flex-wrap: wrap; gap: 5px; }
.crm-chip {
  font-size: 11.5px; padding: 3px 9px; border-radius: 100px;
  background: var(--surface-2); border: 1px solid var(--border); color: var(--ink-soft);
  white-space: nowrap; max-width: 140px; overflow: hidden; text-overflow: ellipsis;
}
.crm-chip-mas { background: transparent; color: var(--muted); }
.cell-acciones { display: flex; align-items: center; justify-content: flex-end; gap: 4px; }
.row-accion {
  display: inline-grid; place-items: center; width: 32px; height: 32px;
  border: none; background: transparent; border-radius: var(--radius-sm);
  color: var(--muted); cursor: pointer; transition: background 0.12s, color 0.12s;
}
.row-accion:hover { background: var(--surface-2); color: var(--ink); }
/* `.row-delete` nace con opacity:0 y solo se revela al pasar el ratón por su
   fila; sin esta regla —la gemela de la de `.row-obra`— el botón de borrar un
   embudo sería invisible para siempre en escritorio. */
.row-crm:hover .row-accion.row-delete { opacity: 1; }
.row-accion.row-delete:hover { background: var(--danger-bg); color: var(--danger); }
.row-accion .icon { width: 16px; height: 16px; }

/* --- Un embudo: tablero kanban -------------------------------------------
   Mismo reparto visual que el embudo de ventas de Holded (una columna por
   etapa, con su total arriba y las tarjetas debajo), con los colores, la
   tipografía y los radios de TES. */

.crm-cab { margin: 4px 0 18px; }
.crm-cab-fila { display: flex; align-items: flex-start; gap: 16px 20px; flex-wrap: wrap; }
.crm-cab-izq { flex: 1 1 320px; min-width: 0; }
.crm-cab-titulo { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.crm-cab-cifras { margin-top: 4px; font-size: 13.5px; color: var(--muted); }
.crm-cab-cifras strong {
  font-weight: 600; color: var(--ink); font-variant-numeric: tabular-nums;
}
.crm-cab-tools { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }

/* Saltar de embudo sin volver al listado */
.crm-selector {
  font: inherit; font-size: 13.5px; color: var(--ink-soft);
  padding: 7px 30px 7px 12px; border: 1px solid var(--border);
  border-radius: var(--radius-sm); background: var(--surface);
  cursor: pointer; max-width: 220px;
  appearance: none; -webkit-appearance: none;
  background-image: url("data:image/svg+xml;charset=utf8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236f6462' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
  background-repeat: no-repeat; background-position: right 9px center; background-size: 15px;
}
.crm-selector:hover { border-color: var(--brand); }

/* Leyenda de tipologías: descifra el tablero de un vistazo y sin ratón, que
   en el móvil no hay «pasar por encima». */
.crm-leyenda {
  display: flex; align-items: center; flex-wrap: wrap; gap: 7px 14px;
  margin-bottom: 14px; padding: 9px 13px;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
}
.crm-leyenda-tit {
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted-2);
}
.crm-leyenda-item {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--ink-soft);
}
.crm-leyenda-dot { width: 8px; height: 8px; border-radius: 50%; flex: none; }
.crm-leyenda-item em {
  font-style: normal; font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--muted);
  padding: 1px 6px; border-radius: 100px; background: var(--surface-2);
}

/* ---- El tablero, a imagen del de Holded ---------------------------------
   Las cabeceras forman una FRANJA continua con separadores finos, no cajas
   sueltas: es lo que hace que se lea como un tablero y no como una lista de
   tarjetas apiladas. Debajo, las tarjetas van sobre el fondo de la página.

   Se desplaza en horizontal y se sale del margen, para que las columnas
   lleguen al borde de la pantalla. */
.crm-board {
  display: flex; gap: 0; align-items: flex-start;
  overflow-x: auto; overflow-y: visible;
  padding: 0 0 14px;
  scroll-snap-type: x proximity;
}
.crm-col {
  flex: 0 0 300px; max-width: 300px;
  display: flex; flex-direction: column;
  scroll-snap-align: start;
}
.crm-col-head {
  padding: 15px 16px 14px;
  background: var(--surface-2);
  border: 1px solid var(--border); border-right: none;
  transition: background 0.14s;
}
.crm-col:last-child .crm-col-head { border-right: 1px solid var(--border); }
/* Redondeo solo en los extremos de la franja, como una sola pieza */
.crm-col:first-child .crm-col-head { border-radius: var(--radius) 0 0 var(--radius); }
.crm-col:last-child .crm-col-head { border-radius: 0 var(--radius) var(--radius) 0; }

.crm-col-nombre {
  display: block; font-size: 15px; font-weight: 600;
  letter-spacing: -0.01em; color: var(--ink);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.crm-col-meta {
  display: flex; align-items: center; gap: 5px; margin-top: 5px;
  font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums;
}
.crm-col-meta strong { font-weight: 600; color: var(--ink-soft); }
.crm-balanza { width: 14px; height: 14px; flex: none; color: var(--muted-2); }

.crm-col-lista { display: flex; flex-direction: column; gap: 10px; min-height: 60px; padding: 14px 7px; }
.crm-col-vacia { margin: 0; padding: 4px 9px; font-size: 12.5px; color: var(--muted-2); font-style: italic; }

/* El color de la etapa va en su cabecera, no en toda la columna: en Holded el
   color fuerte es de las TARJETAS ganadas y perdidas, y repetirlo en la
   columna entera dejaba el tablero teñido y las tarjetas sin destacar. */
.crm-col-ganada .crm-col-head { background: var(--c-green-bg); }
.crm-col-ganada .crm-col-nombre { color: #3f5a42; }
.crm-col-perdida .crm-col-head { background: #f7f2f1; }
.crm-col-suelta .crm-col-head {
  background: repeating-linear-gradient(135deg, var(--surface-2) 0 10px, #f1efe9 10px 20px);
}

/* Diana mientras se arrastra una tarjeta encima */
.crm-col-diana .crm-col-head { background: var(--brand-softer); }
.crm-col-diana .crm-col-lista {
  background: var(--brand-softer); border-radius: var(--radius-sm);
  outline: 1px dashed var(--brand); outline-offset: -6px;
}

/* --- Tarjeta de oportunidad --- */
.crm-card {
  position: relative;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm); padding: 13px 14px;
  display: flex; flex-direction: column; gap: 5px;
  cursor: grab; box-shadow: var(--shadow-sm);
  transition: border-color 0.14s, box-shadow 0.14s, transform 0.14s;
}
.crm-card:hover { border-color: var(--brand); box-shadow: var(--shadow-md); }
.crm-card:active { cursor: grabbing; }
.crm-card-volando { opacity: 0.45; transform: rotate(1.5deg); }

/* Los puntos de tipología, en su propia línea encima del título, como Holded.
   Si la oportunidad no tiene ninguna, la fila desaparece y el título sube. */
.crm-card-dots { display: flex; gap: 5px; }
.crm-card-dots:empty { display: none; }
.crm-card-dot { width: 9px; height: 9px; border-radius: 50%; flex: none; }

.crm-card-nombre {
  font-size: 14px; font-weight: 600; color: var(--ink); line-height: 1.3;
  min-width: 0; overflow-wrap: anywhere;
}
.crm-card-sub {
  margin: 0; font-size: 12.5px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.crm-card-pie { display: flex; align-items: center; gap: 10px; margin-top: 3px; }

/* La antigüedad, en la pastilla roja de Holded */
.crm-card-dias {
  font-size: 11.5px; font-weight: 600; font-variant-numeric: tabular-nums;
  padding: 3px 9px; border-radius: 100px;
  background: var(--danger-bg); color: var(--danger);
}
.crm-card-sello {
  font-size: 10.5px; font-weight: 700; letter-spacing: 0.06em;
  padding: 3px 9px; border-radius: 100px;
  background: rgba(255, 255, 255, 0.28); color: #fff;
}
.crm-card-val {
  margin-left: auto; font-size: 14px; font-weight: 600;
  color: var(--ink); font-variant-numeric: tabular-nums;
}

/* Ganada y perdida: el color ocupa la tarjeta entera, que es como se leen de
   un vistazo en el tablero de Holded sin buscar un sello pequeño. */
.crm-card-ganada, .crm-card-perdida { border-color: transparent; }
.crm-card-ganada { background: #4e9c6b; }
.crm-card-perdida { background: #e2705d; }
.crm-card-ganada .crm-card-nombre, .crm-card-perdida .crm-card-nombre,
.crm-card-ganada .crm-card-val, .crm-card-perdida .crm-card-val { color: #fff; }
.crm-card-ganada .crm-card-sub, .crm-card-perdida .crm-card-sub { color: rgba(255, 255, 255, 0.85); }
.crm-card-ganada .crm-card-dot, .crm-card-perdida .crm-card-dot {
  box-shadow: 0 0 0 2px rgba(255, 255, 255, 0.55);
}
.crm-card-ganada:hover, .crm-card-perdida:hover { border-color: var(--ink); }
/* Los botones de acción, legibles sobre el color */
.crm-card-ganada .crm-card-acciones, .crm-card-perdida .crm-card-acciones {
  background: rgba(255, 255, 255, 0.92);
}

/* Lo íntegro, junto al total del embudo. En las columnas ya no aparece —Holded
   pone una sola cifra— pero aquí arriba sí cabe, y es la que dice cuánto hay
   en juego de verdad. */
.crm-otra-cifra {
  margin-left: 10px; font-size: 12.5px;
  color: var(--muted-2); font-variant-numeric: tabular-nums;
}

/* «¿Por qué este total?». Discreto: solo se busca cuando la cifra no cuadra. */
.crm-porque {
  margin-left: 12px; padding: 0; border: 0; background: none;
  font: inherit; font-size: 12.5px; color: var(--brand-ink);
  text-decoration: underline; text-underline-offset: 3px; cursor: pointer;
}
.crm-porque:hover { color: var(--brand); }
.crm-cab-perdidas { margin: 4px 0 0; font-size: 12.5px; color: var(--muted-2); }

/* Desglose del total, oportunidad por oportunidad */
.modal-cuadre { max-width: 780px; display: flex; flex-direction: column; max-height: 86vh; }
.cuadre-scroll { flex: 1; min-height: 0; overflow: auto; margin: 0 -4px; padding: 0 4px; }
.cuadre { width: 100%; border-collapse: collapse; font-size: 13px; }
.cuadre th, .cuadre td { padding: 8px 10px; text-align: left; border-bottom: 1px solid var(--border); }
.cuadre th {
  position: sticky; top: 0; background: var(--surface);
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted-2); white-space: nowrap;
}
.cuadre .num { text-align: right; font-variant-numeric: tabular-nums; white-space: nowrap; }
.cuadre .muted { color: var(--muted-2); }
.cuadre tr.fuera td { color: var(--muted-2); text-decoration: line-through; }
.cuadre tr.fuera td.muted { text-decoration: none; }
.cuadre tfoot td {
  position: sticky; bottom: 0; background: var(--surface-2);
  font-weight: 600; border-bottom: none; border-top: 1px solid var(--border-strong);
}

/* Por qué esta cifra no coincide con la de Holded. Va debajo del total, que es
   donde se está mirando cuando surge la duda. */
.crm-cab-nota {
  display: flex; align-items: flex-start; gap: 7px;
  margin: 8px 0 0; max-width: 62ch;
  font-size: 12.5px; line-height: 1.45; color: var(--muted);
}
.crm-cab-nota .icon { width: 14px; height: 14px; flex: none; margin-top: 2px; color: var(--warn); }

.crm-col-lista { display: flex; flex-direction: column; gap: 9px; min-height: 60px; }
.crm-col-vacia { margin: 0; padding: 10px 3px; font-size: 12.5px; color: var(--muted-2); font-style: italic; }

/* Columna de ganados: el verde de la marca (--c-green), el papel que en
   Holded hace su verde. OJO: --verde/--verde-soft son de la hoja de estilos
   del PDF, no existen aquí. */
.crm-col-ganada { background: var(--c-green-bg); border-color: #cbdccd; }
.crm-col-ganada .crm-col-nombre, .crm-col-ganada .crm-col-meta strong { color: #3f5a42; }
.crm-col-perdida { background: #f7f2f1; }
.crm-col-suelta { background: repeating-linear-gradient(135deg, var(--surface-2) 0 10px, #f1efe9 10px 20px); }

/* Diana mientras se arrastra una tarjeta encima */
.crm-col-diana { border-color: var(--brand); background: var(--brand-softer); }

/* Las acciones no ensucian la tarjeta: aparecen al pasar el ratón, arriba a la
   derecha. En táctil (donde no hay hover) se muestran siempre — la regla de
   `@media (hover: none)` de más abajo se encarga. */
.crm-card-acciones {
  position: absolute; top: 7px; right: 7px;
  display: flex; gap: 2px; opacity: 0;
  background: var(--surface); border-radius: 7px; padding: 1px;
  box-shadow: var(--shadow-sm);
  transition: opacity 0.14s;
}
.crm-card:hover .crm-card-acciones, .crm-card:focus-within .crm-card-acciones { opacity: 1; }
.crm-card-btn {
  display: inline-grid; place-items: center; width: 27px; height: 27px;
  border: none; background: transparent; border-radius: 6px;
  color: var(--muted); cursor: pointer; transition: background 0.12s, color 0.12s;
}
.crm-card-btn:hover { background: var(--surface-2); color: var(--ink); }
.crm-card-btn-danger:hover { background: var(--danger-bg); color: var(--danger); }
.crm-card-btn .icon { width: 15px; height: 15px; }

/* ============================================================================
   Clientes (arquitectos y promotores)
   Una fila por ficha, con lo que se busca de un vistazo: quién es, su NIF,
   por dónde se le localiza, de dónde es y de qué tipo. Misma familia visual
   que la tabla de obras, con el avatar de iniciales de la ficha.
   ========================================================================= */
.row-cli {
  display: grid;
  grid-template-columns: 46px minmax(0, 1.25fr) minmax(96px, 118px) minmax(0, 1.1fr) minmax(0, 0.85fr) minmax(112px, 138px) 76px;
  align-items: center;
  gap: 16px;
  padding: 14px 20px;
  border-bottom: 1px solid var(--border);
  cursor: pointer;
  transition: background 0.12s;
}
.row-cli:last-child { border-bottom: none; }
.row-cli:not(.row-head):hover { background: var(--surface-2); }
.row-cli.row-head {
  cursor: default; background: var(--surface-2);
  font-size: 11px; font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}
.row-cli.row-head:hover { background: var(--surface-2); }

/* Avatar de iniciales, tintado según el tipo: distingue arquitecto de
   promotor antes incluso de leer la etiqueta. */
.cli-avatar {
  display: inline-grid; place-items: center;
  width: 38px; height: 38px; flex: none;
  border-radius: 50%;
  font-size: 13px; font-weight: 600; letter-spacing: 0.02em;
}
.cli-avatar .icon { width: 18px; height: 18px; }
/* Azul para el arquitecto, teal para el promotor: --c-indigo es en realidad
   el naranja de marca, y junto al ámbar no se distinguían de un vistazo, que
   era justo lo que el color tenía que resolver. */
/* Azul (frío) para arquitecto, ámbar (cálido) para promotor: --c-blue y
   --c-teal, probados antes, tienen casi la misma luminosidad y matiz —a
   primera vista costaba distinguirlos—; azul y ámbar sí contrastan de un
   vistazo, sin mirar dos veces. */
.cli-avatar-arquitecto { background: var(--c-blue-bg); color: var(--c-blue); }
.cli-avatar-promotor { background: var(--c-amber-bg); color: var(--c-amber); }
/* Violeta para «otros colaboradores»: se evita el verde (ya significa "hecho"
   en certificaciones y documentación) y contrasta bien con el azul y el ámbar
   de los otros dos tipos. */
.cli-avatar-colaborador { background: var(--c-violet-bg); color: var(--c-violet); }

.cell-cli-nombre { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.cli-nombre {
  font-size: 15px; font-weight: 600; color: var(--ink); letter-spacing: -0.01em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cli-sub {
  font-size: 12.5px; color: var(--muted);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cli-nif {
  font-size: 13px; color: var(--ink-soft);
  font-variant-numeric: tabular-nums; letter-spacing: 0.02em;
}

/* Email y teléfono como enlaces directos: desde el listado se llama o se
   escribe sin tener que entrar en la ficha. */
.cli-contacto { display: flex; flex-direction: column; gap: 3px; min-width: 0; }
.cli-via {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--ink-soft); text-decoration: none;
  min-width: 0; white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cli-via .icon { width: 13px; height: 13px; flex: none; color: var(--muted-2); }
.cli-via:hover { color: var(--brand-ink); }
.cli-via:hover .icon { color: var(--brand-ink); }

.cli-ubi {
  display: inline-flex; align-items: center; gap: 6px;
  font-size: 12.5px; color: var(--ink-soft); min-width: 0;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.cli-ubi .icon { width: 13px; height: 13px; flex: none; color: var(--muted-2); }

.cell-cli-tipo { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.cli-tipo {
  font-size: 11.5px; font-weight: 600;
  padding: 4px 10px; border-radius: 100px; white-space: nowrap;
}
.cli-tipo-arquitecto { background: var(--c-blue-bg); color: var(--c-blue); }
.cli-tipo-promotor { background: var(--c-amber-bg); color: var(--c-amber); }
.cli-tipo-colaborador { background: var(--c-violet-bg); color: var(--c-violet); }
.cli-obras { font-size: 11.5px; color: var(--muted-2); font-variant-numeric: tabular-nums; }

.cell-cli-acciones { display: flex; align-items: center; justify-content: flex-end; gap: 2px; }
/* Igual que en obras: aparecen al pasar el ratón por la fila. La regla de
   `@media (hover: none)` de más abajo las deja fijas en táctil. */
.row-cli:hover .row-accion.row-delete { opacity: 1; }

/* Elegir tipo al crear: dos opciones grandes, no un desplegable */
.cli-tipo-elegir { display: flex; flex-direction: column; gap: 10px; margin: 4px 0 20px; }
.cli-tipo-op {
  display: flex; align-items: center; gap: 14px; text-align: left;
  font: inherit; padding: 14px 16px; cursor: pointer;
  background: var(--surface); border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  transition: border-color 0.12s, background 0.12s;
}
.cli-tipo-op:hover { border-color: var(--brand); background: var(--brand-softer); }
.cli-tipo-op-txt { display: flex; flex-direction: column; gap: 2px; }
.cli-tipo-op-txt strong { font-size: 14.5px; font-weight: 600; color: var(--ink); }
.cli-tipo-op-txt span { font-size: 12.5px; color: var(--muted); }

/* --- Panel de filtros del listado de obras --- */
.filtro-boton { flex: none; }
.filtro-boton.activo { border-color: var(--brand); color: var(--brand-ink); }
.filtro-boton-n {
  font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums;
  min-width: 18px; padding: 1px 6px; border-radius: 100px;
  background: var(--brand); color: #fff;
}
/* Lo que está filtrado, a la vista y quitable de uno en uno: si no, es fácil
   no entender por qué falta una obra del listado. */
.filtro-chips { display: flex; flex-wrap: wrap; gap: 7px; margin: -4px 0 14px; }
.filtro-chip {
  display: inline-flex; align-items: center; gap: 6px;
  font: inherit; font-size: 12.5px; color: var(--brand-ink);
  padding: 5px 11px; border-radius: 100px;
  background: var(--brand-soft); border: 1px solid var(--brand-soft);
  cursor: pointer; transition: border-color 0.12s;
}
.filtro-chip:hover { border-color: var(--brand); }
.filtro-chip .icon { width: 13px; height: 13px; opacity: 0.7; }
.filtro-chip-limpiar { background: transparent; border-color: var(--border); color: var(--muted); }
.filtro-chip-limpiar:hover { border-color: var(--muted); color: var(--ink-soft); }

/* El cuerpo del panel: grupos como bloques propios, separados con aire de
   verdad (gap, no un margen que se va acumulando) — es lo que evita que todo
   se lea apelotonado en una sola caja. */
.filtro-cuerpo { display: flex; flex-direction: column; gap: 26px; margin-top: 6px; }
.filtro-grupo { display: flex; flex-direction: column; gap: 12px; }
.filtro-grupo-tit {
  display: block;
  font-size: 11px; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted-2);
}
.filtro-ops { display: flex; flex-wrap: wrap; gap: 9px; }
.filtro-op {
  display: inline-flex; align-items: center; gap: 8px;
  font: inherit; font-size: 13.5px; color: var(--ink-soft);
  padding: 9px 15px; border-radius: 100px;
  background: var(--surface); border: 1px solid var(--border);
  cursor: pointer; transition: border-color 0.12s, background 0.12s, color 0.12s;
}
.filtro-op:hover { border-color: var(--brand); }
.filtro-op.activo { background: var(--brand-soft); border-color: var(--brand); color: var(--brand-ink); font-weight: 600; }
.filtro-op em {
  font-style: normal; font-size: 11px; font-weight: 600;
  font-variant-numeric: tabular-nums; color: var(--muted);
}
.filtro-op.activo em { color: var(--brand-ink); }
.filtro-rejilla { display: grid; grid-template-columns: 1fr 1fr; gap: 14px 16px; }
.filtro-campo { display: flex; flex-direction: column; gap: 7px; min-width: 0; }
.filtro-campo-lbl { font-size: 12.5px; color: var(--ink-soft); font-weight: 500; }

/* El pie, separado del cuerpo con un filo — como ya hace `.modal-perfil >
   .modal-actions` en el resto de la app — en vez de quedar pegado al último
   grupo. «Quitar todos» se aparta a la izquierda y en texto: antes las tres
   pastillas (Quitar todos / Cancelar / Aplicar) pesaban igual y era fácil
   confundir cuál deshacía qué. */
.filtro-pie {
  display: flex; align-items: center; justify-content: space-between; gap: 14px;
  margin: 26px -26px -26px; padding: 18px 26px;
  border-top: 1px solid var(--border); background: var(--surface-2);
  border-radius: 0 0 var(--radius) var(--radius);
}
.filtro-limpiar {
  font: inherit; font-size: 13.5px; font-weight: 600; color: var(--muted);
  background: none; border: none; padding: 8px 4px; cursor: pointer;
  transition: color 0.12s;
}
.filtro-limpiar:hover { color: var(--danger); }
.filtro-pie-acciones { display: flex; gap: 10px; }

/* --- Panel lateral de la oportunidad ---
   El equivalente al panel que abre Holded al pulsar una tarjeta: entra desde
   la derecha, ocupa el alto de la pantalla y deja el tablero detrás. */
.panel-overlay {
  position: fixed; inset: 0; z-index: 90;
  background: rgba(48, 41, 41, 0.28);
  display: flex; justify-content: flex-end;
  animation: panel-fondo 0.16s ease;
}
.panel-lateral {
  width: 100%; max-width: 440px; height: 100%;
  background: var(--surface); box-shadow: var(--shadow-lg);
  display: flex; flex-direction: column;
  animation: panel-entra 0.18s ease;
}
/* Al cerrar se invierte; el nodo se retira cuando termina. */
.panel-overlay.cerrando { animation: panel-fondo 0.15s ease reverse forwards; }
.panel-overlay.cerrando .panel-lateral { animation: panel-entra 0.15s ease reverse forwards; }
@keyframes panel-fondo { from { opacity: 0; } to { opacity: 1; } }
@keyframes panel-entra { from { transform: translateX(24px); } to { transform: translateX(0); } }
.panel-cuerpo { display: flex; flex-direction: column; height: 100%; min-height: 0; }
.panel-scroll { flex: 1; min-height: 0; overflow-y: auto; padding: 0 22px 22px; }

.panel-cab {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 20px 22px 16px; border-bottom: 1px solid var(--border);
}
.panel-cab-txt { flex: 1; min-width: 0; }
.panel-titulo {
  margin: 0; font-size: 19px; font-weight: 600; letter-spacing: -0.01em;
  color: var(--ink); overflow-wrap: anywhere;
}
.panel-sub { display: block; margin-top: 3px; font-size: 12px; color: var(--muted); }

.panel-bloque { margin-top: 20px; }
.panel-bloque-tit {
  display: block; margin-bottom: 10px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted-2);
}

/* Contacto y sus vías de aviso */
.panel-contacto { margin: 18px 0 12px; font-size: 13.5px; color: var(--muted); }
.panel-contacto strong { font-weight: 600; color: var(--ink); }
.panel-vias { display: flex; gap: 8px; }
.panel-via {
  flex: 1; display: flex; flex-direction: column; align-items: center; gap: 6px;
  padding: 11px 6px; border-radius: var(--radius-sm);
  background: var(--surface-2); border: 1px solid var(--border);
  font-size: 11.5px; color: var(--ink-soft); text-decoration: none;
  transition: border-color 0.12s, background 0.12s;
}
.panel-via:hover { border-color: var(--brand); background: var(--brand-softer); }
.panel-via-ic {
  display: inline-grid; place-items: center; width: 32px; height: 32px;
  border-radius: 50%; background: var(--brand-soft); color: var(--brand-ink);
}
.panel-via-ic .icon { width: 16px; height: 16px; }
/* Sin dato al que llamar: se ve que existe la vía, pero apagada */
.panel-via.apagada { opacity: 0.42; pointer-events: none; }
.panel-via.apagada .panel-via-ic { background: var(--surface-2); color: var(--muted-2); }

/* Las cifras, en dos columnas como en Holded */
.panel-cifras {
  display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
  margin-top: 20px; background: var(--border);
  border: 1px solid var(--border); border-radius: var(--radius-sm); overflow: hidden;
}
.panel-celda { background: var(--surface); padding: 13px 14px; min-width: 0; }
.panel-celda-lbl { display: block; font-size: 11.5px; color: var(--muted); }
.panel-celda-val {
  display: block; margin-top: 4px; font-size: 17px; font-weight: 600;
  color: var(--ink); font-variant-numeric: tabular-nums; overflow-wrap: anywhere;
}
.panel-tipol { display: inline-flex; align-items: center; gap: 7px; font-size: 14px; font-weight: 400; }
/* Con un número impar de celdas, la última ocupa las dos columnas: si no,
   queda un hueco gris con el fondo de la rejilla asomando. */
.panel-celda-ancha { grid-column: 1 / -1; }

/* Ganado / Perdido: llevan a la etapa correspondiente del embudo */
.panel-desenlace { display: flex; gap: 8px; margin-top: 12px; }
.panel-btn-gan, .panel-btn-per {
  flex: 1; font: inherit; font-size: 13px; font-weight: 600;
  padding: 11px 10px; border-radius: var(--radius-sm); cursor: pointer;
  border: 1px solid transparent; transition: filter 0.12s;
}
.panel-btn-gan { background: var(--c-green-bg); color: #3f5a42; }
.panel-btn-per { background: var(--danger-bg); color: var(--danger); }
.panel-btn-gan:hover, .panel-btn-per:hover { filter: brightness(0.96); }
.panel-btn-gan.puesto { border-color: var(--c-green); }
.panel-btn-per.puesto { border-color: var(--danger); }

/* Barra de etapas: enseña por dónde va y mueve al pulsarla */
.panel-etapas { display: flex; gap: 3px; margin-top: 16px; }
.panel-etapa {
  flex: 1; min-width: 0; position: relative;
  font: inherit; font-size: 0; line-height: 0;
  height: 30px; padding: 0; cursor: pointer;
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 4px; transition: background 0.12s, border-color 0.12s;
}
.panel-etapa:hover { border-color: var(--brand); }
.panel-etapa.pasada { background: var(--brand-soft); border-color: var(--brand-soft); }
/* La actual se ensancha y muestra su nombre; las demás son solo el tramo. */
.panel-etapa.actual {
  flex: 3 1 auto; background: var(--brand); border-color: var(--brand);
  display: flex; align-items: center; justify-content: center; padding: 0 10px;
}
.panel-etapa.actual span {
  font-size: 10px; font-weight: 600; letter-spacing: 0.08em; line-height: 1.2;
  text-transform: uppercase; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.panel-etapa:not(.actual) span { display: none; }

/* El nombre de la etapa al pasar por encima, como en Holded.
 *
 * En un tramo de 50 px sin rótulo es la única forma de saber a qué etapa vas a
 * mover la oportunidad. Se pinta con CSS y no con el `title` del navegador
 * porque ese tarda casi un segundo en aparecer —justo cuando ya has decidido
 * y pulsado— y no se le puede dar ningún estilo. */
.panel-etapa::after {
  content: attr(data-etapa);
  position: absolute; bottom: calc(100% + 8px); left: 50%; transform: translateX(-50%);
  z-index: 5; pointer-events: none;
  padding: 5px 10px; border-radius: 6px;
  background: var(--ink); color: #fff;
  font-size: 11.5px; font-weight: 600; line-height: 1.2;
  letter-spacing: 0; text-transform: none; white-space: nowrap;
  opacity: 0; transition: opacity 0.12s;
}
/* La puntita que señala el tramo */
.panel-etapa::before {
  content: ''; position: absolute; bottom: calc(100% + 2px); left: 50%;
  transform: translateX(-50%); z-index: 5; pointer-events: none;
  border: 5px solid transparent; border-top-color: var(--ink);
  opacity: 0; transition: opacity 0.12s;
}
.panel-etapa:hover::after, .panel-etapa:hover::before,
.panel-etapa:focus-visible::after, .panel-etapa:focus-visible::before { opacity: 1; }
/* En el tramo actual sobra: su nombre ya está escrito dentro. */
.panel-etapa.actual::after, .panel-etapa.actual::before { content: none; }

/* El panel recorta por los lados (tiene desplazamiento propio), así que los
   tramos de los extremos alinean el rótulo con su borde en vez de centrarlo:
   centrado, el de la primera etapa se saldría por la izquierda. */
.panel-etapa:nth-child(-n+2)::after { left: 0; transform: none; }
.panel-etapa:nth-last-child(-n+2)::after { left: auto; right: 0; transform: none; }

.panel-crear { display: flex; flex-wrap: wrap; gap: 8px; }
.panel-crear-btn {
  display: inline-flex; align-items: center; gap: 8px;
  font: inherit; font-size: 13px; color: var(--ink-soft);
  padding: 10px 15px; border-radius: var(--radius-sm);
  background: var(--surface); border: 1px solid var(--border);
  cursor: pointer; transition: border-color 0.12s, background 0.12s;
}
.panel-crear-btn:hover { border-color: var(--brand); background: var(--brand-softer); }
.panel-crear-btn .icon { width: 15px; height: 15px; color: var(--brand-ink); }

.panel-pie {
  display: flex; gap: 8px; flex: none;
  padding: 14px 22px; border-top: 1px solid var(--border); background: var(--surface);
}
.panel-pie .btn { flex: 1; justify-content: center; }

/* --- Ficha de una oportunidad ---
   Lo que en Holded es abrir la tarjeta: todo lo que su API devuelve de esa
   oportunidad, sin esconder nada, y las acciones que permite. */
.modal-ancho { max-width: 560px; max-height: 86vh; overflow-y: auto; }
.ficha-cab { display: flex; align-items: flex-start; gap: 12px; }
.ficha-cab .modal-title { flex: 1; min-width: 0; margin-bottom: 0; overflow-wrap: anywhere; }
.ficha-cerrar {
  flex: none; display: inline-grid; place-items: center; width: 32px; height: 32px;
  border: none; background: transparent; border-radius: var(--radius-sm);
  color: var(--muted); cursor: pointer;
}
.ficha-cerrar:hover { background: var(--surface-2); color: var(--ink); }
.ficha-cifra { display: flex; align-items: center; gap: 14px; flex-wrap: wrap; margin: 10px 0 18px; }
.ficha-importe {
  font-size: 24px; font-weight: 600; letter-spacing: -0.02em;
  color: var(--brand-ink); font-variant-numeric: tabular-nums;
}
.ficha-tipol {
  display: inline-flex; align-items: center; gap: 7px;
  font-size: 12.5px; color: var(--ink-soft);
  padding: 4px 11px; border-radius: 100px;
  background: var(--surface-2); border: 1px solid var(--border);
}
.ficha-datos { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 12px 18px; }
.ficha-dato { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ficha-dato-lbl {
  font-size: 10px; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted-2);
}
.ficha-dato-val { font-size: 13.5px; color: var(--ink); overflow-wrap: anywhere; }
.ficha-bloque { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--border); }
.ficha-bloque-tit {
  display: block; margin-bottom: 11px;
  font-size: 10px; font-weight: 600; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--brand-ink);
}
.ficha-acciones {
  display: flex; flex-wrap: wrap; gap: 8px;
  margin-top: 22px; padding-top: 18px; border-top: 1px solid var(--border);
}
.ficha-nota { margin: 14px 0 0; font-size: 11.5px; color: var(--muted-2); line-height: 1.45; }

/* --- Selector de etapa --- */
.crm-etapa-lista { display: flex; flex-direction: column; gap: 6px; margin: 14px 0; }
.crm-etapa-op {
  display: flex; align-items: center; gap: 9px; width: 100%;
  padding: 12px 14px; border: 1px solid var(--border); background: var(--surface);
  border-radius: var(--radius-sm); font-size: 14px; color: var(--ink-soft);
  cursor: pointer; text-align: left; transition: border-color 0.12s, background 0.12s;
}
.crm-etapa-op:hover { border-color: var(--brand); background: var(--surface-2); }
.crm-etapa-op.active { border-color: var(--brand); color: var(--ink); font-weight: 600; }
.crm-etapa-op .icon { margin-left: auto; color: var(--brand-ink); }

/* En pantallas táctiles no hay hover: las acciones que aparecían al pasar el
   ratón (editar, eliminar) serían invisibles e inalcanzables. */
@media (hover: none) {
  .edit-btn, .row-delete { opacity: 1; }
  /* Sin ratón no hay forma de descubrir las acciones de una tarjeta: se dejan
     puestas. Y arrastrar tampoco funciona, para eso está el botón «Mover». */
  .crm-card-acciones { opacity: 1; }
  .crm-card { cursor: default; }

  /* El enganche del tablero es de TODA pantalla táctil, no solo del móvil: en
     una tablet las columnas caben de dos en dos pero se sigue pasando de etapa
     con el dedo, y sin esto el desplazamiento se queda a medias entre dos. */
  .crm-board { scroll-snap-type: x mandatory; }
  .crm-col { scroll-snap-stop: always; }
}

/* ---- Móvil: cabecera + barra de pestañas -------------------------------- */
@media (max-width: 760px) {
  /* Cashflow en móvil: un mes por línea. Una fila de veinticuatro casillas
     desplazándose de lado no hay dedo que la rellene; en vertical, cada mes
     es una fila grande con su nombre y su importe, y se baja con el pulgar. */
  /* Aquí no hay desplazamiento lateral: los meses se apilan en filas. El
     `fit-content` del escritorio no vale, porque encogería la tabla al ancho
     de su fila más corta en vez de ocupar la tarjeta. */
  .cf-scroll { overflow-x: visible; width: auto; max-width: none; margin: 0; padding: 0; }
  .cf-tabla { flex-direction: column; width: auto; min-width: 0; margin-inline: 0; }
  /* Aquí cada «columna» es una FILA a lo ancho: el tope de 132px del
     escritorio la dejaría en una tira estrecha. */
  .cf-col, .cf-col-obra, .cf-col-mas {
    flex: none; flex-direction: row; align-items: stretch;
    width: auto; max-width: none;
    border-left: none; border-top: 1px solid var(--border);
  }
  .cf-col:first-child { border-top: none; }
  .cf-col-obra { position: static; box-shadow: none; background: var(--surface-2); }
  .cf-col-obra .cf-celda-cab { display: none; }
  .cf-col-obra .cf-celda-obra { padding: 12px 14px; }
  .cf-celda-cab {
    flex: 0 0 42%; min-height: 56px; padding: 8px 14px;
    background: transparent; border-bottom: none; border-right: 1px solid var(--border);
  }
  .cf-celda { flex: 1; min-height: 56px; }
  .cf-input { font-size: 16px; padding: 12px 8px; }

  /* Aquí cada mes ya es una fila, así que «añadir» es una fila más a lo ancho,
     no una columna estrecha al final. */
  .cf-col-mas { flex: none; background: transparent; }
  .cf-col-mas .cf-celda-cab { display: none; }
  .cf-celda-mas { padding: 10px 14px; }
  .cf-mas { width: 100%; justify-content: center; min-height: 48px; }
  /* La ✕ del mes añadido, a tamaño de dedo */
  .cf-mes-quitar { width: 38px; height: 38px; }
  .cf-mes-quitar .icon { width: 16px; height: 16px; }
  .cf-col-extra .cf-celda-cab { background: var(--brand-softer); }
  .cf-cifra-val { font-size: 23px; }
  .cf-cifras { gap: 10px 24px; }
  /* Selectores del mes de aprobación: grandes para el dedo, y a 16px para
     que el iPhone no haga zoom al tocarlos. */
  .cf-inicio-lbl { flex: 0 0 100%; }
  .cf-sel { font-size: 16px; padding: 11px 10px; }
  .cf-sel:first-of-type { flex: 1 1 auto; }

  .cf-fijo { font-size: 16px; padding: 12px 8px; }
  /* Lo facturado: una línea más debajo de cada mes, a todo lo ancho y con su
     rótulo. El total va en la explicación de debajo de la tabla. */
  .cf-col { flex-wrap: wrap; }
  .cf-celda-real { flex: 0 0 100%; height: auto; min-height: 40px; justify-content: space-between; padding: 0 14px; }
  .cf-real-lbl { display: inline; font-weight: 500; }
  .cf-col-obra .cf-celda-real { display: none; }
  /* Un mes que aún no ha llegado y sin factura no tiene nada que enseñar, y
     aquí cada línea vacía es un desplazamiento más con el pulgar. */
  .cf-celda-real.futuro:not(.con) { display: none; }
  .cf-real-nota, .cf-real-btns, .cf-real-lista { margin-left: 0; }
  .cf-real-btns .btn { min-height: 44px; }
  .cf-acciones-btns { width: 100%; }
  .cf-acciones-btns .btn { flex: 1 1 auto; justify-content: center; min-height: 48px; }
  .cf-modo { flex: 1 1 100%; margin-left: 0; }
  .cf-modo-op { flex: 1; min-height: 44px; font-size: 14.5px; }
  .cf-gastos-scroll { width: auto; }
  .cfgg-quitar { width: 34px; height: 34px; }
  /* En la columna fija del móvil no caben sangría, total y papelera juntos. */
  .cfgg-concepto-pie.cfgg-sangria { padding-left: 0; }
  .cfgg-anadir-otro { margin-left: 0; min-height: 40px; }
  /* `stretch`: el `center` del escritorio es para las filas de la rejilla; en
     columna centraría cada concepto a su ancho y quedarían escalonados. */
  .cfgg-conceptos { display: flex; flex-direction: column; align-items: stretch; gap: 12px; }
  .cfgg-concepto {
    display: grid; grid-template-columns: 1fr auto 40px; gap: 5px 10px; align-items: center;
    grid-template-areas: "nom val pct" "barra barra barra";
  }
  .cfgg-concepto-nom { grid-area: nom; }
  .cfgg-concepto-val { grid-area: val; }
  .cfgg-concepto-pct { grid-area: pct; }
  .cfgg-concepto-barra { grid-area: barra; }
  .cfgg-barra { padding: 0 14px 12px; }
  .cfgg-todas { flex: 1 1 100%; justify-content: center; min-height: 44px; }
  .cfgg-plegar { width: 32px; height: 32px; }
  .cfgg-sangria { padding-left: 38px; }
  .cf-gastos-scroll .cfg-tabla { grid-template-columns: 136px repeat(var(--cfg-meses, 1), 116px); }

  /* La tabla de TODAS las obras sí sigue desplazándose de lado en el móvil:
     apilarla no serviría de nada, porque lo que se mira es precisamente la
     misma columna de mes para todas las obras. Se estrecha, y el nombre se
     queda fijo a la izquierda. */
  .cfg-card .cf-scroll { overflow-x: auto; }
  .cfg-tabla { grid-template-columns: 148px repeat(var(--cfg-meses, 1), 124px); }
  .cfg-obra { padding: 10px; }
  .cfg-obra-nom { font-size: 12.5px; }
  .cfg-obra-cifra { font-size: 11px; }
  .cfg-obra-base { display: none; }
  .cfg-cab { padding: 8px 10px; }
  .cfg-celda { padding: 8px 10px 8px 4px; }

  /* --- CRM en móvil ---
     El listado: el nombre del embudo manda y las etapas pasan debajo; la
     cabecera de la tabla sobra cuando ya no hay columnas que rotular. */
  .row-crm { grid-template-columns: minmax(0, 1fr) auto; gap: 8px 10px; }
  .row-crm.row-head { display: none; }
  .row-crm .cell-etapas { grid-column: 1 / -1; }
  .acceso-card-acciones { width: 100%; }
  .acceso-card-acciones .btn { flex: 1; justify-content: center; }

  /* El panel de la oportunidad ocupa la pantalla entera: a 390px, un panel
     lateral estrecho no deja sitio ni para las cifras. */
  .panel-lateral { max-width: none; }
  .panel-cifras { grid-template-columns: 1fr; }
  .panel-scroll { padding: 0 16px 16px; }
  .panel-cab, .panel-pie { padding-left: 16px; padding-right: 16px; }
  .panel-crear-btn { flex: 1; justify-content: center; }

  .filtro-rejilla { grid-template-columns: 1fr; }
  .filtro-boton { width: 100%; justify-content: center; }
  /* «Quitar todos» pasa a su propia línea, encima de Cancelar/Aplicar: en
     una fila de 390px las tres pastillas no caben sin apretarse. */
  .filtro-pie { flex-wrap: wrap; }
  .filtro-limpiar { order: 1; width: 100%; text-align: left; padding-left: 0; }
  .filtro-pie-acciones { order: 2; width: 100%; }
  .filtro-pie-acciones .btn { flex: 1; justify-content: center; }

  /* El tablero sigue moviéndose en horizontal, como en escritorio: pasar de
   * etapa es un gesto lateral, no bajar toda la pantalla para llegar a
   * «Ganados». Cada columna ocupa casi el ancho entero con un asomo de la
   * siguiente —el «peek»—, que es lo que avisa de que hay más hacia la
   * derecha sin tener que decirlo con texto.
   *
   * El arrastre de tarjetas SÍ sigue sin funcionar con el dedo (no hay
   * `dragstart` táctil sin JS aparte), pero para eso ya existe el botón
   * «Mover de etapa» de cada tarjeta, visible en pantallas táctiles por la
   * regla de `@media (hover: none)` de más arriba.
   */
  .crm-board { scroll-snap-type: x mandatory; padding-bottom: 16px; }
  .crm-col { flex: 0 0 88vw; max-width: 360px; scroll-snap-stop: always; }
  /* La lista de tarjetas no crece sin límite: si una etapa tiene treinta
   * oportunidades, su columna se queda de un alto manejable y esas treinta se
   * repasan bajando DENTRO de ella, sin perder la referencia de en qué etapa
   * se está ni el resto del tablero detrás. */
  /* El 260 sale de medir: la cabecera de la página, la franja de etapas y el
     aire de la lista. Que sobre o falte un poco no rompe nada —la columna sale
     algo más corta, o hay que bajar un dedo más—, pero afinarlo es la
     diferencia entre que una etapa entre entera en pantalla o no. */
  .crm-col-lista { max-height: calc(100dvh - var(--topbar-h) - var(--safe-t) - 260px); overflow-y: auto; }
  .crm-cab-tools { width: 100%; }
  .crm-cab-tools .btn { flex: 1; justify-content: center; }
  .crm-selector { max-width: 100%; flex: 1 1 100%; }
  /* Botones cómodos para el dedo */
  .crm-card { padding: 13px; }
  .crm-card-btn { width: 40px; height: 40px; }
  .crm-card-acciones { position: static; opacity: 1; box-shadow: none; background: transparent; padding: 0; margin-left: 16px; }
  /* Sobre una ganada o una perdida, los iconos en blanco. En pantalla ancha
     van flotando sobre una placa clara que los despega del color; aquí van
     DENTRO de la tarjeta, y esa placa sería un parche blanco en mitad del
     verde. Depende del ancho —de si las acciones flotan o no—, no de que haya
     dedo: una ventana estrecha de escritorio tiene el mismo problema. */
  .crm-card-ganada .crm-card-acciones,
  .crm-card-perdida .crm-card-acciones { background: transparent; box-shadow: none; }
  .crm-card-ganada .crm-card-btn,
  .crm-card-perdida .crm-card-btn { color: rgba(255, 255, 255, 0.92); }
  .crm-card-ganada .crm-card-btn:hover,
  .crm-card-perdida .crm-card-btn:hover { background: rgba(255, 255, 255, 0.2); color: #fff; }

  html, body { font-size: 16px; }
  .app-shell { display: block; min-height: 100dvh; }
  .sidebar { display: none; }

  /* Cabecera fija: marca, estado de guardado y acceso a la cuenta */
  .topbar {
    display: flex; align-items: center; gap: 10px;
    position: sticky; top: 0; z-index: 40;
    height: calc(var(--topbar-h) + var(--safe-t));
    padding: var(--safe-t) max(14px, var(--safe-r)) 0 max(14px, var(--safe-l));
    background: rgba(255, 255, 255, 0.88);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-bottom: 1px solid var(--border);
  }
  .topbar-brand { display: inline-flex; align-items: center; min-width: 0; }
  .topbar-brand .logo-tes { height: 21px; }
  .topbar-acciones { margin-left: auto; display: flex; align-items: center; gap: 6px; }
  /* En móvil la campana ya va en la cabecera: la franja del escritorio sobra. */
  .main-bar { display: none; }
  .topbar .campana { width: 44px; height: 44px; border-radius: 12px; }
  .topbar .campana .icon { width: 21px; height: 21px; }
  .topbar .campana-badge { box-shadow: 0 0 0 2px #fff; }
  .topbar-cuenta {
    display: inline-grid; place-items: center; flex: none;
    width: 44px; height: 44px; border-radius: 12px;
    background: none; border: 0; padding: 0; cursor: pointer;
  }
  /* El menú no puede desbordar la pantalla por la derecha. */
  .topbar .menu-flot { min-width: min(268px, calc(100vw - 28px)); }
  .topbar-cuenta .sb-avatar { width: 32px; height: 32px; font-size: 14px; border-radius: 10px; }
  .topbar-cuenta .icon { width: 18px; height: 18px; }
  /* El estado de guardado se reduce a su icono; el texto vive en «Cuenta». */
  .sb-sync.compacto { padding: 9px; border-radius: 100px; }
  .sb-sync.compacto .sb-sync-txt { display: none; }
  .sb-sync.compacto .icon { width: 15px; height: 15px; }

  /* Barra de pestañas inferior */
  .tabbar {
    display: grid; grid-auto-flow: column; grid-auto-columns: 1fr;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 45;
    gap: 2px;
    padding: 6px max(6px, var(--safe-l)) calc(6px + var(--safe-b)) max(6px, var(--safe-r));
    background: rgba(255, 255, 255, 0.94);
    backdrop-filter: saturate(180%) blur(12px);
    -webkit-backdrop-filter: saturate(180%) blur(12px);
    border-top: 1px solid var(--border);
  }
  .tab-item {
    position: relative;
    display: flex; flex-direction: column; align-items: center; justify-content: center;
    gap: 3px; min-height: 50px; padding: 5px 2px; border-radius: 10px;
    color: var(--muted); font-size: 12px; font-weight: 600; line-height: 1.1;
    -webkit-tap-highlight-color: transparent;
    transition: color 0.15s, background 0.15s;
  }
  .tab-item .nav-ic { width: 24px; height: 24px; color: inherit; }
  .tab-item .nav-ic .icon { width: 22px; height: 22px; }
  .tab-item .nav-label { display: none; }
  .tab-item .nav-label-corto { display: block; }
  .tab-item:active { background: var(--surface-2); }
  .tab-item.active { color: var(--brand-ink); }
  .tab-item.active .nav-ic { color: var(--brand); }
  .tab-item .nav-badge {
    position: absolute; top: 1px; left: 50%; margin-left: 5px;
    min-width: 17px; height: 17px; padding: 0 4px; font-size: 10.5px;
  }

  /* El contenido deja hueco por debajo para no quedar bajo las pestañas */
  .container {
    padding: 20px max(16px, var(--safe-l)) calc(var(--tabbar-h) + var(--safe-b) + 26px) max(16px, var(--safe-r));
  }

  /* -- Tipografía y controles propios del móvil --------------------------- */
  .page-title { font-size: 25px; }
  .page-sub { font-size: 14.5px; }
  .kpi-value { font-size: 28px; }
  .sb-version { font-size: 12.5px; }
  /* 16px evita el zoom automático de iOS al enfocar un campo */
  .field-input, .combo-input, .perfil-search, .mini-select, .tel-pais { font-size: 16px; }
  .btn { min-height: 46px; padding: 12px 18px; }
  .page-head .btn { width: 100%; }
  .periodo-select { max-width: 100%; }
  .link-back { margin-bottom: 6px; }

  /* -- Estructura ---------------------------------------------------------- */
  .page-head { flex-direction: column; align-items: stretch; }
  /* Los controles de cabecera se apilan a lo ancho: alineados a la derecha
     quedaban flotando sueltos en su propia línea. */
  .page-head-tools { flex-direction: column; align-items: stretch; }
  .dash-periodo { justify-content: space-between; min-height: 46px; }
  /* En obra: el botón de PDF a lo ancho y el estado debajo, al alcance del pulgar */
  .detalle-acciones { flex-direction: column; align-items: stretch; width: 100%; }
  .fase-badge { width: 100%; justify-content: center; }
  .fase-badge-texto { align-items: center; }
  .fase-badge-nombre { max-width: none; }
  .fase-menu { left: 16px !important; right: 16px; width: auto; min-width: 0; }

  /* Con dos botones ya no caben junto al título en 390 px: bajan a su propia
     fila y se reparten el ancho, que además es como se pulsan en obra. */
  .hon-card-header { flex-wrap: wrap; }
  .hon-card-acciones { width: 100%; }
  .hon-card-acciones > .btn { flex: 1; justify-content: center; }
  .hon-cta-acciones { width: 100%; }
  .hon-cta-acciones > .btn { flex: 1; justify-content: center; }

  /* -- Certificaciones ------------------------------------------------------ */
  .cert-grid { grid-template-columns: 1fr; }
  .cert-hero { padding: 18px 16px; }
  .cert-hero-top { flex-direction: column; align-items: stretch; gap: 16px; }
  .cert-hero-campo { width: 100%; }
  /* En móvil los dos botones se apilan a todo el ancho: en obra se pulsan con
     el dedo y con guantes. */
  .cert-hero-btns { flex-direction: column; align-items: stretch; width: 100%; gap: 10px; }
  .cert-add-btn { width: 100%; }
  .cert-hero-valor { font-size: 28px; }
  /* La fila de capítulo se despliega en tres líneas: número + descripción,
     cifras, y las acciones en su propia línea. Con cuatro botones (subir,
     bajar, editar, eliminar) a 42px cada uno no caben junto a las cifras. */
  .cert-cap {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: 'num desc desc' 'num cifras cifras' 'num acciones acciones';
    gap: 10px 12px;
  }
  .cert-cap-num { grid-area: num; align-self: start; }
  .cert-cap-main { grid-area: desc; }
  .cert-cap-cifras { grid-area: cifras; flex-direction: row; align-items: baseline; justify-content: flex-start; gap: 10px; }
  .cert-cap-acciones { grid-area: acciones; }
  .cert-caps-head { flex-direction: column; align-items: stretch; gap: 6px; }
  .cert-pct-val { font-size: 22px; min-width: 88px; }
  .cert-cap-ro { grid-template-columns: auto minmax(0, 1fr); grid-template-areas: 'num desc' 'num cifras'; }
  .cert-cap-ro .cert-cap-cifras { grid-area: cifras; flex-direction: row; align-items: baseline; justify-content: flex-start; gap: 10px; }

  /* Fase 1: aviso y cierre */
  .cert-fase { flex-direction: column; gap: 10px; padding: 14px 16px; }
  .cert-cerrar { flex-direction: column; align-items: stretch; gap: 14px; padding: 16px; }
  .cert-cerrar .btn { width: 100%; }

  /* Histórico: número + mes arriba, las dos cifras debajo a lo ancho */
  .cert-hist-row {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: 'num mes chev' 'num cifras del';
    gap: 10px 12px;
  }
  .cert-hist-num { grid-area: num; align-self: start; }
  .cert-hist-main { grid-area: mes; }
  .cert-hist-cifras { grid-area: cifras; gap: 20px; }
  .cert-hist-stat { align-items: flex-start; min-width: 0; }
  .cert-hist-del { grid-area: del; align-self: center; }
  .cert-hist-chev { grid-area: chev; }

  /* Nueva certificación: cada capítulo pasa a ser una tarjeta con sus dos
     campos debajo; la fila de cabecera sobra y cada campo lleva su rótulo. */
  .cert-nc-cabecera { display: none; }
  .cert-nc-fila {
    grid-template-columns: auto minmax(0, 1fr) minmax(0, 1fr);
    grid-template-areas: 'num cap cap' 'num pem pem' 'num euros pct' 'num aviso aviso';
    gap: 10px 12px; padding: 14px 4px;
  }
  .cert-nc-fila .cert-cap-num { grid-area: num; align-self: start; }
  .cert-nc-cap { grid-area: cap; }
  .cert-nc-fila .cert-nc-pem { grid-area: pem; text-align: left; font-size: 19px; }
  .cert-nc-fila .campo-euros { grid-area: euros; }
  .cert-nc-fila .campo-pct { grid-area: pct; }
  .cert-nc-campo { display: flex; flex-direction: column; gap: 5px; }
  .cert-nc-campo-lbl { display: block; font-size: 11.5px; font-weight: 600; color: var(--muted); }
  .cert-nc-aviso { grid-area: aviso; }
  .cert-nc-cab { flex-direction: column; align-items: stretch; gap: 14px; }
  .cert-nc-total { flex-direction: column; align-items: stretch; gap: 14px; }

  /* Ver certificación: importe y avance del mes bajan a su propia línea */
  .cert-ver-fila {
    grid-template-columns: auto minmax(0, 1fr) auto;
    grid-template-areas: 'num cap cap' 'num datos datos';
    gap: 8px 12px;
  }
  .cert-ver-cabecera { display: none; }
  .cert-ver-fila .cert-cap-num { grid-area: num; align-self: start; }
  .cert-ver-fila .cert-nc-cap { grid-area: cap; }
  .cert-ver-importe, .cert-ver-acum, .cert-ver-pct, .cert-ver-delta {
    grid-area: datos; text-align: left; font-size: 13px;
  }
  /* Los cuatro datos comparten línea, separados y etiquetados por su color */
  .cert-ver-fila {
    grid-template-areas: 'num cap cap' 'num d1 d1' 'num d2 d2';
  }
  .cert-ver-importe { grid-area: d1; color: var(--muted); }
  .cert-ver-acum { grid-area: d1; justify-self: end; }
  .cert-ver-pct { grid-area: d2; }
  .cert-ver-delta { grid-area: d2; justify-self: end; }
  .cert-ver-mes { align-items: flex-start; }
  /* El rótulo del total se lleva su propia línea; debajo, el importe */
  .cert-ct-label { flex: 1 1 100%; }
  /* Las tres acciones del modal de alta se apilan; Terminar arriba del todo
     (es la acción principal), Salir al fondo (la de menos peso). */
  .cert-modal-actions { flex-direction: column-reverse; align-items: stretch; }
  .cert-modal-actions-right { flex-direction: column-reverse; width: 100%; }
  .cert-modal-actions .btn, .cert-modal-actions-right .btn { width: 100%; }
  .modal.modal-capitulo.con-lista { max-width: 100%; }

  /* Precios adicionales: cada entrada se apila; las cifras pasan a ocupar el
     ancho, y las pestañas de filtro se deslizan en horizontal. */
  .acceso-card { padding: 13px 15px; gap: 12px; }
  /* Baja a su propia línea bajo el texto, ceñido a su contenido: con
     `flex-basis: 100%` no contaba el gap del contenedor y se salía. */
  .acceso-card { flex-wrap: wrap; }
  .acceso-card-txt { flex: 1 1 100%; order: 0; }
  .acceso-card-aviso { order: 1; }
  .acceso-card-chev { order: 2; margin-left: auto; }
  .adic-item-cab { grid-template-columns: minmax(0, 1fr); }
  .adic-item-cifras { gap: 0; justify-content: space-between; }
  .adic-cifra { align-items: flex-start; text-align: left; }
  .adic-cifra:last-child { align-items: flex-end; text-align: right; }
  .adic-item-pie { gap: 12px; }
  .adic-visados { width: 100%; }
  .adic-visado { flex: 1 1 auto; justify-content: center; min-height: 38px; }
  /* La fecha y el plazo se quedan a la izquierda y los dos botones juntos a
     la derecha: con space-between el de editar quedaba suelto en mitad de
     la fila. En una columna estrecha, fecha y plazo se apilan aparte. */
  .adic-item-fin { width: 100%; justify-content: flex-end; flex-wrap: wrap; }
  .adic-meta { margin-right: auto; flex-direction: column; align-items: flex-start; gap: 3px; }
  .filtros-barra { flex-direction: column; align-items: stretch; gap: 10px; }
  /* Los cuatro filtros no caben en una línea: se reparten en dos. Deslizarlos
     en horizontal escondería «En trámite», que es justo el que más se usa. */
  /* Se empaquetan de izquierda a derecha en vez de estirarse: con un número
     impar de filtros, estirar dejaba la última fila con un botón enorme. */
  .filtro-tabs-wrap { align-items: stretch; width: 100%; }
  .filtro-tabs { width: 100%; overflow-x: visible; flex-wrap: wrap; }
  .filtro-tabs .seg-tab { padding: 8px 12px; }
  .filtro-busca { flex: none; }
  /* Los dos campos y sus porcentajes se apilan: no hay ancho para pares */
  .adic-form { grid-template-columns: 1fr; }
  .adic-check { flex: 1 1 100%; min-height: 46px; }
  .form-grid { grid-template-columns: 1fr; }
  .coste-fields.two { grid-template-columns: 1fr; }

  /* Fila de obra en dos líneas: el estado baja y nada desborda a lo ancho */
  .row-obra {
    grid-template-columns: 40px minmax(0, 1fr) auto;
    grid-template-areas: 'av enc del' 'av est est';
    gap: 8px 12px;
    padding: 14px 16px;
  }
  .row-obra .cell-avatar { grid-area: av; align-self: start; }
  .row-obra .cell-encargo { grid-area: enc; }
  .row-obra .cell-estado { grid-area: est; }
  .row-obra .cell-acciones { grid-area: del; align-self: start; }
  .row-obra .cell-fecha { display: none; }
  .obra-avatar { width: 36px; height: 36px; border-radius: var(--radius-sm); }
  .row-head { display: none; }

  /* Ficha de cliente en tres líneas: nombre arriba, y debajo el contacto y la
     ubicación a lo ancho. Con siete columnas en 390px el nombre se quedaba en
     cero y el texto se montaba encima del resto. */
  .row-cli {
    grid-template-columns: 40px minmax(0, 1fr) auto;
    grid-template-areas: 'av nom acc' 'av con con' 'av ubi tip';
    gap: 6px 12px;
    padding: 14px 16px;
  }
  .row-cli .cell-cli-avatar { grid-area: av; align-self: start; }
  .row-cli .cell-cli-nombre { grid-area: nom; }
  .row-cli .cell-cli-contacto { grid-area: con; }
  .row-cli .cell-cli-ubi { grid-area: ubi; display: block; }
  .row-cli .cell-cli-tipo { grid-area: tip; align-items: flex-end; }
  .row-cli .cell-cli-acciones { grid-area: acc; align-self: start; }
  /* El NIF pasa a la línea del nombre, junto a la persona de contacto: como
     dato suelto ocupaba una línea entera para tres caracteres. */
  .row-cli .cell-cli-nif { display: none; }
  .row-cli:not(.row-head) .cli-sub[data-nif]::after {
    content: ' · ' attr(data-nif);
    font-variant-numeric: tabular-nums;
  }
  .cli-avatar { width: 36px; height: 36px; }
  .cli-contacto { flex-direction: row; flex-wrap: wrap; gap: 4px 14px; }

  .seg-tabs { display: flex; width: 100%; overflow-x: auto; }
  .seg-tab { flex: 1; justify-content: center; }

  /* Ficha de obra: etiqueta encima del valor */
  .campo { grid-template-columns: minmax(0, 1fr) auto; gap: 4px 12px; }
  .campo-label { grid-column: 1 / -1; margin-bottom: 2px; }
  .inline-editor .field-input, .inline-combo { max-width: none; width: 100%; }

  /* Fichas de perfil: etiqueta encima del valor */
  .pf-header-main { flex-wrap: wrap; }
  .pf-head-actions { width: 100%; }
  .pf-head-actions .btn { flex: 1; justify-content: center; }
  .pf-row { grid-template-columns: minmax(0, 1fr); gap: 5px; align-items: start; }
  .pf-row.editing .pf-label { padding-top: 0; }
  .pf-card { padding: 20px 18px; }
  .card { padding: 22px 18px; }
  .form-card { padding: 6px 18px 20px; }

  /* Modal casi a pantalla completa, respetando los márgenes del dispositivo */
  .modal-overlay {
    padding: max(14px, var(--safe-t)) max(14px, var(--safe-r))
             max(14px, var(--safe-b)) max(14px, var(--safe-l));
  }
  .modal { padding: 22px 20px; }
  .modal-actions { flex-wrap: wrap; }
  .modal-actions .btn { flex: 1 1 auto; justify-content: center; }
  .modal-perfil { max-height: 92dvh; }
  .modal-perfil .form-grid { grid-template-columns: 1fr; }
  .modal-perfil > .modal-title { padding: 18px 20px 14px; font-size: 17px; }
  .modal-perfil-body { padding: 4px 20px; }
  .modal-perfil > .modal-actions { padding: 14px 20px 16px; }
  .perfil-error { padding: 12px 20px 0; }

  /* Campos con sufijo: se reparten el ancho y nunca recortan las cifras */
  .coste-field { flex-direction: column; align-items: stretch; gap: 9px; }
  /* Igual que arriba: en columna el `flex-basis` es altura, no anchura. */
  .coste-field-label, .coste-field-inputs { flex: 0 0 auto; }
  .coste-field-inputs { width: 100%; justify-content: flex-start; }
  /* Solo dentro de `.coste-field-inputs`, que es una fila: ahí el basis mide
     anchura. En honorarios el campo cuelga directo de `.coste-field`, que en
     móvil es una columna, y un basis en px se convertiría en altura. */
  .coste-field-inputs > .money-wrap { width: auto; flex: 1 1 148px; }
  .coste-field-inputs > .money-wrap.narrow { width: auto; flex: 1 1 130px; }
  .coste-field > .money-wrap { flex: 0 0 auto; width: 100%; }
  .coste-field-inputs .mini-select { flex: 1 1 130px; min-width: 0; }

  /* Conceptos dinámicos: nombre a línea completa, importes debajo */
  .soft-row > .field-input { flex: 1 1 100%; }
  .soft-row .money-wrap, .soft-row .money-wrap.narrow { flex: 1 1 130px; }
  .soft-row .mini-select { flex: 1 1 130px; min-width: 0; }

  /* Desglose: concepto arriba, «× N/año» debajo y el importe a la derecha.
     En una sola línea el concepto se quedaba en 16px de ancho. */
  .resumen-row {
    grid-template-columns: minmax(0, 1fr) auto;
    grid-template-areas: 'label val' 'pagos val';
    gap: 1px 12px;
  }
  .resumen-label { grid-area: label; }
  .resumen-pagos { grid-area: pagos; }
  .resumen-val { grid-area: val; align-self: center; }

  .tel-pais { width: 96px; }
  .notif-card { flex-wrap: wrap; padding: 16px 16px; }
  .notif-actions { width: 100%; justify-content: flex-end; }
  .aviso-costes { padding: 15px 16px; }
  .hero-card { padding: 22px 18px; }
  .hero-value { font-size: 36px; }
  .live-value { font-size: 34px; }
  .hon-hero { grid-template-columns: minmax(0, 1fr); gap: 16px; }
  .hon-card { padding: 20px 18px; }
  .hon-figure { padding: 16px 16px; }
  .hon-figure-value, .hon-big-input { font-size: 28px; }
  .danger-zone { justify-content: stretch; }
  .danger-zone .btn { width: 100%; }
  .cuenta-acciones { flex-direction: column; align-items: stretch; }

  /* ======================================================================= *
   *  Que el móvil se lea como la misma app que el escritorio
   *
   *  En escritorio los tres KPI van en fila y se abarcan de una mirada. Uno
   *  debajo de otro, cada uno ocupaba ~170px: hacían falta tres pantallas de
   *  desplazamiento para ver tres números, y el panel dejaba de parecer un
   *  panel. Aquí van en rejilla de dos, con el del medidor a lo ancho: se
   *  mantiene la misma jerarquía —cifra grande, etiqueta arriba, apunte
   *  debajo— en un tercio del alto.
   * ======================================================================= */
  .dash-kpis {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 12px;
  }
  /* El de «% aceptado» lleva medidor: a media caja la barra no se lee. */
  .dash-kpis > *:last-child { grid-column: 1 / -1; }
  .kpi { padding: 15px 15px 14px; }
  .kpi-top { margin-bottom: 10px; gap: 9px; }
  .kpi-chip { width: 32px; height: 32px; }
  .kpi-chip .icon { width: 16px; height: 16px; }
  .kpi-label { font-size: 11.5px; letter-spacing: 0.005em; }
  /* Tamaño atado al ancho de la pantalla, no fijo: a media caja, «873.950,00 €»
     a 23px pedía 153px y solo había 144, y se cortaba. Con `clamp` la cifra se
     ajusta sola en pantallas estrechas y no depende de que los importes de hoy
     tengan los dígitos de hoy. */
  .kpi-value { font-size: clamp(17px, 5.2vw, 22px); overflow-wrap: anywhere; }
  .kpi-sub { font-size: 11.5px; margin-top: 6px; }

  /* Objetivos de dedo. El proyecto se usa en obra, a veces con guantes: 32px
     es un blanco pequeño incluso a mano limpia. */
  .row-accion { width: 40px; height: 40px; }
  .row-accion .icon { width: 18px; height: 18px; }
  /* En escritorio el botón de borrar solo aparece al pasar el ratón. En el
     móvil no hay ratón que pasar: si se deja oculto, no hay forma de llegar
     a él. */
  .row-accion.row-delete { opacity: 1; }

  /* Pestañas de sección: ruedan de lado sin que se vea barra, pero dejando
     asomar la siguiente para que se note que hay más. */
  .tabs-seccion { scroll-snap-type: x proximity; }
  .tab-seccion { scroll-snap-align: start; }

  /* La barra de pestañas de abajo: la marca de la activa pasa de ser solo
     color a una pastilla, que se distingue de un vistazo y sin depender del
     naranja —que en la marca es punto de atención, no color de texto—. */
  .tab-item {
    position: relative;
    border-radius: 12px;
    transition: background 0.18s ease, color 0.18s ease;
  }
  .tab-item.active { background: var(--brand-softer); }
  .tab-item.active::after {
    content: ''; position: absolute; top: 4px; left: 50%;
    width: 16px; height: 2px; margin-left: -8px;
    border-radius: 2px; background: var(--brand);
  }
  /* Un «aquí no hay datos» no necesita el alto de un gráfico. En escritorio
     ese hueco cuadra las tres tarjetas de la fila; en el móvil, apiladas, solo
     es pantalla que hay que pasar para llegar a lo que sí tiene contenido. */
  .chart-empty { padding: 22px 8px; }

  /* Respuesta al dedo: sin `:hover` que valga en táctil, el único acuse de
     recibo posible es el del momento de pulsar. */
  .btn:active, .tab-item:active, .row-obra:active,
  .proy-card:active, .cert-card:active, .doc-card:active {
    transform: scale(0.985);
  }
  .btn, .tab-item, .row-obra, .proy-card, .cert-card, .doc-card {
    transition: transform 0.09s ease;
  }
}

@media (max-width: 760px) and (prefers-reduced-motion: reduce) {
  .btn, .tab-item, .row-obra, .proy-card, .cert-card, .doc-card { transition: none; }
  .btn:active, .tab-item:active, .row-obra:active,
  .proy-card:active, .cert-card:active, .doc-card:active { transform: none; }
}

/* ---- Móviles estrechos (≤400px) ----------------------------------------- */
@media (max-width: 400px) {
  .container { padding-left: max(13px, var(--safe-l)); padding-right: max(13px, var(--safe-r)); }
  .card { padding: 18px 15px; }
  .pf-card { padding: 18px 15px; }
  .form-card { padding: 4px 15px 18px; }
  .row-obra { padding: 13px 13px; }
  .bar-row { grid-template-columns: minmax(0, 96px) minmax(0, 1fr) auto; }
  .barlist.compact .bar-row { grid-template-columns: 1fr auto; }
  /* Los pares "coste × veces" se quedan en la misma línea: apilarlos dejaba
     el "×" suelto en mitad de la nada y una fila de 182px por cada gasto. */
  .coste-field-inputs:not(.cada) { flex-wrap: nowrap; gap: 8px; }
  .coste-field-inputs:not(.cada) > .money-wrap,
  .coste-field-inputs:not(.cada) > .money-wrap.narrow { flex: 1 1 0; width: auto; min-width: 0; }
  .coste-field-inputs.cada > .money-wrap,
  .coste-field-inputs.cada > .money-wrap.narrow { flex: 1 1 100%; }
  .coste-field-inputs.cada .cada-prefix { flex: 1 1 100%; }
  .soft-row .money-wrap, .soft-row .money-wrap.narrow, .soft-row .mini-select { flex: 1 1 100%; }
  .tab-item { font-size: 11.5px; }
  /* Los 26px de antes eran para un KPI a lo ancho de la pantalla. Ahora van
     de dos en dos, así que la cifra manda menos ancho y se ajusta sola. */
  .kpi-value { font-size: clamp(16px, 5.2vw, 21px); }
  .page-title { font-size: 23px; }
  .hero-value { font-size: 32px; }
  .donut-wrap, .donut { width: 148px; height: 148px; }
  .donut-total { font-size: 26px; }
  .tel-input { flex-wrap: wrap; }
  .tel-pais { width: 100%; }
  .tel-num { flex: 1 1 100%; }
}

/* ==========================================================================
   Mapa de obras (panel de control)
   ========================================================================== */
.mapa-card .chart-head { display: flex; align-items: baseline; justify-content: space-between; gap: 12px; }
.mapa-cuenta { font-size: 12.5px; color: var(--muted); white-space: nowrap; }

/* Alto fijo: el mapa no tiene contenido que lo estire, así que sin esto
   Leaflet lo mediría a 0 y no se vería nada. Más bajo en móvil, donde la
   pantalla es de por sí corta. */
.mapa-lienzo {
  height: 380px;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
  background: var(--surface-2);
  /* Leaflet numera sus capas por dentro con valores muy altos: 400 las
     teselas, 600 los pines, 650 los rótulos, 800 los botones de zoom. Sin
     esta línea el mapa no encierra esa numeración, y esos números compiten
     con los del resto de la página —donde la barra lateral, que tiene que
     flotar por encima del contenido para su submenú, vale 20—.

     Que hoy se vea bien depende de que algún elemento intermedio esté
     creando contexto de apilado por casualidad; el día que eso cambie, el
     mapa se pone por delante del submenú. `isolation` lo deja atado: las
     capas de Leaflet no salen de aquí, pase lo que pase por encima.

     Subir el z-index de la barra lateral NO vale como alternativa: tendría
     que pasar de 800 para ganar al mapa, y entonces taparía los diálogos,
     que están en 100. */
  isolation: isolate;
}

/* El pin: una gota (círculo con la esquina inferior en punta) del color del
   estado de la obra, para que el mapa se lea igual que las pastillas. */
.mapa-pin-wrap { background: none; border: none; }
.mapa-pin {
  display: block; width: 22px; height: 22px;
  border-radius: 50% 50% 50% 0;
  transform: rotate(-45deg);
  border: 2px solid #fff;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.35);
  background: var(--st-estudio);
  transition: transform 0.12s ease;
}
.mapa-pin-wrap:hover .mapa-pin,
.mapa-pin-wrap:focus .mapa-pin { transform: rotate(-45deg) scale(1.18); }

.mapa-pin-estudio { background: var(--st-estudio); }
/* Solo en el mapa: «Aprobada» se pinta en naranja de marca, distinto del
   --st-aprobada que usan las pastillas de estado en el resto de la app. */
.mapa-pin-aprobada { background: var(--brand); }
.mapa-pin-consultoria { background: var(--st-consultoria); }
.mapa-pin-ejecucion { background: var(--st-ejecucion); }
.mapa-pin-paralizada { background: var(--st-paralizada); }
.mapa-pin-finalizada { background: var(--st-finalizada); }
.mapa-pin-rechazada { background: var(--st-rechazada); }

/* Globo al pasar el cursor. Se le quita el estilo por defecto de Leaflet para
   que hable el mismo idioma visual que el resto de tarjetas. */
.mapa-tip.leaflet-tooltip {
  background: var(--surface);
  color: var(--ink);
  border: 1px solid var(--border);
  border-radius: var(--radius-sm);
  box-shadow: var(--shadow-sm);
  padding: 7px 10px;
  font-family: inherit;
  display: flex; flex-direction: column; gap: 2px;
}
.mapa-tip.leaflet-tooltip::before { border-top-color: var(--border); }
.mapa-tip strong { font-size: 13px; font-weight: 600; }
.mapa-tip-ref { font-size: 11px; color: var(--muted); }
.mapa-tip-estado { font-size: 11px; font-weight: 600; margin-top: 2px; }
.mapa-tip-estudio { color: var(--st-estudio); }
.mapa-tip-aprobada { color: var(--brand); }
.mapa-tip-consultoria { color: var(--st-consultoria); }
.mapa-tip-ejecucion { color: var(--st-ejecucion); }
.mapa-tip-paralizada { color: var(--st-paralizada); }
.mapa-tip-finalizada { color: var(--st-finalizada); }
.mapa-tip-rechazada { color: var(--st-rechazada); }

.leaflet-container a.leaflet-popup-close-button { color: var(--muted); }
.leaflet-container { font-family: inherit; background: var(--surface-2); }

/* Obras que no se han podido situar */
.mapa-pendientes { margin-top: 14px; }
.mapa-pendientes-head {
  display: flex; align-items: center; gap: 7px;
  font-size: 12.5px; font-weight: 600; color: var(--warn-ink);
  background: var(--warn-bg); border: 1px solid var(--warn-bd);
  border-radius: var(--radius-sm);
  padding: 8px 11px;
}
.mapa-pendientes-head svg { flex: none; }
.mapa-pendientes-lista { display: flex; flex-direction: column; gap: 1px; margin-top: 8px; }
.mapa-pendiente {
  display: flex; align-items: center; gap: 10px;
  width: 100%; text-align: left;
  background: none; border: none; cursor: pointer;
  font: inherit; color: var(--ink);
  padding: 10px 8px;
  border-radius: var(--radius-sm);
  min-height: 44px;                 /* objetivo táctil cómodo en obra */
  transition: background 0.12s;
}
.mapa-pendiente:hover { background: var(--surface-2); }
.mapa-pendiente-nombre { font-size: 13px; font-weight: 500; }
.mapa-pendiente-motivo { font-size: 11.5px; color: var(--muted); margin-left: auto; text-align: right; }
.mapa-pendiente .chev-right { flex: none; width: 15px; height: 15px; opacity: 0.5; }

/* Pista de «pulsa el mapa para hacer zoom». Aparece sola al rodar la rueda
   sobre un mapa que todavía no se ha pulsado, y se va sola. `pointer-events`
   a `none` para que no se coma el clic que justamente pide dar. */
.mapa-pista {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  z-index: 500;                     /* por encima de teselas y pines */
  pointer-events: none;
  background: rgba(28, 26, 23, 0.82);
  color: #fff;
  font-size: 13px; font-weight: 500;
  padding: 9px 15px;
  border-radius: 100px;
  white-space: nowrap;
  opacity: 0;
  transition: opacity 0.18s ease;
}
.mapa-pista.visible { opacity: 1; }

@media (max-width: 640px) {
  .mapa-lienzo { height: 260px; }
  /* El motivo no cabe al lado del nombre: baja a su propia línea. El `order`
     mantiene la flecha pegada al nombre, arriba; sin él caería suelta a una
     tercera línea, como si fuera otro elemento de la lista. */
  .mapa-pendiente { flex-wrap: wrap; gap: 2px 10px; }
  .mapa-pendiente-nombre { flex: 1; }
  .mapa-pendiente .chev-right { order: 1; }
  .mapa-pendiente-motivo { order: 2; margin-left: 0; width: 100%; text-align: left; }
}

/* Motivo técnico bajo el aviso de reconexión: útil para saber qué pasa,
   pero secundario respecto a la instrucción de qué hacer. */
.aviso-costes .aviso-detalle {
  margin-top: 4px;
  font-size: 12.5px;
  color: var(--muted);
}

/* Los datos en crudo, cuando el navegador no deja copiar solo */
.cuadre-crudo {
  width: 100%; min-height: 320px; resize: vertical;
  font-family: ui-monospace, SFMono-Regular, Menlo, monospace; font-size: 11.5px;
  line-height: 1.45; color: var(--ink-soft);
  border: 1px solid var(--border); border-radius: var(--radius-sm);
  padding: 10px; background: var(--surface-2);
}


/* ==========================================================================
 *  Ficha de obra: aprovechar el alto
 *
 *  En una obra se entra a mirar honorarios, avance y cashflow. Con los
 *  espacios de antes eso ocupaba pantalla y media larga, y las tres cifras de
 *  honorarios se llevaban 187px para tres números.
 *
 *  Todo lo que se aprieta aquí va con `clamp()` atado al ancho de la ventana,
 *  no con saltos en dos o tres medidas: el estudio trabaja desde el portátil
 *  de 13", un monitor de 27" y el móvil en obra, y entre esos tamaños hay de
 *  todo. Así el mismo ajuste sirve para cualquier ancho sin dejar huecos raros
 *  justo antes de cada salto.
 * ========================================================================== */
.detalle-obra .card {
  padding: clamp(15px, 1.9vw, 24px) clamp(15px, 2vw, 26px);
  margin-bottom: clamp(11px, 1.3vw, 16px);
}
.detalle-obra .hon-card { padding: clamp(15px, 1.9vw, 22px) clamp(15px, 2vw, 24px); }

/* Cabecera de honorarios: el mismo contenido, menos aire alrededor */
.detalle-obra .hon-card-header { padding-bottom: clamp(11px, 1.2vw, 15px); gap: 11px; }
.detalle-obra .hon-chip { width: 34px; height: 34px; }
.detalle-obra .hon-chip .icon { width: 17px; height: 17px; }

/* Las tres cifras: lo que más alto se llevaba.
   El mínimo de columna baja de 200 a 184px para que en pantallas medianas las
   tres sigan cabiendo en una fila en vez de partirse en dos. */
.detalle-obra .hon-hero {
  grid-template-columns: repeat(auto-fit, minmax(184px, 1fr));
  gap: clamp(10px, 1.1vw, 14px);
  padding: clamp(12px, 1.4vw, 17px) 0;
}
.detalle-obra .hon-figure { padding: clamp(11px, 1.2vw, 15px) clamp(13px, 1.4vw, 17px); gap: 7px; }
/* La cifra crece con la pantalla en vez de imponer 33px también en un portátil */
.detalle-obra .hon-figure-value,
.detalle-obra .hon-big-input { font-size: clamp(23px, 2.35vw, 31px); }
.detalle-obra .hon-cur { font-size: clamp(15px, 1.5vw, 19px); }

.detalle-obra .hon-composition { padding-top: clamp(12px, 1.4vw, 17px); }
.detalle-obra .hon-bar { margin: 10px 0 12px; }
.detalle-obra .hon-servicios { margin-top: clamp(11px, 1.2vw, 15px); padding: 11px 13px; }
.detalle-obra .hon-servicios-list { margin-top: 8px; gap: 7px; }
.detalle-obra .hon-servicio-chip { padding: 5px 12px; }

/* Cashflow dentro de la ficha */
.detalle-obra .cf-resumen { gap: 9px; }
.detalle-obra .cf-inicio { padding: 9px 12px; }
.detalle-obra .cf-cab { margin-bottom: 12px; }

/* Cabecera de la pantalla y zona de borrado */
.detalle-obra .page-head { margin-bottom: clamp(12px, 1.4vw, 18px); }
.detalle-obra .danger-zone { margin-top: clamp(8px, 1vw, 14px); }

/* En el móvil manda el dedo por encima de la densidad: los botones y las
   casillas mantienen su altura, y solo se recorta el aire de alrededor. */
@media (max-width: 760px) {
  .detalle-obra .hon-figure { padding: 13px 14px; }
  .detalle-obra .hon-hero { gap: 10px; padding: 13px 0; }
}

/* ---- Filtro por año del cashflow ---------------------------------------- *
 * Pastillas en vez de un desplegable: son cuatro opciones fijas y cortas, y
 * así se ve de un vistazo cuál está puesta sin tener que abrir nada.
 * -------------------------------------------------------------------------- */
.cf-filtro {
  display: flex; gap: 4px; flex-wrap: wrap;
  padding: 4px; margin: 0 0 14px;
  background: var(--surface-2); border-radius: var(--radius);
  width: fit-content; max-width: 100%;
}
.cf-filtro-op {
  padding: 7px 15px; min-height: 38px;
  display: inline-flex; align-items: center;
  border: 0; border-radius: calc(var(--radius) - 5px);
  background: transparent; color: var(--muted);
  font-family: inherit; font-size: 13.5px; font-weight: 600;
  font-variant-numeric: tabular-nums; cursor: pointer; white-space: nowrap;
  transition: background 0.15s, color 0.15s, box-shadow 0.15s;
}
.cf-filtro-op:hover { color: var(--ink); }
.cf-filtro-op.activo {
  background: var(--surface); color: var(--ink);
  box-shadow: var(--shadow-sm);
}
.cf-filtro-op:focus-visible { outline: 2px solid var(--ring); outline-offset: 1px; }

/* El subtotal del tramo, al lado de las otras dos cifras del resumen */
.cf-cifra-tramo .cf-cifra-val { color: var(--brand-ink); }

/* Cuando el tramo elegido no tiene ningún mes */
.cf-sin-tramo {
  display: flex; flex-direction: column; align-items: flex-start; gap: 10px;
  padding: 18px 2px 4px;
}
.cf-sin-tramo p { margin: 0; color: var(--muted); font-size: 14px; }

/* En el móvil las pastillas ocupan el ancho y se reparten por igual */
@media (max-width: 560px) {
  .cf-filtro { width: 100%; }
  .cf-filtro-op { flex: 1; justify-content: center; padding: 7px 8px; }
}

/* ==========================================================================
 *  Gráfico de cashflow: la curva de cobros, mes a mes
 *
 *  Línea suave con un velo degradado debajo. La rejilla es de filetes finos y
 *  continuos, con las cifras en un margen propio a la izquierda para que
 *  nunca se monten sobre la curva. Los puntos, la guía y el cuadro de cada
 *  mes van en HTML encima del dibujo, que se estira al ancho de la tarjeta.
 * ========================================================================== */
.cfx { --cfx-margen: 64px; margin: 2px 0 18px; }
/* El alto incluye la banda de los meses: si solo midiera el dibujo, las
   etiquetas quedarían fuera y la tarjeta criaría su propio scroll. */
.cfx-lienzo { position: relative; height: 220px; }
.cfx-rejilla, .cfx-plano, .cfx-cols {
  position: absolute; top: 10px; bottom: 28px; left: var(--cfx-margen); right: 6px;
}
.cfx-rejilla { pointer-events: none; }
/* Filetes continuos, nunca discontinuos: el punteado se leería como umbral. */
.cfx-linea { position: absolute; left: 0; right: 0; border-top: 1px solid var(--border); opacity: 0.7; }
.cfx-linea.base { border-top-color: var(--border-strong, var(--border)); opacity: 1; }
.cfx-tick {
  position: absolute; right: calc(100% + 10px); top: -8px;
  font-size: 11px; line-height: 16px; color: var(--muted-2); white-space: nowrap;
  font-variant-numeric: tabular-nums;
}

.cfx-plano { pointer-events: none; }
.cfx-svg { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; }

/* ---- La gráfica de tres series (estilo «Objetivos» de Holded) ----------- */
/* Los colores de las series pasaron el validador de paletas (también en
   daltonismo, por parejas); el porqué, en cashflow.js. La gráfica mide su
   propio ancho (no el de la pantalla): la misma va en la ficha de una obra y
   en la pantalla de todas, con anchos muy distintos. */
.cfx3 { --cfx-ing: #1b7f4b; --cfx-gas: #ef7a45; --cfx-res: #2c5fd0; --cfx-margen: 44px; container-type: inline-size; }
.cfx3-cuerpo { display: flex; flex-direction: column; gap: 14px; }
.cfx3-grafica { min-width: 0; }
.cfx3 .cfx-lienzo { height: 230px; }

/* La columna de la cifra. En estrecho va encima, con los botones a su
   derecha; en ancho, a la izquierda de la gráfica, como en Holded. */
.cfx3-cab { display: flex; align-items: flex-end; justify-content: space-between; flex-wrap: wrap; gap: 12px 16px; }
.cfx3-hero { display: flex; flex-direction: column; min-width: 0; }
.cfx3-periodo { font-size: 12.5px; color: var(--muted-2); margin-bottom: 6px; }
.cfx3-hero-lbl { font-size: 13.5px; font-weight: 600; color: var(--muted); }
.cfx3-hero-val {
  font-size: 28px; line-height: 1.2; font-weight: 700; color: var(--ink);
  font-variant-numeric: tabular-nums; letter-spacing: -0.015em;
}
.cfx3-hero-val.neg { color: var(--danger); }
.cfx3-hero-sub { margin-top: 2px; font-size: 12.5px; color: var(--muted); font-variant-numeric: tabular-nums; }

@container (min-width: 720px) {
  .cfx3-cuerpo { display: grid; grid-template-columns: 196px minmax(0, 1fr); gap: 28px; align-items: start; }
  .cfx3-cab { flex-direction: column; align-items: flex-start; justify-content: flex-start; gap: 18px; padding-top: 4px; }
  /* Dos renglones siempre, quepa en uno o no: al cambiar de serie el texto
     cambia de largo y, sin esto, el selector de debajo daría un salto. */
  .cfx3-hero-sub { min-height: calc(2 * 1.45em); line-height: 1.45; }
  .cfx3 .cfx-lienzo { height: 260px; }
}

/* El selector: «Previsión» y un botón cuadrado por serie. Cuando se conecte
   con Holded, «Real» será otro igual al lado. */
.cfx3-series {
  display: inline-flex; align-items: center; gap: 2px;
  padding: 3px 3px 3px 12px;
  border: 1px solid var(--border); border-radius: 12px; background: var(--surface);
}
.cfx3-escenario { margin-right: 6px; font-size: 12.5px; font-weight: 600; color: var(--muted); }
.cfx3-serie {
  --c: var(--muted); position: relative;
  display: inline-flex; align-items: center; justify-content: center;
  width: 38px; height: 38px; padding: 0; border: 0; border-radius: 9px;
  background: transparent; cursor: pointer; transition: background 0.12s, box-shadow 0.12s;
}
.cfx3-serie.ing { --c: var(--cfx-ing); }
.cfx3-serie.gas { --c: var(--cfx-gas); }
.cfx3-serie.res { --c: var(--cfx-res); }
.cfx3-serie:hover { background: var(--surface-2, #f4f1ee); }
.cfx3-serie.on { background: color-mix(in srgb, var(--c) 13%, transparent); box-shadow: inset 0 0 0 1.5px var(--c); }
.cfx3-serie:focus-visible { outline: none; box-shadow: 0 0 0 3px var(--ring); }
/* El nombre, en un globo encima al pasar el ratón (o con el tabulador). */
.cfx3-serie::after {
  content: attr(data-nombre); position: absolute; bottom: calc(100% + 8px); left: 50%;
  transform: translate(-50%, 3px); padding: 5px 9px; border-radius: 7px;
  background: #2b2626; color: #fff; font-size: 12px; font-weight: 600; white-space: nowrap;
  opacity: 0; pointer-events: none; transition: opacity 0.12s, transform 0.12s; z-index: 4;
}
@media (hover: hover) { .cfx3-serie:hover::after { opacity: 1; transform: translate(-50%, 0); } }
.cfx3-serie:focus-visible::after { opacity: 1; transform: translate(-50%, 0); }

/* El icono de cada serie: blanco sobre su color, en cuadrado redondeado. Lo
   comparten los botones y el cuadro. */
.cfx3-ico {
  display: inline-flex; align-items: center; justify-content: center; flex: none;
  width: 24px; height: 24px; border-radius: 6px; color: #fff; background: var(--muted);
}
.cfx3-ico svg { width: 14px; height: 14px; }
.cfx3-ico.ing, .cfx3-serie.ing .cfx3-ico { background: var(--cfx-ing); }
.cfx3-ico.gas, .cfx3-serie.gas .cfx3-ico { background: var(--cfx-gas); }
.cfx3-ico.res, .cfx3-serie.res .cfx3-ico { background: var(--cfx-res); }

/* El cero, más marcado que el resto de la rejilla: por debajo, pérdidas. */
.cfx-linea.cero { border-top-color: var(--muted-2); opacity: 1; }

/* Las líneas: tramos rectos; lo que está por venir, discontinuo. La serie
   destacada va gruesa y al frente; las otras dos, finas y claras. */
.cfx3-trazo {
  fill: none; stroke-width: 1.5; stroke-linecap: round; stroke-linejoin: round; opacity: 0.3;
  transition: opacity 0.15s, stroke-width 0.15s;
}
.cfx3-trazo.ing { stroke: var(--cfx-ing); }
.cfx3-trazo.gas { stroke: var(--cfx-gas); }
.cfx3-trazo.res { stroke: var(--cfx-res); }
.cfx3-trazo.futuro { stroke-dasharray: 4 5; }
.cfx3[data-foco="ing"] .cfx3-trazo.ing,
.cfx3[data-foco="gas"] .cfx3-trazo.gas,
.cfx3[data-foco="res"] .cfx3-trazo.res { opacity: 1; stroke-width: 2.5; }
.cfx3[data-foco="ing"] .cfx3-trazo.ing.futuro,
.cfx3[data-foco="gas"] .cfx3-trazo.gas.futuro,
.cfx3[data-foco="res"] .cfx3-trazo.res.futuro { opacity: 0.8; }

/* El área de la serie destacada, de la línea al cero. Lo que viene, más
   tenue todavía. */
.cfx3-area { stroke: none; opacity: 0; transition: opacity 0.15s; }
.cfx3-area.ing { fill: var(--cfx-ing); }
.cfx3-area.gas { fill: var(--cfx-gas); }
.cfx3-area.res { fill: var(--cfx-res); }
.cfx3[data-foco="ing"] .cfx3-area.ing,
.cfx3[data-foco="gas"] .cfx3-area.gas,
.cfx3[data-foco="res"] .cfx3-area.res { opacity: 0.12; }
.cfx3[data-foco="ing"] .cfx3-area.ing.futuro,
.cfx3[data-foco="gas"] .cfx3-area.gas.futuro,
.cfx3[data-foco="res"] .cfx3-area.res.futuro { opacity: 0.05; }

/* Los puntos, solo en la serie destacada: 8px con un aro del color de la
   tarjeta, que los despega de la línea y de la rejilla. */
.cfx3-punto {
  position: absolute; width: 8px; height: 8px; margin: 0 0 -4px -4px;
  border-radius: 50%; box-shadow: 0 0 0 2px var(--surface); opacity: 0; transition: opacity 0.15s;
}
.cfx3-punto.ing { background: var(--cfx-ing); }
.cfx3-punto.gas { background: var(--cfx-gas); }
.cfx3-punto.res { background: var(--cfx-res); }
.cfx3[data-foco="ing"] .cfx3-punto.ing,
.cfx3[data-foco="gas"] .cfx3-punto.gas,
.cfx3[data-foco="res"] .cfx3-punto.res { opacity: 1; }
.cfx3[data-foco="ing"] .cfx3-punto.ing.futuro,
.cfx3[data-foco="gas"] .cfx3-punto.gas.futuro,
.cfx3[data-foco="res"] .cfx3-punto.res.futuro { opacity: 0.8; }

/* La franja del mes señalado: un sombreado que ocupa toda la columna. */
.cfx3-franja {
  position: absolute; top: 0; bottom: 0; border-radius: 6px;
  background: var(--ink); opacity: 0; transition: opacity 0.12s, left 0.12s ease-out;
}
.cfx-plano.activo .cfx3-franja { opacity: 0.05; }

/* El cuadro: oscuro, como el de Holded, para que se lea encima de las
   líneas sin confundirse con la tarjeta. Las tres series, con la destacada
   al frente y las otras un punto apagadas. */
.cfx-tip {
  position: absolute; top: 2px;
  display: flex; flex-direction: column; gap: 5px;
  min-width: 150px; padding: 9px 12px 10px;
  background: #2b2626; border-radius: 10px;
  box-shadow: 0 8px 22px rgba(48, 41, 41, 0.22);
  font-size: 12.5px; color: rgba(255, 255, 255, 0.78); white-space: nowrap;
  opacity: 0; transition: opacity 0.12s, left 0.12s ease-out; z-index: 3;
}
.cfx-plano.activo .cfx-tip { opacity: 1; }
.cfx3-tip-mes { font-size: 11px; font-weight: 600; letter-spacing: 0.05em; text-transform: uppercase; color: rgba(255, 255, 255, 0.6); }
.cfx3-tip-fila { display: flex; align-items: center; gap: 8px; opacity: 0.6; }
.cfx3[data-foco="ing"] .cfx3-tip-fila.ing,
.cfx3[data-foco="gas"] .cfx3-tip-fila.gas,
.cfx3[data-foco="res"] .cfx3-tip-fila.res { opacity: 1; }
.cfx3-tip .cfx3-ico { width: 18px; height: 18px; border-radius: 5px; }
.cfx3-tip .cfx3-ico svg { width: 11px; height: 11px; }
.cfx3-tip-fila strong { margin-left: auto; padding-left: 14px; font-size: 13.5px; font-weight: 700; color: #fff; font-variant-numeric: tabular-nums; }
.cfx3-tip-real { font-weight: 500; color: rgba(255, 255, 255, 0.6); }
.cfx3-tip-nota { margin-top: 2px; font-size: 11px; color: rgba(255, 255, 255, 0.5); }

/* Las franjas de cada mes: el blanco del ratón, el dedo y el tabulador. */
.cfx-cols { display: flex; }
.cfx-col { flex: 1; min-width: 0; position: relative; cursor: default; border-radius: 6px; outline: none; }
.cfx-col:focus-visible { box-shadow: inset 0 0 0 2px var(--ring); }
.cfx-etiq {
  position: absolute; left: 50%; top: calc(100% + 9px); transform: translateX(-50%);
  font-size: 10.5px; font-weight: 600; letter-spacing: 0.06em;
  color: var(--muted-2); white-space: nowrap;
}
.cfx-etiq.oculta { visibility: hidden; }
.cfx-col.hoy .cfx-etiq { color: var(--brand-ink); }

.cfx-vacio { padding: 20px 2px 14px; }
.cfx-vacio p { margin: 0; font-size: 13.5px; color: var(--muted-2); }

/* En pantallas estrechas se achica, pero no por debajo de lo que se lee. */
@media (max-width: 560px) {
  .cfx { --cfx-margen: 52px; }
  .cfx-lienzo { height: 176px; }
  .cfx-tick { font-size: 10px; right: calc(100% + 7px); }
  .cfx-etiq { font-size: 9.5px; letter-spacing: 0.03em; }
  .cfx3 { --cfx-margen: 38px; }
  .cfx3 .cfx-lienzo { height: 200px; }
  .cfx3-hero-val { font-size: 24px; }
}
@media (prefers-reduced-motion: reduce) {
  .cfx3-franja, .cfx-tip, .cfx3-serie, .cfx3-serie::after, .cfx3-trazo, .cfx3-area, .cfx3-punto { transition: none; }
}
