﻿/* Sistema de diseño. Todo lo visual sale de estas variables: cambiar aquí cambia
   la app entera y evita los valores sueltos repartidos por la hoja. */
:root {
  /* Superficies: escalonadas de fondo a primer plano, para que los paneles
     apilados se distingan sin necesidad de bordes gruesos. */
  --bg: #0d1119; --panel: #151b27; --panel-2: #1c2433; --panel-3: #232c3e;
  --line: #2a3346; --line-soft: #212a3a;
  --text: #eef2f8; --text-2: #c3ccdd; --muted: #8b97ae;
  --accent: #4c8dff; --accent-soft: rgba(76,141,255,.14); --accent-line: rgba(76,141,255,.45);
  --accent-2: #2fbf8c; --danger: #ff5f6d; --warn: #ffb547;
  /* Radios y sombras coherentes: un solo lenguaje de formas. */
  --r-sm: 6px; --r: 9px; --r-lg: 14px; --radius: 9px;
  --sh-1: 0 1px 2px rgba(0,0,0,.28);
  --sh-2: 0 4px 14px rgba(0,0,0,.32);
  --sh-3: 0 14px 40px rgba(0,0,0,.45);
  --ease: cubic-bezier(.2,.7,.3,1);
  --canvas-bg: #0b0f18;
  --scroll: #33405e; --scroll-hover: #46567c;
}

/* TEMA CLARO. No es un adorno: un plano se enseña y se imprime en blanco, y hay
   quien trabaja a pleno sol en obra. Se activa con `data-theme="claro"` en <html>
   (lo pone `main.js`), y el LIENZO tiene su propia paleta en `editor/theme.js`
   porque el canvas no entiende de variables CSS. */
:root[data-theme="claro"] {
  --bg: #eef1f7; --panel: #ffffff; --panel-2: #f4f6fb; --panel-3: #e8edf6;
  --line: #d8dfec; --line-soft: #e7ecf5;
  --text: #131a26; --text-2: #3c4658; --muted: #6a7588;
  --accent: #1f6fe5; --accent-soft: rgba(31,111,229,.10); --accent-line: rgba(31,111,229,.42);
  --accent-2: #0d9465; --danger: #d93a45; --warn: #b57500;
  --sh-1: 0 1px 2px rgba(20,30,50,.07);
  --sh-2: 0 4px 14px rgba(20,30,50,.10);
  --sh-3: 0 16px 44px rgba(20,30,50,.18);
  --canvas-bg: #f5f7fb;
  --scroll: #c3ccdc; --scroll-hover: #a8b3c8;
}
/* La transición hace que el cambio no dé un latigazo. Solo en superficies. */
body, #topbar, .card, .toolbar, .palette, .right, .tabbar, .modal, .ctxmenu {
  transition: background-color .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
* { box-sizing: border-box; }
html, body { height: 100%; }
body {
  margin: 0; background: var(--bg); color: var(--text);
  font: 14.5px/1.55 system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", sans-serif;
  -webkit-font-smoothing: antialiased;
  /* Cifras de ancho fijo: las medidas y los precios no bailan al cambiar. */
  font-variant-numeric: tabular-nums;
}
a { color: var(--accent); text-decoration: none; }
.muted { color: var(--muted); }
.spacer { flex: 1; }

/* FOCO VISIBLE en todo lo interactivo. Faltaba: con el teclado no se sabía dónde
   estabas, y es lo primero que se nota en una auditoría de accesibilidad. */
:where(button, a, input, select, textarea, [tabindex]):focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 2px;
  border-radius: var(--r-sm);
}
::selection { background: var(--accent-soft); }

/* `hidden` GANA SIEMPRE. Ésta es la CUARTA vez que el mismo fallo cuesta un rato: el
   `display: none` que el navegador le da a `[hidden]` viene de su hoja de estilos, así
   que CUALQUIER regla nuestra con `display` (y media hoja lo lleva: flex, grid,
   inline-grid…) lo pisa, y `el.hidden = true` deja el elemento en pantalla. Cuando
   apareció se parcheó suelto —`.impersonando[hidden]`, `.enl-tabla[hidden]`—, y así se
   siguió cazando de uno en uno: la barra de arriba seguía puesta en la pantalla de
   entrar, la chapa del aviso de capas ocultas salía siempre vacía, y el aviso con acción
   no se iba ni con el aspa, ni con Esc, ni a los 9,6 s. Con `!important` se acaba la
   familia entera, presente y futura: si algo lleva `hidden`, no se ve. */
[hidden] { display: none !important; }

/* Scrollbars personalizadas */
* { scrollbar-width: thin; scrollbar-color: var(--scroll) transparent; }
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--scroll); border-radius: 8px; border: 2px solid var(--panel); background-clip: padding-box; }
::-webkit-scrollbar-thumb:hover { background: var(--scroll-hover); background-clip: padding-box; }
::-webkit-scrollbar-corner { background: transparent; }

/* Topbar */
#topbar {
  display: flex; align-items: center; gap: 14px; padding: 9px 18px;
  background: var(--panel); border-bottom: 1px solid var(--line);
  position: sticky; top: 0; z-index: 20; box-shadow: var(--sh-1);
}
.brand { display: inline-flex; align-items: center; gap: 8px; font-weight: 700; color: var(--text); letter-spacing: -.01em; }
.brand svg { color: var(--accent); }
.nav-tit { display: inline-flex; align-items: center; gap: 5px; }
#crumbs { display: flex; align-items: center; gap: 8px; color: var(--muted); }
#crumbs .sep { opacity: .5; }
#whoami { font-size: 13px; }

/* Layout */
#app { min-height: calc(100% - 52px); }
/* 1100 px se quedaba corto en cuanto la tarjeta llevó dibujo: en una pantalla normal
   sobraba medio ancho de pantalla vacío a los lados y las tarjetas salían apretadas. */
.page { max-width: 1240px; margin: 0 auto; padding: 24px 18px 60px; }
.page-head { display: flex; align-items: center; justify-content: space-between; gap: 16px; margin-bottom: 18px; }
.page-head h2 { margin: 0; }
.page-acts { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; }
.center { min-height: 100%; display: grid; place-items: center; padding: 24px; }
.loading { padding: 40px; text-align: center; color: var(--muted); }

/* ===========================================================================
   PANTALLA DE ENTRADA. Era una cajita de 380 px flotando arriba del todo, con un
   emoji por logotipo. Es lo primero que ve alguien que abre esto, y decía «proyecto
   de fin de semana» antes de que nadie tocara nada.

   Partida en dos: a la izquierda lo que hace la herramienta sobre una retícula de
   plano (hecha con gradientes: ni una imagen que descargar), a la derecha el
   formulario. En móvil el lado izquierdo se pliega y queda solo la entrada, que es
   lo único imprescindible.
   =========================================================================== */
/* `100vh` y no `100%`: en la pantalla de entrar la barra de arriba está oculta, así
   que la página ES la ventana. Con `100%` la mitad de abajo quedaba en blanco, porque
   un porcentaje contra un padre sin altura fija no resuelve. */
.auth { min-height: 100vh; display: grid; grid-template-columns: 1.15fr .85fr; }
.auth-lado {
  position: relative; overflow: hidden; padding: 54px clamp(28px, 5vw, 72px);
  display: flex; flex-direction: column; justify-content: center; gap: 18px;
  background:
    radial-gradient(120% 90% at 12% 0%, var(--accent-soft), transparent 60%),
    linear-gradient(160deg, var(--panel-2), var(--bg) 70%);
  border-right: 1px solid var(--line);
}
/* La retícula del plano, de fondo y muy tenue: es el producto, no un adorno. */
.auth-plano {
  position: absolute; inset: 0; pointer-events: none; opacity: .5;
  background-image:
    linear-gradient(var(--line-soft) 1px, transparent 1px),
    linear-gradient(90deg, var(--line-soft) 1px, transparent 1px);
  background-size: 46px 46px, 46px 46px;
  -webkit-mask-image: radial-gradient(80% 70% at 70% 90%, #000, transparent 75%);
          mask-image: radial-gradient(80% 70% at 70% 90%, #000, transparent 75%);
  z-index: 0;
}
.auth-lado > *:not(.auth-plano) { position: relative; z-index: 1; }
.auth-marca { display: inline-flex; align-items: center; gap: 10px; font-size: 19px; font-weight: 700; letter-spacing: -.02em; }
.auth-logo {
  display: grid; place-items: center; width: 38px; height: 38px; border-radius: 11px;
  background: var(--accent); color: #fff; box-shadow: var(--sh-2);
}
.auth-lado h1 {
  margin: 6px 0 0; font-size: clamp(28px, 3.4vw, 42px); line-height: 1.1;
  letter-spacing: -.03em; max-width: 12em;
}
.auth-claim { margin: 0; max-width: 34em; color: var(--text-2); font-size: 15.5px; }
.auth-puntos { list-style: none; margin: 10px 0 0; padding: 0; display: grid; gap: 12px; max-width: 30em; }
.auth-puntos li { display: flex; align-items: flex-start; gap: 11px; }
.auth-puntos svg { color: var(--accent); flex: none; margin-top: 2px; }
.auth-puntos strong { display: block; font-size: 14.5px; }
.auth-puntos span span { color: var(--muted); font-size: 13px; }

.auth-caja { display: grid; align-content: center; justify-items: stretch; padding: 40px clamp(20px, 4vw, 56px); }
.auth-form { width: min(380px, 100%); margin: 0 auto; }
.auth-form h2 { margin: 0 0 6px; font-size: 22px; letter-spacing: -.02em; }
.btn.big { width: 100%; margin-top: 18px; padding: 11px 16px; font-size: 15px; }
.auth-demos { width: min(380px, 100%); margin: 22px auto 0; display: grid; gap: 8px; }
/* Separador con texto: dos líneas y la frase en medio. */
.auth-sep { display: flex; align-items: center; gap: 10px; margin: 0 0 4px; color: var(--muted); font-size: 12px; }
.auth-sep::before, .auth-sep::after { content: ''; flex: 1; height: 1px; background: var(--line); }
.auth-demo {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  padding: 10px 13px; cursor: pointer; color: var(--text);
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
  font: inherit; transition: border-color .14s var(--ease), background .14s var(--ease), transform .14s var(--ease);
}
.auth-demo:hover { border-color: var(--accent-line); background: var(--panel-2); transform: translateY(-1px); }
.auth-demo svg { color: var(--accent); flex: none; }
.auth-demo strong { display: block; font-size: 14px; }
.auth-demo .small { display: block; line-height: 1.35; }
@media (max-width: 880px) {
  .auth { grid-template-columns: 1fr; }
  .auth-lado { display: none; }
}

/* ===========================================================================
   CABECERA DE PÁGINA CON CIFRAS. Una lista de proyectos que solo dice el nombre
   obliga a entrar en cada uno para saber cuál es cuál. Las cifras van arriba,
   grandes, y salen del MISMO modelo que el plano (m² del recinto, no un campo que
   alguien teclea y se queda viejo).
   =========================================================================== */
.hero { margin-bottom: 22px; }
.hero-top { display: flex; align-items: flex-start; justify-content: space-between; gap: 16px; flex-wrap: wrap; }
.hero h2 { margin: 0; font-size: 26px; letter-spacing: -.025em; }
.hero .sub { margin: 4px 0 0; color: var(--muted); }
.stats { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 16px; }
.stat {
  flex: 1 1 130px; min-width: 120px; padding: 11px 14px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
}
.stat b { display: block; font-size: 21px; line-height: 1.15; letter-spacing: -.02em; }
.stat span { display: block; margin-top: 2px; font-size: 12px; color: var(--muted); }
.stat.acc b { color: var(--accent); }
.stat.ok b { color: var(--accent-2); }

/* Cards / grid */
.grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); gap: 14px; }
.card {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 16px 18px; display: block; color: var(--text);
  transition: border-color .16s var(--ease), transform .16s var(--ease), box-shadow .16s var(--ease);
}
a.card:hover {
  border-color: var(--accent-line); transform: translateY(-2px); box-shadow: var(--sh-2);
}
.card h3 { margin: 0 0 6px; }
.badge {
  display: inline-flex; align-items: center; gap: 5px; margin-top: 10px; padding: 3px 9px; font-size: 12px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 999px; color: var(--muted);
}
.card .open { display: block; margin-top: 12px; color: var(--accent); font-size: 13px; }

/* Tarjeta de ESTANCIA con vista previa del plano. La miniatura es un SVG hecho
   con la geometría real, así que siempre está al día y pesa nada. */
.card.room.with-prev, .card.room { padding: 0; overflow: hidden; }
.card.room .prev {
  display: block; background: var(--canvas-bg); border-bottom: 1px solid var(--line);
  color: var(--text-2); padding: 6px;
}
.card.room .plan-prev { display: block; width: 100%; height: 132px; }
.card.room .prev-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; height: 132px; color: var(--muted); font-size: 12px;
}
.card.room .room-meta { padding: 12px 14px 14px; }
.card.room .room-meta h3 { margin: 0 0 8px; font-size: 15.5px; }
.card.room .room-meta .badge { margin: 0 5px 0 0; }
.card.room .card-acts { top: 8px; right: 8px; }
.card.room:hover .plan-prev { color: var(--accent); }
.grid { grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); }

