/* Keedian Proposal Wizard — UI conforme al design system de keedian-platform-guide.
   Tokens: 04-design-system/tokens/colors.md + components.md + design-principles.md */
:root {
  --color-black: #000000;
  --color-white: #FFFFFF;
  --brand-active-bg: #CFDEFF;  /* solo estado activo/seleccionado */
  --brand-blue: #3372FF;       /* solo hover/interactivo */
  --navy-deep: #002475;
  --navy-rgb: 0, 36, 117;      /* canales del navy para sombras/overlays con opacidad (rgba) */
  --border-soft: #B89CF9;
  --app-bg: #EEF2FF;

  /* Paleta de estado (chips) */
  --status-green-bg:  #D4F4E2;  --status-green-tx:  #1A7A45;
  --status-gray-bg:   #E8E8E8;  --status-gray-tx:   #5A5A5A;
  --status-pink-bg:   #FFD6E7;  --status-pink-tx:   #B5195A;  /* danger / error */
  --status-pink-tx-strong: #800f3d;  /* hover de danger */
  --status-red-bg:    #FDECEC;  --status-red-tx:    #C62828;  /* rojo destructivo (acciones de borrado) */
  --status-red-tx-strong: #8E1515;  /* hover del rojo destructivo */
  --status-blue-bg:   #D0E8FF;  --status-blue-tx:   #1A5FA8;
  --status-orange-bg: #FFE5CC;  --status-orange-tx: #A04A00;

  /* Avisos (notices) y superficies funcionales */
  --notice-bg: #FFF7CC;  --notice-tx: #7A6200;  /* aviso informativo */
  --warn-bg:   #FFF0E0;  --warn-tx:   #8A4B00;  /* advertencia */
  --panel-soft: #FAFBFF;  /* fondo suave de paneles (eq-block, formularios) */
  --row-hover:  #F5F7FF;  /* hover de filas de tabla */

  /* Neutros funcionales (de components.md: disabled) */
  --disabled-bg: #D9D9D9;
  --disabled-tx: #9E9E9E;

  --text-muted: #5A5A5A;
  --divider: #E4E8F2;          /* neutro suave para densidad de tabla */

  /* Paleta de dataviz (gráficos de ROI, Chart.js — ver public/proposals-roi.js).
     No tienen equivalente exacto en la paleta de UI: son colores específicos de gráfico. */
  --dataviz-blue-light: #A9C0FF;  /* barra de ahorros (cashflow) */
  --dataviz-gray:       #9aa3b2;  /* barra de implementación / serie conservadora (drivers) */
  --dataviz-ink:        #111111;  /* barra de costo recurrente (cashflow) */
  --dataviz-green:      #16C79A;  /* línea de neto acumulado (cashflow) */

  --font-sans: 'Funnel Sans', system-ui, -apple-system, Segoe UI, Roboto, sans-serif;
  --font-mono: 'Roboto Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
}

* { box-sizing: border-box; }

body {
  margin: 0;
  font-family: var(--font-sans);
  font-size: 14px;
  line-height: 1.5;
  background: var(--app-bg);
  color: var(--color-black);
}

/* Datos técnicos / numéricos en Roboto Mono */
.mono { font-family: var(--font-mono); }

/* --- Topbar -------------------------------------------------- */
.topbar {
  display: flex; align-items: center; gap: 12px;
  height: 56px; padding: 0 24px;
  background: var(--color-white);
  border-bottom: 1px solid var(--divider);
}
.topbar .brand { font-weight: 700; font-size: 16px; }
.topbar .app-name { color: var(--text-muted); font-size: 13px; }
.nav { display: flex; gap: 4px; margin-left: 24px; }
.nav a {
  text-decoration: none; color: var(--text-muted); font-weight: 500;
  padding: 6px 12px; border-radius: 8px;
}
.nav a:hover { background: var(--brand-active-bg); color: var(--brand-blue); }
.nav a.active { color: var(--color-black); background: var(--brand-active-bg); }
.nav-group { position: relative; }
.nav-trigger {
  background: none; border: none; cursor: pointer; font: inherit; font-weight: 500;
  color: var(--text-muted); padding: 6px 12px; border-radius: 8px;
}
.nav-trigger:hover { background: var(--brand-active-bg); color: var(--brand-blue); }
.nav-group.has-active .nav-trigger { color: var(--color-black); background: var(--brand-active-bg); }
.nav-menu {
  position: absolute; top: 100%; left: 0; margin-top: 4px;
  background: var(--color-white); border: 1px solid var(--divider); border-radius: 8px;
  box-shadow: 0 4px 12px rgba(var(--navy-rgb), .08);
  min-width: 180px; padding: 4px; display: none; z-index: 100;
}
.nav-group.open .nav-menu { display: block; }
.nav-menu a { display: block; padding: 8px 12px; border-radius: 6px; }
.nav-menu a:hover { background: var(--brand-active-bg); color: var(--brand-blue); }
.topbar { flex-wrap: wrap; min-height: 56px; height: auto; padding-top: 8px; padding-bottom: 8px; }
.topbar-cta { margin-left: auto; text-decoration: none; padding: 6px 14px; font-size: 13px; white-space: nowrap; }
.lang-toggle { display: flex; gap: 4px; }
.fmt-menu { min-width: 200px; padding: 10px; }
.fmt-section { margin-bottom: 8px; }
.fmt-label { font-size: 12px; color: var(--text-muted); margin-bottom: 4px; }
.fmt-opt, .fmt-dec, .fmt-date {
  display: inline-block; margin: 2px 4px 2px 0; padding: 4px 10px; cursor: pointer; font: inherit; font-size: 13px;
  background: transparent; border: 1px solid var(--divider); border-radius: 6px; color: var(--color-black);
}
.fmt-opt:hover, .fmt-dec:hover, .fmt-date:hover { background: var(--brand-active-bg); }
.fmt-opt.active, .fmt-dec.active, .fmt-date.active { background: var(--brand-active-bg); color: var(--brand-blue); border-color: var(--brand-blue); }
.lang-toggle button {
  background: transparent; border: 1px solid var(--divider); color: var(--text-muted);
  border-radius: 6px; padding: 4px 10px; font-size: 12px; font-weight: 500; cursor: pointer;
}
.lang-toggle button.active { background: var(--brand-active-bg); color: var(--brand-blue); border-color: var(--brand-blue); }
.totals-row { display: flex; gap: 24px; flex-wrap: wrap; color: var(--text-muted); font-size: 13px; }
.totals-row .grand { color: var(--color-black); font-weight: 700; font-size: 15px; }
/* Costo total en la barra del sitio: separado del desglose por un divisor a la izquierda. */
.totals-row .tot-sep { border-left: 1px solid var(--divider); padding-left: 24px; }
/* Punto 1: la barra de resumen del sitio se separa de la tabla de Proyecto solo con más espacio. */
.site-ro-totals { margin-top: 20px; }
.notice { background: var(--notice-bg); color: var(--notice-tx); padding: 10px 14px; border-radius: 8px; font-size: 13px; margin-bottom: 14px; }
/* Editor de costos por sitio — diseño compacto: con varios sitios esta sección se repite,
   así que reducimos cajas, fuente y espacios para que entre más en pantalla. */
