/* ═══════════════════════════════════════════════════════════════════════════
   R10 · HUB «PRESUPUESTOS» + MODO GUÍA — estilos de P4 (oleada W2)
   ---------------------------------------------------------------------------
   Consume las utilidades de css/r10-system.css (S1) que son puro ritmo/tipografía
   sin color («.r10-flow-*», «.r10-num»): el Hub vive sobre el LIENZO oscuro
   (`#hub-view{background:var(--bg)}`, no papel), así que las primitivas de S1
   que SÍ llevan color de papel (`.r10-sheet`, `.r10-section-title`, tinta
   `--ink`) no se usan aquí sin adaptar — usarlas tal cual pintaría texto oscuro
   sobre fondo oscuro. Este fichero define el equivalente para lienzo (tokens
   `--text`/`--text2`/`--text3`/`--gold*`, ya theme-aware vía body.light).

   Se carga ÚLTIMO (index.html) → puede sobreescribir por orden de cascada
   cualquier regla de igual especificidad en css/styles.css sin !important.
   Cero valores hardcodeados fuera de var(--…).
   ═══════════════════════════════════════════════════════════════════════════ */

/* ── MASTHEAD DEL HUB (A1-ux H6: una sola CTA primaria) ───────────────────
   Antes: título + búsqueda + botón «Nuevo presupuesto» apretados en una fila
   de toolbar → se leía como la cabecera de un panel de administración. Ahora:
   fila 1 = título + LA acción primaria (grande, sola); fila 2 = utilidades
   secundarias (buscar/recargar), más pequeñas y calladas. */
.ctrl-hero{ margin-bottom:var(--sp-5); }
.ctrl-hero-top{
  display:flex;
  align-items:flex-end;
  justify-content:space-between;
  gap:var(--sp-4);
  flex-wrap:wrap;
}
.ctrl-hero-text{ min-width:0; }
.ctrl-hero-title{
  font-family:var(--serif);
  font-weight:600;
  font-size:var(--t-xl);
  line-height:1.15;
  letter-spacing:-.01em;
  color:var(--text);
  margin:0 0 var(--sp-1);
  position:relative;
  display:inline-block;
  padding-bottom:var(--sp-2);
}
/* Firma: regla dorada corta (misma idea que .r10-section-title de S1, pero en
   tinta legible sobre lienzo — nunca --ink, que es tinta de papel). */
.ctrl-hero-title::after{
  content:'';
  position:absolute;
  left:0; bottom:0;
  width:40px; height:1px;
  background:var(--gold-line);
  opacity:.7;
}
.ctrl-hero-top .ctrl-new-btn{
  flex:0 0 auto;
  font-size:13px;
  padding:10px 18px;
  white-space:nowrap;
}
.ctrl-toolbar{
  display:flex;
  gap:var(--sp-2);
  align-items:center;
  margin-top:var(--sp-3);
}
.ctrl-toolbar .ctrl-search{ flex:1 1 260px; max-width:340px; }

/* ── Democión de la CTA duplicada de la topbar (A1-ux H6) ─────────────────
   `.tb-hub` («Nuevo», onclick=newPresupuestoFlow) SOLO se muestra cuando el
   Hub está activo (setToolbar('hub'), js/ext-shell.js) — comparte acción con
   `.ctrl-new-btn` de arriba, que ahora es la única primaria destacada. No se
   toca su markup/aria-label «Nuevo» (los e2e la localizan por rol+nombre):
   solo baja de peso visual — deja de competir por la vista con la CTA del hub. */
.tb-hub{
  background:transparent;
  border:1px solid var(--border2);
  color:var(--text2);
  box-shadow:none;
  font-size:12px;
  padding:6px 12px;
}
.tb-hub:hover{
  background:var(--gold-dim);
  border-color:var(--gold);
  color:var(--gold);
}

/* ── BANNER compartido (A1-ux H8 + invitación al modo guía) ───────────────
   Un solo patrón: icono + título + descripción (+ acciones opcionales) — la
   nota de «modo local» y la invitación al modo guía son la MISMA familia
   visual, no dos improvisaciones distintas. Nada de side-stripe: la
   diferencia es el icono/color de acento, nunca un borde lateral. */