/* TARJETA DE PROYECTO con la planta de su estancia mayor. Mismo argumento que en las
   estancias: el dibujo se reconoce antes que cualquier texto, y sale de la geometría
   real, así que no hay nada que mantener al día. */
.card.project { padding: 0; overflow: hidden; display: flex; flex-direction: column; }
.card.project .prev {
  display: block; background: var(--canvas-bg); border-bottom: 1px solid var(--line);
  color: var(--text-2); padding: 6px; transition: color .16s var(--ease);
}
.card.project .plan-prev { display: block; width: 100%; height: 112px; }
.card.project:hover .plan-prev { color: var(--accent); }
.card.project .prev-empty {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 6px; height: 112px; color: var(--muted); font-size: 12px;
}
.card.project .proj-meta { padding: 13px 15px 15px; display: flex; flex-direction: column; gap: 6px; flex: 1; }
.card.project .proj-meta h3 { margin: 0; font-size: 15.5px; }
.card.project .proj-meta .muted { margin: 0; font-size: 13px; }
.card.project .proj-cifras {
  margin-top: auto; padding-top: 10px; border-top: 1px solid var(--line-soft);
  display: flex; align-items: baseline; gap: 4px; flex-wrap: wrap; font-size: 12.5px; color: var(--muted);
}
.card.project .proj-cifras b { color: var(--text); font-weight: 600; }
.card.project .proj-cifras .sep { opacity: .45; }

/* Mandos de la tarjeta (renombrar / borrar). Aparecen al pasar el ratón para no
   competir con el contenido, pero SIEMPRE visibles con el foco por teclado. */
.card { position: relative; }
.card-acts {
  position: absolute; top: 10px; right: 10px; display: flex; gap: 4px;
  opacity: 0; transition: opacity .14s var(--ease);
}
.card:hover .card-acts, .card:focus-within .card-acts { opacity: 1; }
.icon-btn {
  width: 28px; height: 28px; display: grid; place-items: center; padding: 0;
  font-size: 13px; line-height: 1; cursor: pointer; color: var(--text-2);
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-sm);
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.icon-btn:hover { color: var(--text); border-color: var(--accent-line); background: var(--panel-3); }
.icon-btn.danger:hover { border-color: var(--danger); background: rgba(255,95,109,.14); }

/* Form / login */
.login { width: min(380px, 92vw); }
.login h1 { margin: 0 0 4px; }
label { display: block; margin: 12px 0 4px; font-size: 13px; color: var(--muted); }
input, select, textarea {
  width: 100%; padding: 9px 11px; background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r); font: inherit;
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
input:hover, select:hover { border-color: #3a4459; }
input:focus, select:focus, textarea:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-soft);
}
input::placeholder { color: #6b7789; }
label { font-weight: 500; letter-spacing: .01em; }
.hint { font-size: 12px; margin-top: 14px; }

/* Botones. Tres niveles: primario (acción principal), normal y fantasma. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 6px;
  padding: 8px 13px; border-radius: var(--r); border: 1px solid var(--line);
  background: var(--panel-2); color: var(--text-2); cursor: pointer; font: inherit;
  line-height: 1.2; white-space: nowrap;
  transition: background .14s var(--ease), border-color .14s var(--ease),
              color .14s var(--ease), transform .06s var(--ease);
}
.btn:hover { background: var(--panel-3); border-color: #3a4459; color: var(--text); }
.btn:active { transform: translateY(1px); }
.btn.primary {
  background: var(--accent); border-color: var(--accent); color: #fff; font-weight: 600;
  box-shadow: var(--sh-1);
}
.btn.primary:hover { background: #5f9aff; border-color: #5f9aff; }
.btn.ghost { background: transparent; border-color: transparent; }
.btn.ghost:hover { background: var(--panel-2); border-color: var(--line); }
.btn.small { padding: 6px 10px; font-size: 12.5px; border-radius: var(--r-sm); }
.btn.active { background: var(--accent-soft); border-color: var(--accent-line); color: #cfe0ff; }
.btn.danger:hover { background: rgba(255,95,109,.14); border-color: var(--danger); color: #ffb3ba; }
.btn:disabled { opacity: .4; cursor: not-allowed; }
.btn:disabled:hover { background: var(--panel-2); border-color: var(--line); transform: none; }
/* ICONOS. Son SVG de trazo que heredan el color del texto: un solo lenguaje
   gráfico en toda la app, en vez de emojis que cada sistema pinta a su manera. */
.ic { flex: 0 0 auto; display: block; }
.btn .ic { margin-right: -1px; }
.icon-btn .ic { display: block; }
/* Botón SOLO icono: cuadrado, sin el hueco del texto. */
.btn.icon-only { padding: 7px; }

/* Toast */
.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translateX(-50%);
  padding: 11px 18px 11px 16px; border-radius: var(--r); background: var(--panel-2);
  border: 1px solid var(--line); border-left-width: 3px;
  z-index: 100; box-shadow: var(--sh-3); font-size: 13.5px;
  animation: toast-in .2s var(--ease);
}
@keyframes toast-in { from { opacity: 0; transform: translate(-50%, 10px); } }
.toast.con-accion { display: flex; align-items: center; gap: 14px; padding-right: 6px; max-width: min(560px, 92vw); }
/* El aspa va SEPARADA de la acción y más apagada: son cosas opuestas y pulsar una
   creyendo pulsar la otra, con 9,6 s de reloj corriendo, es de las que fastidian. */
.toast-cerrar {
  flex: none; display: grid; place-items: center; width: 26px; height: 26px; margin-left: -6px;
  padding: 0; cursor: pointer; color: var(--muted); background: none; border: none;
  border-radius: var(--r-sm);
}
.toast-cerrar:hover { color: var(--text); background: var(--panel-3); }
.toast-act {
  flex: none; padding: 5px 11px; margin: 0; cursor: pointer;
  font: inherit; font-size: 12.5px; font-weight: 600; color: var(--accent);
  background: none; border: 1px solid var(--accent-line); border-radius: var(--r-sm);
}
.toast-act:hover { color: #fff; background: var(--accent); border-color: var(--accent); }
.toast.ok { border-left-color: var(--accent-2); }
.toast.error { border-left-color: var(--danger); }
.toast.info { border-left-color: var(--accent); }

/* ---------- Responsive (tablet / móvil) ---------- */
@media (max-width: 1024px) {
  .palette { width: 150px; }
  .right { width: 216px; }
}
@media (max-width: 760px) {
  body { overflow-x: hidden; }
  #whoami { display: none; }
  /* La barra de arriba tenía siete cosas y en 412 px se salía por la derecha.
     Se queda con lo que se usa: marca, migas y salir. */
  #topbar { gap: 8px; padding: 8px 10px; }
  #topbar .brand span { display: none; }
  #crumbs { font-size: 12.5px; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
  #crumbs a:not(:last-child), #crumbs .sep:first-of-type { display: none; }
  .empresa-chip { display: none; }
  .toolbar { gap: 4px; padding: 6px 8px; }
  .toolbar .btn.small { padding: 6px 8px; }
  .palette { width: 118px; }
  .palette h5 { font-size: 10px; }
  .pal-grid { grid-template-columns: 1fr; }
  .right { width: 186px; }
  .v3d-bar { flex-wrap: wrap; gap: 8px; }
  .v3d-ctl span { display: none; }
}

/* ---------- Editor ---------- */
.editor { display: flex; flex-direction: column; height: calc(100vh - 53px); }
.toolbar {
  display: flex; align-items: center; gap: 5px; padding: 7px 10px; flex-wrap: wrap;
  background: var(--panel); border-bottom: 1px solid var(--line); box-shadow: var(--sh-1);
}
.toolbar .sep-v { width: 1px; height: 20px; background: var(--line); margin: 0 5px; }
/* Las herramientas forman un bloque: se lee como un selector, no como botones sueltos. */
.toolbar .tool {
  padding: 7px; background: transparent; border-color: transparent;
}
.toolbar .tool:hover { background: var(--panel-2); border-color: var(--line); }
.toolbar .tool.active {
  background: var(--accent); border-color: var(--accent); color: #fff;
  box-shadow: 0 0 0 3px var(--accent-soft);
}
.toolbar select.small { width: auto; padding: 5px 8px; font-size: 12.5px; }
.chk {
  display: inline-flex; align-items: center; gap: 5px; font-size: 12.5px; color: var(--muted);
  padding: 5px 8px; border-radius: var(--r-sm); cursor: pointer; user-select: none;
}
.chk:hover { background: var(--panel-2); color: var(--text-2); }
.chk input { width: auto; accent-color: var(--accent); cursor: pointer; }

.editor-body { flex: 1; display: flex; min-height: 0; }
.palette { width: 190px; overflow-y: auto; padding: 12px 10px; border-right: 1px solid var(--line); background: var(--panel); }
.palette h5 { margin: 14px 0 7px; color: var(--muted); font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; }
.palette h5:first-child { margin-top: 0; }
.pal-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.pal-item {
  display: flex; flex-direction: column; align-items: center; gap: 4px; padding: 9px 4px;
  background: var(--panel-2); border: 1px solid var(--line-soft); border-radius: var(--r);
  color: var(--text-2); cursor: pointer; font-size: 10.5px; text-align: center;
  transition: background .14s var(--ease), border-color .14s var(--ease), transform .06s var(--ease);
}
.pal-item:hover { border-color: var(--accent-line); background: var(--panel-3); color: var(--text); }
.pal-item:active { transform: translateY(1px); }
.pal-item.active {
  border-color: var(--accent); background: var(--accent-soft); color: #cfe0ff;
  box-shadow: 0 0 0 3px var(--accent-soft);
}
/* EN SERIE: la pieza se queda cargada hasta Esc. Tiene que distinguirse de la
   marcada normal —que coloca UNA— porque el error que esto arregla era justamente no
   saber en qué modo estabas. Va un borde discontinuo, que se lee como «esto sigue
   abierto», y el «∞» dice cuántas sin ocupar sitio. */
.pal-item.serie { border-style: dashed; border-color: var(--accent); position: relative; }
.pal-item.serie::after {
  content: '∞'; position: absolute; top: -1px; right: 3px;
  font-size: 12px; line-height: 1; color: var(--accent); font-weight: 700;
}
.pal-ic { display: grid; place-items: center; height: 32px; font-size: 20px; color: var(--text-2); opacity: .92; }
.pal-ic svg { display: block; max-width: 100%; }
.pal-item:hover .pal-ic, .pal-item.active .pal-ic { color: inherit; opacity: 1; }
.pal-lbl { line-height: 1.1; }

.canvas { flex: 1; min-width: 0; position: relative; background: var(--canvas-bg); overflow: hidden; }
.canvas .konvajs-content { position: absolute; inset: 0; }

/* Campo para escribir una medida SOBRE el plano (clic en el número). */
.dim-input {
  position: absolute; z-index: 6; width: 76px; padding: 3px 6px; margin: 0;
  transform: translate(-50%, -50%); text-align: center;
  font: 600 13px/1.2 inherit; color: var(--text);
  /* EL FONDO IBA A FUEGO (#0d1526) y el texto seguía al tema: en modo claro salían
     números oscuros sobre un fondo oscuro y no se leía lo que estabas escribiendo —
     justo en el campo donde se teclea una medida—. Va con los tokens, como el resto
     de lo que flota sobre el lienzo; la sombra también, que la de antes estaba
     calculada para fondo oscuro y en claro era una mancha. */
  background: var(--panel); border: 1px solid var(--accent); border-radius: 6px;
  box-shadow: var(--sh-2);
}
.dim-input:focus { outline: none; border-color: var(--accent); }

/* Navegador de la vista: minimapa + cruceta (sustituye a la mano y a «Ajustar»). */
.nav-widget {
  /* Arriba a la derecha: la esquina de abajo es del CAJETÍN del plano, que es
     contenido y no un mando. */
  position: absolute; right: 12px; top: 12px; z-index: 5; width: 164px;
  padding: 6px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--radius); box-shadow: 0 6px 20px rgba(0,0,0,.45);
  user-select: none;
}
.nav-head {
  display: flex; align-items: center; justify-content: space-between;
  font-size: 10px; letter-spacing: .06em; text-transform: uppercase; color: var(--muted);
  padding: 0 2px 5px;
}
.nav-tog {
  width: 20px; height: 18px; padding: 0; line-height: 1; font-size: 11px; cursor: pointer;
  background: transparent; border: 1px solid var(--line); border-radius: 5px; color: var(--muted);
}
.nav-tog:hover { color: var(--text); border-color: var(--accent); }
.nav-widget.closed { width: auto; }
.nav-widget.closed .nav-head { padding-bottom: 0; }
.nav-widget.closed .nav-body { display: none; }
.nav-body { display: flex; flex-direction: column; gap: 6px; }
.nav-map {
  display: block; width: 152px; height: 106px; cursor: crosshair;
  border: 1px solid var(--line); border-radius: 6px; background: var(--canvas-bg);
}
.nav-ctl { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.nav-pad { display: grid; grid-template-columns: repeat(3, 26px); grid-auto-rows: 22px; gap: 2px; }
.nav-zoom { display: grid; grid-template-columns: 26px 26px; grid-auto-rows: 22px; gap: 2px; }
.nav-zoom .nav-btn:last-child { grid-column: span 2; }
.nav-gap { display: block; }
.nav-btn {
  display: grid; place-items: center; padding: 0; font-size: 12px; line-height: 1; cursor: pointer;
  color: var(--text); background: var(--panel-2); border: 1px solid var(--line); border-radius: 5px;
}
.nav-btn:hover { border-color: var(--accent); background: rgba(79,140,255,.18); }
.nav-btn:active { transform: translateY(1px); }
.nav-fit { color: var(--accent); }

@media (max-width: 900px) {
  /* En pantallas pequeñas el lienzo es lo escaso: solo la cruceta. */
  .nav-widget { width: auto; right: 8px; top: 8px; }
  .nav-map { display: none; }
}

/* El panel NO scrollea entero: la pestañera se queda fija y es CADA pestaña la
   que scrollea. Así la cabecera de acabados puede fijarse de verdad (con el panel
   entero como scroller, el `sticky` no llegaba a engancharse). */
.right {
  width: 264px; padding: 0; border-left: 1px solid var(--line); background: var(--panel);
  display: flex; flex-direction: column; min-height: 0; overflow: hidden;
}
.tabbar { display: flex; flex: 0 0 auto; background: var(--panel); border-bottom: 1px solid var(--line); }
.tabbar .tab {
  flex: 1 1 0; min-width: 0; padding: 10px 2px; font-size: 11px; font-weight: 500;
  display: inline-flex; align-items: center; justify-content: center; gap: 4px;
  background: transparent; border: none; border-bottom: 2px solid transparent;
  color: var(--muted); cursor: pointer; white-space: nowrap; overflow: hidden;
  transition: color .14s var(--ease), border-color .14s var(--ease);
}
.tabbar .tab span { overflow: hidden; text-overflow: ellipsis; }
.tabbar .tab:hover { color: var(--text-2); background: var(--panel-2); }
.tabbar .tab.active { color: var(--text); border-bottom-color: var(--accent); font-weight: 600; }
.tabpane { padding: 12px; flex: 1 1 auto; min-height: 0; overflow-y: auto; overflow-x: hidden; }

/* Selector de materiales/acabados */
.mat-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 8px; margin: 6px 0 12px; }
.mat-item {
  display: flex; flex-direction: column; align-items: stretch; gap: 3px; padding: 5px;
  background: var(--panel-2); border: 2px solid var(--line); border-radius: 8px; color: var(--text);
  cursor: pointer; font-size: 11px; text-align: center;
}
.mat-item:hover { border-color: var(--accent); }
.mat-item.active { border-color: var(--accent-2); box-shadow: 0 0 0 1px var(--accent-2); }
.mat-item:disabled { cursor: default; opacity: .9; }
.mat-sw { width: 100%; height: 42px; object-fit: cover; border-radius: 5px; display: block; }
.mat-none { height: 42px; display: grid; place-items: center; font-size: 20px; color: var(--muted); border: 1px dashed var(--line); border-radius: 5px; }
.mat-name { font-weight: 600; line-height: 1.1; }
.mat-price { color: var(--muted); font-size: 10px; }