/* Editor de costos en dos grupos: "Parámetros base" y "Parámetros de instalación".
   Cada grupo es un recuadro suave a TODO el ancho (apilados, como el bloque de equipo). */
.costs-edit { display: flex; flex-direction: column; gap: 12px; margin-bottom: 12px; }
.cost-group { border: 1px solid var(--divider); border-radius: 10px; padding: 10px 12px; background: var(--panel-soft); }
.cost-group-h { font-size: 11px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; color: var(--text-muted); margin-bottom: 8px; }
.cost-fields { display: flex; align-items: flex-end; gap: 8px 10px; flex-wrap: wrap; }
.costs-edit label { display: flex; flex-direction: column; gap: 2px; color: var(--text-muted); font-size: 11.5px; }
/* El label oculto (modo no elegido) debe DESAPARECER: el display:flex de arriba pisaba el
   atributo [hidden], por eso se veían las dos cajas (monto total + por hora) a la vez. */
.costs-edit label[hidden] { display: none; }
.costs-edit label input, .costs-edit label select { color: var(--color-black); padding: 5px 8px; font-size: 13px; border-radius: 6px; }
.costs-edit label input { width: 150px; }
.costs-edit label input.pct { width: 76px; }
.costs-edit label select { width: 168px; }
.costs-edit #saveCosts { padding: 6px 14px; }
/* Nota de prorrateo: dentro del card de instalación, debajo de los campos. */
.inst-mode-note { display: block; margin-top: 8px; }
/* Inputs/selects del editor de sitio compactos (form de alta, cantidades por línea, etc.). */
#siteEditor .filters { gap: 8px; }
#siteEditor input, #siteEditor select { padding: 5px 8px; font-size: 13px; }

/* --- Equipos (kits) en la propuesta — compacto (se repite por equipo y por sitio) --- */
/* Encabezado del alta de dispositivo (form siempre visible, sin botón previo). */
.add-device-head { display: flex; align-items: baseline; gap: 10px; margin-bottom: 8px; flex-wrap: wrap; }
.add-device-head strong { font-size: 13px; }
.eq-block { border: 1px solid var(--divider); border-radius: 10px; padding: 10px 12px; margin-bottom: 10px; background: var(--panel-soft); }
.eq-head { display: flex; align-items: center; gap: 8px; margin-bottom: 6px; flex-wrap: wrap; }
.eq-head .eq-name { font-weight: 700; min-width: 180px; }
.eq-head .eq-qty { width: 70px; }
.eq-head .eq-x { color: var(--text-muted); }
.eq-add { margin-top: 8px; }
.eq-add .eq-dev { min-width: 240px; }
/* Botón "+ Agregar dispositivo": contained, compacto y alineado a la derecha de la fila
   (margin-left auto) para que su posición no cambie aunque se oculten checkboxes (p. ej. licencias). */
.eq-addline { padding: 6px 12px; font-size: 13px; margin-left: auto; }
.eq-pkg { margin: 4px 0 8px; color: var(--text-muted); font-size: 12.5px; }
.eq-pkg .eq-pkg-sel { min-width: 240px; margin-left: 6px; }
/* Reserva el espacio del selector de paquete aplicable mientras carga en 2.º plano
   (loadApplicablePackages) — evita el salto de layout cuando se inserta el select real. */
.eq-pkg-skeleton .skeleton-bar {
  display: inline-block; width: 240px; height: 14px; border-radius: 4px;
  background: var(--divider); animation: skeleton-pulse 1.2s ease-in-out infinite;
}
@keyframes skeleton-pulse { 0%, 100% { opacity: .6; } 50% { opacity: 1; } }
.eq-block table.prices { font-size: 12.5px; }
.eq-block table.prices th { padding: 5px 8px; font-size: 10.5px; }
.eq-block table.prices td { padding: 4px 8px; }
#siteEditor .totals-row { gap: 16px; font-size: 12.5px; margin-top: 8px; }
.tax-cell { white-space: nowrap; }
.tax-cell label { font-size: 11px; color: var(--text-muted); margin-right: 6px; cursor: pointer; }

/* --- Proyecto: tipos de hora (propuesta, en acordeón) + líneas (sitio, en card) --- */
#laborTypes { margin-bottom: 14px; }
.labor-head, .project-head { display: flex; align-items: center; gap: 12px; margin-bottom: 8px; }
.labor-type-row { display: flex; align-items: flex-end; gap: 10px; flex-wrap: wrap; padding: 4px 0; }
.labor-type-row .lt-name { min-width: 200px; padding: 5px 8px; font-size: 13px; }
.labor-type-row label { display: flex; flex-direction: column; gap: 2px; font-size: 11.5px; color: var(--text-muted); }
.labor-type-row label input { padding: 5px 8px; font-size: 13px; width: 100px; }
/* Proyecto (líneas del sitio): card suave, consistente con el bloque de equipo. */
#projectArea { margin-top: 12px; }
.project-box { border: 1px solid var(--divider); border-radius: 10px; padding: 10px 12px; background: var(--panel-soft); }
/* Misma densidad que las tablas de equipo (.eq-block) para consistencia visual entre dominios. */
.project-box table.prices { font-size: 12.5px; }
.project-box table.prices th { padding: 5px 8px; font-size: 10.5px; }
.project-box table.prices td { padding: 4px 8px; }

/* --- Pestañas del detalle de propuesta --- */
.tabs { display: flex; gap: 4px; border-bottom: 1px solid var(--divider); margin-bottom: 16px; }
.tab {
  background: none; border: none; border-bottom: 2px solid transparent;
  padding: 10px 14px; cursor: pointer; color: var(--text-muted); font: inherit; font-weight: 500;
}
.tab:hover { color: var(--color-black); }
.tab.active { color: var(--color-black); border-bottom-color: var(--brand-blue); }

/* Sub-tabs (segundo nivel) */
.subtabs { display: flex; align-items: center; gap: 2px; margin-bottom: 14px; }
/* Switch de moneda (USD ↔ moneda de la propuesta): a la derecha de la barra de subtabs. */
.subtabs-curr { margin-left: auto; flex: 0 0 auto; }
/* .seg fija display:inline-flex y pisaría [hidden]; forzar el ocultado (más específico que .seg). */
.subtabs-curr[hidden] { display: none; }
.scope-sub-ref { margin-left: 8px; }
.subtab {
  background: transparent; border: 1px solid var(--divider); border-radius: 6px;
  padding: 6px 12px; cursor: pointer; color: var(--text-muted); font: inherit; font-size: 13px;
}
.subtab:hover { color: var(--color-black); }
.subtab.active { background: var(--brand-active-bg); color: var(--brand-blue); border-color: var(--brand-blue); }

/* Scope of work */
.scope-card { border: 1px solid var(--divider); border-radius: 10px; padding: 16px; margin-bottom: 14px; }
.scope-head { display: flex; align-items: center; justify-content: space-between; gap: 12px; flex-wrap: wrap; margin-bottom: 8px; }
.scope-head label { color: var(--text-muted); font-size: 13px; }
.scope-controls { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; }
.scope-sub { color: var(--text-muted); font-size: 13px; }
.scope-sections { margin-top: 12px; }
.scope-sec { margin-top: 16px; }
.scope-sec h4 { margin: 0 0 8px; font-size: 13px; color: var(--brand-blue); }
.scope-item { display: flex; gap: 8px; align-items: flex-start; font-size: 13px; padding: 3px 0; max-width: 900px; }
.scope-item input[type="checkbox"] { margin-top: 3px; flex: none; }
.scope-sec ul { margin: 0; padding-left: 18px; font-size: 13px; max-width: 900px; }
.scope-sec li { margin-bottom: 4px; }