.ctrl-banner{
  display:flex;
  align-items:flex-start;
  gap:var(--sp-3);
  padding:var(--sp-4);
  border-radius:var(--r3);
  border:1px solid var(--border);
  background:var(--bg2);
  margin:0 0 var(--sp-4);
}
.ctrl-banner-ic{
  flex:0 0 auto;
  line-height:0;
  color:var(--gold-bright);
  margin-top:2px;
}
.ctrl-banner-body{ flex:1 1 auto; min-width:0; }
.ctrl-banner-t{
  font-family:var(--sans);
  font-weight:600;
  font-size:var(--t-sm,13px);
  color:var(--text);
  margin-bottom:2px;
}
.ctrl-banner-d{
  font-family:var(--sans);
  font-size:12px;
  line-height:1.5;
  /* C2 #5: a 12px normal el umbral es 4.5:1. `--text3` fallaba AA en AMBOS temas
     (3.90:1 oscuro / 3.69:1 claro). `--text2` pasa holgado (9.97:1 oscuro; en
     claro `#4a4640` sobre `--bg2` blanco ≈ 8.9:1) sin volverse tan fuerte como
     el título `.ctrl-banner-t` (`--text`), que sigue por encima. */
  color:var(--text2);
  max-width:var(--r10-measure);
}
.ctrl-banner-acts{
  flex:0 0 auto;
  display:flex;
  align-items:center;
  gap:var(--sp-2);
  margin-left:var(--sp-2);
}
.ctrl-banner-x{
  border:none;
  background:transparent;
  color:var(--text3);
  cursor:pointer;
  line-height:0;
  padding:6px;
  border-radius:var(--r-sm,4px);
}
.ctrl-banner-x:hover{ color:var(--text); background:var(--bg3); }
.ctrl-banner-x:focus-visible,
.ctrl-banner-acts .btn:focus-visible{
  outline:2px solid var(--gold);
  outline-offset:1px;
}

/* Nota de nube (H8): mismo patrón, sin acciones (solo informa). */
.ctrl-cloud-note .ctrl-banner-ic{ color:var(--gold); opacity:.9; }

/* Invitación al modo guía: acento distinto SOLO por color de icono (nunca un
   borde lateral) para que se lea como "aviso amistoso", no como error/alerta. */
.ctrl-guide-invite{ flex-wrap:wrap; }
.ctrl-guide-invite .ctrl-banner-ic{ color:var(--gold-bright); }
@media (max-width:640px){
  .ctrl-guide-invite{ flex-direction:column; }
  .ctrl-guide-invite .ctrl-banner-acts{ margin-left:0; }
}

/* ── Ritmo vertical entre bloques del hub (aire, no más cajas) ────────────
   .r10-flow-groups (S1, css/r10-system.css) ya separa los HIJOS DIRECTOS de
   `.ctrl-hero` (fila título+CTA / fila utilidades) con el paso «grupo» de la
   escala. Aquí solo se ajusta el bloque de analíticas, que ya usaba su propio
   margen — se deja intacto (regla ya en styles.css), añadimos aire tras el
   banner de invitación para que no se pegue a los chips de estado. */
.ctrl-guide-invite + .ctrl-estado-chips{ margin-top:var(--sp-1); }

/* ── Bans activos (DESIGN.md): fuera eyebrow-uppercase y gradient-accent ──
   `.ctrl-card-title` (styles.css) usaba mayúsculas + tracking ancho — es
   exactamente el patrón «eyebrows uppercase por sección» baneado. Se
   sobrescribe aquí a un nivel-2 discreto (sans, semibold, sin versalitas);
   la reglilla `::after` (línea que rellena el resto del ancho) se conserva —
   es un separador, no un side-stripe. */
.ctrl-card-title{
  text-transform:none;
  letter-spacing:0;
  font-size:12px;
  font-weight:600;
  color:var(--text2);
}
/* `.ctrl-kpi::after` (styles.css) pinta un halo de gradiente radial al hover —
   coincide literalmente con el acento-gradiente del «hero-metric template»
   baneado. Se neutraliza sin tocar el resto del microinteracción de hover
   (elevación + borde dorado, que sí es feedback de estado legítimo). */
.ctrl-kpi:hover::after{ opacity:0; }

/* ── Empty states: algo más de aire, mismo contenido (ya llevaban ilustración
   + CTA desde R9 — H7 estaba resuelto; solo se refuerza el ritmo). ────────── */
.ctrl-empty-teach{ padding:var(--sp-7) var(--sp-5); }
.ctrl-empty-filtered{ padding:var(--sp-6) var(--sp-4); }

/* ── Microcopy inyectada por js/ext-guide.js en los pasos ②/③ del modo guía ──
   Reusa `.ws-panel-head`/`.ws-panel-title`/`.ws-panel-sub` (mismas reglas que
   ①/⑤ en css/styles.css) — cero CSS nuevo para la copy en sí. La única pieza
   propia es esta: en «PDF técnico» (@media print) el paso ③ se fuerza visible
   (`#ws-panel-resultados{display:block!important}`), así que SIN esto la
   cabecera nueva de guía se colaría en el documento impreso. Ámbito acotado a
   la clase que P4 añade (`--r10guide`) — no toca el `.ws-panel-head` real de
   ①/⑤ (ya oculto en print porque sus paneles enteros lo están). */