/* Cabecera FIJA del panel de acabados: superficie + ficha + filtros.
   El 34px es el alto de la pestañera, que también es sticky. */
.fin-head {
  /* El scroller es la propia pestaña, así que se fija arriba del todo. */
  position: sticky; top: -12px; z-index: 1;
  /* Se sale del padding del panel para que al scrollar nada asome por los lados. */
  margin: -12px -12px 0; padding: 12px 12px 9px;
  background: var(--panel); border-bottom: 1px solid var(--line);
}
.fin-seg { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; }
.fin-tab {
  display: grid; grid-template-columns: 34px 1fr; grid-template-rows: auto auto;
  gap: 0 8px; align-items: center; padding: 6px 8px; cursor: pointer; text-align: left;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px; color: var(--text);
}
.fin-tab:hover { border-color: var(--accent); }
.fin-tab.active { border-color: var(--accent); background: rgba(79,140,255,.16); }
.fin-tab-sw { grid-row: span 2; width: 34px; height: 34px; object-fit: cover; border-radius: 5px; display: block; }
.fin-tab-none, .fin-tab-varios {
  display: grid; place-items: center; font-size: 15px; color: var(--muted);
  border: 1px dashed var(--line); border-radius: 5px;
}
.fin-tab-lbl { font-size: 12.5px; font-weight: 600; line-height: 1.15; }
.fin-tab-mat {
  font-size: 10.5px; color: var(--muted); line-height: 1.15;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}

/* Catálogo de proveedor: filtros + ficha del acabado puesto */
.mat-filters { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin: 8px 0 0; }
.mat-filters select, .mat-filters input { width: 100%; min-width: 0; padding: 5px 7px; font-size: 12px; }
.mat-filters .mat-serie, .mat-filters input { grid-column: span 2; }
/* Aviso de paredes con acabado propio (vista de estancia) */
.wall-scope {
  display: flex; align-items: center; justify-content: space-between; gap: 6px;
  margin: 6px 0 0; padding: 5px 7px; border-radius: 7px;
  background: rgba(79,140,255,.14); font-size: 11.5px;
}
.fin-intro { margin: 0 0 8px; font-size: 11.5px; line-height: 1.3; }
/* Ficha en UNA fila: miniatura · nombre+datos · €/m². Va en la cabecera fija. */
.mat-card {
  display: grid; grid-template-columns: 40px minmax(0, 1fr) auto; gap: 8px; align-items: center;
  padding: 6px 7px; margin: 6px 0 0;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 8px;
}
.mat-card-img { width: 40px; height: 34px; object-fit: cover; border-radius: 4px; display: block; }
.mat-card-txt { min-width: 0; display: flex; flex-direction: column; }
.mat-card-name {
  font-size: 12.5px; font-weight: 600; line-height: 1.2; color: var(--text);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
a.mat-card-name:hover { color: var(--accent); }
.mat-card-ext { color: var(--accent); }
.mat-card-txt span { font-size: 10.5px; line-height: 1.2; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mat-card-price { display: flex; align-items: center; gap: 4px; margin: 0; }
.mat-card-price span { font-size: 10px; color: var(--muted); }
.mat-card-price input { width: 54px; padding: 3px 5px; font-size: 12px; text-align: right; }
.mat-card-empty { margin: 6px 0 0; font-size: 11.5px; }
/* Selector de acabado dentro de Propiedades (pared seleccionada) */
.props-fin-head { display: flex; align-items: center; justify-content: space-between; gap: 6px; }
.props-fin-head .btn, .wall-scope .btn { text-transform: none; letter-spacing: 0; white-space: nowrap; padding: 4px 9px; }
.props .mat-filters { margin-top: 6px; }
.props .mat-grid { margin-bottom: 4px; }
.mat-more { grid-column: span 2; margin: 4px 0 0; text-align: center; }
.finishes-panel .mat-grid { margin-top: 10px; }
/* Miniaturas de azulejo real: algo más altas, que se aprecie el despiece */
.mat-item .mat-sw { height: 50px; }
.right h4 { margin: 14px 0 8px; font-size: 13px; }
.right h4:first-child { margin-top: 0; }
.layer-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 14px; }
.layer-row span { flex: 1; }
.layer-row input { width: auto; }
.field { display: block; margin: 8px 0; }
.field span { display: block; font-size: 12px; color: var(--muted); margin-bottom: 3px; }
.props .small { font-size: 12px; }
/* Selector segmentado (tipo de abertura, lado de bisagra…) */
.seg-field span { margin-bottom: 4px; }
.seg { display: flex; gap: 0; border: 1px solid var(--line); border-radius: 8px; overflow: hidden; }
.seg-btn {
  flex: 1 1 0; min-width: 0; padding: 6px 4px; font: inherit; font-size: 11.5px;
  background: var(--panel-2); color: var(--muted); border: none; cursor: pointer;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
  border-right: 1px solid var(--line); transition: background .12s, color .12s;
}
.seg-btn:last-child { border-right: none; }
.seg-btn:hover { color: var(--text); }
.seg-btn.active { background: var(--accent); color: #fff; font-weight: 600; }

.rot-row { display: flex; align-items: flex-end; gap: 6px; }
.rot-row .field { flex: 1; margin-bottom: 0; }
.rot-row .btn { white-space: nowrap; padding: 8px 10px; }

.hintbar { display: flex; align-items: center; gap: 12px;
  display: flex; align-items: center; padding: 6px 14px; border-top: 1px solid var(--line);
  font-size: 12px; background: var(--panel); min-height: 28px; color: var(--muted);
}

/* Panel de presupuesto (dentro del editor) */
.budget-panel { font-size: 13px; }
.bud-sub { display: flex; align-items: center; justify-content: space-between; margin: 14px 0 5px; font-size: 10.5px; font-weight: 600; text-transform: uppercase; letter-spacing: .07em; color: var(--muted); }
.bud-row { display: flex; align-items: center; gap: 6px; padding: 3px 0; }
/* EL NOMBRE DE LA PARTIDA BAJA DE LÍNEA EN VEZ DE CORTARSE. Con el campo de precio
   (62 px) y el importe (78 px), al nombre le quedaban 87 px de los 264 del panel: se
   cortaban TODAS las líneas, hasta «Pintura de techo» por 7 px, y el `title` llevaba
   los m² —no el nombre—, así que lo cortado no había forma de leerlo. Los importes no
   se tocan: en un presupuesto, la cifra recortada sería mucho peor que el rótulo.
   Las que caben siguen en una línea; solo crecen las que lo necesitan.
   Se mantiene `align-items: center` de la fila: alinear arriba descolocaba las filas
   con campo —el importe del IVA se iba por encima de su propia casilla— porque el
   campo es más alto que el texto. */
.bud-row span.bud-name { flex: 1; min-width: 0; overflow-wrap: anywhere; line-height: 1.3; }
.bud-row input.bud-price, .bud-row .bud-sum { flex: 0 0 auto; }
.bud-row input { min-width: 0; }
.bud-row input.bud-name { flex: 1; padding: 4px 6px; }
/* Alicatado partido por material: la cabecera lleva los metros y el subtotal, y
   debajo va una fila por material con SU €/m². Se sangran para que se lea que
   suman a la de arriba y no son cuatro partidas sueltas. */
.bud-row-cab { padding-bottom: 0; }
.bud-row-cab .bud-name { font-weight: 600; }
.bud-row-mat { padding-left: 12px; border-left: 2px solid var(--line); margin-left: 2px; }
.bud-row-mat .bud-name { color: var(--text-2); }

/* Chapa de «hay alguien más aquí». Discreta a propósito: que dos personas tengan la
   misma estancia abierta es lo normal —el medidor en la obra, quien presupuesta en la
   oficina—, así que informa sin dar la impresión de que hay que hacer algo. */
.badge.presencia { display: inline-flex; align-items: center; gap: 5px; }
.badge.presencia svg { opacity: .8; }
.budget-panel, .finishes-panel { overflow-x: hidden; }
.bud-price, .bud-qty, .bud-iva { width: 62px; padding: 4px 6px; text-align: right; }
.bud-qty { width: 48px; }
.bud-iva { width: 52px; }
/* Va dentro de un `label.chk`, y `.chk input { width:auto }` le ganaba por
   especificidad: el campo del IVA se estiraba y se comía el importe. */
.chk input.bud-iva { width: 52px; }
.bud-sum { width: 78px; text-align: right; white-space: nowrap; color: var(--text); }
.bud-totals { margin-top: 10px; border-top: 1px solid var(--line); padding-top: 8px; }
.bud-totals .total { font-size: 16px; font-weight: 700; color: var(--accent-2); }
.bud-totals .btn { width: 100%; margin-top: 10px; }

/* Modales (plantillas, ayuda) */
.modal-back {
  position: fixed; inset: 0; z-index: 250; background: rgba(6,9,16,.66);
  backdrop-filter: blur(3px); display: grid; place-items: center; padding: 20px;
  animation: fade-in .14s var(--ease);
}
@keyframes fade-in { from { opacity: 0; } }
.modal {
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg);
  padding: 22px; width: min(560px, 96vw); max-height: 90vh; overflow: auto;
  box-shadow: var(--sh-3); animation: modal-in .18s var(--ease);
}
@keyframes modal-in { from { opacity: 0; transform: translateY(8px) scale(.985); } }
.modal h3 { margin: 0 0 14px; font-size: 17px; letter-spacing: -.01em; }
.tpl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(164px, 1fr)); gap: 10px; margin-bottom: 14px; }
.tpl-card {
  display: flex; flex-direction: column; align-items: stretch; gap: 3px; padding: 8px 8px 10px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: 10px;
  color: var(--text); cursor: pointer; text-align: left;
}
.tpl-card:hover { border-color: var(--accent); }
/* La MISMA miniatura que las estancias guardadas: se elige por la forma de la planta,
   no por un emoji que en cada sistema se dibuja distinto y no dice nada del reparto. */