/* ROI */
.roi-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 12px; }
.roi-cell { border: 1px solid var(--divider); border-radius: 10px; padding: 14px; display: flex; flex-direction: column; gap: 6px; }
.roi-cell strong { font-size: 18px; }
.roi-cell.roi-net { background: var(--brand-active-bg); border-color: var(--brand-blue); }
.roi-inputs { display: grid; grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); gap: 12px; }
.roi-inputs label { display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.roi-quot { display: flex; flex-direction: column; gap: 4px; max-width: 460px; }
.roi-quot select { width: 100%; }
/* Fila superior del ROI: cotización + segmented (por sitio / integral). */
.roi-toprow { display: flex; gap: 16px; flex-wrap: wrap; align-items: end; }
.roi-toprow .roi-quot { max-width: 360px; flex: 1 1 240px; }
.roi-seg { align-self: end; }
/* Separar el acordeón/resultado de la fila superior (cotización + segmented). */
#roiViewBody { margin-top: 20px; }
/* Acciones dentro del ROI de cada sitio (Guardar + estado). */
.roi-site-actions { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; margin-top: 12px; }
/* Métricas compactas en la cabecera del acordeón de ROI: grilla 3 col (label · opt · cons). */
.roi-mini { display: grid; grid-template-columns: auto auto auto; gap: 0 12px; font-size: 11px; text-align: right; align-items: baseline; }
.roi-mini-h { color: var(--text-muted); font-weight: 600; }
.roi-mini-l { color: var(--text-muted); text-align: left; padding-right: 6px; }
/* Supuestos del modelo (editables por propuesta) — colapsable y compacto. */
.roi-assumptions { border: 1px solid var(--divider); border-radius: 10px; padding: 10px 14px; margin: 16px 0; }
.roi-assumptions > summary { cursor: pointer; font-weight: 600; font-size: 14px; }
/* Supuestos: grilla de tarjetas por driver (usa el espacio lateral, no solo hacia abajo). */
.asm-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 14px; margin-top: 8px; }
.asm-card { border: 1px solid var(--divider); border-radius: 8px; padding: 10px 12px; }
.asm-card-h { font-weight: 700; font-size: 13px; color: var(--navy-deep); margin-bottom: 8px; }
.asm-sub { margin: 8px 0; }
.asm-sub-h { font-size: 12px; font-weight: 600; color: var(--brand-blue); margin-bottom: 4px; }
/* Grupos por asset (HVAC/Refrig/Light/Other) → en fila, no apilados. */
.asm-assets > .asm-sub-body { display: grid; grid-template-columns: repeat(auto-fit, minmax(108px, 1fr)); gap: 8px; }
.asm-field { display: flex; align-items: center; justify-content: space-between; gap: 8px; padding: 2px 0; font-size: 12.5px; }
.asm-assets .asm-field { flex-direction: column; align-items: stretch; gap: 2px; }
.asm-lbl { color: var(--text-muted); }
.asm-field input { width: 88px; padding: 4px 6px; font-size: 12.5px; }
.asm-assets .asm-field input { width: 100%; }
.asm-range { display: flex; gap: 6px; }
.asm-range input { width: 62px; }
/* Caja de rango con micro-etiqueta Cons./Opt. debajo (clarifica el par sin agregar filas). */
.asm-co { display: flex; flex-direction: column; align-items: center; }
.asm-co em { font-style: normal; font-size: 9px; color: var(--text-muted); margin-top: 1px; }
/* Indicador de suma de un reparto (debe = 100%): verde si cuadra, rojo si no. */
.asm-share-sum { font-size: 11px; font-weight: 700; padding: 0 5px; border-radius: 4px; white-space: nowrap; }
.asm-share-sum.ok  { color: var(--status-green-tx); background: var(--status-green-bg); }
.asm-share-sum.bad { color: var(--status-red-tx);   background: var(--status-red-bg); }
/* Categoría de un solo atributo (p. ej. Savings potential, Product-loss reduction): se separa con un
   divisor del reparto contiguo para que se lea como su propia sección, no como parte de él. */
.asm-sub.asm-standalone:not(:first-child) { border-top: 1px solid var(--divider); margin-top: 10px; padding-top: 8px; }
.roi-asm-actions { display: flex; align-items: center; gap: 12px; margin-top: 12px; }
.roi-charts { display: grid; grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); gap: 18px; }
.roi-chart .status-note { display: block; margin-bottom: 6px; }
.roi-canvas-wrap { position: relative; height: 280px; border: 1px solid var(--divider); border-radius: 10px; padding: 10px; }
.doc-form { display: grid; grid-template-columns: 2fr 1fr 2fr; gap: 14px; align-items: end; max-width: 880px; }
.doc-form label { display: flex; flex-direction: column; gap: 6px; font-size: 13px; color: var(--text-muted); }
.doc-form label span { color: var(--text-muted); }
.doc-form select { width: 100%; }
/* Opciones del documento en grilla de 2 columnas (Sitios · ROI · Costos · Anexo). */
/* align-items: stretch → las cajas de una misma fila igualan su altura (no se dimensionan al
   contenido), para que queden parejas aunque tengan distinta cantidad de campos. */
.doc-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; max-width: 880px; margin-top: 14px; align-items: stretch; }
.doc-cards .doc-sites { margin-top: 0; max-width: none; }
.doc-cards .status-note { margin-top: 8px; }
/* Selección de sitios para el documento (Ola 4) */
.doc-sites { border: 1px solid var(--divider); border-radius: 10px; padding: 10px 14px; margin-top: 14px; max-width: 880px; }
/* Aviso de preliminar separado de las tarjetas (sitios / ROI) de arriba. */
#docPrelim { margin-top: 18px; }
.doc-sites legend { font-size: 13px; color: var(--text-muted); padding: 0 6px; }
.doc-site-row { display: flex; align-items: center; gap: 8px; padding: 4px 0; font-size: 14px; }
/* Fila de ROI: nombre (izq) + selector de modo (der: no incluir / tablas / tablas+gráficas). */
.doc-roi-row { display: flex; align-items: center; justify-content: space-between; gap: 16px; padding: 5px 0; font-size: 14px; }
.doc-roi-name { display: flex; align-items: center; gap: 8px; }
.doc-roi-mode { min-width: 170px; }
.doc-consolidated { display: flex; align-items: center; gap: 8px; margin-top: 8px; font-size: 14px; }
.notice.warn { background: var(--warn-bg); color: var(--warn-tx); }
.roi-detail { border: 1px solid var(--divider); border-radius: 10px; padding: 6px 14px; margin-bottom: 8px; }
.roi-detail > summary { cursor: pointer; font-size: 14px; padding: 6px 0; }
.roi-detail[open] > summary { border-bottom: 1px solid var(--divider); margin-bottom: 10px; }
.roi-detail-body .roi-params { list-style: none; margin: 0 0 10px; padding: 0; display: flex; flex-direction: column; gap: 4px; font-size: 13px; }
.roi-params .status-note { margin-right: 4px; }