@media print{
  .ws-panel-head--r10guide{ display:none !important; }
}
/* Solo tiene sentido en MODO GUÍA. En superficies (Preparar/Proponer, el
   defecto de R10) NO se muestra: verificado en QA manual que, sin esto,
   duplicaba el título de P1 en «Preparar» (P1 ya viste ① como cabecera de la
   hoja de papel y ② lleva su propio «Días del evento») y encima se pintaba sin
   tematizar (tinta de lienzo oscuro heredada de `.ws-panel-title` sobre el
   papel claro de P1 → casi ilegible). `body.bbp-expert` es el hook de S1 para
   «superficies activas»; oculto SOLO mi propia clase, nunca el `.ws-panel-head`
   real de ①/⑤ que sí pertenece a esa superficie. */
body.bbp-expert .ws-panel-head--r10guide{ display:none; }

/* ═══════════════════════════════════════════════════════════════════════════
   R10 W4 · «Que te acompañe» — feedback vivo del rail (F4)
   ---------------------------------------------------------------------------
   El rail resumen (js/ws-shell.js) vive fuera del hub, pero su CSS de ESTADO se
   aloja aquí por límite de propiedad de la oleada W4 (css/styles.css, donde vive
   el resto de `.ws-rail-*`, es ajeno a este agente). Motion SOLO de estado (ban
   de coreografía de DESIGN.md), anulado bajo `prefers-reduced-motion` (guard
   propio + bloqueo global de styles.css). Cero color/duración hardcodeados.
   ═══════════════════════════════════════════════════════════════════════════ */

/* (c) Latido sutil del TOTAL del rail al CAMBIAR — el pulse de P2 late en el
   héroe (invisible mientras editas en «Preparar»); este late donde sí miras.
   Reusa el keyframe `r10-price-pulse` de css/r10-system.css (un beat de escala);
   origen izquierda para no empujar el layout del rail. */
.ws-rail-total.is-recalc{
  animation:r10-price-pulse var(--r10-pulse-dur) var(--ease-soft);
  transform-origin:left center;
}

/* (a) Estado «Recalculando…»: el indicador dirty en modo ocupado. El icono late
   suave en opacidad → se lee como «vivo/pensando», nunca como spinner de carga.
   La caja gold del propio `.ws-rail-dirty` (styles.css) ya comunica atención. */
@keyframes ws-rail-busy-pulse{
  0%,100%{ opacity:.5; }
  50%{     opacity:1; }
}
.ws-rail-dirty.is-busy .ws-rail-ic-busy{
  animation:ws-rail-busy-pulse 1s var(--ease-soft) infinite;
}

@media (prefers-reduced-motion:reduce){
  .ws-rail-total.is-recalc{ animation:none; }
  .ws-rail-dirty.is-busy .ws-rail-ic-busy{ animation:none; }
}

/* Paginación de la lista del hub (rediseño 2026-07-13) */
.ctrl-pager{display:flex;align-items:center;justify-content:space-between;gap:12px;flex-wrap:wrap;padding:12px 4px 2px}
.ctrl-pager-nums{display:flex;align-items:center;gap:4px;flex-wrap:wrap}
.ctrl-pager-btn{min-width:32px;height:32px;padding:0 8px;border:1px solid var(--border);background:transparent;color:var(--text);border-radius:8px;cursor:pointer;font:inherit;line-height:1}
.ctrl-pager-btn:hover:not(:disabled){border-color:var(--gold-on-surface);color:var(--gold-on-surface)}
.ctrl-pager-btn.active{background:color-mix(in srgb, var(--gold-on-surface) 16%, transparent);border-color:var(--gold-on-surface);color:var(--gold-on-surface);font-weight:600;cursor:default}
.ctrl-pager-btn:disabled{opacity:.4;cursor:default}
.ctrl-pager-nav{font-size:18px}
.ctrl-pager-gap{padding:0 4px;color:var(--text);opacity:.5}
.ctrl-pager-range{color:var(--text);opacity:.7;font-size:13px}

/* Acordeón de la lista del hub (rediseño 2026-07-13) — espejo de .ctrl-trash-h */
.ctrl-list-acc-h{display:flex;align-items:center;gap:8px;margin-bottom:6px}
.ctrl-list-acc-toggle{display:inline-flex;align-items:center;gap:6px;font-weight:600}
.ctrl-list-collapsed{padding-bottom:8px}