.tpl-prev {
  display: block; margin-bottom: 5px; border-radius: 7px; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line);
}
.tpl-prev .plan-prev { display: block; width: 100%; height: auto; }
.tpl-card .tpl-name { font-size: 13px; font-weight: 600; }
.tpl-name { font-weight: 600; }
.modal-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 14px; }

/* Diálogos de formulario (crear/renombrar). Sustituyen a `prompt()`, que bloquea
   la pestaña y no se puede estilar ni automatizar. */
.modal-form { width: min(420px, 96vw); }
.modal-form .fields { display: flex; flex-direction: column; gap: 10px; }
.modal-form .fld { display: block; margin: 0; }
.modal-form .fld > span {
  display: block; margin-bottom: 4px; font-size: 12.5px; color: var(--text-2);
}
.modal-form input.err, .modal-form select.err { border-color: var(--danger); }
.btn.danger {
  background: rgba(255,95,109,.16); border-color: rgba(255,95,109,.5); color: #ffb3ba; font-weight: 600;
}
.mount-row { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; margin: 4px 0 8px; padding: 6px 8px; background: var(--panel-2); border: 1px dashed var(--line); border-radius: 8px; }
.mount-row span { flex: 1 1 auto; }
.ai-file { display: block; width: 100%; margin: 4px 0; }
.ai-preview { display: block; max-width: 100%; max-height: 300px; margin: 10px auto; border: 1px solid var(--line); border-radius: 10px; object-fit: contain; }
.ai-howto { margin: 10px 0; padding: 8px 12px; background: var(--panel-2); border: 1px solid var(--line); border-left: 3px solid var(--accent); border-radius: 8px; }
.ai-howto ol { margin: 6px 0 0; padding-left: 18px; color: var(--muted, #8fa3c9); }
.ai-howto li { margin: 2px 0; }
.ai-status { margin-top: 10px; }
.ai-status.error { color: var(--danger, #ff6b6b); }
.bg-controls { margin-top: 12px; padding-top: 10px; border-top: 1px solid var(--line); }
.bg-controls h5 { margin: 0 0 6px; }
.bg-controls .field { margin: 4px 0 8px; }
.bg-controls .btn { width: 100%; justify-content: center; }
.help-list { display: flex; flex-direction: column; gap: 4px; margin-bottom: 14px; }
.help-row { display: flex; justify-content: space-between; gap: 16px; padding: 6px 0; border-bottom: 1px solid var(--line); }
.help-row kbd { font-family: inherit; background: var(--panel-2); border: 1px solid var(--line); border-radius: 6px; padding: 2px 8px; font-size: 12px; color: var(--muted); }

/* Menú contextual (clic derecho) */
.ctxmenu {
  position: fixed; z-index: 300; min-width: 190px; padding: 5px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--sh-3); display: flex; flex-direction: column;
  animation: menu-in .12s var(--ease);
}
@keyframes menu-in { from { opacity: 0; transform: translateY(-4px); } }
.ctx-item {
  display: flex; align-items: center; gap: 9px;
  text-align: left; padding: 8px 12px; background: transparent; border: none;
  color: var(--text-2); cursor: pointer; border-radius: var(--r-sm); font: inherit; font-size: 13px;
  transition: background .1s var(--ease), color .1s var(--ease);
}
.ctx-item .ic { color: var(--muted); flex: 0 0 auto; }
.ctx-item:hover .ic { color: #fff; }
.ctx-item:hover { background: var(--accent); color: #fff; }
.ctx-sep { height: 1px; margin: 5px 8px; background: var(--line); }
.toolbar .more { padding: 7px; }
/* Conmutador de instalaciones: apagado se ve claramente apagado. */
.toolbar .inst.off { color: var(--muted); opacity: .75; }
.toolbar .inst.off .ic { opacity: .6; }
.toolbar .inst:not(.off) { border-color: var(--accent-line); background: var(--accent-soft); color: #cfe0ff; }
:root[data-theme="claro"] .toolbar .inst:not(.off) { color: var(--accent); }

/* Vista 3D */
.v3d-overlay { position: fixed; inset: 0; z-index: 200; background: #0e1422; display: flex; flex-direction: column; }
.v3d-bar { display: flex; align-items: center; gap: 12px; padding: 10px 16px; background: var(--panel); border-bottom: 1px solid var(--line); }
.v3d-ctl { display: inline-flex; align-items: center; gap: 6px; font-size: 12px; color: var(--muted); }
.v3d-ctl select { width: auto; padding: 5px 8px; }
.v3d-canvas { flex: 1; min-height: 0; position: relative; }
.v3d-canvas canvas { display: block; }
.v3d-error { padding: 30px; color: var(--muted); text-align: center; }

/* Impresión del presupuesto */
#print-root { display: none; }
@media print {
  body > *:not(#print-root) { display: none !important; }
  #print-root { display: block !important; color: #000; padding: 20px; font: 13px system-ui, sans-serif; }
  #print-root h1 { margin: 0 0 4px; }
  #print-root table { width: 100%; border-collapse: collapse; margin-top: 12px; }
  #print-root th, #print-root td { border: 1px solid #bbb; padding: 6px 8px; text-align: left; }
  #print-root th { background: #eee; }
  #print-root .ptot { margin-top: 16px; text-align: right; line-height: 1.7; }
  #print-root .pgrand { font-size: 20px; font-weight: 700; border-top: 2px solid #000; display: inline-block; padding-top: 6px; margin-top: 6px; }

  /* Dossier del cliente: plano + 3D + acabados + presupuesto en un documento.
     Pensado para «Guardar como PDF» desde el propio diálogo de impresión. */
  #print-root.dossier { padding: 0 8mm; font-size: 12px; }
  .dossier .dos-head {
    display: flex; align-items: flex-end; justify-content: space-between; gap: 16px;
    padding-bottom: 10px; border-bottom: 2px solid #111; margin-bottom: 14px;
  }
  .dossier .dos-head h1 { font-size: 24px; letter-spacing: -.02em; }
  .dossier .dos-marca { display: flex; align-items: center; gap: 14px; }
  .dossier .dos-logo { max-width: 130px; max-height: 54px; object-fit: contain; }
  .dossier .dos-emp { text-align: right; font-size: 11px; line-height: 1.5; color: #444; }
  .dossier .dos-emp strong { display: block; font-size: 13px; color: #111; }
  .dossier .dos-emp span { display: block; }
  .dossier .dos-sub { margin: 4px 0 0; color: #444; }
  .dossier .dos-date { color: #444; white-space: nowrap; }
  .dossier .dos-kpis { display: flex; gap: 10px; margin-bottom: 16px; }
  .dossier .dos-kpis > div {
    flex: 1; border: 1px solid #ccc; border-radius: 6px; padding: 8px 10px; text-align: center;
  }
  .dossier .dos-kpis b { display: block; font-size: 17px; }
  .dossier .dos-kpis span { font-size: 10.5px; color: #555; text-transform: uppercase; letter-spacing: .04em; }
  .dossier h2 {
    font-size: 14px; text-transform: uppercase; letter-spacing: .06em; color: #333;
    margin: 0 0 8px; padding-bottom: 4px; border-bottom: 1px solid #ddd;
  }
  .dossier section { margin-bottom: 18px; }
  /* Cada bloque grande, en su hoja: si no, el plano parte por la mitad. */
  .dossier .dos-break { break-before: page; page-break-before: always; }
  /* Fondo BLANCO: el PNG del plano sale con fondo transparente (Konva no pinta el
     del contenedor) y el dossier se genera siempre con la paleta clara. */
  .dossier .dos-img {
    display: block; width: 100%; max-height: 165mm; object-fit: contain;
    border: 1px solid #ddd; border-radius: 6px; background: #fff;
  }
  .dossier table { font-size: 11.5px; margin-top: 0; }
  .dossier td.n, .dossier th.n { text-align: right; }
  .dossier td.na { color: #666; font-style: italic; }
  .dossier tbody tr:nth-child(even) { background: #f6f6f6; }
  .dossier .dos-foot { margin-top: 10px; padding-top: 8px; border-top: 1px solid #ddd; font-size: 10.5px; color: #555; }
  /* Plano de instalaciones: notas de método y comprobaciones del gremio. */
  .dossier .dos-nota { margin: 6px 0 0; font-size: 10.5px; color: #555; line-height: 1.45; }
  .dossier .dos-avisos { margin: 0; padding-left: 18px; font-size: 11.5px; line-height: 1.5; }
  .dossier .dos-avisos li { margin-bottom: 4px; }
  /* Punto de color del circuito, el mismo que su línea en el plano. */
  .dossier .dos-chip {
    display: inline-block; width: 9px; height: 9px; border-radius: 50%;
    margin-right: 6px; vertical-align: middle;
  }
}

/* Los dos botones de impresión del panel de presupuesto, uno al lado del otro. */
.bud-print { display: flex; gap: 6px; flex-wrap: wrap; margin-top: 10px; }
.bud-print .btn { flex: 1 1 auto; }

/* ---------- Presupuesto ---------- */
.room-actions { display: flex; gap: 8px; margin-top: 12px; }
.budget-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.metrics { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 10px; margin: 6px 0 20px; }
.metric { background: var(--panel); border: 1px solid var(--line); border-radius: 10px; padding: 12px; }
.metric .mv { display: block; font-size: 20px; font-weight: 700; }
.metric .mk { display: block; font-size: 12px; color: var(--muted); margin-top: 2px; }

.budget-table { width: 100%; border-collapse: collapse; background: var(--panel); border: 1px solid var(--line); border-radius: 10px; overflow: hidden; }
.budget-table th { text-align: left; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .03em; padding: 10px; border-bottom: 1px solid var(--line); background: var(--panel-2); }
.budget-table td { padding: 6px 8px; border-bottom: 1px solid var(--line); vertical-align: middle; }
.budget-table td.num { text-align: right; white-space: nowrap; }
.budget-table input, .budget-table select { padding: 6px 8px; background: var(--panel-2); }
.budget-table input[type=number] { text-align: right; }
.budget-table td:nth-child(1) input { width: 130px; }
.budget-table td:nth-child(2) input { width: 100%; min-width: 180px; }
.budget-table td:nth-child(4) input { width: 90px; }
.budget-table td:nth-child(5) input { width: 100px; }

.totals { margin: 16px 0 0; margin-left: auto; width: min(340px, 100%); }
.totals .trow { display: flex; justify-content: space-between; padding: 8px 10px; }
.totals .trow.total { font-size: 18px; font-weight: 700; border-top: 2px solid var(--line); margin-top: 4px; color: var(--accent-2); }

/* Impresión: solo el presupuesto, en claro */
@media print {
  #topbar, .no-print, .budget-table th:last-child, .budget-table td:last-child { display: none !important; }
  body { background: #fff; color: #000; }
  .page.budget { max-width: none; padding: 0; }
  .metric, .budget-table, .budget-table th, .totals .trow.total { background: #fff !important; color: #000 !important; border-color: #ccc !important; }
  .budget-table input, .budget-table select { border: none !important; background: #fff !important; color: #000 !important; -webkit-appearance: none; appearance: none; }
  .metric .mk, .muted { color: #444 !important; }
}


/* ---------- Paleta de comandos (Ctrl+K) ----------
   Un solo sitio para buscar y ejecutar cualquier cosa. En una app con 37 tipos de
   pieza y mil acabados, escribir gana siempre a buscar con el ratón. */
/* Disparador de la paleta en la barra superior: parece un buscador porque es lo
   que la gente busca con la vista, y enseña el atajo. */
.cmdk-trigger {
  display: inline-flex; align-items: center; gap: 8px; padding: 6px 10px;
  min-width: 210px; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 999px; color: var(--muted); cursor: pointer; font: inherit; font-size: 12.5px;
  transition: border-color .14s var(--ease), color .14s var(--ease);
}
.cmdk-trigger:hover { border-color: var(--accent-line); color: var(--text-2); }
.cmdk-trigger span { flex: 1; text-align: left; }
.cmdk-trigger kbd {
  padding: 1px 6px; border: 1px solid var(--line); border-radius: 5px;
  background: var(--panel); font: inherit; font-size: 11px; color: var(--muted);
}
@media (max-width: 900px) { .cmdk-trigger { min-width: 0; } .cmdk-trigger span, .cmdk-trigger kbd { display: none; } }

.cmdk-back {
  position: fixed; inset: 0; z-index: 400; background: rgba(6,9,16,.55);
  backdrop-filter: blur(4px); display: flex; justify-content: center;
  align-items: flex-start; padding: 12vh 16px 16px;
  animation: fade-in .12s var(--ease);
}
:root[data-theme="claro"] .cmdk-back { background: rgba(30,40,60,.34); }
.cmdk {
  width: min(620px, 100%); max-height: 66vh; display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--sh-3); overflow: hidden; animation: modal-in .16s var(--ease);
}
.cmdk-head { display: flex; align-items: center; gap: 10px; padding: 12px 16px; border-bottom: 1px solid var(--line); }
.cmdk-head .ic { color: var(--muted); }
.cmdk-input {
  flex: 1; padding: 0; border: none; background: transparent; color: var(--text);
  font-size: 16px; outline: none;
}
.cmdk-input::placeholder { color: var(--muted); }
.cmdk-list { flex: 1; overflow-y: auto; padding: 6px; }
.cmdk-group {
  padding: 10px 10px 4px; font-size: 10.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
}
.cmdk-item {
  display: flex; align-items: center; gap: 10px; padding: 8px 10px; border-radius: var(--r-sm);
  color: var(--text-2); cursor: pointer; font-size: 13.5px;
}
.cmdk-item .ic { color: var(--muted); }
.cmdk-item.sel { background: var(--accent); color: #fff; }
.cmdk-item.sel .ic, .cmdk-item.sel .cmdk-hint { color: rgba(255,255,255,.82); }
.cmdk-lbl { flex: 1; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.cmdk-hint { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
.cmdk-empty { padding: 26px; text-align: center; color: var(--muted); }
.cmdk-foot {
  display: flex; gap: 16px; padding: 8px 14px; border-top: 1px solid var(--line);
  background: var(--panel-2); font-size: 11.5px; color: var(--muted);
}
.cmdk-foot kbd {
  padding: 1px 5px; margin-right: 4px; border: 1px solid var(--line); border-radius: 4px;
  background: var(--panel); font: inherit; font-size: 11px;
}


/* ---------- Revisión del plano ----------
   El contador vive en la barra y el detalle en un panel flotante: un aviso que
   hay que ir a buscar a una pestaña no lo lee nadie. */
.toolbar .check .check-n {
  min-width: 17px; padding: 0 5px; border-radius: 999px; font-size: 11px; font-weight: 700;
  background: var(--panel-3); color: var(--muted);
  display: inline-flex; align-items: center; justify-content: center;   /* el «sin avisos» es un SVG */
}
.toolbar .check .check-n svg { display: block; }
.toolbar .check.has-error { color: #ffc3c8; border-color: rgba(255,95,109,.5); background: rgba(255,95,109,.14); }
.toolbar .check.has-error .check-n { background: var(--danger); color: #fff; }
.toolbar .check.has-warn { color: #ffd9a0; border-color: rgba(255,181,71,.45); background: rgba(255,181,71,.12); }
.toolbar .check.has-warn .check-n { background: var(--warn); color: #241800; }
.toolbar .check.all-ok .check-n { background: rgba(47,191,140,.2); color: var(--accent-2); }

.revpanel {
  position: fixed; z-index: 260; width: min(390px, 94vw); max-height: 70vh;
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--sh-3); animation: menu-in .14s var(--ease);
}
.rev-head { display: flex; align-items: center; gap: 8px; padding: 11px 12px; border-bottom: 1px solid var(--line); flex: none; }
/* TODO lo que no es la cabecera rueda junto. Antes scrolleaba solo la lista de avisos y
   lo de debajo —botón de corregir, pie y repaso del jefe de obra— se salía del panel y
   quedaba cortado, sin manera de llegar a ello. `min-height: 0` es imprescindible: sin
   él un hijo flexible no baja de su contenido y no aparece la barra. */
.rev-scroll { flex: 1 1 auto; min-height: 0; overflow-y: auto; }
.rev-head .ic { color: var(--accent); }
.rev-sum { margin: 10px 12px 4px; }
/* --- ALZADOS Y DESPIECE --------------------------------------------------
   La pared vista de frente. La pieza CORTADA se distingue de la entera con un relleno
   más apagado: de un vistazo se ve dónde queda el corte, que es lo único que se mira
   en un despiece. */
.modal-alz { width: min(680px, 96vw); max-height: 92vh; display: flex; flex-direction: column; }
.alz-cuerpo { flex: 1 1 auto; min-height: 0; overflow-y: auto; margin: 6px -4px 0; padding: 0 4px; }
.alz-bloque { margin-bottom: 18px; }
.alz-cab { display: flex; align-items: baseline; gap: 10px; justify-content: space-between; margin-bottom: 4px; }
/* Tamaño REAL del SVG (no 100%): así todos los alzados de una estancia salen a la misma
   escala y se pueden comparar de un vistazo, que es para lo que se miran juntos. */
.alz { display: block; max-width: 100%; background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-sm); }
.alz-pieza { fill: var(--accent-soft, rgba(90,150,255,.14)); stroke: var(--line); stroke-width: .6; }
/* La CORTADA se distingue por relleno, no solo por el borde: en un despiece lo único
   que se busca es dónde queda el corte. */
.alz-pieza.cortada { fill: var(--warn-soft, rgba(230,170,60,.22)); stroke: var(--warn); stroke-width: .5; }
.alz-hueco { fill: var(--panel); stroke: var(--muted); stroke-width: 1.2; }
.alz-hueco-t { fill: var(--muted); font-size: 9px; }
.alz-muro { fill: none; stroke: var(--text-2); stroke-width: 1.6; }
.alz-punto { fill: var(--warn); stroke: var(--panel); stroke-width: 1; }
.alz-punto.toma_agua, .alz-punto.desague, .alz-punto.llave_paso, .alz-punto.toma_lavadora { fill: var(--accent-2); }
.alz-punto-t { fill: var(--muted); font-size: 8px; }
/* El mecanismo que cae mal en el alicatado: se ve en el dibujo Y se explica debajo.
   Solo en el dibujo no se entiende qué le pasa; solo en el texto no se sabe cuál es. */
.alz-punto.mal { fill: var(--danger); stroke: var(--panel); stroke-width: 1.4; }
.alz-avisos { margin-top: 5px; display: flex; flex-direction: column; gap: 4px; }
.alz-aviso {
  display: flex; gap: 7px; align-items: flex-start; padding: 6px 9px; font-size: 12px;
  line-height: 1.45; color: var(--text-2);
  background: var(--warn-soft, rgba(230,170,60,.12));
  border: 1px solid var(--warn); border-radius: var(--r-sm);
}
.alz-aviso .ic { flex: none; color: var(--warn); margin-top: 2px; }
.alz-cota { stroke: var(--muted); stroke-width: .8; }
.alz-cota-t { fill: var(--muted); font-size: 9px; }
.alz-datos { display: flex; flex-wrap: wrap; gap: 4px 16px; margin-top: 5px; font-size: 12px; }
.alz-dato { white-space: nowrap; }

/* MATERIAL A PEDIR dentro del presupuesto: se distingue de las partidas porque NO suma
   al total — es lo que pagas, no lo que cobras. Borde discontinuo y fondo apagado. */
.bud-pedido:not(:empty) {
  margin: 8px 0; padding: 2px 0 6px;
  border-top: 1px dashed var(--line); border-bottom: 1px dashed var(--line);
}
.bud-row.bud-ped .bud-sum { color: var(--text-2); font-weight: 500; }
.bud-ped-nota { margin: -2px 0 6px; padding-left: 2px; line-height: 1.35; }

.alz-compra { margin-top: 6px; padding-top: 12px; border-top: 1px solid var(--line); }
.alz-compra h4 { margin: 0 0 3px; font-size: 14px; }
.alz-mat { padding: 9px 11px; margin-top: 8px; background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-sm); }
/* La cadena m² pared → con cortes → con merma, en una línea: enseñar SOLO el número
   final no convence a nadie de que hay que pedir más de lo que mide la pared. */
.alz-linea { display: flex; flex-wrap: wrap; align-items: center; gap: 7px; margin: 4px 0 6px; font-size: 12px; color: var(--muted); }
.alz-fl { opacity: .55; }
.alz-cajas { display: flex; align-items: baseline; gap: 6px; }
.alz-cajas strong { font-size: 15px; color: var(--accent); }

/* ALTURA LIBRE de la estancia, encima de los acabados: de ella salen los m² de pared,
   así que se enseña el resultado al lado del campo — si no, parece un dato de ficha. */
.alt-fila {
  margin: 0 0 10px; padding: 8px 10px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-sm);
}
.alt-linea { display: flex; align-items: center; gap: 8px; }
.alt-lbl { display: inline-flex; align-items: center; gap: 6px; font-size: 12.5px; font-weight: 600; color: var(--text); }
.alt-lbl .ic { color: var(--accent); }
.alt-in {
  width: 68px; padding: 4px 7px; font: inherit; font-size: 13px; text-align: right;
  color: var(--text); background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-sm);
}
.alt-in:focus { outline: none; border-color: var(--accent); }
.alt-in:disabled { opacity: .6; }
/* En su propia línea y con permiso para partirse: es el dato que explica PARA QUÉ
   sirve el campo, y era justo el que se cortaba. */
.alt-m2 { margin-top: 5px; line-height: 1.35; }

.rev-ia { width: calc(100% - 16px); margin: 2px 8px 6px; justify-content: center; }
.rev-foot { margin: 4px 12px 10px; opacity: .8; }
/* El botón de repaso dentro de la burbuja del asistente: separado del texto, no pegado. */
.asis-fix { margin-top: 8px; }

/* EL REPASO DEL JEFE DE OBRA: la otra mitad de «revisar». Arriba lo que está mal
   dibujado; aquí lo que NO ESTÁ. Va separado por una línea y con el fondo un punto
   más apagado, porque no es una comprobación instantánea: se pide, tarda y cuesta. */
.rev-repaso { margin: 0 8px 10px; padding: 10px; background: var(--panel-2); border: 1px solid var(--line-soft); border-radius: var(--r-sm); }
.rev-rep-cab { display: flex; align-items: center; gap: 7px; margin-bottom: 5px; color: var(--text); }
.rev-rep-cab .ic { color: var(--accent); }
.rev-repaso > p { margin: 0 0 8px; font-size: 12px; line-height: 1.45; }
.rev-rep-btn { width: 100%; justify-content: center; }
.rev-rep-esp { animation: emp-lat 1.2s ease-in-out infinite; }
.rev-rep-err { color: var(--danger); }
.rev-rep-ok { color: var(--ok, var(--accent-2)); }
.rev-rep-item {
  padding: 8px 9px; margin-bottom: 5px; border-radius: var(--r-sm);
  background: var(--panel); border: 1px solid var(--line-soft); border-left: 3px solid var(--muted);
}
/* El color va por CERTEZA, no por importe: lo que decide si esto te para antes de
   enviar el presupuesto es si va a pasar, no cuántos euros son. */
.rev-rep-item.seguro { border-left-color: var(--danger); }
.rev-rep-item.probable { border-left-color: var(--warn); }
.rev-rep-item.preguntar { border-left-color: var(--accent); }
.rev-rep-tit { display: flex; align-items: baseline; gap: 8px; justify-content: space-between; }
.rev-rep-tit strong { font-size: 12.5px; color: var(--text); }
.rev-rep-cert { flex: none; font-size: 10.5px; color: var(--muted); white-space: nowrap; }
.rev-rep-item p { margin: 3px 0 6px; font-size: 12px; line-height: 1.45; color: var(--muted); }
/* El nombre de la partida viene de la IA: largo imprevisible. Se parte por palabras y,
   si aun así se pasa de tres líneas, se corta con puntos suspensivos — el título
   completo sigue en el `title` del botón y en el propio presupuesto. */
.rev-rep-part {
  margin: 0 0 6px !important; font-size: 11.5px; line-height: 1.4; color: var(--text-2);
  overflow-wrap: anywhere; display: -webkit-box; -webkit-line-clamp: 3; -webkit-box-orient: vertical; overflow: hidden;
}
.rev-rep-item .btn { width: 100%; justify-content: center; }
/* YA EN EL PRESUPUESTO: se queda a la vista pero apagada y al final de la lista. No se
   borra del repaso a propósito — saber lo que YA has cubierto es la mitad de un
   repaso—, pero tiene que distinguirse de un vistazo de lo que falta por hacer. */
.rev-rep-item.hecha { opacity: .62; border-left-color: var(--ok, var(--accent-2)); }
.rev-rep-cert.ok { display: inline-flex; align-items: center; gap: 4px; color: var(--ok, var(--accent-2)); }
.rev-rep-quitar {
  display: flex; align-items: center; gap: 6px; width: 100%; justify-content: center;
  padding: 5px 8px; font: inherit; font-size: 11.5px; color: var(--muted);
  background: none; border: 1px dashed var(--line); border-radius: var(--r-sm); cursor: pointer;
}
.rev-rep-quitar:hover { color: var(--text-2); border-color: var(--accent-line, var(--accent)); }
/* Ya no lleva scroll propio: rueda con `.rev-scroll`. Dos barras anidadas en un panel
   de 390 px es la forma más rápida de que no se encuentre ninguna de las dos. */
.rev-list { padding: 4px 8px; }
.rev-item {
  display: flex; gap: 9px; align-items: flex-start; width: 100%; padding: 9px 10px; margin-bottom: 4px;
  background: var(--panel-2); border: 1px solid var(--line-soft); border-left: 3px solid var(--muted);
  border-radius: var(--r-sm); color: var(--text-2);
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.rev-item:hover { background: var(--panel-3); }
/* El aviso es una COLUMNA: el texto arriba y, si la propuesta sabe arreglarlo, su
   botón debajo. El texto sigue siendo un botón (lleva al plano), así que el arreglo
   no puede ir dentro de él —un botón dentro de otro no es HTML válido y el clic se
   iría al de fuera—. */
.rev-body { flex: 1; min-width: 0; display: flex; flex-direction: column; align-items: flex-start; }
.rev-txt {
  width: 100%; min-width: 0; text-align: left; padding: 0; background: none; border: none;
  color: inherit; cursor: pointer; font: inherit;
}
/* El arreglo se ve SIEMPRE, no al pasar por encima como silenciar: es la acción
   principal del aviso, y una acción que hay que descubrir moviendo el ratón no la
   encuentra quien no sabe que existe. */
.rev-fix { margin-top: 8px; }
.rev-fix-btn { border-color: var(--accent-line); color: var(--text); }
.rev-fix-btn .ic { color: var(--accent); }
.rev-fix-btn:hover { border-color: var(--accent); background: var(--accent-soft); }
/* El botón de silenciar aparece al pasar por encima: es una salida, no una acción
   de todos los días. */
.rev-mute { opacity: 0; flex: 0 0 auto; }
.rev-item:hover .rev-mute, .rev-mute:focus-visible { opacity: 1; }
.rev-mudos {
  display: flex; align-items: center; gap: 7px; width: calc(100% - 16px); margin: 2px 8px 0;
  padding: 8px 10px; background: transparent; border: 1px dashed var(--line);
  border-radius: var(--r-sm); color: var(--muted); cursor: pointer; font: inherit; font-size: 12px;
}
.rev-mudos:hover { color: var(--text-2); border-color: var(--accent-line); }
.rev-ok .btn { margin-top: 8px; }
.rev-item strong { display: block; font-size: 13px; color: var(--text); }
.rev-item p { margin: 2px 0 0; font-size: 12px; line-height: 1.45; color: var(--muted); }
.rev-item.error { border-left-color: var(--danger); }
.rev-item.error .ic { color: var(--danger); }
.rev-item.aviso { border-left-color: var(--warn); }
.rev-item.aviso .ic { color: var(--warn); }
.rev-ok { display: flex; align-items: center; gap: 12px; padding: 18px 14px 20px; }
.rev-ok .ic { color: var(--accent-2); flex: 0 0 auto; }
.rev-ok p { margin: 3px 0 0; }


/* ---------- Modo presentación ----------
   Lo que ve el CLIENTE. Nada de mandos de edición: cifras grandes, el plano, la 3D
   en vivo, el antes/después y el total. */
.present {
  position: fixed; inset: 0; z-index: 300; display: flex; flex-direction: column;
  background: var(--bg); animation: fade-in .16s var(--ease);
}
.pres-bar {
  display: flex; align-items: center; gap: 10px; padding: 10px 16px;
  background: var(--panel); border-bottom: 1px solid var(--line);
}
.pres-bar .ic { color: var(--accent); }
.pres-tit { font-size: 12.5px; color: var(--muted); }
.pres-dots { display: flex; gap: 6px; margin: 0 6px; }
.pres-dot {
  width: 9px; height: 9px; padding: 0; border-radius: 50%; cursor: pointer;
  background: var(--panel-3); border: 1px solid var(--line);
}
.pres-dot.on { background: var(--accent); border-color: var(--accent); }
.pres-body { flex: 1; min-height: 0; display: flex; align-items: center; justify-content: center; padding: 26px; }

.pres-cover { display: flex; flex-direction: column; gap: 34px; width: min(980px, 100%); }
.pres-eyebrow { margin: 0 0 6px; color: var(--accent); font-size: 13px; letter-spacing: .08em; text-transform: uppercase; }
.pres-cover h1 { margin: 0; font-size: clamp(34px, 6vw, 62px); line-height: 1.05; letter-spacing: -.03em; }
.pres-sub { margin: 10px 0 0; color: var(--muted); font-size: 16px; }
.pres-kpis { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 14px; }
.pres-kpi {
  padding: 18px 20px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.pres-kpi strong { display: block; font-size: 25px; letter-spacing: -.02em; }
.pres-kpi span { display: block; margin-top: 4px; font-size: 12px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }

.pres-figura { display: flex; flex-direction: column; gap: 12px; align-items: center; width: 100%; height: 100%; }
.pres-img {
  flex: 1; min-height: 0; max-width: 100%; object-fit: contain;
  background: #fff; border: 1px solid var(--line); border-radius: var(--r-lg);
}
.pres-3d {
  flex: 1; width: min(1200px, 100%); min-height: 0; position: relative; overflow: hidden;
  border: 1px solid var(--line); border-radius: var(--r-lg); background: var(--canvas-bg);
}
.pres-3d canvas { display: block; width: 100%; height: 100%; }
.pres-pie { margin: 0; color: var(--muted); font-size: 12.5px; }

.pres-panel { width: min(940px, 100%); }
.pres-panel h2 { margin: 0 0 18px; font-size: 26px; letter-spacing: -.02em; }
.pres-mats { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 12px; }
.pres-mat {
  display: flex; gap: 14px; align-items: center; padding: 12px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg);
}
.pres-mat-img {
  width: 74px; height: 74px; flex: 0 0 auto; border-radius: var(--r); background-size: cover;
  background-position: center; border: 1px solid var(--line); display: grid; place-items: center; color: var(--muted);
}
.pres-mat-sup { margin: 0 0 2px; font-size: 11.5px; color: var(--accent); text-transform: uppercase; letter-spacing: .06em; }
.pres-mat strong { font-size: 15px; }
.pres-mat p:last-child { margin: 3px 0 0; }

.pres-lineas { display: flex; flex-direction: column; gap: 2px; margin-bottom: 22px; }
.pres-linea {
  display: flex; justify-content: space-between; padding: 13px 4px;
  border-bottom: 1px solid var(--line-soft); font-size: 16px;
}
.pres-total {
  display: flex; align-items: flex-end; justify-content: space-between; gap: 20px;
  padding-top: 16px; border-top: 2px solid var(--text);
}
.pres-total-n { margin: 2px 0 0; font-size: clamp(30px, 5vw, 46px); font-weight: 700; letter-spacing: -.03em; }

@media (max-width: 700px) {
  .pres-body { padding: 14px; }
  .pres-bar .pres-tit { display: none; }
}


/* Ajustes de la empresa */
.modal-empresa { width: min(560px, 96vw); }
.emp-logo { display: flex; gap: 14px; align-items: center; margin: 12px 0 4px; }
.emp-logo > div { display: flex; flex-direction: column; gap: 6px; }
.logo-prev {
  width: 96px; height: 64px; flex: 0 0 auto; display: grid; place-items: center;
  border: 1px dashed var(--line); border-radius: var(--r); color: var(--muted);
  background-size: contain; background-position: center; background-repeat: no-repeat;
  background-color: var(--panel-2);
}
.modal-form textarea {
  width: 100%; resize: vertical; padding: 9px 11px; font: inherit; font-size: 13.5px;
  background: var(--panel-2); color: var(--text); border: 1px solid var(--line); border-radius: var(--r);
}
.pres-logo { display: block; max-width: 220px; max-height: 70px; object-fit: contain; margin-bottom: 6px; }
.pres-marca { margin: 0 0 4px; font-weight: 700; letter-spacing: .02em; }

/* ---------- Asistente del plano (chat) ----------
   Cajón a la derecha, sobre el lienzo: se habla con él mientras se ve el plano
   cambiar detrás. */
.asis {
  /* `bottom` cuenta con la BARRA DE ESTADO (`.hintbar`, 28 px + borde): a 14 px la
     pastilla plegada se sentaba encima de «Área … · Esc 1:25». Lo que va fijo al
     viewport tiene que descontar lo que ya vive pegado al borde. */
  position: fixed; right: 14px; bottom: 42px; z-index: 240; width: min(390px, calc(100vw - 28px));
  max-height: min(620px, calc(100vh - 118px)); display: flex; flex-direction: column;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--sh-3); overflow: hidden; animation: modal-in .18s var(--ease);
}
.asis-cab { display: flex; align-items: center; gap: 8px; padding: 11px 12px; border-bottom: 1px solid var(--line); }
.asis-cab .ic { color: var(--accent); }
.asis-chapa { display: none; }

/* PLEGADO: la pastilla en reposo. Ocupa lo que un botón y deja el plano libre, pero el
   hilo entero sigue montado debajo — replegar no es cerrar, y la IA conserva el
   contexto de lo que lleváis hablado. Es además el ÚNICO acceso: por eso está siempre
   a la vista, que un botón de texto perdido entre otros seis se ve menos. */
.asis.plegado {
  width: auto; max-height: none; border-radius: 999px;
  box-shadow: var(--sh-2); cursor: pointer;
  transition: border-color .14s var(--ease), background .14s var(--ease);
}
.asis.plegado:hover { border-color: var(--accent); background: var(--panel-2); }
.asis.plegado .asis-hilo, .asis.plegado .asis-pie, .asis.plegado .asis-plegar,
.asis.plegado .spacer, .asis.plegado .asis-tit { display: none; }
.asis.plegado .asis-cab { border-bottom: 0; padding: 9px 15px 9px 13px; }
.asis.plegado .asis-chapa { display: inline; font-size: 13px; font-weight: 600; color: var(--text); }
/* El punto que dice que hay conversación esperando: sin él, replegar y olvidarse de
   que la tienes ahí es lo más fácil del mundo. */
.asis.plegado.con-hilo .asis-chapa::after {
  content: ''; display: inline-block; width: 6px; height: 6px; margin-left: 7px;
  border-radius: 50%; background: var(--accent); vertical-align: middle;
}
.asis-hilo { flex: 1; overflow-y: auto; padding: 12px; display: flex; flex-direction: column; gap: 10px; }
.asis-msg { max-width: 92%; padding: 9px 12px; border-radius: 12px; font-size: 13.5px; line-height: 1.5; }
.asis-msg p { margin: 0; }
.asis-msg.yo { align-self: flex-end; background: var(--accent); color: #fff; border-bottom-right-radius: 4px; }
.asis-msg.ia { align-self: flex-start; background: var(--panel-2); border: 1px solid var(--line); border-bottom-left-radius: 4px; }
.asis-msg.error { align-self: flex-start; background: rgba(255,95,109,.14); border: 1px solid rgba(255,95,109,.45); color: #ffb3ba; }
.asis-msg.pensando { opacity: .7; }
.asis-extra { margin-top: 6px !important; font-size: 12px; color: var(--muted); }
.asis-msg.yo .asis-extra { color: rgba(255,255,255,.8); }
.asis-pie { display: flex; gap: 8px; align-items: flex-end; padding: 10px 12px; border-top: 1px solid var(--line); background: var(--panel-2); }
.asis-campo {
  flex: 1; resize: none; padding: 8px 10px; font: inherit; font-size: 13.5px; line-height: 1.4;
  background: var(--panel); color: var(--text); border: 1px solid var(--line); border-radius: var(--r);
}
.asis-campo:focus { outline: none; border-color: var(--accent); }
.asis-pie .btn { height: 38px; }
@media (max-width: 700px) {
  .asis { left: 8px; right: 8px; bottom: 36px; width: auto; }
  /* Plegado en móvil NO se estira de lado a lado: es una pastilla, no una barra. */
  .asis.plegado { left: auto; right: 8px; width: auto; }
}

/* ---------- Multiempresa: chapa de empresa y aviso de soporte ---------- */
.empresa-chip {
  padding: 3px 10px; border: 1px solid var(--line); border-radius: 999px;
  background: var(--panel-2); color: var(--muted); font-size: 12px; white-space: nowrap;
}
.empresa-chip.soporte { border-color: var(--accent); color: var(--accent); }
/* El aviso de suplantación va FIJO y en un color que no se confunde con nada:
   estar dentro de los datos de un cliente no puede pasar desapercibido. */
/* El parche de `[hidden]` que había aquí ya no hace falta: lo cubre la regla global de
   arriba (buscar «`hidden` GANA SIEMPRE»), que resolvió la familia entera. */
.impersonando {
  display: flex; align-items: center; justify-content: center; gap: 12px;
  padding: 7px 14px; font-size: 13px;
  background: #7a4a12; color: #ffe9c7; border-bottom: 1px solid #a9691c;
}
:root[data-theme="claro"] .impersonando { background: #fde8c8; color: #7a4a12; border-bottom-color: #e6c48b; }
.impersonando .btn { background: rgba(255,255,255,.14); border-color: currentColor; color: inherit; }

/* ---------- Tablas de gestión (usuarios, empresas, tarifa) ---------- */
.tabla-cont { overflow-x: auto; margin-bottom: 18px; }
.tabla { width: 100%; border-collapse: collapse; font-size: 14px; }
.tabla th, .tabla td { padding: 9px 12px; text-align: left; border-bottom: 1px solid var(--line-soft); }
.tabla th { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); font-weight: 600; }
.tabla tbody tr:hover { background: var(--panel-2); }
.tabla tr.inactivo td { opacity: .55; }
/* Los mandos, en LÍNEA: `.icon-btn` es `display:grid` y en una celda se apilaban
   uno debajo de otro, dejando filas de tres pisos. */
.tabla td.acciones { text-align: right; white-space: nowrap; }
.tabla td.acciones { display: flex; gap: 4px; justify-content: flex-end; align-items: center; }
.tabla td.acciones .icon-btn { display: inline-grid; }
.tabla td .badge { margin-top: 0; }
.tabla td strong + .badge, .tabla td .badge + .badge { margin-left: 6px; }
.tabla.compacta th, .tabla.compacta td { padding: 5px 10px; font-size: 12.5px; }
.badge.warn { border-color: #b4741d; color: #e0a44a; }
.badge.ok { border-color: var(--accent); color: var(--accent); }
.sec-title { margin: 22px 0 10px; font-size: 15px; }

.kpis { display: flex; gap: 12px; flex-wrap: wrap; margin-bottom: 18px; }
.kpi {
  flex: 1 1 130px; background: var(--panel); border: 1px solid var(--line);
  border-radius: var(--r-lg); padding: 12px 14px;
}
.kpi b { display: block; font-size: 22px; line-height: 1.1; }
.kpi span { font-size: 11px; text-transform: uppercase; letter-spacing: .05em; color: var(--muted); }

/* ---------- Tarifa de la empresa ---------- */
.tarifa-grid { display: grid; grid-template-columns: 1fr auto; gap: 8px 14px; align-items: center; }
.tarifa-grid input { width: 110px; text-align: right; }
.tarifa-sec { margin: 16px 0 8px; font-size: 13px; color: var(--muted); text-transform: uppercase; letter-spacing: .05em; }
@media (max-width: 700px) {
  .tabla th:nth-child(2), .tabla td:nth-child(2) { display: none; }
}

/* ---------- Mi catálogo (materiales de la empresa) ----------
   OJO con los nombres: `.mat-*` ya es del selector de acabados del editor, y
   reutilizarlo aquí convertía la ficha en una rejilla de dos columnas con la
   muestra de color hecha una tira. Prefijo propio, `cat-`. */
.cat-grid { grid-template-columns: repeat(auto-fill, minmax(230px, 1fr)); }
.cat-card { display: block; padding: 0; overflow: hidden; }
.cat-muestra { height: 96px; background-size: cover; background-position: center; border-bottom: 1px solid var(--line); }
.cat-info { padding: 12px 14px 14px; }
.cat-info h3 { margin: 0 0 2px; font-size: 15px; }
.cat-info .badge { margin: 8px 6px 0 0; }
/* Estado vacío con salida: una pantalla en blanco no dice qué hacer. */
.vacio {
  text-align: center; padding: 46px 20px; border: 1px dashed var(--line);
  border-radius: var(--r-lg); background: var(--panel);
}
.vacio h3 { margin: 0 0 6px; }
.vacio p { max-width: 460px; margin: 0 auto 16px; }
.tarifa-els { max-height: 260px; overflow-y: auto; padding-right: 4px; }
/* Un precio PROPIO se distingue del orientativo del catálogo de un vistazo. */
.tarifa-els input.propio { border-color: var(--accent); }
#whoami.clickable { cursor: pointer; }
#whoami.clickable:hover { color: var(--text); text-decoration: underline; }

/* ---------- Plano de distribución de la vivienda ---------- */
.page-ancha { max-width: 1400px; }
.dist-lienzo {
  height: 560px; background: var(--canvas-bg); border: 1px solid var(--line);
  border-radius: var(--r-lg); overflow: hidden; margin-bottom: 10px;
}

/* ---------- Vista de obra (a pie de tajo) ----------
   Dedos con guantes y pantalla al sol: casillas grandes, contraste alto y nada
   que se pueda tocar sin querer. */
.obra-progreso {
  position: relative; height: 30px; background: var(--panel-2); border: 1px solid var(--line);
  border-radius: 999px; overflow: hidden; margin-bottom: 18px;
}
.obra-barra { height: 100%; width: 0; background: var(--accent); transition: width .25s var(--ease); }
.obra-progreso.completo .obra-barra { background: var(--accent-2); }
.obra-pct {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 13px; font-weight: 600; color: var(--text);
}
.obra-cols { display: grid; grid-template-columns: 1fr 400px; gap: 22px; align-items: start; }
.obra-mini { position: sticky; top: 70px; background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg); padding: 12px; }
.obra-mini .plan-prev { width: 100%; height: 260px; color: var(--text-2); }
.obra-tarea {
  display: flex; align-items: center; gap: 14px; padding: 13px 14px; margin: 0 0 8px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
  cursor: pointer; user-select: none;
}
.obra-tarea:hover { border-color: var(--accent-line); }
.obra-tarea input { width: 26px; height: 26px; flex: none; accent-color: var(--accent-2); cursor: pointer; }
.obra-txt { flex: 1; }
.obra-tarea.hecha { background: var(--panel-2); }
.obra-tarea.hecha .obra-txt { text-decoration: line-through; opacity: .6; }
.obra-firma { font-size: 11.5px; color: var(--muted); white-space: nowrap; }
@media (max-width: 900px) {
  .obra-cols { grid-template-columns: 1fr; }
  .obra-mini { position: static; order: -1; }
}

/* ---------- Editor en MÓVIL: los laterales pasan a ser cajones ----------
   Con paleta y panel fijos, en 400 px el plano se quedaba en una tira de 120 px.
   Aquí se abren por encima del lienzo, con velo, y se cierran al tocar fuera o al
   elegir una pieza. La barra inferior es lo único que ocupa sitio siempre. */
.movil-bar { display: none; }
.cajon-velo { display: none; }
@media (max-width: 760px) {
  /* `overflow: hidden` no es cosmético: el cajón derecho, aparcado en
     `translateX(102%)`, asomaba fuera y dejaba la página con scroll horizontal. */
  .editor-body { position: relative; overflow: hidden; }
  /* El lienzo pasa a ocupar TODO: los laterales ya no reservan sitio. */
  .editor-body > .canvas { flex: 1 1 100%; width: 100%; }
  .palette, .right {
    position: absolute; top: 0; bottom: 0; z-index: 12;
    width: min(78vw, 300px); max-width: none;
    transform: translateX(-102%); transition: transform .2s var(--ease);
    box-shadow: var(--sh-3);
  }
  .palette { left: 0; }
  .right { right: 0; transform: translateX(102%); }
  .palette.abierto, .right.abierto { transform: translateX(0); }
  .palette .pal-grid { grid-template-columns: 1fr 1fr; }
  .cajon-velo {
    display: block; position: absolute; inset: 0; z-index: 11;
    background: rgba(0,0,0,.45); opacity: 0; pointer-events: none;
    transition: opacity .2s var(--ease);
  }
  .cajon-velo.visible { opacity: 1; pointer-events: auto; }
  /* Barra inferior: los dos accesos, con área de toque de verdad. */
  .movil-bar {
    display: flex; gap: 8px; padding: 8px 10px;
    background: var(--panel); border-top: 1px solid var(--line);
  }
  .movil-bar .btn { flex: 1; justify-content: center; height: 42px; }
  /* La ayuda de abajo se come una línea entera de una pantalla pequeña. */
  .hintbar { display: none; }
  /* La barra de herramientas ocupaba TRES filas de las nueve que caben. Fuera lo
     informativo (escala, área) y las etiquetas largas: los iconos se entienden. */
  #ed-zoom, .toolbar .rejilla-lbl, .toolbar .area-lbl { display: none; }
  .toolbar { gap: 4px; padding: 5px 7px; }
  .toolbar .btn.small { padding: 5px 7px; }
}

/* ---------- Desplegable «Ver» (estado de la vista) ----------
   Cuelga de su botón en la barra. Nada flota sobre el plano: aparece donde lo
   pides y se va al soltar. */
.ver-btn.activo { border-color: var(--accent); background: var(--accent-soft); color: var(--text); }
.ver-btn.con-ocultas { border-color: var(--warn); }
.ver-punto {
  display: inline-grid; place-items: center; min-width: 16px; height: 16px; padding: 0 4px;
  margin-left: 2px; border-radius: 999px; background: var(--warn); color: #201400;
  font-size: 10.5px; font-weight: 700; line-height: 1;
}
.pop {
  position: fixed; z-index: 300; width: 268px; padding: 12px 14px 14px;
  background: var(--panel-2); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: var(--sh-3); animation: menu-in .12s var(--ease);
}
.pop-tit {
  margin: 0 0 6px; font-size: 10.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
}
.pop-sep { height: 1px; background: var(--line); margin: 14px -14px 12px; }
/* Cada fila: etiqueta a la izquierda, mando a la derecha, alineados en columna.
   Es lo que hace que una lista de ocho controles se lea como una lista y no como
   un montón de casillas sueltas. */
.pop-fila {
  display: flex; align-items: center; gap: 10px; min-height: 30px;
  margin: 0; padding: 0; cursor: pointer; user-select: none;
}
.pop-lbl { flex: 1; font-size: 13.5px; color: var(--text); }
.pop-fila select { width: 96px; padding: 4px 7px; }
/* Marca de «capa activa»: solo se ve al pasar el ratón o cuando está puesta. */
.pop-activa {
  display: grid; place-items: center; width: 22px; height: 22px; padding: 0;
  background: none; border: 0; border-radius: var(--r-sm); color: var(--muted);
  opacity: 0; cursor: pointer; transition: opacity .12s var(--ease);
}
.pop-fila:hover .pop-activa { opacity: .6; }
.pop-activa.on, .pop-activa:hover { opacity: 1; color: var(--accent); }

/* Interruptor. Un `checkbox` de sistema en una lista de ocho se ve a rayas; esto
   da una columna limpia y un objetivo de toque decente. */
/* OJO con la especificidad: las filas de capa conservan `.layer-row` (los tests
   las buscan así) y `.layer-row span { flex: 1 }` estiraba el interruptor hasta
   los 98 px. Por eso el selector va prefijado con `.pop`. */
.pop .sw, .sw { position: relative; display: inline-block; width: 34px; height: 20px; flex: 0 0 34px; }
.sw-in { position: absolute; inset: 0; opacity: 0; margin: 0; cursor: pointer; }
.sw-track {
  position: absolute; inset: 0; border-radius: 999px; background: var(--panel-3);
  border: 1px solid var(--line); transition: background .15s var(--ease), border-color .15s var(--ease);
}
.sw-track::after {
  content: ''; position: absolute; top: 2px; left: 2px; width: 14px; height: 14px;
  border-radius: 50%; background: var(--muted); transition: transform .15s var(--ease), background .15s var(--ease);
}
.sw-in:checked + .sw-track { background: var(--accent-soft); border-color: var(--accent-line); }
.sw-in:checked + .sw-track::after { transform: translateX(14px); background: var(--accent); }
.sw-in:focus-visible + .sw-track { outline: 2px solid var(--accent); outline-offset: 2px; }
.pop .ver-atajo { width: 100%; justify-content: center; margin-top: 10px; }
.pop .bg-controls { border: 0; padding: 0; margin: 10px 0 0; }
.pop .bg-controls p { margin: 0 0 8px; }
.pop .bg-controls .btn { width: 100%; justify-content: center; }


/* Cuerpo del desplegable «Ver». Antes de esto fue una tarjeta fija sobre el
   lienzo: se descartó porque tapaba el plano y competía con el navegador. */
.ver-body { display: flex; flex-direction: column; }

/* Diálogo de plantillas: con veintitantas, por grupos y con buscador. */
.modal-tpl { width: min(720px, 94vw); }
.modal-tpl input[type="search"] { margin-bottom: 4px; }
.tpl-cuerpo { max-height: 54vh; overflow-y: auto; margin: 6px -4px 4px; padding: 0 4px; }
.tpl-grupo {
  margin: 14px 0 8px; font-size: 10.5px; font-weight: 600; letter-spacing: .07em;
  text-transform: uppercase; color: var(--muted);
}
.tpl-cuerpo .tpl-grupo:first-child { margin-top: 4px; }
.empresa-chip.clickable { cursor: pointer; }
.empresa-chip.clickable:hover { border-color: var(--accent-line); color: var(--text); }

/* Miga de pan renombrable: el lápiz solo aparece al pasar por encima. */
.crumb-edit {
  display: inline-flex; align-items: center; gap: 5px; padding: 2px 6px;
  background: none; border: 1px solid transparent; border-radius: var(--r-sm);
  color: inherit; font: inherit; cursor: pointer;
}
.crumb-edit svg { opacity: 0; transition: opacity .12s var(--ease); }
.crumb-edit:hover { border-color: var(--line); background: var(--panel-2); }
.crumb-edit:hover svg { opacity: .7; }

/* Menú de empresa: mismo desplegable que «Ver», con dos líneas por opción. */
.pop-emp { width: 280px; padding: 6px; }
.pop-item {
  display: flex; align-items: flex-start; gap: 10px; width: 100%; padding: 9px 10px;
  background: none; border: 0; border-radius: var(--r); color: var(--text);
  font: inherit; text-align: left; cursor: pointer;
}
.pop-item:hover { background: var(--panel-3); }
.pop-item svg { margin-top: 2px; color: var(--muted); flex: none; }
.pop-item strong { display: block; font-weight: 600; font-size: 13.5px; }
.pop-item .small { display: block; line-height: 1.35; }
.emp-btn .chev, .exp-btn .chev { opacity: .6; font-size: 10px; margin-left: 2px; }

/* EXPORTAR: todo lo que sale del editor, en dos grupos (cliente / obra). Sustituye
   al menú ⋯ y al icono de descarga que hacía una sola de las seis cosas. */
.exp-btn.activo { color: var(--text); border-color: var(--accent-line); background: var(--panel-3); }
.pop-exp { width: 300px; padding: 8px; }
.pop-exp .pop-tit { margin: 8px 8px 4px; }
.pop-exp .pop-tit:first-child { margin-top: 2px; }

/* --- Pantalla de arranque del lienzo vacío -------------------------------
   Un plano en blanco no es un estado: es una pregunta («¿y ahora qué?»), y es la
   pantalla que más gente ve por primera vez. Manda la comodidad del que no sabe de
   planos: dos clics con dibujos delante, la caja de texto A LA VISTA (no detrás de
   un botón) y lo demás en el pie. El envoltorio NO captura el ratón —se puede
   seguir moviendo la vista por detrás—; solo la tarjeta. Se va sola al haber paredes. */
.empezar {
  position: absolute; inset: 0; z-index: 5;
  display: flex; align-items: center; justify-content: center;
  padding: 16px; pointer-events: none;
}
.emp-card {
  pointer-events: auto; position: relative;
  width: min(680px, 100%); max-height: 100%; overflow: auto;
  padding: 22px 22px 16px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-lg);
  box-shadow: 0 18px 48px rgba(0,0,0,.34);
  animation: emp-in .18s var(--ease) both;
}
@keyframes emp-in { from { opacity: 0; transform: translateY(6px) scale(.99); } }
.emp-card h3 { margin: 0 0 3px; font-size: 17px; }
.emp-card > p { margin: 0 0 12px; max-width: 52ch; }
.emp-x { position: absolute; top: 10px; right: 10px; }

/* Título de paso, con su número en una chapa: en una pantalla con tres caminos, sin
   numerar no se sabe cuál es «el» camino. */
.emp-tit {
  display: flex; align-items: center; gap: 8px;
  margin: 0 0 9px; font-size: 13px; font-weight: 600; color: var(--text);
}
.emp-num {
  flex: none; display: grid; place-items: center; width: 19px; height: 19px;
  font-size: 11.5px; font-weight: 700; border-radius: 999px;
  color: var(--accent); background: var(--accent-soft, rgba(90,150,255,.14));
}

/* PASO 1: qué estancia. Botones anchos con el símbolo en planta — se reconoce antes
   que el texto, y es el mismo dibujo que verá luego en el plano. */
.emp-tipos { display: flex; flex-wrap: wrap; gap: 8px; }
.emp-tipo {
  display: flex; align-items: center; gap: 7px; flex: 1 1 108px;
  padding: 10px 12px; margin: 0; cursor: pointer; font: inherit; font-size: 13px;
  color: var(--text); background: var(--panel-2);
  border: 1px solid var(--line); border-radius: var(--r);
  transition: border-color .16s var(--ease), background .16s var(--ease), transform .16s var(--ease);
}
.emp-tipo:hover { border-color: var(--accent); background: var(--panel-3); transform: translateY(-1px); }
.emp-tipo:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.emp-tipo.on { border-color: var(--accent); background: var(--panel-3); color: var(--text); font-weight: 600; }
.emp-tipo.on svg { color: var(--accent); }

/* PASO 2: cuál se parece. La planta dibujada manda; el nombre y las medidas la
   acompañan. Es la misma miniatura que la galería de plantillas y que las estancias
   guardadas: si mejora una, mejoran las tres. */
.emp-paso2:not(:empty) { margin-top: 13px; }
.emp-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); gap: 8px; }
.emp-tpl {
  display: flex; flex-direction: column; gap: 2px; align-items: stretch; text-align: left;
  padding: 7px; margin: 0; cursor: pointer; font: inherit;
  color: var(--text); background: var(--panel-2);
  border: 1px solid var(--line); border-radius: var(--r);
  transition: border-color .16s var(--ease), background .16s var(--ease), transform .16s var(--ease);
}
.emp-tpl:hover { border-color: var(--accent); background: var(--panel-3); transform: translateY(-1px); }
.emp-tpl:focus-visible { outline: 2px solid var(--accent); outline-offset: 2px; }
.emp-prev {
  display: block; border: 1px solid var(--line); border-radius: var(--r-sm);
  background: var(--panel); overflow: hidden; margin-bottom: 3px;
}
.emp-prev svg, .emp-prev img { display: block; width: 100%; height: auto; }
.emp-tpl-n { font-size: 12.5px; font-weight: 600; line-height: 1.25; }

.emp-medidas {
  display: flex; flex-wrap: wrap; align-items: center; gap: 7px;
  margin-top: 10px; padding: 9px 11px;
  background: var(--panel-2); border: 1px dashed var(--line); border-radius: var(--r);
}
.emp-med {
  width: 74px; padding: 5px 7px; font: inherit; font-size: 13px;
  color: var(--text); background: var(--panel); border: 1px solid var(--line); border-radius: var(--r-sm);
}

/* Separador con texto: marca que lo de abajo es OTRO camino, no el paso siguiente. */
.emp-o {
  display: flex; align-items: center; gap: 10px; margin: 14px 0 9px;
  font-size: 12px; color: var(--muted);
}
.emp-o::before, .emp-o::after { content: ''; flex: 1; height: 1px; background: var(--line); }

.emp-decir { display: flex; gap: 8px; align-items: stretch; }
.emp-campo {
  flex: 1; min-width: 0; resize: vertical; padding: 9px 11px; font: inherit; font-size: 13.5px;
  background: var(--panel-2); color: var(--text);
  border: 1px solid var(--line); border-radius: var(--r);
}
.emp-campo:focus { outline: none; border-color: var(--accent); }
.emp-decir-bts { display: flex; flex-direction: column; gap: 6px; justify-content: center; }
.emp-decir-bts .btn { white-space: nowrap; }
/* Grabando: el punto que late. Un botón que solo cambia de texto no se ve mientras
   hablas mirando a otro lado. */
.emp-mic.grabando { border-color: var(--danger, #e5484d); color: var(--danger, #e5484d); }
.emp-mic.grabando svg { animation: emp-lat 1.1s ease-in-out infinite; }
@keyframes emp-lat { 50% { opacity: .3; } }

.emp-ejs { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 8px; }
.emp-ej {
  padding: 4px 10px; margin: 0; cursor: pointer; font: inherit; font-size: 12px;
  color: var(--muted); background: none;
  border: 1px solid var(--line); border-radius: 999px;
}
.emp-ej:hover { color: var(--text); border-color: var(--accent-line, var(--accent)); background: var(--panel-2); }

.emp-pie {
  display: flex; flex-wrap: wrap; gap: 4px; justify-content: center;
  margin: 13px -6px 0; padding-top: 10px; border-top: 1px solid var(--line);
}
.emp-otra {
  display: flex; align-items: center; gap: 6px; padding: 6px 10px;
  font: inherit; font-size: 12.5px; color: var(--muted);
  background: none; border: 0; border-radius: var(--r-sm); cursor: pointer;
}
.emp-otra:hover { color: var(--text); background: var(--panel-2); }

@media (max-width: 720px) {
  .emp-card { padding: 18px 16px 12px; }
  .emp-tipo { flex: 1 1 46%; }
  .emp-grid { grid-template-columns: repeat(auto-fill, minmax(128px, 1fr)); }
  .emp-decir { flex-direction: column; }
  .emp-decir-bts { flex-direction: row; }
  .emp-decir-bts .btn { flex: 1; justify-content: center; }
}

/* --- Diálogo del PDF -----------------------------------------------------
   Un documento es PARA ALGUIEN: primero se elige el destinatario y solo después,
   si hace falta, se toca la lista de secciones. */
.modal-pdf { width: min(560px, 94vw); }
.pdf-presets { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; margin: 12px 0 4px; }
.pdf-preset {
  display: block; text-align: left; padding: 10px; margin: 0; cursor: pointer;
  color: var(--text); background: var(--panel-2);
  border: 1px solid var(--line); border-radius: var(--r);
  transition: border-color .16s var(--ease), background .16s var(--ease);
}
.pdf-preset:hover { border-color: var(--accent-line); background: var(--panel-3); }
.pdf-preset.sel { border-color: var(--accent); background: var(--accent-soft); }
.pdf-preset strong { display: block; font-size: 13px; margin-bottom: 2px; }
.pdf-preset .small { display: block; line-height: 1.3; }
.pdf-libre {
  grid-column: 1 / -1; justify-self: start; padding: 2px 8px;
  font-size: 11px; font-weight: 600; color: var(--accent);
  background: var(--accent-soft); border-radius: 999px;
}
.pdf-sep { height: 1px; background: var(--line); margin: 14px 0 10px; }
.pdf-tit { margin: 0 0 6px; font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase; color: var(--muted); }
.pdf-secs { display: grid; grid-template-columns: 1fr 1fr; gap: 2px 14px; max-height: 40vh; overflow-y: auto; }
.pdf-sec { display: flex; gap: 8px; align-items: flex-start; padding: 5px 2px; cursor: pointer; }
/* La regla global pone width:100% a TODO input, y una casilla con ancho de campo de
   texto empuja la etiqueta y parte cada palabra. Aqui se le da su tamano. */
.pdf-sec input { flex: none; width: 15px; height: 15px; min-width: 15px; margin: 2px 0 0; padding: 0; }
.pdf-sec > span { min-width: 0; }
.pdf-sec strong { display: block; font-size: 12.5px; font-weight: 500; }
.pdf-sec .small { display: block; line-height: 1.3; }
.pdf-aviso { margin: 10px 0 0; }
.pdf-estado { margin: 4px 0 0; min-height: 1.2em; color: var(--accent); }
.pdf-estado.error { color: var(--danger); }

@media (max-width: 620px) {
  .pdf-presets, .pdf-secs { grid-template-columns: 1fr; }
}

/* --- Ayuda de la barra superior -----------------------------------------
   Los atajos se leen de arriba abajo buscando uno concreto, así que la ventana
   scrollea sola y los títulos de sección se quedan pegados: con 27 filas, sin eso
   pierdes de vista a qué ámbito pertenece la que estás mirando. */
.pop-ayuda { width: 272px; padding: 8px; }
.modal-ayuda { width: min(600px, 94vw); }
.ayuda-cuerpo { max-height: 62vh; overflow-y: auto; margin: 12px 0 4px; padding-right: 4px; }
.ayuda-grupo {
  position: sticky; top: 0; z-index: 1; margin: 0 0 6px; padding: 6px 0 4px;
  font-size: 11px; font-weight: 600; letter-spacing: .06em; text-transform: uppercase;
  color: var(--muted); background: var(--panel);
}
.ayuda-cuerpo .help-list:not(:last-child) { margin-bottom: 4px; }

/* La plantilla que está puesta ahora mismo, marcada en el selector: probar plantillas
   es comparar, y sin saber de cuál vienes no se puede comparar. */
.tpl-card.actual { border-color: var(--accent); background: var(--accent-soft); }
.tpl-actual {
  align-self: flex-start; margin-bottom: 4px; padding: 1px 7px;
  font-size: 10.5px; font-weight: 600; color: var(--accent);
  background: var(--panel); border-radius: 999px;
}
.pdf-opcion { grid-column: 1 / -1; padding: 2px 2px 0; }

/* Aviso de conflicto: dos personas en la misma estancia. Es un alto en el camino, no
   un toast — hay que leerlo y decidir, así que no se cierra tocando fuera. */
.modal-conf { width: min(500px, 94vw); }
.modal-conf h3 { display: flex; align-items: center; gap: 8px; color: var(--warn); }
.modal-conf p { margin: 10px 0 0; }
.conf-acciones { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-end; margin-top: 18px; }
.conf-acciones .btn.danger { color: #ffc3c8; border-color: rgba(255,95,109,.5); background: rgba(255,95,109,.14); }
.conf-acciones .btn.danger:hover { background: rgba(255,95,109,.22); }

/* --- Documentos compartidos --------------------------------------------- */
.enl-tabla { display: flex; flex-direction: column; gap: 2px; margin-top: 12px; }
.enl-fila {
  display: grid; grid-template-columns: 1fr 110px 110px 90px 120px; gap: 12px;
  align-items: center; padding: 10px 12px;
  background: var(--panel); border: 1px solid var(--line); border-radius: var(--r);
  font-size: 13px;
}
.enl-fila strong { display: block; }
.enl-fila .small { display: block; }
.enl-cab {
  background: none; border: 0; padding: 0 12px 2px;
  font-size: 11px; font-weight: 600; letter-spacing: .05em; text-transform: uppercase; color: var(--muted);
}
.enl-num { text-align: right; }
.enl-acts { display: flex; gap: 4px; justify-content: flex-end; }
/* Un enlace retirado se sigue viendo, en gris: saber que YA no vale es tan útil como
   saber que vale. */
.enl-fila.muerto { opacity: .55; }
.enl-fila.muerto strong { text-decoration: line-through; }

@media (max-width: 760px) {
  .enl-fila { grid-template-columns: 1fr auto; gap: 6px; }
  .enl-cab { display: none; }
  .enl-acts { grid-column: 2; grid-row: 1 / span 3; }
}
.enl-plegar { margin-top: 12px; }
/* El parche de `[hidden]` de aquí también se retiró: lo cubre la regla global. */