/* --- Searchable select (combobox) --- */
.ss { position: relative; display: inline-block; min-width: 280px; vertical-align: middle; }
.ss-input { width: 100%; }
.ss-panel {
  position: absolute; top: calc(100% + 2px); left: 0; right: 0; z-index: 200;
  max-height: 280px; overflow-y: auto; background: var(--color-white);
  border: 1px solid var(--brand-blue); border-radius: 8px; box-shadow: 0 6px 16px rgba(var(--navy-rgb), .12);
}
.ss-opt { padding: 8px 12px; cursor: pointer; font-size: 13px; border-bottom: 1px solid var(--divider); }
.ss-opt:last-child { border-bottom: none; }
.ss-opt:hover { background: var(--brand-active-bg); color: var(--brand-blue); }
.ss-empty { padding: 8px 12px; color: var(--text-muted); font-size: 13px; }
/* Auto-enhance: el <select> nativo queda oculto (sigue siendo la fuente de verdad) */
.ss > select.ss-value { display: none !important; }
.ss-wrap { min-width: 200px; }
.editor label > .ss-wrap, label > .ss-wrap, .row2 .ss-wrap { display: block; width: 100%; min-width: 0; }
.filters .ss-wrap { min-width: 150px; }
.roi-quot .ss-wrap, #docArea .ss-wrap { display: block; width: 100%; max-width: 420px; }

/* --- Multiselect con chips (comportamiento en util.js: msEnhance) --- */
/* El <select multiple> nativo queda oculto (fuente de verdad); el código lee .selectedOptions. */
.ms { position: relative; display: block; width: 100%; min-width: 0; }
.ms > select.ms-value { display: none !important; }
/* Trigger cerrado: mismo alto/padding que los demás inputs del form; crece (wrap) si hay
   muchos chips, nunca scroll interno ni alto fijo distinto al resto del form. */
.ms-trigger {
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px;
  min-height: calc(1em + 20px); /* ≈ alto de input con padding 9px + borde */
  background: var(--color-white); color: var(--color-black);
  border: 1px solid var(--disabled-bg); border-radius: 8px;
  padding: 6px 11px; cursor: pointer;
}
.ms-trigger:focus { outline: none; border-color: var(--brand-blue); }
.ms-ph { color: var(--text-muted); font-size: 13px; }
.ms-chip {
  display: inline-flex; align-items: center; gap: 6px;
  background: var(--brand-active-bg); color: var(--navy-deep);
  border-radius: 100px; padding: 2px 4px 2px 10px; font-size: 12px; font-weight: 500;
}
.ms-chip-x {
  display: inline-flex; align-items: center; justify-content: center;
  width: 16px; height: 16px; border: none; border-radius: 100px;
  background: transparent; color: var(--navy-deep); cursor: pointer;
  font: inherit; font-size: 14px; line-height: 1; padding: 0;
}
.ms-chip-x:hover { background: rgba(var(--navy-rgb), .18); }
.ms-panel {
  position: absolute; top: calc(100% + 2px); left: 0; right: 0; z-index: 200;
  background: var(--color-white);
  border: 1px solid var(--brand-blue); border-radius: 8px; box-shadow: 0 6px 16px rgba(var(--navy-rgb), .12);
}
.ms-search { width: 100%; border: none; border-bottom: 1px solid var(--divider); border-radius: 8px 8px 0 0; }
.ms-search:focus { border-color: var(--brand-blue); }
.ms-list { max-height: 240px; overflow-y: auto; }
.ms-opt {
  display: flex; align-items: center; gap: 8px;
  padding: 8px 12px; cursor: pointer; font-size: 13px; color: var(--color-black);
  border-bottom: 1px solid var(--divider);
}
.ms-opt:last-child { border-bottom: none; }
.ms-opt:hover { background: var(--brand-active-bg); color: var(--brand-blue); }
.ms-empty { padding: 8px 12px; color: var(--text-muted); font-size: 13px; }

/* --- Comentarios (tab Support) --- */
.section-h { font-size: 14px; font-weight: 700; margin: 0 0 12px; }
.mt-section { margin-top: 18px; }
.comment-form { display: flex; gap: 10px; align-items: flex-start; margin-bottom: 16px; }
.comment-form textarea { flex: 1; }
.comment { border-bottom: 1px solid var(--divider); padding: 10px 0; }
.comment-meta { color: var(--text-muted); font-size: 12px; display: flex; align-items: center; gap: 8px; }
.comment-body { white-space: pre-wrap; margin-top: 4px; }

/* --- Versionado --- */
/* Vive en la fila de estado (.detail-status-row), debajo del header → sin margen propio. */
.status-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.status-note { color: var(--text-muted); font-size: 12px; }
.tab-panel.locked,
.subtab-panel.locked { pointer-events: none; }
/* Aunque el panel esté bloqueado (cotización cerrada), los toggles del acordeón siguen
   navegables: se puede expandir/colapsar y cambiar de sitio para VER (no editar). */
.subtab-panel.locked .acc-toggle,
.subtab-panel.locked [data-acc-toggle] { pointer-events: auto; cursor: pointer; }
/* Los botones de acción de un panel bloqueado se atenúan (señal de no-acción); los inputs NO
   se atenúan con opacidad: se grisean (regla de solo-lectura de abajo) para quedar legibles. */
.subtab-panel.locked .btn,
.subtab-panel.locked .btn-text { opacity: .5; }
/* Solo lectura — MISMO gris para los inputs de un ROI "listo" (disabled) y de una cotización
   cerrada (.locked): caja gris clara con texto legible (no el gris tenue del navegador). */
input:disabled, select:disabled, textarea:disabled,
.subtab-panel.locked input, .subtab-panel.locked select, .subtab-panel.locked textarea {
  background: var(--disabled-bg); color: var(--text-muted);
  -webkit-text-fill-color: var(--text-muted); opacity: 1; cursor: not-allowed;
}
input[type="checkbox"]:disabled { accent-color: var(--disabled-tx); }
.subtab-panel.locked input[type="checkbox"] { accent-color: var(--disabled-tx); }
.snap-actions { display: flex; justify-content: space-between; margin-bottom: 10px; }
.snap-assumptions { margin: 0 0 18px; max-width: 520px; }

/* --- Adjuntos --- */
.attach-form { display: flex; align-items: center; gap: 10px; margin-bottom: 14px; flex-wrap: wrap; }
.attach-row { display: flex; align-items: center; gap: 12px; border-bottom: 1px solid var(--divider); padding: 8px 0; }
.attach-name { font-weight: 500; }
.attach-row .status-note { margin-right: auto; }

/* --- Layout -------------------------------------------------- */
main { padding: 24px; }

.card {
  background: var(--color-white);
  border: 1px solid var(--divider);
  border-radius: 12px;
  padding: 20px 24px;
}

.toolbar {
  display: flex; align-items: center; justify-content: space-between;
  gap: 12px 16px; flex-wrap: wrap; margin-bottom: 12px;
}
/* Bloque izquierdo: ← Propuestas arriba + título debajo; los botones (derecha) se centran
   verticalmente contra este bloque (alineados con el back y el título). */
.detail-head-left { display: flex; flex-direction: column; align-items: flex-start; gap: 4px; }
.detail-head-left #back { text-align: left; }
.toolbar h1 { font-size: 16px; font-weight: 700; margin: 0; line-height: 1.25; }
/* Título + meta en una sola línea (compacto): "Nombre · Cliente · Perfil · País". */
.detail-title { display: flex; align-items: baseline; gap: 10px; flex-wrap: wrap; }
.detail-title .app-name { font-size: 13px; }
/* Toolbar del catálogo (index.html): columna de botones a la derecha (sin cambios). */
.actions { display: flex; flex-direction: column; align-items: flex-end; gap: 8px; }
/* Sólo los botones de operación viven en el header de la propuesta, a la derecha del back+título. */
.actions-ops { display: flex; align-items: center; gap: 10px 12px; flex-wrap: wrap; justify-content: flex-end; }
#back { padding: 2px 0; margin-bottom: 6px; }
/* Fila de estado a todo el ancho, debajo del header: Etapa + chip + mensaje de versión. */
.detail-status-row { display: flex; align-items: center; gap: 10px 16px; flex-wrap: wrap; margin-bottom: 14px; }
.detail-status-row .status-bar { margin: 0; }
/* Resumen del proyecto: separar el toggle (Por local/Por dispositivo) del contenido. */
#summaryArea { margin-top: 18px; }
.chk { color: var(--text-muted); display: flex; align-items: center; gap: 6px; white-space: nowrap; }

/* --- Filtros ------------------------------------------------- */
.filters {
  display: flex; flex-wrap: wrap; align-items: center; gap: 10px;
  margin-bottom: 14px;
}
.filters #search { width: 280px; flex: 1 1 240px; }
.filters select { min-width: 130px; }
.filters .primary-country { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-muted); }
.filters .primary-country select { min-width: 110px; }
#grid th.num, #grid td.num { text-align: right; }
.count { color: var(--text-muted); font-size: 13px; margin-left: auto; }

/* --- Form fields --------------------------------------------- */
input, select, textarea {
  font: inherit;
  background: var(--color-white);
  color: var(--color-black);
  border: 1px solid var(--disabled-bg);
  border-radius: 8px;
  padding: 9px 11px;
}
input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--brand-blue);
}
#search { width: 300px; }

/* --- Buttons (components.md) --------------------------------- */
.btn {
  font: inherit; font-weight: 500;
  border-radius: 8px; padding: 10px 20px;
  border: 1px solid transparent; cursor: pointer;
}
.btn-contained { background: var(--color-black); color: var(--color-white); }
.btn-contained:hover { background: var(--brand-blue); }
.btn-contained:disabled { background: var(--disabled-bg); color: var(--disabled-tx); cursor: default; }
.btn-lg { padding: 12px 24px; font-size: 15px; }
.btn-sm { padding: 6px 12px; font-size: 13px; }

.btn-outline { background: transparent; color: var(--color-black); border-color: var(--color-black); }
.btn-outline:hover { background: var(--brand-active-bg); color: var(--brand-blue); border-color: var(--brand-blue); }

.btn-text {
  background: transparent; color: var(--color-black);
  border: none; border-radius: 8px; padding: 6px 10px;
  font: inherit; font-weight: 500; cursor: pointer;
}
.btn-text:hover { background: var(--brand-active-bg); color: var(--brand-blue); }

/* --- Table (densidad operacional) ---------------------------- */
.table-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; }
table#grid { min-width: 720px; }
th, td { text-align: left; padding: 10px 14px; border-bottom: 1px solid var(--divider); }
th {
  color: var(--text-muted); font-weight: 500; font-size: 12px;
  text-transform: uppercase; letter-spacing: .04em;
}
tbody tr:hover { background: var(--row-hover); }
#grid tbody tr { cursor: pointer; }
.tr-link { cursor: pointer; }
#grid thead th[data-sort] { cursor: pointer; user-select: none; white-space: nowrap; }
#grid thead th[data-sort]:hover { color: var(--brand-blue); }

/* Sistema de diseño — tabla ordenable `table.sortable` (comportamiento en util.js: makeSortable).
   El indicador (↕ inactivo · ↑/↓ activo) sale de aria-sort, no del textContent → convive con data-i18n.
   Es el patrón canónico; #grid usa la variante vieja (textContent) a migrar oportunistamente. */
/* Piso de ancho (como #grid=720px y table.prices=560px): con 8 columnas y las etiquetas más largas
   (ES), evita que el navegador angoste columnas y parta el contenido; en viewports angostos el
   scroll queda contenido en .table-wrap (overflow-x: auto), sin romper columnas. */
table.sortable { min-width: 860px; }
table.sortable thead th[data-sort] { cursor: pointer; user-select: none; white-space: nowrap; }
table.sortable thead th[data-sort]:hover { color: var(--brand-blue); }
table.sortable thead th[data-sort]::after { content: '↕'; opacity: .3; margin-left: .35em; font-size: .9em; }
table.sortable thead th[data-sort][aria-sort="ascending"]::after { content: '↑'; opacity: 1; }
table.sortable thead th[data-sort][aria-sort="descending"]::after { content: '↓'; opacity: 1; }
td.actions-cell { text-align: right; white-space: nowrap; }
.empty { color: var(--text-muted); text-align: center; padding: 40px; }
.empty.empty-sm { padding: 12px; }  /* empty state compacto (p. ej. Proyecto sin costos) */

/* --- Chip de estado (pill, full radius) ---------------------- */
.chip {
  display: inline-block; border-radius: 100px; white-space: nowrap;
  padding: 4px 12px; font-size: 12px; font-weight: 500;
  /* Ancho mínimo + centrado: los chips de estado quedan del mismo ancho (p. ej. "listo" iguala a
     "borrador") para mantener la alineación visual entre chips contiguos. Si el texto es más largo,
     el chip crece naturalmente. */
  min-width: 84px; text-align: center;
}
.chip.green { background: var(--status-green-bg); color: var(--status-green-tx); }
.chip.gray  { background: var(--status-gray-bg);  color: var(--status-gray-tx); }
/* Paleta de estado extendida (colors.md): enviada / perdida / vencida */
.chip.blue   { background: var(--status-blue-bg); color: var(--status-blue-tx); }
.chip.pink   { background: var(--status-pink-bg); color: var(--status-pink-tx); }
.chip.orange { background: var(--status-orange-bg); color: var(--status-orange-tx); }

/* --- Pipeline de propuestas (lista) -------------------------- */
.stage-chips { display: flex; gap: 6px; flex-wrap: wrap; }
.stage-filter {
  background: transparent; border: 1px solid var(--divider); border-radius: 100px;
  padding: 5px 12px; font: inherit; font-size: 12px; color: var(--text-muted); cursor: pointer;
}
.stage-filter:hover { background: var(--brand-active-bg); color: var(--brand-blue); }
.stage-filter.active { background: var(--brand-active-bg); color: var(--brand-blue); border-color: var(--brand-blue); }
.stage-label { display: inline-flex; align-items: center; gap: 8px; font-size: 13px; color: var(--text-muted); }

/* --- Edición masiva de precios -------------------------------- */
#bulkRows tr.dirty { background: var(--notice-bg); }
#bulkRows input.bulk-in { padding: 6px 8px; }

/* --- Condiciones generales (página /terms.html) ------------- */
td.cell-muted { color: var(--text-muted); font-size: 13px; max-width: 480px; }
textarea.terms-body { font-family: 'Roboto Mono', Consolas, monospace; font-size: 13px; line-height: 1.5; min-height: 360px; }
.btn-text.danger { color: var(--status-red-tx); }
.btn-text.danger:hover { color: var(--status-red-tx-strong); }

/* --- Editor (modal) ------------------------------------------ */
.overlay {
  position: fixed; inset: 0; background: rgba(var(--navy-rgb), .25);
  align-items: flex-start; justify-content: center;
  padding: 48px 16px; overflow: auto;
  /* Por encima del drawer (z-index:10): al editar un device DESDE la cortina, el
     form se abría detrás de ella y su "Cancelar" quedaba tapado/inalcanzable. */
  z-index: 50;
}
.overlay:not([hidden]) { display: flex; }
.editor { width: 640px; max-width: 100%; display: flex; flex-direction: column; gap: 14px; }
.editor h2 { margin: 0 0 4px; font-size: 16px; font-weight: 700; }
.editor label { display: flex; flex-direction: column; gap: 6px; color: var(--text-muted); font-size: 13px; }
.editor label input, .editor label select, .editor label textarea { color: var(--color-black); }
.editor { width: 720px; }
.editor.editor-sm { width: 420px; gap: 10px; }
.editor.editor-sm .notice { padding: 8px 12px; margin-bottom: 4px; }
.row2 { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
.row3 { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 14px; }
.chk-block { flex-direction: row !important; align-items: center; gap: 8px; color: var(--color-black) !important; }
.form-actions { display: flex; justify-content: flex-end; gap: 10px; margin-top: 6px; }
.error { color: var(--status-pink-tx); margin: 0; }
.req-mark { color: var(--status-pink-tx); }
.field-note { color: var(--text-muted); font-size: 12px; margin: 0 0 -6px; }

/* --- Detail drawer ------------------------------------------- */
.drawer { position: fixed; inset: 0; background: rgba(var(--navy-rgb), .25); z-index: 10; }
.drawer:not([hidden]) { display: block; }
.drawer-panel {
  position: absolute; top: 0; right: 0; height: 100%; width: min(900px, 96vw); max-width: 100%;
  background: var(--color-white); border-left: 1px solid var(--divider);
  padding: 20px 24px; overflow-y: auto;
  display: flex; flex-direction: column; gap: 16px;
}
/* Los hijos no deben encogerse: si no, .table-wrap (que con overflow-x:auto se
   vuelve scroll-container en ambos ejes) se comprime al abrir el form de precio
   y genera un mini-scroll vertical propio. Que scrollee toda la cortina. */
.drawer-panel > * { flex-shrink: 0; }
/* Cortina angosta: para forms cortos (alta de propuesta) que no necesitan el ancho del
   detalle con tabla de devices. Ancho similar al .editor.editor-sm. */
.drawer-panel-sm { width: min(420px, 96vw); }
/* Cortina de form anidada sobre la de detalle (z-index:10): debe pintar por encima. */
.drawer-form { z-index: 50; }
/* El form de edición vive dentro de la cortina → ocupa el ancho del panel (anula el ancho fijo
   de .editor, pensado para el modal centrado). */
.drawer-panel > .editor { width: 100%; }
.drawer-head { display: flex; align-items: flex-start; justify-content: space-between; gap: 12px; }
.drawer-head h2 { margin: 0; font-size: 16px; font-weight: 700; }
.drawer-actions { display: flex; gap: 10px; align-items: center; }

.detail-grid {
  display: grid; grid-template-columns: max-content 1fr; gap: 6px 16px; margin: 0;
  font-size: 13px;
}
.detail-grid dt { color: var(--text-muted); }
.detail-grid dd { margin: 0; }

.prices-head { display: flex; align-items: center; justify-content: space-between; margin-top: 4px; }
.prices-head h3 { font-size: 14px; font-weight: 700; margin: 0; }
table.prices { font-size: 13px; min-width: 560px; border-collapse: collapse; width: 100%; }
table.prices th { font-size: 11px; text-align: left; padding: 8px 10px; border-bottom: 1px solid var(--disabled-bg); color: var(--text-muted); }
table.prices td { padding: 8px 10px; border-bottom: 1px solid var(--disabled-bg); }
table.prices td.num { text-align: right; }
/* Tablas del resumen del proyecto: layout fijo + colgroup compartido por vista → columnas
   ALINEADAS entre secciones (Hardware/Instalación/Proyecto y entre domains). Numéricas a la
   derecha (table.prices td.num) y sin cortar; texto largo (device/part) hace wrap. */
.sum-tbl { table-layout: fixed; font-size: 12px; }
.sum-tbl th, .sum-tbl td { padding: 6px 7px; }   /* más compacto → más ancho útil para el texto */
.sum-tbl td.num, .sum-tbl th.num { white-space: nowrap; }
.sum-tbl td:not(.num) { word-break: break-word; }
/* Tablas del EDITOR de cotización (device · license · proyecto): layout fijo + colgroup
   compartido (EQ_COLS / EQ_COLS_RO en proposals.js) → columnas de igual concepto alineadas
   entre dominios. El texto largo (parte/dispositivo) hace wrap; impuestos/acciones no se cortan. */
.eq-tbl { table-layout: fixed; }
.eq-tbl td:not(.tax-cell):not(.actions-cell) { word-break: break-word; }
.empty.error { color: var(--status-pink-tx); }

.price-form {
  /* OJO: sin `display:flex` aquí — pisaría el [hidden] del navegador (display:none)
     y el botón Cancelar (que hace hidden=true) no ocultaría el form. El display
     se setea solo en :not([hidden]). */
  border: 1px solid var(--divider); border-radius: 10px; padding: 16px;
  flex-direction: column; gap: 12px; background: var(--panel-soft);
}
.price-form:not([hidden]) { display: flex; }
.price-form h4 { margin: 0; font-size: 13px; font-weight: 700; }
.price-form label { display: flex; flex-direction: column; gap: 5px; color: var(--text-muted); font-size: 12px; }
.price-form label input, .price-form label select { color: var(--color-black); }

/* --- Toast (feedback / errores no silenciosos) --------------- */
#kdp-toasts {
  position: fixed; right: 16px; bottom: 16px; z-index: 1000;
  display: flex; flex-direction: column; gap: 8px; max-width: min(90vw, 380px);
}
.kdp-toast {
  background: var(--color-black); color: var(--color-white);
  padding: 10px 14px; border-radius: 8px; font-size: 13px; line-height: 1.4;
  box-shadow: 0 6px 16px rgba(var(--navy-rgb), .18);
  opacity: 1; transition: opacity .3s ease, transform .3s ease;
}
.kdp-toast.err { background: var(--status-pink-tx); }
.kdp-toast.out { opacity: 0; transform: translateY(8px); }

/* ============================================================
   Responsive / mobile (≤ 768px)
   ============================================================ */
@media (max-width: 768px) {
  main { padding: 12px; }
  .card { padding: 14px; border-radius: 10px; }

  /* Topbar compacta; el CTA "+ Nueva propuesta" baja a su propia fila */
  .topbar { padding: 8px 12px; gap: 8px; }
  .topbar .app-name { display: none; }
  .nav { margin-left: 8px; gap: 2px; flex-wrap: wrap; }
  .nav a, .nav-trigger { padding: 6px 10px; }
  .topbar-cta { margin-left: 0; order: 5; flex: 1 1 100%; text-align: center; }
  .lang-toggle { margin-left: auto; }

  /* Tabs/subtabs: scroll horizontal en lugar de romperse en varias filas */
  .tabs, .subtabs { flex-wrap: nowrap; overflow-x: auto; -webkit-overflow-scrolling: touch; }
  .tab, .subtab { white-space: nowrap; flex: 0 0 auto; }

  /* Grids de formulario / ROI → una columna */
  .row2, .row3, .doc-form, .doc-cards, .roi-inputs, .roi-grid, .roi-charts { grid-template-columns: 1fr; }

  /* Inputs y comboboxes ocupan el ancho disponible (no desbordan la pantalla) */
  .ss, .ss-wrap { min-width: 0; width: 100%; display: block; }
  .costs-edit { gap: 10px; }
  .costs-edit label, .costs-edit label input, .costs-edit label input.pct { width: 100%; }
  .filters { gap: 8px; }
  .filters #search, .filters select, .filters .ss-wrap, .filters label, .filters .primary-country {
    width: 100%; flex: 1 1 100%; min-width: 0;
  }
  .filters .count { margin-left: 0; }
  .eq-head .eq-name, .eq-add .eq-dev, .eq-pkg .eq-pkg-sel { min-width: 0; width: 100%; }

  /* Overlays / editor casi a pantalla completa */
  .overlay { padding: 12px; }
  .editor { width: 100%; }
  .form-actions .btn { flex: 1; }

  /* Drawer de detalle de device a ancho completo */
  .drawer-panel { width: 100%; padding: 16px 14px; }

  /* Tablas densas: scroll horizontal suave + celdas más compactas.
     La tabla mantiene min-width, así que se desliza en vez de aplastarse. */
  .table-wrap { overflow-x: auto; -webkit-overflow-scrolling: touch; }
  th, td { padding: 8px 10px; }

  .roi-canvas-wrap { height: 240px; }
  .toolbar h1 { font-size: 15px; }

  /* Touch targets ≥ 40 px — obligatorio en mobile (regla UX del proyecto) */
  .kebab-btn, .btn-sm, .btn-text,
  .lang-toggle button, .stage-filter, .subtab, .switch-opt { min-height: 40px; }
}

/* Resumen del proyecto (Ola 2). El toggle Por local/Por dispositivo usa el segmented `.seg`
   del sistema de diseño (la barra de sitios y los chips ad-hoc se reemplazaron por el acordeón). */
.summary-grand { text-align: right; font-size: 1.05em; margin-top: 14px; }
/* Totales del sitio (resumen por local): subtotal hardware + subtotal proyecto + total,
   alineados a la derecha en una misma columna para que el ojo los compare. */
.site-totals { margin-top: 12px; display: flex; flex-direction: column; align-items: flex-end; gap: 4px; }
.site-totals .st-row { display: grid; grid-template-columns: auto 140px; gap: 16px; align-items: baseline; }
.site-totals .st-row > span:first-child { text-align: right; color: var(--text-muted); font-size: 13px; }
.site-totals .st-row .mono { text-align: right; }
.site-totals .st-total { border-top: 1px solid var(--divider); padding-top: 6px; margin-top: 2px; font-weight: 700; }
.site-totals .st-total > span:first-child { color: var(--color-black); }
/* Costo total del sitio: va arriba, separado de los subtotales de precio por un divisor. */
.site-totals .st-cost { border-bottom: 1px solid var(--divider); padding-bottom: 6px; margin-bottom: 2px; }
.site-totals .st-cost > span:first-child { color: var(--color-black); }
/* Mini-tabla de cierre Costo | Precio | Margen (componente reusable del sistema de diseño). */
.mini-totals-foot { display: flex; justify-content: flex-end; margin-top: 10px; }
.mini-totals { border-collapse: collapse; font-size: 13px; }
.mini-totals th, .mini-totals td { padding: 4px 14px; text-align: right; }
.mini-totals thead th { color: var(--text-muted); font-weight: 600; border-bottom: 1px solid var(--divider); }
.mini-totals tbody td { color: var(--color-black); font-weight: 700; padding-top: 6px; }
/* Resumen por tipo de costo: usa el mismo acordeón que Por local / Por dispositivo. */
.cost-type-foot { margin-top: 8px; }
/* Barra del resumen: segmented de vistas + botón Exportar en la misma fila. */
.sum-bar { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
#exportSummaryBtn { margin-left: auto; }

/* Impresión del resumen del proyecto (Opción A: window.print + @media print).
   Orientación landscape: las tablas tienen 8-9 columnas — portrait quiebra líneas incluso con
   fuente mínima. Con landscape (~267 mm útiles) todo entra en un renglón. */
@media print {
  body.printing-summary > *:not(#summaryPrintArea) { display: none !important; }

  /* Landscape solo para este export; no afecta otras impresiones. */
  body.printing-summary { -webkit-print-color-adjust: exact; print-color-adjust: exact; }
  @page { size: landscape; margin: 14mm 16mm; }

  #summaryPrintArea { display: block !important; padding: 0; }
  #summaryPrintArea h1 { font-size: 16px; margin: 0 0 2px; }
  #summaryPrintArea .sum-print-header { margin-bottom: 14px; }
  #summaryPrintArea .sum-print-section { margin-bottom: 16px; }
  #summaryPrintArea .sum-print-section-title { font-size: 12px; font-weight: 700; margin: 0 0 6px; border-bottom: 1px solid var(--color-black); padding-bottom: 3px; }
  #summaryPrintArea .accordion { border: 1px solid var(--divider); border-radius: 4px; }
  #summaryPrintArea .acc-item + .acc-item { border-top: 1px solid var(--divider); }
  #summaryPrintArea .acc-head { display: flex !important; justify-content: space-between; padding: 5px 10px; background: var(--panel-soft) !important; font-size: 10px; }
  #summaryPrintArea .acc-title::before { display: none; }
  #summaryPrintArea .acc-item > .acc-body { display: block !important; padding: 6px 10px; }
  #summaryPrintArea .table-wrap { overflow: visible; }

  /* Fuente compacta + thead que se repite al cortar de página. */
  #summaryPrintArea .sum-tbl { font-size: 9px; }
  #summaryPrintArea .sum-tbl thead { display: table-header-group; }

  /* Columnas numéricas y part number no envuelven; solo el nombre de device puede envolver. */
  #summaryPrintArea .sum-tbl td.num,
  #summaryPrintArea .sum-tbl th.num,
  #summaryPrintArea .sum-tbl td.mono { white-space: nowrap; }

  #summaryPrintArea .summary-grand { text-align: right; font-weight: 700; margin-top: 6px; font-size: 10px; }
  #summaryPrintArea .status-note { font-size: 9px; }
  #summaryPrintArea .site-totals { margin-top: 6px; font-size: 9px; }
  #summaryPrintArea .site-totals .st-row { grid-template-columns: auto 110px; gap: 10px; }
  #summaryPrintArea .project-head { font-size: 9px; }
}

/* ============================================================================
   SISTEMA DE DISEÑO — componentes compartidos reutilizables.
   Catálogo y reglas de uso: docs/design-system.md. NO rearmar por pestaña:
   reusar estas clases. Colores SIEMPRE desde tokens (:root), nunca hardcode.
   ============================================================================ */

/* Acordeón — secciones colapsables apiladas (patrón canónico para listar
   entidades con cabecera + cuerpo: sitios, etc.). Markup:
   <div class="accordion">
     <section class="acc-item open">
       <button class="acc-head" data-acc-toggle>
         <span class="acc-title">…</span><span class="acc-meta">…</span>
       </button>
       <div class="acc-body">…</div>
     </section>
   </div>
   El toggle lo maneja util.js (delegado en [data-acc-toggle]). */
.accordion { border: 1px solid var(--divider); border-radius: 12px; overflow: hidden; }
.acc-item + .acc-item { border-top: 1px solid var(--divider); }
.acc-head { width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 12px;
  padding: 13px 16px; background: none; border: 0; font: inherit; cursor: pointer; text-align: left; color: inherit; }
.acc-head:hover { background: color-mix(in srgb, var(--brand-active-bg) 35%, transparent); }
.acc-item.open > .acc-head { background: var(--brand-active-bg); }
.acc-title { display: flex; align-items: center; gap: 10px; font-weight: 600; font-size: 14px; }
/* El chip de estado (p. ej. "borrador") NO debe agrandar la cabecera: con su line-height por
   defecto medía más que la línea del título y dejaba el acordeón "Por local" más alto que los otros
   (se notaba al saltar entre Por local / Por dispositivo / Por tipo de costo). Acotado → altura
   uniforme en las 3 vistas; el título manda la altura de fila. */
.acc-title .chip { line-height: 1; }
.acc-title::before { content: '▸'; color: var(--text-muted); font-size: 12px; transition: transform .15s; }
.acc-item.open > .acc-head .acc-title::before { transform: rotate(90deg); }
.acc-meta { color: var(--text-muted); font-size: 14px; }
.acc-body { padding: 14px 16px; }
.acc-item:not(.open) > .acc-body { display: none; }

/* Segmented control — alternar vistas mutuamente excluyentes (toggle bi/tri-estado). Markup:
   <div class="seg"><button class="seg-opt active">A</button><button class="seg-opt">B</button></div> */
.seg { display: inline-flex; gap: 6px; }
.seg-opt { border: 1px solid var(--divider); background: var(--color-white); border-radius: 999px;
  padding: 6px 14px; cursor: pointer; font: inherit; color: var(--text-muted); }
.seg-opt.active { border-color: var(--brand-blue); background: var(--brand-active-bg); color: var(--navy-deep); font-weight: 600; }

/* Switch — toggle DESLIZANTE de 2 opciones (estilo iOS segmented). A diferencia del .seg (pills
   sueltas) y de los subtabs, tiene un indicador (thumb) que se desliza bajo la opción activa, así se
   lee claramente como un interruptor. Markup:
   <div class="switch"><button class="switch-opt active">A</button><button class="switch-opt">B</button>
     <span class="switch-thumb"></span></div>
   El thumb se posiciona con la clase `is-right` en el contenedor (2.ª opción activa). Comportamiento
   delegado en la página (toggle + sincronizar `active`/`is-right`). Ver docs/design-system.md. */
.switch { position: relative; display: inline-flex; padding: 3px; background: var(--panel-soft);
  border: 1px solid var(--divider); border-radius: 999px; }
.switch-opt { flex: 1 1 0; position: relative; z-index: 1; border: 0; background: transparent;
  cursor: pointer; padding: 8px 16px; min-width: 56px; text-align: center; white-space: nowrap;
  border-radius: 999px; font: inherit; font-size: 13px; font-weight: 600; line-height: 1;
  color: var(--text-muted); transition: color .18s ease; }
.switch-opt.active { color: var(--navy-deep); }
.switch-thumb { position: absolute; top: 3px; bottom: 3px; left: 3px; width: calc(50% - 3px);
  background: var(--color-white); border-radius: 999px; box-shadow: 0 1px 3px rgba(var(--navy-rgb), .22);
  transition: transform .2s ease; pointer-events: none; }
.switch.is-right .switch-thumb { transform: translateX(100%); }

/* Menú kebab (⋮) — dropdown compacto de acciones por fila/ítem (tablas). Markup:
   <span class="kebab">
     <button class="kebab-btn" aria-haspopup="true">⋮</button>
     <div class="kebab-menu" role="menu">
       <button class="kebab-item"         data-action="…">{icon} Acción neutra</button>
       <button class="kebab-item muted"   data-action="…">{icon} Acción secundaria</button>
       <button class="kebab-item success" data-action="…">{icon} Cerrar</button>
       <button class="kebab-item danger"  data-action="…">{icon} Borrar</button>
     </div>
   </span>
   Cada ítem lleva un ÍCONO (helper icon() de util.js) + label. El color es SEMÁNTICO, no decorativo:
   neutro (default, navy) y .muted (gris) para acciones no destacadas; .success (verde) para acciones
   positivas/de cierre; .danger (rojo/rosa) solo para destructivas. El ícono hereda el color (currentColor).
   Abrir/cerrar y POSICIÓN: delegado en util.js (position:fixed calculado en JS para no quedar recortado
   por contenedores con overflow, p. ej. .table-wrap). */
.kebab { position: relative; display: inline-block; }
.kebab-btn {
  background: transparent; border: none; cursor: pointer; font: inherit; font-size: 18px; line-height: 1;
  color: var(--navy-deep); padding: 4px 10px; border-radius: 6px;
}
.kebab-btn:hover { background: var(--brand-active-bg); color: var(--brand-blue); }
.kebab-menu {
  position: absolute; top: calc(100% + 2px); right: 0; z-index: 200;
  background: var(--color-white); border: 1px solid var(--divider); border-radius: 8px;
  box-shadow: 0 4px 12px rgba(var(--navy-rgb), .12);
  min-width: 184px; padding: 4px; display: none;
}
.kebab.open .kebab-menu { display: block; }
.kebab-item {
  display: flex; align-items: center; gap: 10px; width: 100%; text-align: left; background: none; border: none;
  cursor: pointer; font: inherit; font-weight: 600; font-size: 14px; padding: 8px 12px; border-radius: 6px;
  color: var(--navy-deep);
}
.kebab-item .ico { flex: none; opacity: .85; }
.kebab-item:hover { background: var(--brand-active-bg); }
.kebab-item.muted { color: var(--text-muted); }
.kebab-item.success { color: var(--status-green-tx); }
.kebab-item.success:hover { background: var(--status-green-bg); }
.kebab-item.danger { color: var(--status-red-tx); }
.kebab-item.danger:hover { background: var(--status-red-bg); color: var(--status-red-tx-strong); }

/* Composición del acordeón de sitios (Ola 3) */
.acc-head { cursor: default; }
.acc-toggle { display: flex; align-items: center; cursor: pointer; flex: 1; min-width: 0; }
.acc-head-actions { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.site-add-row { margin: 10px 2px 4px; }

.site-edit-row { margin-top: 6px; }
